alecpl
2011-05-20 254d5ef32b7ec45a48abd43f19c84168dabe13d1
program/js/tiny_mce/tiny_mce_src.js
@@ -5,9 +5,9 @@
   var tinymce = {
      majorVersion : '3',
      minorVersion : '4.1',
      minorVersion : '4.2',
      releaseDate : '2011-03-24',
      releaseDate : '2011-04-07',
      _init : function() {
         var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
@@ -1407,7 +1407,7 @@
                  name = styleList[i];
                  value = styles[name];
                  if (value !== undef)
                  if (value !== undef && value.length > 0)
                     css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
               }
            }
@@ -1423,7 +1423,7 @@
            for (name in styles) {
               value = styles[name];
               if (value !== undef)
               if (value !== undef && value.length > 0)
                  css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
            }
         }
@@ -2483,11 +2483,12 @@
      },
      isEmpty : function(elements) {
         var self = this, node = self.firstChild, i;
         var self = this, node = self.firstChild, i, name;
         if (node) {
            do {
               if (node.type === 1) {
                  // Ignore bogus elements
                  if (node.attributes.map['data-mce-bogus'])
                     continue;
@@ -2495,10 +2496,11 @@
                  if (elements[node.name])
                     return false;
                  // Keep elements with data attributes
                  // Keep elements with data attributes or name attribute like <a name="1"></a>
                  i = node.attributes.length;
                  while (i--) {
                     if (node.attributes[i].name.indexOf('data-') === 0)
                     name = node.attributes[i].name;
                     if (name === "name" || name.indexOf('data-') === 0)
                        return false;
                  }
               }
@@ -2540,6 +2542,7 @@
      var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {};
      settings = settings || {};
      settings.validate = "validate" in settings ? settings.validate : true;
      settings.root_name = settings.root_name || 'body';
      self.schema = schema = schema || new tinymce.html.Schema();
@@ -2690,16 +2693,17 @@
      };
      self.parse = function(html, args) {
         var parser, rootNode, node, nodes, i, l, fi, fl, list, name,
         var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate,
            blockElements, startWhiteSpaceRegExp, invalidChildren = [],
            endWhiteSpaceRegExp, allWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements;
         args = args || {};
         matchedNodes = {};
         matchedAttributes = {};
         blockElements = tinymce.extend(tinymce.makeMap('script,style,head,title,meta,param'), schema.getBlockElements());
         blockElements = tinymce.extend(tinymce.makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
         nonEmptyElements = schema.getNonEmptyElements();
         children = schema.children;
         validate = settings.validate;
         whiteSpaceElements = schema.getWhiteSpaceElements();
         startWhiteSpaceRegExp = /^[ \t\r\n]+/;
@@ -2721,9 +2725,26 @@
            return node;
         };
         function removeWhitespaceBefore(node) {
            var textNode, textVal, sibling;
            for (textNode = node.prev; textNode && textNode.type === 3; ) {
               textVal = textNode.value.replace(endWhiteSpaceRegExp, '');
               if (textVal.length > 0) {
                  textNode.value = textVal;
                  textNode = textNode.prev;
               } else {
                  sibling = textNode.prev;
                  textNode.remove();
                  textNode = sibling;
               }
            }
         };
         parser = new tinymce.html.SaxParser({
            validate : settings.validate,
            fix_self_closing : false, // Let the DOM parser handle <li> in <li> or <p> in <p> for better results
            validate : validate,
            fix_self_closing : !validate, // Let the DOM parser handle <li> in <li> or <p> in <p> for better results
            cdata: function(text) {
               node.append(createNode('#cdata', 4)).value = text;
@@ -2754,16 +2775,21 @@
            pi: function(name, text) {
               node.append(createNode(name, 7)).value = text;
               removeWhitespaceBefore(node);
            },
            doctype: function(text) {
               node.append(createNode('#doctype', 10)).value = text;
               var newNode;
               newNode = node.append(createNode('#doctype', 10));
               newNode.value = text;
               removeWhitespaceBefore(node);
            },
            start: function(name, attrs, empty) {
               var newNode, attrFiltersLen, elementRule, textNode, attrName, text, sibling, parent;
               elementRule = schema.getElementRule(name);
               elementRule = validate ? schema.getElementRule(name) : {};
               if (elementRule) {
                  newNode = createNode(elementRule.outputName || name, 1);
                  newNode.attributes = attrs;
@@ -2792,20 +2818,8 @@
                  }
                  // Trim whitespace before block
                  if (blockElements[name]) {
                     for (textNode = newNode.prev; textNode && textNode.type === 3; ) {
                        text = textNode.value.replace(endWhiteSpaceRegExp, '');
                        if (text.length > 0) {
                           textNode.value = text;
                           textNode = textNode.prev;
                        } else {
                           sibling = textNode.prev;
                           textNode.remove();
                           textNode = sibling;
                        }
                     }
                  }
                  if (blockElements[name])
                     removeWhitespaceBefore(newNode);
                  // Change current node if the element wasn't empty i.e not <br /> or <img />
                  if (!empty)
@@ -2816,7 +2830,7 @@
            end: function(name) {
               var textNode, elementRule, text, sibling, tempNode;
               elementRule = schema.getElementRule(name);
               elementRule = validate ? schema.getElementRule(name) : {};
               if (elementRule) {
                  if (blockElements[name]) {
                     if (!whiteSpaceElements[node.name]) {
@@ -2887,7 +2901,8 @@
         parser.parse(html);
         fixInvalidChildren(invalidChildren);
         if (validate)
            fixInvalidChildren(invalidChildren);
         // Run node filters
         for (name in matchedNodes) {
@@ -3019,8 +3034,12 @@
         else
            html[html.length] = ' />';
         /*if (indent && indentAfter[name])
            html.push('\n');*/
         if (empty && indent && indentAfter[name] && html.length > 0) {
            value = html[html.length - 1];
            if (value.length > 0 && value !== '\n')
               html.push('\n');
         }
      },
      end: function(name) {
@@ -3061,10 +3080,13 @@
            html.push('<?', name, ' ', text, '?>');
         else
            html.push('<?', name, '?>');
         if (indent)
            html.push('\n');
      },
      doctype: function(text) {
         html.push('<!DOCTYPE', text, '>');
         html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
      },
      reset: function() {
@@ -3201,7 +3223,8 @@
      isIE = tinymce.isIE,
      Entities = tinymce.html.Entities,
      simpleSelectorRe = /^([a-z0-9],?)+$/i,
      blockElementsMap = tinymce.html.Schema.blockElementsMap;
      blockElementsMap = tinymce.html.Schema.blockElementsMap,
      whiteSpaceRegExp = /^[ \t\r\n]*$/;
   tinymce.create('tinymce.dom.DOMUtils', {
      doc : null,
@@ -3239,7 +3262,8 @@
            keep_values : false,
            hex_colors : 1
         }, s);
         t.schema = s.schema;
         t.styles = new tinymce.html.Styles({
            url_converter : s.url_converter,
            url_converter_scope : s.url_converter_scope
@@ -3469,9 +3493,7 @@
      remove : function(node, keep_children) {
         return this.run(node, function(node) {
            var parent, child;
            parent = node.parentNode;
            var child, parent = node.parentNode;
            if (!parent)
               return null;
@@ -3539,7 +3561,7 @@
         n = this.get(n);
         if (!n)
            return false;
            return;
         // Gecko
         if (this.doc.defaultView && c) {
@@ -3568,7 +3590,7 @@
         if (n.currentStyle && c)
            return n.currentStyle[na];
         return n.style[na];
         return n.style ? n.style[na] : undefined;
      },
      setStyles : function(e, o) {
@@ -3589,8 +3611,8 @@
      removeAllAttribs: function(e) {
         return this.run(e, function(e) {
            var attrs = e.attributes;
            for (var i = attrs.length - 1; i >= 0; i--) {
            var i, attrs = e.attributes;
            for (i = attrs.length - 1; i >= 0; i--) {
               e.removeAttributeNode(attrs.item(i));
            }
         });
@@ -3645,7 +3667,7 @@
                  }
                  break;
               case "shape":
                  e.setAttribute('data-mce-style', v);
                  break;
@@ -4257,6 +4279,45 @@
         return n.attributes;
      },
      isEmpty : function(node, elements) {
         var self = this, i, attributes, type, walker, name;
         node = node.firstChild;
         if (node) {
            walker = new tinymce.dom.TreeWalker(node);
            elements = elements || self.schema ? self.schema.getNonEmptyElements() : null;
            do {
               type = node.nodeType;
               if (type === 1) {
                  // Ignore bogus elements
                  if (node.getAttribute('data-mce-bogus'))
                     continue;
                  // Keep empty elements like <img />
                  if (elements && elements[node.nodeName.toLowerCase()])
                     return false;
                  // Keep elements with data attributes or name attribute like <a name="1"></a>
                  attributes = self.getAttribs(node);
                  i = node.attributes.length;
                  while (i--) {
                     name = node.attributes[i].nodeName;
                     if (name === "name" || name.indexOf('data-') === 0)
                        return false;
                  }
               }
               // Keep non whitespace text nodes
               if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue)))
                  return false;
            } while (node = walker.next());
         }
         return true;
      },
      destroy : function(s) {
         var t = this;
@@ -4312,23 +4373,21 @@
         // this function will then trim of empty edges and produce:
         //   <p>text 1</p><b>CHOP</b><p>text 2</p>
         function trim(node) {
            var i, children = node.childNodes;
            var i, children = node.childNodes, type = node.nodeType;
            if (node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark')
            if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark')
               return;
            for (i = children.length - 1; i >= 0; i--)
               trim(children[i]);
            if (node.nodeType != 9) {
            if (type != 9) {
               // Keep non whitespace text nodes
               if (node.nodeType == 3 && node.nodeValue.length > 0) {
               if (type == 3 && node.nodeValue.length > 0) {
                  // If parent element isn't a block or there isn't any useful contents for example "<p>   </p>"
                  if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0)
                     return;
               }
               if (node.nodeType == 1) {
               } else if (type == 1) {
                  // If the only child is a bookmark then move it up
                  children = node.childNodes;
                  if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark')
@@ -7428,7 +7487,13 @@
            if (s) {
               t.explicitRange = r;
               s.removeAllRanges();
               try {
                  s.removeAllRanges();
               } catch (ex) {
                  // IE9 might throw errors here don't know why
               }
               s.addRange(r);
               t.selectedRange = s.getRangeAt(0);
            }
@@ -7859,6 +7924,10 @@
            args.content = htmlSerializer.serialize(
               htmlParser.parse(args.getInner ? node.innerHTML : tinymce.trim(dom.getOuterHTML(node), args), args)
            );
            // Replace all BOM characters for now until we can find a better solution
            if (!args.cleanup)
               args.content = args.content.replace(/\uFEFF/g, '');
            // Post process
            if (!args.no_events)
@@ -9762,21 +9831,20 @@
      hideMenu : function(e) {
         var t = this;
         // Prevent double toogles by canceling the mouse click event to the button
         if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
            return;
         if (t.isMenuVisible) {
            // Prevent double toogles by canceling the mouse click event to the button
            if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
               return;
         if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) {
            DOM.removeClass(t.id, 'mceSplitButtonSelected');
            Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
            Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
            DOM.hide(t.id + '_menu');
            if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) {
               DOM.removeClass(t.id, 'mceSplitButtonSelected');
               Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
               Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
               DOM.hide(t.id + '_menu');
            }
            t.isMenuVisible = 0;
         }
         t.onHideMenu.dispatch(t);
         t.isMenuVisible = 0;
         t.editor.focus();
      },
      renderMenu : function() {
@@ -9950,7 +10018,7 @@
(function(tinymce) {
// Shorten class names
var dom = tinymce.DOM, each = tinymce.each
var dom = tinymce.DOM, each = tinymce.each;
tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
   renderHTML : function() {
      var t = this, h = '', c, co, s = t.settings, i, pr, nx, cl;
@@ -12622,14 +12690,17 @@
         mceInsertContent : function(command, ui, value) {
            var caretNode, rng, rootNode, parent, node, rng, nodeRect, viewPortRect, args;
            function findSuitableCaretNode(start_node, root_node) {
               var node, walker = new tinymce.dom.TreeWalker(start_node, root_node);
            function findSuitableCaretNode(node, root_node, next) {
               var walker = new tinymce.dom.TreeWalker(next ? node.nextSibling : node.previousSibling, root_node);
               while ((node = walker.current())) {
                  if ((node.nodeType == 3 && tinymce.trim(node.nodeValue).length) || node.nodeName == 'BR' || node.nodeName == 'IMG')
                     return node;
                  walker.prev();
                  if (next)
                     walker.next();
                  else
                     walker.prev();
               }
            };
@@ -12650,7 +12721,7 @@
            // Move the caret into the last suitable location within the previous sibling if it's a block since the block might be split
            if (caretNode.previousSibling && dom.isBlock(caretNode.previousSibling) || caretNode.parentNode == rootNode) {
               node = findSuitableCaretNode(caretNode.previousSibling, rootNode);
               node = findSuitableCaretNode(caretNode, rootNode);
               if (node) {
                  if (node.nodeName == 'BR')
                     node.parentNode.insertBefore(caretNode, node);
@@ -12666,9 +12737,7 @@
                  // This will remove invalid elements/attributes and fix nesting issues
                  dom.setOuterHTML(parent, 
                     new tinymce.html.Serializer({}, editor.schema).serialize(
                        new tinymce.html.DomParser({
                           remove_trailing_brs : true
                        }, editor.schema).parse(dom.getOuterHTML(parent))
                        editor.parser.parse(dom.getOuterHTML(parent))
                     )
                  );
@@ -12682,7 +12751,7 @@
            // Find caret after cleanup and move selection to that location
            caretNode = dom.select('#__mce')[0];
            if (caretNode) {
               node = findSuitableCaretNode(caretNode.previousSibling, rootNode);
               node = findSuitableCaretNode(caretNode, rootNode) || findSuitableCaretNode(caretNode, rootNode, true);
               dom.remove(caretNode);
               if (node) {
@@ -12791,7 +12860,7 @@
         },
         mceReplaceContent : function(command, ui, value) {
            editor.execCommand('mceInsertContent', false, selection.setContent(value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'}))));
            editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'})));
         },
         mceInsertLink : function(command, ui, value) {
@@ -13064,19 +13133,10 @@
      return rng2.cloneContents().textContent.length == 0;
   };
   function isEmpty(n) {
      n = n.innerHTML;
      n = n.replace(/<(img|hr|table|input|select|textarea)[ \>]/gi, '-'); // Keep these convert them to - chars
      n = n.replace(/<[^>]+>/g, ''); // Remove all tags
      return n.replace(/[ \u00a0\t\r\n]+/g, '') == '';
   };
   function splitList(selection, dom, li) {
      var listBlock, block;
      if (isEmpty(li)) {
      if (dom.isEmpty(li)) {
         listBlock = dom.getParent(li, 'ul,ol');
         if (!dom.getParent(listBlock.parentNode, 'ul,ol')) {
@@ -13607,7 +13667,7 @@
            aft.innerHTML = aft.firstChild.innerHTML;
         // Padd empty blocks
         if (isEmpty(bef))
         if (dom.isEmpty(bef))
            bef.innerHTML = '<br />';
         function appendStyles(e, en) {
@@ -13641,7 +13701,7 @@
         };
         // Fill empty afterblook with current style
         if (isEmpty(aft))
         if (dom.isEmpty(aft))
            car = appendStyles(aft, en);
         // Opera needs this one backwards for older versions