I main php page in which there are 2 frames. Inside the second frame there is iframe.
I want to access value of element on iframe document from the 1st frame.
I tried like this:
var frame1 = parent.frames[1];
var frame2 = frame1.document.getElementsByTagName('iframe')[0];
var eleValue =frame2.contentWindow.document.getElementById("MyElement").value;
but I am not receiving any value though it is there.
var frame1 = parent.frames[1];
alert(frame1.name);
var frame2 = frame1.document.getElementsByTagName('iframe')[0];
alert(frame2.name);
var txtClinic = frame1.document.getElementsByTagName('iframe')[0].contentDocument.getElementById("clinicFlag");
last line of code doesnot return any control object.
Here's a modified snippet of my answer linked in a comment. Function returns the window object of an (i)frame with id passed (id), or null, if the (i)frame is not found. This method works only, if all the (i)frames are in the same domain. Also ids given to (i)frame elements must be unique throughout all documents involved in the window structure.
function searchFrame(id) { // id = the id of the wanted (i)frame
var result = null, // Stores the result
search = function (iframes) { // Recursively called function
var n; // General loop counter
for (n = 0; n < iframes.length; n++) { // Iterate through all passed windows in (i)frames
if (iframes[n].frameElement.id === id) { // Check the id of the (i)frame
result = iframes[n]; // If found the wanted id, store the window to result
}
if (!result && iframes[n].frames.length > 0) { // Check if result not found and current window has (i)frames
search(iframes[n].frames); // Call search again, pass the windows in current window
}
}
};
search(window.top.frames); // Start searching from the topmost window
return result; // Returns the wanted window if found, null otherwise
}
This function can find a frame or iframe with the passed id regardless where it is placed in the window structure. Also the function can be placed and called in any window. I'd put this to the main page (as global). If the method is needed in subwindows, just call with top.searchFrame(...).
Instead of ids, also names can be used, as long as they are also unique. In that case the id check in searchFrame() needs to be edited to name check.
In your case, first you need to give an id to the target iframe, then you can use the code for example like this:
var txtClinic = searchFrame('IFRAME_ID').document.getElementById('clinicFlag');
The method above might be a bit overkilling to get a single reference, but it's very helpful, if you have to get these cross-window references multiple times within different windows.
The specific task of yours could be done like this:
var txtClinic = parent.frames[1].frames[0].document.getElementById('clinicFlag');
names of the (i)frame are also handy to use with frames collection. Instead indices you can use names. Just always chain the reference starting from the main page, i.e. from top. For example:
var iframeWin = top.frames['frame2'].frames['iframe1'];
Useful reading:
window.top
window.frameElement
window.frames
Related
The elements are created in a for loop. I have tried storing each element ID in an array but it and using it but its always set to the last value the for loop ran through. Tried solving this problem with closures and still nothing works.
Heres a function I have after for loop, with i being passed in each time. moreinfolink is an empty array initialised outside the for loop. idarr is another array with different values in, which I want to reference using the moreinfolink array. Essentially when each element is clicked, the id it has based on its position in the moreinfolink should be used to then get its relevant position in the idarr, which are passed on to another page. And that pages content is genered using an API, for which we need the correct id (found in the idarr). Hope Im making sense.
function passthrough (a){
moreinfolink[a] = document.createElement("a");
moreinfolink[a].id = a;
newmoreinfo.appendChild(moreinfolink[a]); /* element I created elsewhere */
moreinfolink[a].innerHTML = "ID position in array is " + moreinfolink[a].id;
moreinfolink[a].href = "respage.html";
moreinfolink[a].onclick = moreinfo(idarr, moreinfolink[a].id); }
Both the overall array of returned ids (idarr) and each links relevant reference id (moreinfolink[a]) is passed into this function below upon the click event. Problem is that the last id is always passed through, so no matter which link you click it always passes through the last id the loop ended with instead of the one that should be assigned to that particular element.
function moreinfo (relarr, val) {
var carryover = [];
carryover.push(val);
window.name = carryover;
console.log("carryover is " + carryover)}
The function below is called when the other page is opened.
function generateapage () {console.log(window.name);}
You can add query stirng to href:
moreinfolink[a].href = `/respage&id=${moreinfolink[a].id}`;
Then you can read it when other pages load:
let id = new URLSearchParams(window.location.search).get('id')
With the yrss library, I am loading a RSS feed into my HTML document. This works.
But then I want to access the divs from my JavaScript.
I can lookup the parent node (var test) and put it in the console. But when I want to get the number of child elements, it returns 0.
I'm using the following code:
var test = document.querySelector('#History_0');
console.log("test:");
console.log(test); //Returns <div class="item_trackHistory rss-feed" id="History_0">
console.log("test.childElementCount:");
console.log(test.childElementCount); //Returns 0
However, I can see the child elements I want to access in the inspector.
Why is it that I can see the children of the #History_0-div in Developer Tools, but the attribute childElementCount returns 0?
How can I access an element's children in JavaScript?
Sorry for making mistakes in the way I edited my question the first time.
here is the entire function call. I also entered the suggested solution from below. Unfortunately, it didn't work out.
code
for (var i = 0; i < obj.results.length ; i++ ){
var div = "History_" + i
getRSS(div ,obj.results[i].feedUrl, i);
}
code
this.getRSS = function(div, link, iteration){
$('#'+div+'').yrss(link,{
limit: 50,
dateformat: 'localedate',
tags:'true',
logging:'false'
});
var parent = document.querySelector('#History_'+iteration+'');
var childCount = 0;
if (parent !== null){
var childElements = parent.getElementsByClassName('entry-wrapper');
console.log(childElements);
console.log(childElements.item(0));
if(childElements !== null){
childCount = childElements.length;
console.log(childCount);
}
}
The console.log of ChildElements Returns a HTML Collection, which appears to have 20 entries. But console logging the ChildElement.item(0), it Returns a null.
The console log of childCount Returns 0.
Does anyone have an idea, how it is possible to access the childElements?
Where in my entire js-file should I call a function to Access the divs, that the yrss function creates?
Not the best question as others have pointed out, however, some simple things we can look at. I am unsure if the page loads the RSS feed after the page has loaded or not. I presume not, and will answer it presuming exactly that.
You can see my working code example here:
https://codepen.io/vincentritter/pen/vJmBrd?editors=1010
I've added notes too. Here is the snippet that should be the most important to get you started.
// Grab 'parent' div - History_0 or by class name 'rss-feed'
var parent = document.querySelector('.rss-feed');
var childCount = 0; // Just want to spit this out on the page so you can see.
// Check if parent isn't null
if(parent !== null){
// Get child elements by class name
var childElements = parent.getElementsByClassName('entry-wrapper');
// Check if child elements isn't null...
if(childElements !== null){
// Print results, just so we can look.
childCount = childElements.length;
console.log(childCount);
}
}
I used your images as reference.
To note, I grab stuff by their class name. Just find that easier. But everyone is different, whatever works for you.
That should get you going at least.
I have a javascript variable like below:
var treeNode= [{"id":"T1"},{"id":"T2","children":[{"id":"T3"},{"id":"T4"},{"id":"T5","children":[{"id":"T6"}, {"id":"T7"},{"id":"T8"}]},{"id":"T9"},{"id":"T10"}]},{"id":"T11"},{"id":"T12"}];
node t3,t4,t5,t6,t7,t8,t9,t10 are the child of node t2
i have a link of deactivate on each node.on click on deactivate link make active and delete link .mentioned in image.
now i want to make same active and delete link on all child node of parent node.
for example T3,T4,T5,T6,T7,T8,T9,T10 are the child of T2.
if i click on T5 then this will work on T6,T7,T8.
I tried below recursive code.may be my approach is not right.please advice.
var objTreeNode = eval(treeNode);
trav(objTreeNode);
function trav(TreeNodeObj){
var i=0;
for (i=0;i<TreeNodeObj.length;i++){
if(!TreeNodeObj[i].children){
if(objID==TreeNodeObj[i].id){ // will get T2 if click on deactivate link of Item T2
document.getElementById('span_'+TreeNodeObj[i].id).innerHTML = 'Activate <a href="javascript:deleteNode(\'' + objID
+'\');">Delete</a>';
}
}
else{
childObj = TreeNodeObj[i].children;
trav(childObj)
}
}
}
There are a few silly things in your code, let me fix them:
1. "Eval is evil!"
var treeNode= [{"id":"T1"},{"id":"T2","children":[{"id":"T3"}]}];
var objTreeNode = eval(treeNode);
trav(objTreeNode);
Why would you call eval()?
Let's see what MDN has to say about this:
Don't use eval! It's dangerous and slow. There are safe (and fast!) alternatives to eval() for common use-cases.
So what is your "use-case"? Why do you call eval here? What is the "better" solution? If you read the whole documentation on MDN you can read that:
If the argument of eval() is not a string, eval() returns the argument unchanged.
So unless treeNode is a string var objTreeNode = eval(treeNode); basically equals to var objTreeNode = treeNode;
You can drop that whole eval() line and just use treeNode. It's already an object.
2. camelCase
function trav(TreeNodeObj) {
This is not an error just a convention: In JavaScript (and also in most languages with C-like syntax) the parameters of a function are written with lower camel case (first letter is lowercase, and every other word's first letter is uppercase).
function trav(treeNodeObj) {
3. objID is undefined
There is no objID variable defined in your code. Although it is possible that you have a global defined elsewhere at the given time, it is much safer to introduce it as a parameter in your function.
function trav(treeNodeObj, objID) {
4. What your code does with what and when
Let me just figure out what your code currently does:
Iterates over a given object's children property (which is hopefully an array).
If an element has no children
Check if the array item has a desired ID property, and change it's innerHTML
Else
Call the function on the children
So what it does: Changes the element with the given ID if it has no children.
What you need is: Change the element with the given ID and also it's children.
I just modified your function like this:
function trav(treeNodeObj, objID, activate) {
var i = 0;
for (i = 0; i < treeNodeObj.length; i++) {
var childrenActive = false;
if (objID === treeNodeObj[i].id || activate) { // will get T2 if click on deactivate link of Item T2
childrenActive = true;
document.getElementById('span_' + treeNodeObj[i].id).innerHTML = 'Activate Delete';
}
if (treeNodeObj[i].children) {
childObj = treeNodeObj[i].children;
trav(childObj, objID, childrenActive);
}
}
}
Since you need to change all the child elements I needed to introduce a cut. This is the activate parameter. If the activate parameter is true you don't need to check the ID anymore you know that we are iterating over the subelements of the element with the given ID, and therefore change the element anyway.
Also you need to change the elements even if they have child nodes, so I restructured the if-s.
I have also made a jsfiddle for you to test: http://jsfiddle.net/JZ52g/3/
You can change the id parameter at the function call.
I am customizing Denis Gritcyuk's Popup date picker.
This pop-up script uses inline Javascript in a href link, to set the selected date into the input field, in the parent window, that is was called for. An example URL looks like:
<a href="javascript:window.opener.document.formname.field.value='03-10-2011';
window.close();">3</a>
The input field name, (e.g. document.formname.field), is passed to the script as a string parameter.
I would like to add things done when that link is clicked (e.g. change background color of field, set flag, etc.). So while this DOES work, it's getting ugly fast.
<a href="javascript:window.opener.document.formname.field.value='03-10-2011';
window.opener.document.formname.field.style.backgroundColor='#FFB6C1';
window.close();">3</a>
How would I move these inline commands into a JS function? This would give me much cleaner URLs and code. The URL would now look something like
3
with a function like (this example obviously does NOT work):
function updateField (str_target, str_datetime) {
var fieldName = "window.opener" + str_target;
[fieldName].value = str_datetime;
[fieldName].style.backgroundColor = '#FFB6C1';
// Set flag, etc.
window.close();
}
So any suggestions on how this can be done, please?
I'd prefer to hide the dom path tracing back from the current window back to the opener. It's appropriate to bake that into the function since the function will always be used in the context of that child popup. Then your function call is cleaner and more readable. Obviously, replace "myField" with the ID of the field you're intending to update.
3
function updateField ( str_date, str_fieldname ) {
var fieldToUpdate = document.getElementById( str_fieldname );
fieldToUpdate.value = str_date;
fieldToUpdate.style.backgroundColor = '#FFB6C1';
// Set flag, etc.
window.close();
}
You're acessing the property incorrectly. Try:
function updateField (str_target, str_datetime) {
var fieldName = window.opener;
str_target = str_target.split('.');
for (var i = 0; i < str_target.length; i++)
fieldName = fieldName[str_target[i]];
fieldName.value = str_datetime;
fieldName.style.backgroundColor = '#FFB6C1';
// Set flag, etc.
window.close();
}
The bracket notation ([]) is only used for properties of objects, not objects themselves. If you found my post helpful, please vote for it.
You can build a string and evaluate it as code using the eval function, but I would recommend against it.
There are a couple of things wrong with your code:
You cannot use the [] operator in a global context, you have to suffix it on an object, so you can say window["opener"] and this will be equivalent to window.opener, but there is no such thing as simply ["window"]
When navigating nested properties, as in window.opener.document you cannot navigate multiple levels using the [] operator. I.e. window["opener.document"] is not allowed. You must use window["opener"]["document"] instead.
A simple question I'm sure, but I can't figure it out.
I have some JSON returned from the server
while ($Row = mysql_fetch_array($params))
{
$jsondata[]= array('adc'=>$Row["adc"],
'adSNU'=>$Row["adSNU"],
'adname'=>$Row["adname"],
'adcl'=>$Row["adcl"],
'adt'=>$Row["adt"]);
};
echo json_encode(array("Ships" => $jsondata));
...which I use on the client side in an ajax call. It should be noted that the JSON is parsed into a globally declared object so to be available later, and that I've assumed that you know that I formated the ajax call properly...
if (ajaxRequest.readyState==4 && ajaxRequest.status==200 || ajaxRequest.status==0)
{
WShipsObject = JSON.parse(ajaxRequest.responseText);
var eeWShips = document.getElementById("eeWShipsContainer");
for (i=0;i<WShipsObject.Ships.length;i++)
{
newElement = WShipsObject.Ships;
newWShip = document.createElement("div");
newWShip.id = newElement[i].adSNU;
newWShip.class = newElement[i].adc;
eeWShips.appendChild(newWShip);
} // end for
}// If
You can see for example here that I've created HTML DIV elements inside a parent div with each new div having an id and a class. You will note also that I haven't used all the data returned in the object...
I use JQuery to handle the click on the object, and here is my problem, what I want to use is the id from the element to return another value, say for example adt value from the JSON at the same index. The trouble is that at the click event I no longer know the index because it is way after the element was created. ie I'm no longer in the forloop.
So how do I do this?
Here's what I tried, but I think I'm up the wrong tree... the .inArray() returns minus 1 in both test cases. Remember the object is globally available...
$(".wShip").click(function(){
var test1 = $.inArray(this.id, newElement.test);
var test2 = $.inArray(this.id, WShipsObject);
//alert(test1+"\n"+test2+"\n"+this.id);
});
For one you can simply use the ID attribute of the DIV to store a unique string, in your case it could be the index.
We do similar things in Google Closure / Javascript and if you wire up the event in the loop that you are creating the DIV in you can pass in a reference to the "current" object.
The later is the better / cleaner solution.
$(".wShip").click(function(){
var id = $(this).id;
var result;
WShipsObject.Ships.each(function(data) {
if(data.adSNU == id) {
result = data;
}
});
console.log(result);
}
I could not find a way of finding the index as asked, but I created a variation on the answer by Devraj.
In the solution I created a custom attribute called key into which I stored the index.
newWShip.key = i;
Later when I need the index back again I can use this.key inside the JQuery .click()method:
var key = this.key;
var adt = WShipsObject.Ships[key].adt;
You could argue that in fact I could store all the data into custom attributes, but I would argue that that would be unnecessary duplication of memory.