app/assets/source/tinymce/tinymce.jquery.js in tinymce-rails-4.0.7 vs app/assets/source/tinymce/tinymce.jquery.js in tinymce-rails-4.0.8

- old
+ new

@@ -1,6 +1,6 @@ -// 4.0.7 (2013-10-02) +// 4.0.8 (2013-10-10) /** * Compiled inline version. (Library mode) */ @@ -200,10 +200,16 @@ var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope || this; function compress(prefix, suffix) { var top, right, bottom, left; + // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p> + // So lets asume it shouldn't be there + if (styles['border-image'] === 'none') { + delete styles['border-image']; + } + // Get values and check it it needs compressing top = styles[prefix + '-top' + suffix]; if (!top) { return; } @@ -626,13 +632,13 @@ * @private * @param {Event} evt Event object. * @param {String} id Expando id value to look for. */ function executeHandlers(evt, id) { - var callbackList, i, l, callback; + var callbackList, i, l, callback, container = events[id]; - callbackList = events[id][evt.type]; + callbackList = container && container[evt.type]; if (callbackList) { for (i = 0, l = callbackList.length; i < l; i++) { callback = callbackList[i]; // Check if callback exists might be removed if a unbind is called inside the callback @@ -13632,12 +13638,13 @@ dom.insertAfter(caretContainer, formatNode); } // Move selection to text node selection.setCursorLocation(node, 1); + // If the formatNode is empty, we can remove it safely. - if(dom.isEmpty(formatNode)) { + if (dom.isEmpty(formatNode)) { dom.remove(formatNode); } } } @@ -14688,10 +14695,14 @@ addBrToBlockIfNeeded(parentBlock); moveToCaretPosition(newBlock); } dom.setAttrib(newBlock, 'id', ''); // Remove ID since it needs to be document unique + + // Allow custom handling of new blocks + editor.fire('NewBlock', { newBlock: newBlock }); + undoManager.add(); } editor.on('keydown', function(evt) { if (evt.keyCode == 13) { @@ -16876,11 +16887,23 @@ getWindowSize: function() { return DOMUtils.DOM.getViewPort(); }, getSize: function(elm) { - return DOMUtils.DOM.getSize(elm); + var width, height; + + if (elm.getBoundingClientRect) { + var rect = elm.getBoundingClientRect(); + + width = Math.max(rect.width || (rect.right - rect.left), elm.offsetWidth); + height = Math.max(rect.height || (rect.bottom - rect.bottom), elm.offsetHeight); + } else { + width = elm.offsetWidth; + height = elm.offsetHeight; + } + + return {width: width, height: height}; }, getPos: function(elm, root) { return DOMUtils.DOM.getPos(elm, root); }, @@ -16968,10 +16991,14 @@ var Control = Class.extend({ Statics: { controlIdLookup: {} }, + isRtl: function() { + return Control.rtl; + }, + /** * Class/id prefix to use for all controls. * * @final * @field {String} classPrefix @@ -17171,11 +17198,11 @@ return elm.currentStyle[name]; } function getSide(name) { - var val = parseInt(getStyle(name), 10); + var val = parseFloat(getStyle(name), 10); return isNaN(val) ? 0 : val; } return { @@ -17195,22 +17222,23 @@ * @return {Object} Layout rect instance. */ initLayoutRect: function() { var self = this, settings = self.settings, borderBox, layoutRect; var elm = self.getEl(), width, height, minWidth, minHeight, autoResize; - var startMinWidth, startMinHeight; + var startMinWidth, startMinHeight, initialSize; - // Measure boxes + // Measure the current element borderBox = self._borderBox = self._borderBox || self.measureBox(elm, 'border'); self._paddingBox = self._paddingBox || self.measureBox(elm, 'padding'); self._marginBox = self._marginBox || self.measureBox(elm, 'margin'); + initialSize = DomUtils.getSize(elm); // Setup minWidth/minHeight and width/height startMinWidth = settings.minWidth; startMinHeight = settings.minHeight; - minWidth = startMinWidth || elm.offsetWidth; - minHeight = startMinHeight || elm.offsetHeight; + minWidth = startMinWidth || initialSize.width; + minHeight = startMinHeight || initialSize.height; width = settings.width; height = settings.height; autoResize = settings.autoResize; autoResize = typeof(autoResize) != "undefined" ? autoResize : !width && !height; @@ -17625,10 +17653,21 @@ return args; }, /** + * Returns true/false if the specified event has any listeners. + * + * @method hasEventListeners + * @param {String} name Name of the event to check for. + * @return {Boolean} True/false state if the event has listeners. + */ + hasEventListeners: function(name) { + return name in this._bindings; + }, + + /** * Returns a control collection with all parent controls. * * @method parents * @param {String} selector Optional selector expression to find parents. * @return {tinymce.ui.Collection} Collection with all parent controls. @@ -18432,11 +18471,11 @@ * @param {String} value Value to set to control. * @return {String/tinymce.ui.Control} Current control on a set operation or current value on a get. */ // title: function(value) {} -- Generated }); -window.elementIdCache = elementIdCache; + return Control; }); // Included from: js/tinymce/classes/ui/Factory.js @@ -18598,10 +18637,14 @@ self._super(settings); settings = self.settings; self._fixed = settings.fixed; self._items = new Collection(); + if (self.isRtl()) { + self.addClass('rtl'); + } + self.addClass('container'); self.addClass('container-body', 'body'); if (settings.containerCls) { self.addClass(settings.containerCls); @@ -19389,11 +19432,11 @@ "tinymce/ui/DomUtils" ], function(DomUtils) { "use strict"; function calculateRelativePosition(ctrl, targetElm, rel) { - var ctrlElm, pos, x, y, selfW, selfH, targetW, targetH, viewport; + var ctrlElm, pos, x, y, selfW, selfH, targetW, targetH, viewport, size; viewport = DomUtils.getViewPort(); // Get pos of target pos = DomUtils.getPos(targetElm); @@ -19405,16 +19448,18 @@ y -= viewport.y; } // Get size of self ctrlElm = ctrl.getEl(); - selfW = ctrlElm.offsetWidth; - selfH = ctrlElm.offsetHeight; + size = DomUtils.getSize(ctrlElm); + selfW = size.width; + selfH = size.height; // Get size of target - targetW = targetElm.offsetWidth; - targetH = targetElm.offsetHeight; + size = DomUtils.getSize(targetElm); + targetW = size.width; + targetH = size.height; // Parse align string rel = (rel || '').split(''); // Target corners @@ -19867,11 +19912,11 @@ }); }); if (settings.popover) { self._preBodyHtml = '<div class="' + self.classPrefix + 'arrow"></div>'; - self.addClass('popover').addClass('bottom').addClass('start'); + self.addClass('popover').addClass('bottom').addClass(self.isRtl() ? 'end' : 'start'); } }, fixed: function(state) { var self = this; @@ -20399,10 +20444,14 @@ init: function(settings) { var self = this; self._super(settings); + if (self.isRtl()) { + self.addClass('rtl'); + } + self.addClass('window'); self._fixed = true; // Create statusbar if (settings.buttons) { @@ -20410,11 +20459,11 @@ layout: 'flex', border: '1 0 0 0', spacing: 3, padding: 10, align: 'center', - pack: 'end', + pack: self.isRtl() ? 'start' : 'end', defaults: { type: 'button' }, items: settings.buttons }); @@ -20489,12 +20538,16 @@ var self = this, layoutRect = self._super(), deltaH = 0, headEl; // Reserve vertical space for title if (self.settings.title && !self._fullscreen) { headEl = self.getEl('head'); - layoutRect.headerW = headEl.offsetWidth; - layoutRect.headerH = headEl.offsetHeight; + + var size = DomUtils.getSize(headEl); + + layoutRect.headerW = size.width; + layoutRect.headerH = size.height; + deltaH += layoutRect.headerH; } // Reserve vertical space for statusbar if (self.statusbar) { @@ -22105,10 +22158,11 @@ editor.contentStyles.push('body {min-height: 150px}'); editor.on('click', function(e) { if (e.target.nodeName == 'HTML') { editor.execCommand('SelectAll'); editor.selection.collapse(true); + editor.nodeChanged(); } }); } } @@ -22993,10 +23047,11 @@ */ init: function() { var self = this, settings = self.settings, elm = self.getElement(); var w, h, minHeight, n, o, url, bodyId, bodyClass, re, i, initializedPlugins = []; + self.rtl = this.editorManager.i18n.rtl; self.editorManager.add(self); settings.aria_label = settings.aria_label || DOM.getAttrib(elm, 'aria-label', self.getLang('aria.rich_text_area')); /** @@ -24268,12 +24323,21 @@ } // Move selection to start of body if it's a after init setContent call // This prevents IE 7/8 from moving focus to empty editors if (!args.initial) { - self.selection.select(body, true); - self.selection.collapse(true); + var dom = self.dom, selection = self.selection; + + // IE can't have the caret inside <body><p>|</p></body> unless we do some magic + if (ie < 11 && dom.isBlock(body.firstChild) && dom.isEmpty(body.firstChild)) { + body.firstChild.appendChild(dom.doc.createTextNode('\u00a0')); + selection.select(body.firstChild, true); + dom.remove(body.firstChild.lastChild); + } else { + selection.select(body, true); + selection.collapse(true); + } } return args.content; }, @@ -24579,10 +24643,14 @@ }, bindNative: function(name) { var self = this; + if (self.settings.readonly) { + return; + } + if (self.initialized) { self.dom.bind(getEventTarget(self, name), name, function(e) { self.fire(name, e); }); } else { @@ -24724,20 +24792,30 @@ var data = {}; return { /** + * Property gets set to true if a RTL language pack was loaded. + * + * @property rtl + * @type {Boolean} + */ + rtl: false, + + /** * Adds translations for a specific language code. * * @method add * @param {String} code Language code like sv_SE. * @param {Array} items Name/value array with English en_US to sv_SE. */ add: function(code, items) { for (var name in items) { data[name] = items[name]; } + + this.rtl = this.rtl || data._dir === 'rtl'; }, /** * Translates the specified text. * @@ -25025,19 +25103,19 @@ * Minor version of TinyMCE build. * * @property minorVersion * @type String */ - minorVersion : '0.7', + minorVersion : '0.8', /** * Release date of TinyMCE build. * * @property releaseDate * @type String */ - releaseDate: '2013-10-02', + releaseDate: '2013-10-10', /** * Collection of editor instances. * * @property editors @@ -26790,11 +26868,11 @@ return ( '<div id="' + id + '" class="' + self.classes() + '" tabindex="-1">' + '<button role="presentation" type="button" tabindex="-1">' + (icon ? '<i class="' + icon + '"' + image + '></i>' : '') + - (self._text ? (icon ? ' ' : '') + self.encode(self._text) : '') + + (self._text ? (icon ? '\u00a0' : '') + self.encode(self._text) : '') + '</button>' + '</div>' ); } }); @@ -27044,11 +27122,11 @@ self.panel.reflow(); } else { self.panel.show(); } - self.panel.moveRel(self.getEl(), settings.popoverAlign || ['bc-tl', 'bc-tc']); + self.panel.moveRel(self.getEl(), settings.popoverAlign || (self.isRtl() ? ['bc-tr', 'bc-tc'] : ['bc-tl', 'bc-tc'])); }, /** * Hides the panel for the button. * @@ -27248,12 +27326,12 @@ if (e.target.nodeName == "INPUT" && e.keyCode == 13) { self.parents().reverse().each(function(ctrl) { e.preventDefault(); self.fire('change'); - if (ctrl.submit) { - ctrl.submit(); + if (ctrl.hasEventListeners('submit') && ctrl.toJSON) { + ctrl.fire('submit', {data: ctrl.toJSON()}); return false; } }); } }); @@ -27353,11 +27431,11 @@ repaint: function() { var self = this, elm = self.getEl(), openElm = self.getEl('open'), rect = self.layoutRect(); var width, lineHeight; if (openElm) { - width = rect.w - openElm.offsetWidth - 10; + width = rect.w - DomUtils.getSize(openElm).width - 10; } else { width = rect.w - 10; } // Detect old IE 7+8 add lineHeight to align caret vertically in the middle @@ -27450,33 +27528,33 @@ /** * Creates a new path control. * * @-x-less Path.less * @class tinymce.ui.Path - * @extends tinymce.ui.Control + * @extends tinymce.ui.Widget */ define("tinymce/ui/Path", [ - "tinymce/ui/Control", + "tinymce/ui/Widget", "tinymce/ui/KeyboardNavigation" -], function(Control, KeyboardNavigation) { +], function(Widget, KeyboardNavigation) { "use strict"; - return Control.extend({ - Defaults: { - delimiter: "\u00BB" - }, - + return Widget.extend({ /** * Constructs a instance with the specified settings. * * @constructor * @param {Object} settings Name/value object with settings. * @setting {String} delimiter Delimiter to display between items in path. */ init: function(settings) { var self = this; + if (!settings.delimiter) { + settings.delimiter = '\u00BB'; + } + self._super(settings); self.addClass('path'); self.canFocus = true; self.on('click', function(e) { @@ -27556,11 +27634,11 @@ */ renderHtml: function() { var self = this; return ( - '<div id="' + self._id + '" class="' + self.classPrefix + 'path">' + + '<div id="' + self._id + '" class="' + self.classes() + '">' + self._getPathHtml() + '</div>' ); }, @@ -27761,11 +27839,16 @@ direction: 'column', align: 'stretch', flex: 1, padding: 20, labelGap: 30, - spacing: 10 + spacing: 10, + callbacks: { + submit: function() { + this.submit(); + } + } }, /** * This method gets invoked before the control is rendered. * @@ -28086,13 +28169,13 @@ // Get container items, properties and settings items = container.items().filter(':visible'); contLayoutRect = container.layoutRect(); contPaddingBox = container._paddingBox; contSettings = container.settings; - direction = contSettings.direction; + direction = container.isRtl() ? (contSettings.direction || 'row-reversed') : contSettings.direction; align = contSettings.align; - pack = contSettings.pack; + pack = container.isRtl() ? (contSettings.pack || 'end') : contSettings.pack; spacing = contSettings.spacing || 0; if (direction == "row-reversed" || direction == "column-reverse") { items = items.set(items.toArray().reverse()); direction = direction.split('-')[0]; @@ -28364,10 +28447,14 @@ "tinymce/Env" ], function(Control, Widget, FloatPanel, Tools, EditorManager, Env) { var each = Tools.each; EditorManager.on('AddEditor', function(e) { + if (e.editor.rtl) { + Control.rtl = true; + } + registerControls(e.editor); }); Control.translate = function(text) { return EditorManager.translate(text); @@ -29311,12 +29398,13 @@ * @-x-less Label.less * @class tinymce.ui.Label * @extends tinymce.ui.Widget */ define("tinymce/ui/Label", [ - "tinymce/ui/Widget" -], function(Widget) { + "tinymce/ui/Widget", + "tinymce/ui/DomUtils" +], function(Widget, DomUtils) { "use strict"; return Widget.extend({ /** * Constructs a instance with the specified settings. @@ -29352,45 +29440,26 @@ */ initLayoutRect: function() { var self = this, layoutRect = self._super(); if (self.settings.multiline) { + var size = DomUtils.getSize(self.getEl()); + // Check if the text fits within maxW if not then try word wrapping it - if (self.getEl().offsetWidth > layoutRect.maxW) { + if (size.width > layoutRect.maxW) { layoutRect.minW = layoutRect.maxW; self.addClass('multiline'); } self.getEl().style.width = layoutRect.minW + 'px'; - layoutRect.startMinH = layoutRect.h = layoutRect.minH = Math.min(layoutRect.maxH, self.getEl().offsetHeight); + layoutRect.startMinH = layoutRect.h = layoutRect.minH = Math.min(layoutRect.maxH, DomUtils.getSize(self.getEl()).height); } return layoutRect; }, /** - * Sets/gets the disabled state on the control. - * - * @method disabled - * @param {Boolean} state Value to set to control. - * @return {Boolean/tinymce.ui.Label} Current control on a set operation or current state on a get. - */ - disabled: function(state) { - var self = this, undef; - - if (state !== undef) { - self.toggleClass('label-disabled', state); - - if (self._rendered) { - self.getEl()[0].className = self.classes(); - } - } - - return self._super(state); - }, - - /** * Repaints the control after a layout operation. * * @method repaint */ repaint: function() { @@ -29641,11 +29710,11 @@ self.aria('expanded', true); } self.menu.show(); self.menu.layoutRect({w: self.layoutRect().w}); - self.menu.moveRel(self.getEl(), ['bl-tl', 'tl-bl']); + self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']); }, /** * Hides the menu for the button. * @@ -29689,11 +29758,11 @@ return ( '<div id="' + id + '" class="' + self.classes() + '" tabindex="-1">' + '<button id="' + id + '-open" role="presentation" type="button" tabindex="-1">' + (icon ? '<i class="' + icon + '"></i>' : '') + - '<span>' + (self._text ? (icon ? ' ' : '') + self.encode(self._text) : '') + '</span>' + + '<span>' + (self._text ? (icon ? '\u00a0' : '') + self.encode(self._text) : '') + '</span>' + ' <i class="' + prefix + 'caret"></i>' + '</button>' + '</div>' ); }, @@ -30064,11 +30133,15 @@ menu._parentMenu = parent; menu.addClass('menu-sub'); - var rel = menu.testMoveRel(self.getEl(), ['tr-tl', 'br-bl', 'tl-tr', 'bl-br']); + var rel = menu.testMoveRel( + self.getEl(), + self.isRtl() ? ['tl-tr', 'bl-br', 'tr-tl', 'br-bl'] : ['tr-tl', 'br-bl', 'tl-tr', 'bl-br'] + ); + menu.moveRel(self.getEl(), rel); rel = 'menu-sub-' + rel; menu.removeClass(menu._lastRel); menu.addClass(rel); @@ -30495,14 +30568,12 @@ * @class tinymce.ui.SplitButton * @extends tinymce.ui.Button */ define("tinymce/ui/SplitButton", [ "tinymce/ui/MenuButton", - "tinymce/dom/DOMUtils" + "tinymce/ui/DomUtils" ], function(MenuButton, DomUtils) { - var DOM = DomUtils.DOM; - return MenuButton.extend({ Defaults: { classes: "widget btn splitbtn", role: "splitbutton" }, @@ -30518,16 +30589,16 @@ self._super(); mainButtonElm = elm.firstChild; menuButtonElm = elm.lastChild; - DOM.css(mainButtonElm, { - width: rect.w - menuButtonElm.offsetWidth, + DomUtils.css(mainButtonElm, { + width: rect.w - DomUtils.getSize(menuButtonElm).width, height: rect.h - 2 }); - DOM.css(menuButtonElm, { + DomUtils.css(menuButtonElm, { height: rect.h - 2 }); btnStyle = mainButtonElm.firstChild.style; btnStyle.width = btnStyle.height = "100%"; @@ -30544,11 +30615,11 @@ * @private */ activeMenu: function(state) { var self = this; - DOM.toggleClass(self.getEl().lastChild, self.classPrefix + 'active', state); + DomUtils.toggleClass(self.getEl().lastChild, self.classPrefix + 'active', state); }, /** * Renders the control as a HTML string. * @@ -30565,11 +30636,11 @@ (icon ? '<i class="' + icon + '"></i>' : '') + (self._text ? (icon ? ' ' : '') + self._text : '') + '</button>' + '<button type="button" class="' + prefix + 'open" hidefocus tabindex="-1">' + //(icon ? '<i class="' + icon + '"></i>' : '') + - (self._menuBtnText ? (icon ? ' ' : '') + self._menuBtnText : '') + + (self._menuBtnText ? (icon ? '\u00a0' : '') + self._menuBtnText : '') + ' <i class="' + prefix + 'caret"></i>' + '</button>' + '</div>' ); }, @@ -30581,13 +30652,23 @@ */ postRender: function() { var self = this, onClickHandler = self.settings.onclick; self.on('click', function(e) { - if (e.control == this && !DOM.getParent(e.target, '.' + this.classPrefix + 'open')) { - e.stopImmediatePropagation(); - onClickHandler.call(this, e); + var node = e.target; + + if (e.control == this) { + // Find clicks that is on the main button + while (node) { + if (node.nodeName == 'BUTTON' && node.className.indexOf('open') == -1) { + e.stopImmediatePropagation(); + onClickHandler.call(this, e); + return; + } + + node = node.parentNode; + } } }); delete self.settings.onclick; @@ -30759,11 +30840,11 @@ * @return {Object} Layout rect instance. */ initLayoutRect: function() { var self = this, rect, minW, minH; - minW = self.getEl('head').offsetWidth; + minW = DomUtils.getSize(self.getEl('head')).width; minW = minW < 0 ? 0 : minW; minH = 0; self.items().each(function(item, i) { minW = Math.max(minW, item.layoutRect().minW); minH = Math.max(minH, item.layoutRect().minH); @@ -30784,17 +30865,17 @@ w: minW, h: minH }); }); - var headH = self.getEl('head').offsetHeight; + var headH = DomUtils.getSize(self.getEl('head')).height; self.settings.minWidth = minW; self.settings.minHeight = minH + headH; rect = self._super(); - rect.deltaH += self.getEl('head').offsetHeight; + rect.deltaH += headH; rect.innerH = rect.h - rect.deltaH; return rect; } }); @@ -30850,11 +30931,11 @@ self.on('keydown', function(e) { if (e.keyCode == 13) { self.parents().reverse().each(function(ctrl) { e.preventDefault(); - if (ctrl.submit) { - ctrl.submit(); + if (ctrl.hasEventListeners('submit') && ctrl.toJSON) { + ctrl.fire('submit', {data: ctrl.toJSON()}); return false; } }); } }); \ No newline at end of file