A kind reminder we would like all registered users to weigh in on one of our forum's security policies.
Please take a moment to read this thread and place a vote. https://forum.palemoon.org/viewtopic.php?f=17&t=32935
One may decide that assigning a value to the off-screen textbox control broke it. But the reality is a little more complicated.
Apart from document.createElement(), there is .cloneNode() function. And using it I receive somewhat different results.
A clone works even after off-screen initialization:
But again: the things are a bit more complicated.
If I clone not a single element, but a DOM tree of nested elements (that's the point of .cloneNode(true)), then textbox does not work been initialized either off-screen:
I don't think you're handling the XUL hierarchy correctly.
IIRC, just using .before isn't doing what you expect.
You may want to reference https://udn.realityripple.com/docs/Web/API/Node/insertBefore -- inserting a sibling is a little more involved since you have to reference the parent node. As a result I think the added element will be a childNode and not a sibling, so your references to manipulate the value would then be wrong.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite
As a result I think the added element will be a childNode and not a sibling, so your references to manipulate the value would then be wrong.
I am manipulating the value of an element that I created - by using the return value of createElement()/cloneNode(), and not of getElementsBy...(). So the result can not depend on where exactly this element was inserted. Especially in those cases, where I modified the .value before adding the element to the DOM.
In my view it's best not to use DOM manipulation to create the UI when XUL exists. In fact don't even mix XUL and Javascript. You can assign the script to the XUL file using the script tag and then reference all XUL elements within it by name, and set the script to load when the window loads. Strict separation between UI and control logic.
Unless you're dynamically adding elements to the UI at runtime there is zero need to createElement or createNode.
"One hosts to look them up, one DNS to find them and in the darkness BIND them."
You can assign the script to the XUL file using the script tag and then reference all XUL elements within it by name, and set the script to load when the window loads.
I agree. But initially I discovered this problem when was working on the "Search Engine Editor" extension, and it is structured exactly as you have described.
In examples above everything is placed into one file just for simplicity.
Unless you're dynamically adding elements to the UI at runtime there is zero need to createElement or createNode.
Below is a fragment of EngineEditor.xul, which the handler of its "load" event (resided in EngineEditor.js) have to duplicate unpredictable number of times, because it is not known beforehand how many these panels the window must contain.
Keep in mind that Web APIs not always apply to XUL in the same way. e.g. by default you can't use html elements that the browser supports in content. Namespaces are different and not all bindings necessarily work the same way. I don't even know what the situation is exactly with in-lining js with <![CDATA[ -- moonbat makes a good point about having js separate. i.e.: I'm not so sure this is a bug, per se, and more a design decision (e.g. for chrome-sec reasons).
I'm not sure why you want to manipulate the XUL tree in-place to begin with. Just separate out the XUL UI elements as UI structure in .xul, any scripting into .js, and treat it as a more traditional trio of XML/JS/CSS than trying to do DOM jiggery-pokery to manipulate the elements.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite
Keep in mind that Web APIs not always apply to XUL in the same way. e.g. by default you can't use html elements that the browser supports in content.
In examples above I use either createElement(), or cloneNode(). Both functions are described in Web API section, but also both are equally mentioned in XUL documentation:
You can create new elements using the createElement() function of the document. It takes one argument, the tag name of the element to create. You can then set attributes of the element using the setAttribute() function and append it to the XUL document using the appendChild() function.
To copy nodes however, you may call the cloneNode() function. This function makes a copy of an existing node so that you can add it somewhere else. The original node will stay where it is. It takes one boolean argument which indicates whether to copy all of the node's children or not. If false, only the node is copied, such that the copy won't have any children. If true, all of the children are copied as well.
- explicitly and without any precautions.
textbox specification also does not impose any restrictions on manipulation with .value:
value
Type: string
Holds the current value of the textbox as a string. The current value may be modified by setting this property.
I'm not sure why you want to manipulate the XUL tree in-place to begin with. Just separate out the XUL UI elements as UI structure in .xul, any scripting into .js, and treat it as a more traditional trio of XML/JS/CSS than trying to do DOM jiggery-pokery to manipulate the elements.
As I answered to moonbat, the problem initially was observed in a real code, where everything (XUL/JS/CSS) was in separate files.
MDN Web APIs only applies to web content. It may or may not apply the same way to XUL.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite
Yes, the methods may be "sanctioned", but you may run into nuance differences.
But, if you feel it's an actual bug then please file an issue on the tracker, and if you want to help improve, find the bugzilla bug that fixed it (assuming Mozilla fixed it); e.g. using mozregression.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite
If there is need to contextually show different controls at the same place, i think better approach would be have them all defined in XUL, but all hidden except default set, and then showing/hiding them as needed instead of document tree manipulation.
If there is need to contextually show different controls at the same place, i think better approach would be have them all defined in XUL, but all hidden except default set, and then showing/hiding them as needed instead of document tree manipulation.
This is the normal way of doing it. e.g. tabbed interfaces just disable/hide the tabs (and tab contents) not active but they are all in the UI at the same time.
"There is no point in arguing with an idiot, because then you're both idiots." - Anonymous
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite
<?xml version="1.0"?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept"
ondialogaccept="alert(textBox.value); textBox.value='updated 123'; return false;">
<label id="label"/>
<script>
<![CDATA[
var label = document.getElementById("label");
var textBox = document.createElement("textbox");
var de = document.documentElement;
de.appendChild(textBox);
// The property "value" seems to be missing at the moment
// or the setter has not been assigned yet.
// Assigning will create the property, but it will not work any further
// (i.e. it will not be related to the state of the textbox).
// Use setAttribute here.
textBox.setAttribute('value', "initial value abc");
]]>
</script>
</dialog>
The problem is probably that the dialog hasn't fully initialized yet while your script is running.
Here it is - it works as it should if you create the element during the "load" event:
This your example works not because the code is executed in the "load" event handler, but because it changes the .value after attaching the element to a DOM tree. (Let try the opposite order.)
Today i put some efforts, studying the sources and tracing in the debugger, so I already understand what happens, when and why. I only need a time to issue the post.
(I see what can be changed in the XBL bindings file to overcome all these hassles. Just two additional lines of code.)
Anyway, using setAttribute it works too. And you don't need to use events and you can set the initial value before adding the element to the DOM. So for those who don't want to wait... :