Get Element By Classname Script Not Working - javascript

I know, it's not supported by IE, but I found a cool script online that someone was generous enough to provide for free, but I can't figure out why it's not working. I've been staring at this for hours, please point me in the right direction!
My code:
<script language="javascript" type="text/javascript" src="getbyclass.js"></script>
<script type="text/javascript" language="javascript">
function editToggle(toggle){
if (toggle == "off"){
getElementsByClassName("editp").style.display ="none";
document.getElementById('editToggle').innerHTML=">Edit Mode: <span style=\"color:red;\">OFF</span>";
toggle="on";
}else{
getElementsByClassName("editp").style.display ="inline";
document.getElementById('editToggle').innerHTML=">Edit Mode: <span style=\"color:green;\">on</span>";
toggle="off";
}
}
also:
echo "<span id=\"editToggle\">Edit Mode: <span style=\"color:red;\">OFF</span></span>";
The code from getbyclass.js can be seen here.
In response to the answers below, I've tried this:
function editToggle(toggle){
var list = getElementsByClassName("editp");
if (toggle == "off"){
//getElementsByClassName("editp").style.display ="none";
for (index = 0; index < list.length; ++index) {
list[index].style.display ="none";
}
document.getElementById('editToggle').innerHTML=">Editfalse;\">Edit Mode: <span style=\"color:red;\">OFF</span>";
toggle="on";
}else{
//getElementsByClassName("editp").style.display ="inline";
for (index = 0; index < list.length; ++index) {
list[index].style.display ="inline";
}
document.getElementById('editToggle').innerHTML=">Editfalse;\">Edit Mode: <span style=\"color:green;\">on</span>";
toggle="off";
}
}
But it's still not working.

getElementsByClassName returns a collection. You might need to loop through the results, like this:
var elements = document.getElementsByClassName('editp');
for(var i=0; i<elements.length; i++) {
elements[i].style.display='none';
}
elements is a live NodeList of found elements in the order they appear in the tree.
names is a string representing the list of class names to match; class names are separated by whitespace
getElementsByClassName can be called on any element, not only on the document. The element on which it is called will be used as the root of the search.
Should go through this.

getElementsByClassName returns a NodeList (or an array if it's not built-in), but you're using it as though it were an HTMLElement by referring directly to a style property on it:
getElementsByClassName("editp").style.display ="none";
// here ------------------------^
You should be seeing an error in the JavaScript console, since you're trying to retrieve the property display from undefined (since getElementsByClassName("editp").style will be undefined).
If you want to act on the first matching element:
var elm = getElementsByClassName("editp")[0];
if (elm) {
elm.style.display ="none";
}
...or if you want to act on all of them:
var index;
var list = getElementsByClassName("editp");
for (index = 0; index < list.length; ++index) {
list[index].style.display ="none";
}
Update:
At some point, you edited the question and removed var toggle = "off" from the code (at global scope, just above the function) and made toggle an argument to editToggle. But you're not passing anything into editToggle according to your quoted markup, and even if you were, setting toggle to a new value within the function won't have any lasting effect if it's a function argument, as nothing refers to it after the function returns.

There may be unterminated string literals in the markup you create. It also appears there may be other issues as mentioned in other posts.
Change:
"Edit Mode: <span style=\"color:red;>OFF</span>";
to
"Edit Mode: <span style=\"color:red;\">OFF</span>";
This situation is also present in the other markup you create.
Change:
"Edit Mode: <span style=\"color:green;>on</span>";
to
"Edit Mode: <span style=\"color:green;\">on</span>";

You seem to have a missing semicolumn after var toggle="off".
Make sure that you call editToggle() somewhere in your code.
I advise you to use inspectors built into browsers or extensions. For example Firebug extension for Firefox or Chrome Inspector. Use the console to debug and see if there are errors in your javascript.

Related

Javascript string.slice() with negative values

I am trying to hide or show divs based on the title of the page. This is only required because I can't figure out a better way of passing a value into the page.
Here's the current code in the HTML file:
function toggle(divId) {
var divArray = document.getElementsByTagName("div");
for(i = 0; i < divArray.length; i++){
if(divArray[i].id == divId){
if(divArray[i].style.display != 'none'){
divArray[i].style.display = 'none';
}else{
divArray[i].style.display = '';
}
}
}
}
function togglePayLink() {
var h1Array = document.getElementsByTagName("h1");
for(i = 0; i < h1Array.length; i++){
if(h1Array[i].id == 'Title'){
var title = h1Array[i].innerHTML;
title = title.slice(1);
title = title.slice(-4);
toggle('descr'+ title);
}
}
}
Also in the HTML file is a header with the page title. The %%GLOBAL_PageTitle%% is replaced in server side code that I don't have access to. However, the values will be "$100 Fee" (with different numbers).
<h1 id="Title" class="TitleHeading">%%GLOBAL_PageTitle%%</h1>
Finally, I have a set of hidden divs with id's in the format descr + a number, so if the page title is "$100 Fee" I want to show the div with the id "descr100".
<div id="descr100" style="display:none;width: 75%;"></div>
When the script above runs, I get no error (I'm using chrome's console), but the div does not show. I know the toggle function works because it was previously being used with only a single div on the page that had to be toggled. I wrote the togglePayLink function, which I assume is the issue, but I have no idea how to debug this. I was wondering if the dollar sign in the title could be causing issues, but I would think I would get an error if that were the case.
EDIT: Changed the togglePayLink function to use var instead of string, but I'm getting a typeError when slice() is called.
Going forward, you should probably just assign a unique class to the page using %%GLOBAL_PageTitle%%. This way you can show/hide elements using CSS.
<div class="page %%GLOBAL_PageTitle%%">
For pages that BigCommerce doesn't give access to the HTML of the h1 for each individual page (ex. Web Pages, Account, Cart), I usually run this script on page load to strip the page title of spaces and other characters, and assign a specific class to the page element.
var catName = $('.TitleHeading').text();
var catName = catName.replace(/ /g, '');
var catName = catName.replace(/'/g, '');
var catName = catName.replace(/&/g, '');
var catName = $.trim(catName);
$('.page').addClass(''+catName+'');
The way your doing it seems a bit over the top, but if it was setup this way by someone else, I understand.
The problem is here:
String title = h1Array[i].innerHTML;
In Javascript, all variables are set with var (except for functions, which can be set other ways). So it would be:
var title = h1Array[i].innerHTML;
Additionally, you probably have to define it outside the for loop, in which case you would omit the "var" when you are setting it in the for loop:
<script language="javascript">
var title;
function togglePayLink() {
var h1Array = document.getElementsByTagName("h1");
for(i = 0; i < h1Array.length; i++){
if(h1Array[i].id == 'Title'){
title = h1Array[i].innerHTML;
title = title.slice(1);
title = title.slice(-4);
toggle('descr'+ title);
}
}
}
</script>
Edit: If you only use it in the for loop, but use it in different iterations, then I'm not sure if it can be defined locally. I'd still define it globally, though.
title.slice(-4) was giving me the last four digits of the string instead of everything before the last four digits like I thought it would. toggling the non-existent 'descrFee' div was not doing anything.

Adding javascript programmatically to dynamicly generated hyperlinks with the same id

Might be a strange setup, but I have a number of hyperlinks on the page with the same id (yeah, I know, but it was not my choice and I cannot change that at this time plus those hyperlinks are generated dynamically).
Example:
<div id="Links">
<div class="myItem">Some text</div>
<div class="myItem">More text</div>
<div class="myItem">Even more text</div>
</div>
Now I need to attach javascript to those links dynamically (the hyperlinks are also dynamically generated). The easiest way I see is by getting all hyperlinks on the page and then check the hyperlink id to ensure I only take care of those that have id of "myLink" (I have many other hyperlinks on the page).
I thought of using getElementById but that would only grab the first element with the specified id.
am attaching javascript to those links using the following:
window.onload = function() {
var anchors = document.getElementsByTagName('a');
for(var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
if (anchor.id='myLink')
{
if (anchor.getAttribute("LinkID") != null)
{
anchor.onclick = function() {
MyFunction(this.getAttribute("LinkID"), false);
return false;
}
}
}
}
}
The above function works fine, but it creates another issue - affects the styling of other hyperlinks on the page. So I was wondering if there is a way to accomplish the same thing but without affecting other elements on the page?
This is more modern and corrects your equality test:
window.onload = function() {
var anchors = document.getElementsByTagName('a');
for(var i = 0; i < anchors.length; i++) {
if (anchor[i].id==='myLink' && anchor[i].getAttribute("LinkID") !== null)
{
anchor[i].addEventListener("click", function() {
MyFunction(this.getAttribute("LinkID"), false);
}
}
}
}
Even with your original code, I don't see anything that would interfere with styling in the code. Can you elaborate as what styling changes you were getting?
You can use an attribute selector and document.querySelector([id=<id>]) pretty reliably depending on your browser support situation: http://codepen.io/anon/pen/YwLdKj
Then, of course, loop through that result and make subsequent changes or event bindings.
If not, you could use jQuery (referenced in above code pen).
You might also use JavaScript event delegation and listen for all click events, check if the user is clicking a link with the correct id.
If a combination of tag == 'a', class == "myItem" and presence of a LinkID attribute is sufficient to identify nodes requiring a click handler they could be identified using multiple CSS selectors. If this is not possible however, a query selector not using id can create a list of nodes to be checked for id, as for example:
function callMyFunction()
{ MyFunction(this.getAttribute("LinkID"), false);
}
function addClickHandlers()
{ var list = document.querySelectorAll("a[LinkID]")
var i, node;
for( i = 0; i < list.length; ++i)
{ node = list[i];
if(node.id == "myLink")
{ node.onclick=callMyFunction;
}
}
}
See also running a selector query on descendant elements of given node if of interest.

Adding target="blank" to links with javascript

I'm attempting to add target="_blank" to links on a page depending on a checkbox click.
On the javascript side I have:
function newTab(v) {
if(v.tab.checked == true) {
document.getElementsByTagName('a').setAttribute('target', '_blank');
} else {
document.getElementsByTagName('a').setAttribute('target', '_self');
}
} //end function
And on the HTML side I have:
<form>
<input type="checkbox" name="tab" onclick="newTab(this.form)" />
<label>Open Links In New Tab?</label>
</form>
Gmail
Naturally it isn't as simple as I thought it would be, so it doesn't work.
The page contains over a dozen links so I need the checkbox to apply to all links on the page - why I used getElementsByTagName(). Any help appreciated!
EDIT:
Code that works is as follows:
function newTab(f) {
var els = document.getElementsByTagName('a'); //read anchor elements into variable
if(f.tab.checked == true) { //If the box is checked.
for (var i in els) {
els[i].setAttribute('target', '_blank'); //Add 'target="blank"' to the HTML
}
} else { // not checked...
for (var i in els) {
els[i].setAttribute('target', '_self'); //Add 'target="self" to HTML
}
}
} //end function.
getElementsByTagName() returns a nodeset. You need to iterate over it and apply the change to each one in turn. What you currently have is more like jQuery syntax, which handles this internally for you.
This would have shown up in the console. With JS issues, always check the console before wondering what's wrong.
var els = document.getElementsByTagName('p');
for (var i=0, len = els.length; i<len; i++)
els[i].setAttribute('name', 'value');
Also, with checkboxes use change, not click events, as someone might toggle them via the keyboard, not mouse. Lastly, you should look into handling your events centrally, not inline DOM-zero events specified in the HTML. Numerous reasons for this that are beyond the scope of this question.

Script to enable/disable input elements?

I'm wondering if it's possible for a script to enable/disable all input elements on the page with some sort of toggle button.
I googled it but didn't find anything too useful except for this:
http://www.codetoad.com/javascript/enable_disable_form_element.asp
but I'm not sure how to edit it for the toggle.
Something like this would work:
var inputs=document.getElementsByTagName('input');
for(i=0;i<inputs.length;i++){
inputs[i].disabled=true;
}
A working example:
$().ready(function() {
$('#clicker').click(function() {
$('input').each(function() {
if ($(this).attr('disabled')) {
$(this).removeAttr('disabled');
}
else {
$(this).attr({
'disabled': 'disabled'
});
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<input type='text'></input>
<input type='text'></input>
<input type='text'></input>
<div id='clicker' style='background-color:#FF0000; height:40px; width:100px;'></div>
Here is a function to toggle all inputs on the page:
function toggle_inputs() {
var inputs = document.getElementsByTagName('input');
for (var i = inputs.length, n = 0; n < i; n++) {
inputs[n].disabled = !inputs[n].disabled;
}
}
It works by using the logical NOT operator (the exclamation point), which returns the opposite of the operand. For example, !true will return false. So by using !inputs[n].disabled, it will return the opposite of what it's currently set to, thereby toggling it.
If you need code to bind the click event to the button:
document.getElementById('your_button_id').onclick = toggle_inputs;
You can also use addEventListener, but see the linked page for more information, including compatibility with Internet Explorer. The code I gave above should work across all browsers with no trouble.
for (var i = 0; i < document.getElementyByTagName('input').length; i++) {
document.getElementsByTagName('input')[i].disabled = 'disabled';
}
http://code.google.com/p/getelementsbyclassname/
^^Robert Nyman has a "get elements by class" script. Basically you'd just assign all those input elements to the same class, and then do something like:
//Collapse all the nodes
function collapseNodesByClass(theClass){
var nodes = getElementsByClassName(theClass);
for(i = 0; i < nodes.length; i++){
nodes[i].style.display='none';
}
}
This is a piece of code I'm actually currently using to collapse everything with a given class name (it uses the script I mentioned above). But in any case I think the key to your problem is being able to refer to multiple elements at once, which that script will help you with.
Also the link in your question didn't work for me :(.

Javascript to modify CSS not working in IE

I'm a bit of a novice when it comes to Javascript, but I've managed to create this script which 'greys out' text and inputs found in a div. It accepts a boolean (show) to declare whether the elements are being hidden or reshown, as well as the name of the div(s) to hide.
It works exactly as intended in Chrome and Firefox, but IE won't do a thing. Through 'debugging' using alerts, I think the issue lies with this line:
var div = document.getElementsByName(divName);
...of the following code:
function hideAndShow(show, divName) {
var hideColor = "#DFDFDF";
// Find all matching divs and loop through
var div = document.getElementsByName(divName);
for (var count1 = 0; count1 < div.length; count1++) {
// Find and loop through all elements in div
var elements = div[count1].getElementsByTagName("*");
for (var count2 = 0; count2 < elements.length; count2++) {
if (elements[count2].tagName == "TEXTAREA" || elements[count2].tagName == "INPUT") {
elements[count2].disabled = !show; //Disable
elements[count2].style.borderColor = (show) ? "" : hideColor; // Change border colour
elements[count2].value = ""; //Clear existing text
}
}
// Change the colour of anything left, such as text
div[count1].style.color = (show) ? "" : hideColor;
alert(div[count1].id);
}
}
Can anybody please help or point me in the right direction? I'm stumped!
It's possible that IE is getting confused by your page: http://www.romantika.name/v2/javascripts-getelementsbyname-ie-vs-firefox/
afaik the IE implementation of getElementsByName actually searches on id
In IE7 at least:
// works in IE but not Chrome
<div id="test"></div>
alert(document.getElementsByName('test').length);
// doesn't work in IE, works in Chrome
<div name="test"></div>
alert(document.getElementsByName('test').length);
Libraries like jQuery deal with all this nonsense for you and make selecting DOM elements trivial.
If you want to do it in pure JS, you might want to look at providing an implementation of getElementsByClassName (see here for an example) to solve the problem.

Categories

Resources