-
26 Jun 2010 2:30 PM #1
[OPEN-1078] DomHelper insertHtml throws error on thead element
[OPEN-1078] DomHelper insertHtml throws error on thead element
While writing a plugin for GridPanel that was attempting to insert html inside the <thead> element of the header, I was getting an "invalid target element for this operation" error. I tracked it down to Ext.DomHelper.
Here is my fix:
Code:Ext.DomHelper = function(){ var tempTableEl = null, emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i, tableRe = /^table|thead|tbody|tr|td$/i, confRe = /tag|children|cn|html$/i, tableElRe = /td|tr|tbody/i, cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi, endRe = /end/i, pub, afterbegin = 'afterbegin', afterend = 'afterend', beforebegin = 'beforebegin', beforeend = 'beforeend', ts = '<table>', te = '</table>', ths = ts+'<thead>', the = ts+'</thead>', tbs = ts+'<tbody>', tbe = '</tbody>'+te, trs = tbs + '<tr>', tre = '</tr>'+tbe; function doInsert(el, o, returnElement, pos, sibling, append){ var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o)); return returnElement ? Ext.get(newNode, true) : newNode; } function createHtml(o){ var b = '', attr, val, key, keyVal, cn; if(typeof o == "string"){ b = o; } else if (Ext.isArray(o)) { for (var i=0; i < o.length; i++) { if(o[i]) { b += createHtml(o[i]); } }; } else { b += '<' + (o.tag = o.tag || 'div'); for (attr in o) { val = o[attr]; if(!confRe.test(attr)){ if (typeof val == "object") { b += ' ' + attr + '="'; for (key in val) { b += key + ':' + val[key] + ';'; }; b += '"'; }else{ b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"'; } } }; if (emptyTags.test(o.tag)) { b += '/>'; } else { b += '>'; if ((cn = o.children || o.cn)) { b += createHtml(cn); } else if(o.html){ b += o.html; } b += '</' + o.tag + '>'; } } return b; } function ieTable(depth, s, h, e){ tempTableEl.innerHTML = [s, h, e].join(''); var i = -1, el = tempTableEl, ns; while(++i < depth){ el = el.firstChild; } if(ns = el.nextSibling){ var df = document.createDocumentFragment(); while(el){ ns = el.nextSibling; df.appendChild(el); el = ns; } el = df; } return el; } function insertIntoTable(tag, where, el, html) { var node, before; tempTableEl = tempTableEl || document.createElement('div'); if(tag == 'td' && (where == afterbegin || where == beforeend) || !tableElRe.test(tag) && (where == beforebegin || where == afterend)) { return; } before = where == beforebegin ? el : where == afterend ? el.nextSibling : where == afterbegin ? el.firstChild : null; if (where == beforebegin || where == afterend) { el = el.parentNode; } if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) { node = ieTable(4, trs, html, tre); } else if ((tag == 'thead' && (where == beforeend || where == afterbegin)) || (el.parentNode.tagName.toLowerCase() == 'thead' && (tag == 'tr' && (where == beforebegin || where == afterend)))) { node = ieTable(3, ths, html, the); } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) || (tag == 'tr' && (where == beforebegin || where == afterend))) { node = ieTable(3, tbs, html, tbe); } else { node = ieTable(2, ts, html, te); } el.insertBefore(node, before); return node; } pub = { markup : function(o){ return createHtml(o); }, applyStyles : function(el, styles){ if(styles){ var i = 0, len, style, matches; el = Ext.fly(el); if(typeof styles == "function"){ styles = styles.call(); } if(typeof styles == "string"){ while((matches = cssRe.exec(styles))){ el.setStyle(matches[1], matches[2]); } }else if (typeof styles == "object"){ el.setStyle(styles); } } }, insertHtml : function(where, el, html){ var hash = {}, hashVal, setStart, range, frag, rangeEl, rs; where = where.toLowerCase(); hash[beforebegin] = ['BeforeBegin', 'previousSibling']; hash[afterend] = ['AfterEnd', 'nextSibling']; if (el.insertAdjacentHTML) { if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){ return rs; } hash[afterbegin] = ['AfterBegin', 'firstChild']; hash[beforeend] = ['BeforeEnd', 'lastChild']; if ((hashVal = hash[where])) { el.insertAdjacentHTML(hashVal[0], html); return el[hashVal[1]]; } } else { range = el.ownerDocument.createRange(); setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before'); if (hash[where]) { range[setStart](el); frag = range.createContextualFragment(html); el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling); return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling']; } else { rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child'; if (el.firstChild) { range[setStart](el[rangeEl]); frag = range.createContextualFragment(html); if(where == afterbegin){ el.insertBefore(frag, el.firstChild); }else{ el.appendChild(frag); } } else { el.innerHTML = html; } return el[rangeEl]; } } throw 'Illegal insertion point -> "' + where + '"'; }, insertBefore : function(el, o, returnElement){ return doInsert(el, o, returnElement, beforebegin); }, insertAfter : function(el, o, returnElement){ return doInsert(el, o, returnElement, afterend, 'nextSibling'); }, insertFirst : function(el, o, returnElement){ return doInsert(el, o, returnElement, afterbegin, 'firstChild'); }, append : function(el, o, returnElement){ return doInsert(el, o, returnElement, beforeend, '', true); }, overwrite : function(el, o, returnElement){ el = Ext.getDom(el); el.innerHTML = createHtml(o); return returnElement ? Ext.get(el.firstChild) : el.firstChild; }, createHtml : createHtml }; return pub; }();
-
9 May 2011 12:52 PM #2
Still a problem in Ext Core 3.1.0 and ExtJS 3.3.1
Still a problem in Ext Core 3.1.0 and ExtJS 3.3.1
Thanks in2chicago!
Your solution nearly worked for me. I had to add support for TH elements (treated just like TDs).
Devs: this remains a problem in Ext Core 3.1.0 and ExtJS 3.3.1
(Core, remember that one? Would love an update!
)
Test page:
Here's the fully-fixed code with support for both THEAD and TH:Code:<html> <head> <script type="text/javascript" src="ext-core-3.1.0/ext-core.js"></script> </head> <body> <table border=1> <thead> <tr id="thead1"><th>THEAD One</th></tr> </thead> <tbody> <tr id="tbody1"><th>TBODY One</th></tr> <tr id="tbody2"><td>TBODY Two</td></tr> </tbody> </table> <h5>Note: works in IE when target is TR; also works when TD; does NOT when TH</h5> <script> alert('test 1...'); Ext.DomHelper.insertAfter(Ext.get('tbody1').down('th').dom,{ tag: 'th', children: [{ tag: 'th' ,html: 'THEAD 2 - from ExtJS' }] }); alert('test 2...'); Ext.DomHelper.insertAfter(Ext.get('thead1').down('th').dom,{ tag: 'td', children: [{ tag: 'td' ,html: 'THEAD 2 - from ExtJS' }] }); </script> </body></html>
Code:Ext.DomHelper = function(){ var tempTableEl = null, emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i, tableRe = /^table|thead|tbody|tr|td|th$/i, confRe = /tag|children|cn|html$/i, tableElRe = /th|td|tr|tbody/i, cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi, endRe = /end/i, pub, afterbegin = 'afterbegin', afterend = 'afterend', beforebegin = 'beforebegin', beforeend = 'beforeend', ts = '<table>', te = '</table>', ths = ts+'<thead>', the = ts+'</thead>', tbs = ts+'<tbody>', tbe = '</tbody>'+te, trs = tbs + '<tr>', tre = '</tr>'+tbe; function doInsert(el, o, returnElement, pos, sibling, append){ var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o)); return returnElement ? Ext.get(newNode, true) : newNode; } function createHtml(o){ var b = '', attr, val, key, keyVal, cn; if(typeof o == "string"){ b = o; } else if (Ext.isArray(o)) { for (var i=0; i < o.length; i++) { if(o[i]) { b += createHtml(o[i]); } }; } else { b += '<' + (o.tag = o.tag || 'div'); for (attr in o) { val = o[attr]; if(!confRe.test(attr)){ if (typeof val == "object") { b += ' ' + attr + '="'; for (key in val) { b += key + ':' + val[key] + ';'; }; b += '"'; }else{ b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"'; } } }; if (emptyTags.test(o.tag)) { b += '/>'; } else { b += '>'; if ((cn = o.children || o.cn)) { b += createHtml(cn); } else if(o.html){ b += o.html; } b += '</' + o.tag + '>'; } } return b; } function ieTable(depth, s, h, e){ tempTableEl.innerHTML = [s, h, e].join(''); var i = -1, el = tempTableEl, ns; while(++i < depth){ el = el.firstChild; } if(ns = el.nextSibling){ var df = document.createDocumentFragment(); while(el){ ns = el.nextSibling; df.appendChild(el); el = ns; } el = df; } return el; } function insertIntoTable(tag, where, el, html) { var node, before; tempTableEl = tempTableEl || document.createElement('div'); if((tag == 'td' || tag == 'th') && (where == afterbegin || where == beforeend) || !tableElRe.test(tag) && (where == beforebegin || where == afterend)) { return; } before = where == beforebegin ? el : where == afterend ? el.nextSibling : where == afterbegin ? el.firstChild : null; if (where == beforebegin || where == afterend) { el = el.parentNode; } if ((tag == 'td' || tag == 'th') || (tag == 'tr' && (where == beforeend || where == afterbegin))) { node = ieTable(4, trs, html, tre); } else if ((tag == 'thead' && (where == beforeend || where == afterbegin)) || (el.parentNode.tagName.toLowerCase() == 'thead' && (tag == 'tr' && (where == beforebegin || where == afterend)))) { node = ieTable(3, ths, html, the); } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) || (tag == 'tr' && (where == beforebegin || where == afterend))) { node = ieTable(3, tbs, html, tbe); } else { node = ieTable(2, ts, html, te); } el.insertBefore(node, before); return node; } pub = { markup : function(o){ return createHtml(o); }, applyStyles : function(el, styles){ if(styles){ var i = 0, len, style, matches; el = Ext.fly(el); if(typeof styles == "function"){ styles = styles.call(); } if(typeof styles == "string"){ while((matches = cssRe.exec(styles))){ el.setStyle(matches[1], matches[2]); } }else if (typeof styles == "object"){ el.setStyle(styles); } } }, insertHtml : function(where, el, html){ var hash = {}, hashVal, setStart, range, frag, rangeEl, rs; where = where.toLowerCase(); hash[beforebegin] = ['BeforeBegin', 'previousSibling']; hash[afterend] = ['AfterEnd', 'nextSibling']; if (el.insertAdjacentHTML) { if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){ return rs; } hash[afterbegin] = ['AfterBegin', 'firstChild']; hash[beforeend] = ['BeforeEnd', 'lastChild']; if ((hashVal = hash[where])) { el.insertAdjacentHTML(hashVal[0], html); return el[hashVal[1]]; } } else { range = el.ownerDocument.createRange(); setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before'); if (hash[where]) { range[setStart](el); frag = range.createContextualFragment(html); el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling); return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling']; } else { rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child'; if (el.firstChild) { range[setStart](el[rangeEl]); frag = range.createContextualFragment(html); if(where == afterbegin){ el.insertBefore(frag, el.firstChild); }else{ el.appendChild(frag); } } else { el.innerHTML = html; } return el[rangeEl]; } } throw 'Illegal insertion point -> "' + where + '"'; }, insertBefore : function(el, o, returnElement){ return doInsert(el, o, returnElement, beforebegin); }, insertAfter : function(el, o, returnElement){ return doInsert(el, o, returnElement, afterend, 'nextSibling'); }, insertFirst : function(el, o, returnElement){ return doInsert(el, o, returnElement, afterbegin, 'firstChild'); }, append : function(el, o, returnElement){ return doInsert(el, o, returnElement, beforeend, '', true); }, overwrite : function(el, o, returnElement){ el = Ext.getDom(el); el.innerHTML = createHtml(o); return returnElement ? Ext.get(el.firstChild) : el.firstChild; }, createHtml : createHtml }; return pub; }();-Michael B2B web application developer
Thank you for reporting this bug. We will make it our priority to review this report.
Similar Threads
-
[OPEN][2.x] Element.insertFirst does not accept a string as a DomHelper spec
By Animal in forum Ext 2.x: BugsReplies: 2Last Post: 17 Apr 2009, 2:43 AM -
[2.??] IE add component to panel after render cause Ext.DomHelper.insertHtml error
By miles.huang in forum Ext 2.x: BugsReplies: 1Last Post: 21 Apr 2008, 8:44 AM -
Ext 1.1.1: DomHelper.insertHtml
By jbraband in forum Ext 1.x: Help & DiscussionReplies: 5Last Post: 8 Oct 2007, 2:09 PM -
DomHelper.insertHtml and IE tables
By af040 in forum Ext 1.x: BugsReplies: 2Last Post: 15 Aug 2007, 6:07 PM -
DomHelper.insertHtml
By humpdi in forum Ext 1.x: Help & DiscussionReplies: 2Last Post: 19 Mar 2007, 11:31 AM


Reply With Quote