Changing an elements ID using Javascript - javascript

I'm trying to change the id 'character' to 'characterSelected'
var character = document.getElementById('character');
var characterSelected = document.getElementById('characterSelected');
function klik() {
character.innerHTML = characterSelected;
}
character.addEventListener('click', klik);
This is what I have so far but it doensn't seem to work. I want to do this using Javascript only, no jQuery.
Thanks

You tried something, it didn't work. Now is the time to look up the standard properties and functions you're using incorrectly. If guessing doesn't work, always look for reliable documentation.
A good reference would be the Mozilla Developer Network (MDN). It's a wiki-style encyclopedia about the web, its standards and current browser compatibility. If you look at the page about innerHTML, you'll find the following:
The Element.innerHTML property sets or gets the HTML syntax describing
the element's descendants.
This means that the innerHTML property is used to replace the content of a tag as if you wrote that HTML inside it. Not what you want.
What you wanted was to change the id of an element. If you search for element id, you'll land on the Element.id page. And how practical, there's an example:
var idStr = elt.id; // Get the id.
elt.id = idStr; // Set the id
However, this is not going to fix your issues. You see, you guessed wrong when trying to use the getElementById function. This function looks at the page and finds the element with that id right now. If you don't have any element with the characterSelected id at first, then this variable you set is going to be null for the rest of time. Variables won't magically update when an element with that id is placed in the page.
And finally, you have missed the purpose of the id attribute itself.
Its purpose is to identify the element when linking (using a fragment
identifier), scripting, or styling (with CSS).
The purpose of an id is to identify an element uniquely. You might think: "that's what I'm doing". No. You're using an id to represent whether or not an element is selected. This is wrong. Depending on your objective, I would say: just store the selected element inside a variable. Then whenever you need to do something with the selected element, it's in that variable. If you need specific style for that element, then you could set a class to it. But the id isn't meant for this at all - in fact, an id isn't meant to change once an element is placed.

Related

How to use insertBefore on a element inside a iframe by a data-attribute

i have a iframe inside my page and i want to move a element by select the destination with a "data-attribute", so i trie to do this:
var ifr=frames['myiframeID'].document;
var element='#idofdiv';
var destination='value_for_my_attribute';
I trie it in this way
$(element,ifr).insertBefore('[data-my-attribute="'+destination+'"]');
and in this way
$(element,ifr).insertBefore('[data-my-attribute="'+destination+'"]', ifr);
Both way failes, nothing happens.
What i do wrong?
Update
I check this:
console.log('check',$(element,ifr), $('[data-my-attribute="'+destination+'"]', ifra));
Both will return the object.
Note: As you say you do satisfy the Same origin policy so in theory you should be able to access and manipulate subordinate IFRAME DOM.
The reason why it won't work is the way selectors work. If both elements are supposed to be within a different frame than where the code is running, then they both need to be selected providing their parent frame. Your code doesn't. Only the element being inserted is correctly selected, but the selector of the target data attributed reference element isn't.
$(element, ifr).insertBefore('[data-my-attribute="'+destination+'"]');
// ^ correct ^ incorrect
As per jQuery documentation, you can't simply add parent element to the insertBefore function call.
This should therefore work:
var el = $(element, ifr);
var ref = $('[data-my-attribute="'+destination+'"]', ifr);
el.insertBefore(ref);
// or
ref.before(el);
This should work as expected.

Why "document.title" and NOT "document.head.title"? RE: Traversing the DOM

I am just beginning to learn client-side JavaScript and using an online tutorial, so please bear with me.
This question is based on my understanding of the following:
To access the properties of the document's body, the syntax is "document.body", which returns all the elements in the body.
Similarly when you access the head, you use "document.head". Makes sense and most importantly, it works.
However, when I attempt to access elements WITHIN the body or head following the same logic, I get a return value of "undefined". For example, document.body.h1, returns "undefined", in spite of there being an h1 element inside the body element.
Further, when I enter document.head.title -- "undefined".
Strangely, however, when I enter "document.title", it returns the string value associated with the title tag.
I thought in order to access the title, you would have to access it through the head, since it is an element nested inside the head. But ok, that's fine. Using the same logic, I should then be able to enter document.h1 and get its value. Nope, instead, I get undefined.
Would someone be kind enough to explain to me why this behavior is so inconsistent. Thanks in advance.
You've really asked two questions:
Why document.title rather than document.head.title?
and
Why doesn't document.body.h1 return an element if there's an h1 in the body?
document.title
document.title is historical. Various parts of the browser environment were developed somewhat ad hoc by multiple different people/organizations in the 1990s. :-) That said, it's the title of the document, so this isn't an unreasonable place to put it, even if you use the title tag in head.
document.body.h1
One answer is: Because no one decided to design it that way. There were some early things like document.all (a list of all elements in the document) and even tag-specific ones (I forget exactly what they were, but they weren't a million miles off your document.body.h1 — I think document.tags.h1 or something, where again it was a list.)
But another answer is: Because the DOM is a tree. body can have multiple h1 elements, both as direct children and as children of children (or deeper); collectively, descendants. Creating automatic lists with all of these proved not to be scalable to large documents.
Instead, you can query the DOM (either the entire document, or just the contents of a specific element) via a variety of methods:
getElementById - (Just on document) Get an element using its id attribute value.
querySelector - Find the first element matching a CSS selector (can use it on document or on an element). Returns null if there were no matches.
querySelectorAll - Get a list of all elements matching a CSS selector (can use it on document or on an element). You can rely on getting back a list; its length may be 0, of course.
getElementsByTagName - Get a list of all elements with a given tag name (such as "h1").
getElementsByClassName - (No support in IE8 and earlier) Get a list of all elements with a given class.
There are many more. See MDN's web documentation and/or the WHAT-WG DOM Standard for more.
Some of the automatic lists persist (they got so much use that they had to be maintained/kept), such as document.forms, document.links, the rows property on HTMLTableElement and HTMLTableSectionElement instances, the cells property on HTMLTableRowElement instances, and various others.
document.head.title is a thing... but not what you might think.
title is an attribute that is applicable to all html elements; that is, it is a global attribute. It's meaning is 'advisory information'; one use is to display a tooltip:
<span title="hover over me and you'll see this">information</span>
So, all elements have a title attribute - including head. The title element - which is completely different - should be a child of the head though. So you might be tempted to set its value via document.head.title = "my title" , but document.head.title is not the head's title element, it's a property of the head element.
What you're actually doing is setting the title property on the head element:
<head title="my title">.... </head>
... which isn't what you want at all.
The correct way to set the title is document.title, which is a shortcut way of doing
document.querySelector("title").innerText = "my title"

How do I access the value of a textarea with javascript?

In one javascript function I am creating a textarea based on some JSON data I am grabbing from another site. I create the textarea here:
if(type == 'fill-in'){
var textField = $('<center><div id="response-text"><textarea id="test" name="test" rows="10" cols="80">Answer here</textarea></div></center>').appendTo(panel.root);
}
In another function, I need to grab the value of this textfield and send it off to another site. I have tried this in various ways using
document.getElementById("test").value
But that gives me an error, and if I use
document.getElementByName("test").value
It tells me that the value is undefined. Do text areas not automatically set their values to whatever you type into them? Is there a better way to grab what is being typed into the textarea?
EDIT:
getElementById is working now... not sure what I was doing before but I must have tried it 3-4 times. I apologize for the pointless question.
Here's my best guess as to what's actually going on in your code and why you may be getting screwed over by variable hoisting.
I imagine you're trying to dynamically add your text area and then grab a reference right after by using var test = document.getElementById("test");. Because of variable hoisting, declared variables are hoisted to the top of the current scope. This would result in the declaration happening before the text area gets added.
As it is unclear where the problem lies with the OP, I did notice that you're using getElementsByName incorrectly.
getElementByName should be getElementsByName. A subtle but significant difference. Since names do not need to be unique, the function gathers a node list of all DOM elements with a given name attribute.
getElementById on the other hand returns a reference to the element itself.
getElementsByName:
Returns a list of elements with a given name in the HTML document.
getElementById:
Returns a reference to the element by its ID.
Using getElementById works just fine. You must have something wrong with your HTML markup - perhaps another element with the id of test.
Working fiddle:
I am assuming that Teaxarea element is loaded successfully and present in the DOM. In that case, your javascript is loading & executing even before Textarea element is loaded & ready in the DOM.
Regards,

javascript find node without id

Due to a limitation of the Javascript library I'm using, I can't assign an id to a <div>. Unfortunately, I don't know how to attach a Tooltip object from Tipped, a Javascript tooltip library, to the element without an id. I don't know if this is possible, but I'm trying to find the object via other means which will hopefully allow me to modify the id.
The element I'm looking for is a button on a toolbar, but it's not an HTML button. It's a <div> that has CSS styles and Javascript events assigned to make it look and feel like a button. I know the class name of the parent and I know the id of the grandparent <div>, but that's as much as I know. Part of the issue is that there doesn't seem to be a good reference for how to iteratively operate on HTML objects once you get a reference to them. I've seen plenty of examples like this:
var x = document.getElementsById("asdf")
but no follow-up code showing how to actually do anything. What's in x? What methods does it have? I know of innerHTML and innerTEXT, but I can't figure out if they apply to x, a child of x, or ???. The Chrome console has helped a little bit, but I'm basically lost.
This is the relevant code for my button:
As you can see, there is no id on the Export button, but the parent has a class name and the grandparent has an id. The other snag is that the grandparent's id isn't static. It always starts with "dhxtoolbar" and there is only one toolbar on the page, but I haven't been able to make a regex search find the toolbar.
Ultimately, I'd like to be able to attach a Tipped tooltip to the Export button. I think Tipped requires an id, but maybe it doesn't. Regardless, I'd like to understand more about how to iterate through the DOM and, as a bonus, figure out how or if I can change the id of an element on a live page. Thanks.
Tipped actually accepts any CSS selector as an argument. If the class is unique, you could target it that way:
Tipped.create('.dhx_toolbar_btn', 'some tooltip text');
Or if the class isn't unique, you could try target it via the tree structure. Made up example:
Tipped.create('.header .sidebar .dhx_toolbar_btn', 'some tooltip text');
I noticed in your html that the buttons have empty title attributes (or maybe your inspector just added them). If you can set the title attribute for the buttons Tipped will pick it up automatically. Example:
<div class="dhx_toolbar_btn" title="test title">
You would then only have to use:
Tipped.create('.dhx_toolbar_btn');
And Tipped will automatically pick up the title and use it.
This is what I was trying to have explained:
var Obj = document.getElementsByClassName("classname");
var ObjChildren = Obj[0].getElementsByTagName("tag")
var searchText = "string";
for (var i = 0; i < ObjChildren.length; i < i++) {
if (ObjChildren[i].innerHTML == searchText) {
console.log(ObjChildren[i].innerHTML);
}
}

What information about a DOM element would allow JavaScript to identify it (somewhat) uniquely? (e.g. when it doesn't have `id`)

Here's what I'm trying to do: I have a bookmarklet that is looking for elements in the current page (which can be any site) and dispatch a click event on the ones that match. I have that part working.
In some cases though, nothing matches automatically and I want to be able to show (by hovering it) what element should be activated and then save some info about it in localStorage. The next time I'm using the bookmarklet on that page, I want to retrieve that info to identify the element in the DOM and then dispatch a click event.
The question is: what information should I save to be able to identify it? (in most cases, since it will always be possible to create a case where it doesn't work)
In the best case, said-element will have an id value and I'm good to go. In some other cases, it won't and I'd like to see your suggestions as to what info and what method I should use to get it back.
So far my idea is to save some of the element's properties and traverse the DOM to find elements that match everything. Not all properties will work (e.g. clientWidth will depend on the size of the browser) and not all types of elements will have all properties (e.g. a div node won't have a src value), which means that on one hand, I can't blindly save all properties, but on the other, I need to either choose a limited list of properties that will work for any kinds of element (at the risk of losing some useful info) or have different cases for different elements (which doesn't sound super great).
Things I was thinking I could use:
id of course
className, tagName would help, though className is likely to not be a clear match in some cases
innerHTML should work in a lot of cases if the content is text
src should work in most cases if the content is an image
the hierarchy of ancestors (but that can get messy)
...?
So, my question is a bit "how would you go about this?", not necessarily code.
Thanks!
You could do what #brendan said. You can also make up a jQuery-style selector string for each element in the DOM by figuring out the element's "index" in terms of its place in its parent's list of child nodes, and then building that up by walking up the DOM to the body tag.
What you'd end up with is something that looks like
body > :nth-child(3) > :nth-child(0) > :nth-child(4)
Of course if the DOM changes that won't work so good. You could add class names etc, but as you said yourself things like this are inherently fragile if you don't have a good "id" to start with, one that's put there at page creation time by whatever logic knows what's supposed to be in the page in the first place.
an approach would be using name, tagName and className-combination. innerHTML could may be too big.
another approach would be to look for child elements of your choosen element which have an id.
check for id => check for childs with id => check for name, tagName and className-combination (if => tell user to choose a different item :-)
What about finding all elements without an ID and assigning them a unique id. Then you could always use id.
What about using the index (integer) of the element within the DOM? You could loop through every element on page load and set a custom attribute to the index...
var els = document.getElementsByTagName("*");
for(var i = 0, l = els.length; i < l; i++) {
els[i].customIndex = i;
}

Categories