i want to achieve some feature like this:
var el = document.createElement("iframe");
el.setAttribute('id', 'ifrm');
document.body.appendChild(el);
el.setAttribute('src', 'http://www.example.com');
and if "ifrm" exists, jt won't create new iframe. if it doesn't exist, it will create that frame. i want to do this to avoid duplicate frame creation when user keeps click on the same button to generate frame. is there a way to check whether a specific iframe exists? thanks
You can check with getElementById('ifrm') whether or not the frame with that id already exists. If not, create it. Like so:
if(!document.getElementById("ifrm"))
// Create the damn thing
If you wish to check if there is any iframe at all, you could use getElementsByTagName('iframe').
To make live a little easier, you can take a look at jQuery. This is a Javascript library that helps you to create DOM objects and/or find them in the DOM tree.
if(document.getElementById("ifrm"))
//then it exists
else
//it doesn't exist yet
Related
Please bear with me; Im very new to JS- as in barely started a beginners course.
I know this is possible in html, but I want to know if its doable in js.
var a = document.createElement('a');
const link = document.querySelector(`.logoImg`);
a.href(link) = `https://website.com`;
Sorry if this is infuriatingly simple but I can't seem to see where i'm going wrong, thanks in advance!
EDIT: .logoImg is a class that already exists, that I want to add the link to.
var a = document.createElement('a'); gives you an element (a brand new <a> that isn't attached to the DOM yet).
const link = document.querySelector(`.logoImg`); also gives you an element (assuming that the selector matched something in the document) which is already in the DOM.
Now you have two variables pointing to two different elements.
You probably only want one of those two lines. Which one depends on which of the elements you want to modify.
a.href(link) is nonsense. It takes the href of the newly created element (off the top of my head I can't remember if it is undefined or '' by default) and tries to execute it as a function (passing link as an argument). Neither undefined nor '' is a function so this will error.
You need a.href = or link.href = depending on which element you want modify the href property of.
Things get more complicated if the element with class="logoImg" isn't a <a> but something else that you want to put inside a new <a>.
I am trying to fill a textarea in a window opened with open(link_here) (on the same domain). It works fine in all browsers except IE/Edge.
Steps to reproduce here on stackoverflow:
var w = open('https://stackoverflow.com'); // example
// (allow popups and) wait for window to be opened, then:
let input = w.document.getElementsByClassName('f-input js-search-field')[0]
const prototype = Object.getPrototypeOf(input); // returns null on IE/Edge
Any workaround?
Thanks
I believe it is a Hierarchy access restriction. Since the element is not in the same window as the Object you are using, it doesn't have access to the object's information. You will have a somewhat similar problem if you try to append an element created by the main document and try to append it to the iframe document. When attempting this you will get a HierarchyRequestError.
Instead of using the main window's Object use the iframe window's Object:
var prototype = w.window.Object.getPrototypeOf(input);
console.log(prototype);
instead of vanilla javascript try JQUERY which works on every browser correct so change your selector to jquery one you need to include first JQUERY at your file
I'm trying to detect if an element with a specific tag name has been inserted into the document. I am aware of DOMSubtreeModified and MutationObserver and I know that they can detect changes in the elements, but if the document is big and many changes are applied to the document, these two methods can become quite heavy.
One of the ideas I had was to collect all elements using getElementsByTagName and then detect a change of HTMLCollection's length property but I didn't find any method that could watch this property and trigger an event.
Another idea I had was to set an interval, but the problem with this is that an item can be deleted and inserted in between the timer and this wouldn't be detected in the interval's function.
Is there any efficient way of detecting new element insertion in the whole document? Alternatively, how can I detect change of HTMLCollection's length property?
Thanks for any answer.
Here is a thought:
var cnt=0;
var f = Element.prototype.appendChild;
Element.prototype.appendChild = function(){
f.apply(this, arguments);
console.log("added",++cnt)
};
However you will need to see if it is the same element that is added and I have not figured out how to check the remove since that is parentNode.removeChild
If you want events on all selects in jQuery all you have to do is delegate
$(document).on("change","select",function() {
// all current and future selects will have this event
});
I'm creating a chrome extension that hides a jQuery element on the page when clicked.
I need to store a reference to this element in the chrome.storage API, so when the page is loaded at a later date I can have that element hidden again.
I know the DOM tree is rebuilt on page load, and I'm not sure if this will effect anything. The element could be anything on the page as well, so not necessarily having a class/id name.
What is the best way to go about storing the reference? I'm all out of ideas on how to do this (brand new to JavaScript).
Update
As suggested by Xan, I am now using xPath to store a reference to the element.
//Get the element
var elem = e.target || e.srcElement;
$(elem).click(function () {
xPathOfElem = getElementXPath(elem); //Get xPath of element
updateStorage(xPathOfElem);
$(elem).hide("");
return false;
});
//Store it
function updateStorage(xPathOfElem) {
chrome.storage.sync.set({"element":xPathOfElem} //set xPath to storage
, function (data) {});
};
//Retrieve it on load later
function getStorage() {
chrome.storage.sync.get(null, function (data) {
$(getElementsByXPath(document, data.element)).hide(""); //get and hide element
});
}
window.onload = function () {
getStorage();
};
As Xan mentioned, not a perfect approach if the page isn't static but it does what I need it to
This is a very broad question and the reason is: in general, there is no way you can reliably pinpoint an element on a page, especially if it's dynamic.
There is no "single" solution that works for every page. However, assuming that you can devise a method of pinpointing an element, you should look into DOM XPath.
It's a rich way of describing how to find an element, much more general than class/id name. And it's just a string, so it can easily be stored. Once you have this description, you can find the element using document.evaluate.
The downside is, there is no such thing as "the XPath" of an element. You need to come up with your own method of constructing one for a given element, and like I said to do so automatically is nigh-impossible. You're certainly welcome to try an cover many common cases, but finding a universal solution is hopeless.
P.S. See this question for finding "an XPath" of an element. Again, would only work reliably in a static page.
I'm trying to write a Firefox extension that adds elements to the loaded page. So far, I get the root element of the document via
var domBody = content.document.getElementsByTagName("BODY").item(0);
and create the new elements via
var newDiv = content.document.createElement("div");
and everything worked quite well, actually. But the problems came when I added a button with on onclick attribute. While the button is correctly displayed, I get an error. I already asked asked here, and the answer with document.createElement() (without content) works.
But if I remove the 'content.' everywhere, the real trouble starts. Firstly, domBody is null/undefined, no matter how I try to access it, e.g. document.body (And actually I add all elements _after_the document is fully loaded. At least I think so). And secondly, all other elements look differently. It's seem the style information, e.g., element.style.width="300px" are no longer considered.
In short, with 'content.document' everything looks good, but the button.onclick throws an error. with only 'document' the button works, but the elements are no longer correctly displayed. Does anybody see a solution for that.
It should work fine if you use addEventListener [MDN] (at least this is what I used). I read somewhere (I will search for it) that you cannot attach event listener via properties when creating elements in chrome code.
You still should use content.document.createElement though:
Page = function(...) {
...
};
Page.prototype = {
...
addButton : function() {
var b = content.document.createElement('button');
b.addEventListener('click', function() {
alert('OnClick');
}, false);
},
...
};
I would store a reference to content.document somewhere btw.
The existing answer doesn't have a real explanation and there are too many comments already, so I'll add another answer. When you access the content document then you are not accessing it directly - for security reasons you access it through a wrapper that exposes only actual DOM methods/properties and hides anything that the page's JavaScript might have added. This has the side-effect that properties like onclick won't work (this is actually the first point in the list of limitations of XPCNativeWrapper). You should use addEventListener instead. This has the additional advantage that more than one event listener can coexist, e.g. the web page won't remove your event listener by setting onclick itself.
Side-note: your script executes in the browser window, so document is the XUL document containing the browser's user interface. There is no <body> element because XUL documents don't have one. And adding a button won't affect the page in the selected tab, only mess up the browser's user interface. The global variable content refers to the window object of the currently selected tab so that's your entry point if you want to work with it.