Summary of Editable Input Box Operation

Keywords: Javascript IE Fragment less

In my spare time, to deepen my understanding of the basics, I have a message board: input box.Say less and get to the point.The crude effect is as follows: Download Code):

Define requirements

  1. You can enter text and insert emoticons.
  2. Compatibility: IE and standard browsers

2. Detailed design

Depending on our needs, we can generally think of the following questions:

  1. Compatibility handling
    1. Event Binding Compatibility
    2. Expression insertion compatibility for editable input boxes
    3. Get data compatibility
  2. Three modules
    1. Module for message board interaction with ui
    2. Emotional Display Module
    3. The operational module of the editable input box, so I plan the following class structure:

  • LeaveMsg: Implement UI interaction with message boards
  • FaceWrap: Manage emoticons and respond to events such as show/hide, get emoticons, initialize emoticons list, etc.
  • SelectionUitls: Implements editable input boxes such as inserting an emoticon, getting data, etc.The compatibility of each module is described in the following details.

3. Code implementation

1. FaceWrap class (emoticon list management class)

var FaceWrap = function(head, cont, opts){
    this.$head = head;
    this.$cont = cont;
    this.data = ['one', 'two', 'thr'];
    var self = this;
    var toggle = false;
    this.onClickHandHandle = function(evt){
        if(!toggle){
            self.$cont.style.display = 'block';
            toggle = true;
        }else{
            self.$cont.style.display = 'none';
            toggle = false;
        }
        if(opts.onClickHandHandle){
            opts.onClickHandHandle(toggle);
        }
    }
    this.onChooseImg = opts. onChooseImg || function(){}
    this.generalFaceImg();
    this.bind();
}
var facePt = FaceWrap.prototype;
facePt.generalFaceImg = function(){
    var fragment = document.createDocumentFragment();
    for( var index =0; index < this.data.length; ++index){
        var data = this.data[index];
        var img = document.createElement('img');
        img.setAttribute('src', '../img/face/' + data + '.jpg');
        img.setAttribute('data-id', data);
        img.setAttribute('class','face-img');
        fragment.appendChild(img);
    }
    this.$cont.appendChild(fragment);
}
facePt.bind = function(){  
    if(document.attachEvent){
        this.$head.attachEvent('onclick',this.onClickHandHandle);
        this.$cont.attachEvent('onclick',this.onChooseImg);
    }else{       
        this.$head.addEventListener('click',this.onClickHandHandle);
        this.$cont.addEventListener('click',this.onChooseImg);
    }
}
facePt.hide = function(){
    this.onClickHandHandle();
}

Points to note:

1. Use fragments to improve performance when initializing the general FaceImg;

2. After setting the display none of the element in the class, the displayvalue of this element cannot be obtained with js.

Compatibility has the following points:

  1. Event binding: attacheEvent and addEventListener.
  2. classList unsupported issue in ie8-temporarily selected to be replaced by setAttribute
  3. AppndChild is all supported, append is supported in chrome, but not in ie

2. SelectionUitls class (editable input box management class)

var SelectionUitls = function(dom){
    this.dom = dom;
    this.cursorIndex;
}
var pt = SelectionUitls.prototype;
pt.insertDomForStandard = function(dom){
    var sel = window.getSelection(); //Get Selection Collection
    var range = sel.getRangeAt(0); //Get the first choice
    range.deleteContents(); //Remove elements of precinct weight
    range.insertNode(dom); //Insert element at the top of selection
    range = range.cloneRange(); //Cloning a Selection
    range.setStartAfter(dom); //Set the selection start cursor position after the specified element
    range.collapse(true);//Merge Start and End Cursors
    sel.removeAllRanges();//Remove all districts
    sel.addRange(range); //Add a Selection
}
pt.insertDomForIe = function(dom){
    this.dom.focus();
    var wrap = document.createElement('div');
    wrap.appendChild(dom);

    document.selection.createRange().pasteHTML(wrap.innerHTML);
}
pt.insertDom = function(dom){
    //Insert non-elements at cursor
    if(window.getSelection){
        this.insertDomForStandard(dom);
    }else{
        this.insertDomForIe(dom);
    }
}
pt.getContent = function(){
    //get data
    var nodes = this.dom.childNodes;
    var datas = [];
    for(var index = 0; index < nodes.length; index ++){
        var node = nodes[index];
        if(node.nodeType == 3){
            datas.push(node.textContent || node.nodeValue || node.data);
        }else{
            datas.push(node.getAttribute('data-id'));
        }
    }
    return datas.join('##');
}

Main Contents:

  1. range: Compatibility between IE and standard browsers. It is important to note that when IE manipulates a selection, the element being manipulated (that is, the element in which the selection is located) needs to be focused, otherwise it will fail.
  2. The APi of the standard browser range can refer to this address: http://www.w3school.com.cn/xmldom/dom_range.asp
  3. GettContent: Converts html structured data into standard data to prevent script attacks.

3. LeaveMsg class (message board management class)

var LeaveMsg = function(opts){
    this.opts = opts;
    this.createFaceWrap();
    this.createUitls();
    this.curLocation;
}
var leaveMsgPt = LeaveMsg.prototype;
leaveMsgPt._insertFace = function(id){
    var img = document.createElement('img');
    img.setAttribute('class','face-img');
    img.setAttribute('data-id', id);
    img.src= '../img/face/' + id + '.jpg';
    this.selectionUitls.insertDom(img);
    this.faceWrap.hide();
}
leaveMsgPt.createFaceWrap = function(){
    var self = this;
    var faceOpt = {
        onChooseImg:function(evt){
            //Insert Emotions, Get Position, Get Emotions, Insert Emotions
            var id = (evt.target||evt.srcElement).getAttribute('data-id');
            self._insertFace(id);
        }
    }
    this.faceWrap = new FaceWrap(this.opts.faceHead, this.opts.faceCont, faceOpt);
}
leaveMsgPt.createUitls = function(){
    this.selectionUitls = new SelectionUitls(this.opts.area);
}
leaveMsgPt.getContent = function(evt){
    this.selectionUitls.getContent();
}

Implements a combination of FaceWrap, SelectionUitls, and LeaveMsg classes, and provides the equivalent API to the UI.

4. Use them

js part code

var leaveMsgArea = document.getElementById('leaveMsgArea');
var faceHead = document.getElementById('head');
var faceCont = document.getElementById('cont');


var leaveMsg = new LeaveMsg({
    area: leaveMsgArea,
    faceHead: faceHead,
    faceCont: faceCont
});

HTML Part Code

<div class="leaveMsgArea" contenteditable="true" id="leaveMsgArea">
</div>
<div class="face-wrap">
    <a class="face-head" id="head" href="javascript:void(0)">Expression</a>
    <div class="face-cont" id="cont">

    </div>
</div>
<div class="button-group">
    <button type="button" onclick="leaveMsg.getContent(event)" >Get Content</button>
</div>

Posted by falian on Sat, 06 Jul 2019 15:10:27 -0700