From 961078b419cb0f20ed70010bcc3ace83cd885f43 Mon Sep 17 00:00:00 2001 From: peak Date: Thu, 9 Mar 2017 18:03:04 +0800 Subject: [PATCH] compatible with ie11 --- .eslintignore | 3 +- dist/vue-html5-editor.js | 96 ++++++++++++++++++++++++++++++++++++---- example/basic.html | 6 +-- src/editor.js | 27 +++++++---- src/index.js | 2 + src/polyfill-ie.js | 56 +++++++++++++++++++++++ src/range/handler.js | 8 ++++ 7 files changed, 177 insertions(+), 21 deletions(-) create mode 100644 src/polyfill-ie.js diff --git a/.eslintignore b/.eslintignore index f0165fa..d3e96b2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,5 @@ *.sass *.pcss *.css -*.html \ No newline at end of file +*.html +src/polyfill-ie.js \ No newline at end of file diff --git a/dist/vue-html5-editor.js b/dist/vue-html5-editor.js index 5e2c785..e3f9e7d 100644 --- a/dist/vue-html5-editor.js +++ b/dist/vue-html5-editor.js @@ -1,7 +1,7 @@ /** * Vue-html5-editor 1.0.0 * https://github.com/PeakTai/vue-html5-editor - * build at Mon Mar 06 2017 17:49:58 GMT+0800 (CST) + * build at Thu Mar 09 2017 16:42:28 GMT+0800 (CST) */ (function (global, factory) { @@ -27,6 +27,62 @@ function __$styleInject(css, returnValue) { return returnValue; } +var polyfill = function () { + // https://tc39.github.io/ecma262/#sec-array.prototype.includes + if (!Array.prototype.includes) { + Object.defineProperty(Array.prototype, 'includes', { + value: function value(searchElement, fromIndex) { + // 1. Let O be ? ToObject(this value). + if (this == null) { + throw new TypeError('"this" is null or not defined') + } + + var o = Object(this); + + // 2. Let len be ? ToLength(? Get(O, "length")). + var len = o.length >>> 0; + + // 3. If len is 0, return false. + if (len === 0) { + return false + } + + // 4. Let n be ? ToInteger(fromIndex). + // (If fromIndex is undefined, this step produces the value 0.) + var n = fromIndex | 0; + + // 5. If n ≥ 0, then + // a. Let k be n. + // 6. Else n < 0, + // a. Let k be len + n. + // b. If k < 0, let k be 0. + var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); + + // 7. Repeat, while k < len + while (k < len) { + // a. Let elementK be the result of ? Get(O, ! ToString(k)). + // b. If SameValueZero(searchElement, elementK) is true, return true. + // c. Increase k by 1. + // NOTE: === provides the correct "SameValueZero" comparison needed here. + if (o[k] === searchElement) { + return true + } + k++; + } + + // 8. Return false + return false + } + }); + } + // text.contains() + if (!Text.prototype.contains) { + Text.prototype.contains = function contains(node) { + return this === node + }; + } +}; + var template = "
"; /** @@ -743,6 +799,14 @@ var isInlineElement = function (node) { return inlineNodeNames.includes(node.nodeName) }; +// for IE 11 +if (!Text.prototype.contains) { + Text.prototype.contains = function contains(otherNode) { + return this === otherNode + }; +} + + /** * Created by peak on 2017/2/14. */ @@ -1143,14 +1207,24 @@ var editor = { return this.range }, saveCurrentRange: function saveCurrentRange(){ + var this$1 = this; + var selection = window.getSelection ? window.getSelection() : document.getSelection(); - var range = selection.rangeCount ? selection.getRangeAt(0) : null; - if (!range) { + if (!selection.rangeCount) { return } - if (this.$refs.content.contains(range.startContainer) && - this.$refs.content.contains(range.endContainer)) { - this.range = range; + var content = this.$refs.content; + for (var i = 0; i < selection.rangeCount; i++) { + var range = selection.getRangeAt(0); + var start = range.startContainer; + var end = range.endContainer; + // for IE11 : node.contains(textNode) always return false + start = start.nodeType === Node.TEXT_NODE ? start.parentNode : start; + end = end.nodeType === Node.TEXT_NODE ? end.parentNode : end; + if (content.contains(start) && content.contains(end)) { + this$1.range = range; + break + } } }, restoreSelection: function restoreSelection(){ @@ -1194,12 +1268,15 @@ var editor = { var content = this.$refs.content; content.innerHTML = this.content; content.addEventListener('mouseup', this.saveCurrentRange, false); - content.addEventListener('keyup', this.saveCurrentRange, false); - content.addEventListener('mouseout', this.saveCurrentRange, false); content.addEventListener('keyup', function () { this$1.$emit('change', content.innerHTML); + this$1.saveCurrentRange(); + }, false); + content.addEventListener('mouseout', function (e) { + if (e.target === content) { + this$1.saveCurrentRange(); + } }, false); - this.touchHandler = function (e) { if (content.contains(e.target)) { this$1.saveCurrentRange(); @@ -1349,6 +1426,7 @@ function mixin(source, ext) { return source } +polyfill(); /** * Vue html5 Editor * @param Vue {Vue} diff --git a/example/basic.html b/example/basic.html index 135cdad..fd46413 100644 --- a/example/basic.html +++ b/example/basic.html @@ -47,14 +47,14 @@ showModuleName: false, }, methods: { - updateData(data){ + updateData: function (data) { // sync content to component this.content = data }, - fullScreen(){ + fullScreen: function () { this.$refs.editor.enableFullScreen() }, - focus(){ + focus: function () { this.$refs.editor.focus() } } diff --git a/src/editor.js b/src/editor.js index d53dc32..905439e 100644 --- a/src/editor.js +++ b/src/editor.js @@ -105,13 +105,21 @@ export default { }, saveCurrentRange(){ const selection = window.getSelection ? window.getSelection() : document.getSelection() - const range = selection.rangeCount ? selection.getRangeAt(0) : null - if (!range) { + if (!selection.rangeCount) { return } - if (this.$refs.content.contains(range.startContainer) && - this.$refs.content.contains(range.endContainer)) { - this.range = range + const content = this.$refs.content + for (let i = 0; i < selection.rangeCount; i++) { + const range = selection.getRangeAt(0) + let start = range.startContainer + let end = range.endContainer + // for IE11 : node.contains(textNode) always return false + start = start.nodeType === Node.TEXT_NODE ? start.parentNode : start + end = end.nodeType === Node.TEXT_NODE ? end.parentNode : end + if (content.contains(start) && content.contains(end)) { + this.range = range + break + } } }, restoreSelection(){ @@ -151,12 +159,15 @@ export default { const content = this.$refs.content content.innerHTML = this.content content.addEventListener('mouseup', this.saveCurrentRange, false) - content.addEventListener('keyup', this.saveCurrentRange, false) - content.addEventListener('mouseout', this.saveCurrentRange, false) content.addEventListener('keyup', () => { this.$emit('change', content.innerHTML) + this.saveCurrentRange() + }, false) + content.addEventListener('mouseout', (e) => { + if (e.target === content) { + this.saveCurrentRange() + } }, false) - this.touchHandler = (e) => { if (content.contains(e.target)) { this.saveCurrentRange() diff --git a/src/index.js b/src/index.js index 5fadd77..70e88e6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,11 @@ +import polyfill from './polyfill-ie' import buildInModules from './modules/index' import editor from './editor' import i18nZhCn from './i18n/zh-cn' import i18nEnUs from './i18n/en-us' import mixin from './util/mixin' +polyfill() /** * Vue html5 Editor * @param Vue {Vue} diff --git a/src/polyfill-ie.js b/src/polyfill-ie.js new file mode 100644 index 0000000..91887ad --- /dev/null +++ b/src/polyfill-ie.js @@ -0,0 +1,56 @@ +export default () => { + // https://tc39.github.io/ecma262/#sec-array.prototype.includes + if (!Array.prototype.includes) { + Object.defineProperty(Array.prototype, 'includes', { + value(searchElement, fromIndex) { + // 1. Let O be ? ToObject(this value). + if (this == null) { + throw new TypeError('"this" is null or not defined') + } + + const o = Object(this) + + // 2. Let len be ? ToLength(? Get(O, "length")). + const len = o.length >>> 0 + + // 3. If len is 0, return false. + if (len === 0) { + return false + } + + // 4. Let n be ? ToInteger(fromIndex). + // (If fromIndex is undefined, this step produces the value 0.) + const n = fromIndex | 0 + + // 5. If n ≥ 0, then + // a. Let k be n. + // 6. Else n < 0, + // a. Let k be len + n. + // b. If k < 0, let k be 0. + let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0) + + // 7. Repeat, while k < len + while (k < len) { + // a. Let elementK be the result of ? Get(O, ! ToString(k)). + // b. If SameValueZero(searchElement, elementK) is true, return true. + // c. Increase k by 1. + // NOTE: === provides the correct "SameValueZero" comparison needed here. + if (o[k] === searchElement) { + return true + } + k++ + } + + // 8. Return false + return false + } + }) + } + // text.contains() + if (!Text.prototype.contains) { + Text.prototype.contains = function contains(node) { + return this === node + } + } +} + diff --git a/src/range/handler.js b/src/range/handler.js index 1516cfb..9c38961 100644 --- a/src/range/handler.js +++ b/src/range/handler.js @@ -8,6 +8,14 @@ import { isInlineElement } from './util' +// for IE 11 +if (!Text.prototype.contains) { + Text.prototype.contains = function contains(otherNode) { + return this === otherNode + } +} + + /** * Created by peak on 2017/2/14. */