selected html elements into global object to avoid duplication - javascript

I one day was thinking that I could remove duplication of id this way:
htmlElements = {
$tabs: jQuery('#tabs'),
$tabs1: jQuery('#tabs-1'),
};
and in javascript when need to acceess - use htmlElements.$tabs for example. I was thinking - if the design needs to be changed, it the designers might use different ids and we will need to change things either in design or in javascript code to replace all ids. And this way we would need to replace in one place.
Is it too hardcore or good thing? Cannot find on internet questions about this.
I think I decided to do this after I saw that backbone has $el in the object.

Related

Should I be using classes more than ID's when utilizing jQuery?

As a new web developer, I've been utilizing a lot of resources like StackOverflow to assist me in the learning and development process.
When using jQuery, all of the examples/responses that I've come across so far have only referenced classes, like so:
$('.yourClass')
as opposed to
$('#yourID')
Seeing that class referencing seems to be the trend (I honestly haven't found one author who writes a jQuery to an ID), are there any pitfalls I should be aware of for using ID's w/ jQuery or JS in general? Thanks!
EDIT 1: I'm aware that ID's are for single-items, classes are for accessing multiple items. I'm more interested in why I don't see any jQuery or JS examples referencing ID's. Thank you!
You would have to ask each author on a case-by-case basis, but generally when creating examples, the selector used doesn't matter; what's important is that you have a jQuery collection that you can call a method on.
By using a class selector in the example, you avoid newbie developers claiming that your plugin doesn't work when they try to use it on multiple elements with the same ID. Your example serves the purpose of showing how to use it on one or more elements, rather than just one.
People like to use classes because ids have to be unique across the whole page. When trying to make reusable, pluggable components, id's make this impossible to enforce.
Exception: the new web-components standard allows you to encapsulate ids to just your component.
An ID must be unique, you can have only one (like highlanders).
Classes are used to identify a "type" of object not a specific one.
An obligatory car analogy:
An ID is a license plate, unique to one specific thing #345-abc
The class relates to a whole category of things like .truck
Take note that a selector like $(".something") will actually be capable of producing a list of DOM elements; as it will select all DOM elements with the class of "something"
An ID selector $("#unique") will only ever return one element
Think of your HTML and CSS first.
Using Classes
If you have multiple HTML elements which all will look, feel and behave in the same way, then it is highly recommended to use a class to represent their style and behavior.
Example: rows or columns on a table, navigation buttons which animate in the exact same way, wrapper to images which have the same size throughout your website, etc.
Using ID's
However, if you have a unique HTML element which represents a particular thing or state or action in one of your pages, then that element should contain an id.
Example: pop up modal, a unique looking button, unique sections on your website which you can navigate to by their id, etc.
Then, you can use this behavior in your JavaScript and jQuery or whatever else you like to use.
Further reading
I know that you are fully aware of why we should use ID's or classes.
But the vast majority of answers that are given here, are thinking of a project context.
So, let's say editing a .js file that is linked to the scope of the entire project, the idea here is to be as reusable as possible, so that's why you'll see much more classes references than ID's. Is hard to maintain a project js file that makes reference to different ID's that are abroad the project.
Same thing will apply to css.
I hope the answer is enough, be free to post a comment or suggestions. :-)

Is there a better way to do innerHTML?

I want to know if there is a better way to be doing innerHTML than what I do here. The way I am doing it is causing problems because of the fact that I can't have triple nested quotes. along side that, it is really hard to look at and manage. Thanks!
function buttonClicked(buttonValue)
{
switch (buttonValue)
{
case 1:
soundFolders.innerHTML = "<li onClick='buttonClicked(11);'>Thunder 1</li> <li onClick='buttonClicked(13);'>Light Rain 1</li> <li onClick='buttonClicked(0);'>Back</li>";
break;
case 11:
if(!thunder1Control)
{
thunder1.play();
var thunder1Control = document.createElement("li");
soundList.appendChild(thunder1Control);
thunder1Control.innerHTML = "<h3>Thunder 1</h3> <button class='stopSound' onClick='thunder1.pause(); thunder1.currentTime=0; thunder1Control.parentNode.removeChild(thunder1Control); '>X</button> <button class='volDown' onClick='thunder1.volume -= 0.25;'>-</button> <button class='volUp' onClick='thunder1.volume += 0.25;'>+</button>";
thunder1Control.setAttribute("class", "playingSound");
}
P.S. Do you guys know why the thunder1Control.parentNode.removeChild(thunder1Control) is not working?
To your first question about another way to approach this type of code, "best" is a matter of opinion so I won't really try to address what is best. But, I will give you some alternatives:
Avoid putting code into strings in your HTML. There are all sorts of limitations with that and you generally want to separate code from presentation anyway.
Install event handlers in your code with obj.addEventListener() instead of putting event handlers and code in your HTML.
Use classes and IDs or DOM queries from a particular point in the hierarchy to retrieve specific objects in your page rather than trying to save references to them in global variables. In plain javascript, element.querySelectorAll() is pretty powerful.
In many cases, it's much simpler to just hide and show blocks of HTML using obj.style.display = "none" and obj.style.display = "block" than it is to dynamically create and destroy HTML and this has the added advantage of the HTML is all specified in the page and doesn't have to be shoehorned into a javascript string.
For large blocks of dynamic HTML that wouldn't work well with hide/show for whatever reason, you can dynamically load snippets/templates of HTML from your server using ajax or you dynamically create the HTML using javascript. My first preference is generally hide/show and then if that isn't practical for some reason, it depends upon how much the HTML I want to insert varies based on the state for whether I'd rather load a template or create it dynamically using javascript. If you have large blocks of HTML you have to fit in your javascript, it is messy with quoting, etc... - no way around that if you go that route other than using one quoting scheme for the JS string delimiter and the other in your HTML.
In your particular case, it sure looks like the hide/show method would be simple.
To your second question, this line of code:
thunder1Control.parentNode.removeChild(thunder1Control)
does not work because the thunder1Control variable is long, long out of scope when your click handler is executed because it's a local variable in your buttonClicked() clicked function.
When you put code into a string as part of HTML, it is evaluated in the global scope only so any variables that it tries to reference, must themselves be global in scope.
I'd suggest that you NOT put code into strings in your HTML like that. Use references to actual javascript functions. In that particular case, I'd have to see your HTML to know how to best advise you. If there is only ever one thunder1Control, then I'd suggest you just put an id value on it and retrieve it with document.getElementBtId() when you need it rather than trying to save a reference to it in a variable.
There are essentially two other ways that I can see:
Use a framework that helps with this kind of things. Others have
mentioned jQuery. A commenter is arguing that it might be overkill
to include a framework for just this. I would argue that if you're
doing any javascript at all, you should be using a framework to
make it less terrible. But continue onto suggestion 2 if you
disagree!
You can create each of the elements via plain old javascript and append it to the elements that you need, instead of inserting it directly into innerHTML. ex.
var li = document.createElement("li");
soundFolders.appendChild(li);
etc...
But, honestly, use jQuery with some of the suggestions from others. It's pretty small, and it will heavily clean up all of your javascript. Include it via Google and it will likely already be cached in the users browser.
https://developers.google.com/speed/libraries/devguide#jquery
I think a better alternative is to use jQuery, and then instead of using .html() (equivalent of innerHTML in jQuery), you can create a template with your html and use .load() instead. Works nicer and it's cleaner. And you don't have to worry about triple nesting quotes as you said.
Edit: I'm not sure why I'm getting downvoted so much here... The poster doesn't want to worry about triple nesting quotes. A simple and, to me, elegant solution is to use .load() and to create a template, rather than a really long string of html...

Set variable to HTML elements with certain class?

I'm sure there is a way to set a JavaScript variable to any HTML element with a certain class attached to it? I'm just not sure how to write it. Can anyone help me out?
The best way would be to use a framework, such as jquery, that makes an easy use of (css) selectors, e.g, to select all elements with class my-class do
$('.my-class')
and then apply any code to the list of those elements
edit: don't forget to use the $(document).ready wrapper
you could simply go var x = document.getElementById('somediv'); for example. Now whatever style class pertains to somediv will of course still obtain unless you change it programatically in your javascript.
Hope that helps -- might be able to be more helpful if you give a broader context of what you are trying to accomplish.
To do this without document.getElementsByClassName('myclass') nor $(.'myclass') would be difficult and require some advanced tactics. You would have to recursively generate a list of all DOM objects from the document. While generating the list, every element touched would have to be tested for .className = 'myclass'. This is essentially what jquery does behind the scenes, although I believe on page load it caches the whole DOM for easier querying.

Best way to manipulate dom element attributes with javascript/jQuery

I want some return about dom manipulation. I think we can save elements' status in several ways. For exemple, you want to make an element "inserted", what do i have to use? :
Add css class as "inserted"
Save an attribute with .data("inserted",true)
Push my element in a global array containing all "inserted" elements
...
But what is the best way? Maybe the solution is to use all possibilities. I don't know.
That's a general question. I don't have a specific problem, but i am starting developing a huge javascript application and i want to choose my rules :)
Do you want selected elements to look in a specific way?
--> Use the css-class
Do you want to check whether a specific element is selected at a different place in code?
--> Use .data
Do you want to do something to all selected elements?
--> Use an array.
If you plan to do multiple of the things above, you can also combine the approaches.
If you want a visual element to accompany the status, then the CSS class is the obvious way to go.
Data elements are a perfectly valid way of tagging something as well.
If you want to persist state, then saving element status in a JSON structure may be a good option. The JSON data is the "master model" and the elements are rendered based on its model. The JSON data can be passed to the server or to the next page easily.
This is a hard question to answer generally because it really depends on the needs of your application. How many elements do you need to evaluate at any given time? A dozen? A few thousand? What else do you need to do with these elements when you select them? Basic guidelines are:
Don't add a selected class unless you really need to change the style of the element.
If you need to traverse to an element based on whether it has been selected or not, do not use the data() option.
Do not cache the selected elements in memory (variables or localStorage or whatever) if you don't need them to persist for more than one simple call. The overhead of managing your array of selected elements is only worth it if you have a noticeable performance gain or need to persist the data.
So, what do you really need to do with these elements? With more information about your situation, we can make a better recommendation.
For me this depends on what the use of the status will be...
If layout changes depending on selected, i use a class
JS logic (more than only styling) -> atribute
I hardly use classes to add js logic to elements ... css tends to change more often than the underlying javascript files. In case I use classes in js, I force myself to keep the classnames and selectors in css or just redo all element-selection in both js and css when one needs to change (for instance because of using another library or css templates)
as for your third option, an attribute can give you an array of all selected alemens useing a jquery selector $('*[selected]')
if things get complicated I put enhanced dom elements into "classes"
var InserttMe = function(element){
this.element = element;
this.inserted= false;
};
selectMe.prototype = {
insert: function(){
this.inserted= true;
//do whatever you do with your element
}
}

Any value in JavaScript/HTML Decoupling? if so how?

Lately I've been writing more and more JavaScript for the websites I've been creating. And I can't help but think that I'm doing something wrong, or there has to be a better way.
I have a clean separation of concerns on the server side, but on the client side, I find myself having entire sections of JavaScript that are dependent on specific element id's and class names, etc. For example, on one page, that has a lot of form fields, I may have a section of code that looks like:
$(document).ready(function() {
$("#ButtonID1").button();
$("#Grid").someGridFunction();
$(".data-fields").datepicker();
$(".submit-links").click(function() { this.closest("form").submit(); });
});
What I'd almost prefer is some way for the HTML elements to request to obtain certain functionality. Something like:
<input type="text" data-make="datepicker" />
But even that is flawed, because customization of that would require more and more attributes on the HTML element to detail specifics. I had a similar setup done with KnockoutJS and I really wasn't happy with the HTML that was required.
Maybe something along the lines of this:
<input type="text" data-init="buildDefaultDatePicker" />
where "buildDefaultDatePicker" is a JavaScript function that handles the necessary work.
In the end, the question I have is two fold. Is there any value in separating the JavaScript from the UI in regards to specific element ids and class names. And if so, what patterns, and or methods have you used to achieve this?
(Note, I'm using jQuery syntax above, but I think this question is framework agnostic, so shouldn't matter for the answers)
It looks to me like you've got the right idea already (using classes to apply JavaScript enhancement to specific elements). Using a custom attribute such as data-make or data-init would be just another (more fiddly) way of doing the same thing. The way you have things already, specific classes can be used as the request to obtain certain functionality.
The method I'd advise is keeping a clean separation between your HTML and JavaScript. The JavaScript should always be in external files, and written to target page elements on $(document).ready to provide the requested functionality.
I'd just use a class to signify the elements you want to attach behavior to. It has a semantic meaning, and you aren't coupling the html IDs or their locations into the javascript.
In the likely event that you need some specifics, like say a minimum or maximum date on a date picker, a light sprinkling of data attributes I think is an elegant way to provide it. But anything that would require more than a few data attributes is probably, in reality, a whole new kind of thing that deserves its own class, thus removing the need for the data attributes. For example, you might have a datepicker class, and find yourself constantly providing a minimum date of today to force a future date selection. Well, just make a 'futuredatepicker' class instead.

Categories

Resources