I have a DOM that is being set (in part) by a plugin at runtime so I don't have full control over it. The initial object that I create in my HTML is a <select> object to which the plugin bootstrap-select is creating a <button> as a sibling. This <button> in turn has a child <span> element (also created by the plugin). It is this <span> element whose text I want to change.
I also am changing the background color of the button itself, and this works. I just need to add a line or two to my function to update the text of the span, and I'm good to go.
Here is a screenshot of the relevant part of the DOM (the gray part is what I have to set):
And here is my code. This was written originally to set the background color of the button, and to that extent it works correctly. I just need to expand it to set the text, as well:
function setColorForSelect(elem, col) {
// this will change the background color of the <select> object just changed to match the selection
// this is necessary because bootstrap-select imposes a complex DOM structure on the <select> item
// (there is a <button> that is what is being displayed, so that is the object whose background color needs
// to be changed, not the <select> object itself)
$(elem).siblings().each(function() {
var _this = $(this);
if(_this.is(":button")){
_this.css('background-color', col);
$(this).children(":first").innerHTML = col; //<-- THIS IS THE LINE THAT DOESN'T WORK!
return false;
}
});
}
This isn't throwing any errors, but it isn't changing anything that I can see. How can I get a reference to this <span> so that I can change its text? Thank you!
Use this syntax.
Find the first span in the button and change its text.
$(this).find("span:eq(0)").text(col);
Or
Find the span by specific class and change its text.
$(this).find("span.filter-option").text(col);
There are couple of other methods too. I think those are already pointed out in other answers.
The reason there are no errors is because you just assigned the col value to an innerHTML property on a jQuery object.
Either use the html function jQuery provides for its object
.children(":first").html(col);
or use the text function jQuery provides
.children(":first").text(col);
or use the native JavaScript api by accessing the native element
.children(":first")[0].innerHTML = col;
or use the getter jQuery provides to get the native element and then use the native API
.children(":first").get(0).innerHTML = col
One more...
You could also do:
$('span:first',this).text(col); //
Hope it helps!
Related
I have a 'click' event on an image in javascript that I want to use to change the text content of the parent element when clicked. However, when I click it, the parent's text changes, but the image deletes itself. I assume I can just create and append a new child element after, but this doesn't seem to be the most efficient, and I would also like to understand why the child element gets deleted. My code looks like the following:
<body>
<ul>
<li> Hello <img src="img/hello.png"></li>
<ul>
<body>
<script>
const helloImage = document.querySelector('img')
helloImage.addEventListener('click', (e) => {
let parentEle = e.target.parentElement
parentEle.textContent = 'bye'
})
<script>
I have looked for a while for an answer, but can't seem to find anything with regards to modern javascript. I found one answer to a similar question with jQuery, but I got the same result when applying the solution's logic. Any help or if you can just point me in the right direction, I would really appreciate it. Thank you!
When you set textContent you overwrite all other child nodes.
From MDN:
Warning: Setting textContent on a node removes all of the node's children and replaces them with a single text node with the given string value.
The corresponding spec for the textContent setter says
String replace all with the given value within this.
If you only want to change the text then alter your HTML and wrap the text you want to change in a distinct element. Then reference that element's textContent in the click handler.
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);
}
}
I have a form that I am trying to alter with jQuery. Basically, my form has two elements and I need to change the value of the first option in each of them. However, there is an "add more" option that uses AJAX to dynamically generate another element that also needs changed. This add more button can be clicked an unlimited amount of times.
Right now I have this:
$(document).ready(function(){
$("#myname-0-field option:first").val("None");
$("#myname-1-field option:first").val("None");
});
This works fine, but once the "add more" button is clicked, I have more elements called "#myname-2-field", "#myname-3-field", "#myname-4-field" etc. These obviously aren't affected by adding another line into my jQuery as the document has already loaded when they are added.
So the real question is, can someone point me in the right direction of writing a function that can react when the new element is added and change it. If possible, I'm also looking for the function to be aware and look for "#myname-X-field option:first" for tidyness.
use live() function
Then using each function set value
From the jQuery API look live function
Maybe you could add class to your element, so that finding particular element would be easier and it would not add event to other similar elements.
In the example I have a Li with class
$('li.myClass').live('click', function() {
$(this).val(); // this is the getter for clicked value
$(this).val("some_value_here"); // this is the setter for clicked value
});
Now you can add more elements (that has myClass class) and it will have a click event.
Btw. if you know that all elements are inside some container (div for example) then you can write more efficient jQuery using delegate.
$('#container_id').delegate('li.myClass', 'click', function () {
});
This is more efficient because it looks your new elements only under "containter" not from the whole DOM structure.
I want to know the most effctive way to dynamically update, insert or remove elements from an html page.
The outcome of this is that, I can change an input element into a div element and vice versa based on a user action.
eg
<form><input type="text" value="Value to save"/></form>
and based on some event, i will change that to
<form><div>Value to Save</div></form>
Tx
I think you could do this task this way (pure JS, without using external frameworks):
//retrieve the <form>
var form = document.getElementsByTagName('form')[0];
//retrieve the <input> inside the form
var input = form.getElementsByTagName('input')[0];
//create a new <div> DOM element
var newElement = document.createElement('div');
//The containing div text is equal to the input value (your case)
newElement.innerHTML = input.value;
//simple empty the form by set innerHTML = ""
form.innerHTML = "";
//append the <div> inside the form
form.appendChild(newElement);
By the way, I sugges you, if you want to manipulate DOM and do stuff like these in an easier way, learn how to do it by using frameworks like jQuery or mootools ;)
This is a general description:
Creating: You can create elements with document.createElement and then use one the various insertion methods to the insert the element at a certain position (e.g. Node.appendChild). You need to get references to related nodes first.
Most browser also support the innerHTML attribute for elements. You can set that attribute to an HTML(or text) string and the content of the element will be updated accordingly.
Updating: It depends on which data you want to update. E.g. an input element has an attribute value. In order to change the value of a text input you need to get a reference to that element first, then you can do element.value = 'new value'. For content, you can use the already mentioned innerHTML attribute.
Have a look at an HTML element reference to see what attributes they have.
Deleting: You want Node.removeChild.
I suggest to also have a look at DOM traversal methods and be aware of browser differences.
Using:
element.removeChild
element.appendChild
By using these methods, you can retain references to the elements in case you want to swap them back over again. Any event handlers in place will remain attached to the elements, too.
This depends on your definition of most effective.
If you mean the simplest way, then you can use a library like jQuery and do it like this:
$('form').html('<dynamic markup>');
If you mean the most performant way you can do the following:
document.getElementByTagName('form').innerHTML = '<dynamic markup>';
I'm trying to change the border color of an image using its id with jquery
( photo['id'] is passed in from a previous function )
the ids of the photos are of the form 'photo239839'
$('#photo'+photo['id']+'').click(function(){
$('#photo'+photo['id']+'').css('border-color','#777');
});
When I try to use this same code using its class it works,
but I can't use this method since there are multiple images on the same
page with the same class
$('img.flickr_photo').click(function() {
$("this.flickr_photo").css('border-color','#777');
});
This is what you need to do:
$('img.flickr_photo').click(function(){
$(this).css('border-color','#777');
});
I would always always add a css class rather than an inline style.
Much more maintainable and extensible.
Example:
$('img.flickr_photo').click(function(){
$(this).addClass('greyishBorder');
});
Either photo['id'] is wrong, or is changing after you set up the click handler.
To test for the first case, you can alert (or console.log with FireBug, or whatever) the length of the jQuery selection:
alert($('#photo'+photo['id']).length);
The solution in the second case is to use 'this'. In the click handler, 'this' is set to the element that caused the click event.
$('#photo'+photo['id']).click(function(){
$(this).css('border-color','#777');
});
Edit: #Dreas Grech is right, as long as you want to apply the behavior to all the elements with the flickr_photo class. If you can generalize the selector to select all the elements with a single query, it's better to do that.