roojs-core.js
[roojs1] / roojs-debug.js
index 9b96233..9771318 100644 (file)
@@ -53,15 +53,26 @@ Roo.apply = function(o, c, defaults){
     var isStrict = document.compatMode == "CSS1Compat",
         isOpera = ua.indexOf("opera") > -1,
         isSafari = (/webkit|khtml/).test(ua),
+        isFirefox = ua.indexOf("firefox") > -1,
         isIE = ua.indexOf("msie") > -1,
         isIE7 = ua.indexOf("msie 7") > -1,
+        isIE11 = /trident.*rv\:11\./.test(ua),
         isGecko = !isSafari && ua.indexOf("gecko") > -1,
         isBorderBox = isIE && !isStrict,
         isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
         isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
         isLinux = (ua.indexOf("linux") != -1),
         isSecure = window.location.href.toLowerCase().indexOf("https") === 0,
-        isTouch =  'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
+        isIOS = /iphone|ipad/.test(ua),
+        isTouch =  (function() {
+            try {  
+                document.createEvent("TouchEvent");  
+                return true;  
+            } catch (e) {  
+                return false;  
+            } 
+            
+        })();
     // remove css image flicker
        if(isIE && !isIE7){
         try{
@@ -602,10 +613,14 @@ Roo.factory(conf, Roo.data);
         /** @type Boolean */
         isSafari : isSafari,
         /** @type Boolean */
+        isFirefox : isFirefox,
+        /** @type Boolean */
         isIE : isIE,
         /** @type Boolean */
         isIE7 : isIE7,
         /** @type Boolean */
+        isIE11 : isIE11,
+        /** @type Boolean */
         isGecko : isGecko,
         /** @type Boolean */
         isBorderBox : isBorderBox,
@@ -616,6 +631,8 @@ Roo.factory(conf, Roo.data);
         /** @type Boolean */
         isMac : isMac,
         /** @type Boolean */
+        isIOS : isIOS,
+        /** @type Boolean */
         isTouch : isTouch,
 
         /**
@@ -917,6 +934,7 @@ Roo.applyIf(Number.prototype, {
  */
 Roo.applyIf(Array.prototype, {
     /**
+     * 
      * Checks whether or not the specified object exists in the array.
      * @param {Object} o The object to check for
      * @return {Number} The index of o in the array (or -1 if it is not found)
@@ -1225,6 +1243,7 @@ Date.parseDate = function(input, format) {
 /**
  * @private
  */
+
 Date.createParser = function(format) {
     var funcName = "parse" + Date.parseFunctions.count++;
     var regexNum = Date.parseRegexes.length;
@@ -4220,8 +4239,10 @@ Roo.DomHelper = function(){
             if(attr=="cls" && Roo.isIE){
                 el.className = o["cls"];
             }else{
-                if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
-                else el[attr] = o[attr];
+                if(useSet) { el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);}
+                else { 
+                    el[attr] = o[attr];
+                }
             }
         }
         Roo.DomHelper.applyStyles(el, o.style);
@@ -6560,6 +6581,9 @@ Roo.onReady(function(){
     if(Roo.isLinux){
         cls.push("roo-linux");
     }
+    if(Roo.isIOS){
+        cls.push("roo-ios");
+    }
     if(Roo.isBorderBox){
         cls.push('roo-border-box');
     }
@@ -7021,6 +7045,7 @@ if(opt.anim.isAnimated()){
          * @type String
          */
         defaultUnit : "px",
+        
         /**
          * Sets the element's visibility mode. When setVisible() is called it
          * will use this to determine whether to set the visibility or the display property.
@@ -15166,7 +15191,7 @@ Roo.Component = function(config){
         destroy : true
     });
     if(!this.id){
-        this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
+        this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
     }
     Roo.ComponentMgr.register(this);
     Roo.Component.superclass.constructor.call(this);
@@ -22598,6 +22623,7 @@ var myReader = new Roo.data.JsonReader({
  * @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
  * @cfg {String} root name of the property which contains the Array of row objects.
  * @cfg {String} id Name of the property within a row object that contains a record identifier value.
+ * @cfg {Array} fields Array of field definition objects
  * @constructor
  * Create a new JsonReader
  * @param {Object} meta Metadata configuration options
@@ -37067,7 +37093,7 @@ Roo.extend(Roo.form.Field, Roo.BoxComponent,  {
      * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
      * {tag: "input", type: "text", size: "20", autocomplete: "off"})
      */
-    defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},
+    defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "new-password"},
     /**
      * @cfg {String} fieldClass The default CSS class for the field (defaults to "x-form-field")
      */
@@ -37979,7 +38005,7 @@ Roo.extend(Roo.form.TriggerField, Roo.form.TextField,  {
      * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
      * {tag: "input", type: "text", size: "16", autocomplete: "off"})
      */
-    defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
+    defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "new-password"},
     /**
      * @cfg {Boolean} hideTrigger True to hide the trigger element and display only the base text field (defaults to false)
      */
@@ -38259,7 +38285,7 @@ Roo.extend(Roo.form.TextArea, Roo.form.TextField,  {
             this.defaultAutoCreate = {
                 tag: "textarea",
                 style:"width:300px;height:60px;",
-                autocomplete: "off"
+                autocomplete: "new-password"
             };
         }
         Roo.form.TextArea.superclass.onRender.call(this, ct, position);
@@ -38977,7 +39003,7 @@ Roo.extend(Roo.form.MonthField, Roo.form.TriggerField,  {
      * {tag: "input", type: "text", size: "10", autocomplete: "off"})
      */ 
     // private
-    defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
+    defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "new-password"},
     
     // private
     hiddenField: false,
@@ -41224,7 +41250,6 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     getDocMarkup : function(){
         // body styles..
         var st = '';
-        Roo.log(this.stylesheets);
         
         // inherit styels from page...?? 
         if (this.stylesheets === false) {
@@ -41242,10 +41267,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 st = '<style type="text/css">' +
                     'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
                    '</style>';
-        } else {
-            Roo.each(this.stylesheets, function(s) {
-                st += '<link rel="stylesheet" type="text/css" href="' + s +'" />'
-            });
+        } else { 
             
         }
         
@@ -41326,8 +41348,6 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         };
         Roo.TaskMgr.start(task);
 
-        
-         
     },
 
     // private
@@ -41599,7 +41619,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         this.execCmd('FontSize', v  );
     },
 
-    onEditorEvent : function(e){
+    onEditorEvent : function(e)
+    {
         this.owner.fireEvent('editorevent', this, e);
       //  this.updateToolbar();
         this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
@@ -42238,21 +42259,12 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         
     },
+    
     /**
      * Clean up MS wordisms...
      */
     cleanWord : function(node)
     {
-        var _t = this;
-        var cleanWordChildren = function()
-        {
-            if (!node.childNodes.length) {
-                return;
-            }
-            for (var i = node.childNodes.length-1; i > -1 ; i--) {
-               _t.cleanWord(node.childNodes[i]);
-            }
-        }
         
         
         if (!node) {
@@ -42282,7 +42294,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 node.parentNode.insertBefore(cn, node);
             }
             node.parentNode.removeChild(node);
-            cleanWordChildren();
+            this.iterateChildren(node, this.cleanWord);
             return;
         }
         // clean styles
@@ -42326,11 +42338,87 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 node.removeAttribute('style');
             }
         }
+        this.iterateChildren(node, this.cleanWord);
+        
+        
+        
+    },
+    /**
+     * iterateChildren of a Node, calling fn each time, using this as the scole..
+     * @param {DomNode} node node to iterate children of.
+     * @param {Function} fn method of this class to call on each item.
+     */
+    iterateChildren : function(node, fn)
+    {
+        if (!node.childNodes.length) {
+                return;
+        }
+        for (var i = node.childNodes.length-1; i > -1 ; i--) {
+           fn.call(this, node.childNodes[i])
+        }
+    },
+    
+    
+    /**
+     * cleanTableWidths.
+     *
+     * Quite often pasting from word etc.. results in tables with column and widths.
+     * This does not work well on fluid HTML layouts - like emails. - so this code should hunt an destroy them..
+     *
+     */
+    cleanTableWidths : function(node)
+    {
+         
+         
+        if (!node) {
+            this.cleanTableWidths(this.doc.body);
+            return;
+        }
+        
+        // ignore list...
+        if (node.nodeName == "#text" || node.nodeName == "#comment") {
+            return; 
+        }
+        Roo.log(node.tagName);
+        if (!node.tagName.toLowerCase().match(/^(table|td|tr)$/)) {
+            this.iterateChildren(node, this.cleanTableWidths);
+            return;
+        }
+        if (node.hasAttribute('width')) {
+            node.removeAttribute('width');
+        }
+        
+         
+        if (node.hasAttribute("style")) {
+            // pretty basic...
+            
+            var styles = node.getAttribute("style").split(";");
+            var nstyle = [];
+            Roo.each(styles, function(s) {
+                if (!s.match(/:/)) {
+                    return;
+                }
+                var kv = s.split(":");
+                if (kv[0].match(/^\s*(width|min-width)\s*$/)) {
+                    return;
+                }
+                // what ever is left... we allow.
+                nstyle.push(s);
+            });
+            node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
+            if (!nstyle.length) {
+                node.removeAttribute('style');
+            }
+        }
         
-        cleanWordChildren();
+        this.iterateChildren(node, this.cleanTableWidths);
         
         
     },
+    
+    
+    
+    
     domToHTML : function(currentElement, depth, nopadtext) {
         
         depth = depth || 0;
@@ -42529,13 +42617,42 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         }, this);
     },
     
-    setStylesheets : function(href)
+    setStylesheets : function(stylesheets)
+    {
+        if(typeof(stylesheets) == 'string'){
+            Roo.get(this.iframe.contentDocument.head).createChild({
+                tag : 'link',
+                rel : 'stylesheet',
+                type : 'text/css',
+                href : stylesheets
+            });
+            
+            return;
+        }
+        var _this = this;
+     
+        Roo.each(stylesheets, function(s) {
+            if(!s.length){
+                return;
+            }
+            
+            Roo.get(_this.iframe.contentDocument.head).createChild({
+                tag : 'link',
+                rel : 'stylesheet',
+                type : 'text/css',
+                href : s
+            });
+        });
+
+        
+    },
+    
+    removeStylesheets : function()
     {
-        Roo.get(this.iframe.contentDocument.head).createChild({
-            tag : 'link',
-            rel : 'stylesheet',
-            type : 'text/css',
-            href : href
+        var _this = this;
+        
+        Roo.each(Roo.get(_this.iframe.contentDocument.head).select('link[rel=stylesheet]', true).elements, function(s){
+            s.remove();
         });
     }
     
@@ -42761,7 +42878,7 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
     defaultAutoCreate : { // modified by initCompnoent..
         tag: "textarea",
         style:"width:500px;height:300px;",
-        autocomplete: "off"
+        autocomplete: "new-password"
     },
 
     // private
@@ -42852,7 +42969,7 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
         this.defaultAutoCreate =  {
             tag: "textarea",
             style:'width: ' + this.width + 'px;height: ' + this.height + 'px;',
-            autocomplete: "off"
+            autocomplete: "new-password"
         };
     },
 
@@ -43218,9 +43335,14 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
         this.editorcore.pushValue();
     },
     
-    setStylesheets : function(href)
+    setStylesheets : function(stylesheets)
+    {
+        this.editorcore.setStylesheets(stylesheets);
+    },
+    
+    removeStylesheets : function()
     {
-        this.editorcore.setStylesheets(href);
+        this.editorcore.removeStylesheets();
     }
      
     
@@ -43662,6 +43784,15 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarStandard.prototype,  {
                     tabIndex:-1
                 });
             }
+             cmenu.menu.items.push({
+                actiontype : 'tablewidths',
+                html: 'Remove Table Widths',
+                handler: function(a,b) {
+                    editorcore.cleanTableWidths();
+                    editorcore.syncValue();
+                },
+                tabIndex:-1
+            });
             cmenu.menu.items.push({
                 actiontype : 'word',
                 html: 'Remove MS Word Formating',
@@ -43685,8 +43816,23 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarStandard.prototype,  {
                 },
                 tabIndex:-1
             });
+            
+            cmenu.menu.items.push({
+                actiontype : 'all',
+                html: 'Remove All CSS Classes',
+                handler: function(a,b) {
+                    
+                    var c = Roo.get(editorcore.doc.body);
+                    c.select('[class]').each(function(s) {
+                        s.dom.className = '';
+                    });
+                    editorcore.syncValue();
+                },
+                tabIndex:-1
+            });
+            
              cmenu.menu.items.push({
-                actiontype : 'word',
+                actiontype : 'tidy',
                 html: 'Tidy HTML Source',
                 handler: function(a,b) {
                     editorcore.doc.body.innerHTML = editorcore.domToHTML();
@@ -44346,6 +44492,8 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
     /**
      * Protected method that will not generally be called directly. It triggers
      * a toolbar update by reading the markup state of the current selection in the editor.
+     *
+     * Note you can force an update by calling on('editorevent', scope, false)
      */
     updateToolbar: function(editor,ev,sel){
 
@@ -44357,6 +44505,8 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
             return;
         }
         
+        
+        
         // http://developer.yahoo.com/yui/docs/simple-editor.js.html
         // selectNode - might want to handle IE?
         if (ev &&
@@ -44404,7 +44554,8 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         this.tb.selectedNode = sel;
         
         // if current menu does not match..
-        if ((this.tb.name != tn) || (lastSel != this.tb.selectedNode)) {
+        
+        if ((this.tb.name != tn) || (lastSel != this.tb.selectedNode) || ev === false) {
                 
             this.tb.el.hide();
             ///console.log("show: " + tn);
@@ -46675,7 +46826,7 @@ Roo.extend(Roo.form.FCKeditor, Roo.form.TextArea,
             this.defaultAutoCreate = {
                 tag: "textarea",
                 style:"width:300px;height:60px;",
-                autocomplete: "off"
+                autocomplete: "new-password"
             };
         }
         Roo.form.FCKeditor.superclass.onRender.call(this, ct, position);
@@ -46998,7 +47149,7 @@ Roo.extend(Roo.form.GridField, Roo.form.Field,  {
      * {tag: "input", type: "checkbox", autocomplete: "off"})
      */
    // defaultAutoCreate : { tag: 'div' },
-    defaultAutoCreate : { tag: 'input', type: 'hidden', autocomplete: 'off'},
+    defaultAutoCreate : { tag: 'input', type: 'hidden', autocomplete: 'new-password'},
     /**
      * @cfg {String} addTitle Text to include for adding a title.
      */
@@ -47241,7 +47392,7 @@ Roo.extend(Roo.form.DayPicker, Roo.form.Field,  {
      * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
      * {tag: "input", type: "checkbox", autocomplete: "off"})
      */
-    defaultAutoCreate : { tag: "input", type: 'hidden', autocomplete: "off"},
+    defaultAutoCreate : { tag: "input", type: 'hidden', autocomplete: "new-password"},
     
    
     actionMode : 'viewEl', 
@@ -50050,7 +50201,7 @@ Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
  * @cfg {Boolean}   floatable       False to disable floating (defaults to true)
  * @cfg {Object}    margins         Margins for the element (defaults to {top: 0, left: 0, right:0, bottom: 0})
  * @cfg {Object}    cmargins        Margins for the element when collapsed (defaults to: north/south {top: 2, left: 0, right:0, bottom: 2} or east/west {top: 0, left: 2, right:2, bottom: 0})
- * @cfg {String}    tabPosition     "top" or "bottom" (defaults to "bottom")
+ * @cfg {String}    tabPosition     (top|bottom) "top" or "bottom" (defaults to "bottom")
  * @cfg {String}    collapsedTitle  Optional string message to display in the collapsed block of a north or south region
  * @cfg {Boolean}   alwaysShowTabs  True to always display tabs even when there is only 1 panel (defaults to false)
  * @cfg {Boolean}   autoScroll      True to enable overflow scrolling (defaults to false)
@@ -50474,8 +50625,10 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
      * @param {Number/String/ContentPanel} panelId The panel's index, id or the panel itself
      * @return {Roo.ContentPanel} The shown panel, or null if a panel could not be found from panelId
      */
-    showPanel : function(panel){
-        if(panel = this.getPanel(panel)){
+    showPanel : function(panel)
+    {
+        panel = this.getPanel(panel);
+        if(panel){
             if(this.tabs){
                 var tab = this.tabs.getTab(panel.getEl().id);
                 if(tab.isHidden()){
@@ -55246,6 +55399,9 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
     /**
      * @cfg {String} cursor (Optional)
      */
+    /**
+     * @cfg {String} tooltip (Optional)
+     */
     /**
      * Returns the id of the column at the specified index.
      * @param {Number} index The column index
@@ -55784,6 +55940,7 @@ Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel,  {
         s.each(function(r){
             if((i = ds.indexOfId(r.id)) != -1){
                 v.onRowSelect(i);
+                s.add(ds.getAt(i)); // updating the selection relate data
             }else{
                 s.remove(r);
             }