{"version":3,"sources":["jsdelivr-header.js","/npm/nytimes-ice@0.6.3/dist/webpack:/webpack/bootstrap 6b9af40b136b8e3d4f79","/npm/nytimes-ice@0.6.3/dist/webpack:/external \"jquery\"","webpack:///src/index.js","webpack:///src/ice.js","webpack:///src/bookmark.js","webpack:///src/dom.js","webpack:///src/icePlugin.js","webpack:///src/icePluginManager.js","webpack:///src/polyfills.js","webpack:///src/selection.js","/npm/nytimes-ice@0.6.3/dist/webpack:/external \"rangy\"","webpack:///src/plugins/IceAddTitlePlugin/IceAddTitlePlugin.js","webpack:///src/plugins/IceCopyPastePlugin/IceCopyPastePlugin.js","webpack:///src/plugins/IceEmdashPlugin/IceEmdashPlugin.js","webpack:///src/plugins/IceSmartQuotesPlugin/IceSmartQuotesPlugin.js"],"names":[],"mappings":"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","file":"/npm/nytimes-ice@0.6.3/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/nytimes-ice@0.6.3/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n",null,null,"/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\nvar ice = require('./ice');\n\nrequire('./bookmark.js');\nrequire('./dom.js');\nrequire('./icePlugin.js');\nrequire('./icePluginManager.js');\nrequire('./polyfills.js');\nrequire('./selection.js');\nrequire('./plugins/IceAddTitlePlugin/IceAddTitlePlugin.js');\nrequire('./plugins/IceCopyPastePlugin/IceCopyPastePlugin.js');\nrequire('./plugins/IceEmdashPlugin/IceEmdashPlugin.js');\nrequire('./plugins/IceSmartQuotesPlugin/IceSmartQuotesPlugin.js');\n\nmodule.exports = ice;\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/index.js\n// module id = 1\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function () {\n\n\tvar exports = this,\n\t\tdefaults, InlineChangeEditor;\n\n    var ice = exports.ice = this.ice || {};\n\n\t\tdefaults = {\n\t\t\t// ice node attribute names:\n\t\t\tchangeIdAttribute: 'data-cid',\n\t\t\tuserIdAttribute: 'data-userid',\n\t\t\tuserNameAttribute: 'data-username',\n\t\t\ttimeAttribute: 'data-time',\n\n\t\t\t// Prepended to `changeType.alias` for classname uniqueness, if needed\n\t\t\tattrValuePrefix: '',\n\n\t\t\t// Block element tagname, which wrap text and other inline nodes in `this.element`\n\t\t\tblockEl: 'p',\n\n\t\t\t// All permitted block element tagnames\n\t\t\tblockEls: ['p', 'ol', 'ul', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote'],\n\n\t\t\t// Node names for all elements that may wrap other nodes in `this.element`\n\t\t\tblockParentsNodeName: ['P', 'UL', 'OL', 'TABLE'],\n\n\t\t\t// Unique style prefix, prepended to a digit, incremented for each encountered user, and stored\n\t\t\t// in ice node class attributes - cts1, cts2, cts3, ...\n\t\t\tstylePrefix: 'cts',\n\t\t\tcurrentUser: {\n\t\t\t\tid: null,\n\t\t\t\tname: null\n\t\t\t},\n\n\t\t\t// Default change types are insert and delete. Plugins or outside apps should extend this\n\t\t\t// if they want to manage new change types. The changeType name is used as a primary\n\t\t\t// reference for ice nodes; the `alias`, is dropped in the class attribute and is the\n\t\t\t// primary method of identifying ice nodes; and `tag` is used for construction only.\n\t\t\t// Invoking `this.getCleanContent()` will remove all delete type nodes and remove the tags\n\t\t\t// for the other types, leaving the html content in place.\n\t\t\tchangeTypes: {\n\t\t\t\tinsertType: {\n\t\t\t\t\ttag: 'span',\n\t\t\t\t\talias: 'ins',\n\t\t\t\t\taction: 'Inserted'\n\t\t\t\t},\n\t\t\t\tdeleteType: {\n\t\t\t\t\ttag: 'span',\n\t\t\t\t\talias: 'del',\n\t\t\t\t\taction: 'Deleted'\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// set maximum colors for tracked changes\n\t\t\t// if set to 12, user 13 will have same color as user 1\n\t\t\tstyleColorsNumber: 0,\n\n\t\t\t// If `true`, setup event listeners on `this.element` and handle events - good option for a basic\n\t\t\t// setup without a text editor. Otherwise, when set to `false`, events need to be manually passed\n\t\t\t// to `handleEvent`, which is good for a text editor with an event callback handler, like tinymce.\n\t\t\thandleEvents: false,\n\n\t\t\t// Sets this.element with the contentEditable element\n\t\t\tcontentEditable: true,\n\n\t\t\t// Switch for toggling track changes on/off - when `false` events will be ignored.\n\t\t\tisTracking: true,\n\n\t\t\t// NOT IMPLEMENTED - Selector for elements that will not get track changes\n\t\t\tnoTrack: '.ice-no-track',\n\n\t\t\t// Class name not tracked on deletion\n\t\t\tclassNotTracked: '',\n\n\t\t\t// Selector for elements to avoid - move range before or after - similar handling to deletes\n\t\t\tavoid: '.ice-avoid',\n\n\t\t\t// Switch for whether paragraph breaks should be removed when the user is deleting over a\n\t\t\t// paragraph break while changes are tracked.\n\t\t\tmergeBlocks: true\n\t\t};\n\n\t\tInlineChangeEditor = function (options) {\n\n\t\t\t// Data structure for modelling changes in the element according to the following model:\n\t\t\t//  [changeid] => {`type`, `time`, `userid`, `username`}\n\t\t\tthis._changes = {};\n\t\t\tthis._userStyles = {};\n\n\t\t\toptions || (options = {});\n\t\t\tif (!options.element) throw Error(\"`options.element` must be defined for ice construction.\");\n\t\t\tif (!options.styleColorsNumber) throw Error(\"`options.styleColorsNumber` must be set to > 0 for ice construction.\");\n\n\t\t\tice.dom.extend(true, this, defaults, options);\n\n\t\t\tthis.pluginsManager = new ice.IcePluginManager(this);\n\t\t\tif (options.plugins) this.pluginsManager.usePlugins('ice-init', options.plugins);\n\t\t};\n\n\t\tInlineChangeEditor.prototype = {\n\t\t\t// Tracks all of the styles for users according to the following model:\n\t\t\t//  [userId] => styleId; where style is \"this.stylePrefix\" + \"this.uniqueStyleIndex\"\n\t\t\t_userStyles: {},\n\t\t\t_trackedUsersId: [],\n\n\t\t\t_browserType: null,\n\n\t\t\t// One change may create multiple ice nodes, so this keeps track of the current batch id.\n\t\t\t_batchChangeid: null,\n\n\t\t\t// Incremented for each new change, dropped in the changeIdAttribute.\n\t\t\t// _uniqueIDIndex: null,\n\n\t\t\t// Temporary bookmark tags for deletes, when delete placeholding is active.\n\t\t\t_delBookmark: 'tempdel',\n\t\t\tisPlaceHoldingDeletes: false,\n\n\t\t\t/**\n\t\t\t * Turns on change tracking - sets up events, if needed, and initializes the environment,\n\t\t\t * range, and editor.\n\t\t\t */\n\t\t\tstartTracking: function () {\n\t\t\t\t// If we are handling events setup the delegate to handle various events on `this.element`.\n\t\t\t\tif (this.handleEvents) {\n\t\t\t\t\tvar self = this;\n\t\t\t\t\tice.dom.bind(self.element, 'keyup.ice keydown.ice keypress.ice mousedown.ice mouseup.ice', function (e) {\n\t\t\t\t\t\treturn self.handleEvent(e);\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.initializeEnvironment();\n\t\t\t\tthis.initializeEditor();\n\t\t\t\tthis.findTrackTags();\n\n\t\t\t\tthis.pluginsManager.fireEnabled(this.element);\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Removes contenteditability and stops event handling.\n\t\t\t */\n\t\t\tstopTracking: function () {\n\t\t\t\t// If we are handling events setup the delegate to handle various events on `this.element`.\n\t\t\t\tif (this.handleEvents) {\n\t\t\t\t\tvar self = this;\n\t\t\t\t\tice.dom.unbind(self.element, 'keyup.ice keydown.ice keypress.ice mousedown.ice mouseup.ice');\n\t\t\t\t}\n\n\t\t\t\tthis.pluginsManager.fireDisabled(this.element);\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Initializes the `env` object with pointers to key objects of the page.\n\t\t\t */\n\t\t\tinitializeEnvironment: function () {\n\t\t\t\tthis.env || (this.env = {});\n\t\t\t\tthis.env.element = this.element;\n\t\t\t\tthis.env.document = this.element.ownerDocument;\n\t\t\t\tthis.env.window = this.env.document.defaultView || this.env.document.parentWindow || window;\n\t\t\t\tthis.env.frame = this.env.window.frameElement;\n\t\t\t\tthis.env.selection = this.selection = new ice.Selection(this.env);\n\t\t\t\t// Hack for using custom tags in IE 8/7\n\t\t\t\tthis.env.document.createElement(this.changeTypes.insertType.tag);\n\t\t\t\tthis.env.document.createElement(this.changeTypes.deleteType.tag);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Initializes the content in the editor - cleans non-block nodes found between blocks.\n\t\t\t */\n\t\t\tinitializeEditor: function () {\n\t\t\t\t// Clean the element html body - add an empty block if there is no body, or remove any\n\t\t\t\t// content between elements.\n\t\t\t\tvar body = this.env.document.createElement('div');\n\t\t\t\tif (this.element.childNodes.length) {\n\t\t\t\t\tbody.innerHTML = this.element.innerHTML;\n\t\t\t\t\tice.dom.removeWhitespace(body);\n\t\t\t\t\tif (body.innerHTML === '') body.appendChild(ice.dom.create('<' + this.blockEl + ' ><br/></' + this.blockEl + '>'));\n\t\t\t\t} else {\n\t\t\t\t\tbody.appendChild(ice.dom.create('<' + this.blockEl + ' ><br/></' + this.blockEl + '>'));\n\t\t\t\t}\n\t\t\t\tif (this.element.innerHTML != body.innerHTML) {\n\t\t\t\t\tthis.element.innerHTML = body.innerHTML;\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\t/*\n\t\t\t * Updates the list of changes to include all track tags found inside the element.\n\t\t\t */\n\t\t\tfindTrackTags: function () {\n\n\t\t\t\t// Grab class for each changeType\n\t\t\t\tvar styleIndex = 1;\n\t\t\t\tvar self = this, changeTypeClasses = [];\n\t\t\t\tvar trackedElements = this.element.querySelectorAll('[data-cid]');\n\n\t\t\t\tif(trackedElements.length) {\n\t\t\t\t\tself._trackedUsersId = Array.prototype.map.call(trackedElements, function(elem) {\n\t\t\t\t\t\treturn parseInt(elem.attributes['data-userid'].nodeValue, 10);\n\t\t\t\t\t}).filter(function(elem, idx, arr) {\n\t\t\t\t\t\treturn arr.indexOf(elem) == idx;\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (var changeType in this.changeTypes) {\n\t\t\t\t\tchangeTypeClasses.push(this._getIceNodeClass(changeType));\n\t\t\t\t}\n\n\t\t\t\tice.dom.each(ice.dom.find(this.element, '.' + changeTypeClasses.join(', .')), function (i, el) {\n\t\t\t\t\tvar ctnType = '';\n\t\t\t\t\tvar classList = el.className.split(' ');\n\t\t\t\t\tfor (var i = 0; i < classList.length; i++) {\n\t\t\t\t\t\tvar ctnReg = new RegExp('(' + changeTypeClasses.join('|') + ')').exec(classList[i]);\n\t\t\t\t\t\tif (ctnReg) ctnType = self._getChangeTypeFromAlias(ctnReg[1]);\n\t\t\t\t\t}\n\t\t\t\t\tvar userid = ice.dom.attr(el, self.userIdAttribute);\n\t\t\t\t\tif (trackedElements.length) {\n\t\t\t\t\t\tstyleIndex = self._trackedUsersId.indexOf(userid) ? el.className.match(/\\d+/)[0] : self._trackedUsersId.length % self.styleColorsNumber + 1;\n\t\t\t\t\t}\n\t\t\t\t\tself.setUserStyle(userid, Number(styleIndex));\n\t\t\t\t\tvar changeid = ice.dom.attr(el, self.changeIdAttribute);\n\t\t\t\t\tself._changes[changeid] = {\n\t\t\t\t\t\ttype: ctnType,\n\t\t\t\t\t\tuserid: userid,\n\t\t\t\t\t\tusername: ice.dom.attr(el, self.userNameAttribute),\n\t\t\t\t\t\ttime: ice.dom.attr(el, self.timeAttribute)\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Turn on change tracking and event handling.\n\t\t\t */\n\t\t\tenableChangeTracking: function () {\n\t\t\t\tthis.isTracking = true;\n\t\t\t\tthis.pluginsManager.fireEnabled(this.element);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Turn off change tracking and event handling.\n\t\t\t */\n\t\t\tdisableChangeTracking: function () {\n\t\t\t\tthis.isTracking = false;\n\t\t\t\tthis.pluginsManager.fireDisabled(this.element);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Set the user to be tracked. A user object has the following properties:\n\t\t\t * {`id`, `name`}\n\t\t\t */\n\t\t\tsetCurrentUser: function (user) {\n\t\t\t\tthis.currentUser = user;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * If tracking is on, handles event e when it is one of the following types:\n\t\t\t * mouseup, mousedown, keypress, keydown, and keyup. Each event type is\n\t\t\t * propagated to all of the plugins. Prevents default handling if the event\n\t\t\t * was fully handled.\n\t\t\t */\n\t\t\thandleEvent: function (e) {\n\t\t\t\tif (!this.isTracking) return;\n\t\t\t\tif (e.type == 'mouseup') {\n\t\t\t\t\tvar self = this;\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\tself.mouseUp(e);\n\t\t\t\t\t}, 200);\n\t\t\t\t} else if (e.type == 'mousedown') {\n\t\t\t\t\treturn this.mouseDown(e);\n\t\t\t\t} else if (e.type == 'keypress') {\n\t\t\t\t\tvar needsToBubble = this.keyPress(e);\n\t\t\t\t\tif (!needsToBubble) e.preventDefault();\n\t\t\t\t\treturn needsToBubble;\n\t\t\t\t} else if (e.type == 'keydown') {\n\t\t\t\t\tvar needsToBubble = this.keyDown(e);\n\t\t\t\t\tif (!needsToBubble) e.preventDefault();\n\t\t\t\t\treturn needsToBubble;\n\t\t\t\t} else if (e.type == 'keyup') {\n\t\t\t\t\tthis.pluginsManager.fireCaretUpdated();\n\t\t\t\t}\n\t\t\t},\n\t\t\tvisible: function(el) {\n\t\t\t\tif(el.nodeType === ice.dom.TEXT_NODE) el = el.parentNode;\n\t\t\t\tvar rect = el.getBoundingClientRect();\n\t\t\t\treturn ( rect.top > 0 && rect.left > 0);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns a tracking tag for the given `changeType`, with the optional `childNode` appended.\n\t\t\t */\n\t\t\tcreateIceNode: function (changeType, childNode) {\n\t\t\t\tvar node = this.env.document.createElement(this.changeTypes[changeType].tag);\n\t\t\t\tice.dom.addClass(node, this._getIceNodeClass(changeType));\n\n\t\t\t\tnode.appendChild(childNode ? childNode : this.env.document.createTextNode(''));\n\t\t\t\tthis.addChange(this.changeTypes[changeType].alias, [node]);\n\n\t\t\t\tthis.pluginsManager.fireNodeCreated(node, {\n\t\t\t\t\t'action': this.changeTypes[changeType].action\n\t\t\t\t});\n\t\t\t\treturn node;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Inserts the given string/node into the given range with tracking tags, collapsing (deleting)\n\t\t\t * the range first if needed. If range is undefined, then the range from the Selection object\n\t\t\t * is used. If the range is in a parent delete node, then the range is positioned after the delete.\n\t\t\t */\n\t\t\tinsert: function (node, range) {\n\t\t\t\t// If the node is not defined, then we need to insert an\n\t\t\t\t// invisible space and force propagation to the browser.\n\t\t\t\tvar isPropagating = !node;\n\t\t\t\tnode || (node = '\\uFEFF');\n\n\t\t\t\tif (range) this.selection.addRange(range);\n\t\t\t\telse range = this.getCurrentRange();\n\n\t\t\t\trange = range.cloneRange();\n\t\t\t\tthis.selection._selection.removeAllRanges();\n\n\t\t\t\tif (typeof node === \"string\") node = document.createTextNode(node);\n\n\t\t\t\t// If we have any nodes selected, then we want to delete them before inserting the new text.\n\t\t\t\tif (!range.collapsed) {\n\t\t\t\t\tthis.deleteContents();\n\t\t\t\t\t// Update the range\n\t\t\t\t\trange = this.getCurrentRange();\n\t\t\t\t\tif (range.startContainer === range.endContainer && this.element === range.startContainer) {\n\t\t\t\t\t\t// The whole editable element is selected. Need to remove everything and init its contents.\n\t\t\t\t\t\tice.dom.empty(this.element);\n\t\t\t\t\t\tvar firstSelectable = range.getLastSelectableChild(this.element);\n\t\t\t\t\t\trange.setStartAfter(firstSelectable);\n\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If we are in a non-tracking/void element, move the range to the end/outside.\n\t\t\t\tthis._moveRangeToValidTrackingPos(range);\n\n\t\t\t\tvar changeid = this.startBatchChange();\n\t\t\t\t// Send a dummy node to be inserted, if node is undefined\n\t\t\t\tthis._insertNode(node, range, isPropagating);\n\t\t\t\tthis.pluginsManager.fireNodeInserted(node, range);\n\t\t\t\tthis.endBatchChange(changeid);\n\t\t\t\treturn isPropagating;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * This command will drop placeholders in place of delete tags in the element\n\t\t\t * body and store references in the `_deletes` array to the original delete nodes.\n\t\t\t *\n\t\t\t * A placeholder tag is of the following structure:\n\t\t\t *   <tempdel data-allocation=\"[NUM]\" />\n\t\t\t * Where [NUM] is the referenced allocation in the `_deletes` array where the\n\t\t\t * original delete node is stored.\n\t\t\t */\n\t\t\tplaceholdDeletes: function () {\n\t\t\t\tvar self = this;\n\t\t\t\tif (this.isPlaceholdingDeletes) {\n\t\t\t\t\tthis.revertDeletePlaceholders();\n\t\t\t\t}\n\t\t\t\tthis.isPlaceholdingDeletes = true;\n\t\t\t\tthis._deletes = [];\n\t\t\t\tvar deleteSelector = '.' + this._getIceNodeClass('deleteType');\n\t\t\t\tice.dom.each(ice.dom.find(this.element, deleteSelector), function (i, el) {\n\t\t\t\t\tself._deletes.push(ice.dom.cloneNode(el));\n\t\t\t\t\tice.dom.replaceWith(el, '<' + self._delBookmark + ' data-allocation=\"' + (self._deletes.length - 1) + '\"/>');\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Replaces all delete placeholders in the element body with the referenced\n\t\t\t * delete nodes in the `_deletes` array.\n\t\t\t *\n\t\t\t * A placeholder tag is of the following structure:\n\t\t\t *   <tempdel data-allocation=\"[NUM]\" />\n\t\t\t * Where [NUM] is the referenced allocation in the `_deletes` array where the\n\t\t\t * original delete node is stored.\n\t\t\t */\n\t\t\trevertDeletePlaceholders: function () {\n\t\t\t\tvar self = this;\n\t\t\t\tif (!this.isPlaceholdingDeletes) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tice.dom.each(this._deletes, function (i, el) {\n\t\t\t\t\tice.dom.find(self.element, self._delBookmark + '[data-allocation=' + i + ']').replaceWith(el);\n\t\t\t\t});\n\t\t\t\tthis.isPlaceholdingDeletes = false;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t/**\n\t\t\t * Deletes the contents in the given range or the range from the Selection object. If the range\n\t\t\t * is not collapsed, then a selection delete is handled; otherwise, it deletes one character\n\t\t\t * to the left or right if the right parameter is false or true, respectively.\n\t\t\t *\n\t\t\t * @return true if deletion was handled.\n\t\t\t */\n\t\t\tdeleteContents: function (right, range) {\n\t\t\t\tvar prevent = true;\n\t\t\t\tvar browser = ice.dom.browser();\n\n\t\t\t\tif (range) {\n\t\t\t\t\tthis.selection.addRange(range);\n\t\t\t\t} else {\n\t\t\t\t\trange = this.getCurrentRange();\n\t\t\t\t}\n\n\t\t\t\tvar changeid = this.startBatchChange(this.changeTypes['deleteType'].alias);\n\t\t\t\tif (range.collapsed === false) {\n\t\t\t\t\tif(this._currentUserIceNode(range.startContainer.parentNode)){\n\t\t\t\t\t\tthis._deleteSelection(range);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._deleteSelection(range);\n\t\t\t\t\t\tif(browser[\"type\"] === \"mozilla\"){\n\t\t\t\t\t\t\tif(range.startContainer.parentNode.nextSibling){\n\t\t\t\t\t\t\t\trange.setEnd(range.startContainer.parentNode.nextSibling, 0);\n\t\t\t\t\t\t\t\t// range.moveEnd(ice.dom.CHARACTER_UNIT, ice.dom.getNodeCharacterLength(range.endContainer));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trange.setEndAfter(range.startContainer.parentNode);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trange.collapse(false);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif(!this.visible(range.endContainer)){\n\t\t\t\t\t\t\t\trange.setEnd(range.endContainer, range.endOffset - 1);\n\t\t\t\t\t\t\t\trange.collapse(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (right) {\n\t\t\t\t\t\t// RIGHT DELETE\n\t\t\t\t\t\tif(browser[\"type\"] === \"mozilla\"){\n\t\t\t\t\t\t\tprevent = this._deleteRight(range);\n\t\t\t\t\t\t\t// Handling track change show/hide\n\t\t\t\t\t\t\tif(!this.visible(range.endContainer)){\n\t\t\t\t\t\t\t\tif(range.endContainer.parentNode.nextSibling){\n\t\t\t\t\t\t\t\t\t//            range.setEnd(range.endContainer.parentNode.nextSibling, 0);\n\t\t\t\t\t\t\t\t\trange.setEndBefore(range.endContainer.parentNode.nextSibling);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\trange.setEndAfter(range.endContainer);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trange.collapse(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Calibrate Cursor before deleting\n\t\t\t\t\t\t\tif(range.endOffset === ice.dom.getNodeCharacterLength(range.endContainer)){\n\t\t\t\t\t\t\t\tvar next = range.startContainer.nextSibling;\n\t\t\t\t\t\t\t\tif (ice.dom.is(next,  '.' + this._getIceNodeClass('deleteType'))) {\n\t\t\t\t\t\t\t\t\twhile(next){\n\t\t\t\t\t\t\t\t\t\tif (ice.dom.is(next,  '.' + this._getIceNodeClass('deleteType'))) {\n\t\t\t\t\t\t\t\t\t\t\tnext = next.nextSibling;\n\t\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\trange.setStart(next, 0);\n\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Delete\n\t\t\t\t\t\t\tprevent = this._deleteRight(range);\n\n\t\t\t\t\t\t\t// Calibrate Cursor after deleting\n\t\t\t\t\t\t\tif(!this.visible(range.endContainer)){\n\t\t\t\t\t\t\t\tif (ice.dom.is(range.endContainer.parentNode,  '.' + this._getIceNodeClass('insertType') + ', .' + this._getIceNodeClass('deleteType'))) {\n\t\t\t\t\t\t\t\t\t//            range.setStart(range.endContainer.parentNode.nextSibling, 0);\n\t\t\t\t\t\t\t\t\trange.setStartAfter(range.endContainer.parentNode);\n\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// LEFT DELETE\n\t\t\t\t\t\tif(browser[\"type\"] === \"mozilla\"){\n\t\t\t\t\t\t\tprevent = this._deleteLeft(range);\n\t\t\t\t\t\t\t// Handling track change show/hide\n\t\t\t\t\t\t\tif(!this.visible(range.startContainer)){\n\t\t\t\t\t\t\t\tif(range.startContainer.parentNode.previousSibling){\n\t\t\t\t\t\t\t\t\trange.setEnd(range.startContainer.parentNode.previousSibling, 0);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\trange.setEnd(range.startContainer.parentNode, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trange.moveEnd(ice.dom.CHARACTER_UNIT, ice.dom.getNodeCharacterLength(range.endContainer));\n\t\t\t\t\t\t\t\trange.collapse(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif(!this.visible(range.startContainer)){\n\t\t\t\t\t\t\t\tif(range.endOffset === ice.dom.getNodeCharacterLength(range.endContainer)){\n\t\t\t\t\t\t\t\t\tvar prev = range.startContainer.previousSibling;\n\t\t\t\t\t\t\t\t\tif (ice.dom.is(prev,  '.' + this._getIceNodeClass('deleteType'))) {\n\t\t\t\t\t\t\t\t\t\twhile(prev){\n\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.is(prev,  '.' + this._getIceNodeClass('deleteType'))) {\n\t\t\t\t\t\t\t\t\t\t\t\tprev = prev.prevSibling;\n\t\t\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\trange.setEndBefore(prev.nextSibling, 0);\n\t\t\t\t\t\t\t\t\t\t\trange.collapse(false);\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tprevent = this._deleteLeft(range);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.selection.addRange(range);\n\t\t\t\tthis.endBatchChange(changeid);\n\t\t\t\treturn prevent;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the changes - a hash of objects with the following properties:\n\t\t\t * [changeid] => {`type`, `time`, `userid`, `username`}\n\t\t\t */\n\t\t\tgetChanges: function () {\n\t\t\t\treturn this._changes;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns an array with the user ids who made the changes\n\t\t\t */\n\t\t\tgetChangeUserids: function () {\n\t\t\t\tvar result = [];\n\t\t\t\tvar keys = Object.keys(this._changes);\n\n\t\t\t\tfor (var key in keys)\n\t\t\t\t\tresult.push(this._changes[keys[key]].userid);\n\n\t\t\t\treturn result.sort().filter(function (el, i, a) {\n\t\t\t\t\tif (i == a.indexOf(el)) return 1;\n\t\t\t\t\treturn 0;\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the html contents for the tracked element.\n\t\t\t */\n\t\t\tgetElementContent: function () {\n\t\t\t\treturn this.element.innerHTML;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the html contents, without tracking tags, for `this.element` or\n\t\t\t * the optional `body` param which can be of either type string or node.\n\t\t\t * Delete tags, and their html content, are completely removed; all other\n\t\t\t * change type tags are removed, leaving the html content in place. After\n\t\t\t * cleaning, the optional `callback` is executed, which should further\n\t\t\t * modify and return the element body.\n\t\t\t *\n\t\t\t * prepare gets run before the body is cleaned by ice.\n\t\t\t */\n\t\t\tgetCleanContent: function (body, callback, prepare) {\n\t\t\t\tvar classList = '';\n\t\t\t\tvar self = this;\n\t\t\t\tice.dom.each(this.changeTypes, function (type, i) {\n\t\t\t\t\tif (type != 'deleteType') {\n\t\t\t\t\t\tif (i > 0) classList += ',';\n\t\t\t\t\t\tclassList += '.' + self._getIceNodeClass(type);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (body) {\n\t\t\t\t\tif (typeof body === 'string') body = ice.dom.create('<div>' + body + '</div>');\n\t\t\t\t\telse body = ice.dom.cloneNode(body, false)[0];\n\t\t\t\t} else {\n\t\t\t\t\tbody = ice.dom.cloneNode(this.element, false)[0];\n\t\t\t\t}\n\t\t\t\tbody = prepare ? prepare.call(this, body) : body;\n\t\t\t\tvar changes = ice.dom.find(body, classList);\n\t\t\t\tice.dom.each(changes, function (el, i) {\n\t\t\t\t\tice.dom.replaceWith(this, ice.dom.contents(this));\n\t\t\t\t});\n\t\t\t\tvar deletes = ice.dom.find(body, '.' + this._getIceNodeClass('deleteType'));\n\t\t\t\tice.dom.remove(deletes);\n\n\t\t\t\tbody = callback ? callback.call(this, body) : body;\n\n\t\t\t\treturn body.innerHTML;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Accepts all changes in the element body - removes delete nodes, and removes outer\n\t\t\t * insert tags keeping the inner content in place.\n\t\t\t */\n\t\t\tacceptAll: function () {\n\t\t\t\tthis.element.innerHTML = this.getCleanContent();\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Rejects all changes in the element body - removes insert nodes, and removes outer\n\t\t\t * delete tags keeping the inner content in place.*\n\t\t\t */\n\t\t\trejectAll: function () {\n\t\t\t\tvar insSel = '.' + this._getIceNodeClass('insertType');\n\t\t\t\tvar delSel = '.' + this._getIceNodeClass('deleteType');\n\n\t\t\t\tice.dom.remove(ice.dom.find(this.element, insSel));\n\t\t\t\tice.dom.each(ice.dom.find(this.element, delSel), function (i, el) {\n\t\t\t\t\tice.dom.replaceWith(el, ice.dom.contents(el));\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Accepts the change at the given, or first tracking parent node of, `node`.  If\n\t\t\t * `node` is undefined then the startContainer of the current collapsed range will be used.\n\t\t\t * In the case of insert, inner content will be used to replace the containing tag; and in\n\t\t\t * the case of delete, the node will be removed.\n\t\t\t */\n\t\t\tacceptChange: function (node) {\n\t\t\t\tthis.acceptRejectChange(node, true);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Rejects the change at the given, or first tracking parent node of, `node`.  If\n\t\t\t * `node` is undefined then the startContainer of the current collapsed range will be used.\n\t\t\t * In the case of delete, inner content will be used to replace the containing tag; and in\n\t\t\t * the case of insert, the node will be removed.\n\t\t\t */\n\t\t\trejectChange: function (node) {\n\t\t\t\tthis.acceptRejectChange(node, false);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Handles accepting or rejecting tracking changes\n\t\t\t */\n\t\t\tacceptRejectChange: function (node, isAccept) {\n\t\t\t\tvar delSel, insSel, selector, removeSel, replaceSel, trackNode, changes, dom = ice.dom;\n\t\t\t\tvar nodeParent = node.parentElement;\n\t\t\t\tvar nodeParentChanges = null;\n\n\t\t\t\tif (!node) {\n\t\t\t\t\tvar range = this.getCurrentRange();\n\t\t\t\t\tif (!range.collapsed) return;\n\t\t\t\t\telse node = range.startContainer;\n\t\t\t\t}\n\n\t\t\t\tdelSel = removeSel = '.' + this._getIceNodeClass('deleteType');\n\t\t\t\tinsSel = replaceSel = '.' + this._getIceNodeClass('insertType');\n\t\t\t\tselector = delSel + ',' + insSel;\n\t\t\t\ttrackNode = dom.getNode(node, selector);\n\t\t\t\t// Some changes are done in batches so there may be other tracking\n\t\t\t\t// nodes with the same `changeIdAttribute` batch number.\n\t\t\t\tchanges = dom.find(this.element, '[' + this.changeIdAttribute + '=' + dom.attr(trackNode, this.changeIdAttribute) + ']');\n\t\t\t\tnodeParentChanges = [].map.call(changes, function(change) {\n\t\t\t\t\tvar parent = change.parentElement;\n\t\t\t\t\twhile(parent && this.blockParentsNodeName.indexOf(parent.nodeName) === -1) {\n\t\t\t\t\t\tparent = parent.parentElement;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn parent;\n\t\t\t\t}.bind(this));\n\n\t\t\t\tif (!isAccept) {\n\t\t\t\t\tremoveSel = insSel;\n\t\t\t\t\treplaceSel = delSel;\n\t\t\t\t}\n\n\t\t\t\tif (ice.dom.is(trackNode, replaceSel)) {\n\t\t\t\t\tdom.each(changes, function (i, node) {\n\t\t\t\t\t\tdom.replaceWith(node, ice.dom.contents(node));\n\t\t\t\t\t});\n\t\t\t\t} else if (dom.is(trackNode, removeSel)) {\n\t\t\t\t\tdom.remove(changes);\n\t\t\t\t\tnodeParentChanges = nodeParentChanges.filter(function (node) {\n\t\t\t\t\t\treturn dom.hasNoTextOrStubContent(node);\n\t\t\t\t\t});\n\t\t\t\t\tif (nodeParentChanges.length && isAccept) {\n\t\t\t\t\t\tdom.remove(nodeParentChanges);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns true if the given `node`, or the current collapsed range is in a tracking\n\t\t\t * node; otherwise, false.\n\t\t\t */\n\t\t\tisInsideChange: function (node) {\n\t\t\t\tvar selector = '.' + this._getIceNodeClass('insertType') + ', .' + this._getIceNodeClass('deleteType');\n\t\t\t\tif (!node) {\n\t\t\t\t\tvar range = this.getCurrentRange();\n\t\t\t\t\tif (!range.collapsed) return false;\n\t\t\t\t\telse node = range.startContainer;\n\t\t\t\t}\n\t\t\t\treturn !!ice.dom.getNode(node, selector);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Add a new change tracking typeName with the given tag and alias.\n\t\t\t */\n\t\t\taddChangeType: function (typeName, tag, alias, action) {\n\t\t\t\tvar changeType = {\n\t\t\t\t\ttag: tag,\n\t\t\t\t\talias: alias\n\t\t\t\t};\n\n\t\t\t\tif (action) changeType.action = action;\n\n\t\t\t\tthis.changeTypes[typeName] = changeType;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns this `node` or the first parent tracking node with the given `changeType`.\n\t\t\t */\n\t\t\tgetIceNode: function (node, changeType) {\n\t\t\t\tvar selector = '.' + this._getIceNodeClass(changeType);\n\t\t\t\treturn ice.dom.getNode(node, selector);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Sets the given `range` to the first position, to the right, where it is outside of\n\t\t\t * void elements.\n\t\t\t */\n\t\t\t_moveRangeToValidTrackingPos: function (range) {\n\t\t\t\tvar onEdge = false;\n\t\t\t\tvar voidEl = this._getVoidElement(range.endContainer);\n\t\t\t\twhile (voidEl) {\n\t\t\t\t\t// Move end of range to position it inside of any potential adjacent containers\n\t\t\t\t\t// E.G.:  test|<em>text</em>  ->  test<em>|text</em>\n\t\t\t\t\ttry {\n\t\t\t\t\t\trange.moveEnd(ice.dom.CHARACTER_UNIT, 1);\n\t\t\t\t\t\trange.moveEnd(ice.dom.CHARACTER_UNIT, -1);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// Moving outside of the element and nothing is left on the page\n\t\t\t\t\t\tonEdge = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (onEdge || ice.dom.onBlockBoundary(range.endContainer, range.startContainer, this.blockEls)) {\n\t\t\t\t\t\trange.setStartAfter(voidEl);\n\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tvoidEl = this._getVoidElement(range.endContainer);\n\t\t\t\t\tif (voidEl) {\n\t\t\t\t\t\trange.setEnd(range.endContainer, 0);\n\t\t\t\t\t\trange.moveEnd(ice.dom.CHARACTER_UNIT, ice.dom.getNodeCharacterLength(range.endContainer));\n\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t} else {\n\t\t\t\t\t\trange.setStart(range.endContainer, 0);\n\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the given `node` or the first parent node that matches against the list of no track elements.\n\t\t\t */\n\t\t\t_getNoTrackElement: function (node) {\n\t\t\t\tvar noTrackSelector = this._getNoTrackSelector();\n\t\t\t\tvar parent = ice.dom.is(node, noTrackSelector) ? node : (ice.dom.parents(node, noTrackSelector)[0] || null);\n\t\t\t\treturn parent;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns a selector for not tracking changes\n\t\t\t */\n\t\t\t_getNoTrackSelector: function () {\n\t\t\t\treturn this.noTrack;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the given `node` or the first parent node that matches against the list of void elements.\n\t\t\t */\n\t\t\t_getVoidElement: function (node) {\n\t\t\t\tvar voidSelector = this._getVoidElSelector();\n\t\t\t\treturn ice.dom.is(node, voidSelector) ? node : (ice.dom.parents(node, voidSelector)[0] || null);\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns a combined selector for delete and void elements.\n\t\t\t */\n\t\t\t_getVoidElSelector: function () {\n\t\t\t\treturn '.' + this._getIceNodeClass('deleteType') + ',' + this.avoid;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns true if node has a user id attribute that matches the current user id.\n\t\t\t */\n\t\t\t_currentUserIceNode: function (node) {\n\t\t\t\treturn ice.dom.attr(node, this.userIdAttribute) == this.currentUser.id;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * With the given alias, searches the changeTypes objects and returns the\n\t\t\t * associated key for the alias.\n\t\t\t */\n\t\t\t_getChangeTypeFromAlias: function (alias) {\n\t\t\t\tvar type, ctnType = null;\n\t\t\t\tfor (type in this.changeTypes) {\n\t\t\t\t\tif (this.changeTypes.hasOwnProperty(type)) {\n\t\t\t\t\t\tif (this.changeTypes[type].alias == alias) {\n\t\t\t\t\t\t\tctnType = type;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ctnType;\n\t\t\t},\n\n\t\t\t_getIceNodeClass: function (changeType) {\n\t\t\t\treturn this.attrValuePrefix + this.changeTypes[changeType].alias;\n\t\t\t},\n\n\t\t\tgetUserStyle: function (userid) {\n\t\t\t\tvar styleIndex = null;\n\t\t\t\tif (this._userStyles[userid]) styleIndex = this._userStyles[userid];\n\t\t\t\telse styleIndex = this.setUserStyle(userid, this.getNewStyleId(userid));\n\t\t\t\treturn styleIndex;\n\t\t\t},\n\n\t\t\tsetUserStyle: function (userid, styleIndex) {\n\t\t\t\tvar style = this.stylePrefix + '-' + styleIndex;\n\t\t\t\treturn this._userStyles[userid] = style;\n\t\t\t},\n\n\t\t\tgetNewStyleId: function (userid) {\n\t\t\t\treturn this._userStyles[userid] ? this._userStyles[userid].match(/\\d+/)[0] : this._trackedUsersId.length % this.styleColorsNumber + 1;\n\t\t\t},\n\n\t\t\taddChange: function (ctnType, ctNodes) {\n\t\t\t\tvar changeid = this._batchChangeid || this.getNewChangeId();\n\t\t\t\tif (!this._changes[changeid]) {\n\t\t\t\t\t// Create the change object.\n\t\t\t\t\tthis._changes[changeid] = {\n\t\t\t\t\t\ttype: this._getChangeTypeFromAlias(ctnType),\n\t\t\t\t\t\ttime: (new Date()).getTime(),\n\t\t\t\t\t\tuserid: this.currentUser.id,\n\t\t\t\t\t\tusername: this.currentUser.name\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tvar self = this;\n\t\t\t\tice.dom.foreach(ctNodes, function (i) {\n\t\t\t\t\tself.addNodeToChange(changeid, ctNodes[i]);\n\t\t\t\t});\n\n\t\t\t\treturn changeid;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Adds tracking attributes from the change with changeid to the ctNode.\n\t\t\t * @param changeid Id of an existing change.\n\t\t\t * @param ctNode The element to add for the change.\n\t\t\t */\n\t\t\taddNodeToChange: function (changeid, ctNode) {\n\t\t\t\tif (this._batchChangeid !== null) changeid = this._batchChangeid;\n\n\t\t\t\tvar change = this.getChange(changeid);\n\n\t\t\t\tif (!ctNode.getAttribute(this.changeIdAttribute)) ctNode.setAttribute(this.changeIdAttribute, changeid);\n\n\t\t\t\tif (!ctNode.getAttribute(this.userIdAttribute)) ctNode.setAttribute(this.userIdAttribute, change.userid);\n\n\t\t\t\tif (!ctNode.getAttribute(this.userNameAttribute)) ctNode.setAttribute(this.userNameAttribute, change.username);\n\n\t\t\t\tif (!ctNode.getAttribute(this.timeAttribute)) ctNode.setAttribute(this.timeAttribute, change.time);\n\n\t\t\t\tif (!ice.dom.hasClass(ctNode, this._getIceNodeClass(change.type))) ice.dom.addClass(ctNode, this._getIceNodeClass(change.type));\n\n\t\t\t\tvar style = this.getUserStyle(change.userid);\n\t\t\t\tif (!ice.dom.hasClass(ctNode, style)) ice.dom.addClass(ctNode, style);\n\t\t\t},\n\n\t\t\tgetChange: function (changeid) {\n\t\t\t\tvar change = null;\n\t\t\t\tif (this._changes[changeid]) {\n\t\t\t\t\tchange = this._changes[changeid];\n\t\t\t\t}\n\t\t\t\treturn change;\n\t\t\t},\n\n\t\t\tgetNewChangeId: function () {\n\t\t\t\tvar getUuid = function() {\n\t\t\t    var d = new Date().getTime();\n\t\t\t    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n\t\t        var r = (d + Math.random()*16)%16 | 0;\n\t\t        d = Math.floor(d/16);\n\t\t        return (c=='x' ? r : (r&0x3|0x8)).toString(16);\n\t\t\t    });\n\t\t\t    return uuid;\n\t\t\t\t}\n\n\t\t\t\tvar id = getUuid(); // ++this._uniqueIDIndex;\n\t\t\t\tif (this._changes[id]) {\n\t\t\t\t\t// Dupe.. create another..\n\t\t\t\t\tid = this.getNewChangeId();\n\t\t\t\t}\n\t\t\t\treturn id;\n\t\t\t},\n\n\t\t\tstartBatchChange: function () {\n\t\t\t\tthis._batchChangeid = this.getNewChangeId();\n\t\t\t\treturn this._batchChangeid;\n\t\t\t},\n\n\t\t\tendBatchChange: function (changeid) {\n\t\t\t\tif (changeid !== this._batchChangeid) return;\n\t\t\t\tthis._batchChangeid = null;\n\t\t\t},\n\n\t\t\tgetCurrentRange: function () {\n\t\t\t\treturn this.selection.getRangeAt(0);\n\t\t\t},\n\n\t\t\t_insertNode: function (node, range, insertingDummy) {\n\t\t\t\tvar origNode = node;\n\t\t\t\tif (!ice.dom.isBlockElement(range.startContainer) && !ice.dom.canContainTextElement(ice.dom.getBlockParent(range.startContainer, this.element)) && range.startContainer.previousSibling) {\n\t\t\t\t\trange.setStart(range.startContainer.previousSibling, 0);\n\n\t\t\t\t}\n\t\t\t\tvar startContainer = range.startContainer;\n\t\t\t\tvar parentBlock = ice.dom.isBlockElement(range.startContainer) && range.startContainer || ice.dom.getBlockParent(range.startContainer, this.element) || null;\n\t\t\t\tif (parentBlock === this.element) {\n\t\t\t\t\tvar firstPar = document.createElement(this.blockEl);\n\t\t\t\t\tparentBlock.appendChild(firstPar);\n\t\t\t\t\trange.setStart(firstPar, 0);\n\t\t\t\t\trange.collapse();\n\t\t\t\t\treturn this._insertNode(node, range, insertingDummy);\n\t\t\t\t}\n\t\t\t\tif (ice.dom.hasNoTextOrStubContent(parentBlock)) {\n\t\t\t\t\tice.dom.empty(parentBlock);\n\t\t\t\t\tice.dom.append(parentBlock, '<br>');\n\t\t\t\t\trange.setStart(parentBlock, 0);\n\t\t\t\t}\n\n\t\t\t\tvar ctNode = this.getIceNode(range.startContainer, 'insertType');\n\t\t\t\tvar inCurrentUserInsert = this._currentUserIceNode(ctNode);\n\n\t\t\t\t// Do nothing, let this bubble-up to insertion handler.\n\t\t\t\tif (insertingDummy && inCurrentUserInsert) return;\n\t\t\t\t// If we aren't in an insert node which belongs to the current user, then create a new ins node\n\t\t\t\telse if (!inCurrentUserInsert) node = this.createIceNode('insertType', node);\n\n\t\t\t\trange.insertNode(node);\n\t\t\t\trange.setEnd(node, 1);\n\n\t\t\t\tif (insertingDummy) {\n\t\t\t\t\t// Create a selection of the dummy character we inserted\n\t\t\t\t\t// which will be removed after it bubbles up to the final handler.\n\t\t\t\t\trange.setStart(node, 0);\n\t\t\t\t} else {\n\t\t\t\t\trange.collapse();\n\t\t\t\t}\n\n\t\t\t\tthis.selection.addRange(range);\n\t\t\t},\n\n\t\t\t_handleVoidEl: function(el, range) {\n\t\t\t\t// If `el` is or is in a void element, but not a delete\n\t\t\t\t// then collapse the `range` and return `true`.\n\t\t\t\tvar voidEl = this._getVoidElement(el);\n\t\t\t\tif (voidEl && !this.getIceNode(voidEl, 'deleteType')) {\n\t\t\t\t\trange.collapse(true);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\n\t\t\t_deleteSelection: function (range) {\n\n\t\t\t\t// Bookmark the range and get elements between.\n\t\t\t\tvar bookmark = new ice.Bookmark(this.env, range);\n\t\t\t\tvar elements = ice.dom.getElementsBetween(bookmark.start, bookmark.end);\n\t\t\t\tvar b1 = ice.dom.parents(range.startContainer, this.blockEls.join(', '))[0];\n\t\t\t\tvar b2 = ice.dom.parents(range.endContainer, this.blockEls.join(', '))[0];\n\t\t\t\tvar betweenBlocks = new Array();\n\n\t\t\t\t// Do not track editable fields\n\t\t\t\telements = elements.filter(function(element) {\n\t\t\t\t\treturn element.nodeType === 1  && element.className ? element.className.indexOf(this.classNotTracked) === -1 : element;\n\t\t\t\t}.bind(this));\n\n\t\t\t\tfor (var i = 0; i < elements.length; i++) {\n\t\t\t\t\tvar elem = elements[i];\n\t\t\t\t\tif (ice.dom.isBlockElement(elem)) {\n\t\t\t\t\t\tbetweenBlocks.push(elem);\n\t\t\t\t\t\tif (!ice.dom.canContainTextElement(elem)) {\n\t\t\t\t\t\t\t// Ignore containers that are not supposed to contain text. Check children instead.\n\t\t\t\t\t\t\tfor (var k = 0; k < elem.childNodes.length; k++) {\n\t\t\t\t\t\t\t\telements.push(elem.childNodes[k]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Ignore empty space nodes\n\t\t\t\t\tif (elem.nodeType === ice.dom.TEXT_NODE && ice.dom.getNodeTextContent(elem).length === 0) continue;\n\n\t\t\t\t\tif (!this._getVoidElement(elem)) {\n\t\t\t\t\t\t// If the element is not a text or stub node, go deeper and check the children.\n\t\t\t\t\t\tif (elem.nodeType !== ice.dom.TEXT_NODE) {\n\t\t\t\t\t\t\t// Browsers like to insert breaks into empty paragraphs - remove them\n\t\t\t\t\t\t\tif (ice.dom.BREAK_ELEMENT == ice.dom.getTagName(elem)) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (ice.dom.isStubElement(elem)) {\n\t\t\t\t\t\t\t\tthis._addNodeTracking(elem, false, true);\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (ice.dom.hasNoTextOrStubContent(elem)) {\n\t\t\t\t\t\t\t\tice.dom.remove(elem);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfor (var j = 0; j < elem.childNodes.length; j++) {\n\t\t\t\t\t\t\t\tvar child = elem.childNodes[j];\n\t\t\t\t\t\t\t\telements.push(child);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar parentBlock = ice.dom.getBlockParent(elem);\n\t\t\t\t\t\tthis._addNodeTracking(elem, false, true, true);\n\t\t\t\t\t\tif (ice.dom.hasNoTextOrStubContent(parentBlock)) {\n\t\t\t\t\t\t\tice.dom.remove(parentBlock);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (this.mergeBlocks && b1 !== b2) {\n\t\t\t\t\twhile (betweenBlocks.length)\n\t\t\t\t\t\tice.dom.mergeContainers(betweenBlocks.shift(), b1);\n\t\t\t\t\tice.dom.removeBRFromChild(b2);\n\t\t\t\t\tice.dom.removeBRFromChild(b1);\n\t\t\t\t\tice.dom.mergeContainers(b2, b1);\n\t\t\t\t}\n\n\t\t\t\tbookmark.selectBookmark();\n\t\t\t\t//      range.collapse(false);\n\t\t\t\trange.collapse(true);\n\t\t\t},\n\n\t\t\t// Delete\n\t\t\t_deleteRight: function (range) {\n\n\t\t\t\tvar parentBlock = ice.dom.isBlockElement(range.startContainer) && range.startContainer || ice.dom.getBlockParent(range.startContainer, this.element) || null,\n\t\t\t\t\tisEmptyBlock = parentBlock ? (ice.dom.hasNoTextOrStubContent(parentBlock)) : false,\n\t\t\t\t\t\tnextBlock = parentBlock && ice.dom.getNextContentNode(parentBlock, this.element),\n\t\t\t\t\t\t\tnextBlockIsEmpty = nextBlock ? (ice.dom.hasNoTextOrStubContent(nextBlock)) : false,\n\t\t\t\t\t\t\t\tinitialContainer = range.endContainer,\n\t\t\t\t\t\t\t\t\tinitialOffset = range.endOffset,\n\t\t\t\t\t\t\t\t\t\tcommonAncestor = range.commonAncestorContainer,\n\t\t\t\t\t\t\t\t\t\t\tnextContainer, returnValue;\n\n\t\t\t\t\t\t\t\t\t\t\t// Some bugs in Firefox and Webkit make the caret disappear out of text nodes, so we try to put them back in.\n\t\t\t\t\t\t\t\t\t\t\tif (commonAncestor.nodeType !== ice.dom.TEXT_NODE) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If placed at the beginning of a container that cannot contain text, such as an ul element, place the caret at the beginning of the first item.\n\t\t\t\t\t\t\t\t\t\t\t\tif (initialOffset === 0 && ice.dom.isBlockElement(commonAncestor) && (!ice.dom.canContainTextElement(commonAncestor))) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar firstItem = commonAncestor.firstElementChild;\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (firstItem) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(firstItem, 0);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn this._deleteRight(range);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (commonAncestor.childNodes.length > initialOffset) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar tempTextContainer = document.createTextNode(' ');\n\t\t\t\t\t\t\t\t\t\t\t\t\tcommonAncestor.insertBefore(tempTextContainer, commonAncestor.childNodes[initialOffset]);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(tempTextContainer, 1);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturnValue = this._deleteRight(range);\n\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(tempTextContainer);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn returnValue;\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\tnextContainer = ice.dom.getNextContentNode(commonAncestor, this.element);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.setEnd(nextContainer, 0);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn this._deleteRight(range);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Move range to position the cursor on the inside of any adjacent container that it is going\n\t\t\t\t\t\t\t\t\t\t\t// to potentially delete into or after a stub element.  E.G.:  test|<em>text</em>  ->  test<em>|text</em> or\n\t\t\t\t\t\t\t\t\t\t\t// text1 |<img> text2 -> text1 <img>| text2\n\n\t\t\t\t\t\t\t\t\t\t\t// Merge blocks: If mergeBlocks is enabled, merge the previous and current block.\n\t\t\t\t\t\t\t\t\t\t\trange.moveEnd(ice.dom.CHARACTER_UNIT, 1);\n\t\t\t\t\t\t\t\t\t\t\trange.moveEnd(ice.dom.CHARACTER_UNIT, -1);\n\n\t\t\t\t\t\t\t\t\t\t\t// Handle cases of the caret is at the end of a container or placed directly in a block element\n\t\t\t\t\t\t\t\t\t\t\tif (initialOffset === initialContainer.data.length && (!ice.dom.hasNoTextOrStubContent(initialContainer))) {\n\t\t\t\t\t\t\t\t\t\t\t\tnextContainer = ice.dom.getNextNode(initialContainer, this.element);\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the next container is outside of ICE then do nothing.\n\t\t\t\t\t\t\t\t\t\t\t\tif (!nextContainer) {\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.selectNodeContents(initialContainer);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the next container is <br> element find the next node\n\t\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.BREAK_ELEMENT == ice.dom.getTagName(nextContainer)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tnextContainer = ice.dom.getNextNode(nextContainer, this.element);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t// If the next container is a text node, look at the parent node instead.\n\t\t\t\t\t\t\t\t\t\t\t\tif (nextContainer.nodeType === ice.dom.TEXT_NODE) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tnextContainer = nextContainer.parentNode;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (nextContainer.nodeName === 'IMG') {\n\t\t\t\t\t\t\t\t\t\t\t\t\tnextContainer.parentNode.removeChild(nextContainer);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the next container is non-editable, enclose it with a delete ice node and add an empty text node after it to position the caret.\n\t\t\t\t\t\t\t\t\t\t\t\tif (!nextContainer.isContentEditable) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturnValue = this._addNodeTracking(nextContainer, false, false);\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar emptySpaceNode = document.createTextNode('');\n\t\t\t\t\t\t\t\t\t\t\t\t\tnextContainer.parentNode.insertBefore(emptySpaceNode, nextContainer.nextSibling);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.selectNode(emptySpaceNode);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn returnValue;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (this._handleVoidEl(nextContainer, range)) return true;\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the caret was placed directly before a stub element, enclose the element with a delete ice node.\n\t\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.isChildOf(nextContainer, parentBlock) && ice.dom.isStubElement(nextContainer)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn this._addNodeTracking(nextContainer, range, false);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tif (this._handleVoidEl(nextContainer, range)) return true;\n\n\t\t\t\t\t\t\t\t\t\t\t// If we are deleting into a no tracking containiner, then remove the content\n\t\t\t\t\t\t\t\t\t\t\tif (this._getNoTrackElement(range.endContainer.parentElement)) {\n\t\t\t\t\t\t\t\t\t\t\t\trange.deleteContents();\n\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.isOnBlockBoundary(range.startContainer, range.endContainer, this.element)) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (this.mergeBlocks && ice.dom.is(ice.dom.getBlockParent(nextContainer, this.element), this.blockEl)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Since the range is moved by character, it may have passed through empty blocks.\n\t\t\t\t\t\t\t\t\t\t\t\t\t// <p>text {RANGE.START}</p><p></p><p>{RANGE.END} text</p>\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (nextBlock !== ice.dom.getBlockParent(range.endContainer, this.element)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.setEnd(nextBlock, 0);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t// The browsers like to auto-insert breaks into empty paragraphs - remove them.\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar elements = ice.dom.getElementsBetween(range.startContainer, range.endContainer);\n\t\t\t\t\t\t\t\t\t\t\t\t\tfor (var i = 0; i < elements.length; i++) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(elements[i]);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar startContainer = range.startContainer;\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar endContainer = range.endContainer;\n\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(ice.dom.find(startContainer, 'br'));\n\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(ice.dom.find(endContainer, 'br'));\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn ice.dom.mergeBlockWithSibling(range, ice.dom.getBlockParent(range.endContainer, this.element) || parentBlock);\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t// If the next block is empty, remove the next block.\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (nextBlockIsEmpty) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(nextBlock);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Place the caret at the start of the next block.\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(nextBlock, 0);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tvar entireTextNode = range.endContainer;\n\t\t\t\t\t\t\t\t\t\t\tvar deletedCharacter = entireTextNode.splitText(range.endOffset);\n\t\t\t\t\t\t\t\t\t\t\tvar remainingTextNode = deletedCharacter.splitText(1);\n\n\t\t\t\t\t\t\t\t\t\t\treturn this._addNodeTracking(deletedCharacter, range, false);\n\n\t\t\t},\n\n\t\t\t// Backspace\n\t\t\t_deleteLeft: function (range) {\n\n\t\t\t\tvar parentBlock = ice.dom.isBlockElement(range.startContainer) && range.startContainer || ice.dom.getBlockParent(range.startContainer, this.element) || null,\n\t\t\t\t\tisEmptyBlock = parentBlock ? ice.dom.hasNoTextOrStubContent(parentBlock) : false,\n\t\t\t\t\t\tprevBlock = parentBlock && ice.dom.getPrevContentNode(parentBlock, this.element), // || ice.dom.getBlockParent(parentBlock, this.element) || null,\n\t\t\t\t\t\t\tprevBlockIsEmpty = prevBlock ? ice.dom.hasNoTextOrStubContent(prevBlock) : false,\n\t\t\t\t\t\t\t\tinitialContainer = range.startContainer,\n\t\t\t\t\t\t\t\t\tinitialOffset = range.startOffset,\n\t\t\t\t\t\t\t\t\t\tcommonAncestor = range.commonAncestorContainer,\n\t\t\t\t\t\t\t\t\t\t\tlastSelectable, prevContainer;\n\t\t\t\t\t\t\t\t\t\t\t// Handle cases of the caret is at the start of a container or outside a text node\n\t\t\t\t\t\t\t\t\t\t\tif (initialOffset === 0 || commonAncestor.nodeType !== ice.dom.TEXT_NODE) {\n\t\t\t\t\t\t\t\t\t\t\t\t// If placed at the end of a container that cannot contain text, such as an ul element, place the caret at the end of the last item.\n\t\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.isBlockElement(commonAncestor) && (!ice.dom.canContainTextElement(commonAncestor))) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (initialOffset === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar firstItem = commonAncestor.firstElementChild;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (firstItem) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(firstItem, 0);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn this._deleteLeft(range);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar lastItem = commonAncestor.lastElementChild;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (lastItem) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlastSelectable = range.getLastSelectableChild(lastItem);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (lastSelectable) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(lastSelectable, lastSelectable.data.length);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn this._deleteLeft(range);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tif (initialOffset === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tprevContainer = ice.dom.getPrevContentNode(initialContainer, this.element);\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar newOffset = initialOffset;\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar style;\n\t\t\t\t\t\t\t\t\t\t\t\t\t//      while(newOffset > 0){\n\t\t\t\t\t\t\t\t\t\t\t\t\t//        prevContainer = commonAncestor.childNodes[--newOffset];\n\t\t\t\t\t\t\t\t\t\t\t\t\t//        if(!ice.dom.hasClass(prevContainer, \"del\")) break;\n\t\t\t\t\t\t\t\t\t\t\t\t\t//        prevContainer = null;\n\t\t\t\t\t\t\t\t\t\t\t\t\t//      }\n\t\t\t\t\t\t\t\t\t\t\t\t\tprevContainer = commonAncestor.childNodes[initialOffset-1];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the previous container is outside of ICE then do nothing.\n\t\t\t\t\t\t\t\t\t\t\t\tif (!prevContainer) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t// Firefox finds an ice node wrapped around an image instead of the image itself sometimes, so we make sure to look at the image instead.\n\t\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.is(prevContainer,  '.' + this._getIceNodeClass('insertType') + ', .' + this._getIceNodeClass('deleteType')) && prevContainer.childNodes.length > 0 && prevContainer.lastChild) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tprevContainer = prevContainer.lastChild;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the previous container is a text node, look at the parent node instead.\n\t\t\t\t\t\t\t\t\t\t\t\tif (prevContainer.nodeType === ice.dom.TEXT_NODE) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tprevContainer = prevContainer.parentNode;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (prevContainer.nodeName === 'IMG') {\n\t\t\t\t\t\t\t\t\t\t\t\t\tprevContainer.parentNode.removeChild(prevContainer);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the previous container is non-editable, enclose it with a delete ice node and add an empty text node before it to position the caret.\n\t\t\t\t\t\t\t\t\t\t\t\tif (!prevContainer.isContentEditable) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar returnValue = this._addNodeTracking(prevContainer, false, true);\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar emptySpaceNode = document.createTextNode('');\n\t\t\t\t\t\t\t\t\t\t\t\t\tprevContainer.parentNode.insertBefore(emptySpaceNode, prevContainer);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.selectNode(emptySpaceNode);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn returnValue;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (this._handleVoidEl(prevContainer, range)) return true;\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the caret was placed directly after a stub element, enclose the element with a delete ice node.\n\t\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.isStubElement(prevContainer) && ice.dom.isChildOf(prevContainer, parentBlock) || !prevContainer.isContentEditable) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn this._addNodeTracking(prevContainer, range, true);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the previous container is a stub element between blocks\n\t\t\t\t\t\t\t\t\t\t\t\t// then just delete and leave the range/cursor in place.\n\t\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.isStubElement(prevContainer)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(prevContainer);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (prevContainer !== parentBlock && !ice.dom.isChildOf(prevContainer, parentBlock)) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (!ice.dom.canContainTextElement(prevContainer)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tprevContainer = prevContainer.lastElementChild;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Before putting the caret into the last selectable child, lets see if the last element is a stub element. If it is, we need to put the caret there manually.\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (prevContainer.lastChild && prevContainer.lastChild.nodeType !== ice.dom.TEXT_NODE && ice.dom.isStubElement(prevContainer.lastChild) && prevContainer.lastChild.tagName !== 'BR') {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStartAfter(prevContainer.lastChild);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Find the last selectable part of the prevContainer. If it exists, put the caret there.\n\t\t\t\t\t\t\t\t\t\t\t\t\tlastSelectable = range.getLastSelectableChild(prevContainer);\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (lastSelectable && !ice.dom.isOnBlockBoundary(range.startContainer, lastSelectable, this.element)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.selectNodeContents(lastSelectable);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Firefox: If an image is at the start of the paragraph and the user has just deleted the image using backspace, an empty text node is created in the delete node before\n\t\t\t\t\t\t\t\t\t\t\t// the image, but the caret is placed with the image. We move the caret to the empty text node and execute deleteFromLeft again.\n\t\t\t\t\t\t\t\t\t\t\tif (initialOffset === 1 && !ice.dom.isBlockElement(commonAncestor) && range.startContainer.childNodes.length > 1 && range.startContainer.childNodes[0].nodeType === ice.dom.TEXT_NODE && range.startContainer.childNodes[0].data.length === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(range.startContainer, 0);\n\t\t\t\t\t\t\t\t\t\t\t\treturn this._deleteLeft(range);\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Move range to position the cursor on the inside of any adjacent container that it is going\n\t\t\t\t\t\t\t\t\t\t\t// to potentially delete into or before a stub element.  E.G.: <em>text</em>| test  ->  <em>text|</em> test or\n\t\t\t\t\t\t\t\t\t\t\t// text1 <img>| text2 -> text1 |<img> text2\n\t\t\t\t\t\t\t\t\t\t\trange.moveStart(ice.dom.CHARACTER_UNIT, -1);\n\t\t\t\t\t\t\t\t\t\t\trange.moveStart(ice.dom.CHARACTER_UNIT, 1);\n\n\t\t\t\t\t\t\t\t\t\t\t// If we are deleting into a no tracking containiner, then remove the content\n\t\t\t\t\t\t\t\t\t\t\tif (this._getNoTrackElement(range.startContainer.parentElement)) {\n\t\t\t\t\t\t\t\t\t\t\t\trange.deleteContents();\n\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Handles cases in which the caret is at the start of the block.\n\t\t\t\t\t\t\t\t\t\t\tif (ice.dom.isOnBlockBoundary(range.startContainer, range.endContainer, this.element)) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the previous block is empty, remove the previous block.\n\t\t\t\t\t\t\t\t\t\t\t\tif (prevBlockIsEmpty) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(prevBlock);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Merge blocks: If mergeBlocks is enabled, merge the previous and current block.\n\t\t\t\t\t\t\t\t\t\t\t\tif (this.mergeBlocks && ice.dom.is(ice.dom.getBlockParent(prevContainer, this.element), this.blockEl)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Since the range is moved by character, it may have passed through empty blocks.\n\t\t\t\t\t\t\t\t\t\t\t\t\t// <p>text {RANGE.START}</p><p></p><p>{RANGE.END} text</p>\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (prevBlock && prevBlock !== ice.dom.getBlockParent(range.startContainer, this.element)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(prevBlock, prevBlock.childNodes.length);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t// The browsers like to auto-insert breaks into empty paragraphs - remove them.\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar elements = ice.dom.getElementsBetween(range.startContainer, range.endContainer)\n\t\t\t\t\t\t\t\t\t\t\t\t\tfor (var i = 0; i < elements.length; i++) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(elements[i]);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar startContainer = range.startContainer;\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar endContainer = range.endContainer;\n\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(ice.dom.find(startContainer, 'br'));\n\t\t\t\t\t\t\t\t\t\t\t\t\tice.dom.remove(ice.dom.find(endContainer, 'br'));\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn ice.dom.mergeBlockWithSibling(range, ice.dom.getBlockParent(range.endContainer, this.element) || parentBlock);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// If the previous Block ends with a stub element, set the caret behind it.\n\t\t\t\t\t\t\t\t\t\t\t\tif (prevBlock && prevBlock.lastChild && ice.dom.isStubElement(prevBlock.lastChild)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStartAfter(prevBlock.lastChild);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Place the caret at the end of the previous block.\n\t\t\t\t\t\t\t\t\t\t\t\tlastSelectable = range.getLastSelectableChild(prevBlock);\n\t\t\t\t\t\t\t\t\t\t\t\tif (lastSelectable) {\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(lastSelectable, lastSelectable.data.length);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t} else if (prevBlock) {\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.setStart(prevBlock, prevBlock.childNodes.length);\n\t\t\t\t\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tvar entireTextNode = range.startContainer;\n\t\t\t\t\t\t\t\t\t\t\tvar deletedCharacter = entireTextNode.splitText(range.startOffset - 1);\n\t\t\t\t\t\t\t\t\t\t\tvar remainingTextNode = deletedCharacter.splitText(1);\n\n\t\t\t\t\t\t\t\t\t\t\treturn this._addNodeTracking(deletedCharacter, range, true);\n\n\t\t\t},\n\n\t\t\t// Marks text and other nodes for deletion\n\t\t\t_addNodeTracking: function (contentNode, range, moveLeft) {\n\n\t\t\t\tvar contentAddNode = this.getIceNode(contentNode, 'insertType');\n\n\t\t\t\tif (contentAddNode && this._currentUserIceNode(contentAddNode)) {\n\t\t\t\t\tif (range && moveLeft) {\n\t\t\t\t\t\trange.selectNode(contentNode);\n\t\t\t\t\t}\n\t\t\t\t\tcontentNode.parentNode.removeChild(contentNode);\n\t\t\t\t\tvar cleanNode = ice.dom.cloneNode(contentAddNode);\n\t\t\t\t\tice.dom.remove(ice.dom.find(cleanNode, '.iceBookmark'));\n\t\t\t\t\t// Remove a potential empty tracking container\n\t\t\t\t\tif (contentAddNode !== null && (ice.dom.hasNoTextOrStubContent(cleanNode[0]))) {\n\t\t\t\t\t\tvar newstart = this.env.document.createTextNode('');\n\t\t\t\t\t\tice.dom.insertBefore(contentAddNode, newstart);\n\t\t\t\t\t\tif (range) {\n\t\t\t\t\t\t\trange.setStart(newstart, 0);\n\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tice.dom.replaceWith(contentAddNode, ice.dom.contents(contentAddNode));\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\t} else if (range && this.getIceNode(contentNode, 'deleteType')) {\n\t\t\t\t\t// It if the contentNode a text node, unite it with text nodes before and after it.\n\t\t\t\t\tcontentNode.normalize();\n\n\t\t\t\t\tvar found = false;\n\t\t\t\t\tif (moveLeft) {\n\t\t\t\t\t\t// Move to the left until there is valid sibling.\n\t\t\t\t\t\tvar previousSibling = ice.dom.getPrevContentNode(contentNode, this.element);\n\t\t\t\t\t\twhile (!found) {\n\t\t\t\t\t\t\tctNode = this.getIceNode(previousSibling, 'deleteType');\n\t\t\t\t\t\t\tif (!ctNode) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tpreviousSibling = ice.dom.getPrevContentNode(previousSibling, this.element);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (previousSibling) {\n\t\t\t\t\t\t\tvar lastSelectable = range.getLastSelectableChild(previousSibling);\n\t\t\t\t\t\t\tif (lastSelectable) {\n\t\t\t\t\t\t\t\tpreviousSibling = lastSelectable;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trange.setStart(previousSibling, ice.dom.getNodeCharacterLength(previousSibling));\n\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Move the range to the right until there is valid sibling.\n\n\t\t\t\t\t\tvar nextSibling = ice.dom.getNextContentNode(contentNode, this.element);\n\t\t\t\t\t\twhile (!found) {\n\t\t\t\t\t\t\tctNode = this.getIceNode(nextSibling, 'deleteType');\n\t\t\t\t\t\t\tif (!ctNode) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnextSibling = ice.dom.getNextContentNode(nextSibling, this.element);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (nextSibling) {\n\t\t\t\t\t\t\trange.selectNodeContents(nextSibling);\n\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\t// Webkit likes to insert empty text nodes next to elements. We remove them here.\n\t\t\t\tif (contentNode.previousSibling && contentNode.previousSibling.nodeType === ice.dom.TEXT_NODE && contentNode.previousSibling.length === 0) {\n\t\t\t\t\tcontentNode.parentNode.removeChild(contentNode.previousSibling);\n\t\t\t\t}\n\t\t\t\tif (contentNode.nextSibling && contentNode.nextSibling.nodeType === ice.dom.TEXT_NODE && contentNode.nextSibling.length === 0) {\n\t\t\t\t\tcontentNode.parentNode.removeChild(contentNode.nextSibling);\n\t\t\t\t}\n\t\t\t\tvar prevDelNode = this.getIceNode(contentNode.previousSibling, 'deleteType');\n\t\t\t\tvar nextDelNode = this.getIceNode(contentNode.nextSibling, 'deleteType');\n\t\t\t\tvar ctNode;\n\n\t\t\t\tif (prevDelNode && this._currentUserIceNode(prevDelNode)) {\n\t\t\t\t\tctNode = prevDelNode;\n\t\t\t\t\tctNode.appendChild(contentNode);\n\t\t\t\t\tif (nextDelNode && this._currentUserIceNode(nextDelNode)) {\n\t\t\t\t\t\tvar nextDelContents = ice.dom.extractContent(nextDelNode);\n\t\t\t\t\t\tice.dom.append(ctNode, nextDelContents);\n\t\t\t\t\t\tnextDelNode.parentNode.removeChild(nextDelNode);\n\t\t\t\t\t}\n\t\t\t\t} else if (nextDelNode && this._currentUserIceNode(nextDelNode)) {\n\t\t\t\t\tctNode = nextDelNode;\n\t\t\t\t\tctNode.insertBefore(contentNode, ctNode.firstChild);\n\t\t\t\t} else {\n\t\t\t\t\tctNode = this.createIceNode('deleteType');\n\t\t\t\t\tcontentNode.parentNode.insertBefore(ctNode, contentNode);\n\t\t\t\t\tctNode.appendChild(contentNode);\n\t\t\t\t}\n\n\t\t\t\tif (range) {\n\t\t\t\t\tif (ice.dom.isStubElement(contentNode)) {\n\t\t\t\t\t\trange.selectNode(contentNode);\n\t\t\t\t\t} else {\n\t\t\t\t\t\trange.selectNodeContents(contentNode);\n\t\t\t\t\t}\n\t\t\t\t\tif (moveLeft) {\n\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t}\n\t\t\t\t\tcontentNode.normalize();\n\t\t\t\t}\n\t\t\t\treturn true;\n\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Handles arrow, delete key events, and others.\n\t\t\t *\n\t\t\t * @param {event} e The event object.\n\t\t\t * return {void|boolean} Returns false if default event needs to be blocked.\n\t\t\t */\n\t\t\t_handleAncillaryKey: function (e) {\n\t\t\t\tvar key = e.keyCode ? e.keyCode : e.which;\n\t\t\t\tvar browser = ice.dom.browser();\n\t\t\t\tvar preventDefault = true;\n\t\t\t\tvar shiftKey = e.shiftKey;\n\t\t\t\tvar self = this;\n\t\t\t\tvar range = self.getCurrentRange();\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase ice.dom.DOM_VK_DELETE:\n\t\t\t\t\t\tpreventDefault = this.deleteContents();\n\t\t\t\t\t\tthis.pluginsManager.fireKeyPressed(e);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 46:\n\t\t\t\t\t\t// Key 46 is the DELETE key.\n\t\t\t\t\t\tpreventDefault = this.deleteContents(true);\n\t\t\t\t\t\tthis.pluginsManager.fireKeyPressed(e);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t/************************************************************************************/\n\t\t\t\t\t\t/** BEGIN: Handling of caret movements inside hidden .ins/.del elements on Firefox **/\n\t\t\t\t\t\t/**  *Fix for carets getting stuck in .del elements when track changes are hidden  **/\n\t\t\t\t\tcase ice.dom.DOM_VK_DOWN:\n\t\t\t\t\tcase ice.dom.DOM_VK_UP:\n\t\t\t\t\tcase ice.dom.DOM_VK_LEFT:\n\t\t\t\t\t\tthis.pluginsManager.fireCaretPositioned();\n\t\t\t\t\t\tif (browser[\"type\"] === \"mozilla\") {\n\t\t\t\t\t\t\tif (!this.visible(range.startContainer)) {\n\t\t\t\t\t\t\t\t// if Previous sibling exists in the paragraph, jump to the previous sibling\n\t\t\t\t\t\t\t\tif(range.startContainer.parentNode.previousSibling) {\n\t\t\t\t\t\t\t\t\t// When moving left and moving into a hidden element, skip it and go to the previousSibling\n\t\t\t\t\t\t\t\t\trange.setEnd(range.startContainer.parentNode.previousSibling, 0);\n\t\t\t\t\t\t\t\t\trange.moveEnd(ice.dom.CHARACTER_UNIT, ice.dom.getNodeCharacterLength(range.endContainer));\n\t\t\t\t\t\t\t\t\trange.collapse(false);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// if Previous sibling doesn't exist, get out of the hidden zone by moving to the right\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\trange.setEnd(range.startContainer.parentNode.nextSibling, 0);\n\t\t\t\t\t\t\t\t\trange.collapse(false);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpreventDefault = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ice.dom.DOM_VK_RIGHT:\n\t\t\t\t\t\tthis.pluginsManager.fireCaretPositioned();\n\t\t\t\t\t\tif (browser[\"type\"] === \"mozilla\") {\n\t\t\t\t\t\t\tif (!this.visible(range.startContainer)) {\n\t\t\t\t\t\t\t\tif(range.startContainer.parentNode.nextSibling) {\n\t\t\t\t\t\t\t\t\t// When moving right and moving into a hidden element, skip it and go to the nextSibling\n\t\t\t\t\t\t\t\t\trange.setStart(range.startContainer.parentNode.nextSibling,0);\n\t\t\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpreventDefault = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t/** END: Handling of caret movements inside hidden .ins/.del elements ***************/\n\t\t\t\t\t\t/************************************************************************************/\n\n\t\t\t\t\tcase 32:\n\t\t\t\t\t\tpreventDefault = true;\n\t\t\t\t\t\tvar range = this.getCurrentRange();\n\t\t\t\t\t\tthis._moveRangeToValidTrackingPos(range, range.startContainer);\n\t\t\t\t\t\tthis.insert('\\u00A0' , range);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// Ignore key.\n\t\t\t\t\t\tpreventDefault = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t} //end switch\n\n\t\t\t\tif (preventDefault === true) {\n\t\t\t\t\tice.dom.preventDefault(e);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\tkeyDown: function (e) {\n\t\t\t\tif (!this.pluginsManager.fireKeyDown(e)) {\n\t\t\t\t\tice.dom.preventDefault(e);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tvar preventDefault = false;\n\n\t\t\t\tif (this._handleSpecialKey(e) === false) {\n\t\t\t\t\tif (ice.dom.isBrowser('msie') !== true) {\n\t\t\t\t\t\tthis._preventKeyPress = true;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t} else if ((e.ctrlKey === true || e.metaKey === true) && (ice.dom.isBrowser('msie') === true || ice.dom.isBrowser('chrome') === true)) {\n\t\t\t\t\t// IE does not fire keyPress event if ctrl is also pressed.\n\t\t\t\t\t// E.g. CTRL + B (Bold) will not fire keyPress so this.plugins\n\t\t\t\t\t// needs to be notified here for IE.\n\t\t\t\t\tif (!this.pluginsManager.fireKeyPressed(e)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch (e.keyCode) {\n\t\t\t\t\tcase 27:\n\t\t\t\t\t\t// ESC\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tpreventDefault = !(this._handleAncillaryKey(e));\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (preventDefault) {\n\t\t\t\t\tice.dom.preventDefault(e);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\tkeyPress: function (e) {\n\t\t\t\tif (this._preventKeyPress === true) {\n\t\t\t\t\tthis._preventKeyPress = false;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!this.pluginsManager.fireKeyPress(e)) return false;\n\n\t\t\t\tvar c = null;\n\t\t\t\tif (e.which == null) {\n\t\t\t\t\t// IE.\n\t\t\t\t\tc = String.fromCharCode(e.keyCode);\n\t\t\t\t} else if (e.which > 0) {\n\t\t\t\t\tc = String.fromCharCode(e.which);\n\t\t\t\t}\n\n\t\t\t\t// Inside a br - most likely in a placeholder of a new block - delete before handling.\n\t\t\t\tvar range = this.getCurrentRange();\n\t\t\t\tvar br = ice.dom.parents(range.startContainer, 'br')[0] || null;\n\t\t\t\tif (br) {\n\t\t\t\t\trange.moveToNextEl(br);\n\t\t\t\t\tbr.parentNode.removeChild(br);\n\t\t\t\t}\n\n\t\t\t\t// Ice will ignore the keyPress event if CMD or CTRL key is also pressed\n\t\t\t\tif (c !== null && e.ctrlKey !== true && e.metaKey !== true) {\n\t\t\t\t\tvar key = e.keyCode ? e.keyCode : e.which;\n\t\t\t\t\tswitch (key) {\n\t\t\t\t\t\tcase ice.dom.DOM_VK_DELETE:\n\t\t\t\t\t\t\t// Handle delete key for Firefox.\n\t\t\t\t\t\t\treturn this._handleAncillaryKey(e);\n\t\t\t\t\t\tcase ice.dom.DOM_VK_ENTER:\n\t\t\t\t\t\t\treturn this._handleEnter();\n\t\t\t\t\t\tcase 32:\n\t\t\t\t\t\t\treturn this._handleAncillaryKey(e);\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t// If we are in a deletion, move the range to the end/outside.\n\t\t\t\t\t\t\tthis._moveRangeToValidTrackingPos(range, range.startContainer);\n\t\t\t\t\t\t\treturn this.insert(e.key);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn this._handleAncillaryKey(e);\n\t\t\t},\n\n\t\t\t_handleEnter: function () {\n\t\t\t\tvar range = this.getCurrentRange();\n\t\t\t\tif (!range.collapsed) this.deleteContents();\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t_handleSpecialKey: function (e) {\n\t\t\t\tvar keyCode = e.which;\n\t\t\t\tif (keyCode === null) {\n\t\t\t\t\t// IE.\n\t\t\t\t\tkeyCode = e.keyCode;\n\t\t\t\t}\n\n\t\t\t\tvar preventDefault = false;\n\t\t\t\tswitch (keyCode) {\n\t\t\t\t\tcase 65:\n\t\t\t\t\t\t// Check for CTRL/CMD + A (select all).\n\t\t\t\t\t\tif (e.ctrlKey === true || e.metaKey === true) {\n\t\t\t\t\t\t\tpreventDefault = true;\n\t\t\t\t\t\t\tvar range = this.getCurrentRange();\n\n\t\t\t\t\t\t\tif (ice.dom.isBrowser('msie') === true) {\n\t\t\t\t\t\t\t\tvar selStart = this.env.document.createTextNode('');\n\t\t\t\t\t\t\t\tvar selEnd = this.env.document.createTextNode('');\n\n\t\t\t\t\t\t\t\tif (this.element.firstChild) {\n\t\t\t\t\t\t\t\t\tice.dom.insertBefore(this.element.firstChild, selStart);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthis.element.appendChild(selStart);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tthis.element.appendChild(selEnd);\n\n\t\t\t\t\t\t\t\trange.setStart(selStart, 0);\n\t\t\t\t\t\t\t\trange.setEnd(selEnd, 0);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trange.setStart(range.getFirstSelectableChild(this.element), 0);\n\t\t\t\t\t\t\t\tvar lastSelectable = range.getLastSelectableChild(this.element);\n\t\t\t\t\t\t\t\trange.setEnd(lastSelectable, lastSelectable.length);\n\t\t\t\t\t\t\t} //end if\n\n\t\t\t\t\t\t\tthis.selection.addRange(range);\n\t\t\t\t\t\t} //end if\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// Not a special key.\n\t\t\t\t\t\tbreak;\n\t\t\t\t} //end switch\n\n\t\t\t\tif (preventDefault === true) {\n\t\t\t\t\tice.dom.preventDefault(e);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\tmouseUp: function (e, target) {\n\t\t\t\tif (!this.pluginsManager.fireClicked(e)) return false;\n\t\t\t\tthis.pluginsManager.fireSelectionChanged(this.getCurrentRange());\n\t\t\t},\n\n\t\t\tmouseDown: function (e, target) {\n\t\t\t\tif (!this.pluginsManager.fireMouseDown(e)) return false;\n\t\t\t\tthis.pluginsManager.fireCaretUpdated();\n\t\t\t}\n\t\t};\n\n\t\texports.ice.InlineChangeEditor = InlineChangeEditor;\n\n}).call(this);\n\n}.call(window));\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = window.ice;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/ice.js\n// module id = 2\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function() {\n\n  var exports = this, Bookmark;\n\n  Bookmark = function(env, range, keepOldBookmarks) {\n\n    this.env = env;\n    this.element = env.element;\n    this.selection = this.env.selection;\n\n    // Remove all bookmarks?\n    if (!keepOldBookmarks) {\n      this.removeBookmarks(this.element);\n    }\n\n    var currRange = range || this.selection.getRangeAt(0);\n    range = currRange.cloneRange();\n    var startContainer = range.startContainer;\n    var endContainer = range.endContainer;\n    var startOffset  = range.startOffset;\n    var endOffset = range.endOffset;\n    var tmp;\n\n    // Collapse to the end of range.\n    range.collapse(false);\n\n    var endBookmark  = this.env.document.createElement('span');\n    endBookmark.style.display = 'none';\n    ice.dom.setHtml(endBookmark, '&nbsp;');\n    ice.dom.addClass(endBookmark, 'iceBookmark iceBookmark_end');\n    endBookmark.setAttribute('iceBookmark', 'end');\n    range.insertNode(endBookmark);\n    if(!ice.dom.isChildOf(endBookmark, this.element)) {\n      this.element.appendChild(endBookmark);\n    }\n\n    // Move the range to where it was before.\n    range.setStart(startContainer, startOffset);\n    range.collapse(true);\n\n    // Create the start bookmark.\n    var startBookmark = this.env.document.createElement('span');\n    startBookmark.style.display = 'none';\n    ice.dom.addClass(startBookmark, 'iceBookmark iceBookmark_start');\n    ice.dom.setHtml(startBookmark, '&nbsp;');\n    startBookmark.setAttribute('iceBookmark', 'start');\n    try {\n      range.insertNode(startBookmark);\n\n      // Make sure start and end are in correct position.\n      if (startBookmark.previousSibling === endBookmark) {\n        // Reverse..\n        tmp  = startBookmark;\n        startBookmark = endBookmark;\n        endBookmark = tmp;\n      }\n    } catch (e) {\n      // NS_ERROR_UNEXPECTED: I believe this is a Firefox bug.\n      // It seems like if the range is collapsed and the text node is empty\n      // (i.e. length = 0) then Firefox tries to split the node for no reason and fails...\n      ice.dom.insertBefore(endBookmark, startBookmark);\n    }\n\n    if (ice.dom.isChildOf(startBookmark, this.element) === false) {\n      if (this.element.firstChild) {\n        ice.dom.insertBefore(this.element.firstChild, startBookmark);\n      } else {\n        // Should not happen...\n        this.element.appendChild(startBookmark);\n      }\n    }\n\n    if (!endBookmark.previousSibling) {\n      tmp = this.env.document.createTextNode('');\n      ice.dom.insertBefore(endBookmark, tmp);\n    }\n\n    // The original range object must be changed.\n    if (!startBookmark.nextSibling) {\n      tmp = this.env.document.createTextNode('');\n      ice.dom.insertAfter(startBookmark, tmp);\n    }\n\n    currRange.setStart(startBookmark.nextSibling, 0);\n    currRange.setEnd(endBookmark.previousSibling, (endBookmark.previousSibling.length || 0));\n\n    this.start = startBookmark;\n    this.end = endBookmark;\n  };\n\n  Bookmark.prototype = {\n\n    selectBookmark: function() {\n      var range = this.selection.getRangeAt(0);\n      var startPos = null;\n      var endPos = null;\n      var startOffset = 0;\n      var endOffset = null;\n      if (this.start.nextSibling === this.end || ice.dom.getElementsBetween(this.start, this.end).length === 0) {\n        // Bookmark is collapsed.\n        if (this.end.nextSibling) {\n          startPos = ice.dom.getFirstChild(this.end.nextSibling);\n        } else if (this.start.previousSibling) {\n          startPos = ice.dom.getFirstChild(this.start.previousSibling);\n          if (startPos.nodeType === ice.dom.TEXT_NODE) {\n            startOffset = startPos.length;\n          }\n        } else {\n          // Create a text node in parent.\n          this.end.parentNode.appendChild(this.env.document.createTextNode(''));\n          startPos = ice.dom.getFirstChild(this.end.nextSibling);\n        }\n      } else {\n        if (this.start.nextSibling) {\n          startPos = ice.dom.getFirstChild(this.start.nextSibling);\n        } else {\n          if (!this.start.previousSibling) {\n            var tmp = this.env.document.createTextNode('');\n            ice.dom.insertBefore(this.start, tmp);\n          }\n\n          startPos = ice.dom.getLastChild(this.start.previousSibling);\n          startOffset = startPos.length;\n        }\n\n        if (this.end.previousSibling) {\n          endPos = ice.dom.getLastChild(this.end.previousSibling);\n        } else {\n          endPos = ice.dom.getFirstChild(this.end.nextSibling || this.end);\n          endOffset = 0;\n        }\n      }\n\n      ice.dom.remove([this.start, this.end]);\n\n      if (endPos === null) {\n        range.setEnd(startPos, startOffset);\n        range.collapse(false);\n      } else {\n        range.setStart(startPos, startOffset);\n        if (endOffset === null) {\n          endOffset = (endPos.length || 0);\n        }\n        range.setEnd(endPos, endOffset);\n      }\n\n      try {\n        this.selection.addRange(range);\n      } catch (e) {\n        // IE may throw exception for hidden elements..\n      }\n    },\n\n    getBookmark: function(parent, type) {\n      var elem = ice.dom.getClass('iceBookmark_' + type, parent)[0];\n      return elem;\n    },\n\n    removeBookmarks: function(elem) {\n      ice.dom.remove(ice.dom.getClass('iceBookmark', elem, 'span'));\n    }\n  };\n\n  exports.Bookmark = Bookmark;\n\n}).call(this.ice);\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/bookmark.js\n// module id = 3\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function () {\n\n  var exports = this,\n\t\t_browser = null,\n    dom = {};\n\n  dom.DOM_VK_DELETE = 8;\n  dom.DOM_VK_LEFT = 37;\n  dom.DOM_VK_UP = 38;\n  dom.DOM_VK_RIGHT = 39;\n  dom.DOM_VK_DOWN = 40;\n  dom.DOM_VK_ENTER = 13;\n  dom.ELEMENT_NODE = 1;\n  dom.ATTRIBUTE_NODE = 2;\n  dom.TEXT_NODE = 3;\n  dom.CDATA_SECTION_NODE = 4;\n  dom.ENTITY_REFERENCE_NODE = 5;\n  dom.ENTITY_NODE = 6;\n  dom.PROCESSING_INSTRUCTION_NODE = 7;\n  dom.COMMENT_NODE = 8;\n  dom.DOCUMENT_NODE = 9;\n  dom.DOCUMENT_TYPE_NODE = 10;\n  dom.DOCUMENT_FRAGMENT_NODE = 11;\n  dom.NOTATION_NODE = 12;\n  dom.CHARACTER_UNIT = 'character';\n  dom.WORD_UNIT = 'word';\n  dom.BREAK_ELEMENT = 'br';\n  dom.CONTENT_STUB_ELEMENTS = ['img', 'hr', 'br', 'iframe', 'param', 'link', 'meta', 'input', 'frame', 'col', 'base', 'area'];\n  dom.BLOCK_ELEMENTS = ['p', 'div', 'pre', 'ul', 'ol', 'li', 'table', 'tbody', 'td', 'th', 'fieldset', 'form', 'blockquote', 'dl', 'dt', 'dd', 'dir', 'center', 'address', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n  dom.TEXT_CONTAINER_ELEMENTS = ['p', 'div', 'pre', 'li', 'td', 'th', 'blockquote', 'dt', 'dd', 'center', 'address', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\n  dom.STUB_ELEMENTS = dom.CONTENT_STUB_ELEMENTS.slice();\n  dom.STUB_ELEMENTS.push(dom.BREAK_ELEMENT);\n\n  dom.getKeyChar = function (e) {\n    return String.fromCharCode(e.which);\n  };\n  dom.getClass = function (className, startElement, tagName) {\n    if (!startElement) {\n      startElement = document.body;\n    }\n    className = '.' + className.split(' ').join('.');\n    if (tagName) {\n      className = tagName + className;\n    }\n    return jQuery.makeArray(jQuery(startElement).find(className));\n  };\n  dom.getId = function (id, startElement) {\n    if (!startElement) {\n      startElement = document;\n    }\n    return startElement.getElementById(id);\n  };\n  dom.getTag = function (tagName, startElement) {\n    if (!startElement) {\n      startElement = document;\n    }\n    return jQuery.makeArray(jQuery(startElement).find(tagName));\n  };\n  dom.getElementWidth = function (element) {\n    return element.offsetWidth;\n  };\n  dom.getElementHeight = function (element) {\n    return element.offsetHeight;\n  };\n  dom.getElementDimensions = function (element) {\n    var result = {\n      'width': dom.getElementWidth(element),\n      'height': dom.getElementHeight(element)\n    };\n    return result;\n  };\n  dom.trim = function (string) {\n    return jQuery.trim(string);\n  };\n  dom.empty = function (element) {\n    if (element) {\n      return jQuery(element).empty();\n    }\n  };\n  dom.remove = function (element) {\n    if (element) {\n      return jQuery(element).remove();\n    }\n  };\n  dom.prepend = function (parent, elem) {\n    jQuery(parent).prepend(elem);\n  };\n  dom.append = function (parent, elem) {\n    jQuery(parent).append(elem);\n  };\n  dom.insertBefore = function (before, elem) {\n    jQuery(before).before(elem);\n  };\n  dom.insertAfter = function (after, elem) {\n    jQuery(after).after(elem);\n  };\n  dom.getHtml = function (element) {\n    return jQuery(element).html();\n  };\n  dom.setHtml = function (element, content) {\n    if (element) {\n      jQuery(element).html(content);\n    }\n  };\n  // Remove whitespace/newlines between nested block elements\n  // that are supported by ice.\n  // For example the following element with innerHTML:\n  //   <div><p> para </p> <ul>  <li> hi </li>  </ul></div>\n  // Will be converted to the following:\n  //   <div><p> para </p><ul><li> hi </li></ul></div>\n  dom.removeWhitespace = function(element) {\n    jQuery(element).contents().filter(function() {\n      // Ice supports UL and OL, so recurse in these blocks to\n      // make sure that spaces don't exist between inner LI.\n      if (this.nodeType != ice.dom.TEXT_NODE && this.nodeName == 'UL' || this.nodeName == 'OL') {\n        dom.removeWhitespace(this);\n        return false;\n      } else if (this.nodeType != ice.dom.TEXT_NODE) {\n        return false;\n      } else {\n        return !/\\S/.test(this.nodeValue);\n      }\n    }).remove();\n  };\n  dom.contents = function (el) {\n    return jQuery.makeArray(jQuery(el).contents());\n  };\n  /**\n   * Returns the inner contents of `el` as a DocumentFragment.\n   */\n  dom.extractContent = function (el) {\n    var frag = document.createDocumentFragment(),\n      child;\n    while ((child = el.firstChild)) {\n      frag.appendChild(child);\n    }\n    return frag;\n  };\n\n  /**\n   * Returns this `node` or the first parent tracking node that matches the given `selector`.\n   */\n  dom.getNode = function (node, selector) {\n    return dom.is(node, selector) ? node : dom.parents(node, selector)[0] || null;\n  };\n\n  dom.getParents = function (elements, filter, stopEl) {\n    var res = jQuery(elements).parents(filter);\n    var ln = res.length;\n    var ar = [];\n    for (var i = 0; i < ln; i++) {\n      if (res[i] === stopEl) {\n        break;\n      }\n      ar.push(res[i]);\n    }\n    return ar;\n  };\n  dom.hasBlockChildren = function (parent) {\n    var c = parent.childNodes.length;\n    for (var i = 0; i < c; i++) {\n      if (parent.childNodes[i].nodeType === dom.ELEMENT_NODE) {\n        if (dom.isBlockElement(parent.childNodes[i]) === true) {\n          return true;\n        }\n      }\n    }\n    return false;\n  };\n  dom.removeTag = function (element, selector) {\n    jQuery(element).find(selector).replaceWith(function () {\n      return jQuery(this).contents();\n    });\n    return element;\n  };\n  dom.stripEnclosingTags = function (content, allowedTags) {\n    var c = jQuery(content);\n    c.find('*').not(allowedTags).replaceWith(function () {\n      var ret = jQuery();\n      var $this;\n      try{\n        $this = jQuery(this);\n        ret = $this.contents();\n      } catch(e){}\n\n      // Handling jQuery bug (which may be fixed in the official release later)\n      // http://bugs.jquery.com/ticket/13401\n      if(ret.length === 0){\n        $this.remove();\n      }\n      return ret;\n    });\n    return c[0];\n  };\n  dom.getSiblings = function (element, dir, elementNodesOnly, stopElem) {\n    if (elementNodesOnly === true) {\n      if (dir === 'prev') {\n        return jQuery(element).prevAll();\n      } else {\n        return jQuery(element).nextAll();\n      }\n    } else {\n      var elems = [];\n      if (dir === 'prev') {\n        while (element.previousSibling) {\n          element = element.previousSibling;\n          if (element === stopElem) {\n            break;\n          }\n          elems.push(element);\n        }\n      } else {\n        while (element.nextSibling) {\n          element = element.nextSibling;\n          if (element === stopElem) {\n            break;\n          }\n          elems.push(element);\n        }\n      }\n      return elems;\n    }\n  };\n  dom.getNodeTextContent = function (node) {\n    return jQuery(node).text();\n  };\n  dom.getNodeStubContent = function (node) {\n    return jQuery(node).find(dom.CONTENT_STUB_ELEMENTS.join(', '));\n  };\n  dom.hasNoTextOrStubContent = function (node) {\n    if (dom.getNodeTextContent(node).length > 0) return false;\n    if (jQuery(node).find(dom.CONTENT_STUB_ELEMENTS.join(', ')).length > 0) return false;\n    return true;\n  };\n  dom.getNodeCharacterLength = function (node) {\n    return dom.getNodeTextContent(node).length + jQuery(node).find(dom.STUB_ELEMENTS.join(', ')).length;\n  };\n  dom.setNodeTextContent = function (node, txt) {\n    return jQuery(node).text(txt);\n  };\n  dom.getTagName = function (node) {\n    return node.tagName && node.tagName.toLowerCase() || null;\n  };\n  dom.getIframeDocument = function (iframe) {\n    var doc = null;\n    if (iframe.contentDocument) {\n      doc = iframe.contentDocument;\n    } else if (iframe.contentWindow) {\n      doc = iframe.contentWindow.document;\n    } else if (iframe.document) {\n      doc = iframe.document;\n    }\n    return doc;\n  };\n  dom.isBlockElement = function (element) {\n    return dom.BLOCK_ELEMENTS.lastIndexOf(element.nodeName.toLowerCase()) != -1;\n  };\n  dom.isStubElement = function (element) {\n    return dom.STUB_ELEMENTS.lastIndexOf(element.nodeName.toLowerCase()) != -1;\n  };\n  dom.removeBRFromChild = function (node) {\n    if (node && node.hasChildNodes()) {\n      for(var z=0; z < node.childNodes.length ; z++) {\n        var child = node.childNodes[z];\n        if (child && (ice.dom.BREAK_ELEMENT == ice.dom.getTagName(child))) {\n          child.parentNode.removeChild(child);\n        }\n      }\n    }\n  };\n  dom.isChildOf = function (el, parent) {\n    try {\n      while (el && el.parentNode) {\n        if (el.parentNode === parent) {\n          return true;\n        }\n        el = el.parentNode;\n      }\n    } catch (e) {}\n    return false;\n  };\n  dom.isChildOfTagName = function (el, name) {\n    try {\n      while (el && el.parentNode) {\n        if (el.parentNode && el.parentNode.tagName && el.parentNode.tagName.toLowerCase() === name) {\n          return el.parentNode;\n        }\n        el = el.parentNode;\n      }\n    } catch (e) {}\n    return false;\n  };\n\n\n  dom.isChildOfTagNames = function (el, names) {\n    try {\n      while (el && el.parentNode) {\n        if (el.parentNode && el.parentNode.tagName) {\n          var tagName = el.parentNode.tagName.toLowerCase();\n          for (var i = 0; i < names.length; i++) {\n            if (tagName === names[i]) {\n              return el.parentNode;\n            }\n          }\n        }\n        el = el.parentNode;\n      }\n    } catch (e) {}\n    return null;\n  };\n\n  dom.isChildOfClassName = function (el, name) {\n    try {\n      while (el && el.parentNode) {\n        if (jQuery(el.parentNode).hasClass(name)) return el.parentNode;\n        el = el.parentNode;\n      }\n    } catch (e) {}\n    return null;\n  };\n  dom.cloneNode = function (elems, cloneEvents) {\n    if (cloneEvents === undefined) {\n      cloneEvents = true;\n    }\n    return jQuery(elems).clone(cloneEvents);\n  };\n\n  dom.bind = function (element, event, callback) {\n    return jQuery(element).bind(event, callback);\n  };\n\n  dom.unbind = function (element, event, callback) {\n    return jQuery(element).unbind(event, callback);\n  };\n\n  dom.attr = function (elements, key, val) {\n    if (val) return jQuery(elements).attr(key, val);\n    else return jQuery(elements).attr(key);\n  };\n  dom.replaceWith = function (node, replacement) {\n    return jQuery(node).replaceWith(replacement);\n  };\n  dom.removeAttr = function (elements, name) {\n    jQuery(elements).removeAttr(name);\n  };\n  dom.getElementsBetween = function (fromElem, toElem) {\n    var elements = [];\n    if (fromElem === toElem) {\n      return elements;\n    }\n    if (dom.isChildOf(toElem, fromElem) === true) {\n      var fElemLen = fromElem.childNodes.length;\n      for (var i = 0; i < fElemLen; i++) {\n        if (fromElem.childNodes[i] === toElem) {\n          break;\n        } else if (dom.isChildOf(toElem, fromElem.childNodes[i]) === true) {\n          return dom.arrayMerge(elements, dom.getElementsBetween(fromElem.childNodes[i], toElem));\n        } else {\n          elements.push(fromElem.childNodes[i]);\n        }\n      }\n      return elements;\n    }\n    var startEl = fromElem.nextSibling;\n    while (startEl) {\n      if (dom.isChildOf(toElem, startEl) === true) {\n        elements = dom.arrayMerge(elements, dom.getElementsBetween(startEl, toElem));\n        return elements;\n      } else if (startEl === toElem) {\n        return elements;\n      } else {\n        elements.push(startEl);\n        startEl = startEl.nextSibling;\n      }\n    }\n    var fromParents = dom.getParents(fromElem);\n    var toParents = dom.getParents(toElem);\n    var parentElems = dom.arrayDiff(fromParents, toParents, true);\n    var pElemLen = parentElems.length;\n    for (var j = 0; j < (pElemLen - 1); j++) {\n      elements = dom.arrayMerge(elements, dom.getSiblings(parentElems[j], 'next'));\n    }\n    var lastParent = parentElems[(parentElems.length - 1)];\n    elements = dom.arrayMerge(elements, dom.getElementsBetween(lastParent, toElem));\n    return elements;\n  };\n  dom.getCommonAncestor = function (a, b) {\n    var node = a;\n    while (node) {\n      if (dom.isChildOf(b, node) === true) {\n        return node;\n      }\n      node = node.parentNode;\n    }\n    return null;\n  };\n  dom.getNextNode = function (node, container) {\n    if (node) {\n      while (node.parentNode) {\n        if (node === container) {\n          return null;\n        }\n\n        if (node.nextSibling) {\n          // if next sibling is an empty text node, look further\n          if (node.nextSibling.nodeType === dom.TEXT_NODE && node.nextSibling.length === 0) {\n            node = node.nextSibling;\n            continue;\n          }\n\n          return dom.getFirstChild(node.nextSibling);\n        }\n        node = node.parentNode;\n      }\n    }\n    return null;\n  };\n  dom.getNextContentNode = function (node, container) {\n    if (node) {\n      while (node.parentNode) {\n        if (node === container) {\n          return null;\n        }\n\n        if (node.nextSibling && dom.canContainTextElement(dom.getBlockParent(node))) {\n          // if next sibling is an empty text node, look further\n          if (node.nextSibling.nodeType === dom.TEXT_NODE && node.nextSibling.length === 0) {\n            node = node.nextSibling;\n            continue;\n          }\n\n          return node.nextSibling;\n        } else if (node.nextElementSibling) {\n          return node.nextElementSibling;\n        }\n\n        node = node.parentNode;\n      }\n    }\n    return null;\n  };\n\n\n  dom.getPrevNode = function (node, container) {\n    if (node) {\n      while (node.parentNode) {\n        if (node === container) {\n          return null;\n        }\n\n        if (node.previousSibling) {\n          // if previous sibling is an empty text node, look further\n          if (node.previousSibling.nodeType === dom.TEXT_NODE && node.previousSibling.length === 0) {\n            node = node.previousSibling;\n            continue;\n          }\n\n          return dom.getLastChild(node.previousSibling);\n        }\n        node = node.parentNode;\n      }\n    }\n    return null;\n  };\n  dom.getPrevContentNode = function (node, container) {\n    if (node) {\n      while (node.parentNode) {\n        if (node === container) {\n          return null;\n        }\n        if (node.previousSibling && dom.canContainTextElement(dom.getBlockParent(node))) {\n\n          // if previous sibling is an empty text node, look further\n          if (node.previousSibling.nodeType === dom.TEXT_NODE && node.previousSibling.length === 0) {\n            node = node.previousSibling;\n\n            continue;\n          }\n          return node.previousSibling;\n        } else if (node.previousElementSibling) {\n          return node.previousElementSibling;\n        }\n\n        node = node.parentNode;\n      }\n    }\n    return null;\n  };\n\n  dom.canContainTextElement = function (element) {\n    if (element && element.nodeName) {\n      return dom.TEXT_CONTAINER_ELEMENTS.lastIndexOf(element.nodeName.toLowerCase()) != -1;\n    } else {\n      return false;\n    }\n  };\n\n  dom.getFirstChild = function (node) {\n    if (node.firstChild) {\n      if (node.firstChild.nodeType === dom.ELEMENT_NODE) {\n        return dom.getFirstChild(node.firstChild);\n      } else {\n        return node.firstChild;\n      }\n    }\n    return node;\n  };\n  dom.getLastChild = function (node) {\n    if (node.lastChild) {\n      if (node.lastChild.nodeType === dom.ELEMENT_NODE) {\n        return dom.getLastChild(node.lastChild);\n      } else {\n        return node.lastChild;\n      }\n    }\n    return node;\n  };\n  dom.removeEmptyNodes = function (parent, callback) {\n    var elems = jQuery(parent).find(':empty');\n    var i = elems.length;\n    while (i > 0) {\n      i--;\n      if (dom.isStubElement(elems[i]) === false) {\n        if (!callback || callback.call(this, elems[i]) !== false) {\n          dom.remove(elems[i]);\n        }\n      }\n    }\n  };\n  dom.create = function (html) {\n    return jQuery(html)[0];\n  };\n  dom.find = function (parent, exp) {\n    return jQuery(parent).find(exp);\n  };\n  dom.children = function (parent, exp) {\n    return jQuery(parent).children(exp);\n  };\n  dom.parent = function (child, exp) {\n    return jQuery(child).parent(exp)[0];\n  };\n  dom.parents = function (child, exp) {\n    return jQuery(child).parents(exp);\n  };\n  dom.is = function (node, exp) {\n    return jQuery(node).is(exp);\n  };\n  dom.extend = function (deep, target, object1, object2) {\n    return jQuery.extend.apply(this, arguments);\n  };\n  dom.walk = function (elem, callback, lvl) {\n    if (!elem) {\n      return;\n    }\n    if (!lvl) {\n      lvl = 0;\n    }\n    var retVal = callback.call(this, elem, lvl);\n    if (retVal === false) {\n      return;\n    }\n    if (elem.childNodes && elem.childNodes.length > 0) {\n      dom.walk(elem.firstChild, callback, (lvl + 1));\n    } else if (elem.nextSibling) {\n      dom.walk(elem.nextSibling, callback, lvl);\n    } else if (elem.parentNode && elem.parentNode.nextSibling) {\n      dom.walk(elem.parentNode.nextSibling, callback, (lvl - 1));\n    }\n  };\n  dom.revWalk = function (elem, callback) {\n    if (!elem) {\n      return;\n    }\n    var retVal = callback.call(this, elem);\n    if (retVal === false) {\n      return;\n    }\n    if (elem.childNodes && elem.childNodes.length > 0) {\n      dom.walk(elem.lastChild, callback);\n    } else if (elem.previousSibling) {\n      dom.walk(elem.previousSibling, callback);\n    } else if (elem.parentNode && elem.parentNode.previousSibling) {\n      dom.walk(elem.parentNode.previousSibling, callback);\n    }\n  };\n  dom.setStyle = function (element, property, value) {\n    if (element) {\n      jQuery(element).css(property, value);\n    }\n  };\n  dom.getStyle = function (element, property) {\n    return jQuery(element).css(property);\n  };\n  dom.hasClass = function (element, className) {\n    return jQuery(element).hasClass(className);\n  };\n  dom.addClass = function (element, classNames) {\n    jQuery(element).addClass(classNames);\n  };\n  dom.removeClass = function (element, classNames) {\n    jQuery(element).removeClass(classNames);\n  };\n  dom.preventDefault = function (e) {\n    e.preventDefault();\n    dom.stopPropagation(e);\n  };\n  dom.stopPropagation = function (e) {\n    e.stopPropagation();\n  };\n  dom.noInclusionInherits = function (child, parent) {\n    if (parent instanceof String || typeof parent === 'string') {\n      parent = window[parent];\n    }\n    if (child instanceof String || typeof child === 'string') {\n      child = window[child];\n    }\n    var above = function () {};\n    if (dom.isset(parent) === true) {\n      for (var value in parent.prototype) {\n        if (child.prototype[value]) {\n          above.prototype[value] = parent.prototype[value];\n          continue;\n        }\n        child.prototype[value] = parent.prototype[value];\n      }\n    }\n    if (child.prototype) {\n      above.prototype.constructor = parent;\n      child.prototype['super'] = new above();\n    }\n  };\n\n  dom.each = function (val, callback) {\n    jQuery.each(val, function (i, el) {\n      callback.call(this, i, el);\n    });\n  };\n\n  dom.foreach = function (value, cb) {\n    if (value instanceof Array || value instanceof NodeList || typeof value.length != 'undefined' && typeof value.item != 'undefined') {\n      var len = value.length;\n      for (var i = 0; i < len; i++) {\n        var res = cb.call(this, i, value[i]);\n        if (res === false) {\n          break;\n        }\n      }\n    } else {\n      for (var id in value) {\n        if (value.hasOwnProperty(id) === true) {\n          var res = cb.call(this, id);\n          if (res === false) {\n            break;\n          }\n        }\n      }\n    }\n  };\n  dom.isBlank = function (value) {\n    if (!value || /^\\s*$/.test(value)) {\n      return true;\n    }\n    return false;\n  };\n  dom.isFn = function (f) {\n    if (typeof f === 'function') {\n      return true;\n    }\n    return false;\n  };\n  dom.isObj = function (v) {\n    if (v !== null && typeof v === 'object') {\n      return true;\n    }\n    return false;\n  };\n  dom.isset = function (v) {\n    if (typeof v !== 'undefined' && v !== null) {\n      return true;\n    }\n    return false;\n  };\n  dom.isArray = function (v) {\n    return jQuery.isArray(v);\n  };\n  dom.isNumeric = function (str) {\n    var result = str.match(/^\\d+$/);\n    if (result !== null) {\n      return true;\n    }\n    return false;\n  };\n  dom.getUniqueId = function () {\n    var timestamp = (new Date()).getTime();\n    var random = Math.ceil(Math.random() * 1000000);\n    var id = timestamp + '' + random;\n    return id.substr(5, 18).replace(/,/, '');\n  };\n  dom.inArray = function (needle, haystack) {\n    var hln = haystack.length;\n    for (var i = 0; i < hln; i++) {\n      if (needle === haystack[i]) {\n        return true;\n      }\n    }\n    return false;\n  };\n  dom.arrayDiff = function (array1, array2, firstOnly) {\n    var al = array1.length;\n    var res = [];\n    for (var i = 0; i < al; i++) {\n      if (dom.inArray(array1[i], array2) === false) {\n        res.push(array1[i]);\n      }\n    }\n    if (firstOnly !== true) {\n      al = array2.length;\n      for (var i = 0; i < al; i++) {\n        if (dom.inArray(array2[i], array1) === false) {\n          res.push(array2[i]);\n        }\n      }\n    }\n    return res;\n  };\n  dom.arrayMerge = function (array1, array2) {\n    var c = array2.length;\n    for (var i = 0; i < c; i++) {\n      array1.push(array2[i]);\n    }\n    return array1;\n  };\n  /**\n   * Removes allowedTags from the given content html string. If allowedTags is a string, then it\n   * is expected to be a selector; otherwise, it is expected to be array of string tag names.\n   */\n  dom.stripTags = function (content, allowedTags) {\n    if (typeof allowedTags === \"string\") {\n      var c = jQuery('<div>' + content + '</div>');\n      c.find('*').not(allowedTags).remove();\n      return c.html();\n    } else {\n      var match;\n      var re = new RegExp(/<\\/?(\\w+)((\\s+\\w+(\\s*=\\s*(?:\".*?\"|'.*?'|[^'\">\\s]+))?)+\\s*|\\s*)\\/?>/gim);\n      var resCont = content;\n      while ((match = re.exec(content)) != null) {\n        if (dom.isset(allowedTags) === false || dom.inArray(match[1], allowedTags) !== true) {\n          resCont = resCont.replace(match[0], '');\n        }\n      }\n      return resCont;\n    }\n  };\n  dom.browser = function () {\n\t\tif (_browser) {\n      return $.extend({}, _browser);\n    }\n\n    _browser = (function() {\n      function uaMatch( ua ) {\n        ua = ua.toLowerCase();\n\n        var match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n          /(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n          /(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n          /(msie) ([\\w.]+)/.exec( ua ) ||\n          ua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n          [];\n\n\treturn {\n          browser: match[ 1 ] || \"\",\n          version: match[ 2 ] || \"0\"\n        };\n      }\n\n      var ua = navigator.userAgent.toLowerCase(),\n          matched = uaMatch(ua),\n          browser = {\n            type: \"unknown\",\n            version : 0,\n            msie: false\n          };\n\n      if ( matched.browser ) {\n        browser[ matched.browser ] = true;\n        browser.version = matched.version || 0;\n        browser.type = matched.browser;\n      }\n\n      // Chrome is Webkit, but Webkit is also Safari.\n      if ( browser.chrome ) {\n        browser.webkit = true;\n      } else if ( browser.webkit ) {\n        browser.safari = true;\n      }\n      if (browser.webkit) {\n        browser.type = \"webkit\";\n      }\n      browser.firefox = (/firefox/.test(ua) == true);\n      if (! browser.msie) {\n        browser.msie = !! /trident/.test(ua);\n      }\n\n      return browser;\n    })();\n\n    return $.extend({}, _browser);\n  };\n  dom.getBrowserType = function () {\n    if (this._browserType === null) {\n      var tests = ['msie', 'firefox', 'chrome', 'safari'];\n      var tln = tests.length;\n      for (var i = 0; i < tln; i++) {\n        var r = new RegExp(tests[i], 'i');\n        if (r.test(navigator.userAgent) === true) {\n          this._browserType = tests[i];\n          return this._browserType;\n        }\n      }\n\n      this._browserType = 'other';\n    }\n    return this._browserType;\n  };\n  dom.getWebkitType = function(){\n\tif(dom.browser().type !== \"webkit\") {\n\t\tconsole.log(\"Not a webkit!\");\n\t\treturn false;\n\t}\n    var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;\n\tif(isSafari) return \"safari\";\n\treturn \"chrome\";\n  };\n  dom.isBrowser = function (browser) {\n    return (dom.browser().type === browser);\n  };\n\n  dom.getBlockParent = function (node, container) {\n    if (dom.isBlockElement(node) === true) {\n      return node;\n    }\n    if (node) {\n      while (node.parentNode) {\n        node = node.parentNode;\n        if (node === container) {\n          return null;\n        }\n\n        if (dom.isBlockElement(node) === true) {\n          return node;\n        }\n      }\n    }\n    return null;\n  };\n  dom.findNodeParent = function (node, selector, container) {\n    if (node) {\n      while (node.parentNode) {\n        if (node === container) {\n          return null;\n        }\n\n        if (dom.is(node, selector) === true) {\n          return node;\n        }\n        node = node.parentNode;\n      }\n    }\n    return null;\n  };\n  dom.onBlockBoundary = function (leftContainer, rightContainer, blockEls) {\n    if (!leftContainer || !rightContainer) return false\n    var bleft = dom.isChildOfTagNames(leftContainer, blockEls) || dom.is(leftContainer, blockEls.join(', ')) && leftContainer || null;\n    var bright = dom.isChildOfTagNames(rightContainer, blockEls) || dom.is(rightContainer, blockEls.join(', ')) && rightContainer || null;\n    return (bleft !== bright);\n  };\n\n  dom.isOnBlockBoundary = function (leftContainer, rightContainer, container) {\n    if (!leftContainer || !rightContainer) return false\n    var bleft = dom.getBlockParent(leftContainer, container) || dom.isBlockElement(leftContainer, container) && leftContainer || null;\n    var bright = dom.getBlockParent(rightContainer, container) || dom.isBlockElement(rightContainer, container) && rightContainer || null;\n    return (bleft !== bright);\n  };\n\n  dom.mergeContainers = function (node, mergeToNode) {\n    if (!node || !mergeToNode) return false;\n\n    if (node.nodeType === dom.TEXT_NODE || dom.isStubElement(node)) {\n      // Move only this node.\n      mergeToNode.appendChild(node);\n    } else if (node.nodeType === dom.ELEMENT_NODE) {\n      // Move all the child nodes to the new parent.\n      while (node.firstChild) {\n        mergeToNode.appendChild(node.firstChild);\n      }\n\n      dom.remove(node);\n    }\n    return true;\n  };\n\n  dom.mergeBlockWithSibling = function (range, block, next) {\n    var siblingBlock = next ? jQuery(block).next().get(0) : jQuery(block).prev().get(0); // block['nextSibling'] : block['previousSibling'];\n    if (next) dom.mergeContainers(siblingBlock, block);\n    else dom.mergeContainers(block, siblingBlock);\n    range.collapse(true);\n    return true;\n  };\n\n  dom.date = function (format, timestamp, tsIso8601) {\n    if (timestamp === null && tsIso8601) {\n      timestamp = dom.tsIso8601ToTimestamp(tsIso8601);\n      if (!timestamp) {\n        return;\n      }\n    }\n    var date = new Date(timestamp);\n    var formats = format.split('');\n    var fc = formats.length;\n    var dateStr = '';\n    for (var i = 0; i < fc; i++) {\n      var r = '';\n      var f = formats[i];\n      switch (f) {\n        case 'D':\n        case 'l':\n          var names = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n          r = names[date.getDay()];\n          if (f === 'D') {\n            r = r.substring(0, 3);\n          }\n          break;\n        case 'F':\n        case 'm':\n          r = date.getMonth() + 1;\n          if (r < 10) r = '0' + r;\n          break;\n        case 'M':\n          var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\n          r = months[date.getMonth()];\n          if (f === 'M') {\n            r = r.substring(0, 3);\n          }\n          break;\n        case 'd':\n          r = date.getDate();\n          break;\n        case 'S':\n          r = dom.getOrdinalSuffix(date.getDate());\n          break;\n        case 'Y':\n          r = date.getFullYear();\n          break;\n        case 'y':\n          r = date.getFullYear();\n          r = r.toString().substring(2);\n          break;\n        case 'H':\n          r = date.getHours();\n          break;\n        case 'h':\n          r = date.getHours();\n          if (r === 0) {\n            r = 12;\n          } else if (r > 12) {\n            r -= 12;\n          }\n          break;\n        case 'i':\n          r = dom.addNumberPadding(date.getMinutes());\n          break;\n        case 'a':\n          r = 'am';\n          if (date.getHours() >= 12) {\n            r = 'pm';\n          }\n          break;\n        default:\n          r = f;\n          break;\n      }\n      dateStr += r;\n    }\n    return dateStr;\n  };\n  dom.getOrdinalSuffix = function (number) {\n    var suffix = '';\n    var tmp = (number % 100);\n    if (tmp >= 4 && tmp <= 20) {\n      suffix = 'th';\n    } else {\n      switch (number % 10) {\n        case 1:\n          suffix = 'st';\n          break;\n        case 2:\n          suffix = 'nd';\n          break;\n        case 3:\n          suffix = 'rd';\n          break;\n        default:\n          suffix = 'th';\n          break;\n      }\n    }\n    return suffix;\n  };\n  dom.addNumberPadding = function (number) {\n    if (number < 10) {\n      number = '0' + number;\n    }\n    return number;\n  };\n  dom.tsIso8601ToTimestamp = function (tsIso8601) {\n    var regexp = /(\\d\\d\\d\\d)(?:-?(\\d\\d)(?:-?(\\d\\d)(?:[T ](\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(?:Z|(?:([-+])(\\d\\d)(?::?(\\d\\d))?)?)?)?)?)?/;\n    var d = tsIso8601.match(new RegExp(regexp));\n    if (d) {\n      var date = new Date();\n      date.setDate(d[3]);\n      date.setFullYear(d[1]);\n      date.setMonth(d[2] - 1);\n      date.setHours(d[4]);\n      date.setMinutes(d[5]);\n      date.setSeconds(d[6]);\n      var offset = (d[9] * 60);\n      if (d[8] === '+') {\n        offset *= -1;\n      }\n      offset -= date.getTimezoneOffset();\n      var timestamp = (date.getTime() + (offset * 60 * 1000));\n      return timestamp;\n    }\n    return null;\n  };\n\n  exports.dom = dom;\n\n}).call(this.ice);\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/dom.js\n// module id = 4\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function() {\n\t\n\nvar exports = this;\n\nvar IcePlugin = function(ice_instance) {\n\t\n  this._ice = ice_instance;\n};\n\nIcePlugin.prototype = {\n\n  start: function() {},\n  clicked: function(e) {\n    return true;\n  },\n  mouseDown: function(e) {\n    return true;\n  },\n  keyDown: function(e) {\n    return true;\n  },\n  keyPress: function(e) {\n    return true;\n  },\n  selectionChanged: function(range) {},\n  setEnabled: function(enabled) {},\n  setDisabled: function(enabled) {},\n  caretUpdated: function() {},\n  nodeInserted: function(node, range) {},\n  nodeCreated: function(node, options) {},\n  caretPositioned: function() {},\n  remove: function() {\n    this._ice.removeKeyPressListener(this);\n  },\n  setSettings: function(settings) {}\n};\n\nexports.IcePlugin = IcePlugin;\n\n}).call(this.ice);\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/icePlugin.js\n// module id = 5\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function() {\n\t\n\nvar exports = this;\n\nvar IcePluginManager = function(ice_instance) {\n\n  this.plugins = {},\n  this.pluginConstructors = {},\n  this.keyPressListeners = {},\n  this.activePlugin = null,\n  this.pluginSets = {},\n  this.activePluginSet = null,\n\n  this._ice = ice_instance;\n};\n\nIcePluginManager.prototype = {\n\n  getPluginNames: function() {\n    var plugins = [];\n    for (var name in this.plugins) {\n      plugins.push(name);\n    }\n    return plugins;\n  },\n\n  addPluginObject: function(pluginName, pluginObj) {\n    this.plugins[pluginName] = pluginObj;\n  },\n\n  addPlugin: function(name, pluginConstructor) {\n    if (typeof pluginConstructor !== 'function') {\n      throw Error('IcePluginException: plugin must be a constructor function');\n    }\n\n    if (ice.dom.isset(this.pluginConstructors[name]) === false) {\n      this.pluginConstructors[name] = pluginConstructor;\n    }\n  },\n\n  loadPlugins: function(plugins, callback) {\n    if (plugins.length === 0) {\n      callback.call(this);\n    } else {\n      var plugin = plugins.shift();\n      if (typeof plugin === 'object') {\n        plugin = plugin.name;\n      }\n\n      if (ice.dom.isset(ice._plugin[plugin]) === true) {\n        this.addPlugin(plugin, ice._plugin[plugin]);\n        this.loadPlugins(plugins, callback);\n      } else {\n        throw new Error('plugin was not included in the page: ' + plugin);\n      }\n    }\n  },\n\n  _enableSet: function(name) {\n    this.activePluginSet = name;\n    var pSetLen = this.pluginSets[name].length;\n    for (var i = 0; i < pSetLen; i++) {\n      var plugin   = this.pluginSets[name][i];\n      var pluginName = '';\n      if (typeof plugin === 'object') {\n        pluginName = plugin.name;\n      } else {\n        pluginName = plugin;\n      }\n\n      var pluginConstructor = this.pluginConstructors[pluginName];\n      if (pluginConstructor) {\n        var pluginObj = new pluginConstructor(this._ice);\n        this.plugins[pluginName] = pluginObj;\n\n        if (ice.dom.isset(plugin.settings) === true) {\n          pluginObj.setSettings(plugin.settings);\n        }\n\n        pluginObj.start();\n      }\n    }\n  },\n\n  setActivePlugin: function(name) {\n    this.activePlugin = name;\n  },\n\n  getActivePlugin: function() {\n    return this.activePlugin;\n  },\n\n  _getPluginName: function(pluginConstructor) {\n    var fn = pluginConstructor.toString();\n    var start = 'function '.length;\n    var name = fn.substr(start, (fn.indexOf('(') - start));\n    return name;\n  },\n\n  /**\n   * Removes specified plugin.\n   */\n  removePlugin: function(plugin) {\n    if (this.plugins[plugin]) {\n      // Call the remove fn of the plugin incase it needs to do cleanup.\n      this.plugins[plugin].remove();\n    }\n  },\n\n  /**\n   * Returns the plugin object for specified plugin name.\n   */\n  getPlugin: function(name) {\n    return this.plugins[name];\n\n  },\n\n  /**\n   * Add a new set of plugins.\n   */\n  usePlugins: function(name, plugins, callback) {\n    var self = this;\n    if (ice.dom.isset(plugins) === true) {\n      this.pluginSets[name] = plugins;\n    } else {\n      this.pluginSets[name] = [];\n    }\n    var clone = this.pluginSets[name].concat([]);\n    this.loadPlugins(clone, function() {\n      self._enableSet(name);\n      if(callback) callback.call(this);\n    });\n  },\n\n  disablePlugin: function(name) {\n    this.plugins[name].disable();\n  },\n\n  isPluginElement: function(element) {\n    for (var i in this.plugins) {\n      if (this.plugins[i].isPluginElement) {\n        if (this.plugins[i].isPluginElement(element) === true) {\n          return true;\n        }\n      }\n    }\n    return false;\n  },\n\n  fireKeyPressed: function(e) {\n    if (this._fireKeyPressFns(e, 'all_keys') === false) {\n      return false;\n    }\n\n    var eKeys = [];\n    if (e.ctrlKey === true || e.metaKey === true) {\n      eKeys.push('ctrl');\n    }\n\n    if (e.shiftKey === true) {\n      eKeys.push('shift');\n    }\n\n    if (e.altKey === true) {\n      eKeys.push('alt');\n    }\n\n    switch (e.keyCode) {\n      case 13:\n        eKeys.push('enter');\n      break;\n\n      case ice.dom.DOM_VK_LEFT:\n        eKeys.push('left');\n      break;\n\n      case ice.dom.DOM_VK_RIGHT:\n        eKeys.push('right');\n      break;\n\n      case ice.dom.DOM_VK_UP:\n        eKeys.push('up');\n      break;\n\n      case ice.dom.DOM_VK_DOWN:\n        eKeys.push('down');\n      break;\n\n      case 9:\n        eKeys.push('tab');\n      break;\n\n      case ice.dom.DOM_VK_DELETE:\n        eKeys.push('delete');\n      break;\n\n      default:\n        var code;\n        if (e.keyCode) {\n          code = e.keyCode;\n        } else if (e.which) {\n          code = e.which;\n        }\n\n        // Other characters (a-z0-9..).\n        if (code) {\n          eKeys.push(String.fromCharCode(code).toLowerCase());\n        }\n      break;\n    }//end switch\n\n    var eKeysStr = eKeys.sort().join('+');\n\n    return this._fireKeyPressFns(e, eKeysStr);\n\n  },\n\n  _fireKeyPressFns: function(e, eKeysStr) {\n    if (this.keyPressListeners[eKeysStr]) {\n      var ln = this.keyPressListeners[eKeysStr].length;\n      for (var i = 0; i < ln; i++) {\n        var listener = this.keyPressListeners[eKeysStr][i];\n        var eventFn  = listener.fn;\n        var plugin   = listener.plugin;\n        var data   = listener.data;\n\n        if (eventFn) {\n          if (ice.dom.isFn(eventFn) === true) {\n            if (eventFn.call(plugin, e, data) === true) {\n              ice.dom.preventDefault(e);\n              return false;\n            }\n          } else if (plugin[eventFn] && plugin[eventFn].call(plugin, e, data) === true) {\n            ice.dom.preventDefault(e);\n            return false;\n          }\n        }\n      }\n    }\n\n    return true;\n  },\n\n  fireSelectionChanged: function(range) {\n    for (var i in this.plugins) {\n      this.plugins[i].selectionChanged(range);\n    }\n  },\n\n  fireNodeInserted: function(node, range) {\n    for (var i in this.plugins) {\n      if (this.plugins[i].nodeInserted(node, range) === false) {\n        return false;\n      }\n    }\n  },\n\n  fireNodeCreated: function(node, option) {\n    for (var i in this.plugins) {\n      if (this.plugins[i].nodeCreated(node, option) === false) {\n        return false;\n      }\n    }\n  },\n\n  fireCaretPositioned: function() {\n    for (var i in this.plugins) {\n      this.plugins[i].caretPositioned()\n    }\n  },\n\n  fireClicked: function(e) {\n    var val = true;\n    for (var i in this.plugins) {\n      if (this.plugins[i].clicked(e) === false) {\n        val = false;\n      }\n    }\n    return val;\n  },\n\n  fireMouseDown: function(e) {\n    var val = true;\n    for (var i in this.plugins) {\n      if (this.plugins[i].mouseDown(e) === false) {\n        val = false;\n      }\n    }\n    return val;\n  },\n\n  fireKeyDown: function(e) {\n    var val = true;\n    for (var i in this.plugins) {\n      if (this.plugins[i].keyDown(e) === false) {\n        val = false;\n      }\n    }\n    return val;\n  },\n\n  fireKeyPress: function(e) {\n    var val = true;\n    for (var i in this.plugins) {\n      if (this.plugins[i].keyPress(e) === false) {\n        val = false;\n      }\n    }\n    return val;\n  },\n\n  fireEnabled: function(enabled) {\n    for (var i in this.plugins) {\n      this.plugins[i].setEnabled(enabled);\n    }\n  },\n\n  fireDisabled: function(disabled) {\n    for (var i in this.plugins) {\n      this.plugins[i].setDisabled(disabled);\n    }\n  },\n\n  fireCaretUpdated: function() {\n    for (var i in this.plugins) {\n      if (this.plugins[i].caretUpdated) {\n        this.plugins[i].caretUpdated();\n      }\n    }\n  }\n};\n\nexports._plugin = {};\nexports.IcePluginManager = IcePluginManager;\n\n}).call(this.ice);\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/icePluginManager.js\n// module id = 6\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n// Add ECMA262-5 string trim if not supported natively\n//\nif (typeof String.prototype.trim !== 'function') {\n  String.prototype.trim = function() {\n    return this.replace(/^\\s+|\\s+$/g, '');\n  }\n}\n\n// Add ECMA262-5 Array methods if not supported natively\n//\nif (!('indexOf' in Array.prototype)) {\n  Array.prototype.indexOf= function(find, i /*opt*/) {\n    if (i===undefined) i= 0;\n    if (i<0) i+= this.length;\n    if (i<0) i= 0;\n    for (var n= this.length; i<n; i++)\n      if (i in this && this[i]===find)\n        return i;\n    return -1;\n  };\n}\nif (!('lastIndexOf' in Array.prototype)) {\n  Array.prototype.lastIndexOf= function(find, i /*opt*/) {\n    if (i===undefined) i= this.length-1;\n    if (i<0) i+= this.length;\n    if (i>this.length-1) i= this.length-1;\n    for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */\n      if (i in this && this[i]===find)\n        return i;\n    return -1;\n  };\n}\nif (!('map' in Array.prototype)) {\n  Array.prototype.map= function(mapper, that /*opt*/) {\n    var other= new Array(this.length);\n    for (var i= 0, n= this.length; i<n; i++)\n      if (i in this)\n        other[i]= mapper.call(that, this[i], i, this);\n    return other;\n  };\n}\nif (!('filter' in Array.prototype)) {\n  Array.prototype.filter= function(filter, that /*opt*/) {\n    var other= [], v;\n    for (var i=0, n= this.length; i<n; i++)\n      if (i in this && filter.call(that, v= this[i], i, this))\n        other.push(v);\n    return other;\n  };\n}\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/polyfills.js\n// module id = 7\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function () {\n\t\n\n  var exports = this,\n    Selection;\n\n  Selection = function (env) {\n    this._selection = null;\n    this.env = env;\n\n    this._initializeRangeLibrary();\n    this._getSelection();\n  };\n\n  Selection.prototype = {\n\n    /**\n     * Returns the selection object for the current browser.\n     */\n    _getSelection: function () {\n      if (this._selection) {\n\t\t  this._selection.refresh();\n\t  }\n      else if (this.env.frame) {\n\t\t  this._selection = rangy.getIframeSelection(this.env.frame);\n\t  }\n      else {\n\t\t  this._selection = rangy.getSelection();\n\t  }\n      return this._selection;\n    },\n\n    /**\n     * Creates a range object.\n     */\n    createRange: function () {\n      return rangy.createRange(this.env.document);\n    },\n\n    /**\n     * Returns the range object at the specified position. The current range object\n     * is at position 0. Note - currently only setting single range in `addRange` so\n     * position 0 will be the only allocation filled.\n     */\n    getRangeAt: function (pos) {\n      this._selection.refresh();\n      try {\n        return this._selection.getRangeAt(pos);\n      } catch (e) {\n        this._selection = null;\n        return this._getSelection().getRangeAt(0);\n      }\n    },\n\n    /**\n     * Adds the specified range to the current selection. Note - only supporting setting\n     * a single range, so the previous range gets evicted.\n     */\n    addRange: function (range) {\n      this._selection || (this._selection = this._getSelection());\n      this._selection.setSingleRange(range);\n      this._selection.ranges = [range];\n      return;\n    },\n\n    /**\n     * Initialize and extend the `rangy` library with some custom functionality.\n     */\n    _initializeRangeLibrary: function () {\n      var self = this;\n\n      rangy.init();\n      rangy.config.checkSelectionRanges = false;\n\n      var move = function (range, unitType, units, isStart) {\n        if (units === 0) {\n\t\t  return;\n        }\n\n        switch (unitType) {\n          case ice.dom.CHARACTER_UNIT:\n            if (units > 0) {\n              range.moveCharRight(isStart, units);\n            } else {\n              range.moveCharLeft(isStart, units * -1);\n            }\n            break;\n\n          case ice.dom.WORD_UNIT:\n          default:\n            // Removed. TODO: possibly refactor or re-implement.\n            break;\n        }\n      };\n\n      /**\n       * Moves the start of the range using the specified `unitType`, by the specified\n       * number of `units`. Defaults to `CHARACTER_UNIT` and units of 1.\n       */\n      rangy.rangePrototype.moveStart = function (unitType, units) {\n        move(this, unitType, units, true);\n      };\n\n      /**\n       * Moves the end of the range using the specified `unitType`, by the specified\n       * number of `units`.\n       */\n      rangy.rangePrototype.moveEnd = function (unitType, units) {\n        move(this, unitType, units, false);\n      };\n\n      /**\n       * Depending on the given `start` boolean, sets the start or end containers\n       * to the given `container` with `offset` units.\n       */\n      rangy.rangePrototype.setRange = function (start, container, offset) {\n        if (start) {\n          this.setStart(container, offset);\n        } else {\n          this.setEnd(container, offset);\n        }\n      };\n\n      /**\n       * Depending on the given `moveStart` boolean, moves the start or end containers\n       * to the left by the given number of character `units`. Use the following\n       * example as a demonstration for where the range will fall as it moves in and\n       * out of tag boundaries (where \"|\" is the marked range):\n       *\n       * test <em>it</em> o|ut\n       * test <em>it</em> |out\n       * test <em>it</em>| out\n       * test <em>i|t</em> out\n       * test <em>|it</em> out\n       * test| <em>it</em> out\n       * tes|t <em>it</em> out\n       * \n       * A range could be mapped in one of two ways:\n       * \n       * (1) If a startContainer is a Node of type Text, Comment, or CDATASection, then startOffset\n       * is the number of characters from the start of startNode. For example, the following\n       * are the range properties for `<p>te|st</p>` (where \"|\" is the collapsed range):\n       * \n       * startContainer: <TEXT>test<TEXT>\n       * startOffset: 2\n       * endContainer: <TEXT>test<TEXT>\n       * endOffset: 2\n       * \n       * (2) For other Node types, startOffset is the number of child nodes between the start of\n       * the startNode. Take the following html fragment:\n       * \n       * `<p>some <span>test</span> text</p>`\n       * \n       * If we were working with the following range properties:\n       * \n       * startContainer: <p>\n       * startOffset: 2\n       * endContainer: <p>\n       * endOffset: 2\n       * \n       * Since <p> is an Element node, the offsets are based on the offset in child nodes of <p> and\n       * the range is selecting the second child - the <span> tag.\n       * \n       * <p><TEXT>some </TEXT><SPAN>test</SPAN><TEXT> text</TEXT></p>\n       */\n      rangy.rangePrototype.moveCharLeft = function (moveStart, units) {\n        var container, offset;\n\n        if (moveStart) {\n          container = this.startContainer;\n          offset = this.startOffset;\n        } else {\n          container = this.endContainer;\n          offset = this.endOffset;\n        }\n\n        // Handle the case where the range conforms to (2) (noted in the comment above).\n        if (container.nodeType === ice.dom.ELEMENT_NODE && container.innerHTML !== '&nbsp;') {\n          if (container.hasChildNodes() && container.childNodes[offset]) {\n            container = container.childNodes[offset];\n\n            container = this.getPreviousTextNode(container);\n\n            // Get the previous text container that is not an empty text node.\n            while (container && container.nodeType == ice.dom.TEXT_NODE && container.nodeValue === \"\") {\n              container = this.getPreviousTextNode(container);\n            }\n\n            offset = container.data.length - units;\n          } else {\n            offset = units * -1;\n          }\n        } else {\n          offset -= units;\n        }\n\n        if (offset < 0) {\n          // We need to move to a previous selectable container.\n          while (offset < 0) {\n            var skippedBlockElem = [];\n\n            container = this.getPreviousTextNode(container, skippedBlockElem);\n\n            // We are at the beginning/out of the editable - break.\n            if (!container) {\n              return;\n            }\n\n            if (container.nodeType === ice.dom.ELEMENT_NODE) {\n              continue;\n            }\n\n            offset += container.data.length;\n          }\n        }\n\n        this.setRange(moveStart, container, offset);\n      };\n\n      /**\n       * Depending on the given `moveStart` boolean, moves the start or end containers\n       * to the right by the given number of character `units`. Use the following\n       * example as a demonstration for where the range will fall as it moves in and\n       * out of tag boundaries (where \"|\" is the marked range):\n       *\n       * tes|t <em>it</em> out\n       * test| <em>it</em> out\n       * test |<em>it</em> out\n       * test <em>i|t</em> out\n       * test <em>it|</em> out\n       * test <em>it</em> |out\n       * \n       * A range could be mapped in one of two ways:\n       * \n       * (1) If a startContainer is a Node of type Text, Comment, or CDATASection, then startOffset\n       * is the number of characters from the start of startNode. For example, the following\n       * are the range properties for `<p>te|st</p>` (where \"|\" is the collapsed range):\n       * \n       * startContainer: <TEXT>test<TEXT>\n       * startOffset: 2\n       * endContainer: <TEXT>test<TEXT>\n       * endOffset: 2\n       * \n       * (2) For other Node types, startOffset is the number of child nodes between the start of\n       * the startNode. Take the following html fragment:\n       * \n       * `<p>some <span>test</span> text</p>`\n       * \n       * If we were working with the following range properties:\n       * \n       * startContainer: <p>\n       * startOffset: 2\n       * endContainer: <p>\n       * endOffset: 2\n       * \n       * Since <p> is an Element node, the offsets are based on the offset in child nodes of <p> and\n       * the range is selecting the second child - the <span> tag.\n       * \n       * <p><TEXT>some </TEXT><SPAN>test</SPAN><TEXT> text</TEXT></p>\n       */\n      rangy.rangePrototype.moveCharRight = function (moveStart, units) {\n        var container, offset;\n\n        if (moveStart) {\n          container = this.startContainer;\n          offset = this.startOffset;\n        } else {\n          container = this.endContainer;\n          offset = this.endOffset;\n        }\n\n        if (container.nodeType === ice.dom.ELEMENT_NODE) {\n          container = container.childNodes[offset];\n          if (container.nodeType !== ice.dom.TEXT_NODE) {\n            container = this.getNextTextNode(container);\n          }\n\n          offset = units;\n        } else {\n          offset += units;\n        }\n\n        var diff = (offset - container.data.length);\n        if (diff > 0) {\n          var skippedBlockElem = [];\n          // We need to move to the next selectable container.\n          while (diff > 0) {\n            container = this.getNextContainer(container, skippedBlockElem);\n\n            if (container.nodeType === ice.dom.ELEMENT_NODE) {\n              continue;\n            }\n\n            if (container.data.length >= diff) {\n              // We found a container with enough content to select.\n              break;\n            } else if (container.data.length > 0) {\n              // Container does not have enough content,\n              // find the next one.\n              diff -= container.data.length;\n            }\n          }\n\n          offset = diff;\n        }\n\n        this.setRange(moveStart, container, offset);\n      };\n\n      /**\n       * Returns the deepest next container that the range can be extended to.\n       * For example, if the next container is an element that contains text nodes,\n       * the the container's firstChild is returned.\n       */\n      rangy.rangePrototype.getNextContainer = function (container, skippedBlockElem) {\n        if (!container) {\n          return null;\n        }\n\n        while (container.nextSibling) {\n          container = container.nextSibling;\n          if (container.nodeType !== ice.dom.TEXT_NODE) {\n            var child = this.getFirstSelectableChild(container);\n            if (child !== null) {\n              return child;\n            }\n          } else if (this.isSelectable(container) === true) {\n            return container;\n          }\n        }\n\n        // Look at parents next sibling.\n        while (container && !container.nextSibling) {\n          container = container.parentNode;\n        }\n\n        if (!container) {\n          return null;\n        }\n\n        container = container.nextSibling;\n        if (this.isSelectable(container) === true) {\n          return container;\n        } else if (skippedBlockElem && ice.dom.isBlockElement(container) === true) {\n          skippedBlockElem.push(container);\n        }\n\n        var selChild = this.getFirstSelectableChild(container);\n        if (selChild !== null) {\n          return selChild;\n        }\n\n        return this.getNextContainer(container, skippedBlockElem);\n      };\n\n      /**\n       * Returns the deepest previous container that the range can be extended to.\n       * For example, if the previous container is an element that contains text nodes,\n       * then the container's lastChild is returned.\n       */\n      rangy.rangePrototype.getPreviousContainer = function (container, skippedBlockElem) {\n        if (!container) {\n          return null;\n        }\n\n        while (container.previousSibling) {\n          container = container.previousSibling;\n          if (container.nodeType !== ice.dom.TEXT_NODE) {\n            if (ice.dom.isStubElement(container) === true) {\n              return container;\n            } else {\n              var child = this.getLastSelectableChild(container);\n              if (child !== null) {\n                return child;\n              }\n            }\n          } else if (this.isSelectable(container) === true) {\n            return container;\n          }\n        }\n\n        // Look at parents next sibling.\n        while (container && !container.previousSibling) {\n          container = container.parentNode;\n        }\n\n        if (!container) {\n          return null;\n        }\n\n        container = container.previousSibling;\n        if (this.isSelectable(container) === true) {\n          return container;\n        } else if (skippedBlockElem && ice.dom.isBlockElement(container) === true) {\n          skippedBlockElem.push(container);\n        }\n\n        var selChild = this.getLastSelectableChild(container);\n        if (selChild !== null) {\n          return selChild;\n        }\n        return this.getPreviousContainer(container, skippedBlockElem);\n      };\n\n      rangy.rangePrototype.getNextTextNode = function (container) {\n        if (container.nodeType === ice.dom.ELEMENT_NODE) {\n          if (container.childNodes.length !== 0) {\n            return this.getFirstSelectableChild(container);\n          }\n        }\n\n        container = this.getNextContainer(container);\n        if (container.nodeType === ice.dom.TEXT_NODE) {\n          return container;\n        }\n\n        return this.getNextTextNode(container);\n      };\n\n      rangy.rangePrototype.getPreviousTextNode = function (container, skippedBlockEl) {\n        container = this.getPreviousContainer(container, skippedBlockEl);\n        if (container.nodeType === ice.dom.TEXT_NODE) {\n          return container;\n        }\n\n        return this.getPreviousTextNode(container, skippedBlockEl);\n      };\n\n      rangy.rangePrototype.getFirstSelectableChild = function (element) {\n        if (element) {\n          if (element.nodeType !== ice.dom.TEXT_NODE) {\n            var child = element.firstChild;\n            while (child) {\n              if (this.isSelectable(child) === true) {\n                return child;\n              } else if (child.firstChild) {\n                // This node does have child nodes.\n                var res = this.getFirstSelectableChild(child);\n                if (res !== null) {\n                  return res;\n                } else {\n                  child = child.nextSibling;\n                }\n              } else {\n                child = child.nextSibling;\n              }\n            }\n          } else {\n            // Given element is a text node so return it.\n            return element;\n          }\n        }\n        return null;\n      };\n\n      rangy.rangePrototype.getLastSelectableChild = function (element) {\n        if (element) {\n          if (element.nodeType !== ice.dom.TEXT_NODE) {\n            var child = element.lastChild;\n            while (child) {\n              if (this.isSelectable(child) === true) {\n                return child;\n              } else if (child.lastChild) {\n                // This node does have child nodes.\n                var res = this.getLastSelectableChild(child);\n                if (res !== null) {\n                  return res;\n                } else {\n                  child = child.previousSibling;\n                }\n              } else {\n                child = child.previousSibling;\n              }\n            }\n          } else {\n            // Given element is a text node so return it.\n            return element;\n          }\n        }\n        return null;\n      };\n\n      rangy.rangePrototype.isSelectable = function (container) {\n        if (container && container.nodeType === ice.dom.TEXT_NODE && container.data.length !== 0) {\n          return true;\n        }\n        return false;\n      };\n\n      rangy.rangePrototype.getHTMLContents = function (clonedSelection) {\n        if (!clonedSelection) {\n          clonedSelection = this.cloneContents();\n        }\n        var div = self.env.document.createElement('div');\n        div.appendChild(clonedSelection.cloneNode(true));\n        return div.innerHTML;\n      };\n\n      rangy.rangePrototype.getHTMLContentsObj = function () {\n        return this.cloneContents();\n      };\n    }\n  };\n\n  exports.Selection = Selection;\n\n}).call(this.ice);\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/selection.js\n// module id = 8\n// module chunks = 0",null,"/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function() {\n\nvar exports = this, IceAddTitlePlugin;\n  \nIceAddTitlePlugin = function(ice_instance) {\n  this._ice = ice_instance;\n};\n\nIceAddTitlePlugin.prototype = {\n  nodeCreated: function(node, option) {\n    node.setAttribute('title', (option.action || 'Modified') + ' by ' + node.getAttribute(this._ice.userNameAttribute)\n        + ' - ' + ice.dom.date('m/d/Y h:ia', parseInt(node.getAttribute(this._ice.timeAttribute))));\n  }\n};\n\nice.dom.noInclusionInherits(IceAddTitlePlugin, ice.IcePlugin);\nexports._plugin.IceAddTitlePlugin = IceAddTitlePlugin;\n\n}).call(this.ice);\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/plugins/IceAddTitlePlugin/IceAddTitlePlugin.js\n// module id = 10\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function() {\n\nvar exports = this, IceCopyPastePlugin;\n\nIceCopyPastePlugin = function(ice_instance) {\n  this._ice = ice_instance;\n  this._tmpNode = null;\n  this._tmpNodeTagName = 'icepaste';\n  this._pasteId = 'icepastediv';\n  var self = this;\n  \n  // API\n\n  // 'formatted' - paste will be MS Word cleaned.\n  // 'formattedClean' - paste will be MS Word cleaned, insert and\n  //    delete tags will be removed keeping insert content in place,\n  //    and tags not found in `preserve` will be stripped.\n  this.pasteType = 'formattedClean';\n\n  // Subset of tags that will not be stripped when pasteType\n  // is set to 'formattedClean'. Parameter is of type string with\n  // comma delimited tag and attribute definitions. For example:\n  //   'p,a[href],i[style|title],span[*]'\n  // Would allow `p`, `a`, `i` and `span` tags. The attributes for\n  // each one of these tags would be cleaned as follows: `p` tags\n  // would have all attributes removed, `a` tags will have all but\n  // `href` attributes removed, `i` tags will have all but `style`\n  // and `title` attributes removed, and `span` tags will keep all attributes.\n  this.preserve = 'p';\n\n  // Callback triggered before any paste cleaning happens\n  this.beforePasteClean = function(body) { return body; };\n\n  // Callback triggered at the end of the paste cleaning\n  this.afterPasteClean = function(body) { return body; };\n\n  // Event Listener for copying\n  ice_instance.element.oncopy = function() { return self.handleCopy.apply(self); };\n};\n\nIceCopyPastePlugin.prototype = {\n\n  setSettings: function(settings) {\n    settings = settings || {};\n    ice.dom.extend(this, settings);\n\n    this.preserve += ',' + this._tmpNodeTagName;\n    this.setupPreserved();\n  },\n\n  keyDown: function(e) {\n    if (e.metaKey !== true && e.ctrlKey !== true)\n      return;\n    if (e.keyCode == 86)\n      this.handlePaste();\n    else if (e.keyCode == 88)\n      this.handleCut();\n    return true;\n  },\n\n  handleCopy: function(e) {},\n\n  // Inserts a temporary placeholder for the current range and removes\n  // the contents of the ice element body and calls a paste handler.\n  handlePaste: function(e) {\n\n    var range = this._ice.getCurrentRange();\n\n    if (!range.collapsed) {\n      if (this._ice.isTracking) {\n        this._ice.deleteContents();\n        range = range.cloneRange();\n      } else {\n        range.deleteContents();\n        range.collapse(true);\n      }\n    }\n\n    if (this._ice.isTracking)\n      this._ice._moveRangeToValidTrackingPos(range);\n\n    if (range.startContainer == this._ice.element) {\n      // Fix a potentially empty body with a bad selection\n      var firstBlock = ice.dom.find(this._ice.element, this._ice.blockEl)[0];\n      if(!firstBlock) {\n        firstBlock = ice.dom.create('<' + this._ice.blockEl + ' ><br/></' + this._ice.blockEl + '>');\n        this._ice.element.appendChild(firstBlock);\n      }\n      range.setStart(firstBlock, 0);\n      range.collapse(true);\n      this._ice.env.selection.addRange(range);\n    }\n\n    this._tmpNode = this._ice.env.document.createElement(this._tmpNodeTagName);\n    range.insertNode(this._tmpNode);\n\n    switch (this.pasteType) {\n      case 'formatted':\n        this.setupPaste();\n        break;\n      case 'formattedClean':\n        this.setupPaste(true);\n        break;\n    }\n             \n    return true;\n  },\n\n  // Create a temporary div and set focus to it so that the browser can paste into it.\n  // Set a timeout to push a paste handler on to the end of the execution stack.\n  setupPaste: function(stripTags) {\n    var div = this.createDiv(this._pasteId),\n        self = this,\n        range = this._ice.getCurrentRange();\n    \n    range.selectNodeContents(div);\n    this._ice.selection.addRange(range);\n\n    div.onpaste = function(event) {\n      setTimeout(function(){\n        self.handlePasteValue(stripTags);\n      },0);\n       event.stopPropagation();\n    };\n\n    div.focus();\n    return true;\n  },\n\n  // By the time we get here, the pasted content will already be in the body. Extract the\n  // paste, format it, remove any Microsoft or extraneous tags outside of `this.preserve`\n  // and merge the pasted content into the original fragment body.\n  handlePasteValue: function(stripTags) {\n    // Get the pasted content.\n    var doc = this._ice.env.document,\n        pasteDiv = doc.getElementById(this._pasteId),\n        html = ice.dom.getHtml(pasteDiv),\n        childBlocks = ice.dom.children('<div>' + html + '</div>', this._ice.blockEl);\n    if(childBlocks.length === 1 && ice.dom.getNodeTextContent('<div>' + html + '</div>') === ice.dom.getNodeTextContent(childBlocks)) {\n      html = ice.dom.getHtml(html);\n    }\n\n    html = this.beforePasteClean.call(this, html);\n\n    if(stripTags) {\n                    \n      // Strip out change tracking tags.\n      html = this._ice.getCleanContent(html);\n      html = this.stripPaste(html);\n    }\n\n    html = this.afterPasteClean.call(this, html);\n    html = ice.dom.trim(html);\n    var range = this._ice.getCurrentRange();\n    range.setStartAfter(this._tmpNode);\n    range.collapse(true);\n\n    var innerBlock = null, lastEl = null, newEl = null;\n    var fragment = range.createContextualFragment(html);\n    var changeid = this._ice.startBatchChange();\n\n    // If fragment contains block level elements, most likely we will need to\n    // do some splitting so we do not have P tags in P tags, etc. Split the\n    // container from current selection and then insert paste contents after it.\n    if(ice.dom.hasBlockChildren(fragment)) {\n      // Split from current selection.\n      var block = ice.dom.isChildOfTagName(this._tmpNode, this._ice.blockEl);\n      range.setEndAfter(block.lastChild);\n      this._ice.selection.addRange(range);\n      var contents = range.extractContents();\n      var newblock = doc.createElement(this._ice.blockEl);\n      newblock.appendChild(contents);\n      ice.dom.insertAfter(block, newblock);\n\n      range.setStart(newblock, 0);\n      range.collapse(true);\n      this._ice.selection.addRange(range);\n      var prevBlock = range.startContainer;\n      \n      // Paste all of the children in the fragment.\n      while(fragment.firstChild) {\n        if(fragment.firstChild.nodeType === 3 && !jQuery.trim(fragment.firstChild.nodeValue)) {\n          fragment.removeChild(fragment.firstChild);\n          continue;\n        }\n        // We may have blocks with text nodes at the beginning or end. For example, this paste:\n        //  textnode <p>blocktext</p> <p>blocktext</p> moretext\n        // In which case we wrap the leading or trailing text nodes in blocks.\n        if(ice.dom.isBlockElement(fragment.firstChild)) {\n          if(fragment.firstChild.textContent !== \"\") {\n            innerBlock = null;\n            var insert = null;\n            if(this._ice.isTracking) {\n              insert = this._ice.createIceNode('insertType');\n              this._ice.addChange('insertType', [insert]);\n              newEl = doc.createElement(fragment.firstChild.tagName);\n              insert.innerHTML = fragment.firstChild.innerHTML;\n              newEl.appendChild(insert);\n            } else {\n              insert = newEl = doc.createElement(fragment.firstChild.tagName);\n              newEl.innerHTML = fragment.firstChild.innerHTML;\n            }\n            lastEl = insert;\n            ice.dom.insertBefore(prevBlock, newEl);\n          }\n          fragment.removeChild(fragment.firstChild);\n        } else {\n          if(!innerBlock) {\n            // Create a new block and append an insert\n            newEl = doc.createElement(this._ice.blockEl);\n            ice.dom.insertBefore(prevBlock, newEl);\n            if(this._ice.isTracking) {\n              innerBlock = this._ice.createIceNode('insertType');\n              this._ice.addChange('insertType', [innerBlock]);\n              newEl.appendChild(innerBlock);\n            } else {\n              innerBlock = newEl;\n            }\n          }\n          lastEl = innerBlock;\n          innerBlock.appendChild(fragment.removeChild(fragment.firstChild));\n        }\n      }\n      if (!newblock.textContent) {\n        newblock.parentNode.removeChild(newblock);\n      }\n\n    } else {\n      if(this._ice.isTracking) {\n        newEl = this._ice.createIceNode('insertType', fragment);\n        this._ice.addChange('insertType', [newEl]);\n        range.insertNode(newEl);\n        lastEl = newEl;\n      } else {\n        var child;\n        while((child = fragment.firstChild)) {\n          range.insertNode(child);\n          range.setStartAfter(child);\n          range.collapse(true);\n          lastEl = child;\n        }\n      }\n    }\n    this._ice.endBatchChange(changeid);\n    pasteDiv.parentNode.removeChild(pasteDiv);\n    this._cleanup(lastEl);\n  },\n\n\n  createDiv: function(id) {\n    var doc = this._ice.env.document, // Document object of window or tinyMCE iframe\n        oldEl = doc.getElementById(id);\n    if(oldEl) {\n      ice.dom.remove(oldEl);\n    }\n\n    var div = doc.createElement('div');\n    div.id = id;\n    div.setAttribute('contentEditable', true);\n    ice.dom.setStyle(div, 'width', '1px');\n    ice.dom.setStyle(div, 'height', '1px');\n    ice.dom.setStyle(div, 'overflow', 'hidden');\n    ice.dom.setStyle(div, 'position', 'fixed');\n    ice.dom.setStyle(div, 'top', '10px');\n    ice.dom.setStyle(div, 'left', '10px');\n\n    div.appendChild(doc.createElement('br'));\n    doc.body.appendChild(div);\n    return div;\n  },\n\n  // Intercepts cut operation and handles by creating an editable div, copying the current selection\n  // into it, deleting the current selection with track changes, and selecting the contents in the\n  // editable div.\n  handleCut: function() {\n    var self = this,\n        range = this._ice.getCurrentRange();\n    if (range.collapsed) return; // If nothing is selected, there's nothing to mark deleted\n\n    this.cutElement = this.createDiv('icecut');\n    // Chrome strips out spaces between text nodes and elements node during cut\n    this.cutElement.innerHTML = range.getHTMLContents().replace(/ </g, '&nbsp;<').replace(/> /g, '>&nbsp;');\n\n    if (this._ice.isTracking) this._ice.deleteContents();\n    else range.deleteContents();\n\n    var crange = this._ice.env.document.createRange();\n    crange.setStart(this.cutElement.firstChild, 0);\n    crange.setEndAfter(this.cutElement.lastChild);\n\n    setTimeout(function() {\n      self.cutElement.focus();\n\n      // After the browser cuts out of the `cutElement`, reset the range and remove the cut element.\n      setTimeout(function() {\n        ice.dom.remove(self.cutElement);\n        range.setStart(range.startContainer, range.startOffset);\n        range.collapse(false);\n        self._ice.env.selection.addRange(range);\n      }, 100);\n    }, 0);\n    \n    self._ice.env.selection.addRange(crange);\n  },\n\n\n  // Strips ice change tracking tags, Microsoft Word styling/content, and any\n  // tags and attributes not found in `preserve` from the given `content`.\n  stripPaste: function(content) {\n    // Clean word stuff out and strip tags that are not in `this.preserve`.\n    content = this._cleanWordPaste(content);\n    content = this.cleanPreserved(content);\n    return content;\n  },\n\n  // Parses `preserve` to setup `_tags` with a comma delimited list of all of the\n  // defined tags, and the `_attributesMap` with a mapping between the allowed tags and\n  // an array of their allowed attributes. For example, given this value:\n  //   `preserve` = 'p,a[href|class],span[*]'\n  // The following will result:\n  //   `_tags` = 'p,a,span'\n  //   `_attributesMap` = ['p' => [], 'a' => ['href', 'class'], 'span' => ['*']]\n  setupPreserved: function() {\n    var self = this;\n    this._tags = '';\n    this._attributesMap = [];\n    \n    ice.dom.each(this.preserve.split(','), function(i, tagAttr) {\n      // Extract the tag and attributes list\n      tagAttr.match(/(\\w+)(\\[(.+)\\])?/);\n      var tag = RegExp.$1;\n      var attr = RegExp.$3;\n\n      if(self._tags) self._tags += ',';\n      self._tags += tag.toLowerCase();\n      self._attributesMap[tag] = attr.split('|');\n    });\n  },\n\n  // Cleans the given `body` by removing any tags not found in `_tags` and replacing them with\n  // their inner contents, and removes attributes from any tags that aren't mapped in `_attributesMap`.\n  cleanPreserved: function(body) {\n    var self = this;\n    var bodyel = this._ice.env.document.createElement('div');\n    bodyel.innerHTML = body;\n\n    // Strip out any tags not found in `this._tags`, replacing the tags with their inner contents.\n    bodyel = ice.dom.stripEnclosingTags(bodyel, this._tags);\n\n    // Strip out any attributes from the allowed set of tags that don't match what is in the `_attributesMap`\n    ice.dom.each(ice.dom.find(bodyel, this._tags), function(i, el) {\n      if (ice.dom.hasClass(el, 'skip-clean')) {\n        return true;\n      }\n      var tag = el.tagName.toLowerCase();\n      var attrMatches = self._attributesMap[tag];\n\n      // Kleene star - keep all of the attributes for this tag.\n      if(attrMatches[0] && attrMatches[0] === '*')\n        return true;\n\n      // Remove any foreign attributes that do not match the map.\n      if(el.hasAttributes()) {\n        var attributes = el.attributes;\n        for(var i = attributes.length - 1; i >= 0; i--) {\n          if(!ice.dom.inArray(attributes[i].name, attrMatches)) {\n            el.removeAttribute(attributes[i].name);\n          }\n        }\n      }\n    });\n    return bodyel.innerHTML;\n  },\n\n  _cleanWordPaste: function(content) {\n    // Meta and link tags.\n    content = content.replace(/<(meta|link)[^>]+>/g, \"\");\n\n    // Comments.\n    content = content.replace(/<!--(.|\\s)*?-->/g, '');\n\n    // Remove style tags.\n    content = content.replace(/<style>[\\s\\S]*?<\\/style>/g, '');\n\n    // Remove span and o:p etc. tags.\n    //content = content.replace(/<\\/?span[^>]*>/gi, \"\");\n    content = content.replace(/<\\/?\\w+:[^>]*>/gi, '' );\n\n    // Remove XML tags.\n    content = content.replace(/<\\\\?\\?xml[^>]*>/gi, '');\n\n    // Generic cleanup.\n    content = this._cleanPaste(content);\n\n    // Remove class, lang and style attributes.\n    content = content.replace(/<(\\w[^>]*) (lang)=([^ |>]*)([^>]*)/gi, \"<$1$4\");\n  \n    return content;\n  },\n\n  _cleanPaste: function(content) {\n    // Some generic content cleanup. Change all b/i tags to strong/em.\n    content = content.replace(/<b(\\s+|>)/g, \"<strong$1\");\n    content = content.replace(/<\\/b(\\s+|>)/g, \"</strong$1\");\n    content = content.replace(/<i(\\s+|>)/g, \"<em$1\");\n    content = content.replace(/<\\/i(\\s+|>)/g, \"</em$1\");\n    return content;\n  },\n\n  _cleanup: function(moveTo) {\n    try {\n      // Set focus back to ice element.\n      if (this._ice.env.frame)\n        this._ice.env.frame.contentWindow.focus();\n      else\n        this._ice.element.focus();\n\n      moveTo = moveTo && moveTo.lastChild || moveTo || this._tmpNode;\n      // Move the range to the end of moveTo so that the cursor will be at the end of the paste.\n      var range = this._ice.getCurrentRange();\n      range.setStartAfter(moveTo);\n      range.collapse(true);\n      this._ice.selection.addRange(range);\n      \n      // Kill the tmp node.\n      this._tmpNode.parentNode.removeChild(this._tmpNode);\n      this._tmpNode = null;\n      // Kill any empty change nodes.\n      var ins = this._ice.env.document.getElementsByClassName(this._ice.changeTypes['insertType'].alias);\n      for(var i = 0; i < ins.length; i++) {\n        if(!ins[i].textContent) {\n          if(ins[i].parentNode) {\n            ins[i].parentNode.removeChild(ins[i]);\n          }\n        }\n      }\n    } catch(e) {\n      window.console && console.error(e);\n    }\n  }\n};\n\nice.dom.noInclusionInherits(IceCopyPastePlugin, ice.IcePlugin);\nexports._plugin.IceCopyPastePlugin = IceCopyPastePlugin;\n\n}).call(this.ice);\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/plugins/IceCopyPastePlugin/IceCopyPastePlugin.js\n// module id = 11\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function() {\n\nvar exports = this;\n\n/**\n * When active, this plugin will convert two successively typed dashes, within\n * the ice block element, into an emdash.\n */\nvar IceEmdashPlugin = function(ice_instance) {\n\tthis._ice = ice_instance;\n};\n\nIceEmdashPlugin.prototype = {\n\n\tkeyDown: function(e) {\n\t\t// Catch dashes.\n\t\tif (ice.dom.isBrowser('mozilla')) {\n      var version = parseInt(ice.dom.browser().version);\n      if ((version > 14 && e.keyCode === 173) || (version <= 14 && e.keyCode === 109)) {\n        return this.convertEmdash(e);\n      }\n\t\t} else if (e.keyCode === 189) {\n\t\t\treturn this.convertEmdash(e);\n\t\t}\n\t\treturn true;\n\t},\n\n\tconvertEmdash: function(e) {\n\t\tvar range = this._ice.getCurrentRange();\n\t\tif(range.collapsed) {\n\t\t\ttry {\n\t\t\t\t// Move the start back one character so we can enclose the range around the previous character to check if it is a dash\n\t\t\t\trange.moveStart(ice.dom.CHARACTER_UNIT, -1);\n\t\t\t\t// Get the parent block element for the start and end containers\n\t\t\t\tvar startBlock = ice.dom.getParents(range.startContainer, this._ice.blockEl)[0];\n\t\t\t\tvar endBlock = ice.dom.getParents(range.endContainer, this._ice.blockEl)[0];\n\t\t\t\t// Make sure that the start and end containers aren't in different blocks, or that the start isn't in a delete.\n\t\t\t\tif(startBlock === endBlock && !this._ice.getIceNode(range.startContainer, 'deleteType')) {\n\t\t\t\t\t// Get the last character and check to see if it is a dash.\n\t\t\t\t\tvar c = range.toHtml();\n\t\t\t\t\tif(c === '-') {\n\t\t\t\t\t\t// Extract the last character/dash and insert an emdash\n\t\t\t\t\t\trange.extractContents();\n\t\t\t\t\t\trange.collapse();\n\t\t\t\t\t\tvar mdash = this._ice.env.document.createTextNode('\\u2014');\n\t\t\t\t\t\tif (this._ice.isTracking) {\n\t\t\t\t\t\t\tthis._ice._insertNode(mdash, range);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trange.insertNode(mdash);\n\t\t\t\t\t\t\trange.setStart(mdash, 1);\n\t\t\t\t\t\t\trange.collapse(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis._ice._preventKeyPress = true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch(e) {}\n\t\t\trange.collapse();\n\t\t}\n\t\treturn true;\n\t}\n\n};\n\nice.dom.noInclusionInherits(IceEmdashPlugin, ice.IcePlugin);\nexports._plugin.IceEmdashPlugin = IceEmdashPlugin;\n\n}).call(this.ice);\n\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/plugins/IceEmdashPlugin/IceEmdashPlugin.js\n// module id = 12\n// module chunks = 0","/*** IMPORTS FROM imports-loader ***/\n(function() {\nvar ice = window.ice;\n\n(function() {\n\nvar exports = this, ice = this.ice;\n\nvar IceSmartQuotesPlugin = function(ice_instance) {\n  this._ice = ice_instance;\n};\n\nIceSmartQuotesPlugin.prototype = {\n\n  /**\n   * Finds each block in `element` and converts quotes into smart quotes.\n   */\n  convert: function(element) {\n    var self = this;\n    try {\n      self._ice.placeholdDeletes();\n      ice.dom.each(element.getElementsByTagName(this._ice.blockEl), function(i, el) {\n        self._convertBlock(el);\n      });\n    } catch(e) {\n      window.console && console.error(e);\n    } finally {\n      self._ice.revertDeletePlaceholders();\n    }\n  },\n  \n  // Converts the quotes in the given element to smart quotes.\n  _convertBlock: function(el) {\n\n    // If there are less than 2 characters, we don't have enough to go on.\n    if (ice.dom.getNodeTextContent(el) < 2) return;\n\n    var previous, current, next, data, html = '', getNextChar,\n      regularSingle = \"'\",\n      regularDouble = '\"',\n      smartSingleLeft = String.fromCharCode(8216),  // aka - open curly single quote\n      smartSingleRight = String.fromCharCode(8217),   // aka - close curly single quote\n      smartDoubleLeft = String.fromCharCode(8220),  // aka - open curly double quote\n      smartDoubleRight = String.fromCharCode(8221),   // aka - close curly double quote\n      isDigit = function(c) { return /\\d/.test(c); },\n      isChar = function(c) { return /\\w/.test(c); },\n      isSpace = function(c) { return c === String.fromCharCode(160) || c === String.fromCharCode(32); },\n      isStartChar = function(c) { return isSpace(c) || c === '('; },\n      isEndChar = function(c) { return isSpace(c) || c == null || c === ';' || c === ')' || c == '.' || c === '!' || c === ',' || c === '?' || c === ':'; },\n      isNonSpace = function(c) { return !isSpace(c); },\n      isDouble = function(c) { return c === regularDouble || c === smartDoubleLeft || c === smartDoubleRight; },\n      isSingle = function(c) { return c === regularSingle || c === smartSingleLeft || c === smartSingleRight; };\n\n    // Split the html into array allocations with the following criteria:\n    //   html tags: starts with \"<\" and ends with \">\"\n    //   html entities: starts with \"&\" and ends with \";\"\n    //   characters: any character outside of an html tag or entity\n    // So the following html:\n    //   n&ce <b id=\"bold\">test</b>\n    // Would split into the following array:\n    //  ['n', '&amp;', 'c', 'e', ' ', '<b id=\"bold\">', 't', 'e', 's', 't', '</b>'];\n    data = ice.dom.getHtml(el).match(/(<(\"[^\"]*\"|'[^']*'|[^'\">])*>|&.*;|.)/g);\n\n    // Searches through the `data` array from the given index a given number of\n    // characters forward or backward and returns the found character.\n    getNextChar = function(data, fromIndex, nCharacters) {\n      var dLength = data.length,\n        addWith = nCharacters < 0 ? -1 : 1;\n    \n      return (function getChar(data, fromIndex, nCharacters) {\n        // Base case - did we move outside of the bounds of the data array?\n        if (fromIndex < 0 || fromIndex >= dLength) return null;\n        \n        var next = data[fromIndex + addWith];\n\n        // If we find a character and we have moved through the\n        // nCharacters, then the recursion is done.\n        if (next && next.length == 1) {\n          nCharacters += (addWith * -1);\n          if (!nCharacters) return next;\n        }\n        return getChar(data, fromIndex + addWith, nCharacters);\n\n      })(data, fromIndex, nCharacters);\n    };\n\n    ice.dom.each(data, function(pos, val) {\n      // Convert space entities so that they can be processed as normal characters.\n      if (val == '&nbsp;') val = data[pos] = ' ';\n\n      // If the val is a character, then examine the surroundings\n      // and convert smart quotes, if necessary.\n      if (val.length == 1) {\n        \n        // Keep convenience pointers to the previous, current and next characters.\n        previous = getNextChar(data, pos, -1);\n        current = val;\n        next = getNextChar(data, pos, 1);\n\n        switch (current) {\n          \n          /**\n           * Conversion Rules:\n           * ----------------\n           * \n           * START: assign smart left/open\n           *   [SPACE|START_PARENTHESIS]'word\n           *   [SPACE|START_PARENTHESIS]\"word\n           * \n           * END: assign smart right/close\n           *   word'[SPACE|SEMICOLON|COLON|PERIOD|COMMA|EXCLAMATION_MARK|QUESTION_MARK|END_PARENTHESIS|NULL]\n           *   word\"[SPACE|SEMICOLON|COLON|PERIOD|COMMA|EXCLAMATION_MARK|QUESTION_MARK|END_PARENTHESIS|NULL]\n           * \n           * PLURAL_CONTRACTION: assign smart right/close\n           *   Matt's\n           *   can't\n           *   O'Reilly\n           * \n           * YEAR_ABBREVIATION: assign smart right/close\n           *   [SPACE|NULL]'99[SPACE|SEMICOLON|COLON|PERIOD|COMMA|EXCLAMATION_MARK|QUESTION_MARK|END_PARENTHESIS|NULL]\n           * \n           * NESTED_START: assign smart left/open\n           *   [SPACE|NULL]\"[SPACE]'word\n           * \n           * NESTED_END: assign smart left/open\n           *   word'[SPACE]\"[SPACE|SEMICOLON|COLON|PERIOD|COMMA|EXCLAMATION_MARK|QUESTION_MARK|END_PARENTHESIS|NULL]\n           * \n           * Notes:\n           *  - The following will not be converted correctly - ...word 'Til Death - it should\n           *  get a right/close smart quote, but will get a left/open.\n           *  - Distinguishing between year abbreviation, '99, and when to use an open single quote\n           *  could fail if a single quoted region starts with a double digit number - '99 problems'\n           *  - Since they are a rare case and there are many permutations, measurements are not being\n           *  handled (6'8\", 6' 8\", 6', 8\").\n           */\n\n          // Convert smart single quotes to non-smart quote and fall through to single quote \n          // handling, in case the context has changed and we need to update the smart quote.\n          case smartSingleLeft:\n          case smartSingleRight:\n            current = regularSingle;\n          case regularSingle:\n            // YEAR_ABBREVIATION - look 2 ahead to see if there are two digits in a row - not fool proof\n            if ((previous == null || isSpace(previous)) && isDigit(next) && isDigit(getNextChar(data, pos, 2)) && isEndChar(getNextChar(data, pos, 3)))\n              current = smartSingleRight;\n            // START\n            else if (previous == null || (isStartChar(previous) && isNonSpace(next)))\n              current = smartSingleLeft;\n            // END\n            else if (next == null || (isNonSpace(previous) && isEndChar(next)))\n              current = smartSingleRight;\n            // PLURAL_CONTRACTION\n            else if (isChar(previous) && isChar(next))\n              current = smartSingleRight;\n            break;\n          \n          // Convert smart double quotes to non-smart quote and fall through to double quote \n          // handling, in case the context has changed and we need to update the smart quote.\n          case smartDoubleLeft:\n          case smartDoubleRight:\n            current = regularDouble;\n          case regularDouble:\n            // NESTED_END\n            if (isEndChar(next) && isSpace(previous) && isSingle(getNextChar(data, pos, -2)))\n              current = smartDoubleRight;\n            // START\n            else if (previous == null || (isStartChar(previous) && isNonSpace(next)))\n              current = smartDoubleLeft;\n            // END\n            else if (next == null || (isNonSpace(previous) && isEndChar(next)))\n              current = smartDoubleRight;\n            // NESTED_START\n            else if ((previous == null || isSpace(previous)) && (isSpace(next) && isSingle(getNextChar(data, pos, 1))))\n              current = smartDoubleLeft;\n            break;\n        }\n        if (current != null) data[pos] = current;\n      }\n    });\n    \n    ice.dom.setHtml(el, data.join(''));\n  }\n};\n\nice.dom.noInclusionInherits(IceSmartQuotesPlugin, ice.IcePlugin);\nexports.ice._plugin.IceSmartQuotesPlugin = IceSmartQuotesPlugin;\n\n}).call(this);\n}.call(window));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/plugins/IceSmartQuotesPlugin/IceSmartQuotesPlugin.js\n// module id = 13\n// module chunks = 0"]}