X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=roojs-debug.js;h=27f607683cfc9137cb51c7d1ab1977af84eeedc3;hb=b999dac6d220ed742af894af4750d19d0e6dc586;hp=2ff78ba979b6505bf4d0a8a595126bfccef37587;hpb=342e739abc83491daf6bb3acb3fa9614a47fdee0;p=roojs1 diff --git a/roojs-debug.js b/roojs-debug.js index 2ff78ba979..27f607683c 100644 --- a/roojs-debug.js +++ b/roojs-debug.js @@ -5208,7 +5208,167 @@ undoManager.transact({ }; -/* +/** + * @class Roo.lib.Range + * @constructor + * This is a toolkit, normally used to copy features into a Dom Range element + * Roo.lib.Range.wrap(x); + * + * + * + */ +Roo.lib.Range = function() { }; + +/** + * Wrap a Dom Range object, to give it new features... + * @static + * @param {Range} the range to wrap + */ +Roo.lib.Range.wrap = function(r) { + return Roo.apply(r, Roo.lib.Range.prototype); +}; +/** + * find a parent node eg. LI / OL + * @param {string|Array} node name or array of nodenames + * @return {DomElement|false} + */ +Roo.apply(Roo.lib.Range.prototype, +{ + + closest : function(str) + { + if (typeof(str) != 'string') { + // assume it's a array. + for(var i = 0;i < str.length;i++) { + var r = this.closest(str[i]); + if (r !== false) { + return r; + } + + } + return false; + } + str = str.toLowerCase(); + var n = this.commonAncestorContainer; // might not be a node + while (n.nodeType != 1) { + n = n.parentNode; + } + + if (n.nodeName.toLowerCase() == str ) { + return n; + } + if (n.nodeName.toLowerCase() == 'body') { + return false; + } + + return n.closest(str) || false; + + }, + cloneRange : function() + { + return Roo.lib.Range.wrap(Range.prototype.cloneRange.call(this)); + } +});/** + * @class Roo.lib.Selection + * @constructor + * This is a toolkit, normally used to copy features into a Dom Selection element + * Roo.lib.Selection.wrap(x); + * + * + * + */ +Roo.lib.Selection = function() { }; + +/** + * Wrap a Dom Range object, to give it new features... + * @static + * @param {Range} the range to wrap + */ +Roo.lib.Selection.wrap = function(r, doc) { + Roo.apply(r, Roo.lib.Selection.prototype); + r.ownerDocument = doc; // usefull so we dont have to keep referening to it. + return r; +}; +/** + * find a parent node eg. LI / OL + * @param {string|Array} node name or array of nodenames + * @return {DomElement|false} + */ +Roo.apply(Roo.lib.Selection.prototype, +{ + /** + * the owner document + */ + ownerDocument : false, + + getRangeAt : function(n) + { + return Roo.lib.Range.wrap(Selection.prototype.getRangeAt.call(this,n)); + }, + + /** + * insert node at selection + * @param {DomElement|string} node + * @param {string} cursor (after|in|none) where to place the cursor after inserting. + */ + insertNode: function(node, cursor) + { + if (typeof(node) == 'string') { + node = this.ownerDocument.createElement(node); + if (cursor == 'in') { + node.innerHTML = ' '; + } + } + + var range = this.getRangeAt(0); + + if (this.type != 'Caret') { + range.deleteContents(); + } + var sn = node.childNodes[0]; // select the contents. + + + + range.insertNode(node); + if (cursor == 'after') { + node.insertAdjacentHTML('afterend', ' '); + sn = node.nextSibling; + } + + if (cursor == 'none') { + return; + } + + this.cursorText(sn); + }, + + cursorText : function(n) + { + + //var range = this.getRangeAt(0); + range = Roo.lib.Range.wrap(new Range()); + //range.selectNode(n); + + var ix = Array.from(n.parentNode.childNodes).indexOf(n); + range.setStart(n.parentNode,ix); + range.setEnd(n.parentNode,ix+1); + //range.collapse(false); + + this.removeAllRanges(); + this.addRange(range); + + Roo.log([n, range, this,this.baseOffset,this.extentOffset, this.type]); + }, + cursorAfter : function(n) + { + if (!n.nextSibling || n.nextSibling.nodeValue != ' ') { + n.insertAdjacentHTML('afterend', ' '); + } + this.cursorText (n.nextSibling); + } + + +});/* * Based on: * Ext JS Library 1.1.1 * Copyright(c) 2006-2007, Ext JS, LLC. @@ -5476,10 +5636,15 @@ Roo.DomHelper = function(){ from.data = to.data; return; } - + if (!from.parentNode) { + // not sure why this is happening? + return; + } // assume 'to' doesnt have '1/3 nodetypes! + // not sure why, by from, parent node might not exist? if (from.nodeType !=1 || from.tagName != to.tagName) { Roo.log(["ReplaceChild" , from, to ]); + from.parentNode.replaceChild(to, from); return; } @@ -34606,6 +34771,7 @@ Roo.extend(Roo.LayoutDialog, Roo.BasicDialog, { /** * @class Roo.MessageBox + * @static * Utility class for generating different styles of message boxes. The alias Roo.Msg can also be used. * Example usage: *

@@ -39824,7 +39990,7 @@ Roo.extend(Roo.menu.Item, Roo.menu.BaseItem, {
      */
     text: '',
      /**
-     * @cfg {String} HTML to render in menu
+     * @cfg {String} html to render in menu
      * The text to show on the menu item (HTML version).
      */
     html: '',
@@ -46023,7 +46189,7 @@ Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
         var cn = Array.from(node.childNodes);
         var nn = node;
         Roo.each(inject, function(t) {
-            var nc = node.ownerDocument.createelement(t);
+            var nc = node.ownerDocument.createElement(t);
             nn.appendChild(nc);
             nn = nc;
         });
@@ -46103,6 +46269,42 @@ Roo.extend(Roo.htmleditor.FilterLongBr, Roo.htmleditor.Filter,
 
     }
     
+}); 
+
+/**
+ * @class Roo.htmleditor.FilterBlock
+ * removes id / data-block and contenteditable that are associated with blocks
+ * usage should be done on a cloned copy of the dom
+ * @constructor
+* Run a new Attribute Filter { node : xxxx }}
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterBlock = function(cfg)
+{
+    Roo.apply(this, cfg);
+    var qa = cfg.node.querySelectorAll;
+    this.removeAttributes('data-block');
+    this.removeAttributes('contenteditable');
+    this.removeAttributes('id');
+    
+}
+
+Roo.apply(Roo.htmleditor.FilterBlock.prototype,
+{
+    node: true, // all tags
+     
+     
+    removeAttributes : function(attr)
+    {
+        var ar = this.node.querySelectorAll('*[' + attr + ']');
+        for (var i =0;i insetion
+        if (pli.innerText.trim() == '' &&
+            pli.previousSibling &&
+            pli.previousSibling.nodeName == 'LI' &&
+            pli.previousSibling.innerText.trim() ==  '') {
+            pli.parentNode.removeChild(pli.previousSibling);
+            sel.cursorAfter(pc);
+            this.core.undoManager.addEvent();
+            this.core.fireEditorEvent(e);
             return false;
-            
-            
         }
-        //add the br, or p, or something else
-        newEle = doc.createElement('br');
-        docFragment.appendChild(newEle);
     
-        //make the br replace selection
-        
-        range.deleteContents();
+        var li = doc.createElement('LI');
+        li.innerHTML = ' ';
+        if (!pli || !pli.firstSibling) {
+            pc.appendChild(li);
+        } else {
+            pli.parentNode.insertBefore(li, pli.firstSibling);
+        }
+        sel.cursorText (li.firstChild);
+      
+        this.core.undoManager.addEvent();
+        this.core.fireEditorEvent(e);
+
+        return false;
         
-        range.insertNode(docFragment);
-        range = range.cloneRange();
-        range.collapse(true);
-        var sel = this.core.win.getSelection();
-        sel.removeAllRanges();
-        sel.addRange(range);
-        sel.collapseToEnd();
     
-        return false;
+        
+        
          
     }
 };
@@ -46357,24 +46551,51 @@ Roo.htmleditor.Block  = function(cfg)
 {
     // do nothing .. should not be called really.
 }
-
+/**
+ * factory method to get the block from an element (using cache if necessary)
+ * @static
+ * @param {HtmlElement} the dom element
+ */
 Roo.htmleditor.Block.factory = function(node)
 {
-    
+    var cc = Roo.htmleditor.Block.cache;
     var id = Roo.get(node).id;
-    if (typeof(Roo.htmleditor.Block.cache[id]) != 'undefined') {
-        Roo.htmleditor.Block.cache[id].readElement();
+    if (typeof(cc[id]) != 'undefined' && (!cc[id].node || cc[id].node.closest('body'))) {
+        Roo.htmleditor.Block.cache[id].readElement(node);
         return Roo.htmleditor.Block.cache[id];
     }
-    
-    var cls = Roo.htmleditor['Block' + node.getAttribute('data-block')];
+    var db  = node.getAttribute('data-block');
+    if (!db) {
+        db = node.nodeName.toLowerCase().toUpperCaseFirst();
+    }
+    var cls = Roo.htmleditor['Block' + db];
     if (typeof(cls) == 'undefined') {
-        Roo.log("OOps missing block : " + 'Block' + node.getAttribute('data-block'));
+        //Roo.log(node.getAttribute('data-block'));
+        Roo.log("OOps missing block : " + 'Block' + db);
         return false;
     }
     Roo.htmleditor.Block.cache[id] = new cls({ node: node });
     return Roo.htmleditor.Block.cache[id];  /// should trigger update element
 };
+
+/**
+ * initalize all Elements from content that are 'blockable'
+ * @static
+ * @param the body element
+ */
+Roo.htmleditor.Block.initAll = function(body, type)
+{
+    if (typeof(type) == 'undefined') {
+        var ia = Roo.htmleditor.Block.initAll;
+        ia(body,'table');
+        ia(body,'td');
+        ia(body,'figure');
+        return;
+    }
+    Roo.each(Roo.get(body).query(type), function(e) {
+        Roo.htmleditor.Block.factory(e);    
+    },this);
+};
 // question goes here... do we need to clear out this cache sometimes?
 // or show we make it relivant to the htmleditor.
 Roo.htmleditor.Block.cache = {};
@@ -46384,7 +46605,10 @@ Roo.htmleditor.Block.prototype = {
     node : false,
     
      // used by context menu
-    friendly_name : 'Image with caption',
+    friendly_name : 'Based Block',
+    
+    // text for button to delete this element
+    deleteTitle : false,
     
     context : false,
     /**
@@ -46419,14 +46643,17 @@ Roo.htmleditor.Block.prototype = {
             // but kiss for now.
             n = node.getElementsByTagName(tag).item(0);
         }
+        if (!n) {
+            return '';
+        }
         if (attr == 'html') {
             return n.innerHTML;
         }
         if (attr == 'style') {
-            return n.style[style]
+            return n.style[style]; 
         }
         
-        return Roo.get(n).attr(attr);
+        return n.hasAttribute(attr) ? n.getAttribute(attr) : '';
             
     },
     /**
@@ -46457,8 +46684,8 @@ Roo.htmleditor.Block.prototype = {
  * Block that has an image and a figcaption
  * @cfg {String} image_src the url for the image
  * @cfg {String} align (left|right) alignment for the block default left
- * @cfg {String} text_align (left|right) alignment for the text caption default left.
  * @cfg {String} caption the text to appear below  (and in the alt tag)
+ * @cfg {String} caption_display (block|none) display or not the caption
  * @cfg {String|number} image_width the width of the image number or %?
  * @cfg {String|number} image_height the height of the image number or %?
  * 
@@ -46480,45 +46707,167 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
     
     // setable values.
     image_src: '',
-    
-    align: 'left',
+    align: 'center',
     caption : '',
-    text_align: 'left',
+    caption_display : 'block',
+    width : '100%',
+    cls : '',
+    href: '',
+    video_url : '',
     
-    width : '46%',
-    margin: '2%',
+    // margin: '2%', not used
+    
+    text_align: 'left', //   (left|right) alignment for the text caption default left. - not used at present
+
     
     // used by context menu
     friendly_name : 'Image with caption',
+    deleteTitle : "Delete Image and Caption",
     
-    context : { // ?? static really
-        width : {
-            title: "Width",
-            width: 40
-            // ?? number
-        },
-        margin : {
-            title: "Margin",
-            width: 40
-            // ?? number
-        },
-        align: {
-            title: "Align",
-            opts : [[ "left"],[ "right"]],
-            width : 80
+    contextMenu : function(toolbar)
+    {
+        
+        var block = function() {
+            return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+        };
+        
+        
+        var rooui =  typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+        
+        var syncValue = toolbar.editorcore.syncValue;
+        
+        var fields = {};
+        
+        return [
+             {
+                xtype : 'TextItem',
+                text : "Source: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'TextField',
+                allowBlank : false,
+                width : 150,
+                name : 'image_src',
+                listeners : {
+                    keyup : function (combo, e)
+                    { 
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.image_src = this.getValue();
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form
+                
+            },
+            {
+                xtype : 'TextItem',
+                text : "Width: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'width',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.width = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['auto'],
+                        ['50%'],
+                        ['100%']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            {
+                xtype : 'TextItem',
+                text : "Align: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'align',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.align = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['left'],
+                        ['right'],
+                        ['center']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
             
-        },
-        text_align: {
-            title: "Caption Align",
-            opts : [ [ "left"],[ "right"],[ "center"]],
-            width : 80
-        },
+            
+            {
+                xtype : 'Button',
+                text: 'Hide Caption',
+                name : 'caption_display',
+                pressed : false,
+                enableToggle : true,
+                setValue : function(v) {
+                    this.toggle(v == 'block' ? false : true);
+                },
+                listeners : {
+                    toggle: function (btn, state)
+                    {
+                        var b  = block();
+                        b.caption_display = b.caption_display == 'block' ? 'none' : 'block';
+                        this.setText(b.caption_display == 'block' ? "Hide Caption" : "Show Caption");
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            }
+        ];
         
-       
-        image_src : {
-            title: "Src",
-            width: 220
-        }
     },
     /**
      * create a DomHelper friendly object - for use with
@@ -46529,48 +46878,115 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
         var d = document.createElement('div');
         d.innerHTML = this.caption;
         
-        return {
+        var m = this.width == '50%' && this.align == 'center' ? '0 auto' : 0; 
+        
+        var img =   {
+            tag : 'img',
+            contenteditable : 'false',
+            src : this.image_src,
+            alt : d.innerText.replace(/\n/g, " "), // removeHTML..
+            style: {
+                width : 'auto',
+                'max-width': '100%',
+                margin : '0px' 
+                
+                
+            }
+        };
+        /*
+        '
' + + '' + + '' + + '' + + '
', + */ + + if (this.href.length > 0) { + img = { + tag : 'a', + href: this.href, + contenteditable : 'true', + cn : [ + img + ] + }; + } + + + if (this.video_url.length > 0) { + img = { + tag : 'div', + cls : this.cls, + frameborder : 0, + allowfullscreen : true, + width : 420, // these are for video tricks - that we replace the outer + height : 315, + src : this.video_url, + cn : [ + img + ] + }; + } + + return { tag: 'figure', 'data-block' : 'Figure', contenteditable : 'false', style : { - display: 'table', + display: 'block', float : this.align , - width : this.width, - margin: this.margin + 'max-width': this.width, + width : 'auto', + margin: m, + padding: '10px' + }, + + + align : this.align, cn : [ - { - tag : 'img', - src : this.image_src, - alt : d.innerText.replace(/\n/g, " "), // removeHTML.. - style: { - width: '100%' - } - }, + img, + { tag: 'figcaption', contenteditable : true, style : { - 'text-align': this.text_align + 'text-align': 'left', + 'margin-top' : '16px', + 'font-size' : '16px', + 'line-height' : '24px', + 'font-style': 'italic', + display : this.caption_display }, + cls : this.cls.length > 0 ? (this.cls + '-thumbnail' ) : '', html : this.caption } ] }; + }, readElement : function(node) { + // this should not really come from the link... + this.video_url = this.getVal(node, 'div', 'src'); + this.cls = this.getVal(node, 'div', 'class'); + this.href = this.getVal(node, 'a', 'href'); + this.image_src = this.getVal(node, 'img', 'src'); - this.align = this.getVal(node, 'figure', 'style', 'float'); + + this.align = this.getVal(node, 'figure', 'align'); this.caption = this.getVal(node, 'figcaption', 'html'); - this.text_align = this.getVal(node, 'figcaption', 'style','text-align'); - this.width = this.getVal(node, 'figure', 'style', 'width'); - this.margin = this.getVal(node, 'figure', 'style', 'margin'); + //this.text_align = this.getVal(node, 'figcaption', 'style','text-align'); + this.width = this.getVal(node, 'figure', 'style', 'max-width'); + //this.margin = this.getVal(node, 'figure', 'style', 'margin'); - } + }, + removeNode : function() + { + return this.node; + } @@ -46581,270 +46997,1524 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, { }) -//