all files / directives/duplex/ updateDataEvents.compact.js

81.08% Statements 90/111
84.09% Branches 37/44
61.54% Functions 8/13
81.08% Lines 90/111
43 statements, 7 functions, 22 branches Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208                        33×   33×     13× 13×                                             13×         12×                 12× 12×   12×     12×                     13×     33× 13× 13× 13× 13×     33× 84×                                                                                                        
/* 
 * 通过绑定事件同步vmodel
 * 总共有三种方式同步视图
 * 1. 各种事件 input, change, click, propertychange, keydown...
 * 2. value属性重写
 * 3. 定时器轮询
 */
 
import { avalon, getShortID as markID, window, document, msie } from '../../seed/core'
import { updateModel } from './updateDataHandle'
 
 
export function updateDataEvents(dom, data) {
    var events = {}
        //添加需要监听的事件
    switch (data.dtype) {
        case 'radio':
        case 'checkbox':
            events.click = updateModel
            break
        case 'select':
            events.change = updateModel
            break
        case 'contenteditable':
            /* istanbul ignore if */
            Iif (data.isChanged) {
                events.blur = updateModel
                    /* istanbul ignore else */
            } else {
                /* istanbul ignore if*/
 
                Eif (avalon.modern) {
                    Iif (window.webkitURL) {
                        // http://code.metager.de/source/xref/WebKit/LayoutTests/fast/events/
                        // https://bugs.webkit.org/show_bug.cgi?id=110742
                        events.webkitEditableContentChanged = updateModel
                    } else Eif (window.MutationEvent) {
                        events.DOMCharacterDataModified = updateModel
                    }
                    events.input = updateModel
                        /* istanbul ignore else */
                } else {
                    events.keydown = updateModelKeyDown
                    events.paste = updateModelDelay
                    events.cut = updateModelDelay
                    events.focus = closeComposition
                    events.blur = openComposition
                }
 
            }
            break
        case 'input':
            /* istanbul ignore if */
            if (data.isChanged) {
                events.change = updateModel
                    /* istanbul ignore else */
            } else {
                //http://www.cnblogs.com/rubylouvre/archive/2013/02/17/2914604.html
                //http://www.matts411.com/post/internet-explorer-9-oninput/
                Iif (msie < 10) {
                    //IE6-8的propertychange有问题,第一次用JS修改值时不会触发,而且你是全部清空value也不会触发
                    //IE9的propertychange不支持自动完成,退格,删除,复制,贴粘,剪切或点击右边的小X的清空操作
                    events.propertychange = updateModelHack
                    events.paste = updateModelDelay
                    events.cut = updateModelDelay
                        //IE9在第一次删除字符时不会触发oninput
                    events.keyup = updateModelKeyDown
                } else {
                    events.input = updateModel
                    events.compositionstart = openComposition
                        //微软拼音输入法的问题需要在compositionend事件中处理
                    events.compositionend = closeComposition
                        //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
                        //处理低版本的标准浏览器,通过Int8Array进行区分
                    Iif (!/\[native code\]/.test(window.Int8Array)) {
                        events.keydown = updateModelKeyDown //safari < 5 opera < 11
                        events.paste = updateModelDelay //safari < 5
                        events.cut = updateModelDelay //safari < 5 
                        if (window.netscape) {
                            // Firefox <= 3.6 doesn't fire the 'input' event when text is filled in through autocomplete
                            events.DOMAutoComplete = updateModel
                        }
                    }
                }
            }
            break
    }
 
    if (/password|text/.test(dom.type)) {
        events.focus = openCaret //判定是否使用光标修正功能 
        events.blur = closeCaret
        data.getCaret = getCaret
        data.setCaret = setCaret
    }
 
    for (var name in events) {
        avalon.bind(dom, name, events[name])
    }
}
 
 
function updateModelHack(e) {
    if (e.propertyName === 'value') {
        updateModel.call(this, e)
    }
}
 
function updateModelDelay(e) {
    var elem = this
    setTimeout(function() {
        updateModel.call(elem, e)
    }, 0)
}
 
 
function openCaret() {
    this.caret = true
}
/* istanbul ignore next */
function closeCaret() {
    this.caret = false
}
/* istanbul ignore next */
function openComposition() {
    this.composing = true
}
/* istanbul ignore next */
function closeComposition(e) {
    this.composing = false
    updateModelDelay.call(this, e)
}
/* istanbul ignore next */
function updateModelKeyDown(e) {
    var key = e.keyCode
        // ignore
        //    command            modifiers                   arrows
    if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40))
        return
    updateModel.call(this, e)
}
 
markID(openCaret)
markID(closeCaret)
markID(openComposition)
markID(closeComposition)
markID(updateModel)
markID(updateModelHack)
markID(updateModelDelay)
markID(updateModelKeyDown)
 
//IE6-8要处理光标时需要异步
var mayBeAsync = function(fn) {
        setTimeout(fn, 0)
    }
    /* istanbul ignore next */
function setCaret(target, cursorPosition) {
    var range
    if (target.createTextRange) {
        mayBeAsync(function() {
            target.focus()
            range = target.createTextRange()
            range.collapse(true)
            range.moveEnd('character', cursorPosition)
            range.moveStart('character', cursorPosition)
            range.select()
        })
    } else {
        target.focus()
        if (target.selectionStart !== undefined) {
            target.setSelectionRange(cursorPosition, cursorPosition)
        }
    }
}
/* istanbul ignore next*/
function getCaret(target) {
    var start = 0
    var normalizedValue
    var range
    var textInputRange
    var len
    var endRange
 
    if (target.selectionStart + target.selectionEnd > -1) {
        start = target.selectionStart
    } else {
        range = document.selection.createRange()
 
        if (range && range.parentElement() === target) {
            len = target.value.length
            normalizedValue = target.value.replace(/\r\n/g, '\n')
 
            textInputRange = target.createTextRange()
            textInputRange.moveToBookmark(range.getBookmark())
 
            endRange = target.createTextRange()
            endRange.collapse(false)
 
            if (textInputRange.compareEndPoints('StartToEnd', endRange) > -1) {
                start = len
            } else {
                start = -textInputRange.moveStart('character', -len)
                start += normalizedValue.slice(0, start).split('\n').length - 1
            }
        }
    }
 
    return start
}