tinymce-rails 4.0.26 → 4.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/app/assets/source/tinymce/tinymce.jquery.js +1111 -671
- data/app/assets/source/tinymce/tinymce.js +1108 -668
- data/lib/tinymce/rails/configuration.rb +28 -2
- data/lib/tinymce/rails/version.rb +2 -2
- data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/link/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/lists/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/spellchecker/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/visualblocks/css/visualblocks.css +7 -0
- data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.ie7.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/tinymce.jquery.js +10 -10
- data/vendor/assets/javascripts/tinymce/tinymce.js +11 -10
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3d61de30fa04cae313a1896b6cb9326acb089427
         | 
| 4 | 
            +
              data.tar.gz: c505df76105015340cc701707fda4801201756ee
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 43bd86134162aa09da12d021d390f0795a1eeaa064b4eaa7b9a3daa5ce07cca60a777ac350c9cde96d495acd094a4a116f7020067c1b71a4cf2aec8513659399
         | 
| 7 | 
            +
              data.tar.gz: cdf88d954d3b887f44a2a4f4e9834c5657a87659e9e9440a44d748dc52150957bc5d63dcb4a5cac3fe2d5543c4e930890d2870917e4e30435e46209d7c08ee0e
         | 
    
        data/README.md
    CHANGED
    
    | @@ -25,8 +25,9 @@ Be sure to add to the global group, not the `assets` group. Then run `bundle ins | |
| 25 25 | 
             
            **2. Create a `config/tinymce.yml` file with your global configuration options:**
         | 
| 26 26 |  | 
| 27 27 | 
             
            ```yml
         | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 28 | 
            +
            toolbar:
         | 
| 29 | 
            +
              - styleselect | bold italic | link image | undo redo
         | 
| 30 | 
            +
              - table | fullscreen
         | 
| 30 31 | 
             
            plugins:
         | 
| 31 32 | 
             
              - table
         | 
| 32 33 | 
             
              - fullscreen
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            // 4.0. | 
| 1 | 
            +
            // 4.0.28 (2014-05-27)
         | 
| 2 2 |  | 
| 3 3 | 
             
            /**
         | 
| 4 4 | 
             
             * Compiled inline version. (Library mode)
         | 
| @@ -146,10 +146,15 @@ define("tinymce/html/Styles", [], function() { | |
| 146 146 | 
             
            			urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,
         | 
| 147 147 | 
             
            			styleRegExp = /\s*([^:]+):\s*([^;]+);?/g,
         | 
| 148 148 | 
             
            			trimRightRegExp = /\s+$/,
         | 
| 149 | 
            -
            			undef, i, encodingLookup = {}, encodingItems, invisibleChar = '\uFEFF';
         | 
| 149 | 
            +
            			undef, i, encodingLookup = {}, encodingItems, validStyles, invalidStyles, invisibleChar = '\uFEFF';
         | 
| 150 150 |  | 
| 151 151 | 
             
            		settings = settings || {};
         | 
| 152 152 |  | 
| 153 | 
            +
            		if (schema) {
         | 
| 154 | 
            +
            			validStyles = schema.getValidStyles();
         | 
| 155 | 
            +
            			invalidStyles = schema.getInvalidStyles();
         | 
| 156 | 
            +
            		}
         | 
| 157 | 
            +
             | 
| 153 158 | 
             
            		encodingItems = ('\\" \\\' \\; \\: ; : ' + invisibleChar).split(' ');
         | 
| 154 159 | 
             
            		for (i = 0; i < encodingItems.length; i++) {
         | 
| 155 160 | 
             
            			encodingLookup[encodingItems[i]] = invisibleChar + i;
         | 
| @@ -407,16 +412,16 @@ define("tinymce/html/Styles", [], function() { | |
| 407 412 | 
             
            			 *
         | 
| 408 413 | 
             
            			 * @method serialize
         | 
| 409 414 | 
             
            			 * @param {Object} styles Object to serialize as string for example: {border: '1px solid red'}
         | 
| 410 | 
            -
            			 * @param {String}  | 
| 415 | 
            +
            			 * @param {String} elementName Optional element name, if specified only the styles that matches the schema will be serialized.
         | 
| 411 416 | 
             
            			 * @return {String} String representation of the style object for example: border: 1px solid red.
         | 
| 412 417 | 
             
            			 */
         | 
| 413 | 
            -
            			serialize: function(styles,  | 
| 418 | 
            +
            			serialize: function(styles, elementName) {
         | 
| 414 419 | 
             
            				var css = '', name, value;
         | 
| 415 420 |  | 
| 416 421 | 
             
            				function serializeStyles(name) {
         | 
| 417 422 | 
             
            					var styleList, i, l, value;
         | 
| 418 423 |  | 
| 419 | 
            -
            					styleList =  | 
| 424 | 
            +
            					styleList = validStyles[name];
         | 
| 420 425 | 
             
            					if (styleList) {
         | 
| 421 426 | 
             
            						for (i = 0, l = styleList.length; i < l; i++) {
         | 
| 422 427 | 
             
            							name = styleList[i];
         | 
| @@ -429,18 +434,36 @@ define("tinymce/html/Styles", [], function() { | |
| 429 434 | 
             
            					}
         | 
| 430 435 | 
             
            				}
         | 
| 431 436 |  | 
| 437 | 
            +
            				function isValid(name, elementName) {
         | 
| 438 | 
            +
            					var styleMap;
         | 
| 439 | 
            +
             | 
| 440 | 
            +
            					styleMap = invalidStyles['*'];
         | 
| 441 | 
            +
            					if (styleMap && styleMap[name]) {
         | 
| 442 | 
            +
            						return false;
         | 
| 443 | 
            +
            					}
         | 
| 444 | 
            +
             | 
| 445 | 
            +
            					styleMap = invalidStyles[elementName];
         | 
| 446 | 
            +
            					if (styleMap && styleMap[name]) {
         | 
| 447 | 
            +
            						return false;
         | 
| 448 | 
            +
            					}
         | 
| 449 | 
            +
             | 
| 450 | 
            +
            					return true;
         | 
| 451 | 
            +
            				}
         | 
| 452 | 
            +
             | 
| 432 453 | 
             
            				// Serialize styles according to schema
         | 
| 433 | 
            -
            				if ( | 
| 454 | 
            +
            				if (elementName && validStyles) {
         | 
| 434 455 | 
             
            					// Serialize global styles and element specific styles
         | 
| 435 456 | 
             
            					serializeStyles('*');
         | 
| 436 | 
            -
            					serializeStyles( | 
| 457 | 
            +
            					serializeStyles(elementName);
         | 
| 437 458 | 
             
            				} else {
         | 
| 438 459 | 
             
            					// Output the styles in the order they are inside the object
         | 
| 439 460 | 
             
            					for (name in styles) {
         | 
| 440 461 | 
             
            						value = styles[name];
         | 
| 441 462 |  | 
| 442 463 | 
             
            						if (value !== undef && value.length > 0) {
         | 
| 443 | 
            -
            							 | 
| 464 | 
            +
            							if (!invalidStyles || isValid(name, elementName)) {
         | 
| 465 | 
            +
            								css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
         | 
| 466 | 
            +
            							}
         | 
| 444 467 | 
             
            						}
         | 
| 445 468 | 
             
            					}
         | 
| 446 469 | 
             
            				}
         | 
| @@ -466,6 +489,11 @@ define("tinymce/html/Styles", [], function() { | |
| 466 489 | 
             
            /*jshint loopfunc:true*/
         | 
| 467 490 | 
             
            /*eslint no-loop-func:0 */
         | 
| 468 491 |  | 
| 492 | 
            +
            /**
         | 
| 493 | 
            +
             * This class wraps the browsers native event logic with more convenient methods.
         | 
| 494 | 
            +
             *
         | 
| 495 | 
            +
             * @class tinymce.dom.EventUtils
         | 
| 496 | 
            +
             */
         | 
| 469 497 | 
             
            define("tinymce/dom/EventUtils", [], function() {
         | 
| 470 498 | 
             
            	"use strict";
         | 
| 471 499 |  | 
| @@ -3274,7 +3302,9 @@ define("tinymce/dom/DOMUtils", [ | |
| 3274 3302 | 
             
            				selectorVal = selector;
         | 
| 3275 3303 |  | 
| 3276 3304 | 
             
            				if (selector === '*') {
         | 
| 3277 | 
            -
            					selector = function(node) { | 
| 3305 | 
            +
            					selector = function(node) {
         | 
| 3306 | 
            +
            						return node.nodeType == 1;
         | 
| 3307 | 
            +
            					};
         | 
| 3278 3308 | 
             
            				} else {
         | 
| 3279 3309 | 
             
            					selector = function(node) {
         | 
| 3280 3310 | 
             
            						return self.is(node, selectorVal);
         | 
| @@ -3591,7 +3621,7 @@ define("tinymce/dom/DOMUtils", [ | |
| 3591 3621 | 
             
            						});
         | 
| 3592 3622 |  | 
| 3593 3623 | 
             
            						// Default px suffix on these
         | 
| 3594 | 
            -
            						if (typeof(value) === 'number' && !numericCssMap[name]) {
         | 
| 3624 | 
            +
            						if (((typeof(value) === 'number') || /^[\-0-9\.]+$/.test(value)) && !numericCssMap[name]) {
         | 
| 3595 3625 | 
             
            							value += 'px';
         | 
| 3596 3626 | 
             
            						}
         | 
| 3597 3627 |  | 
| @@ -6352,7 +6382,8 @@ define("tinymce/html/Schema", [ | |
| 6352 6382 | 
             
            		if (type != "html5-strict") {
         | 
| 6353 6383 | 
             
            			addAttrs("script", "language xml:space");
         | 
| 6354 6384 | 
             
            			addAttrs("style", "xml:space");
         | 
| 6355 | 
            -
            			addAttrs("object", "declare classid codebase codetype archive standby align border hspace vspace");
         | 
| 6385 | 
            +
            			addAttrs("object", "declare classid code codebase codetype archive standby align border hspace vspace");
         | 
| 6386 | 
            +
            			addAttrs("embed", "align name hspace vspace");
         | 
| 6356 6387 | 
             
            			addAttrs("param", "valuetype type");
         | 
| 6357 6388 | 
             
            			addAttrs("a", "charset name rev shape coords");
         | 
| 6358 6389 | 
             
            			addAttrs("br", "clear");
         | 
| @@ -6421,6 +6452,27 @@ define("tinymce/html/Schema", [ | |
| 6421 6452 | 
             
            		return schema;
         | 
| 6422 6453 | 
             
            	}
         | 
| 6423 6454 |  | 
| 6455 | 
            +
            	function compileElementMap(value, mode) {
         | 
| 6456 | 
            +
            		var styles;
         | 
| 6457 | 
            +
             | 
| 6458 | 
            +
            		if (value) {
         | 
| 6459 | 
            +
            			styles = {};
         | 
| 6460 | 
            +
             | 
| 6461 | 
            +
            			if (typeof value == 'string') {
         | 
| 6462 | 
            +
            				value = {
         | 
| 6463 | 
            +
            					'*': value
         | 
| 6464 | 
            +
            				};
         | 
| 6465 | 
            +
            			}
         | 
| 6466 | 
            +
             | 
| 6467 | 
            +
            			// Convert styles into a rule list
         | 
| 6468 | 
            +
            			each(value, function(value, key) {
         | 
| 6469 | 
            +
            				styles[key] = mode == 'map' ? makeMap(value, /[, ]/) : explode(value, /[, ]/);
         | 
| 6470 | 
            +
            			});
         | 
| 6471 | 
            +
            		}
         | 
| 6472 | 
            +
             | 
| 6473 | 
            +
            		return styles;
         | 
| 6474 | 
            +
            	}
         | 
| 6475 | 
            +
             | 
| 6424 6476 | 
             
            	/**
         | 
| 6425 6477 | 
             
            	 * Constructs a new Schema instance.
         | 
| 6426 6478 | 
             
            	 *
         | 
| @@ -6429,9 +6481,10 @@ define("tinymce/html/Schema", [ | |
| 6429 6481 | 
             
            	 * @param {Object} settings Name/value settings object.
         | 
| 6430 6482 | 
             
            	 */
         | 
| 6431 6483 | 
             
            	return function(settings) {
         | 
| 6432 | 
            -
            		var self = this, elements = {}, children = {}, patternElements = [], validStyles, schemaItems;
         | 
| 6433 | 
            -
            		var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap;
         | 
| 6434 | 
            -
            		var blockElementsMap, nonEmptyElementsMap, textBlockElementsMap,  | 
| 6484 | 
            +
            		var self = this, elements = {}, children = {}, patternElements = [], validStyles, invalidStyles, schemaItems;
         | 
| 6485 | 
            +
            		var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap, validClasses;
         | 
| 6486 | 
            +
            		var blockElementsMap, nonEmptyElementsMap, textBlockElementsMap, textInlineElementsMap;
         | 
| 6487 | 
            +
            		var customElementsMap = {}, specialElements = {};
         | 
| 6435 6488 |  | 
| 6436 6489 | 
             
            		// Creates an lookup table map object for the specified option or the default value
         | 
| 6437 6490 | 
             
            		function createLookupTable(option, default_value, extendWith) {
         | 
| @@ -6463,15 +6516,9 @@ define("tinymce/html/Schema", [ | |
| 6463 6516 | 
             
            			settings.valid_elements = '*[*]';
         | 
| 6464 6517 | 
             
            		}
         | 
| 6465 6518 |  | 
| 6466 | 
            -
            		 | 
| 6467 | 
            -
            		 | 
| 6468 | 
            -
             | 
| 6469 | 
            -
             | 
| 6470 | 
            -
            			// Convert styles into a rule list
         | 
| 6471 | 
            -
            			each(settings.valid_styles, function(value, key) {
         | 
| 6472 | 
            -
            				validStyles[key] = explode(value);
         | 
| 6473 | 
            -
            			});
         | 
| 6474 | 
            -
            		}
         | 
| 6519 | 
            +
            		validStyles = compileElementMap(settings.valid_styles);
         | 
| 6520 | 
            +
            		invalidStyles = compileElementMap(settings.invalid_styles, 'map');
         | 
| 6521 | 
            +
            		validClasses = compileElementMap(settings.valid_classes, 'map');
         | 
| 6475 6522 |  | 
| 6476 6523 | 
             
            		// Setup map objects
         | 
| 6477 6524 | 
             
            		whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object');
         | 
| @@ -6486,6 +6533,8 @@ define("tinymce/html/Schema", [ | |
| 6486 6533 | 
             
            		blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' +
         | 
| 6487 6534 | 
             
            						'th tr td li ol ul caption dl dt dd noscript menu isindex option ' +
         | 
| 6488 6535 | 
             
            						'datalist select optgroup', textBlockElementsMap);
         | 
| 6536 | 
            +
            		textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font strike u var cite ' +
         | 
| 6537 | 
            +
            										'dfn code mark q sup sub samp');
         | 
| 6489 6538 |  | 
| 6490 6539 | 
             
            		each((settings.special || 'script noscript style textarea').split(' '), function(name) {
         | 
| 6491 6540 | 
             
            			specialElements[name] = new RegExp('<\/' + name + '[^>]*>','gi');
         | 
| @@ -6842,10 +6891,32 @@ define("tinymce/html/Schema", [ | |
| 6842 6891 | 
             
            		/**
         | 
| 6843 6892 | 
             
            		 * Name/value map object with valid styles for each element.
         | 
| 6844 6893 | 
             
            		 *
         | 
| 6845 | 
            -
            		 * @ | 
| 6894 | 
            +
            		 * @method getValidStyles
         | 
| 6895 | 
            +
            		 * @type Object
         | 
| 6896 | 
            +
            		 */
         | 
| 6897 | 
            +
            		self.getValidStyles = function() {
         | 
| 6898 | 
            +
            			return validStyles;
         | 
| 6899 | 
            +
            		};
         | 
| 6900 | 
            +
             | 
| 6901 | 
            +
            		/**
         | 
| 6902 | 
            +
            		 * Name/value map object with valid styles for each element.
         | 
| 6903 | 
            +
            		 *
         | 
| 6904 | 
            +
            		 * @method getInvalidStyles
         | 
| 6905 | 
            +
            		 * @type Object
         | 
| 6906 | 
            +
            		 */
         | 
| 6907 | 
            +
            		self.getInvalidStyles = function() {
         | 
| 6908 | 
            +
            			return invalidStyles;
         | 
| 6909 | 
            +
            		};
         | 
| 6910 | 
            +
             | 
| 6911 | 
            +
            		/**
         | 
| 6912 | 
            +
            		 * Name/value map object with valid classes for each element.
         | 
| 6913 | 
            +
            		 *
         | 
| 6914 | 
            +
            		 * @method getValidClasses
         | 
| 6846 6915 | 
             
            		 * @type Object
         | 
| 6847 6916 | 
             
            		 */
         | 
| 6848 | 
            -
            		self. | 
| 6917 | 
            +
            		self.getValidClasses = function() {
         | 
| 6918 | 
            +
            			return validClasses;
         | 
| 6919 | 
            +
            		};
         | 
| 6849 6920 |  | 
| 6850 6921 | 
             
            		/**
         | 
| 6851 6922 | 
             
            		 * Returns a map with boolean attributes.
         | 
| @@ -6877,6 +6948,16 @@ define("tinymce/html/Schema", [ | |
| 6877 6948 | 
             
            			return textBlockElementsMap;
         | 
| 6878 6949 | 
             
            		};
         | 
| 6879 6950 |  | 
| 6951 | 
            +
            		/**
         | 
| 6952 | 
            +
            		 * Returns a map of inline text format nodes for example strong/span or ins.
         | 
| 6953 | 
            +
            		 *
         | 
| 6954 | 
            +
            		 * @method getTextInlineElements
         | 
| 6955 | 
            +
            		 * @return {Object} Name/value lookup map for text format elements.
         | 
| 6956 | 
            +
            		 */
         | 
| 6957 | 
            +
            		self.getTextInlineElements = function() {
         | 
| 6958 | 
            +
            			return textInlineElementsMap;
         | 
| 6959 | 
            +
            		};
         | 
| 6960 | 
            +
             | 
| 6880 6961 | 
             
            		/**
         | 
| 6881 6962 | 
             
            		 * Returns a map with short ended elements such as BR or IMG.
         | 
| 6882 6963 | 
             
            		 *
         | 
| @@ -7106,6 +7187,36 @@ define("tinymce/html/SaxParser", [ | |
| 7106 7187 | 
             
            ], function(Schema, Entities, Tools) {
         | 
| 7107 7188 | 
             
            	var each = Tools.each;
         | 
| 7108 7189 |  | 
| 7190 | 
            +
            	/**
         | 
| 7191 | 
            +
            	 * Returns the index of the end tag for a specific start tag. This can be
         | 
| 7192 | 
            +
            	 * used to skip all children of a parent element from being processed.
         | 
| 7193 | 
            +
            	 */
         | 
| 7194 | 
            +
            	function skipUntilEndTag(schema, html, startIndex) {
         | 
| 7195 | 
            +
            		var count = 1, matches, tokenRegExp, shortEndedElements;
         | 
| 7196 | 
            +
             | 
| 7197 | 
            +
            		shortEndedElements = schema.getShortEndedElements();
         | 
| 7198 | 
            +
            		tokenRegExp = /<([!?\/])?([A-Za-z0-9\-\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g;
         | 
| 7199 | 
            +
            		tokenRegExp.lastIndex = startIndex;
         | 
| 7200 | 
            +
             | 
| 7201 | 
            +
            		while ((matches = tokenRegExp.exec(html))) {
         | 
| 7202 | 
            +
            			if (matches[1] === '/') { // End element
         | 
| 7203 | 
            +
            				count--;
         | 
| 7204 | 
            +
            			} else if (!matches[1]) { // Start element
         | 
| 7205 | 
            +
            				if (matches[2] in shortEndedElements) {
         | 
| 7206 | 
            +
            					continue;
         | 
| 7207 | 
            +
            				}
         | 
| 7208 | 
            +
             | 
| 7209 | 
            +
            				count++;
         | 
| 7210 | 
            +
            			}
         | 
| 7211 | 
            +
             | 
| 7212 | 
            +
            			if (count === 0) {
         | 
| 7213 | 
            +
            				break;
         | 
| 7214 | 
            +
            			}
         | 
| 7215 | 
            +
            		}
         | 
| 7216 | 
            +
             | 
| 7217 | 
            +
            		return tokenRegExp.lastIndex;
         | 
| 7218 | 
            +
            	}
         | 
| 7219 | 
            +
             | 
| 7109 7220 | 
             
            	/**
         | 
| 7110 7221 | 
             
            	 * Constructs a new SaxParser instance.
         | 
| 7111 7222 | 
             
            	 *
         | 
| @@ -7387,7 +7498,13 @@ define("tinymce/html/SaxParser", [ | |
| 7387 7498 | 
             
            							}
         | 
| 7388 7499 |  | 
| 7389 7500 | 
             
            							// Invalidate element if it's marked as bogus
         | 
| 7390 | 
            -
            							if (attrList.map['data-mce-bogus']) {
         | 
| 7501 | 
            +
            							if ((attr = attrList.map['data-mce-bogus'])) {
         | 
| 7502 | 
            +
            								if (attr === 'all') {
         | 
| 7503 | 
            +
            									index = skipUntilEndTag(schema, html, tokenRegExp.lastIndex);
         | 
| 7504 | 
            +
            									tokenRegExp.lastIndex = index;
         | 
| 7505 | 
            +
            									continue;
         | 
| 7506 | 
            +
            								}
         | 
| 7507 | 
            +
             | 
| 7391 7508 | 
             
            								isValidElement = false;
         | 
| 7392 7509 | 
             
            							}
         | 
| 7393 7510 | 
             
            						}
         | 
| @@ -8050,7 +8167,7 @@ define("tinymce/html/DomParser", [ | |
| 8050 8167 | 
             
            									// Leave nodes that have a name like <a name="name">
         | 
| 8051 8168 | 
             
            									if (!node.attributes.map.name && !node.attributes.map.id) {
         | 
| 8052 8169 | 
             
            										tempNode = node.parent;
         | 
| 8053 | 
            -
            										node. | 
| 8170 | 
            +
            										node.unwrap();
         | 
| 8054 8171 | 
             
            										node = tempNode;
         | 
| 8055 8172 | 
             
            										return;
         | 
| 8056 8173 | 
             
            									}
         | 
| @@ -8229,6 +8346,48 @@ define("tinymce/html/DomParser", [ | |
| 8229 8346 | 
             
            				}
         | 
| 8230 8347 | 
             
            			});
         | 
| 8231 8348 | 
             
            		}
         | 
| 8349 | 
            +
             | 
| 8350 | 
            +
            		if (settings.validate && schema.getValidClasses()) {
         | 
| 8351 | 
            +
            			self.addAttributeFilter('class', function(nodes) {
         | 
| 8352 | 
            +
            				var i = nodes.length, node, classList, ci, className, classValue;
         | 
| 8353 | 
            +
            				var validClasses = schema.getValidClasses(), validClassesMap, valid;
         | 
| 8354 | 
            +
             | 
| 8355 | 
            +
            				while (i--) {
         | 
| 8356 | 
            +
            					node = nodes[i];
         | 
| 8357 | 
            +
            					classList = node.attr('class').split(' ');
         | 
| 8358 | 
            +
            					classValue = '';
         | 
| 8359 | 
            +
             | 
| 8360 | 
            +
            					for (ci = 0; ci < classList.length; ci++) {
         | 
| 8361 | 
            +
            						className = classList[ci];
         | 
| 8362 | 
            +
            						valid = false;
         | 
| 8363 | 
            +
             | 
| 8364 | 
            +
            						validClassesMap = validClasses['*'];
         | 
| 8365 | 
            +
            						if (validClassesMap && validClassesMap[className]) {
         | 
| 8366 | 
            +
            							valid = true;
         | 
| 8367 | 
            +
            						}
         | 
| 8368 | 
            +
             | 
| 8369 | 
            +
            						validClassesMap = validClasses[node.name];
         | 
| 8370 | 
            +
            						if (!valid && validClassesMap && !validClassesMap[className]) {
         | 
| 8371 | 
            +
            							valid = true;
         | 
| 8372 | 
            +
            						}
         | 
| 8373 | 
            +
             | 
| 8374 | 
            +
            						if (valid) {
         | 
| 8375 | 
            +
            							if (classValue) {
         | 
| 8376 | 
            +
            								classValue += ' ';
         | 
| 8377 | 
            +
            							}
         | 
| 8378 | 
            +
             | 
| 8379 | 
            +
            							classValue += className;
         | 
| 8380 | 
            +
            						}
         | 
| 8381 | 
            +
            					}
         | 
| 8382 | 
            +
             | 
| 8383 | 
            +
            					if (!classValue.length) {
         | 
| 8384 | 
            +
            						classValue = null;
         | 
| 8385 | 
            +
            					}
         | 
| 8386 | 
            +
             | 
| 8387 | 
            +
            					node.attr('class', classValue);
         | 
| 8388 | 
            +
            				}
         | 
| 8389 | 
            +
            			});
         | 
| 8390 | 
            +
            		}
         | 
| 8232 8391 | 
             
            	};
         | 
| 8233 8392 | 
             
            });
         | 
| 8234 8393 |  | 
| @@ -8711,15 +8870,6 @@ define("tinymce/dom/Serializer", [ | |
| 8711 8870 | 
             
            			}
         | 
| 8712 8871 | 
             
            		});
         | 
| 8713 8872 |  | 
| 8714 | 
            -
            		// Remove expando attributes
         | 
| 8715 | 
            -
            		htmlParser.addAttributeFilter('data-mce-expando', function(nodes, name) {
         | 
| 8716 | 
            -
            			var i = nodes.length;
         | 
| 8717 | 
            -
             | 
| 8718 | 
            -
            			while (i--) {
         | 
| 8719 | 
            -
            				nodes[i].attr(name, null);
         | 
| 8720 | 
            -
            			}
         | 
| 8721 | 
            -
            		});
         | 
| 8722 | 
            -
             | 
| 8723 8873 | 
             
            		htmlParser.addNodeFilter('noscript', function(nodes) {
         | 
| 8724 8874 | 
             
            			var i = nodes.length, node;
         | 
| 8725 8875 |  | 
| @@ -8734,7 +8884,7 @@ define("tinymce/dom/Serializer", [ | |
| 8734 8884 |  | 
| 8735 8885 | 
             
            		// Force script into CDATA sections and remove the mce- prefix also add comments around styles
         | 
| 8736 8886 | 
             
            		htmlParser.addNodeFilter('script,style', function(nodes, name) {
         | 
| 8737 | 
            -
            			var i = nodes.length, node, value;
         | 
| 8887 | 
            +
            			var i = nodes.length, node, value, type;
         | 
| 8738 8888 |  | 
| 8739 8889 | 
             
            			function trim(value) {
         | 
| 8740 8890 | 
             
            				/*jshint maxlen:255 */
         | 
| @@ -8750,9 +8900,12 @@ define("tinymce/dom/Serializer", [ | |
| 8750 8900 | 
             
            				value = node.firstChild ? node.firstChild.value : '';
         | 
| 8751 8901 |  | 
| 8752 8902 | 
             
            				if (name === "script") {
         | 
| 8753 | 
            -
            					// Remove mce- prefix from script elements and remove default  | 
| 8754 | 
            -
            					 | 
| 8755 | 
            -
            					node.attr('type' | 
| 8903 | 
            +
            					// Remove mce- prefix from script elements and remove default type since the user specified
         | 
| 8904 | 
            +
            					// a script element without type attribute
         | 
| 8905 | 
            +
            					type = node.attr('type');
         | 
| 8906 | 
            +
            					if (type) {
         | 
| 8907 | 
            +
            						node.attr('type', type == 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
         | 
| 8908 | 
            +
            					}
         | 
| 8756 8909 |  | 
| 8757 8910 | 
             
            					if (value.length > 0) {
         | 
| 8758 8911 | 
             
            						node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
         | 
| @@ -8819,13 +8972,19 @@ define("tinymce/dom/Serializer", [ | |
| 8819 8972 | 
             
            		}
         | 
| 8820 8973 |  | 
| 8821 8974 | 
             
            		// Remove internal data attributes
         | 
| 8822 | 
            -
            		htmlParser.addAttributeFilter( | 
| 8823 | 
            -
            			 | 
| 8975 | 
            +
            		htmlParser.addAttributeFilter(
         | 
| 8976 | 
            +
            			'data-mce-src,data-mce-href,data-mce-style,' +
         | 
| 8977 | 
            +
            			'data-mce-selected,data-mce-expando,' +
         | 
| 8978 | 
            +
            			'data-mce-type,data-mce-resize',
         | 
| 8824 8979 |  | 
| 8825 | 
            -
            			 | 
| 8826 | 
            -
            				nodes | 
| 8980 | 
            +
            			function(nodes, name) {
         | 
| 8981 | 
            +
            				var i = nodes.length;
         | 
| 8982 | 
            +
             | 
| 8983 | 
            +
            				while (i--) {
         | 
| 8984 | 
            +
            					nodes[i].attr(name, null);
         | 
| 8985 | 
            +
            				}
         | 
| 8827 8986 | 
             
            			}
         | 
| 8828 | 
            -
            		 | 
| 8987 | 
            +
            		);
         | 
| 8829 8988 |  | 
| 8830 8989 | 
             
            		// Return public methods
         | 
| 8831 8990 | 
             
            		return {
         | 
| @@ -9161,15 +9320,17 @@ define("tinymce/dom/TridentSelection", [], function() { | |
| 9161 9320 |  | 
| 9162 9321 | 
             
            					// Find the text node and offset
         | 
| 9163 9322 | 
             
            					while (sibling) {
         | 
| 9164 | 
            -
            						 | 
| 9165 | 
            -
             | 
| 9166 | 
            -
             | 
| 9167 | 
            -
             | 
| 9168 | 
            -
             | 
| 9169 | 
            -
            							 | 
| 9170 | 
            -
             | 
| 9171 | 
            -
             | 
| 9172 | 
            -
             | 
| 9323 | 
            +
            						if (sibling.nodeType == 3) {
         | 
| 9324 | 
            +
            							nodeValue = sibling.nodeValue;
         | 
| 9325 | 
            +
            							textNodeOffset += nodeValue.length;
         | 
| 9326 | 
            +
             | 
| 9327 | 
            +
            							// We are at or passed the position we where looking for
         | 
| 9328 | 
            +
            							if (textNodeOffset >= offset) {
         | 
| 9329 | 
            +
            								container = sibling;
         | 
| 9330 | 
            +
            								textNodeOffset -= offset;
         | 
| 9331 | 
            +
            								textNodeOffset = nodeValue.length - textNodeOffset;
         | 
| 9332 | 
            +
            								break;
         | 
| 9333 | 
            +
            							}
         | 
| 9173 9334 | 
             
            						}
         | 
| 9174 9335 |  | 
| 9175 9336 | 
             
            						sibling = sibling.nextSibling;
         | 
| @@ -9194,13 +9355,15 @@ define("tinymce/dom/TridentSelection", [], function() { | |
| 9194 9355 | 
             
            					}
         | 
| 9195 9356 |  | 
| 9196 9357 | 
             
            					while (sibling) {
         | 
| 9197 | 
            -
            						 | 
| 9358 | 
            +
            						if (sibling.nodeType == 3) {
         | 
| 9359 | 
            +
            							textNodeOffset += sibling.nodeValue.length;
         | 
| 9198 9360 |  | 
| 9199 | 
            -
             | 
| 9200 | 
            -
             | 
| 9201 | 
            -
             | 
| 9202 | 
            -
             | 
| 9203 | 
            -
             | 
| 9361 | 
            +
            							// We are at or passed the position we where looking for
         | 
| 9362 | 
            +
            							if (textNodeOffset >= offset) {
         | 
| 9363 | 
            +
            								container = sibling;
         | 
| 9364 | 
            +
            								textNodeOffset -= offset;
         | 
| 9365 | 
            +
            								break;
         | 
| 9366 | 
            +
            							}
         | 
| 9204 9367 | 
             
            						}
         | 
| 9205 9368 |  | 
| 9206 9369 | 
             
            						sibling = sibling.previousSibling;
         | 
| @@ -9533,8 +9696,8 @@ define("tinymce/util/VK", [ | |
| 9533 9696 | 
             
            		},
         | 
| 9534 9697 |  | 
| 9535 9698 | 
             
            		metaKeyPressed: function(e) {
         | 
| 9536 | 
            -
            			// Check if ctrl or meta key is pressed  | 
| 9537 | 
            -
            			return (Env.mac ? e.metaKey : e.ctrlKey | 
| 9699 | 
            +
            			// Check if ctrl or meta key is pressed. Edge case for AltGr on Windows where it produces ctrlKey+altKey states
         | 
| 9700 | 
            +
            			return (Env.mac ? e.metaKey : e.ctrlKey && !e.altKey);
         | 
| 9538 9701 | 
             
            		}
         | 
| 9539 9702 | 
             
            	};
         | 
| 9540 9703 | 
             
            });
         | 
| @@ -10066,7 +10229,7 @@ define("tinymce/dom/ControlSelection", [ | |
| 10066 10229 | 
             
            // Included from: js/tinymce/classes/dom/RangeUtils.js
         | 
| 10067 10230 |  | 
| 10068 10231 | 
             
            /**
         | 
| 10069 | 
            -
             *  | 
| 10232 | 
            +
             * RangeUtils.js
         | 
| 10070 10233 | 
             
             *
         | 
| 10071 10234 | 
             
             * Copyright, Moxiecode Systems AB
         | 
| 10072 10235 | 
             
             * Released under LGPL License.
         | 
| @@ -10076,7 +10239,7 @@ define("tinymce/dom/ControlSelection", [ | |
| 10076 10239 | 
             
             */
         | 
| 10077 10240 |  | 
| 10078 10241 | 
             
            /**
         | 
| 10079 | 
            -
             *  | 
| 10242 | 
            +
             * This class contains a few utility methods for ranges.
         | 
| 10080 10243 | 
             
             *
         | 
| 10081 10244 | 
             
             * @class tinymce.dom.RangeUtils
         | 
| 10082 10245 | 
             
             * @private
         | 
| @@ -10087,6 +10250,20 @@ define("tinymce/dom/RangeUtils", [ | |
| 10087 10250 | 
             
            ], function(Tools, TreeWalker) {
         | 
| 10088 10251 | 
             
            	var each = Tools.each;
         | 
| 10089 10252 |  | 
| 10253 | 
            +
            	function getEndChild(container, index) {
         | 
| 10254 | 
            +
            		var childNodes = container.childNodes;
         | 
| 10255 | 
            +
             | 
| 10256 | 
            +
            		index--;
         | 
| 10257 | 
            +
            		
         | 
| 10258 | 
            +
            		if (index > childNodes.length - 1) {
         | 
| 10259 | 
            +
            			index = childNodes.length - 1;
         | 
| 10260 | 
            +
            		} else if (index < 0) {
         | 
| 10261 | 
            +
            			index = 0;
         | 
| 10262 | 
            +
            		}
         | 
| 10263 | 
            +
             | 
| 10264 | 
            +
            		return childNodes[index] || container;
         | 
| 10265 | 
            +
            	}
         | 
| 10266 | 
            +
             | 
| 10090 10267 | 
             
            	function RangeUtils(dom) {
         | 
| 10091 10268 | 
             
            		/**
         | 
| 10092 10269 | 
             
            		 * Walks the specified range like object and executes the callback for each sibling collection it finds.
         | 
| @@ -10199,7 +10376,7 @@ define("tinymce/dom/RangeUtils", [ | |
| 10199 10376 |  | 
| 10200 10377 | 
             
            			// If index based end position then resolve it
         | 
| 10201 10378 | 
             
            			if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
         | 
| 10202 | 
            -
            				endContainer = endContainer | 
| 10379 | 
            +
            				endContainer = getEndChild(endContainer, endOffset);
         | 
| 10203 10380 | 
             
            			}
         | 
| 10204 10381 |  | 
| 10205 10382 | 
             
            			// Same container
         | 
| @@ -10546,6 +10723,398 @@ define("tinymce/dom/RangeUtils", [ | |
| 10546 10723 | 
             
            	return RangeUtils;
         | 
| 10547 10724 | 
             
            });
         | 
| 10548 10725 |  | 
| 10726 | 
            +
            // Included from: js/tinymce/classes/dom/BookmarkManager.js
         | 
| 10727 | 
            +
             | 
| 10728 | 
            +
            /**
         | 
| 10729 | 
            +
             * BookmarkManager.js
         | 
| 10730 | 
            +
             *
         | 
| 10731 | 
            +
             * Copyright, Moxiecode Systems AB
         | 
| 10732 | 
            +
             * Released under LGPL License.
         | 
| 10733 | 
            +
             *
         | 
| 10734 | 
            +
             * License: http://www.tinymce.com/license
         | 
| 10735 | 
            +
             * Contributing: http://www.tinymce.com/contributing
         | 
| 10736 | 
            +
             */
         | 
| 10737 | 
            +
             | 
| 10738 | 
            +
            /**
         | 
| 10739 | 
            +
             * This class handles selection bookmarks.
         | 
| 10740 | 
            +
             *
         | 
| 10741 | 
            +
             * @class tinymce.dom.BookmarkManager
         | 
| 10742 | 
            +
             */
         | 
| 10743 | 
            +
            define("tinymce/dom/BookmarkManager", [
         | 
| 10744 | 
            +
            	"tinymce/Env",
         | 
| 10745 | 
            +
            	"tinymce/util/Tools"
         | 
| 10746 | 
            +
            ], function(Env, Tools) {
         | 
| 10747 | 
            +
            	/**
         | 
| 10748 | 
            +
            	 * Constructs a new BookmarkManager instance for a specific selection instance.
         | 
| 10749 | 
            +
            	 *
         | 
| 10750 | 
            +
            	 * @constructor
         | 
| 10751 | 
            +
            	 * @method BookmarkManager
         | 
| 10752 | 
            +
            	 * @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
         | 
| 10753 | 
            +
            	 */
         | 
| 10754 | 
            +
            	function BookmarkManager(selection) {
         | 
| 10755 | 
            +
            		var dom = selection.dom;
         | 
| 10756 | 
            +
             | 
| 10757 | 
            +
            		/**
         | 
| 10758 | 
            +
            		 * Returns a bookmark location for the current selection. This bookmark object
         | 
| 10759 | 
            +
            		 * can then be used to restore the selection after some content modification to the document.
         | 
| 10760 | 
            +
            		 *
         | 
| 10761 | 
            +
            		 * @method getBookmark
         | 
| 10762 | 
            +
            		 * @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
         | 
| 10763 | 
            +
            		 * @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
         | 
| 10764 | 
            +
            		 * @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
         | 
| 10765 | 
            +
            		 * @example
         | 
| 10766 | 
            +
            		 * // Stores a bookmark of the current selection
         | 
| 10767 | 
            +
            		 * var bm = tinymce.activeEditor.selection.getBookmark();
         | 
| 10768 | 
            +
            		 *
         | 
| 10769 | 
            +
            		 * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
         | 
| 10770 | 
            +
            		 *
         | 
| 10771 | 
            +
            		 * // Restore the selection bookmark
         | 
| 10772 | 
            +
            		 * tinymce.activeEditor.selection.moveToBookmark(bm);
         | 
| 10773 | 
            +
            		 */
         | 
| 10774 | 
            +
            		this.getBookmark = function(type, normalized) {
         | 
| 10775 | 
            +
            			var rng, rng2, id, collapsed, name, element, chr = '', styles;
         | 
| 10776 | 
            +
             | 
| 10777 | 
            +
            			function findIndex(name, element) {
         | 
| 10778 | 
            +
            				var index = 0;
         | 
| 10779 | 
            +
             | 
| 10780 | 
            +
            				Tools.each(dom.select(name), function(node, i) {
         | 
| 10781 | 
            +
            					if (node == element) {
         | 
| 10782 | 
            +
            						index = i;
         | 
| 10783 | 
            +
            					}
         | 
| 10784 | 
            +
            				});
         | 
| 10785 | 
            +
             | 
| 10786 | 
            +
            				return index;
         | 
| 10787 | 
            +
            			}
         | 
| 10788 | 
            +
             | 
| 10789 | 
            +
            			function normalizeTableCellSelection(rng) {
         | 
| 10790 | 
            +
            				function moveEndPoint(start) {
         | 
| 10791 | 
            +
            					var container, offset, childNodes, prefix = start ? 'start' : 'end';
         | 
| 10792 | 
            +
             | 
| 10793 | 
            +
            					container = rng[prefix + 'Container'];
         | 
| 10794 | 
            +
            					offset = rng[prefix + 'Offset'];
         | 
| 10795 | 
            +
             | 
| 10796 | 
            +
            					if (container.nodeType == 1 && container.nodeName == "TR") {
         | 
| 10797 | 
            +
            						childNodes = container.childNodes;
         | 
| 10798 | 
            +
            						container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
         | 
| 10799 | 
            +
            						if (container) {
         | 
| 10800 | 
            +
            							offset = start ? 0 : container.childNodes.length;
         | 
| 10801 | 
            +
            							rng['set' + (start ? 'Start' : 'End')](container, offset);
         | 
| 10802 | 
            +
            						}
         | 
| 10803 | 
            +
            					}
         | 
| 10804 | 
            +
            				}
         | 
| 10805 | 
            +
             | 
| 10806 | 
            +
            				moveEndPoint(true);
         | 
| 10807 | 
            +
            				moveEndPoint();
         | 
| 10808 | 
            +
             | 
| 10809 | 
            +
            				return rng;
         | 
| 10810 | 
            +
            			}
         | 
| 10811 | 
            +
             | 
| 10812 | 
            +
            			function getLocation() {
         | 
| 10813 | 
            +
            				var rng = selection.getRng(true), root = dom.getRoot(), bookmark = {};
         | 
| 10814 | 
            +
             | 
| 10815 | 
            +
            				function getPoint(rng, start) {
         | 
| 10816 | 
            +
            					var container = rng[start ? 'startContainer' : 'endContainer'],
         | 
| 10817 | 
            +
            						offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
         | 
| 10818 | 
            +
             | 
| 10819 | 
            +
            					if (container.nodeType == 3) {
         | 
| 10820 | 
            +
            						if (normalized) {
         | 
| 10821 | 
            +
            							for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
         | 
| 10822 | 
            +
            								offset += node.nodeValue.length;
         | 
| 10823 | 
            +
            							}
         | 
| 10824 | 
            +
            						}
         | 
| 10825 | 
            +
             | 
| 10826 | 
            +
            						point.push(offset);
         | 
| 10827 | 
            +
            					} else {
         | 
| 10828 | 
            +
            						childNodes = container.childNodes;
         | 
| 10829 | 
            +
             | 
| 10830 | 
            +
            						if (offset >= childNodes.length && childNodes.length) {
         | 
| 10831 | 
            +
            							after = 1;
         | 
| 10832 | 
            +
            							offset = Math.max(0, childNodes.length - 1);
         | 
| 10833 | 
            +
            						}
         | 
| 10834 | 
            +
             | 
| 10835 | 
            +
            						point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
         | 
| 10836 | 
            +
            					}
         | 
| 10837 | 
            +
             | 
| 10838 | 
            +
            					for (; container && container != root; container = container.parentNode) {
         | 
| 10839 | 
            +
            						point.push(dom.nodeIndex(container, normalized));
         | 
| 10840 | 
            +
            					}
         | 
| 10841 | 
            +
             | 
| 10842 | 
            +
            					return point;
         | 
| 10843 | 
            +
            				}
         | 
| 10844 | 
            +
             | 
| 10845 | 
            +
            				bookmark.start = getPoint(rng, true);
         | 
| 10846 | 
            +
             | 
| 10847 | 
            +
            				if (!selection.isCollapsed()) {
         | 
| 10848 | 
            +
            					bookmark.end = getPoint(rng);
         | 
| 10849 | 
            +
            				}
         | 
| 10850 | 
            +
             | 
| 10851 | 
            +
            				return bookmark;
         | 
| 10852 | 
            +
            			}
         | 
| 10853 | 
            +
             | 
| 10854 | 
            +
            			if (type == 2) {
         | 
| 10855 | 
            +
            				element = selection.getNode();
         | 
| 10856 | 
            +
            				name = element ? element.nodeName : null;
         | 
| 10857 | 
            +
             | 
| 10858 | 
            +
            				if (name == 'IMG') {
         | 
| 10859 | 
            +
            					return {name: name, index: findIndex(name, element)};
         | 
| 10860 | 
            +
            				}
         | 
| 10861 | 
            +
             | 
| 10862 | 
            +
            				if (selection.tridentSel) {
         | 
| 10863 | 
            +
            					return selection.tridentSel.getBookmark(type);
         | 
| 10864 | 
            +
            				}
         | 
| 10865 | 
            +
             | 
| 10866 | 
            +
            				return getLocation();
         | 
| 10867 | 
            +
            			}
         | 
| 10868 | 
            +
             | 
| 10869 | 
            +
            			// Handle simple range
         | 
| 10870 | 
            +
            			if (type) {
         | 
| 10871 | 
            +
            				return {rng: selection.getRng()};
         | 
| 10872 | 
            +
            			}
         | 
| 10873 | 
            +
             | 
| 10874 | 
            +
            			rng = selection.getRng();
         | 
| 10875 | 
            +
            			id = dom.uniqueId();
         | 
| 10876 | 
            +
            			collapsed = selection.isCollapsed();
         | 
| 10877 | 
            +
            			styles = 'overflow:hidden;line-height:0px';
         | 
| 10878 | 
            +
             | 
| 10879 | 
            +
            			// Explorer method
         | 
| 10880 | 
            +
            			if (rng.duplicate || rng.item) {
         | 
| 10881 | 
            +
            				// Text selection
         | 
| 10882 | 
            +
            				if (!rng.item) {
         | 
| 10883 | 
            +
            					rng2 = rng.duplicate();
         | 
| 10884 | 
            +
             | 
| 10885 | 
            +
            					try {
         | 
| 10886 | 
            +
            						// Insert start marker
         | 
| 10887 | 
            +
            						rng.collapse();
         | 
| 10888 | 
            +
            						rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
         | 
| 10889 | 
            +
             | 
| 10890 | 
            +
            						// Insert end marker
         | 
| 10891 | 
            +
            						if (!collapsed) {
         | 
| 10892 | 
            +
            							rng2.collapse(false);
         | 
| 10893 | 
            +
             | 
| 10894 | 
            +
            							// Detect the empty space after block elements in IE and move the
         | 
| 10895 | 
            +
            							// end back one character <p></p>] becomes <p>]</p>
         | 
| 10896 | 
            +
            							rng.moveToElementText(rng2.parentElement());
         | 
| 10897 | 
            +
            							if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
         | 
| 10898 | 
            +
            								rng2.move('character', -1);
         | 
| 10899 | 
            +
            							}
         | 
| 10900 | 
            +
             | 
| 10901 | 
            +
            							rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
         | 
| 10902 | 
            +
            						}
         | 
| 10903 | 
            +
            					} catch (ex) {
         | 
| 10904 | 
            +
            						// IE might throw unspecified error so lets ignore it
         | 
| 10905 | 
            +
            						return null;
         | 
| 10906 | 
            +
            					}
         | 
| 10907 | 
            +
            				} else {
         | 
| 10908 | 
            +
            					// Control selection
         | 
| 10909 | 
            +
            					element = rng.item(0);
         | 
| 10910 | 
            +
            					name = element.nodeName;
         | 
| 10911 | 
            +
             | 
| 10912 | 
            +
            					return {name: name, index: findIndex(name, element)};
         | 
| 10913 | 
            +
            				}
         | 
| 10914 | 
            +
            			} else {
         | 
| 10915 | 
            +
            				element = selection.getNode();
         | 
| 10916 | 
            +
            				name = element.nodeName;
         | 
| 10917 | 
            +
            				if (name == 'IMG') {
         | 
| 10918 | 
            +
            					return {name: name, index: findIndex(name, element)};
         | 
| 10919 | 
            +
            				}
         | 
| 10920 | 
            +
             | 
| 10921 | 
            +
            				// W3C method
         | 
| 10922 | 
            +
            				rng2 = normalizeTableCellSelection(rng.cloneRange());
         | 
| 10923 | 
            +
             | 
| 10924 | 
            +
            				// Insert end marker
         | 
| 10925 | 
            +
            				if (!collapsed) {
         | 
| 10926 | 
            +
            					rng2.collapse(false);
         | 
| 10927 | 
            +
            					rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
         | 
| 10928 | 
            +
            				}
         | 
| 10929 | 
            +
             | 
| 10930 | 
            +
            				rng = normalizeTableCellSelection(rng);
         | 
| 10931 | 
            +
            				rng.collapse(true);
         | 
| 10932 | 
            +
            				rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
         | 
| 10933 | 
            +
            			}
         | 
| 10934 | 
            +
             | 
| 10935 | 
            +
            			selection.moveToBookmark({id: id, keep: 1});
         | 
| 10936 | 
            +
             | 
| 10937 | 
            +
            			return {id: id};
         | 
| 10938 | 
            +
            		};
         | 
| 10939 | 
            +
             | 
| 10940 | 
            +
            		/**
         | 
| 10941 | 
            +
            		 * Restores the selection to the specified bookmark.
         | 
| 10942 | 
            +
            		 *
         | 
| 10943 | 
            +
            		 * @method moveToBookmark
         | 
| 10944 | 
            +
            		 * @param {Object} bookmark Bookmark to restore selection from.
         | 
| 10945 | 
            +
            		 * @return {Boolean} true/false if it was successful or not.
         | 
| 10946 | 
            +
            		 * @example
         | 
| 10947 | 
            +
            		 * // Stores a bookmark of the current selection
         | 
| 10948 | 
            +
            		 * var bm = tinymce.activeEditor.selection.getBookmark();
         | 
| 10949 | 
            +
            		 *
         | 
| 10950 | 
            +
            		 * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
         | 
| 10951 | 
            +
            		 *
         | 
| 10952 | 
            +
            		 * // Restore the selection bookmark
         | 
| 10953 | 
            +
            		 * tinymce.activeEditor.selection.moveToBookmark(bm);
         | 
| 10954 | 
            +
            		 */
         | 
| 10955 | 
            +
            		this.moveToBookmark = function(bookmark) {
         | 
| 10956 | 
            +
            			var rng, root, startContainer, endContainer, startOffset, endOffset;
         | 
| 10957 | 
            +
             | 
| 10958 | 
            +
            			function setEndPoint(start) {
         | 
| 10959 | 
            +
            				var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
         | 
| 10960 | 
            +
             | 
| 10961 | 
            +
            				if (point) {
         | 
| 10962 | 
            +
            					offset = point[0];
         | 
| 10963 | 
            +
             | 
| 10964 | 
            +
            					// Find container node
         | 
| 10965 | 
            +
            					for (node = root, i = point.length - 1; i >= 1; i--) {
         | 
| 10966 | 
            +
            						children = node.childNodes;
         | 
| 10967 | 
            +
             | 
| 10968 | 
            +
            						if (point[i] > children.length - 1) {
         | 
| 10969 | 
            +
            							return;
         | 
| 10970 | 
            +
            						}
         | 
| 10971 | 
            +
             | 
| 10972 | 
            +
            						node = children[point[i]];
         | 
| 10973 | 
            +
            					}
         | 
| 10974 | 
            +
             | 
| 10975 | 
            +
            					// Move text offset to best suitable location
         | 
| 10976 | 
            +
            					if (node.nodeType === 3) {
         | 
| 10977 | 
            +
            						offset = Math.min(point[0], node.nodeValue.length);
         | 
| 10978 | 
            +
            					}
         | 
| 10979 | 
            +
             | 
| 10980 | 
            +
            					// Move element offset to best suitable location
         | 
| 10981 | 
            +
            					if (node.nodeType === 1) {
         | 
| 10982 | 
            +
            						offset = Math.min(point[0], node.childNodes.length);
         | 
| 10983 | 
            +
            					}
         | 
| 10984 | 
            +
             | 
| 10985 | 
            +
            					// Set offset within container node
         | 
| 10986 | 
            +
            					if (start) {
         | 
| 10987 | 
            +
            						rng.setStart(node, offset);
         | 
| 10988 | 
            +
            					} else {
         | 
| 10989 | 
            +
            						rng.setEnd(node, offset);
         | 
| 10990 | 
            +
            					}
         | 
| 10991 | 
            +
            				}
         | 
| 10992 | 
            +
             | 
| 10993 | 
            +
            				return true;
         | 
| 10994 | 
            +
            			}
         | 
| 10995 | 
            +
             | 
| 10996 | 
            +
            			function restoreEndPoint(suffix) {
         | 
| 10997 | 
            +
            				var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
         | 
| 10998 | 
            +
             | 
| 10999 | 
            +
            				if (marker) {
         | 
| 11000 | 
            +
            					node = marker.parentNode;
         | 
| 11001 | 
            +
             | 
| 11002 | 
            +
            					if (suffix == 'start') {
         | 
| 11003 | 
            +
            						if (!keep) {
         | 
| 11004 | 
            +
            							idx = dom.nodeIndex(marker);
         | 
| 11005 | 
            +
            						} else {
         | 
| 11006 | 
            +
            							node = marker.firstChild;
         | 
| 11007 | 
            +
            							idx = 1;
         | 
| 11008 | 
            +
            						}
         | 
| 11009 | 
            +
             | 
| 11010 | 
            +
            						startContainer = endContainer = node;
         | 
| 11011 | 
            +
            						startOffset = endOffset = idx;
         | 
| 11012 | 
            +
            					} else {
         | 
| 11013 | 
            +
            						if (!keep) {
         | 
| 11014 | 
            +
            							idx = dom.nodeIndex(marker);
         | 
| 11015 | 
            +
            						} else {
         | 
| 11016 | 
            +
            							node = marker.firstChild;
         | 
| 11017 | 
            +
            							idx = 1;
         | 
| 11018 | 
            +
            						}
         | 
| 11019 | 
            +
             | 
| 11020 | 
            +
            						endContainer = node;
         | 
| 11021 | 
            +
            						endOffset = idx;
         | 
| 11022 | 
            +
            					}
         | 
| 11023 | 
            +
             | 
| 11024 | 
            +
            					if (!keep) {
         | 
| 11025 | 
            +
            						prev = marker.previousSibling;
         | 
| 11026 | 
            +
            						next = marker.nextSibling;
         | 
| 11027 | 
            +
             | 
| 11028 | 
            +
            						// Remove all marker text nodes
         | 
| 11029 | 
            +
            						Tools.each(Tools.grep(marker.childNodes), function(node) {
         | 
| 11030 | 
            +
            							if (node.nodeType == 3) {
         | 
| 11031 | 
            +
            								node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
         | 
| 11032 | 
            +
            							}
         | 
| 11033 | 
            +
            						});
         | 
| 11034 | 
            +
             | 
| 11035 | 
            +
            						// Remove marker but keep children if for example contents where inserted into the marker
         | 
| 11036 | 
            +
            						// Also remove duplicated instances of the marker for example by a
         | 
| 11037 | 
            +
            						// split operation or by WebKit auto split on paste feature
         | 
| 11038 | 
            +
            						while ((marker = dom.get(bookmark.id + '_' + suffix))) {
         | 
| 11039 | 
            +
            							dom.remove(marker, 1);
         | 
| 11040 | 
            +
            						}
         | 
| 11041 | 
            +
             | 
| 11042 | 
            +
            						// If siblings are text nodes then merge them unless it's Opera since it some how removes the node
         | 
| 11043 | 
            +
            						// and we are sniffing since adding a lot of detection code for a browser with 3% of the market
         | 
| 11044 | 
            +
            						// isn't worth the effort. Sorry, Opera but it's just a fact
         | 
| 11045 | 
            +
            						if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
         | 
| 11046 | 
            +
            							idx = prev.nodeValue.length;
         | 
| 11047 | 
            +
            							prev.appendData(next.nodeValue);
         | 
| 11048 | 
            +
            							dom.remove(next);
         | 
| 11049 | 
            +
             | 
| 11050 | 
            +
            							if (suffix == 'start') {
         | 
| 11051 | 
            +
            								startContainer = endContainer = prev;
         | 
| 11052 | 
            +
            								startOffset = endOffset = idx;
         | 
| 11053 | 
            +
            							} else {
         | 
| 11054 | 
            +
            								endContainer = prev;
         | 
| 11055 | 
            +
            								endOffset = idx;
         | 
| 11056 | 
            +
            							}
         | 
| 11057 | 
            +
            						}
         | 
| 11058 | 
            +
            					}
         | 
| 11059 | 
            +
            				}
         | 
| 11060 | 
            +
            			}
         | 
| 11061 | 
            +
             | 
| 11062 | 
            +
            			function addBogus(node) {
         | 
| 11063 | 
            +
            				// Adds a bogus BR element for empty block elements
         | 
| 11064 | 
            +
            				if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
         | 
| 11065 | 
            +
            					node.innerHTML = '<br data-mce-bogus="1" />';
         | 
| 11066 | 
            +
            				}
         | 
| 11067 | 
            +
             | 
| 11068 | 
            +
            				return node;
         | 
| 11069 | 
            +
            			}
         | 
| 11070 | 
            +
             | 
| 11071 | 
            +
            			if (bookmark) {
         | 
| 11072 | 
            +
            				if (bookmark.start) {
         | 
| 11073 | 
            +
            					rng = dom.createRng();
         | 
| 11074 | 
            +
            					root = dom.getRoot();
         | 
| 11075 | 
            +
             | 
| 11076 | 
            +
            					if (selection.tridentSel) {
         | 
| 11077 | 
            +
            						return selection.tridentSel.moveToBookmark(bookmark);
         | 
| 11078 | 
            +
            					}
         | 
| 11079 | 
            +
             | 
| 11080 | 
            +
            					if (setEndPoint(true) && setEndPoint()) {
         | 
| 11081 | 
            +
            						selection.setRng(rng);
         | 
| 11082 | 
            +
            					}
         | 
| 11083 | 
            +
            				} else if (bookmark.id) {
         | 
| 11084 | 
            +
            					// Restore start/end points
         | 
| 11085 | 
            +
            					restoreEndPoint('start');
         | 
| 11086 | 
            +
            					restoreEndPoint('end');
         | 
| 11087 | 
            +
             | 
| 11088 | 
            +
            					if (startContainer) {
         | 
| 11089 | 
            +
            						rng = dom.createRng();
         | 
| 11090 | 
            +
            						rng.setStart(addBogus(startContainer), startOffset);
         | 
| 11091 | 
            +
            						rng.setEnd(addBogus(endContainer), endOffset);
         | 
| 11092 | 
            +
            						selection.setRng(rng);
         | 
| 11093 | 
            +
            					}
         | 
| 11094 | 
            +
            				} else if (bookmark.name) {
         | 
| 11095 | 
            +
            					selection.select(dom.select(bookmark.name)[bookmark.index]);
         | 
| 11096 | 
            +
            				} else if (bookmark.rng) {
         | 
| 11097 | 
            +
            					selection.setRng(bookmark.rng);
         | 
| 11098 | 
            +
            				}
         | 
| 11099 | 
            +
            			}
         | 
| 11100 | 
            +
            		};
         | 
| 11101 | 
            +
            	}
         | 
| 11102 | 
            +
             | 
| 11103 | 
            +
            	/**
         | 
| 11104 | 
            +
            	 * Returns true/false if the specified node is a bookmark node or not.
         | 
| 11105 | 
            +
            	 *
         | 
| 11106 | 
            +
            	 * @static
         | 
| 11107 | 
            +
            	 * @method isBookmarkNode
         | 
| 11108 | 
            +
            	 * @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
         | 
| 11109 | 
            +
            	 * @return {Boolean} true/false if the node is a bookmark node or not.
         | 
| 11110 | 
            +
            	 */
         | 
| 11111 | 
            +
            	BookmarkManager.isBookmarkNode = function(node) {
         | 
| 11112 | 
            +
            		return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
         | 
| 11113 | 
            +
            	};
         | 
| 11114 | 
            +
             | 
| 11115 | 
            +
            	return BookmarkManager;
         | 
| 11116 | 
            +
            });
         | 
| 11117 | 
            +
             | 
| 10549 11118 | 
             
            // Included from: js/tinymce/classes/dom/Selection.js
         | 
| 10550 11119 |  | 
| 10551 11120 | 
             
            /**
         | 
| @@ -10572,11 +11141,12 @@ define("tinymce/dom/Selection", [ | |
| 10572 11141 | 
             
            	"tinymce/dom/TridentSelection",
         | 
| 10573 11142 | 
             
            	"tinymce/dom/ControlSelection",
         | 
| 10574 11143 | 
             
            	"tinymce/dom/RangeUtils",
         | 
| 11144 | 
            +
            	"tinymce/dom/BookmarkManager",
         | 
| 10575 11145 | 
             
            	"tinymce/Env",
         | 
| 10576 11146 | 
             
            	"tinymce/util/Tools"
         | 
| 10577 | 
            -
            ], function(TreeWalker, TridentSelection, ControlSelection, RangeUtils, Env, Tools) {
         | 
| 10578 | 
            -
            	var each = Tools.each,  | 
| 10579 | 
            -
            	var isIE = Env.ie | 
| 11147 | 
            +
            ], function(TreeWalker, TridentSelection, ControlSelection, RangeUtils, BookmarkManager, Env, Tools) {
         | 
| 11148 | 
            +
            	var each = Tools.each, trim = Tools.trim;
         | 
| 11149 | 
            +
            	var isIE = Env.ie;
         | 
| 10580 11150 |  | 
| 10581 11151 | 
             
            	/**
         | 
| 10582 11152 | 
             
            	 * Constructs a new selection instance.
         | 
| @@ -10594,7 +11164,7 @@ define("tinymce/dom/Selection", [ | |
| 10594 11164 | 
             
            		self.win = win;
         | 
| 10595 11165 | 
             
            		self.serializer = serializer;
         | 
| 10596 11166 | 
             
            		self.editor = editor;
         | 
| 10597 | 
            -
             | 
| 11167 | 
            +
            		self.bookmarkManager = new BookmarkManager(self);
         | 
| 10598 11168 | 
             
            		self.controlSelection = new ControlSelection(self, editor);
         | 
| 10599 11169 |  | 
| 10600 11170 | 
             
            		// No W3C Range support
         | 
| @@ -10894,169 +11464,7 @@ define("tinymce/dom/Selection", [ | |
| 10894 11464 | 
             
            		 * tinymce.activeEditor.selection.moveToBookmark(bm);
         | 
| 10895 11465 | 
             
            		 */
         | 
| 10896 11466 | 
             
            		getBookmark: function(type, normalized) {
         | 
| 10897 | 
            -
            			 | 
| 10898 | 
            -
             | 
| 10899 | 
            -
            			function findIndex(name, element) {
         | 
| 10900 | 
            -
            				var index = 0;
         | 
| 10901 | 
            -
             | 
| 10902 | 
            -
            				each(dom.select(name), function(node, i) {
         | 
| 10903 | 
            -
            					if (node == element) {
         | 
| 10904 | 
            -
            						index = i;
         | 
| 10905 | 
            -
            					}
         | 
| 10906 | 
            -
            				});
         | 
| 10907 | 
            -
             | 
| 10908 | 
            -
            				return index;
         | 
| 10909 | 
            -
            			}
         | 
| 10910 | 
            -
             | 
| 10911 | 
            -
            			function normalizeTableCellSelection(rng) {
         | 
| 10912 | 
            -
            				function moveEndPoint(start) {
         | 
| 10913 | 
            -
            					var container, offset, childNodes, prefix = start ? 'start' : 'end';
         | 
| 10914 | 
            -
             | 
| 10915 | 
            -
            					container = rng[prefix + 'Container'];
         | 
| 10916 | 
            -
            					offset = rng[prefix + 'Offset'];
         | 
| 10917 | 
            -
             | 
| 10918 | 
            -
            					if (container.nodeType == 1 && container.nodeName == "TR") {
         | 
| 10919 | 
            -
            						childNodes = container.childNodes;
         | 
| 10920 | 
            -
            						container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
         | 
| 10921 | 
            -
            						if (container) {
         | 
| 10922 | 
            -
            							offset = start ? 0 : container.childNodes.length;
         | 
| 10923 | 
            -
            							rng['set' + (start ? 'Start' : 'End')](container, offset);
         | 
| 10924 | 
            -
            						}
         | 
| 10925 | 
            -
            					}
         | 
| 10926 | 
            -
            				}
         | 
| 10927 | 
            -
             | 
| 10928 | 
            -
            				moveEndPoint(true);
         | 
| 10929 | 
            -
            				moveEndPoint();
         | 
| 10930 | 
            -
             | 
| 10931 | 
            -
            				return rng;
         | 
| 10932 | 
            -
            			}
         | 
| 10933 | 
            -
             | 
| 10934 | 
            -
            			function getLocation() {
         | 
| 10935 | 
            -
            				var rng = self.getRng(true), root = dom.getRoot(), bookmark = {};
         | 
| 10936 | 
            -
             | 
| 10937 | 
            -
            				function getPoint(rng, start) {
         | 
| 10938 | 
            -
            					var container = rng[start ? 'startContainer' : 'endContainer'],
         | 
| 10939 | 
            -
            						offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
         | 
| 10940 | 
            -
             | 
| 10941 | 
            -
            					if (container.nodeType == 3) {
         | 
| 10942 | 
            -
            						if (normalized) {
         | 
| 10943 | 
            -
            							for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
         | 
| 10944 | 
            -
            								offset += node.nodeValue.length;
         | 
| 10945 | 
            -
            							}
         | 
| 10946 | 
            -
            						}
         | 
| 10947 | 
            -
             | 
| 10948 | 
            -
            						point.push(offset);
         | 
| 10949 | 
            -
            					} else {
         | 
| 10950 | 
            -
            						childNodes = container.childNodes;
         | 
| 10951 | 
            -
             | 
| 10952 | 
            -
            						if (offset >= childNodes.length && childNodes.length) {
         | 
| 10953 | 
            -
            							after = 1;
         | 
| 10954 | 
            -
            							offset = Math.max(0, childNodes.length - 1);
         | 
| 10955 | 
            -
            						}
         | 
| 10956 | 
            -
             | 
| 10957 | 
            -
            						point.push(self.dom.nodeIndex(childNodes[offset], normalized) + after);
         | 
| 10958 | 
            -
            					}
         | 
| 10959 | 
            -
             | 
| 10960 | 
            -
            					for (; container && container != root; container = container.parentNode) {
         | 
| 10961 | 
            -
            						point.push(self.dom.nodeIndex(container, normalized));
         | 
| 10962 | 
            -
            					}
         | 
| 10963 | 
            -
             | 
| 10964 | 
            -
            					return point;
         | 
| 10965 | 
            -
            				}
         | 
| 10966 | 
            -
             | 
| 10967 | 
            -
            				bookmark.start = getPoint(rng, true);
         | 
| 10968 | 
            -
             | 
| 10969 | 
            -
            				if (!self.isCollapsed()) {
         | 
| 10970 | 
            -
            					bookmark.end = getPoint(rng);
         | 
| 10971 | 
            -
            				}
         | 
| 10972 | 
            -
             | 
| 10973 | 
            -
            				return bookmark;
         | 
| 10974 | 
            -
            			}
         | 
| 10975 | 
            -
             | 
| 10976 | 
            -
            			if (type == 2) {
         | 
| 10977 | 
            -
            				element = self.getNode();
         | 
| 10978 | 
            -
            				name = element ? element.nodeName : null;
         | 
| 10979 | 
            -
             | 
| 10980 | 
            -
            				if (name == 'IMG') {
         | 
| 10981 | 
            -
            					return {name: name, index: findIndex(name, element)};
         | 
| 10982 | 
            -
            				}
         | 
| 10983 | 
            -
             | 
| 10984 | 
            -
            				if (self.tridentSel) {
         | 
| 10985 | 
            -
            					return self.tridentSel.getBookmark(type);
         | 
| 10986 | 
            -
            				}
         | 
| 10987 | 
            -
             | 
| 10988 | 
            -
            				return getLocation();
         | 
| 10989 | 
            -
            			}
         | 
| 10990 | 
            -
             | 
| 10991 | 
            -
            			// Handle simple range
         | 
| 10992 | 
            -
            			if (type) {
         | 
| 10993 | 
            -
            				return {rng: self.getRng()};
         | 
| 10994 | 
            -
            			}
         | 
| 10995 | 
            -
             | 
| 10996 | 
            -
            			rng = self.getRng();
         | 
| 10997 | 
            -
            			id = dom.uniqueId();
         | 
| 10998 | 
            -
            			collapsed = self.isCollapsed();
         | 
| 10999 | 
            -
            			styles = 'overflow:hidden;line-height:0px';
         | 
| 11000 | 
            -
             | 
| 11001 | 
            -
            			// Explorer method
         | 
| 11002 | 
            -
            			if (rng.duplicate || rng.item) {
         | 
| 11003 | 
            -
            				// Text selection
         | 
| 11004 | 
            -
            				if (!rng.item) {
         | 
| 11005 | 
            -
            					rng2 = rng.duplicate();
         | 
| 11006 | 
            -
             | 
| 11007 | 
            -
            					try {
         | 
| 11008 | 
            -
            						// Insert start marker
         | 
| 11009 | 
            -
            						rng.collapse();
         | 
| 11010 | 
            -
            						rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
         | 
| 11011 | 
            -
             | 
| 11012 | 
            -
            						// Insert end marker
         | 
| 11013 | 
            -
            						if (!collapsed) {
         | 
| 11014 | 
            -
            							rng2.collapse(false);
         | 
| 11015 | 
            -
             | 
| 11016 | 
            -
            							// Detect the empty space after block elements in IE and move the
         | 
| 11017 | 
            -
            							// end back one character <p></p>] becomes <p>]</p>
         | 
| 11018 | 
            -
            							rng.moveToElementText(rng2.parentElement());
         | 
| 11019 | 
            -
            							if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
         | 
| 11020 | 
            -
            								rng2.move('character', -1);
         | 
| 11021 | 
            -
            							}
         | 
| 11022 | 
            -
             | 
| 11023 | 
            -
            							rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
         | 
| 11024 | 
            -
            						}
         | 
| 11025 | 
            -
            					} catch (ex) {
         | 
| 11026 | 
            -
            						// IE might throw unspecified error so lets ignore it
         | 
| 11027 | 
            -
            						return null;
         | 
| 11028 | 
            -
            					}
         | 
| 11029 | 
            -
            				} else {
         | 
| 11030 | 
            -
            					// Control selection
         | 
| 11031 | 
            -
            					element = rng.item(0);
         | 
| 11032 | 
            -
            					name = element.nodeName;
         | 
| 11033 | 
            -
             | 
| 11034 | 
            -
            					return {name: name, index: findIndex(name, element)};
         | 
| 11035 | 
            -
            				}
         | 
| 11036 | 
            -
            			} else {
         | 
| 11037 | 
            -
            				element = self.getNode();
         | 
| 11038 | 
            -
            				name = element.nodeName;
         | 
| 11039 | 
            -
            				if (name == 'IMG') {
         | 
| 11040 | 
            -
            					return {name: name, index: findIndex(name, element)};
         | 
| 11041 | 
            -
            				}
         | 
| 11042 | 
            -
             | 
| 11043 | 
            -
            				// W3C method
         | 
| 11044 | 
            -
            				rng2 = normalizeTableCellSelection(rng.cloneRange());
         | 
| 11045 | 
            -
             | 
| 11046 | 
            -
            				// Insert end marker
         | 
| 11047 | 
            -
            				if (!collapsed) {
         | 
| 11048 | 
            -
            					rng2.collapse(false);
         | 
| 11049 | 
            -
            					rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
         | 
| 11050 | 
            -
            				}
         | 
| 11051 | 
            -
             | 
| 11052 | 
            -
            				rng = normalizeTableCellSelection(rng);
         | 
| 11053 | 
            -
            				rng.collapse(true);
         | 
| 11054 | 
            -
            				rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
         | 
| 11055 | 
            -
            			}
         | 
| 11056 | 
            -
             | 
| 11057 | 
            -
            			self.moveToBookmark({id: id, keep: 1});
         | 
| 11058 | 
            -
             | 
| 11059 | 
            -
            			return {id: id};
         | 
| 11467 | 
            +
            			return this.bookmarkManager.getBookmark(type, normalized);
         | 
| 11060 11468 | 
             
            		},
         | 
| 11061 11469 |  | 
| 11062 11470 | 
             
            		/**
         | 
| @@ -11075,150 +11483,7 @@ define("tinymce/dom/Selection", [ | |
| 11075 11483 | 
             
            		 * tinymce.activeEditor.selection.moveToBookmark(bm);
         | 
| 11076 11484 | 
             
            		 */
         | 
| 11077 11485 | 
             
            		moveToBookmark: function(bookmark) {
         | 
| 11078 | 
            -
            			 | 
| 11079 | 
            -
             | 
| 11080 | 
            -
            			function setEndPoint(start) {
         | 
| 11081 | 
            -
            				var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
         | 
| 11082 | 
            -
             | 
| 11083 | 
            -
            				if (point) {
         | 
| 11084 | 
            -
            					offset = point[0];
         | 
| 11085 | 
            -
             | 
| 11086 | 
            -
            					// Find container node
         | 
| 11087 | 
            -
            					for (node = root, i = point.length - 1; i >= 1; i--) {
         | 
| 11088 | 
            -
            						children = node.childNodes;
         | 
| 11089 | 
            -
             | 
| 11090 | 
            -
            						if (point[i] > children.length - 1) {
         | 
| 11091 | 
            -
            							return;
         | 
| 11092 | 
            -
            						}
         | 
| 11093 | 
            -
             | 
| 11094 | 
            -
            						node = children[point[i]];
         | 
| 11095 | 
            -
            					}
         | 
| 11096 | 
            -
             | 
| 11097 | 
            -
            					// Move text offset to best suitable location
         | 
| 11098 | 
            -
            					if (node.nodeType === 3) {
         | 
| 11099 | 
            -
            						offset = Math.min(point[0], node.nodeValue.length);
         | 
| 11100 | 
            -
            					}
         | 
| 11101 | 
            -
             | 
| 11102 | 
            -
            					// Move element offset to best suitable location
         | 
| 11103 | 
            -
            					if (node.nodeType === 1) {
         | 
| 11104 | 
            -
            						offset = Math.min(point[0], node.childNodes.length);
         | 
| 11105 | 
            -
            					}
         | 
| 11106 | 
            -
             | 
| 11107 | 
            -
            					// Set offset within container node
         | 
| 11108 | 
            -
            					if (start) {
         | 
| 11109 | 
            -
            						rng.setStart(node, offset);
         | 
| 11110 | 
            -
            					} else {
         | 
| 11111 | 
            -
            						rng.setEnd(node, offset);
         | 
| 11112 | 
            -
            					}
         | 
| 11113 | 
            -
            				}
         | 
| 11114 | 
            -
             | 
| 11115 | 
            -
            				return true;
         | 
| 11116 | 
            -
            			}
         | 
| 11117 | 
            -
             | 
| 11118 | 
            -
            			function restoreEndPoint(suffix) {
         | 
| 11119 | 
            -
            				var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
         | 
| 11120 | 
            -
             | 
| 11121 | 
            -
            				if (marker) {
         | 
| 11122 | 
            -
            					node = marker.parentNode;
         | 
| 11123 | 
            -
             | 
| 11124 | 
            -
            					if (suffix == 'start') {
         | 
| 11125 | 
            -
            						if (!keep) {
         | 
| 11126 | 
            -
            							idx = dom.nodeIndex(marker);
         | 
| 11127 | 
            -
            						} else {
         | 
| 11128 | 
            -
            							node = marker.firstChild;
         | 
| 11129 | 
            -
            							idx = 1;
         | 
| 11130 | 
            -
            						}
         | 
| 11131 | 
            -
             | 
| 11132 | 
            -
            						startContainer = endContainer = node;
         | 
| 11133 | 
            -
            						startOffset = endOffset = idx;
         | 
| 11134 | 
            -
            					} else {
         | 
| 11135 | 
            -
            						if (!keep) {
         | 
| 11136 | 
            -
            							idx = dom.nodeIndex(marker);
         | 
| 11137 | 
            -
            						} else {
         | 
| 11138 | 
            -
            							node = marker.firstChild;
         | 
| 11139 | 
            -
            							idx = 1;
         | 
| 11140 | 
            -
            						}
         | 
| 11141 | 
            -
             | 
| 11142 | 
            -
            						endContainer = node;
         | 
| 11143 | 
            -
            						endOffset = idx;
         | 
| 11144 | 
            -
            					}
         | 
| 11145 | 
            -
             | 
| 11146 | 
            -
            					if (!keep) {
         | 
| 11147 | 
            -
            						prev = marker.previousSibling;
         | 
| 11148 | 
            -
            						next = marker.nextSibling;
         | 
| 11149 | 
            -
             | 
| 11150 | 
            -
            						// Remove all marker text nodes
         | 
| 11151 | 
            -
            						each(grep(marker.childNodes), function(node) {
         | 
| 11152 | 
            -
            							if (node.nodeType == 3) {
         | 
| 11153 | 
            -
            								node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
         | 
| 11154 | 
            -
            							}
         | 
| 11155 | 
            -
            						});
         | 
| 11156 | 
            -
             | 
| 11157 | 
            -
            						// Remove marker but keep children if for example contents where inserted into the marker
         | 
| 11158 | 
            -
            						// Also remove duplicated instances of the marker for example by a
         | 
| 11159 | 
            -
            						// split operation or by WebKit auto split on paste feature
         | 
| 11160 | 
            -
            						while ((marker = dom.get(bookmark.id + '_' + suffix))) {
         | 
| 11161 | 
            -
            							dom.remove(marker, 1);
         | 
| 11162 | 
            -
            						}
         | 
| 11163 | 
            -
             | 
| 11164 | 
            -
            						// If siblings are text nodes then merge them unless it's Opera since it some how removes the node
         | 
| 11165 | 
            -
            						// and we are sniffing since adding a lot of detection code for a browser with 3% of the market
         | 
| 11166 | 
            -
            						// isn't worth the effort. Sorry, Opera but it's just a fact
         | 
| 11167 | 
            -
            						if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !isOpera) {
         | 
| 11168 | 
            -
            							idx = prev.nodeValue.length;
         | 
| 11169 | 
            -
            							prev.appendData(next.nodeValue);
         | 
| 11170 | 
            -
            							dom.remove(next);
         | 
| 11171 | 
            -
             | 
| 11172 | 
            -
            							if (suffix == 'start') {
         | 
| 11173 | 
            -
            								startContainer = endContainer = prev;
         | 
| 11174 | 
            -
            								startOffset = endOffset = idx;
         | 
| 11175 | 
            -
            							} else {
         | 
| 11176 | 
            -
            								endContainer = prev;
         | 
| 11177 | 
            -
            								endOffset = idx;
         | 
| 11178 | 
            -
            							}
         | 
| 11179 | 
            -
            						}
         | 
| 11180 | 
            -
            					}
         | 
| 11181 | 
            -
            				}
         | 
| 11182 | 
            -
            			}
         | 
| 11183 | 
            -
             | 
| 11184 | 
            -
            			function addBogus(node) {
         | 
| 11185 | 
            -
            				// Adds a bogus BR element for empty block elements
         | 
| 11186 | 
            -
            				if (dom.isBlock(node) && !node.innerHTML && !isIE) {
         | 
| 11187 | 
            -
            					node.innerHTML = '<br data-mce-bogus="1" />';
         | 
| 11188 | 
            -
            				}
         | 
| 11189 | 
            -
             | 
| 11190 | 
            -
            				return node;
         | 
| 11191 | 
            -
            			}
         | 
| 11192 | 
            -
             | 
| 11193 | 
            -
            			if (bookmark) {
         | 
| 11194 | 
            -
            				if (bookmark.start) {
         | 
| 11195 | 
            -
            					rng = dom.createRng();
         | 
| 11196 | 
            -
            					root = dom.getRoot();
         | 
| 11197 | 
            -
             | 
| 11198 | 
            -
            					if (self.tridentSel) {
         | 
| 11199 | 
            -
            						return self.tridentSel.moveToBookmark(bookmark);
         | 
| 11200 | 
            -
            					}
         | 
| 11201 | 
            -
             | 
| 11202 | 
            -
            					if (setEndPoint(true) && setEndPoint()) {
         | 
| 11203 | 
            -
            						self.setRng(rng);
         | 
| 11204 | 
            -
            					}
         | 
| 11205 | 
            -
            				} else if (bookmark.id) {
         | 
| 11206 | 
            -
            					// Restore start/end points
         | 
| 11207 | 
            -
            					restoreEndPoint('start');
         | 
| 11208 | 
            -
            					restoreEndPoint('end');
         | 
| 11209 | 
            -
             | 
| 11210 | 
            -
            					if (startContainer) {
         | 
| 11211 | 
            -
            						rng = dom.createRng();
         | 
| 11212 | 
            -
            						rng.setStart(addBogus(startContainer), startOffset);
         | 
| 11213 | 
            -
            						rng.setEnd(addBogus(endContainer), endOffset);
         | 
| 11214 | 
            -
            						self.setRng(rng);
         | 
| 11215 | 
            -
            					}
         | 
| 11216 | 
            -
            				} else if (bookmark.name) {
         | 
| 11217 | 
            -
            					self.select(dom.select(bookmark.name)[bookmark.index]);
         | 
| 11218 | 
            -
            				} else if (bookmark.rng) {
         | 
| 11219 | 
            -
            					self.setRng(bookmark.rng);
         | 
| 11220 | 
            -
            				}
         | 
| 11221 | 
            -
            			}
         | 
| 11486 | 
            +
            			return this.bookmarkManager.moveToBookmark(bookmark);
         | 
| 11222 11487 | 
             
            		},
         | 
| 11223 11488 |  | 
| 11224 11489 | 
             
            		/**
         | 
| @@ -11808,6 +12073,126 @@ define("tinymce/dom/Selection", [ | |
| 11808 12073 | 
             
            	return Selection;
         | 
| 11809 12074 | 
             
            });
         | 
| 11810 12075 |  | 
| 12076 | 
            +
            // Included from: js/tinymce/classes/dom/ElementUtils.js
         | 
| 12077 | 
            +
             | 
| 12078 | 
            +
            /**
         | 
| 12079 | 
            +
             * ElementUtils.js
         | 
| 12080 | 
            +
             *
         | 
| 12081 | 
            +
             * Copyright, Moxiecode Systems AB
         | 
| 12082 | 
            +
             * Released under LGPL License.
         | 
| 12083 | 
            +
             *
         | 
| 12084 | 
            +
             * License: http://www.tinymce.com/license
         | 
| 12085 | 
            +
             * Contributing: http://www.tinymce.com/contributing
         | 
| 12086 | 
            +
             */
         | 
| 12087 | 
            +
             | 
| 12088 | 
            +
            /**
         | 
| 12089 | 
            +
             * Utility class for various element specific functions.
         | 
| 12090 | 
            +
             *
         | 
| 12091 | 
            +
             * @private
         | 
| 12092 | 
            +
             */
         | 
| 12093 | 
            +
            define("tinymce/dom/ElementUtils", [
         | 
| 12094 | 
            +
            	"tinymce/dom/BookmarkManager",
         | 
| 12095 | 
            +
            	"tinymce/util/Tools"
         | 
| 12096 | 
            +
            ], function(BookmarkManager, Tools) {
         | 
| 12097 | 
            +
            	var each = Tools.each;
         | 
| 12098 | 
            +
             | 
| 12099 | 
            +
            	function ElementUtils(dom) {
         | 
| 12100 | 
            +
            		/**
         | 
| 12101 | 
            +
            		 * Compares two nodes and checks if it's attributes and styles matches.
         | 
| 12102 | 
            +
            		 * This doesn't compare classes as items since their order is significant.
         | 
| 12103 | 
            +
            		 *
         | 
| 12104 | 
            +
            		 * @method compare
         | 
| 12105 | 
            +
            		 * @param {Node} node1 First node to compare with.
         | 
| 12106 | 
            +
            		 * @param {Node} node2 Second node to compare with.
         | 
| 12107 | 
            +
            		 * @return {boolean} True/false if the nodes are the same or not.
         | 
| 12108 | 
            +
            		 */
         | 
| 12109 | 
            +
            		this.compare = function(node1, node2) {
         | 
| 12110 | 
            +
            			// Not the same name
         | 
| 12111 | 
            +
            			if (node1.nodeName != node2.nodeName) {
         | 
| 12112 | 
            +
            				return false;
         | 
| 12113 | 
            +
            			}
         | 
| 12114 | 
            +
             | 
| 12115 | 
            +
            			/**
         | 
| 12116 | 
            +
            			 * Returns all the nodes attributes excluding internal ones, styles and classes.
         | 
| 12117 | 
            +
            			 *
         | 
| 12118 | 
            +
            			 * @private
         | 
| 12119 | 
            +
            			 * @param {Node} node Node to get attributes from.
         | 
| 12120 | 
            +
            			 * @return {Object} Name/value object with attributes and attribute values.
         | 
| 12121 | 
            +
            			 */
         | 
| 12122 | 
            +
            			function getAttribs(node) {
         | 
| 12123 | 
            +
            				var attribs = {};
         | 
| 12124 | 
            +
             | 
| 12125 | 
            +
            				each(dom.getAttribs(node), function(attr) {
         | 
| 12126 | 
            +
            					var name = attr.nodeName.toLowerCase();
         | 
| 12127 | 
            +
             | 
| 12128 | 
            +
            					// Don't compare internal attributes or style
         | 
| 12129 | 
            +
            					if (name.indexOf('_') !== 0 && name !== 'style' && name !== 'data-mce-style') {
         | 
| 12130 | 
            +
            						attribs[name] = dom.getAttrib(node, name);
         | 
| 12131 | 
            +
            					}
         | 
| 12132 | 
            +
            				});
         | 
| 12133 | 
            +
             | 
| 12134 | 
            +
            				return attribs;
         | 
| 12135 | 
            +
            			}
         | 
| 12136 | 
            +
             | 
| 12137 | 
            +
            			/**
         | 
| 12138 | 
            +
            			 * Compares two objects checks if it's key + value exists in the other one.
         | 
| 12139 | 
            +
            			 *
         | 
| 12140 | 
            +
            			 * @private
         | 
| 12141 | 
            +
            			 * @param {Object} obj1 First object to compare.
         | 
| 12142 | 
            +
            			 * @param {Object} obj2 Second object to compare.
         | 
| 12143 | 
            +
            			 * @return {boolean} True/false if the objects matches or not.
         | 
| 12144 | 
            +
            			 */
         | 
| 12145 | 
            +
            			function compareObjects(obj1, obj2) {
         | 
| 12146 | 
            +
            				var value, name;
         | 
| 12147 | 
            +
             | 
| 12148 | 
            +
            				for (name in obj1) {
         | 
| 12149 | 
            +
            					// Obj1 has item obj2 doesn't have
         | 
| 12150 | 
            +
            					if (obj1.hasOwnProperty(name)) {
         | 
| 12151 | 
            +
            						value = obj2[name];
         | 
| 12152 | 
            +
             | 
| 12153 | 
            +
            						// Obj2 doesn't have obj1 item
         | 
| 12154 | 
            +
            						if (typeof value == "undefined") {
         | 
| 12155 | 
            +
            							return false;
         | 
| 12156 | 
            +
            						}
         | 
| 12157 | 
            +
             | 
| 12158 | 
            +
            						// Obj2 item has a different value
         | 
| 12159 | 
            +
            						if (obj1[name] != value) {
         | 
| 12160 | 
            +
            							return false;
         | 
| 12161 | 
            +
            						}
         | 
| 12162 | 
            +
             | 
| 12163 | 
            +
            						// Delete similar value
         | 
| 12164 | 
            +
            						delete obj2[name];
         | 
| 12165 | 
            +
            					}
         | 
| 12166 | 
            +
            				}
         | 
| 12167 | 
            +
             | 
| 12168 | 
            +
            				// Check if obj 2 has something obj 1 doesn't have
         | 
| 12169 | 
            +
            				for (name in obj2) {
         | 
| 12170 | 
            +
            					// Obj2 has item obj1 doesn't have
         | 
| 12171 | 
            +
            					if (obj2.hasOwnProperty(name)) {
         | 
| 12172 | 
            +
            						return false;
         | 
| 12173 | 
            +
            					}
         | 
| 12174 | 
            +
            				}
         | 
| 12175 | 
            +
             | 
| 12176 | 
            +
            				return true;
         | 
| 12177 | 
            +
            			}
         | 
| 12178 | 
            +
             | 
| 12179 | 
            +
            			// Attribs are not the same
         | 
| 12180 | 
            +
            			if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
         | 
| 12181 | 
            +
            				return false;
         | 
| 12182 | 
            +
            			}
         | 
| 12183 | 
            +
             | 
| 12184 | 
            +
            			// Styles are not the same
         | 
| 12185 | 
            +
            			if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
         | 
| 12186 | 
            +
            				return false;
         | 
| 12187 | 
            +
            			}
         | 
| 12188 | 
            +
             | 
| 12189 | 
            +
            			return !BookmarkManager.isBookmarkNode(node1) && !BookmarkManager.isBookmarkNode(node2);
         | 
| 12190 | 
            +
            		};
         | 
| 12191 | 
            +
            	}
         | 
| 12192 | 
            +
             | 
| 12193 | 
            +
            	return ElementUtils;
         | 
| 12194 | 
            +
            });
         | 
| 12195 | 
            +
             | 
| 11811 12196 | 
             
            // Included from: js/tinymce/classes/fmt/Preview.js
         | 
| 11812 12197 |  | 
| 11813 12198 | 
             
            /**
         | 
| @@ -11991,9 +12376,11 @@ define("tinymce/fmt/Preview", [ | |
| 11991 12376 | 
             
            define("tinymce/Formatter", [
         | 
| 11992 12377 | 
             
            	"tinymce/dom/TreeWalker",
         | 
| 11993 12378 | 
             
            	"tinymce/dom/RangeUtils",
         | 
| 12379 | 
            +
            	"tinymce/dom/BookmarkManager",
         | 
| 12380 | 
            +
            	"tinymce/dom/ElementUtils",
         | 
| 11994 12381 | 
             
            	"tinymce/util/Tools",
         | 
| 11995 12382 | 
             
            	"tinymce/fmt/Preview"
         | 
| 11996 | 
            -
            ], function(TreeWalker, RangeUtils, Tools, Preview) {
         | 
| 12383 | 
            +
            ], function(TreeWalker, RangeUtils, BookmarkManager, ElementUtils, Tools, Preview) {
         | 
| 11997 12384 | 
             
            	/**
         | 
| 11998 12385 | 
             
            	 * Constructs a new formatter instance.
         | 
| 11999 12386 | 
             
            	 *
         | 
| @@ -12017,7 +12404,8 @@ define("tinymce/Formatter", [ | |
| 12017 12404 | 
             
            			undef,
         | 
| 12018 12405 | 
             
            			getContentEditable = dom.getContentEditable,
         | 
| 12019 12406 | 
             
            			disableCaretContainer,
         | 
| 12020 | 
            -
            			markCaretContainersBogus | 
| 12407 | 
            +
            			markCaretContainersBogus,
         | 
| 12408 | 
            +
            			isBookmarkNode = BookmarkManager.isBookmarkNode;
         | 
| 12021 12409 |  | 
| 12022 12410 | 
             
            		var each = Tools.each,
         | 
| 12023 12411 | 
             
            			grep = Tools.grep,
         | 
| @@ -12042,7 +12430,6 @@ define("tinymce/Formatter", [ | |
| 12042 12430 |  | 
| 12043 12431 | 
             
            		function defaultFormats() {
         | 
| 12044 12432 | 
             
            			register({
         | 
| 12045 | 
            -
            				
         | 
| 12046 12433 | 
             
            				valigntop: [
         | 
| 12047 12434 | 
             
            					{selector: 'td,th', styles: {'verticalAlign': 'top'}}
         | 
| 12048 12435 | 
             
            				],
         | 
| @@ -12333,7 +12720,7 @@ define("tinymce/Formatter", [ | |
| 12333 12720 |  | 
| 12334 12721 | 
             
            				// get the index of the bookmarks
         | 
| 12335 12722 | 
             
            				each(node.childNodes, function(n, index) {
         | 
| 12336 | 
            -
            					if ( | 
| 12723 | 
            +
            					if (isBookmarkNode(n)) {
         | 
| 12337 12724 | 
             
            						if (n.id == bookmark.id + "_start") {
         | 
| 12338 12725 | 
             
            							startIndex = index;
         | 
| 12339 12726 | 
             
            						} else if (n.id == bookmark.id + "_end") {
         | 
| @@ -13903,21 +14290,10 @@ define("tinymce/Formatter", [ | |
| 13903 14290 |  | 
| 13904 14291 | 
             
            				for (node = inc ? node : node[next]; node; node = node[next]) {
         | 
| 13905 14292 | 
             
            					if (node.nodeType == 1 || !isWhiteSpaceNode(node)) {
         | 
| 13906 | 
            -
            						return node;
         | 
| 13907 | 
            -
            					}
         | 
| 13908 | 
            -
            				}
         | 
| 13909 | 
            -
            			}
         | 
| 13910 | 
            -
            		}
         | 
| 13911 | 
            -
             | 
| 13912 | 
            -
            		/**
         | 
| 13913 | 
            -
            		 * Checks if the specified node is a bookmark node or not.
         | 
| 13914 | 
            -
            		 *
         | 
| 13915 | 
            -
            		 * @private
         | 
| 13916 | 
            -
            		 * @param {Node} node Node to check if it's a bookmark node or not.
         | 
| 13917 | 
            -
            		 * @return {Boolean} true/false if the node is a bookmark node.
         | 
| 13918 | 
            -
            		 */
         | 
| 13919 | 
            -
            		function isBookmarkNode(node) {
         | 
| 13920 | 
            -
            			return node && node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark';
         | 
| 14293 | 
            +
            						return node;
         | 
| 14294 | 
            +
            					}
         | 
| 14295 | 
            +
            				}
         | 
| 14296 | 
            +
            			}
         | 
| 13921 14297 | 
             
            		}
         | 
| 13922 14298 |  | 
| 13923 14299 | 
             
            		/**
         | 
| @@ -13929,99 +14305,7 @@ define("tinymce/Formatter", [ | |
| 13929 14305 | 
             
            		 * @return {Node} Next node if we didn't merge and prev node if we did.
         | 
| 13930 14306 | 
             
            		 */
         | 
| 13931 14307 | 
             
            		function mergeSiblings(prev, next) {
         | 
| 13932 | 
            -
            			var sibling, tmpSibling;
         | 
| 13933 | 
            -
             | 
| 13934 | 
            -
            			/**
         | 
| 13935 | 
            -
            			 * Compares two nodes and checks if it's attributes and styles matches.
         | 
| 13936 | 
            -
            			 * This doesn't compare classes as items since their order is significant.
         | 
| 13937 | 
            -
            			 *
         | 
| 13938 | 
            -
            			 * @private
         | 
| 13939 | 
            -
            			 * @param {Node} node1 First node to compare with.
         | 
| 13940 | 
            -
            			 * @param {Node} node2 Second node to compare with.
         | 
| 13941 | 
            -
            			 * @return {boolean} True/false if the nodes are the same or not.
         | 
| 13942 | 
            -
            			 */
         | 
| 13943 | 
            -
            			function compareElements(node1, node2) {
         | 
| 13944 | 
            -
            				// Not the same name
         | 
| 13945 | 
            -
            				if (node1.nodeName != node2.nodeName) {
         | 
| 13946 | 
            -
            					return FALSE;
         | 
| 13947 | 
            -
            				}
         | 
| 13948 | 
            -
             | 
| 13949 | 
            -
            				/**
         | 
| 13950 | 
            -
            				 * Returns all the nodes attributes excluding internal ones, styles and classes.
         | 
| 13951 | 
            -
            				 *
         | 
| 13952 | 
            -
            				 * @private
         | 
| 13953 | 
            -
            				 * @param {Node} node Node to get attributes from.
         | 
| 13954 | 
            -
            				 * @return {Object} Name/value object with attributes and attribute values.
         | 
| 13955 | 
            -
            				 */
         | 
| 13956 | 
            -
            				function getAttribs(node) {
         | 
| 13957 | 
            -
            					var attribs = {};
         | 
| 13958 | 
            -
             | 
| 13959 | 
            -
            					each(dom.getAttribs(node), function(attr) {
         | 
| 13960 | 
            -
            						var name = attr.nodeName.toLowerCase();
         | 
| 13961 | 
            -
             | 
| 13962 | 
            -
            						// Don't compare internal attributes or style
         | 
| 13963 | 
            -
            						if (name.indexOf('_') !== 0 && name !== 'style' && name !== 'data-mce-style') {
         | 
| 13964 | 
            -
            							attribs[name] = dom.getAttrib(node, name);
         | 
| 13965 | 
            -
            						}
         | 
| 13966 | 
            -
            					});
         | 
| 13967 | 
            -
             | 
| 13968 | 
            -
            					return attribs;
         | 
| 13969 | 
            -
            				}
         | 
| 13970 | 
            -
             | 
| 13971 | 
            -
            				/**
         | 
| 13972 | 
            -
            				 * Compares two objects checks if it's key + value exists in the other one.
         | 
| 13973 | 
            -
            				 *
         | 
| 13974 | 
            -
            				 * @private
         | 
| 13975 | 
            -
            				 * @param {Object} obj1 First object to compare.
         | 
| 13976 | 
            -
            				 * @param {Object} obj2 Second object to compare.
         | 
| 13977 | 
            -
            				 * @return {boolean} True/false if the objects matches or not.
         | 
| 13978 | 
            -
            				 */
         | 
| 13979 | 
            -
            				function compareObjects(obj1, obj2) {
         | 
| 13980 | 
            -
            					var value, name;
         | 
| 13981 | 
            -
             | 
| 13982 | 
            -
            					for (name in obj1) {
         | 
| 13983 | 
            -
            						// Obj1 has item obj2 doesn't have
         | 
| 13984 | 
            -
            						if (obj1.hasOwnProperty(name)) {
         | 
| 13985 | 
            -
            							value = obj2[name];
         | 
| 13986 | 
            -
             | 
| 13987 | 
            -
            							// Obj2 doesn't have obj1 item
         | 
| 13988 | 
            -
            							if (value === undef) {
         | 
| 13989 | 
            -
            								return FALSE;
         | 
| 13990 | 
            -
            							}
         | 
| 13991 | 
            -
             | 
| 13992 | 
            -
            							// Obj2 item has a different value
         | 
| 13993 | 
            -
            							if (obj1[name] != value) {
         | 
| 13994 | 
            -
            								return FALSE;
         | 
| 13995 | 
            -
            							}
         | 
| 13996 | 
            -
             | 
| 13997 | 
            -
            							// Delete similar value
         | 
| 13998 | 
            -
            							delete obj2[name];
         | 
| 13999 | 
            -
            						}
         | 
| 14000 | 
            -
            					}
         | 
| 14001 | 
            -
             | 
| 14002 | 
            -
            					// Check if obj 2 has something obj 1 doesn't have
         | 
| 14003 | 
            -
            					for (name in obj2) {
         | 
| 14004 | 
            -
            						// Obj2 has item obj1 doesn't have
         | 
| 14005 | 
            -
            						if (obj2.hasOwnProperty(name)) {
         | 
| 14006 | 
            -
            							return FALSE;
         | 
| 14007 | 
            -
            						}
         | 
| 14008 | 
            -
            					}
         | 
| 14009 | 
            -
             | 
| 14010 | 
            -
            					return TRUE;
         | 
| 14011 | 
            -
            				}
         | 
| 14012 | 
            -
             | 
| 14013 | 
            -
            				// Attribs are not the same
         | 
| 14014 | 
            -
            				if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
         | 
| 14015 | 
            -
            					return FALSE;
         | 
| 14016 | 
            -
            				}
         | 
| 14017 | 
            -
             | 
| 14018 | 
            -
            				// Styles are not the same
         | 
| 14019 | 
            -
            				if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
         | 
| 14020 | 
            -
            					return FALSE;
         | 
| 14021 | 
            -
            				}
         | 
| 14022 | 
            -
             | 
| 14023 | 
            -
            				return !isBookmarkNode(node1) && !isBookmarkNode(node2);
         | 
| 14024 | 
            -
            			}
         | 
| 14308 | 
            +
            			var sibling, tmpSibling, elementUtils = new ElementUtils(dom);
         | 
| 14025 14309 |  | 
| 14026 14310 | 
             
            			function findElementSibling(node, sibling_name) {
         | 
| 14027 14311 | 
             
            				for (sibling = node; sibling; sibling = sibling[sibling_name]) {
         | 
| @@ -14044,7 +14328,7 @@ define("tinymce/Formatter", [ | |
| 14044 14328 | 
             
            				next = findElementSibling(next, 'nextSibling');
         | 
| 14045 14329 |  | 
| 14046 14330 | 
             
            				// Compare next and previous nodes
         | 
| 14047 | 
            -
            				if ( | 
| 14331 | 
            +
            				if (elementUtils.compare(prev, next)) {
         | 
| 14048 14332 | 
             
            					// Append nodes between
         | 
| 14049 14333 | 
             
            					for (sibling = prev.nextSibling; sibling && sibling != next;) {
         | 
| 14050 14334 | 
             
            						tmpSibling = sibling;
         | 
| @@ -14247,7 +14531,7 @@ define("tinymce/Formatter", [ | |
| 14247 14531 | 
             
            				node = container;
         | 
| 14248 14532 |  | 
| 14249 14533 | 
             
            				if (container.nodeType == 3) {
         | 
| 14250 | 
            -
            					if (offset != container.nodeValue.length | 
| 14534 | 
            +
            					if (offset != container.nodeValue.length) {
         | 
| 14251 14535 | 
             
            						hasContentAfter = true;
         | 
| 14252 14536 | 
             
            					}
         | 
| 14253 14537 |  | 
| @@ -14829,6 +15113,10 @@ define("tinymce/EnterKey", [ | |
| 14829 15113 | 
             
            			function trimInlineElementsOnLeftSideOfBlock(block) {
         | 
| 14830 15114 | 
             
            				var node = block, firstChilds = [], i;
         | 
| 14831 15115 |  | 
| 15116 | 
            +
            				if (!node) {
         | 
| 15117 | 
            +
            					return;
         | 
| 15118 | 
            +
            				}
         | 
| 15119 | 
            +
             | 
| 14832 15120 | 
             
            				// Find inner most first child ex: <p><i><b>*</b></i></p>
         | 
| 14833 15121 | 
             
            				while ((node = node.firstChild)) {
         | 
| 14834 15122 | 
             
            					if (dom.isBlock(node)) {
         | 
| @@ -14869,6 +15157,10 @@ define("tinymce/EnterKey", [ | |
| 14869 15157 | 
             
            					}
         | 
| 14870 15158 | 
             
            				}
         | 
| 14871 15159 |  | 
| 15160 | 
            +
            				if (!root) {
         | 
| 15161 | 
            +
            					return;
         | 
| 15162 | 
            +
            				}
         | 
| 15163 | 
            +
             | 
| 14872 15164 | 
             
            				// Old IE versions doesn't properly render blocks with br elements in them
         | 
| 14873 15165 | 
             
            				// For example <p><br></p> wont be rendered correctly in a contentEditable area
         | 
| 14874 15166 | 
             
            				// until you remove the br producing <p></p>
         | 
| @@ -14878,16 +15170,23 @@ define("tinymce/EnterKey", [ | |
| 14878 15170 | 
             
            					}
         | 
| 14879 15171 | 
             
            				}
         | 
| 14880 15172 |  | 
| 14881 | 
            -
            				if (root.nodeName | 
| 15173 | 
            +
            				if (/^(LI|DT|DD)$/.test(root.nodeName)) {
         | 
| 14882 15174 | 
             
            					var firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
         | 
| 14883 15175 |  | 
| 14884 | 
            -
            					if (firstChild && /^(UL|OL)$/.test(firstChild.nodeName)) {
         | 
| 15176 | 
            +
            					if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
         | 
| 14885 15177 | 
             
            						root.insertBefore(dom.doc.createTextNode('\u00a0'), root.firstChild);
         | 
| 14886 15178 | 
             
            					}
         | 
| 14887 15179 | 
             
            				}
         | 
| 14888 15180 |  | 
| 14889 15181 | 
             
            				rng = dom.createRng();
         | 
| 14890 15182 |  | 
| 15183 | 
            +
            				// Normalize whitespace to remove empty text nodes. Fix for: #6904
         | 
| 15184 | 
            +
            				// Gecko will be able to place the caret in empty text nodes but it won't render propery
         | 
| 15185 | 
            +
            				// Older IE versions will sometimes crash so for now ignore all IE versions
         | 
| 15186 | 
            +
            				if (!Env.ie) {
         | 
| 15187 | 
            +
            					root.normalize();
         | 
| 15188 | 
            +
            				}
         | 
| 15189 | 
            +
             | 
| 14891 15190 | 
             
            				if (root.hasChildNodes()) {
         | 
| 14892 15191 | 
             
            					walker = new TreeWalker(root, root);
         | 
| 14893 15192 |  | 
| @@ -14951,7 +15250,7 @@ define("tinymce/EnterKey", [ | |
| 14951 15250 | 
             
            			// Creates a new block element by cloning the current one or creating a new one if the name is specified
         | 
| 14952 15251 | 
             
            			// This function will also copy any text formatting from the parent block and add it to the new one
         | 
| 14953 15252 | 
             
            			function createNewBlock(name) {
         | 
| 14954 | 
            -
            				var node = container, block, clonedNode, caretNode;
         | 
| 15253 | 
            +
            				var node = container, block, clonedNode, caretNode, textInlineElements = schema.getTextInlineElements();
         | 
| 14955 15254 |  | 
| 14956 15255 | 
             
            				if (name || parentBlockName == "TABLE") {
         | 
| 14957 15256 | 
             
            					block = dom.create(name || newBlockName);
         | 
| @@ -14965,7 +15264,7 @@ define("tinymce/EnterKey", [ | |
| 14965 15264 | 
             
            				// Clone any parent styles
         | 
| 14966 15265 | 
             
            				if (settings.keep_styles !== false) {
         | 
| 14967 15266 | 
             
            					do {
         | 
| 14968 | 
            -
            						if ( | 
| 15267 | 
            +
            						if (textInlineElements[node.nodeName]) {
         | 
| 14969 15268 | 
             
            							// Never clone a caret containers
         | 
| 14970 15269 | 
             
            							if (node.id == '_mce_caret') {
         | 
| 14971 15270 | 
             
            								continue;
         | 
| @@ -15126,7 +15425,7 @@ define("tinymce/EnterKey", [ | |
| 15126 15425 | 
             
            				function getContainerBlock() {
         | 
| 15127 15426 | 
             
            					var containerBlockParent = containerBlock.parentNode;
         | 
| 15128 15427 |  | 
| 15129 | 
            -
            					if (containerBlockParent.nodeName | 
| 15428 | 
            +
            					if (/^(LI|DT|DD)$/.test(containerBlockParent.nodeName)) {
         | 
| 15130 15429 | 
             
            						return containerBlockParent;
         | 
| 15131 15430 | 
             
            					}
         | 
| 15132 15431 |  | 
| @@ -15356,8 +15655,8 @@ define("tinymce/EnterKey", [ | |
| 15356 15655 | 
             
            				parentBlockName = containerBlockName;
         | 
| 15357 15656 | 
             
            			}
         | 
| 15358 15657 |  | 
| 15359 | 
            -
            			// Handle enter in  | 
| 15360 | 
            -
            			if ( | 
| 15658 | 
            +
            			// Handle enter in list item
         | 
| 15659 | 
            +
            			if (/^(LI|DT|DD)$/.test(parentBlockName)) {
         | 
| 15361 15660 | 
             
            				if (!newBlockName && shiftKey) {
         | 
| 15362 15661 | 
             
            					insertBr();
         | 
| 15363 15662 | 
             
            					return;
         | 
| @@ -15602,8 +15901,9 @@ define("tinymce/ForceBlocks", [], function() { | |
| 15602 15901 | 
             
            define("tinymce/EditorCommands", [
         | 
| 15603 15902 | 
             
            	"tinymce/html/Serializer",
         | 
| 15604 15903 | 
             
            	"tinymce/Env",
         | 
| 15605 | 
            -
            	"tinymce/util/Tools"
         | 
| 15606 | 
            -
             | 
| 15904 | 
            +
            	"tinymce/util/Tools",
         | 
| 15905 | 
            +
            	"tinymce/dom/ElementUtils"
         | 
| 15906 | 
            +
            ], function(Serializer, Env, Tools, ElementUtils) {
         | 
| 15607 15907 | 
             
            	// Added for compression purposes
         | 
| 15608 15908 | 
             
            	var each = Tools.each, extend = Tools.extend;
         | 
| 15609 15909 | 
             
            	var map = Tools.map, inArray = Tools.inArray, explode = Tools.explode;
         | 
| @@ -15898,7 +16198,8 @@ define("tinymce/EditorCommands", [ | |
| 15898 16198 |  | 
| 15899 16199 | 
             
            			mceInsertContent: function(command, ui, value) {
         | 
| 15900 16200 | 
             
            				var parser, serializer, parentNode, rootNode, fragment, args;
         | 
| 15901 | 
            -
            				var marker, rng, node, node2, bookmarkHtml;
         | 
| 16201 | 
            +
            				var marker, rng, node, node2, bookmarkHtml, merge;
         | 
| 16202 | 
            +
            				var textInlineElements = editor.schema.getTextInlineElements();
         | 
| 15902 16203 |  | 
| 15903 16204 | 
             
            				function trimOrPaddLeftRight(html) {
         | 
| 15904 16205 | 
             
            					var rng, container, offset;
         | 
| @@ -15928,6 +16229,37 @@ define("tinymce/EditorCommands", [ | |
| 15928 16229 | 
             
            					return html;
         | 
| 15929 16230 | 
             
            				}
         | 
| 15930 16231 |  | 
| 16232 | 
            +
            				function markInlineFormatElements(fragment) {
         | 
| 16233 | 
            +
            					if (merge) {
         | 
| 16234 | 
            +
            						for (node = fragment.firstChild; node; node = node.walk(true)) {
         | 
| 16235 | 
            +
            							if (textInlineElements[node.name]) {
         | 
| 16236 | 
            +
            								node.attr('data-mce-new', "true");
         | 
| 16237 | 
            +
            							}
         | 
| 16238 | 
            +
            						}
         | 
| 16239 | 
            +
            					}
         | 
| 16240 | 
            +
            				}
         | 
| 16241 | 
            +
             | 
| 16242 | 
            +
            				function reduceInlineTextElements() {
         | 
| 16243 | 
            +
            					if (merge) {
         | 
| 16244 | 
            +
            						var root = editor.getBody(), elementUtils = new ElementUtils(dom);
         | 
| 16245 | 
            +
             | 
| 16246 | 
            +
            						each(dom.select('*[data-mce-new]'), function(node) {
         | 
| 16247 | 
            +
            							node.removeAttribute('data-mce-new');
         | 
| 16248 | 
            +
             | 
| 16249 | 
            +
            							for (var testNode = node.parentNode; testNode && testNode != root; testNode = testNode.parentNode) {
         | 
| 16250 | 
            +
            								if (elementUtils.compare(testNode, node)) {
         | 
| 16251 | 
            +
            									dom.remove(node, true);
         | 
| 16252 | 
            +
            								}
         | 
| 16253 | 
            +
            							}
         | 
| 16254 | 
            +
            						});
         | 
| 16255 | 
            +
            					}
         | 
| 16256 | 
            +
            				}
         | 
| 16257 | 
            +
             | 
| 16258 | 
            +
            				if (typeof(value) != 'string') {
         | 
| 16259 | 
            +
            					merge = value.merge;
         | 
| 16260 | 
            +
            					value = value.content;
         | 
| 16261 | 
            +
            				}
         | 
| 16262 | 
            +
             | 
| 15931 16263 | 
             
            				// Check for whitespace before/after value
         | 
| 15932 16264 | 
             
            				if (/^ | $/.test(value)) {
         | 
| 15933 16265 | 
             
            					value = trimOrPaddLeftRight(value);
         | 
| @@ -15975,6 +16307,8 @@ define("tinymce/EditorCommands", [ | |
| 15975 16307 | 
             
            				var parserArgs = {context: parentNode.nodeName.toLowerCase()};
         | 
| 15976 16308 | 
             
            				fragment = parser.parse(value, parserArgs);
         | 
| 15977 16309 |  | 
| 16310 | 
            +
            				markInlineFormatElements(fragment);
         | 
| 16311 | 
            +
             | 
| 15978 16312 | 
             
            				// Move the caret to a more suitable location
         | 
| 15979 16313 | 
             
            				node = fragment.lastChild;
         | 
| 15980 16314 | 
             
            				if (node.attr('id') == 'mce_marker') {
         | 
| @@ -16041,6 +16375,8 @@ define("tinymce/EditorCommands", [ | |
| 16041 16375 | 
             
            					}
         | 
| 16042 16376 | 
             
            				}
         | 
| 16043 16377 |  | 
| 16378 | 
            +
            				reduceInlineTextElements();
         | 
| 16379 | 
            +
             | 
| 16044 16380 | 
             
            				marker = dom.get('mce_marker');
         | 
| 16045 16381 | 
             
            				selection.scrollIntoView(marker);
         | 
| 16046 16382 |  | 
| @@ -16343,11 +16679,9 @@ define("tinymce/util/URI", [ | |
| 16343 16679 | 
             
            	function URI(url, settings) {
         | 
| 16344 16680 | 
             
            		var self = this, baseUri, base_url;
         | 
| 16345 16681 |  | 
| 16346 | 
            -
            		// Trim whitespace
         | 
| 16347 16682 | 
             
            		url = trim(url);
         | 
| 16348 | 
            -
             | 
| 16349 | 
            -
            		// Default settings
         | 
| 16350 16683 | 
             
            		settings = self.settings = settings || {};
         | 
| 16684 | 
            +
            		baseUri = settings.base_uri;
         | 
| 16351 16685 |  | 
| 16352 16686 | 
             
            		// Strange app protocol that isn't http/https or local anchor
         | 
| 16353 16687 | 
             
            		// For example: mailto,skype,tel etc.
         | 
| @@ -16360,7 +16694,7 @@ define("tinymce/util/URI", [ | |
| 16360 16694 |  | 
| 16361 16695 | 
             
            		// Absolute path with no host, fake host and protocol
         | 
| 16362 16696 | 
             
            		if (url.indexOf('/') === 0 && !isProtocolRelative) {
         | 
| 16363 | 
            -
            			url = ( | 
| 16697 | 
            +
            			url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
         | 
| 16364 16698 | 
             
            		}
         | 
| 16365 16699 |  | 
| 16366 16700 | 
             
            		// Relative path http:// or protocol relative //path
         | 
| @@ -16369,7 +16703,8 @@ define("tinymce/util/URI", [ | |
| 16369 16703 | 
             
            			if (settings.base_uri.protocol === "") {
         | 
| 16370 16704 | 
             
            				url = '//mce_host' + self.toAbsPath(base_url, url);
         | 
| 16371 16705 | 
             
            			} else {
         | 
| 16372 | 
            -
            				url = (( | 
| 16706 | 
            +
            				url = /([^#?]*)([#?]?.*)/.exec(url);
         | 
| 16707 | 
            +
            				url = ((baseUri && baseUri.protocol) || 'http') + '://mce_host' + self.toAbsPath(base_url, url[1]) + url[2];
         | 
| 16373 16708 | 
             
            			}
         | 
| 16374 16709 | 
             
            		}
         | 
| 16375 16710 |  | 
| @@ -16391,7 +16726,6 @@ define("tinymce/util/URI", [ | |
| 16391 16726 | 
             
            			self[v] = part;
         | 
| 16392 16727 | 
             
            		});
         | 
| 16393 16728 |  | 
| 16394 | 
            -
            		baseUri = settings.base_uri;
         | 
| 16395 16729 | 
             
            		if (baseUri) {
         | 
| 16396 16730 | 
             
            			if (!self.protocol) {
         | 
| 16397 16731 | 
             
            				self.protocol = baseUri.protocol;
         | 
| @@ -16901,7 +17235,8 @@ define("tinymce/util/EventDispatcher", [ | |
| 16901 17235 | 
             
            	var nativeEvents = Tools.makeMap(
         | 
| 16902 17236 | 
             
            		"focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange " +
         | 
| 16903 17237 | 
             
            		"mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover " +
         | 
| 16904 | 
            -
            		"draggesture dragdrop drop drag submit" | 
| 17238 | 
            +
            		"draggesture dragdrop drop drag submit " +
         | 
| 17239 | 
            +
            		"compositionstart compositionend compositionupdate",
         | 
| 16905 17240 | 
             
            		' '
         | 
| 16906 17241 | 
             
            	);
         | 
| 16907 17242 |  | 
| @@ -17958,9 +18293,11 @@ define("tinymce/ui/DomUtils", [ | |
| 17958 18293 | 
             
            ], function(Tools, DOMUtils) {
         | 
| 17959 18294 | 
             
            	"use strict";
         | 
| 17960 18295 |  | 
| 18296 | 
            +
            	var count = 0;
         | 
| 18297 | 
            +
             | 
| 17961 18298 | 
             
            	return {
         | 
| 17962 18299 | 
             
            		id: function() {
         | 
| 17963 | 
            -
            			return  | 
| 18300 | 
            +
            			return 'mceu_' + (count++);
         | 
| 17964 18301 | 
             
            		},
         | 
| 17965 18302 |  | 
| 17966 18303 | 
             
            		createFragment: function(html) {
         | 
| @@ -21194,9 +21531,117 @@ define("tinymce/ui/FloatPanel", [ | |
| 21194 21531 | 
             
            ], function(Panel, Movable, Resizable, DomUtils) {
         | 
| 21195 21532 | 
             
            	"use strict";
         | 
| 21196 21533 |  | 
| 21197 | 
            -
            	var documentClickHandler, documentScrollHandler, visiblePanels = [];
         | 
| 21534 | 
            +
            	var documentClickHandler, documentScrollHandler, windowResizeHandler, visiblePanels = [];
         | 
| 21198 21535 | 
             
            	var zOrder = [], hasModal;
         | 
| 21199 21536 |  | 
| 21537 | 
            +
            	function bindDocumentClickHandler() {
         | 
| 21538 | 
            +
            		function isChildOf(ctrl, parent) {
         | 
| 21539 | 
            +
            			while (ctrl) {
         | 
| 21540 | 
            +
            				if (ctrl == parent) {
         | 
| 21541 | 
            +
            					return true;
         | 
| 21542 | 
            +
            				}
         | 
| 21543 | 
            +
             | 
| 21544 | 
            +
            				ctrl = ctrl.parent();
         | 
| 21545 | 
            +
            			}
         | 
| 21546 | 
            +
            		}
         | 
| 21547 | 
            +
             | 
| 21548 | 
            +
            		if (!documentClickHandler) {
         | 
| 21549 | 
            +
            			documentClickHandler = function(e) {
         | 
| 21550 | 
            +
            				// Gecko fires click event and in the wrong order on Mac so lets normalize
         | 
| 21551 | 
            +
            				if (e.button == 2) {
         | 
| 21552 | 
            +
            					return;
         | 
| 21553 | 
            +
            				}
         | 
| 21554 | 
            +
             | 
| 21555 | 
            +
            				// Hide any float panel when a click is out side that float panel and the
         | 
| 21556 | 
            +
            				// float panels direct parent for example a click on a menu button
         | 
| 21557 | 
            +
            				var i = visiblePanels.length;
         | 
| 21558 | 
            +
            				while (i--) {
         | 
| 21559 | 
            +
            					var panel = visiblePanels[i], clickCtrl = panel.getParentCtrl(e.target);
         | 
| 21560 | 
            +
             | 
| 21561 | 
            +
            					if (panel.settings.autohide) {
         | 
| 21562 | 
            +
            						if (clickCtrl) {
         | 
| 21563 | 
            +
            							if (isChildOf(clickCtrl, panel) || panel.parent() === clickCtrl) {
         | 
| 21564 | 
            +
            								continue;
         | 
| 21565 | 
            +
            							}
         | 
| 21566 | 
            +
            						}
         | 
| 21567 | 
            +
             | 
| 21568 | 
            +
            						e = panel.fire('autohide', {target: e.target});
         | 
| 21569 | 
            +
            						if (!e.isDefaultPrevented()) {
         | 
| 21570 | 
            +
            							panel.hide();
         | 
| 21571 | 
            +
            						}
         | 
| 21572 | 
            +
            					}
         | 
| 21573 | 
            +
            				}
         | 
| 21574 | 
            +
            			};
         | 
| 21575 | 
            +
             | 
| 21576 | 
            +
            			DomUtils.on(document, 'click', documentClickHandler);
         | 
| 21577 | 
            +
            		}
         | 
| 21578 | 
            +
            	}
         | 
| 21579 | 
            +
             | 
| 21580 | 
            +
            	function bindDocumentScrollHandler() {
         | 
| 21581 | 
            +
            		if (!documentScrollHandler) {
         | 
| 21582 | 
            +
            			documentScrollHandler = function() {
         | 
| 21583 | 
            +
            				var i;
         | 
| 21584 | 
            +
             | 
| 21585 | 
            +
            				i = visiblePanels.length;
         | 
| 21586 | 
            +
            				while (i--) {
         | 
| 21587 | 
            +
            					repositionPanel(visiblePanels[i]);
         | 
| 21588 | 
            +
            				}
         | 
| 21589 | 
            +
            			};
         | 
| 21590 | 
            +
             | 
| 21591 | 
            +
            			DomUtils.on(window, 'scroll', documentScrollHandler);
         | 
| 21592 | 
            +
            		}
         | 
| 21593 | 
            +
            	}
         | 
| 21594 | 
            +
             | 
| 21595 | 
            +
            	function bindWindowResizeHandler() {
         | 
| 21596 | 
            +
            		if (!windowResizeHandler) {
         | 
| 21597 | 
            +
            			windowResizeHandler = function() {
         | 
| 21598 | 
            +
            				FloatPanel.hideAll();
         | 
| 21599 | 
            +
            			};
         | 
| 21600 | 
            +
             | 
| 21601 | 
            +
            			DomUtils.on(window, 'resize', windowResizeHandler);
         | 
| 21602 | 
            +
            		}
         | 
| 21603 | 
            +
            	}
         | 
| 21604 | 
            +
             | 
| 21605 | 
            +
            	/**
         | 
| 21606 | 
            +
            	 * Repositions the panel to the top of page if the panel is outside of the visual viewport. It will
         | 
| 21607 | 
            +
            	 * also reposition all child panels of the current panel.
         | 
| 21608 | 
            +
            	 */
         | 
| 21609 | 
            +
            	function repositionPanel(panel) {
         | 
| 21610 | 
            +
            		var scrollY = DomUtils.getViewPort().y;
         | 
| 21611 | 
            +
             | 
| 21612 | 
            +
            		function toggleFixedChildPanels(fixed, deltaY) {
         | 
| 21613 | 
            +
            			var parent;
         | 
| 21614 | 
            +
             | 
| 21615 | 
            +
            			for (var i = 0; i < visiblePanels.length; i++) {
         | 
| 21616 | 
            +
            				if (visiblePanels[i] != panel) {
         | 
| 21617 | 
            +
            					parent = visiblePanels[i].parent();
         | 
| 21618 | 
            +
             | 
| 21619 | 
            +
            					while (parent && (parent = parent.parent())) {
         | 
| 21620 | 
            +
            						if (parent == panel) {
         | 
| 21621 | 
            +
            							visiblePanels[i].fixed(fixed).moveBy(0, deltaY).repaint();
         | 
| 21622 | 
            +
            						}
         | 
| 21623 | 
            +
            					}
         | 
| 21624 | 
            +
            				}
         | 
| 21625 | 
            +
            			}
         | 
| 21626 | 
            +
            		}
         | 
| 21627 | 
            +
             | 
| 21628 | 
            +
            		if (panel.settings.autofix) {
         | 
| 21629 | 
            +
            			if (!panel._fixed) {
         | 
| 21630 | 
            +
            				panel._autoFixY = panel.layoutRect().y;
         | 
| 21631 | 
            +
             | 
| 21632 | 
            +
            				if (panel._autoFixY < scrollY) {
         | 
| 21633 | 
            +
            					panel.fixed(true).layoutRect({y: 0}).repaint();
         | 
| 21634 | 
            +
            					toggleFixedChildPanels(true, scrollY - panel._autoFixY);
         | 
| 21635 | 
            +
            				}
         | 
| 21636 | 
            +
            			} else {
         | 
| 21637 | 
            +
            				if (panel._autoFixY > scrollY) {
         | 
| 21638 | 
            +
            					panel.fixed(false).layoutRect({y: panel._autoFixY}).repaint();
         | 
| 21639 | 
            +
            					toggleFixedChildPanels(false, panel._autoFixY - scrollY);
         | 
| 21640 | 
            +
            				}
         | 
| 21641 | 
            +
            			}
         | 
| 21642 | 
            +
            		}
         | 
| 21643 | 
            +
            	}
         | 
| 21644 | 
            +
             | 
| 21200 21645 | 
             
            	var FloatPanel = Panel.extend({
         | 
| 21201 21646 | 
             
            		Mixins: [Movable, Resizable],
         | 
| 21202 21647 |  | 
| @@ -21238,56 +21683,6 @@ define("tinymce/ui/FloatPanel", [ | |
| 21238 21683 | 
             
            				FloatPanel.currentZIndex = zIndex;
         | 
| 21239 21684 | 
             
            			}
         | 
| 21240 21685 |  | 
| 21241 | 
            -
            			function isChildOf(ctrl, parent) {
         | 
| 21242 | 
            -
            				while (ctrl) {
         | 
| 21243 | 
            -
            					if (ctrl == parent) {
         | 
| 21244 | 
            -
            						return true;
         | 
| 21245 | 
            -
            					}
         | 
| 21246 | 
            -
             | 
| 21247 | 
            -
            					ctrl = ctrl.parent();
         | 
| 21248 | 
            -
            				}
         | 
| 21249 | 
            -
            			}
         | 
| 21250 | 
            -
             | 
| 21251 | 
            -
            			/**
         | 
| 21252 | 
            -
            			 * Repositions the panel to the top of page if the panel is outside of the visual viewport. It will
         | 
| 21253 | 
            -
            			 * also reposition all child panels of the current panel.
         | 
| 21254 | 
            -
            			 */
         | 
| 21255 | 
            -
            			function repositionPanel(panel) {
         | 
| 21256 | 
            -
            				var scrollY = DomUtils.getViewPort().y;
         | 
| 21257 | 
            -
             | 
| 21258 | 
            -
            				function toggleFixedChildPanels(fixed, deltaY) {
         | 
| 21259 | 
            -
            					var parent;
         | 
| 21260 | 
            -
             | 
| 21261 | 
            -
            					for (var i = 0; i < visiblePanels.length; i++) {
         | 
| 21262 | 
            -
            						if (visiblePanels[i] != panel) {
         | 
| 21263 | 
            -
            							parent = visiblePanels[i].parent();
         | 
| 21264 | 
            -
             | 
| 21265 | 
            -
            							while (parent && (parent = parent.parent())) {
         | 
| 21266 | 
            -
            								if (parent == panel) {
         | 
| 21267 | 
            -
            									visiblePanels[i].fixed(fixed).moveBy(0, deltaY).repaint();
         | 
| 21268 | 
            -
            								}
         | 
| 21269 | 
            -
            							}
         | 
| 21270 | 
            -
            						}
         | 
| 21271 | 
            -
            					}
         | 
| 21272 | 
            -
            				}
         | 
| 21273 | 
            -
             | 
| 21274 | 
            -
            				if (panel.settings.autofix) {
         | 
| 21275 | 
            -
            					if (!panel._fixed) {
         | 
| 21276 | 
            -
            						panel._autoFixY = panel.layoutRect().y;
         | 
| 21277 | 
            -
             | 
| 21278 | 
            -
            						if (panel._autoFixY < scrollY) {
         | 
| 21279 | 
            -
            							panel.fixed(true).layoutRect({y: 0}).repaint();
         | 
| 21280 | 
            -
            							toggleFixedChildPanels(true, scrollY - panel._autoFixY);
         | 
| 21281 | 
            -
            						}
         | 
| 21282 | 
            -
            					} else {
         | 
| 21283 | 
            -
            						if (panel._autoFixY > scrollY) {
         | 
| 21284 | 
            -
            							panel.fixed(false).layoutRect({y: panel._autoFixY}).repaint();
         | 
| 21285 | 
            -
            							toggleFixedChildPanels(false, panel._autoFixY - scrollY);
         | 
| 21286 | 
            -
            						}
         | 
| 21287 | 
            -
            					}
         | 
| 21288 | 
            -
            				}
         | 
| 21289 | 
            -
            			}
         | 
| 21290 | 
            -
             | 
| 21291 21686 | 
             
            			self._super(settings);
         | 
| 21292 21687 | 
             
            			self._eventsRoot = self;
         | 
| 21293 21688 |  | 
| @@ -21295,48 +21690,13 @@ define("tinymce/ui/FloatPanel", [ | |
| 21295 21690 |  | 
| 21296 21691 | 
             
            			// Hide floatpanes on click out side the root button
         | 
| 21297 21692 | 
             
            			if (settings.autohide) {
         | 
| 21298 | 
            -
            				 | 
| 21299 | 
            -
             | 
| 21300 | 
            -
            						// Hide any float panel when a click is out side that float panel and the
         | 
| 21301 | 
            -
            						// float panels direct parent for example a click on a menu button
         | 
| 21302 | 
            -
            						var i = visiblePanels.length;
         | 
| 21303 | 
            -
            						while (i--) {
         | 
| 21304 | 
            -
            							var panel = visiblePanels[i], clickCtrl = panel.getParentCtrl(e.target);
         | 
| 21305 | 
            -
             | 
| 21306 | 
            -
            							if (panel.settings.autohide) {
         | 
| 21307 | 
            -
            								if (clickCtrl) {
         | 
| 21308 | 
            -
            									if (isChildOf(clickCtrl, panel) || panel.parent() === clickCtrl) {
         | 
| 21309 | 
            -
            										continue;
         | 
| 21310 | 
            -
            									}
         | 
| 21311 | 
            -
            								}
         | 
| 21312 | 
            -
             | 
| 21313 | 
            -
            								e = panel.fire('autohide', {target: e.target});
         | 
| 21314 | 
            -
            								if (!e.isDefaultPrevented()) {
         | 
| 21315 | 
            -
            									panel.hide();
         | 
| 21316 | 
            -
            								}
         | 
| 21317 | 
            -
            							}
         | 
| 21318 | 
            -
            						}
         | 
| 21319 | 
            -
            					};
         | 
| 21320 | 
            -
             | 
| 21321 | 
            -
            					DomUtils.on(document, 'click', documentClickHandler);
         | 
| 21322 | 
            -
            				}
         | 
| 21323 | 
            -
             | 
| 21693 | 
            +
            				bindDocumentClickHandler();
         | 
| 21694 | 
            +
            				bindWindowResizeHandler();
         | 
| 21324 21695 | 
             
            				visiblePanels.push(self);
         | 
| 21325 21696 | 
             
            			}
         | 
| 21326 21697 |  | 
| 21327 21698 | 
             
            			if (settings.autofix) {
         | 
| 21328 | 
            -
            				 | 
| 21329 | 
            -
            					documentScrollHandler = function() {
         | 
| 21330 | 
            -
            						var i;
         | 
| 21331 | 
            -
             | 
| 21332 | 
            -
            						i = visiblePanels.length;
         | 
| 21333 | 
            -
            						while (i--) {
         | 
| 21334 | 
            -
            							repositionPanel(visiblePanels[i]);
         | 
| 21335 | 
            -
            						}
         | 
| 21336 | 
            -
            					};
         | 
| 21337 | 
            -
             | 
| 21338 | 
            -
            					DomUtils.on(window, 'scroll', documentScrollHandler);
         | 
| 21339 | 
            -
            				}
         | 
| 21699 | 
            +
            				bindDocumentScrollHandler();
         | 
| 21340 21700 |  | 
| 21341 21701 | 
             
            				self.on('move', function() {
         | 
| 21342 21702 | 
             
            					repositionPanel(this);
         | 
| @@ -21452,7 +21812,8 @@ define("tinymce/ui/FloatPanel", [ | |
| 21452 21812 | 
             
            		},
         | 
| 21453 21813 |  | 
| 21454 21814 | 
             
            		/**
         | 
| 21455 | 
            -
            		 *  | 
| 21815 | 
            +
            		 * Hide all visible float panels with he autohide setting enabled. This is for
         | 
| 21816 | 
            +
            		 * manually hiding floating menus or panels.
         | 
| 21456 21817 | 
             
            		 *
         | 
| 21457 21818 | 
             
            		 * @method hideAll
         | 
| 21458 21819 | 
             
            		 */
         | 
| @@ -21495,7 +21856,8 @@ define("tinymce/ui/FloatPanel", [ | |
| 21495 21856 | 
             
            	});
         | 
| 21496 21857 |  | 
| 21497 21858 | 
             
            	/**
         | 
| 21498 | 
            -
            	 *  | 
| 21859 | 
            +
            	 * Hide all visible float panels with he autohide setting enabled. This is for
         | 
| 21860 | 
            +
            	 * manually hiding floating menus or panels.
         | 
| 21499 21861 | 
             
            	 *
         | 
| 21500 21862 | 
             
            	 * @static
         | 
| 21501 21863 | 
             
            	 * @method hideAll
         | 
| @@ -23901,8 +24263,13 @@ define("tinymce/Shortcuts", [ | |
| 23901 24263 | 
             
            							break;
         | 
| 23902 24264 |  | 
| 23903 24265 | 
             
            						default:
         | 
| 23904 | 
            -
            							 | 
| 23905 | 
            -
            							 | 
| 24266 | 
            +
            							// Allow numeric keycodes like ctrl+219 for ctrl+[
         | 
| 24267 | 
            +
            							if (/^[0-9]{2,}$/.test(value)) {
         | 
| 24268 | 
            +
            								shortcut.keyCode = parseInt(value, 10);
         | 
| 24269 | 
            +
            							} else {
         | 
| 24270 | 
            +
            								shortcut.charCode = value.charCodeAt(0);
         | 
| 24271 | 
            +
            								shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
         | 
| 24272 | 
            +
            							}
         | 
| 23906 24273 | 
             
            					}
         | 
| 23907 24274 | 
             
            				});
         | 
| 23908 24275 |  | 
| @@ -24709,7 +25076,14 @@ define("tinymce/Editor", [ | |
| 24709 25076 | 
             
            					// Add internal attribute if we need to we don't on a refresh of the document
         | 
| 24710 25077 | 
             
            					if (!node.attributes.map[internalName]) {
         | 
| 24711 25078 | 
             
            						if (name === "style") {
         | 
| 24712 | 
            -
            							 | 
| 25079 | 
            +
            							value = dom.serializeStyle(dom.parseStyle(value), node.name);
         | 
| 25080 | 
            +
             | 
| 25081 | 
            +
            							if (!value.length) {
         | 
| 25082 | 
            +
            								value = null;
         | 
| 25083 | 
            +
            							}
         | 
| 25084 | 
            +
             | 
| 25085 | 
            +
            							node.attr(internalName, value);
         | 
| 25086 | 
            +
            							node.attr(name, value);
         | 
| 24713 25087 | 
             
            						} else if (name === "tabindex") {
         | 
| 24714 25088 | 
             
            							node.attr(internalName, value);
         | 
| 24715 25089 | 
             
            							node.attr(name, null);
         | 
| @@ -24726,7 +25100,7 @@ define("tinymce/Editor", [ | |
| 24726 25100 |  | 
| 24727 25101 | 
             
            				while (i--) {
         | 
| 24728 25102 | 
             
            					node = nodes[i];
         | 
| 24729 | 
            -
            					node.attr('type', 'mce-' + (node.attr('type') || ' | 
| 25103 | 
            +
            					node.attr('type', 'mce-' + (node.attr('type') || 'no/type'));
         | 
| 24730 25104 | 
             
            				}
         | 
| 24731 25105 | 
             
            			});
         | 
| 24732 25106 |  | 
| @@ -25340,8 +25714,18 @@ define("tinymce/Editor", [ | |
| 25340 25714 | 
             
            			}
         | 
| 25341 25715 |  | 
| 25342 25716 | 
             
            			// Browser commands
         | 
| 25343 | 
            -
            			 | 
| 25344 | 
            -
             | 
| 25717 | 
            +
            			try {
         | 
| 25718 | 
            +
            				state = self.getDoc().execCommand(cmd, ui, value);
         | 
| 25719 | 
            +
            			} catch (ex) {
         | 
| 25720 | 
            +
            				// Ignore old IE errors
         | 
| 25721 | 
            +
            			}
         | 
| 25722 | 
            +
             | 
| 25723 | 
            +
            			if (state) {
         | 
| 25724 | 
            +
            				self.fire('ExecCommand', {command: cmd, ui: ui, value: value});
         | 
| 25725 | 
            +
            				return true;
         | 
| 25726 | 
            +
            			}
         | 
| 25727 | 
            +
             | 
| 25728 | 
            +
            			return false;
         | 
| 25345 25729 | 
             
            		},
         | 
| 25346 25730 |  | 
| 25347 25731 | 
             
            		/**
         | 
| @@ -25363,8 +25747,8 @@ define("tinymce/Editor", [ | |
| 25363 25747 | 
             
            			if ((queryItem = self.queryStateCommands[cmd])) {
         | 
| 25364 25748 | 
             
            				returnVal = queryItem.func.call(queryItem.scope);
         | 
| 25365 25749 |  | 
| 25366 | 
            -
            				// Fall though on  | 
| 25367 | 
            -
            				if (returnVal  | 
| 25750 | 
            +
            				// Fall though on non boolean returns
         | 
| 25751 | 
            +
            				if (returnVal === true || returnVal === false) {
         | 
| 25368 25752 | 
             
            					return returnVal;
         | 
| 25369 25753 | 
             
            				}
         | 
| 25370 25754 | 
             
            			}
         | 
| @@ -25454,8 +25838,6 @@ define("tinymce/Editor", [ | |
| 25454 25838 | 
             
            			var self = this, doc = self.getDoc();
         | 
| 25455 25839 |  | 
| 25456 25840 | 
             
            			if (!self.hidden) {
         | 
| 25457 | 
            -
            				self.hidden = true;
         | 
| 25458 | 
            -
             | 
| 25459 25841 | 
             
            				// Fixed bug where IE has a blinking cursor left from the editor
         | 
| 25460 25842 | 
             
            				if (ie && doc && !self.inline) {
         | 
| 25461 25843 | 
             
            					doc.execCommand('SelectAll');
         | 
| @@ -25476,6 +25858,7 @@ define("tinymce/Editor", [ | |
| 25476 25858 | 
             
            					DOM.setStyle(self.id, 'display', self.orgDisplay);
         | 
| 25477 25859 | 
             
            				}
         | 
| 25478 25860 |  | 
| 25861 | 
            +
            				self.hidden = true;
         | 
| 25479 25862 | 
             
            				self.fire('hide');
         | 
| 25480 25863 | 
             
            			}
         | 
| 25481 25864 | 
             
            		},
         | 
| @@ -25739,8 +26122,13 @@ define("tinymce/Editor", [ | |
| 25739 26122 | 
             
            		 *
         | 
| 25740 26123 | 
             
            		 * @method insertContent
         | 
| 25741 26124 | 
             
            		 * @param {String} content Content to insert.
         | 
| 26125 | 
            +
            		 * @param {Object} args Optional args to pass to insert call.
         | 
| 25742 26126 | 
             
            		 */
         | 
| 25743 | 
            -
            		insertContent: function(content) {
         | 
| 26127 | 
            +
            		insertContent: function(content, args) {
         | 
| 26128 | 
            +
            			if (args) {
         | 
| 26129 | 
            +
            				content = extend({content: content}, args);
         | 
| 26130 | 
            +
            			}
         | 
| 26131 | 
            +
             | 
| 25744 26132 | 
             
            			this.execCommand('mceInsertContent', false, content);
         | 
| 25745 26133 | 
             
            		},
         | 
| 25746 26134 |  | 
| @@ -26495,7 +26883,7 @@ define("tinymce/EditorManager", [ | |
| 26495 26883 | 
             
            		 * @property minorVersion
         | 
| 26496 26884 | 
             
            		 * @type String
         | 
| 26497 26885 | 
             
            		 */
         | 
| 26498 | 
            -
            		minorVersion : '0. | 
| 26886 | 
            +
            		minorVersion : '0.28',
         | 
| 26499 26887 |  | 
| 26500 26888 | 
             
            		/**
         | 
| 26501 26889 | 
             
            		 * Release date of TinyMCE build.
         | 
| @@ -26503,7 +26891,7 @@ define("tinymce/EditorManager", [ | |
| 26503 26891 | 
             
            		 * @property releaseDate
         | 
| 26504 26892 | 
             
            		 * @type String
         | 
| 26505 26893 | 
             
            		 */
         | 
| 26506 | 
            -
            		releaseDate: '2014-05- | 
| 26894 | 
            +
            		releaseDate: '2014-05-27',
         | 
| 26507 26895 |  | 
| 26508 26896 | 
             
            		/**
         | 
| 26509 26897 | 
             
            		 * Collection of editor instances.
         | 
| @@ -26539,9 +26927,16 @@ define("tinymce/EditorManager", [ | |
| 26539 26927 | 
             
            			var self = this, baseURL, documentBaseURL, suffix = "", preInit, src;
         | 
| 26540 26928 |  | 
| 26541 26929 | 
             
            			// Get base URL for the current document
         | 
| 26542 | 
            -
            			documentBaseURL = document.location.href | 
| 26543 | 
            -
             | 
| 26544 | 
            -
             | 
| 26930 | 
            +
            			documentBaseURL = document.location.href;
         | 
| 26931 | 
            +
             | 
| 26932 | 
            +
            			// Check if the URL is a document based format like: http://site/dir/file
         | 
| 26933 | 
            +
            			// leave other formats like applewebdata://... intact
         | 
| 26934 | 
            +
            			if (/^[^:]+:\/\/[^\/]+\//.test(documentBaseURL)) {
         | 
| 26935 | 
            +
            				documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
         | 
| 26936 | 
            +
             | 
| 26937 | 
            +
            				if (!/[\/\\]$/.test(documentBaseURL)) {
         | 
| 26938 | 
            +
            					documentBaseURL += '/';
         | 
| 26939 | 
            +
            				}
         | 
| 26545 26940 | 
             
            			}
         | 
| 26546 26941 |  | 
| 26547 26942 | 
             
            			// If tinymce is defined and has a base use that or use the old tinyMCEPreInit
         | 
| @@ -29475,13 +29870,19 @@ define("tinymce/ui/Form", [ | |
| 29475 29870 | 
             
            		 * @private
         | 
| 29476 29871 | 
             
            		 */
         | 
| 29477 29872 | 
             
            		recalcLabels: function() {
         | 
| 29478 | 
            -
            			var self = this, maxLabelWidth = 0, labels = [], i, labelGap;
         | 
| 29873 | 
            +
            			var self = this, maxLabelWidth = 0, labels = [], i, labelGap, items;
         | 
| 29479 29874 |  | 
| 29480 29875 | 
             
            			if (self.settings.labelGapCalc === false) {
         | 
| 29481 29876 | 
             
            				return;
         | 
| 29482 29877 | 
             
            			}
         | 
| 29483 29878 |  | 
| 29484 | 
            -
            			self. | 
| 29879 | 
            +
            			if (self.settings.labelGapCalc == "children") {
         | 
| 29880 | 
            +
            				items = self.find('formitem');
         | 
| 29881 | 
            +
            			} else {
         | 
| 29882 | 
            +
            				items = self.items();
         | 
| 29883 | 
            +
            			}
         | 
| 29884 | 
            +
             | 
| 29885 | 
            +
            			items.filter('formitem').each(function(item) {
         | 
| 29485 29886 | 
             
            				var labelCtrl = item.items()[0], labelWidth = labelCtrl.getEl().clientWidth;
         | 
| 29486 29887 |  | 
| 29487 29888 | 
             
            				maxLabelWidth = labelWidth > maxLabelWidth ? labelWidth : maxLabelWidth;
         | 
| @@ -29622,8 +30023,9 @@ define("tinymce/ui/FieldSet", [ | |
| 29622 30023 | 
             
             * @extends tinymce.ui.ComboBox
         | 
| 29623 30024 | 
             
             */
         | 
| 29624 30025 | 
             
            define("tinymce/ui/FilePicker", [
         | 
| 29625 | 
            -
            	"tinymce/ui/ComboBox"
         | 
| 29626 | 
            -
             | 
| 30026 | 
            +
            	"tinymce/ui/ComboBox",
         | 
| 30027 | 
            +
            	"tinymce/util/Tools"
         | 
| 30028 | 
            +
            ], function(ComboBox, Tools) {
         | 
| 29627 30029 | 
             
            	"use strict";
         | 
| 29628 30030 |  | 
| 29629 30031 | 
             
            	return ComboBox.extend({
         | 
| @@ -29634,12 +30036,17 @@ define("tinymce/ui/FilePicker", [ | |
| 29634 30036 | 
             
            		 * @param {Object} settings Name/value object with settings.
         | 
| 29635 30037 | 
             
            		 */
         | 
| 29636 30038 | 
             
            		init: function(settings) {
         | 
| 29637 | 
            -
            			var self = this, editor = tinymce.activeEditor, fileBrowserCallback;
         | 
| 30039 | 
            +
            			var self = this, editor = tinymce.activeEditor, fileBrowserCallback, fileBrowserCallbackTypes;
         | 
| 29638 30040 |  | 
| 29639 30041 | 
             
            			settings.spellcheck = false;
         | 
| 29640 30042 |  | 
| 30043 | 
            +
            			fileBrowserCallbackTypes = editor.settings.file_browser_callback_types;
         | 
| 30044 | 
            +
            			if (fileBrowserCallbackTypes) {
         | 
| 30045 | 
            +
            				fileBrowserCallbackTypes = Tools.makeMap(fileBrowserCallbackTypes, /[, ]/);
         | 
| 30046 | 
            +
            			}
         | 
| 30047 | 
            +
             | 
| 29641 30048 | 
             
            			fileBrowserCallback = editor.settings.file_browser_callback;
         | 
| 29642 | 
            -
            			if (fileBrowserCallback) {
         | 
| 30049 | 
            +
            			if (fileBrowserCallback && (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[settings.filetype])) {
         | 
| 29643 30050 | 
             
            				settings.icon = 'browse';
         | 
| 29644 30051 |  | 
| 29645 30052 | 
             
            				settings.onaction = function() {
         | 
| @@ -30155,6 +30562,7 @@ define("tinymce/ui/FormatControls", [ | |
| 30155 30562 | 
             
            						}
         | 
| 30156 30563 |  | 
| 30157 30564 | 
             
            						menuItem.format = formatName;
         | 
| 30565 | 
            +
            						menuItem.cmd = format.cmd;
         | 
| 30158 30566 | 
             
            					}
         | 
| 30159 30567 |  | 
| 30160 30568 | 
             
            					menu.push(menuItem);
         | 
| @@ -30201,20 +30609,32 @@ define("tinymce/ui/FormatControls", [ | |
| 30201 30609 | 
             
            					},
         | 
| 30202 30610 |  | 
| 30203 30611 | 
             
            					onPostRender: function() {
         | 
| 30204 | 
            -
            						var self = this | 
| 30612 | 
            +
            						var self = this;
         | 
| 30205 30613 |  | 
| 30206 | 
            -
            						 | 
| 30207 | 
            -
            							 | 
| 30614 | 
            +
            						self.parent().on('show', function() {
         | 
| 30615 | 
            +
            							var formatName, command;
         | 
| 30616 | 
            +
             | 
| 30617 | 
            +
            							formatName = self.settings.format;
         | 
| 30618 | 
            +
            							if (formatName) {
         | 
| 30208 30619 | 
             
            								self.disabled(!editor.formatter.canApply(formatName));
         | 
| 30209 30620 | 
             
            								self.active(editor.formatter.match(formatName));
         | 
| 30210 | 
            -
            							} | 
| 30211 | 
            -
             | 
| 30621 | 
            +
            							}
         | 
| 30622 | 
            +
             | 
| 30623 | 
            +
            							command = self.settings.cmd;
         | 
| 30624 | 
            +
            							if (command) {
         | 
| 30625 | 
            +
            								self.active(editor.queryCommandState(command));
         | 
| 30626 | 
            +
            							}
         | 
| 30627 | 
            +
            						});
         | 
| 30212 30628 | 
             
            					},
         | 
| 30213 30629 |  | 
| 30214 30630 | 
             
            					onclick: function() {
         | 
| 30215 30631 | 
             
            						if (this.settings.format) {
         | 
| 30216 30632 | 
             
            							toggleFormat(this.settings.format);
         | 
| 30217 30633 | 
             
            						}
         | 
| 30634 | 
            +
             | 
| 30635 | 
            +
            						if (this.settings.cmd) {
         | 
| 30636 | 
            +
            							editor.execCommand(this.settings.cmd);
         | 
| 30637 | 
            +
            						}
         | 
| 30218 30638 | 
             
            					}
         | 
| 30219 30639 | 
             
            				}
         | 
| 30220 30640 | 
             
            			};
         | 
| @@ -30309,30 +30729,21 @@ define("tinymce/ui/FormatControls", [ | |
| 30309 30729 | 
             
            			});
         | 
| 30310 30730 | 
             
            		});
         | 
| 30311 30731 |  | 
| 30312 | 
            -
            		function  | 
| 30313 | 
            -
            			return  | 
| 30314 | 
            -
             | 
| 30315 | 
            -
             | 
| 30316 | 
            -
            		function hasRedo() {
         | 
| 30317 | 
            -
            			return editor.undoManager ? editor.undoManager.hasRedo() : false;
         | 
| 30318 | 
            -
            		}
         | 
| 30319 | 
            -
             | 
| 30320 | 
            -
            		function toggleUndoState() {
         | 
| 30321 | 
            -
            			var self = this;
         | 
| 30732 | 
            +
            		function toggleUndoRedoState(type) {
         | 
| 30733 | 
            +
            			return function() {
         | 
| 30734 | 
            +
            				var self = this;
         | 
| 30322 30735 |  | 
| 30323 | 
            -
             | 
| 30324 | 
            -
            			editor.on('Undo Redo AddUndo TypingUndo', function() {
         | 
| 30325 | 
            -
            				self.disabled(!hasUndo());
         | 
| 30326 | 
            -
            			});
         | 
| 30327 | 
            -
            		}
         | 
| 30736 | 
            +
            				type = type == 'redo' ? 'hasRedo' : 'hasUndo';
         | 
| 30328 30737 |  | 
| 30329 | 
            -
             | 
| 30330 | 
            -
             | 
| 30738 | 
            +
            				function checkState() {
         | 
| 30739 | 
            +
            					return editor.undoManager ? editor.undoManager[type]() : false;
         | 
| 30740 | 
            +
            				}
         | 
| 30331 30741 |  | 
| 30332 | 
            -
             | 
| 30333 | 
            -
             | 
| 30334 | 
            -
             | 
| 30335 | 
            -
             | 
| 30742 | 
            +
            				self.disabled(!checkState());
         | 
| 30743 | 
            +
            				editor.on('Undo Redo AddUndo TypingUndo ClearUndos', function() {
         | 
| 30744 | 
            +
            					self.disabled(!checkState());
         | 
| 30745 | 
            +
            				});
         | 
| 30746 | 
            +
            			};
         | 
| 30336 30747 | 
             
            		}
         | 
| 30337 30748 |  | 
| 30338 30749 | 
             
            		function toggleVisualAidState() {
         | 
| @@ -30347,13 +30758,13 @@ define("tinymce/ui/FormatControls", [ | |
| 30347 30758 |  | 
| 30348 30759 | 
             
            		editor.addButton('undo', {
         | 
| 30349 30760 | 
             
            			tooltip: 'Undo',
         | 
| 30350 | 
            -
            			onPostRender:  | 
| 30761 | 
            +
            			onPostRender: toggleUndoRedoState('undo'),
         | 
| 30351 30762 | 
             
            			cmd: 'undo'
         | 
| 30352 30763 | 
             
            		});
         | 
| 30353 30764 |  | 
| 30354 30765 | 
             
            		editor.addButton('redo', {
         | 
| 30355 30766 | 
             
            			tooltip: 'Redo',
         | 
| 30356 | 
            -
            			onPostRender:  | 
| 30767 | 
            +
            			onPostRender: toggleUndoRedoState('redo'),
         | 
| 30357 30768 | 
             
            			cmd: 'redo'
         | 
| 30358 30769 | 
             
            		});
         | 
| 30359 30770 |  | 
| @@ -30368,7 +30779,7 @@ define("tinymce/ui/FormatControls", [ | |
| 30368 30779 | 
             
            			text: 'Undo',
         | 
| 30369 30780 | 
             
            			icon: 'undo',
         | 
| 30370 30781 | 
             
            			shortcut: 'Ctrl+Z',
         | 
| 30371 | 
            -
            			onPostRender:  | 
| 30782 | 
            +
            			onPostRender: toggleUndoRedoState('undo'),
         | 
| 30372 30783 | 
             
            			cmd: 'undo'
         | 
| 30373 30784 | 
             
            		});
         | 
| 30374 30785 |  | 
| @@ -30376,7 +30787,7 @@ define("tinymce/ui/FormatControls", [ | |
| 30376 30787 | 
             
            			text: 'Redo',
         | 
| 30377 30788 | 
             
            			icon: 'redo',
         | 
| 30378 30789 | 
             
            			shortcut: 'Ctrl+Y',
         | 
| 30379 | 
            -
            			onPostRender:  | 
| 30790 | 
            +
            			onPostRender: toggleUndoRedoState('redo'),
         | 
| 30380 30791 | 
             
            			cmd: 'redo'
         | 
| 30381 30792 | 
             
            		});
         | 
| 30382 30793 |  | 
| @@ -30511,7 +30922,14 @@ define("tinymce/ui/FormatControls", [ | |
| 30511 30922 | 
             
            			var fontsize_formats = editor.settings.fontsize_formats || defaultFontsizeFormats;
         | 
| 30512 30923 |  | 
| 30513 30924 | 
             
            			each(fontsize_formats.split(' '), function(item) {
         | 
| 30514 | 
            -
            				 | 
| 30925 | 
            +
            				var text = item, value = item;
         | 
| 30926 | 
            +
            				// Allow text=value font sizes.
         | 
| 30927 | 
            +
            				var values = item.split('=');
         | 
| 30928 | 
            +
            				if (values.length > 1) {
         | 
| 30929 | 
            +
            					text = values[0];
         | 
| 30930 | 
            +
            					value = values[1];
         | 
| 30931 | 
            +
            				}
         | 
| 30932 | 
            +
            				items.push({text: text, value: value});
         | 
| 30515 30933 | 
             
            			});
         | 
| 30516 30934 |  | 
| 30517 30935 | 
             
            			return {
         | 
| @@ -31353,19 +31771,29 @@ define("tinymce/ui/ListBox", [ | |
| 31353 31771 | 
             
            		 * @setting {Array} values Array with values to add to list box.
         | 
| 31354 31772 | 
             
            		 */
         | 
| 31355 31773 | 
             
            		init: function(settings) {
         | 
| 31356 | 
            -
            			var self = this, values,  | 
| 31774 | 
            +
            			var self = this, values, selected, selectedText, lastItemCtrl;
         | 
| 31357 31775 |  | 
| 31358 | 
            -
            			 | 
| 31359 | 
            -
             | 
| 31360 | 
            -
            				for (i = 0; i <  | 
| 31361 | 
            -
            					selected =  | 
| 31776 | 
            +
            			function setSelected(menuValues) {
         | 
| 31777 | 
            +
            				// Try to find a selected value
         | 
| 31778 | 
            +
            				for (var i = 0; i < menuValues.length; i++) {
         | 
| 31779 | 
            +
            					selected = menuValues[i].selected || settings.value === menuValues[i].value;
         | 
| 31362 31780 |  | 
| 31363 31781 | 
             
            					if (selected) {
         | 
| 31364 | 
            -
            						selectedText = selectedText ||  | 
| 31365 | 
            -
            						self._value =  | 
| 31782 | 
            +
            						selectedText = selectedText || menuValues[i].text;
         | 
| 31783 | 
            +
            						self._value = menuValues[i].value;
         | 
| 31366 31784 | 
             
            						break;
         | 
| 31367 31785 | 
             
            					}
         | 
| 31786 | 
            +
             | 
| 31787 | 
            +
            					// If the value has a submenu, try to find the selected values in that menu
         | 
| 31788 | 
            +
            					if (menuValues[i].menu) {
         | 
| 31789 | 
            +
            						setSelected(menuValues[i].menu);
         | 
| 31790 | 
            +
            					}
         | 
| 31368 31791 | 
             
            				}
         | 
| 31792 | 
            +
            			}
         | 
| 31793 | 
            +
             | 
| 31794 | 
            +
            			self._values = values = settings.values;
         | 
| 31795 | 
            +
            			if (values) {
         | 
| 31796 | 
            +
            				setSelected(values);
         | 
| 31369 31797 |  | 
| 31370 31798 | 
             
            				// Default with first item
         | 
| 31371 31799 | 
             
            				if (!selected && values.length > 0) {
         | 
| @@ -31406,7 +31834,7 @@ define("tinymce/ui/ListBox", [ | |
| 31406 31834 | 
             
            		 * @return {Boolean/tinymce.ui.ListBox} Value or self if it's a set operation.
         | 
| 31407 31835 | 
             
            		 */
         | 
| 31408 31836 | 
             
            		value: function(value) {
         | 
| 31409 | 
            -
            			var self = this, active, selectedText, menu | 
| 31837 | 
            +
            			var self = this, active, selectedText, menu;
         | 
| 31410 31838 |  | 
| 31411 31839 | 
             
            			function activateByValue(menu, value) {
         | 
| 31412 31840 | 
             
            				menu.items().each(function(ctrl) {
         | 
| @@ -31424,20 +31852,28 @@ define("tinymce/ui/ListBox", [ | |
| 31424 31852 | 
             
            				});
         | 
| 31425 31853 | 
             
            			}
         | 
| 31426 31854 |  | 
| 31855 | 
            +
            			function setActiveValues(menuValues) {
         | 
| 31856 | 
            +
            				for (var i = 0; i < menuValues.length; i++) {
         | 
| 31857 | 
            +
            					active = menuValues[i].value == value;
         | 
| 31858 | 
            +
             | 
| 31859 | 
            +
            					if (active) {
         | 
| 31860 | 
            +
            						selectedText = selectedText || menuValues[i].text;
         | 
| 31861 | 
            +
            					}
         | 
| 31862 | 
            +
             | 
| 31863 | 
            +
            					menuValues[i].active = active;
         | 
| 31864 | 
            +
             | 
| 31865 | 
            +
            					if (menuValues[i].menu) {
         | 
| 31866 | 
            +
            						setActiveValues(menuValues[i].menu);
         | 
| 31867 | 
            +
            					}
         | 
| 31868 | 
            +
            				}
         | 
| 31869 | 
            +
            			}
         | 
| 31870 | 
            +
             | 
| 31427 31871 | 
             
            			if (typeof(value) != "undefined") {
         | 
| 31428 31872 | 
             
            				if (self.menu) {
         | 
| 31429 31873 | 
             
            					activateByValue(self.menu, value);
         | 
| 31430 31874 | 
             
            				} else {
         | 
| 31431 31875 | 
             
            					menu = self.settings.menu;
         | 
| 31432 | 
            -
            					 | 
| 31433 | 
            -
            						active = menu[i].value == value;
         | 
| 31434 | 
            -
             | 
| 31435 | 
            -
            						if (active) {
         | 
| 31436 | 
            -
            							selectedText = selectedText || menu[i].text;
         | 
| 31437 | 
            -
            						}
         | 
| 31438 | 
            -
             | 
| 31439 | 
            -
            						menu[i].active = active;
         | 
| 31440 | 
            -
            					}
         | 
| 31876 | 
            +
            					setActiveValues(menu);
         | 
| 31441 31877 | 
             
            				}
         | 
| 31442 31878 |  | 
| 31443 31879 | 
             
            				self.text(selectedText || this.settings.text);
         | 
| @@ -31579,12 +32015,16 @@ define("tinymce/ui/MenuItem", [ | |
| 31579 32015 |  | 
| 31580 32016 | 
             
            					menu = self.menu = Factory.create(menu).parent(self).renderTo();
         | 
| 31581 32017 | 
             
            					menu.reflow();
         | 
| 31582 | 
            -
            					menu.fire('show');
         | 
| 31583 32018 | 
             
            					menu.on('cancel', function(e) {
         | 
| 31584 32019 | 
             
            						e.stopPropagation();
         | 
| 31585 32020 | 
             
            						self.focus();
         | 
| 31586 32021 | 
             
            						menu.hide();
         | 
| 31587 32022 | 
             
            					});
         | 
| 32023 | 
            +
            					menu.on('show hide', function(e) {
         | 
| 32024 | 
            +
            						e.control.items().each(function(ctrl) {
         | 
| 32025 | 
            +
            							ctrl.active(ctrl.settings.selected);
         | 
| 32026 | 
            +
            						});
         | 
| 32027 | 
            +
            					}).fire('show');
         | 
| 31588 32028 |  | 
| 31589 32029 | 
             
            					menu.on('hide', function(e) {
         | 
| 31590 32030 | 
             
            						if (e.control === menu) {
         | 
| @@ -32681,5 +33121,5 @@ define("tinymce/ui/Throbber", [ | |
| 32681 33121 | 
             
            	};
         | 
| 32682 33122 | 
             
            });
         | 
| 32683 33123 |  | 
| 32684 | 
            -
            expose(["tinymce/dom/Sizzle","tinymce/html/Styles","tinymce/dom/EventUtils","tinymce/dom/TreeWalker","tinymce/util/Tools","tinymce/dom/Range","tinymce/html/Entities","tinymce/Env","tinymce/dom/ | 
| 33124 | 
            +
            expose(["tinymce/dom/Sizzle","tinymce/html/Styles","tinymce/dom/EventUtils","tinymce/dom/TreeWalker","tinymce/util/Tools","tinymce/dom/Range","tinymce/html/Entities","tinymce/Env","tinymce/dom/DOMUtils","tinymce/dom/ScriptLoader","tinymce/AddOnManager","tinymce/html/Node","tinymce/html/Schema","tinymce/html/SaxParser","tinymce/html/DomParser","tinymce/html/Writer","tinymce/html/Serializer","tinymce/dom/Serializer","tinymce/dom/TridentSelection","tinymce/util/VK","tinymce/dom/ControlSelection","tinymce/dom/BookmarkManager","tinymce/dom/Selection","tinymce/dom/ElementUtils","tinymce/Formatter","tinymce/UndoManager","tinymce/EnterKey","tinymce/ForceBlocks","tinymce/EditorCommands","tinymce/util/URI","tinymce/util/Class","tinymce/util/EventDispatcher","tinymce/ui/Selector","tinymce/ui/Collection","tinymce/ui/DomUtils","tinymce/ui/Control","tinymce/ui/Factory","tinymce/ui/KeyboardNavigation","tinymce/ui/Container","tinymce/ui/DragHelper","tinymce/ui/Scrollable","tinymce/ui/Panel","tinymce/ui/Movable","tinymce/ui/Resizable","tinymce/ui/FloatPanel","tinymce/ui/Window","tinymce/ui/MessageBox","tinymce/WindowManager","tinymce/util/Quirks","tinymce/util/Observable","tinymce/EditorObservable","tinymce/Shortcuts","tinymce/Editor","tinymce/util/I18n","tinymce/FocusManager","tinymce/EditorManager","tinymce/LegacyInput","tinymce/util/XHR","tinymce/util/JSON","tinymce/util/JSONRequest","tinymce/util/JSONP","tinymce/util/LocalStorage","tinymce/Compat","tinymce/ui/Layout","tinymce/ui/AbsoluteLayout","tinymce/ui/Tooltip","tinymce/ui/Widget","tinymce/ui/Button","tinymce/ui/ButtonGroup","tinymce/ui/Checkbox","tinymce/ui/PanelButton","tinymce/ui/ColorButton","tinymce/ui/ComboBox","tinymce/ui/Path","tinymce/ui/ElementPath","tinymce/ui/FormItem","tinymce/ui/Form","tinymce/ui/FieldSet","tinymce/ui/FilePicker","tinymce/ui/FitLayout","tinymce/ui/FlexLayout","tinymce/ui/FlowLayout","tinymce/ui/FormatControls","tinymce/ui/GridLayout","tinymce/ui/Iframe","tinymce/ui/Label","tinymce/ui/Toolbar","tinymce/ui/MenuBar","tinymce/ui/MenuButton","tinymce/ui/ListBox","tinymce/ui/MenuItem","tinymce/ui/Menu","tinymce/ui/Radio","tinymce/ui/ResizeHandle","tinymce/ui/Spacer","tinymce/ui/SplitButton","tinymce/ui/StackLayout","tinymce/ui/TabPanel","tinymce/ui/TextBox","tinymce/ui/Throbber"]);
         | 
| 32685 33125 | 
             
            })(this);
         |