whole document cloning not working in javascript - javascript

I am working on some stuff meanwhile i get into something which i didn't understand core reason behind it.
my idea(good or bad) is to clone a document and add changes to it and then reassign my cloned object into document
var tu=document.clone(true);
getComputedStyles(document)//returns all current css values
tu.getElementsByTagName("body")[0].style.backgroundColor="yellow";//when i print tu and inspect style is visible on body
tu.getElementsByTagName("body")[0].style.width="100px";
getComputedStyles(tu)//returns all empty values.
document=tu;
But every step return without an error but after assigning tu to document my body bgColor is still white.
one more thing why getComputedStyles() are returning empty values?

Finally i got something which might be usefull
var documentClone=document.clone(true);
documentClone.body.style.background="yellow";
documentClone.body.style.background="red";`\\many number of operations`
//after many changes
document.replaceChild(documentClone.documentElement,document.documentElement);
//now you can find all your changes..

window.document is not writeable.

Related

Change Spotfire Document Properties value using javascript

I want to Change the value assigned to a Document Property in spot fire. Lets say i have created a new document property called "Test1" as a string and assign it a value "a". Is there are way to change this value using Javascript every time i load the spotfire dashboard ?
I'm unaware of a way to use JavaScript for this, but you can assign a string document property via custom expression (if it's a List Box) or run an IronPython script each time the value changes. So, you could set the expression to the current date, datetimenow() and then every time it's loaded the IronPython script would fire. However, I don't see why you'd need the property control for this.
I suppose it really depends on what you want the document property to be set to. Is it data from your tables? Output from complex code? These are all things to consider.
1) Create an input type property control using the Document Property you want to change.
2) Edit Html to assign parent element an id say "testInput". And add the script as shown below in the Edit HTML window.
<span id="testInput"><SpotfireControl id="7db34e6c423240f59fc99e6b80fa23ec" /></span>
<script>
$("#testInput input").val("after");
$("#testInput input").focus();
$("#testInput input").blur();
</script>
3) This script will change the document property value to "after" whenever you open a file.
As you comment seemed to suggest, something you can do is write this code in Python and attach the script to an action control, e.i. a Link or a Button. Something simple like: Document.Properties["Test1"] = newValue
or even: Document.Properties[changingProperty] = newValue
allowing the code to be more reusable.
Then you insert Javascript into the Text Area as well to the effect of: $("#VeryLongSpotfireControlID").click();
Which should simulate clicking on action control, which in turn triggers the Python script to update the value. Just be careful not to use this approach when it would result in reloading the text area HTML, as this will re-trigger the Javascript, thus creating an endless loop.
I believe I have found a possible solution/work-around for the issue, entirely based on pure JavaScript (since TIBCO removed jQuery starting from Spotfire X). The solution is to force a simulated Enter Keystroke while focusing the input box to trigger updating the Document Property. (No data function and R needed)
HTML (SpotfireControl Element is an single line input-box for a Doc. Prop.):
<div id="container"><SpotfireControl id="b8534f13dc62416db6d4eaab16030f5e" /></div>
JS (focus and blur might no longer be needed for this solution, but I'm still keeping them just in case):
const inputConfirmationEvent = new KeyboardEvent("keypress", {
    keyCode: 13,
    bubbles: true,
    cancelable: false
});
var elem = document.querySelector("#container input");
elem.value = "stringValue";
elem.blur();
elem.focus();
document.querySelector("#container input").dispatchEvent(inputConfirmationEvent);
Hope it helps someone.
Best,
Aaron

Jquery, cannot access css properties of dynamically generated element

I am using jQuery to append elements to a div, and all works fine.
var new_div = $('<div>My stuff</div>');
new_div.appendTo("#container");
However, I'd like the div to appear by fading in, instead of abruptly.
I notice though that I get an error when I try to access graphic properties on my dynamically generated element. So this, for example fails:
new_div.hide().fadeIn();
The console reports the following error:
TypeError: jQuery.curCSS is not a function
Do I understand this correctly, that this fails because current css properties are not defined for the dynamically generated element? Or what else can be goingg wrong?
Important edit
Additional checking and working on this pointed out to a complete misunderstanding from my part. This has nothing to do with the fact that the element was dynamically generated. I got the same thing by calling fadeIn() on whatever element.
I sincerely apologize!
I still didn't get, though, why this happens
Adding elements to the DOM takes some time, miliseconds maybe, but it's still a reason for jquery not be able to find the element.
This process might be even slower if the DOM is a large html page.
Write your code like this:
var new_div = $('<div>My stuff</div>');
new_div.appendTo("#container");
setTimeout( function(){
new_div.hide().fadeIn();
} , 150); // 100 could be also good
It might be enough time for jquery to catch the element.
I would add an id to keep track of all elements I'm creating (just my preference, but it makes it easier to code it).
var new_div = '<div id="myNewDiv1" style="display:none;">My Styff</div>'
$('body').append(new_div);
$('#myNewDiv1').fadeIn();
It does seem to be a compatibility question, although I wasn't able to figure out exactly why and how to fix it.
Adding this code fixes the problem though:
jQuery.curCSS = function(element, prop, val) {
return jQuery(element).css(prop, val);
};

How to reset DOM after manipulation?

My page contains some small wizard which I built using jQuery.
I would like to offer the user to restart/reset the wizard and start it from the beginning level.
There is anyway to do it without refreshing the page?
One way to achieve this would be to clone() the wizard's element tree in its initial state and store it in a global variable or in the document's data:
$(document).data("initialWizard", $("#yourWizard").clone(true));
(Note that passing true to clone() also clones element data and event handlers, which might prove handy in your case.)
Then, when you want to restore the wizard to its original state, you can do:
$(document).data("initialWizard").replaceAll("#yourWizard");
The only way to start over without refreshing the page is for you to manually return the DOM to the state it was in when the page loaded and to restore any javascript state too. You would either have to record/remember the initial state so you could go back to it or keep track of all your incremental changes so you could go back there too.
If you really want to start over, what's wrong with a refresh?
Similar to the above, here's what I ended up doing. I stored the entire jQuery doc contents in a bootup() function (and ran it). The initial contents of the body was stored in an originalDOM variable. Then within I had a playAgain function that would set the contents of the body to that originalDOM, and run the entire jQuery contents again by calling the bootup() function. This would all be triggered by clicking on a button of class ".startover".
bootup();
var bootup = function(){$(document).ready(function(){
var originalDOM=document.body.innerHTML;
//jQuery lines of code here
var playAgain = function(){
$(".startover").click(function(){
document.body.innerHTML = originalDOM;
bootup();
});
};
playAgain();
});};
Hope that helps for anyone looking for something similar, and happy to hear feedback if there's anything I could've improved on!

javascript innerHTML without childNodes?

im having a firefox issue where i dont see the wood for the trees
using ajax i get html source from a php script
this html code contains a tag and within the tbody some more tr/td's
now i want to append this tbody plaincode to an existing table. but there is one more condition: the table is part of a form and thus contains checkboxe's and drop down's. if i would use table.innerHTML += content; firefox reloads the table and reset's all elements within it which isnt very userfriendly as id like to have
what i have is this
// content equals transport.responseText from ajax request
function appendToTable(content){
var wrapper = document.createElement('table');
wrapper.innerHTML = content;
wrapper.setAttribute('id', 'wrappid');
wrapper.style.display = 'none';
document.body.appendChild(wrapper);
// get the parsed element - well it should be
wrapper = document.getElementById('wrappid');
// the destination table
table = document.getElementById('tableid');
// firebug prints a table element - seems right
console.log(wrapper);
// firebug prints the content ive inserted - seems right
console.log(wrapper.innerHTML);
var i = 0;
// childNodes is iterated 2 times, both are textnode's
// the second one seems to be a simple '\n'
for(i=0;i<wrapper.childNodes.length;i++){
// firebug prints 'undefined' - wth!??
console.log(wrapper.childNodes[i].innerHTML);
// firebug prints a textnode element - <TextNode textContent=" ">
console.log(wrapper.childNodes[i]);
table.appendChild(wrapper.childNodes[i]);
}
// WEIRD: firebug has no problems showing the 'wrappid' table and its contents in the html view - which seems there are the elements i want and not textelements
}
either this is so trivial that i dont see the problem OR
its a corner case and i hope someone here has that much of expirience to give an advice on this - anyone can imagine why i get textnodes and not the finally parsed dom elements i expect?
btw: btw i cant give a full example cause i cant write a smaller non working piece of code
its one of those bugs that occure in the wild and not in my testset
thx all
You are probably running into a Firefox quirk of following the W3C spec. In the spec the whitespace between tags are "text" nodes instead of elements. These TextNodes are returned in childNodes. This other answer describes a workaround. Also Using something like JQuery makes this much easier.
I would expect this behavior in any browser as the += operand overwrites what is already in the table by definition. Two solutions:
Instead of receiving HTML code from your PHP file, have the PHP generate a list of items to add to the table. Comma/tab separated, whatever. Then use Table.addRow(), Row.addCell() and cell.innerHTML to add the items to the table. This is the way I would suggest doing it, no point in creating GUI elements in two separate files.
The other solution is to save all the form data that's already been entered to local JavaScript variables, append the table, and then reload the data into the form fields.
Well, returning a JSON object with the new data seems like the best option. Then, you can synthesize the extra table elements by using it.
In case one is forced to get plain HTML as response, it is possible to use var foo = document.createElement('div');, for example, and then do foo.innerHTML = responseText;. This creates an element that is not appended to anything, yet hosts the parsed HTML response.
Then, you can drill down the foo element, get the elements that you need and append them to the table in a DOM-friendly fashion.
Edit:
Well, I think I see your point now.
wrapper is a table element itself. The nodes reside under the tbody, a child of wrapper which is its lastChild (or you can access it via its tBodies[0] member, in Firefox).
Then, using the tBody element, I think that you would be able to get what you want.
BTW, You do not need to append the wrapper to the document before appending its children to the table, so no need to hide it etc.

Accessing created DOM elements

I have code to create another "row" (div with inputs) on a button click. I am creating new input elements and everything works fine, however, I can't find a way to access these new elements.
Example: I have input element (name_1 below). Then I create another input element (name_2 below), by using the javascript's createElement function.
<input type='text' id='name_1' name="name_1" />
<input type='text' id='name_2' name="name_2" />
Again, I create the element fine, but I want to be able to access the value of name_2 after it has been created and modified by the user. Example: document.getElementById('name_2');
This doesn't work. How do I make the DOM recognize the new element? Is it possible?
My code sample (utilizing jQuery):
function addName(){
var parentDiv = document.createElement("div");
$(parentDiv).attr( "id", "lp_" + id );
var col1 = document.createElement("div");
var input1 = $( 'input[name="lp_name_1"]').clone(true);
$(input1).attr( "name", "lp_name_" + id );
$(col1).attr( "class", "span-4" );
$(col1).append( input1 );
$(parentDiv).append( col1 );
$('#main_div').append(parentDiv);
}
I have used both jQuery and JavaScript selectors. Example: $('#lp_2').html() returns null. So does document.getElementById('lp_2');
You have to create the element AND add it to the DOM using functions such as appendChild. See here for details.
My guess is that you called createElement() but never added it to your DOM hierarchy.
If it's properly added to the dom tree you will be able to query it with document.getElementById. However browser bugs may cause troubles, so use a JavaScript toolkit like jQuery that works around browser bugs.
var input1 = $( 'input[name="lp_name_1"]').clone(true);
The code you have posted does not indicate any element with that name attribute. Immediately before this part, you create an element with an id attribute that is similar, but you would use $("#lp_1") to select that, and even that will fail to work until you insert it into the document, which you do not do until afterwards.
var input1 = $( 'input[name="lp_name_1"]').clone(true);
should be
var input1 = $( 'input[#name="lp_name_1"]').clone(true);
Try that first, check that input1 actually returns something (maybe a debug statement of a sort), to make sure that's not the problem.
Edit: just been told that this is only true for older versions of JQuery, so please disregard my advice.
Thank you so much for your answers. After walking away and coming back to my code, I noticed that I had made a mistake. I had two functions which added the line in different ways. I was "100% sure" that I was calling the right one (the code example I posted), but alas, I was not.
For those also experiencing problems, I would say all the answers I received are a great start and I had used them for debugging, they will ensure the correctness of your code.
My code example was 100% correct for what I was needing, I just needed to call it. (Duh!)
Thanks again for all your help,
-Jamie

Categories