html5和css3自定义输入表单的自然语言界面

当前位置:主页 > Html5库 > HTML5动画 > html5和css3自定义输入表单的自然语言界面
html5和css3自定义输入表单的自然语言界面
分享:

    插件介绍

    这是一款非常实用的html5和css3自定义输入表单的自然语言界面插件。通过contenteditable属性用户可以在自然语言环境下通过表单输入和编辑他们的各种需求,之后可以提交表单。

    浏览器兼容性

    浏览器兼容性
    时间:12-19
    阅读:

简要教程

有许多很有趣的自然语言界面,在这个插件中,我们想要使用自定义的表单元素来定制一个自然语言界面。

HTML结构

html结构实用一个form表单,里面包含一些select元素和input元素。

<form id="nl-form" class="nl-form">
  I feel like eating 
  <select>
    <option value="1" selected>any food</option>
    <option value="2">Indian</option>
    <option value="3">French</option>
    <option value="4">Japanese</option>
    <option value="2">Italian</option>
  </select>
  <br />in a
  <select>
    <option value="1" selected>standard</option>
    <option value="2">fancy</option>
    <option value="3">hip</option>
    <option value="4">traditional</option>
    <option value="2">fine</option>
  </select>
  restaurant
  <select>
    <option value="1" selected>anytime</option>
    <option value="1">at 7 p.m.</option>
    <option value="2">at 8 p.m.</option>
    <option value="3">at 9 p.m.</option>
  </select>
  in <input type="text" value="" placeholder="any city" data-subline="For example: <em>Los Angeles</em> or <em>New York</em>"/>
  <div class="nl-submit-wrap">
    <button class="nl-submit" type="submit">Find a restaurant</button>
  </div>
  <div class="nl-overlay"></div>
</form>
                

我们希望将select 元素转换为一个自定义的下拉列表,如下结构:

<div class="nl-field nl-dd">
  <a class="nl-field-toggle">any food</a>
  <ul>
    <li class="nl-dd-checked">any food</li>
    <li>Indian</li>
    <li>French</li>
    <li>Japanese</li>
    <li>Italian</li>
  </ul>
</div>
                

自然语言界面下拉列表框-1

切换时句子中视觉效果的一部分,当我们点击了列表中的某一项时,我们隐藏列表,使该选项显示在句子的当前位置上。

input元素也要被转换为一个类似的元素:

<div class="nl-field nl-ti-text">
  <a class="nl-field-toggle">any city</a>
  <ul>
    <li class="nl-ti-input">
      <input type="text" value="" placeholder="any city" />
      <button class="nl-field-go">Go</button>
    </li>
    <li class="nl-ti-example">For example: <em>Los Angeles</em> or <em>New York</em></li>
  </ul>
</div>
                

自然语言界面下拉列表框-2

JAVASCRIPT

首先定义一个代表表单的对象:

function NLForm( el ) { 
  // the form element
  this.el = el;
  // the overlay
  this.overlay = this.el.querySelector( '.nl-overlay' );
  // array with all the possible custom fields
  this.fields = [];
  // counter for each custom field
  this.fldOpen = -1;
  this._init();
}
                

然后参加一些结构来替换原来表单的html结构。我们将定义一个代表各个自动的对象-NLField。

NLForm.prototype = {
  _init : function() {
    var self = this;
    Array.prototype.slice.call( this.el.querySelectorAll( 'select' ) ).forEach( function( el, i ) {
      self.fldOpen++;
      self.fields.push( new NLField( self, el, 'dropdown', self.fldOpen ) );
    } );
    Array.prototype.slice.call( this.el.querySelectorAll( 'input' ) ).forEach( function( el, i ) {
      self.fldOpen++;
      self.fields.push( new NLField( self, el, 'input', self.fldOpen ) );
    } );
  },
  ...
}

function NLField( form, el, type, idx ) {
  this.form = form;
  // the original HTML element
  this.elOriginal = el;
  this.pos = idx;
  this.type = type;
  this._create();
  this._initEvents();
}
NLField.prototype = {
  _create : function() {
    if( this.type === 'dropdown' ) {
      this._createDropDown(); 
    }
    else if( this.type === 'input' ) {
      this._createInput();  
    }
  },
  ...
}
                

结构的不同依赖与它是一个select选择框或是一个input输入框。

NLField.prototype = {
  ...
  _createDropDown : function() {
    var self = this;
    this.fld = document.createElement( 'div' );
    this.fld.className = 'nl-field nl-dd';
    this.toggle = document.createElement( 'a' );
    this.toggle.innerHTML = this.elOriginal.options[ this.elOriginal.selectedIndex ].innerHTML;
    this.toggle.className = 'nl-field-toggle';
    this.optionsList = document.createElement( 'ul' );
    var ihtml = '';
    Array.prototype.slice.call( this.elOriginal.querySelectorAll( 'option' ) ).forEach( function( el, i ) {
      ihtml += self.elOriginal.selectedIndex === i ? '
' + el.innerHTML + '
' : '
' + el.innerHTML + '
';
      // selected index value
      if( self.elOriginal.selectedIndex === i ) {
        self.selectedIdx = i;
      }
    } );
    this.optionsList.innerHTML = ihtml;
    this.fld.appendChild( this.toggle );
    this.fld.appendChild( this.optionsList );
    this.elOriginal.parentNode.insertBefore( this.fld, this.elOriginal );
    this.elOriginal.style.display = 'none';
  },
  _createInput : function() {
    var self = this;
    this.fld = document.createElement( 'div' );
    this.fld.className = 'nl-field nl-ti-text';
    this.toggle = document.createElement( 'a' );
    this.toggle.innerHTML = this.elOriginal.placeholder;
    this.toggle.className = 'nl-field-toggle';
    this.optionsList = document.createElement( 'ul' );
    this.getinput = document.createElement( 'input' );
    this.getinput.setAttribute( 'type', 'text' );
    this.getinput.placeholder = this.elOriginal.placeholder;
    this.getinputWrapper = document.createElement( 'li' );
    this.getinputWrapper.className = 'nl-ti-input';
    this.inputsubmit = document.createElement( 'button' );
    this.inputsubmit.className = 'nl-field-go';
    this.inputsubmit.innerHTML = 'Go';
    this.getinputWrapper.appendChild( this.getinput );
    this.getinputWrapper.appendChild( this.inputsubmit );
    this.example = document.createElement( 'li' );
    this.example.className = 'nl-ti-example';
    this.example.innerHTML = this.elOriginal.getAttribute( 'data-subline' );
    this.optionsList.appendChild( this.getinputWrapper );
    this.optionsList.appendChild( this.example );
    this.fld.appendChild( this.toggle );
    this.fld.appendChild( this.optionsList );
    this.elOriginal.parentNode.insertBefore( this.fld, this.elOriginal );
    this.elOriginal.style.display = 'none';
  },
  ...
}
                

最后,我们在字段上绑定一些事件。对于下拉列表框,我们将使用用户选择的选项来更新表单的内容,对于输入框,根据用户输入的内容来更新表单的内容。

NLField.prototype = {
  ...
  _initEvents : function() {
    var self = this;
    this.toggle.addEventListener( 'click', function( ev ) { ev.preventDefault(); ev.stopPropagation(); self._open(); } );
    this.toggle.addEventListener( 'touchstart', function( ev ) { ev.preventDefault(); ev.stopPropagation(); self._open(); } );

    if( this.type === 'dropdown' ) {
      var opts = Array.prototype.slice.call( this.optionsList.querySelectorAll( 'li' ) );
      opts.forEach( function( el, i ) {
        el.addEventListener( 'click', function( ev ) { ev.preventDefault(); self.close( el, opts.indexOf( el ) ); } );
        el.addEventListener( 'touchstart', function( ev ) { ev.preventDefault(); self.close( el, opts.indexOf( el ) ); } );
      } );
    }
    else if( this.type === 'input' ) {
      this.getinput.addEventListener( 'keydown', function( ev ) {
        if ( ev.keyCode == 13 ) {
          self.close();
        }
      } );
      this.inputsubmit.addEventListener( 'click', function( ev ) { ev.preventDefault(); self.close(); } );
      this.inputsubmit.addEventListener( 'touchstart', function( ev ) { ev.preventDefault(); self.close(); } );
    }

  },
  _open : function() {
    if( this.open ) {
      return false;
    }
    this.open = true;
    this.form.fldOpen = this.pos;
    var self = this;
    this.fld.className += ' nl-field-open';
  },
  close : function( opt, idx ) {
    if( !this.open ) {
      return false;
    }
    this.open = false;
    this.form.fldOpen = -1;
    this.fld.className = this.fld.className.replace(/\b nl-field-open\b/,'');

    if( this.type === 'dropdown' ) {
      if( opt ) {
        // remove class nl-dd-checked from previous option
        var selectedopt = this.optionsList.children[ this.selectedIdx ];
        selectedopt.className = '';

        opt.className = 'nl-dd-checked';
        this.toggle.innerHTML = opt.innerHTML;

        // update selected index value
        this.selectedIdx = idx;
        // update original select element´s value
        this.elOriginal.value = this.elOriginal.children[ this.selectedIdx ].value;
      }
    }
    else if( this.type === 'input' ) {
      this.getinput.blur();
      this.toggle.innerHTML = this.getinput.value.trim() !== '' ? this.getinput.value : this.getinput.placeholder;
      this.elOriginal.value = this.getinput.value;
    }
  }
  ...
}
                

相关插件