I am trying to add a second class to my element
Before
<div class="foo1">
<a class="class1" >Text</a>
</div>
After
<div class="foo1">
<a class="class1 class2" >Text</a>
</div>
here is my javascript code (tried but no success):
window.onload = function() {
document.getElementById('class1').className = 'class2';
};
UPDATE
actually, all of your answers work, but since this (class1) is a click event, by running the codes it temporarily adds the second class (class2) to the class1 but when page is reloaded , it has disappeared. I need to implement it via a click event by clicking class1. How do I do it?
2nd UPDATE
actually the site users have the ability to change this class, so I am trying to make this happen: that a user changes a class by clicking on class1 and making it "class1 class2"
Two problems with your code:
You're trying to look up class1 as an id, but you don't have any element with id="class1"; I assume you want to look up elements with that class, but that's not what getElementByid does
You're overwriting the class list by assigning to className; instead, you need to append to it (including a space, so you end up with the right string).
If you want to add the second class to all elements that have class1, you'll need a loop:
[].forEach.call(document.querySelectorAll(".class1"), function(element) {
element.className += " class2";
});
querySelectorAll works on all modern browsers, and also IE8. It accepts a CSS selector and returns a list of matching elements. Then, in the above, I loop over the list by borrowing Array#forEach, which is happy to loop through array-like things like the lists from querySelectorAll.
I should mention that if you want to use forEach on IE8, you'll need a polyfill for it. Or of course, use a boring old loop:
var list = document.querySelectorAll(".class1");
var n;
for (n = 0; n < list.length; ++n) {
list[n].className += " class2";
}
Or if you only want to do it if they're inside a .foo1:
[].forEach.call(document.querySelectorAll(".foo1 .class1"), function(element) {
element.className += " class2";
});
Or only direct children of a .foo1:
[].forEach.call(document.querySelectorAll(".foo1 > .class1"), function(element) {
element.className += " class2";
});
Suggested reading:
MDN
DOM
CSS Selectors
In case you're using jQuery and forgot to tag it (hey, it happens):
All:
$(".class1").addClass("class2");
Only inside a .foo1:
$(".foo1 .class1").addClass("class2");
Or only direct children of a .foo1:
$(".foo1 > .class1").addClass("class2");
To get all the elements with that class:
var elements = document.getElementsByClassName('class1');
Then loop over them:
for (var i = 0; i < elements.length; i++)
You need to concat the values:
element.className += ' class2';
So the full code looks like this:
var elements = document.getElementsByClassName('class1');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.className += ' class2';
}
Example (.class2 elements have red colour):
var elements = document.getElementsByClassName('class1');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.className += ' class2';
}
.class2 {
color: red
}
<div class="class1">1</div>
<div class="class1">2</div>
Or, if your browser supports classList (as most modern browsers do), then something like this will work as well:
element.classList.add('class2');
AFTER THE QUESTION UPDATE
but since this is a click event, it temporarily adds the second class but when page is reloaded , it has disappeared. I need to implement it via a click event. How do I do it?
Ideally, you'd use a server-side language to maintain changed classes after a page reloads. Normally, when you reload a page, your whole DOM reloads (including the classes).
There is a client-side solution, but not recommended: use a storage mechanism, like sessionStorage, localStorage, or plain old cookie, to keep track of click events. And then, when you render the page, simply check the storage for those click events you tracked, and adjust classes accordingly using the code above.
Why not recommended? Because this is a way of faking a server-side behaviour using a client-side language. Ideally, if you want to keep things on the client, you'd avoid the page reload completely and have everything happen on a single page (like SPAs do). But I'm afraid I can't tell you much more unless you provide more details about what are you trying to do.
Here's a super-simple example using localStorage, note how it keeps the class settings after a refresh:
http://jsfiddle.net/73efLsht/
Related
I am trying to add a second class to my element on click
Before
<div class="foo1">
<a class="class1" >Text</a>
</div>
After
<div class="foo1">
<a class="class1 class2" >Text</a>
</div>
here are my javascript codes; both of them work:
either this one (thanks to #Shomz)
var elements = document.getElementsByClassName('class1 ');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.className += ' class2';
}
or this one (thanks to #t-j-crowder)
[].forEach.call(document.querySelectorAll(".class1 "), function(element) {
element.className += " class2";
});
Question
The site allows the users to click on class1 and change it to class1 class2 . However, by running these codes, the class1 only temporarily changes to class1 class2, I mean the clicking event is not implemented, it has only visually changed. When the site is reloaded, it is back to the previous state. How to apply a fix to change permanently the class by clicking on it?How to achieve the class changing through a click event and to record this permanently? How can these js codes record this click and change it permanently?
Ok so based upon your comment you need to communicate the change to a server, then when the page loads it needs to request the data back from the server to reflect any stored changes. Theres a number of ways to do this depending on your programming capability, preference in language and compatibility requirements.
The most popular method would likely be a data file that is written dynamically by a php script. When the page is loaded it would generate your content based upon the contents of the datafile on the server(not to be confused with your HTML page). When the user modifies and element your page would call the php script using the AJAX POST method in javascript, then the php script would read the existing datafile, modify it accordingly and save it to the server.
For starters you will need a web server with PHP; if your testing locally MAMP is a good choice for Mac and I believe they now do a windows version as well.
Your would have 3 files( presuming all of your css and js is written in your HTML file):
index.htm
data.js
update.php
Assuming a linear list of div elements, each with a switchable class and child content.
index.htm
<html>
<head>
<script src='datafile.js'></script>
<script>
window.addEventListener('load',onload,false); //register the on load handler
function onload(){
var body = document.getElementsByTagName('body')[0];
var newelement;
for(var i = 0; i < elements.length; i++){
//for each element in the data file
newelement = document.createElement('div');
//create a div element
newelement.innerHTML = elements[i].content;
//place the content within the div
newelement.className = elements[i].class;
//set our classes
body.appendChild(newelement);
//add the div to the body
newelement.addEventListener('click',onclick,false);
//add a click listener to the element
}
}
function onclick(){ //on click function
var elementIndex = elements.indexOf(this); //this will be the element in the callback context
//modify class
postchange(elementIndex,classList);
}
function postchange(element,class){
// new post method
// data = {'element':element,'class':class};
// post data to update.php
}
</head>
<body>
</body>
</html>
data.js
var elements = [
{
"content":'Hello I am div 1',
"class":'classA'
},
{
"content":'Hi, I have been known as div 2... but you can call me Tim',
"class":'classA classB'
}
]
I've left the PHP out, it's not my main language so I don't feel happy improvising any code for you without looking it up and testing it first. That and it shouldn't be too hard for you to find information on POST methods on Stack Overflow.
Similarly I left the POST method in the JS out because the standard JS method is a little overcomplicated. Look up the jQuery POST method which is much more simple, again examples should be easy to find.
So I am writing a script that can be run on a page but I want to click on this element, unfortunately, it does not have an id to get and I am trying to use the .click() function on it, but it doesn't work, here's what I have, anyone know how to fix it? This is the only element in the class also
var classes = document.getElementsByClassName('rateRecipe btns-one-small');
var Rate = classes[0];
Rate.click();
I'd suggest:
document.querySelector('.rateRecipe.btns-one-small').click();
The above code assumes that the given element has both of those classes; otherwise, if the space is meant to imply an ancestor-descendant relationship:
document.querySelector('.rateRecipe .btns-one-small').click();
The method getElementsByClassName() takes a single class-name (rather than document.querySelector()/document.querySelectorAll(), which take a CSS selector), and you passed two (presumably class-names) to the method.
References:
document.getElementsByClassName().
document.querySelector().
If you want to click on all elements selected by some class, you can use this example (used on last.fm on the Loved tracks page to Unlove all).
var divs = document.querySelectorAll('.love-button.love-button--loved');
for (i = 0; i < divs.length; ++i) {
divs[i].click();
};
With ES6 and Babel (cannot be run in the browser console directly)
[...document.querySelectorAll('.love-button.love-button--loved')]
.forEach(div => { div.click(); })
for exactly what you want (if you know the index of button):
var rate = document.getElementsByClassName('rateRecipe btns-one-small')[0];
rate.click();
or for direct action
document.getElementsByClassName('rateRecipe btns-one-small')[0].click();
with jQuery
$('.rateRecipe .btns-one-small').click(function(){
var vIndex = $('.rateRecipe .btns-one-small').index(this);
//vIndex is the index of buttons out of multiple
//do whatever
//alert($(this).val());//for value
});
class of my button is "input-addon btn btn-default fileinput-exists"
below code helped me
document.querySelector('.input-addon.btn.btn-default.fileinput-exists').click();
but I want to click second button, I have two buttons in my screen so I used querySelectorAll
var elem = document.querySelectorAll('.input-addon.btn.btn-default.fileinput-exists');
elem[1].click();
here elem[1] is the second button object that I want to click.
Here is the HTML code:
<span class="holder">
Navigate
</span>
I want to select all such tags with class holder and then under these holders I want to change href of a tag.
What I have tried:
var holders = document.getElementsByClassName('holder'),
i = holders.length;
while(i--) {
holders[i].getElementsByTagName('a').href = "http://www.google.com";
}
But the above code does not work. It does not change the href from /menu/page1 to my custom link. What am I doing wrong?
As I am working with some external web page,I cannot use jquery.
Only Javascript solutions please.
Thank You.
getElementsByTagName returns elements collection, if you want to get the first link, use .getElementsByTagName('a')[0]
As the perent element may contain multiple instances of a same tag, so getElementsByTagName returns a collection of the elements/nodes
So, you have to process it like an array. Bellow is one of the best way to do this
var holders = document.getElementsByClassName('holder'),
i = holders.length;
while(i--) {
var anchors = holders[i].getElementsByTagName('a');
for (var j = 0; j < anchors.length; j++) {
anchors[j].href="'http://www.google.com";
}
}
Demo Fiddle
I have created a view in Drupal. I'm using JavaScript to modify the CSS in each row. The script runs on the first row, but does not make the changes on the rest of rows from the view.
This is the script:
<script language="javascript" type="text/javascript">
window.onload = floatbr;
function floatbr() {
var f = document.getElementById('firstright') // Get div element
var s = document.getElementById('secondright') // Get div element
var w = document.getElementById('catwrapper') // Get div element
var sh = s.offsetHeight // secondright div height
var wh = w.offsetHeight // catwrapper div height
f.style.height = wh - sh + 'px'; }
</script>
I'm using it from this page: http://agsone.100webcustomers.com/floatbottom.php
having the script in the page once does not do the trick.
having the script in the view footer and repeating the script does not work.
The link to the jSfiddle with HTML, CSS and JavaScript is the following one: http://jsfiddle.net/YTN3K/.
Drupal provides and already uses jQuery, so you should use it too. Drupal has its own way to manage JavaScript and comes with some additional JavaScript API, mainly to handle passing variables from PHP to JavaScript properly, register script to run on page load and content addition, etc.
jQuery is well documented and popular, so finding documentation, tutorial and howto is easy. Its own documentation page is a good start. But it requires basic understanding of what an XHTML document is and how it is structured.
It's hard to tell from your question and the markup you've linked to exactly what you're trying to do, so here's some general information to get you going:
The function you're currently using, getElementById, returns a single element: The one on the page with that id value. (id values must be unique on the page.)
To deal with multiple elements, you have several options. Two of the most popular:
You can start with a given element and then use its childNodes, firstChild, nextSibling, and similar properties to navigate from it to other elements nearby.
You can use getElementsByTagName (on the document or on an element) to find all elements within that container (including ones several levels down) that have a given tag. For instance, document.getElementsByTagName("p") gives you a NodeList of all paragraphs on the page.
These are properties and methods of the "DOM" (the Document Object Model), which is the tree of elements and associated information the browser creates when parsing and rendering your HTML.
References:
DOM2 Core
DOM2 HTML bindings
DOM3 Core
HTML5 Specification's DOM info
Here's an example showing some very basic operations (live copy):
HTML:
<div id="justOneDiv">I'm the <code>justOneDiv</code> element. I'm unique on the page. JavaScript code on the page turned me red.</div>
<div id="container">I'm a container called "container" with <span>various</span> <code>span</code> elements. <span>Code</span> on the <span>page</span> has made all of the <code>span</code> elements in this container <span>bold</span>.</div>
<div>I'm a container with <span>various</span> <code>span</code> elements. <span>Note</span> that the <code>span</code> elements are <span>not</span> bold, because I'm <span>not</span> in the container above.</div>
<div>I'm a <code>div</code> with no class.</div>
<div class="foo">I'm a <code>div</code> with class "foo". Code on the page turned me blue.</div>
<div class="bar">I'm a <code>div</code> with class "bar". Code on the page turned me green.</div>
<div>Another classless <code>div</code></div>
<div class="foo other">Another "foo", also with class "other"</div>
<div class="bar">Another "bar"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar test">Another "bar", also with class "test"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar">Another "bar"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar">Another "bar"</div>
JavaScript:
(function() {
hookEvent(window, "load", go);
function go() {
var list, index, div, container;
// Get just the one element, turn it red
document.getElementById("justOneDiv").style.color = "red";
// Get the spans within the specific container
container = document.getElementById("container");
list = container.getElementsByTagName("span");
// Loop through making those spans bold
for (index = 0; index < list.length; ++index) {
list.item(index).style.fontWeight = "bold";
}
// Get a NodeList of all divs on the page
list = document.getElementsByTagName("div");
// Loop it, turning "foo"s blue and "bar"s green
for (index = 0; index < list.length; ++index) {
div = list.item(index);
if (/\bfoo\b/.test(div.className)) {
div.style.color = "blue";
}
else if (/\bbar\b/.test(div.className)) {
div.style.color = "green";
}
}
}
function hookEvent(element, eventName, handler) {
// Very quick-and-dirty, recommend using a proper library,
// this is just for the purposes of the example.
if (typeof element.addEventListener !== "undefined") {
element.addEventListener(eventName, handler, false);
}
else if (typeof element.attachEvent !== "undefined") {
element.attachEvent("on" + eventName, handler);
}
else {
element["on" + eventName] = handler;
}
}
})();
Side note: The operations above can be made dramatically simpler by leveraging the utility functionality provided by any decent JavaScript library like jQuery, Prototype, YUI, Closure, or any of several others.
For example, using that same HTML, here's the JavaScript code using jQuery for the same result (live copy):
jQuery(function($) {
// Get just the one element, turn it red
$("#justOneDiv").css("color", "red");
// Get the spans within the specific container
// Loop through making those spans bold
$("#container span").css("font-weight", "bold");
// Turn all divs with the class "foo" blue
$("div.foo").css("color", "blue");
// Turn all divs with the class "bar" green
$("div.bar").css("color", "green");
});
The DOM is the official API; libraries like jQuery provide alternate or enhanced APIs. They're very useful and powerful, but I would recommend having some understanding of the DOM itself, even if you use a library and end up rarely writing code directly to the DOM API.
Is it possible to apply / create a YUI Button by using an element's class name and not by id. I have to generate a list of buttons then transform it to a YUI button.
[Update]
By the way, I'm trying to apply the button in an anchor tag. So it will be a link button.
[Update:Code]
Ok so here's the code. I have a loop that generates this anchor tag.
<a class="system-button" href="/system/edit/12">Edit</a>
wrumsby's answer perfectly makes sense. But I don't know why it doesn't work. I tried debugging it and the elements are successfully fetched. But it seems that no YUI Buttons are created.
I even tried generating unique ids for the elements but still no luck.
Any ideas?
Looks like I've solved it myself. But I'm not sure if this is the best solution. I generated unique ids then create the buttons.
var i = 0;
$(".system-button").each(function(i,b){
var button = new YAHOO.widget.Button($(b).attr('id','system-button'+i).attr('id'));
i++;
});
And oh yes, I use JQuery here. That framework is so awesome.
You should be able to use the srcelement configuration attribute like so:
(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event,
Button = YAHOO.widget.Button;
Event.onDOMReady(
function() {
var elements = Dom.getElementsByClassName('...');
for (var i = 0; i < elements.length; i++) {
var button = new Button({
srcelement: elements[i],
...
});
...
}
}
);
})();