这是一个关于Ext, Prototype, JavaScript方面的问题,其实下面遇到的问题本不是问题,都是因为错误的理解造成的,本文的宗旨是希望读者朋友避免我犯的同类错误,遇事三思而后行,同时也体会下发现问题,解决问题,反思问题这种精神活动所带来的快乐!
标签呢?
在测试:
var tpl = new Ext.Template('
this is div{id}
');
tpl.append('div1',{id:'2'});
tpl.insertAfter('div2',{id:'3'});
$("result-area").innerText = Ext.getDom("div1").outerHTML;
//.........
结果如下:
this is div1
this is div2
this is div3
(旁白:本来到这就已经能发现问题所在了,但执迷不悟,继续犯错)
原来它把div2,div3插到div1的value/text 后边了.所以运行tpl.overwrite('div1',{id:'88'});后div2,div3没了.
在此附上tpl.overwrite源码(innerHTML直接赋值):
overwrite : function(el, values, returnElement){
el = Ext.getDom(el);
el.innerHTML = this.applyTemplate(values);
return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
}
问题知道了,可怎么办呢,改Ext源码?
从做项目的角度来看,最好别改,因为你不清楚原作者的想法,容易把问题扩大化.
改源码不是不行,但那是没有办法的办法,如果能找到其它好的解决方案, 最好别改
(实际上Ext这块没有问题,只是我在参照API使用时,混淆了一些概念)
不改源码,只能找到其它好的解决方案了,用prototype.js看看:
var tpl = new Ext.Template('
this is div{id}
');
//tpl.append('div1',{id:'2'});
//tpl.insertAfter('div2',{id:'3'});
Insertion.After($('div1'),tpl.applyTemplate({id:'2'}));
Insertion.After($('div1'),tpl.applyTemplate({id:'3'}));
结果:
this is div88
this is div2
this is div3
Problem solved......................................
Reflection: Why?
Look at the code (Narration: the problem gets deeper and deeper)
Prototype.js line:4042 (ver 1.6.0.2)
var Insertion = {
Before: function(element, content) {
return Element.insert(element, {before:content});
},
Top: function(element, content) {
return Element.insert(element, {top:content}) ;
},
Bottom: function(element, content) {
return Element.insert(element, {bottom:content});
},
After: function(element, content ) {
return Element.insert(element, {after:content});
}
};
Then look at: line:1616
insert: function(element, insertions) {
element = $(element);
.............................................
for (var position in insertions) {
content = insertions[position];
position = position.toLowerCase();
insert = Element._insertionTranslations[position];
.......... .....................
return element;
}
See next: line:2490
Element._insertionTranslations = {
before: function(element, node) {
element.parentNode.insertBefore(node, element);
},
top: function(element, node) {
element.insertBefore(node, element.firstChild);
},
bottom: function(element, node) {
element.appendChild(node);
},
after: function(element, node) {
element.parentNode.insertBefore(node, element.nextSibling);
},
.............
};
See the difference:
Ext:
El. insertAdjacentHTML
Prototype:
El.parentNode.insertBefore
Protoype uses El.parentNode.insertBefore to consider compatibility issues. Mozilla does not support El. insertAdjacentHTML, so it is difficult to use Ext Didn’t you consider it? (Narration: The idea is completely messed up and gradually heading towards the abyss of loss)
Reviewing the code: DomHelper.js line: 267
insertHtml: function(where, el, html){
. .....
switch(where){
case "beforebegin":
el.insertAdjacentHTML('BeforeBegin', html);
return el.previousSibling;
case "afterbegin" :
el.insertAdjacentHTML('AfterBegin', html);
return el.firstChild;
case "beforeend":
el.insertAdjacentHTML('BeforeEnd', html);
return el .lastChild;
case "afterend":
el.insertAdjacentHTML('AfterEnd', html);
return el.nextSibling;
}
throw 'Illegal insertion point -> "' where '"';
}
var range = el.ownerDocument.createRange();
var frag;
switch(where){
case "beforebegin":
range. setStartBefore(el);
frag = range.createContextualFragment(html);
el.parentNode.insertBefore(frag, el);
return el.previousSibling;
case "afterbegin":
if(el.firstChild){
range.setStartBefore(el.firstChild);
frag = range.createContextualFragment(html);
el.insertBefore(frag, el.firstChild);
return el .firstChild;
}else{
el.innerHTML = html;
return el.firstChild;
}
case "beforeend":
if(el.lastChild){
range.setStartAfter(el.lastChild);
frag = range.createContextualFragment(html);
el.appendChild(frag);
return el.lastChild;
}else{
el .innerHTML = html;
return el.lastChild;
}
case "afterend":
range.setStartAfter(el);
frag = range.createContextualFragment(html);
el.parentNode.insertBefore(frag, el.nextSibling);
return el.nextSibling;
}
throw 'Illegal insertion point -> "' where '"';
}
From the second part (the second switch block), we can see that Ext is also considered, but if it is IE, the code cannot go to the second part.
Now list the correspondence between the case branch and the previous method name:
insertFirst:' afterBegin'
insertBefore:' beforeBegin'
insertAfter:' afterEnd'
append:' beforeEnd'
Comparing the above code, it seems that the problem is that I am confused append, insertAfter. I thought that append means appending a node directly after the current node, and insertAfter means inserting the node after the current node. In fact, if this is understood, append and insertAfter have the same functions. Then the author of Ext wrote two What is this method for?., Alas, I am stupid, I used it randomly without analyzing the code carefully, and it led to this long series of things.
Excerpt: Explanation on the append and insertAfter methods in Ext.Template
Applies the supplied values to the template and appends the new node(s) to el
Applies the supplied values to the template and inserts the new node(s) after el
Tip: For those who don’t understand, please put Wouldn’t it be much clearer if “to” in the first sentence is understood as “in”? In addition, if you operate on page elements, please use Element, which has the insert and append functions above.
So much effort is used in the wrong way In the direction, the final result is zero!
Alas,
There is nothing in the world, and it is only for mediocre people to disturb themselves.