Javascript / Greasemonkey / Userscript.js identify element and remove one of many classes - javascript
I've spent far too many hours trying to figure this out and as JavaScript is not my primary language and not yet a jQuery guru I've determined I need to ask for help.
In a case where a generated page has a structure where it has a DIV for some odd reason no ID, multiple non-standard data tag attribute tags, but at least standard style CLASS assignment....however...it has been assigned MULTIPLE classes.
Now, just one of those style classes is such that it has a code event associated that I want to neuter and leave all other classes still assigned. What I've tried there (this list is far from complete I have tried many things):
document.getElementsByClassName('Goodclass01')[0].remove('BADCLASS');
document.querySelectorAll('[data-tag-one="["value",
"value"]"]').remove('BADCLASS');
Various jnode calls that all fail due to claims of being unknown
A couple variations of something referred to as the "location hack" none of
which I could get to work but may have very well have been user error.
Safewindow attempt to just replace BADCLASS javascript function all together
but not ideal explained below.
Here is an example of the kind of structure of the target:
<div id="main">
<div class="main_content" data-tag-id="12345">Some stuff sits above</div>
<a href="SOME LINK" class="Goodclass01 Goodclass02 Goodclass03 BADCLASS"
data-tag-one="["value", "value"]">
</div>
In this example there is a javascript function that fires upon clicking the href link above due to the function being associated with BADCLASS style assignment. So, from lots of searching it seemed like I should be able to grab that DIV by any of the initially assigned classes (since there is unfortunately not a class ID which would make it very easy) but then reassign the list of classes back minus the BADCLASS at page load time. So, by the time the user clicks the link, the BADCLASS has been removed to look like this:
<div id="main">
<div class="main_content" data-tag-id="12345">Some stuff sits above</div>
<a href="SOME LINK" class="Goodclass01 Goodclass02 Goodclass03"
data-tag-one="["value", "value"]">
</div>
I also read that simply using unsafewindow to replace the BADCLASS javascript function could be possible, so I am open to hearing one of you gurus help with how easy (or hard) that would be. In a case where BADCLASS could be shared function code perhaps called by another element on the page still having that initial class that perhaps we desire to continue to function which is why if it is only a single element that needs to be altered, I would rather just change this one href div.
Hope the explanation makes sense and what is probably a laughable simple example above for the Javascript gurus so forgive me but your help is greatly appreciated and will save more hair pulling! :)
EDIT: This must work above all in Chrome browser!
Remove the class from all elements
If you want to remove the class from all elements that have the class, simply select all of the elements with that class and remove the class from their class lists.
[...document.querySelectorAll('.BADCLASS')]
.forEach(e => e.classList.remove('BADCLASS'));
const elements = [...document.querySelectorAll('.BADCLASS')];
elements.forEach(e => e.classList.remove('BADCLASS'));
console.log(elements);
<div id="main">
<div class="main_content" data-tag-id="12345">Some stuff sits above</div>
<a href="SOME LINK" class="Goodclass01 Goodclass02 Goodclass03 BADCLASS"
data-tag-one='["value", "value"]'>link</a>
</div>
Using jQuery:
$('.BADCLASS').removeClass('BADCLASS');
const elements = $('.BADCLASS');
elements.removeClass('BADCLASS');
console.log(elements);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<div class="main_content" data-tag-id="12345">Some stuff sits above</div>
<a href="SOME LINK" class="Goodclass01 Goodclass02 Goodclass03 BADCLASS"
data-tag-one='["value", "value"]'>link</a>
</div>
Remove the class from a subset of elements
If you only want to remove the class from a subset elements, select those elements then from the class from their class lists.
[...document.querySelectorAll('.Goodclass01, .Goodclass02, .Goodclass03')]
.forEach(e => e.classList.remove('BADCLASS'));
const elements = [...document.querySelectorAll('.Goodclass01, .Goodclass02, .Goodclass03')];
elements.forEach(e => e.classList.remove('BADCLASS'));
console.log(elements);
<div id="main">
<div class="main_content" data-tag-id="12345">Some stuff sits above</div>
<a href="SOME LINK" class="Goodclass01 Goodclass02 Goodclass03 BADCLASS"
data-tag-one='["value", "value"]'>link</a>
link
</div>
Using jQuery:
$('.Goodclass01, .Goodclass02, .Goodclass03').removeClass('BADCLASS');
const elements = $('.Goodclass01, .Goodclass02, .Goodclass03');
elements.removeClass('BADCLASS');
console.log(elements);
<div id="main">
<div class="main_content" data-tag-id="12345">Some stuff sits above</div>
<a href="SOME LINK" class="Goodclass01 Goodclass02 Goodclass03 BADCLASS"
data-tag-one='["value", "value"]'>link</a>
link
</div>
Run at document idle
The default for the run-at directive is document-idle, but if for some reason that has been changed, either it needs to be document-idle, or you need to otherwise delay execution of the script until the document has loaded.
You could use the run-at directive in the userscript header like so:
// #run-at document-idle
Or attach a load event listener to the window
window.addEventListener('load', function() { /* do stuff */ }, false);
Include jQuery
If you're using one of the jQuery solutions, you will have to include jQuery using the require userscript header directive like so:
// #require https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
Got it with the help of both of the clear, awesome correct answers below that literally came in within seconds of each other and only a few min after my post, so thanks to both #Tiny and #Damian below!
I'm upvoting both as they both listed the same correct jQuery answers, and Tiny also provided the pure JS.
I am posting the full answer below because without the other steps, with Tamper/Greasemonkey neither will produce the desired results.
First, Tamper/Greasemonkey do not load jQuery by default, so it is just easy as add #require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js to your current script and also put this.$ = this.jQuery = jQuery.noConflict(true); to avoid any versioning conflicts.
Also, in this case unfortunately I HAD to change my TamperMonkey header to:
// #run-at document-idle
along with the above mentioned:
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
and begin the script with:
this.$ = this.jQuery = jQuery.noConflict(true);
and finally the primary accepted/best answer in this case of:
$('.Goodclass01').removeClass('BADCLASS');
NOTE: The above #run-at line is required, and since so many (all) of my current Tamper/Greasemonkey scripts are actually set by default to run at START, this is of importance as it means functions like this must be separated to their own scripts to run instead AFTER the page loads (idle). Once this is added, even the above pure JS answer from Tiny did in fact produce the desired result.
As the simplest one-line answer that I was hoping was possible in Javascript, as it is so many other languages in a single line of code. I've used it in the past, but was not aware of this particular removeClass method.
Your question mentions jQuery. Did you want a solution in jQuery?
If so, it's as easy as:
$(".Goodclass01").removeClass("badclass");
Explanation:
jQuery can be referenced as jQuery() or $(). The parameters you can pass are: 1, a Selector statement (like CSS), and 2, context (optional; default is document).
By stating $(".Goodclass01") you are stating, "Give me a jQuery object with all elements that have the class Goodclass01." Then, by using the removeClass() function, you can either pass it no parameters and it would remove all classes, or you can pass it specific classes to remove. In this case, we call .removeClass("badclass") in order to remove the undesired class.
Now, if you need to select only specific elements, such as links that have Goodclass01, you can do:
$("a.GoodClass01").removeClass("badclass");
Or, if you want to select anything that has Goodclass01, but NOT Goodclass02, you can do:
$(".Goodclass01:not(.Goodclass02)").removeClass("badclass");
jQuery is not as intimidating as it looks. Give it a shot!
Edit: I also noticed you were trying to capture a link with maybe a specific property. You can use the [property] syntax to select elements that have a specific property. Most typically, people use $("a[href^=https]") or something to that effect to select all a tags with the property href that begins with ^= the string https.
You could, in your case, use the following...
$("a[data-tag-one]")
... to select all links that have the property data-tag-one.
Note: One thing to keep in mind is that, a jQuery object is different than a pure DOM element. If you have a collection of multiple elements and want to use a pure JavaScript function on one element in particular, you would have to reference it with either [0] or .get(0). Once you do that, you will no longer be able to use jQuery methods until you convert it back to a jQuery object.
But, since jQuery has a whole slew of methods to use to make DOM manipulation easier, you can probably accomplish what you need to using those methods.
Edit: I've included a snippet below so you can see some of the jQuery selectors in action.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
div#main * { background-color: #66ff66; }
div#main .BADCLASS, div#main .BADCLASS * { background-color: #ff8888 !important; }
</style>
<div id="main">
<div class="main_content" data-tag-id="12345">Some stuff sits above</div>
<a href="SOME LINK" class="Goodclass01 Goodclass02 Goodclass03 BADCLASS"
data-tag-one='["value", "value"]'>All classes and data-tag-one</a><br />
<a href="SOME LINK" class="Goodclass01 BADCLASS" data-tag-one='["value", "value"]'>Goodclass01 and data-tag-one</a><br />
All classes, no data-tag-one<br />
<a href="SOME LINK" class="BADCLASS" data-tag-one='["value", "value"]'>Just BADCLASS and data-tag-one</a><br />
<br />
<table class="Goodclass01 BADCLASS"><tr><td>Here is a table</td></tr><tr><td>with Goodclass01 and BADCLASS</td></tr></table>
</div>
<hr>
<div id="buttons">
$(".Goodclass01").removeClass("BADCLASS");<br />
$("a.Goodclass01").removeClass("BADCLASS");<br />
$(".Goodclass01:not(.Goodclass02)").removeClass("BADCLASS");<br />
$("a[data-tag-one]").removeClass("BADCLASS");<br />
Reset the HTML<br />
</div>
<script>
$("#button1").click(function(){
$(".Goodclass01").removeClass("BADCLASS");
});
$("#button2").click(function(){
$("a.Goodclass01").removeClass("BADCLASS");
});
$("#button3").click(function(){
$(".Goodclass01:not(.Goodclass02)").removeClass("BADCLASS");
});
$("#button4").click(function(){
$("a[data-tag-one]").removeClass("BADCLASS");
});
$("#button5").click(function(){
var str = '<div class="main_content" data-tag-id="12345">Some stuff sits above</div>All classes, no data-tag-one<br /><a href="SOME LINK" class="BADCLASS" data-tag-one=\'["value", "value"]\'>Just BADCLASS and data-tag-one</a><br /><br /><table class="Goodclass01 BADCLASS"><tr><td>Here is a table</td></tr><tr><td>with Goodclass01 and BADCLASS</td></tr></table>';
$("div#main").html(str);
});
</script>
Related
How do I access anchor tag in JavaScript?
I want to access this anchor tag in JavaScript: Edit At the moment the HTML where it is located looks like this: <div class="about_section"> <div class="col-md-5"> <div class="panel panel-default"> <div class="panel-heading"> Edit <h3 class="panel-title"> About You </h3> </div> <textarea id="about_me" class="form-control inputstl" rows="5"> </textarea> </div> </div> </div> Now I have tried to access this anchor tag via the following route in my JavaScript: $('.about_section').find('a.pull-right').eq(0).on('click', function() { console.log('Works'); }) This did not work, and also via this route: $('.about_section').find('col-md-5').find('panel panel-default').find('panel-heading').find('a').eq(0).on('click', function() { //$('#edit-modal').modal() console.log('Works'); }) This did not work either, anyone have any suggestions?
You can simply do by using document.querySelectorAll("a.pull-right"); Also you can do like this $(".about_section a.pull-right").on('click',function(){ //rest of code })
Try this <div class="about_section"> <div class="col-md-5"> <div class="panel panel-default"> <div class="panel-heading"> Edit <h3 class="panel-title"> About You </h3> </div> <textarea id="about_me" class="form-control inputstl" rows="5"> </textarea> </div> </div> <script> function fun () { console.log("works"); } </script>
you can use HTML onclick event attribute to trigger a JS function. For example in this case. onclick='test();' on the anchor tag triggers JS method test() method defined on the page. <script> function test() { console.log('works'); } </script> <div class="about_section"> <div class="col-md-5"> <div class="panel panel-default"> <div class="panel-heading"> <a href="#" class="pull-right" onclick='test();'> Edit </a> <h3 class="panel-title"> About You </h3> </div> <textarea id="about_me" class="form-control inputstl" rows="5"></textarea> </div> </div> </div>
So many people here missing so much. One of your first problems is not your anchor tag, but your selectors. .find('col-md-5') won't find anything because you just told it to find an Anchor Tag named col-md-5. You forgot the period (.). You can use selectors in jQuery much the same way you use them in CSS. Also, you have to be careful of spacing. Even if you included the periods, .find('.panel .panel-default') would still not find anything because the element that has the class panel is the same one having the class panel-default. That space tells jQuery "Find an element having class panel with sub-elements having class panel-default" What your line should look like: $('.about_section').find('.col-md-5').find('.panel.panel-default').find('.panel-heading') The following should work fine: $('.about_section a.pull-right').on('click', function() { console.log('Works'); }) <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <div class="about_section"> <div class="col-md-5"> <div class="panel panel-default"> <div class="panel-heading"> Edit <h3 class="panel-title"> About You </h3> </div> <textarea id="about_me" class="form-control inputstl" rows="5"> </textarea> </div> </div> </div> However, there are several ways to fully answer your question as well as several ways this can be better achieved. You're initial question title has many routes for answers. To get all anchor tags in pure JavaScript: var a = document.getElementsByTagName('a') To get all anchor tags in jQuery: var a = jQuery('a') To get a specific anchor by ID, Class, Or Name in vanilla JS: . document.getElementById('ele_id_atr_val') . document.getElementsByClassName('class-name') . document.getElementsByName('ele_name_atr_val') Keep in mind, with Class and Name, it will get all elements having those attribute values. To get a specific anchor by ID, Class, Or Name in vanilla jQuery: . jQuery('#ele_id_atr_val') . jQuery('.class-name') . jQuery('[name=ele_name_atr_val]') Keep in mind, with Class and Name, it will get all elements having those attribute values. With all the basics out of the way, let's look at how we can improve upon what you're doing. You want to add an on_click event to an anchor element. First, let's start with the "action" or the href attribute. You're using the typical, and often recommended #, however, I would assert this is a bad practice. There's various reasons, but this answer here wraps it up pretty well. I would suggest setting your href attribute to href="javascript:void(0)". That ensures no falsy calls or unexpected behavior when the anchor is clicked on. Next, let's discuss "event handlers" and a better establishment thereof. You're making use of .eq(), which will ensure the event is assigned to only one item, but is this really your intent? And if so, then why all the build up? Why not give that one item a unique id and assign the event based on that selector? Also, you're driving through 50 miles of hay to get to a store just around the corner. A personal rule I use, if the selector to my event handler looks like a full sentence on an essay paper, it's too long. The point of jQuery, and even vanilla JS' querySelector is to make things easier. Simplify the matter. So your selector to your event should be as simple as: $('.about_section .pull-right').on('click', function(e) { This sums it up nice. It provides a parent element, the about_section block, as well as it's coordinating child of which we want to apply the event. Now that we have this much, let's make it even better and discuss "dynamic event handling". Known in jQuery as the .on|.off method. By using jQuery's .on method in conjunction with thinking about "dynamic handling" (dealing with elements added after document.readyState="complete", we can write more powerful event delegation statements that better well suit our purpose as well as provide easier readability to those who might be reviewing and/or editing our code in the future. There are two main ways of setting up such dynamics. The first, and most recommended, is to use a static (always there when page loads) element and assign it a child with an event. Such as: $('.about_section').on('click', '.pull-right', function() { console.log('Works'); }); Here, we count on an element having the class about_section to be the parent element always available when the page loads. Basically, this parent is then told "Hey! Hey you! Yes you! Every time you have a kid with the class pull-right, tell that kid to do this thing!" And so it does. Whether added on page load, or five minutes after the page is loaded, the kid having class pull-right will always do as it's parent says. This is different from my previous suggestion of $('.about_section .pull-right') in that it will apply to such dynamic (added after load) elements, whereas the previous one will only work on all those elements that exist when the page loads. The second main way, my preferred, but considered a "dangerous memory" issue by others, is to use $(document).on. First, understand it's not a danger it that it will hurt your app or other computers. It's simply unfavored because it's a danger to the run time memory. In simplest of terms, mostly with days of old (and ancient devices) assigning everything to the document variable could slow the page down. This is generally no longer an issue and for five+ years now I've been using this method with everything from basic business websites to top end, classified military apps I made for the army. Don't ask, I won't tell. Anyway, I prefer this method because it also provides an easy way to organize a whole list of events, as well as maintain the power of dynamic handling, which is so often needed in today's world of "live pages". $(document) .on('click', '.about_section .pull-right', function() { console.log('Works'); }) .on('event', 'selector', function(e) { /* Easily */ }) .on('event', 'selector', function(e) { /* Organized */ }) .on('event', 'selector', function(e) { /* And */ }) .on('event', 'selector', function(e) { /* Easy */ }) .on('event', 'selector', function(e) { /* To */ }) .on('event', 'selector', function(e) { /* Read */ }) .on('event', 'selector', function(e) { /* For */ }) .on('event', 'selector', function(e) { /* Future */ }) .on('event', 'selector', function(e) { /* Devs */ }) Any questions?
Trying to build a content locker using jQuery
I am very new to jQuery and not entirely sure what I'm doing. Will try my best to explain the problem I'm facing. I'm trying to lock some content on a landing page until a user shares the link using FB, Twitter, LinkedIN or G+. The first version of the script I wrote (which worked fine) ran like this: <head> <script type="text/javascript"> ... $(document).ready(function() { $('.class').click(clearroadblock()); buildroadblock(); } </script> <style> .class { [css stuff] } </style> </head> <body> <div id="something"> <ul> <li> Link1 </li> <li> Link2 </li> </ul> </div> </body> The problem I'm now facing is changing out this code to replace the list elements with social share buttons. As they are no longer under .class, but classes like fb-share-button and twitter-share-button. Please help me understand what I need to modify to accommodate this? PS: This is not a Wordpress site. function clearroadblock() { $('#roadblockdiv').css('display', 'none'); $('#roadblockBkg').css('display','none'); } This is the way I'm clearing the overlay once a click is detected, BTW. Can I wrap the social buttons in divs, assign them IDs and use those IDs to trigger the click like below? <div id="Button"> Tweet </div> $('#Button').click(clearroadblock());
You can have multiple classes on an element by separating them with a space. Try the following: class="class fb-share-button" Your jquery will still work off the "class" class. I would recommend you change this name to something more meaningful though. Your css can target the "class" for general styles, but you can also target fb and twitter separately. Update I decided to create a quick JSFiddle for this. Some of the styles etc won't be the same as what you're doing, but the problem is resolved. I've created a div with id main that contains the content that you want to hide. There's an absolutely positioned div over the top of this, this is the roadblock. The javascript is showing the roadblock (assuming that's what you wanted to do with buildroadblock()). On click of a link in the ul with id socialMedia we call clearroadblock. Notice the lack of parenthesis. This hides the roadblock. This isn't a great way of preventing someone from seeing information, you might want to think about pulling the content down from the server when the action is performed, however, I think this answers your question.
passing variables on jquery
just having some issues with this jQuery thing. What i'm trying to do is: i have some audio control buttons that look like this: <p>Play audio</p> but there are too many on the page so i'm trying to optimise the code and make a little function that checks for the div id on the button and adds tells the player what track to play. so i've done this: <div id="audioControlButtons-1"> <div class="speaker"> </div> <div class="play"> </div> <div class="pause"> </div> </div> <script> $(document).ready(function() { $("[id^=audioControlButtons-] div.play").click(function() { var id = new Number; id = $(this).parent().attr('id').replace(/audioControlButtons-/, ''); //alert(id); player1.loadAudio(id); return false; }); }); </script> my problem is: the id is not passing to the the player1.loadAudio(id) if i hardcode player1.loadAudio(1) it works! but the moment i try to pass the variable to the function it doesn't work... however if you uncomment the alert(id) thing you will see the id is getting generated... can someone help? cheers, dan
I think I see your problem. The variable id is a string. Try; player1.loadAudio(parseInt(id)); Yah and the initialise line isn't necessary. Just use; var id = $(this).parent().attr('id').replace(/audioControlButtons-/, '');
I'm actually kind of confused with your example because you originally have this: <p>Play audio</p> but then you don't reference it again. Do you mean that this html: <div id="audioControlButtons-1"> <div class="speaker"> </div> <div class="play"> </div> <div class="pause"> </div> </div> Is what you are actually creating? If so, then you can rewrite it like this: <div class="audio-player"> <div class="speaker"> </div> <div class="play" data-track="1"> </div> <div class="pause"> </div> </div> Then in your script block: <script> $(document).ready(function() { $(".audio-player > .play").click(function() { var track = $(this).data('track'); player1.loadAudio(+track); return false; }); }); </script> So a few things are going on here. I just gave your containing div a class (.audio-player) so that it's much more generic and faster to parse. You don't want to do stuff like [id^=audioControlButtons-] because it is much slower for the javascript to traverse and parse the DOM like that. And if you are going to have multiples of the same element on the page, a class is much more suited for that over IDs. I added the track number you want to the play button as a data attribute (data-track). Using a data attribute allows you to store arbitrary data on DOM elements you're interested on (ie. .play button here). Then this way, you don't need to this weird DOM traversal with a replace method just to get the track number. This saves on reducing unnecessary JS processing and DOM traversing. With this in mind now, I use jQuery's .data() method on the current DOM element with "track" as the argument. This will then get the data-track attribute value. With the new track number, I pass that along into your player1.loadAudio method with a + sign in front. This is a little javascript trick that allows you to convert your value into an actual number if that is what the method requires. There are at least a couple of other optimizations you can do here - event delegation, not doing everything inside the ready event - but that is beyond the scope of this question. Hell, even my implementation could be a little bit optimized, but again, that would require a little bit more in depth explanation.
jQuery click function affecting multiple divs
I'm trying to use jQuery's click function to apply a hover state to a selected div, without differentiating the div's in the JavaScript. I'm currently using: $(document).ready(function(){ $(".project").click(function() { $("a.expand").removeClass("hovered"); $("a.expand").addClass("hovered"); $(".project_full").hide(); var selected_tab = $(this).find("a").attr("href"); $(selected_tab).fadeIn(); return false; }); With the HTML: <div class="project first project_gizmoscoop"> <div class="title"> GizmoScoop! <div class="date">2012</div> </div> <a class="expand" title="(Caption)" href="#project_1">GizmoScoop!</a> </div> <div class="project project_sc"> <div class="title"> Striking Code <div class="date">2011</div> </div> <a class="expand" title="(Caption)" href="#project_2">Striking Code</a> </div> The .hovered class is applied to the clicked link (specific styles from an external CSS file). However, everything is being chosen. (See http://www.codeisdna.com for an example). I know what I'm doing wrong (I should be specifying the individual ID's or using HTML5 data attributes), but I'm stuck unnecessarily. I feel like a complete newb right now, that I can't do something this simple (although I've done more advanced stuff).
You simply need to take advantage of jQuery's flexibility (and good programming practice) and reduce your scope accordingly. You're already doing something similar with your variable definition. For example, to target only those a.expand elements inside the instance of .project that's clicked: $(".project").click(function() { $(this).find("a.expand").removeClass("hovered"); ... });
$(".expand").click(function() { $(this).addClass("hovered"); .. });
from plain javascript to dojo framework
I've started to learn the dojo Toolkit and i like it so far, it seems to me easier to understand than jquery/prototype JS. I'm still new at it (and in javascript) and while there is a plethora of docs available on the net i don't really understand how to achieve simple tasks like making a hidden visible with dojo. So to the problem: the html <!-- the numder in id="comment" and in href="javascript:display_comments('')" is the post_id that i want the comments to be fetched for --> <div class="comments"> <a id="comment8" href="javascript:display_comments('8');">comments</a>(21) </div> <div style="visibility: hidden;" id="display_comments8"> </div> <div class="comments"> <a id="comment7" href="javascript:display_comments('7');">comments</a>(13) </div> <div style="visibility: hidden;" id="display_comments7"> </div> <div class="comments"> <a id="comment15" href="javascript:display_comments('15');">comments</a>(20) </div> <div style="visibility: hidden;" id="display_comments8"> </div> the javascript function display_comments(id) { divid = 'display_comments'+id; var element = document.getElementById(divid); if(element.style.visibility == 'hidden') { element.style.visibility='visible' }else if(element.style.visibility == 'visible') { element.style.visibility='hidden'; element.innerHTML=''; } } The parameter for display_comments() in the post_id which then is merged with the words 'display_comments' so to know which div to make visible. How can this be achieved in dojo?
Basically what you want to do here is automate things a bit right? If you attribute your links either by id, like i use below, or some other way (non validatable properties or html5 data-attributes) then you can use dojo.query to find all the nodes in your container and attach an event to them. I gave you a link to the dojo.query syntax page in case you wanted to make your query syntax more specific. After looping through all the a nodes in container and attaching a click event with a handler that passes the node's id (the dojo.partial stuff), you just need to handle the click event. The toggle display uses dojo core to change and modify the style of the node - pretty simple. Based on your example this is how I would change your code. There are a lot of ways you could achieve these results. Personally, I would create templated widgets. Since this code looks repetitive, you could dojo.declare a comment class and dojoattachevents to the links and dojoattachpoint to the hidden node. This way you wouldn't have to dojo.query or dojo.byId since widget would wire all that up for you. You could create one for each and use class syntax to handle the logic. <div id="container"> <div class="comments"> <a id="8">comments</a>(21) </div> <div style="visibility: hidden;" id="display_comments8"> </div> <div class="comments"> <a id="7">comments</a>(13) </div> <div style="visibility: hidden;" id="display_comments7"> <div> dojo.query reference dojo.query("#container a").forEach(function(node) { dojo.connect reference dojo.partial reference dojo.connect(node, 'onclick', dojo.partial(toggleDisplay, node.id)); }); dojo.byId reference dojo.style reference function toggleDisplay(node) { var hiddenNode = dojo.byId('display_comments' + node); var display = dojo.style(hiddenNode).visibility === 'visible' ? 'hidden' : 'visible'; dojo.style(hiddenNode, { visibility: display }); } Working Example jsfiddle example Books we have dojo the definitive guide and mastering dojo and getting startED with dojo. PS all these books are outdated and the best information is found on the test pages/the irc #dojo chat room/and the reference guides.