Giving my Hyperlinks custom attributes - javascript

I would like to give all of my URL's attributes. There are probably about 400 on each page. Sometimes only 40, just depending on which type of product is being viewed.
I would like something like this:
Stainless Steel Bolts
How can this be done?
I know that in HTML5 there is some kind of data thing, but I can't find it yet, so maybe I misread something somewhere.
Basically, when any one of those links are clicked, I will (PHP) insert that product into their shopping cart in the database. But, based on the attributes of any given link, I may need to do some calculations/adjustments/etc before I insert them into the DB.
And this seems like the only simple, logical (and somewhat fun) way to go about doing this. But I'm not sure about compatibility between browsers, or whether it's even valid or not.

You're right, it's the data- attribute you're looking for. [random reference]
Your link would look something like this:
<a data-partno="DBF-XJ3" data-qtyType="Box QTY" data-quantity="50">
Demo here: http://jsfiddle.net/wesley_murch/ey2pg/
It's really just a javascript hook, and since jQuery seems to handle it well in all browsers I checked (including IE6), I would say its "safe" to use. As far as I know, you can even make up attributes and it will work with jQuery (although it's not recommended). This is really the best way to avoid abusing rel and title and such (as a lot of people do), just for javascript interaction.
However: I would highly suggest using a <form> with hidden <input>s (and a <button> for easy styling) to submit the values. The other way is broken without javascript, you can enhance it with jQuery afterwards.

You'd do it like this:
$(document).ready(function(){
$("a[href]").each(function(){
if($(this).attr("href") == "link.html"){ //I put a condition here just in case you need one
$(this).attr({
"partno": "DBF-XJ3",
"qtyType": "Box QTY",
"quantity": "50"
});
}
});
});
If all your links need the same attributes, you can remove the condition.
Hope this helps. Cheers
PS: It will work in every browser, however HTML5 recommends to prepend the 'data-' prefix to your custom attributes. Example data-partno="DBF-XJ3"

Related

javascript newbie: what's the right way to apply the same behavior to multiple elements?

I'm taking my first adventure with javascript, and totally without my bearings. I'd like to show a thumbnail that opens a modal with a larger view of the picture (and this is really the only front end fanciness I'll need, so I'm trying to keep it simple). I've copied this code from w3schools, which uses getElementById. It works great for the first image on the page but clicking subsequent images doesn't pop anything up. Reading around on stack overflow it sounds like that's because I'm matching on the id, but each element on the page will/should have a different id (which makes sense).
I saw a post here where the person made the ids unique by appending the element's id. I could do something like that, but I (a) wanted to check if that's kosher and (b) then obviously the id will no longer match, so is there some different attribute I would tack on to match up my HTML with my styles? This must be a common problem- what's the right way to apply the same behavior to multiple elements on a page? For example I can give them
thanks!
UPDATE: based on everyone's feedback below I've modified the code to use getElementByClassName instead of getElementById- see gist here: https://gist.github.com/dianekaplan/1602a7c0a1c1ec6aa103b61d6530ff15
If I'm reading the code correctly, then the important lines for me to change are from line 115 to line 116- (to set the image info based on ClassName, not id)- and replacing 'myImg' with popup' in the style lines 5 and 11, but clicking the first image no longer opens the modal, so I missed something. Anyone see what's wrong that I need for it to work?
You should use a class name (the same in all img) instead of ids and then use getElementsByClassName() to fetch all of them, instead of getElementsById() which gets only one (as ids must be unique).
Then, you should store the full size image's url somehow in order to fetch it regardless of which img was clicked. One way may be using data attributes.
Example:
<img src="thumb1.jpg" data-fullsize="full1.jpg" class="popup">
<img src="thumb2.jpg" data-fullsize="full2.jpg" class="popup">
<img src="thumb3.jpg" data-fullsize="full3.jpg" class="popup">
var elems=document.getElementsByClassName("popup");
for(var i=0;i<elems.length;i++) {
elems[i].onclick=function() {
var fullsize=this.dataset.fullsize;
//open de popup, fullsize has the clicked image url
}
}
Code not tested, for the idea only.
To answer your primary question ID's are "supposed to" [1] be unique so unless you came up with a convention such as a prefix or regex you couldn't easily use them to group elements together.
If you want to group together multiple elements you could use a class, instead, in which case instead of getElementById you'd use getElementsByClassName.
That being said I wouldn't recommend that either; using vanilla JavaScript can be very time-consuming to make a complex application. You will be tempted to merge the UI with all your functionality. This works great for smaller applications but it can become very unruly, particularly if you don't take steps to allow yourself to refactor in the future, in which case you'll be stuck with an application few can easily be trained on and modify.
You are correct to learn the language, though, prior to a framework. JavaScript is especially quirky.
I would suggest if you're looking to create a web application to look into a modern JavaScript framework after learning JavaScript, HTML and CSS. (And focus on having a practice to being able to refactor/upgrade/improve otherwise you'll be stuck in 2016 and it'll be 2020 - you don't have to worry about this immediately, but start learning about how to do that while you're learning the language.)
To find frameworks I would suggest exploring what's out there. Here's an example of one on GitHub. That's probably a hand-coded list. It's also good to explore exhaustive lists, such as just looking at the "most starred" Repositories on GitHub that are written in JavaScript. And of course check elsewhere besides GitHub, too.
I happen to know AngularJS the best and it happens to be one of the most popular but I would recommend for you to explore and find one that has syntax you like. You might find a different one more intuitive. Here's a plunker that shows how to solve that problem in AngularJS.
Notice how all the functionality is separate from the UI and how declarative it is - the main directive has no idea how the images are being rendered - it just says here are some image url's and descriptions:
scope.images = [{
url: 'http://www.w3schools.com/howto/img_fjords.jpg',
description: 'Trolltunga, Norway'
},{
url: 'http://www.w3schools.com/howto/img_fjords.jpg',
description: 'Other Description'
},{
url: 'http://www.w3schools.com/howto/img_fjords.jpg',
description: 'Another Description'
}];
This is what initializes the app: <html ng-app="plunker"> and <main></main> is akin to the "main method" in that it is the component that calls all the other components.
It's much easier to test an app's functionality if you're careful to separate out the presentation concerns from the rest of the app. It will take a while to learn JavaScript and probably any framework, though, so don't expect too much too soon if you're just getting your hands wet in JavaScript - but if you've programmed for a while you already know this :)
(Disclaimer: What I did isn't necessarily the "best practices" as I tried to simplify it a bit so as to not overwhelm OP too much with information, although the added complexity is useful in more advanced scenarios.)
[1] "Supposed to" meaning browsers may do their best to render a page, even it isn't "compliant" HTML. Web Applications suffer from having to have the same code work on different browsers, operating systems and versions of each all implementing the standards (or choosing not to) differently. It's a nightmare if you haven't ran into it, yet.

jQuery and selectors: how can I make sure that there really is the element I'm looking for?

I'm no experienced JavaScript developer (I know quite a lot about Ruby, though), and so far, when I had to implement some lines of JS, it seemed enough to use jQuery and hack together something.
As far as I understand jQuery, it doesn't assume HTML elements to really be there, but it simply executes a query, and if there is a matching element (or many), some stuff is done with it. This works well for generic code which may want to apply some action to some elements on a page (which may be there or not), but when it comes to specific logic, it's a problem.
What do I mean with this? Let me give an example.
Let's suppose I have one single page with one single HTML element (with the ID '#my_element'). For exactly this page I have to run some JS code, and I have to be sure that it finds this element and does the things to it that I want.
Doing this with jQuery, I simply do something like $('#my_element').addTooltip(), which seems fine first: when I hover over the element, a tooltip is displayed.
Let's assume that some months later I already have completely forgotten about this JS script, and I change the ID of the element to something else. What happens? Nothing. I won't notice the problem with the missing tooltip until I stumble over it by accident.
So I wonder how I can make sure that my JS is really applied, which means: the required elements are found, the stuff is done to them, etc.
Is jQuery's philosophy the "wrong" tool for this? Do I need another framework? Maybe something more sophisticated pattern, e.g. something like MVC? I played with KnockoutJS before, and it seems that this may be better for this, as it's bound directly to elements using data-bind attributes, so it fits tighter on the code than jQuery does.
The comments mentioned always checking the .length property before performing actions on returned results (which is probably the best answer,) but in the case of an actual syntax error your statement that "nothing happens" isn't always true.
If you're using Chrome developer tools or a similar tool in another browser (firebug, etc.) you should see the error in the "Console"
You can also turn on javascript debugging for more information. When you call the "addTooltip()" on something which is null (the jQuery collection) you'll see an error pop up in the Console and may get an exception in the debugger.
This is one of the easiest ways to find errors in your client-side javascript.
You could add a specific plugin to verify the existence of a non-zero- length collection, and use that in the chain:
(function ($) {
$.fn.verify = function() {
if (this.length) {
return this;
}
else {
console.log("No elements found with supplied selector.")
}
}
})(jQuery);
$("#myElement").verify().addTooltip();
This does, of course, rely on the verify() plugin being manually applied, there is – to the best of my knowledge – no error-reporting built in to jQuery to automatically enable logging of invalid selectors, or reporting of selectors returning zero elements.

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.

How could I "turn off" a stylesheet?

I am creating a website for a University assignment and we have to concentrate on the accessability functions. I have successfully managed to use resize text buttons but am looking for a way to turn off a css file via a button or link.
I have scoured the net and cannot seem to find very much, I found a good website that had the button I am looking for so hit F12 but it would not display the javascript for it.
Ideally I would like to achieve it without the use of javascript but if there is no other way then I am open to any help that I can get.
I am sorry if this is a simple question but I really did look hard for an answer but to no avail, I am only a first year student so have a long way to go!
This should work
for ( i=0; i<document.styleSheets.length; i++) {
void(document.styleSheets.item(i).disabled=true);
}
Here's a good way to do it quickly from javascript:
Precede all of your CSS rules with the tag body.enabled:
body.enabled p {
}
body.enabled #Myselector {
}
...
Declare your markup as such:
...
<body class="enabled">
...
</body>
...
In your JavaScript, when you want to disable CSS, remove the class "enabled" from the <body> and switch it with something else (say, "disabled"). Use whatever methodology you see fit to do this (jQuery would make this easy, but it can be done without)
You're not really disabling CSS using this, you're just making it so that none of it applies. From a user's standpoint, they likely won't know the difference.
You can do it server side when the user clicks on a "special" link, your server side code simply "skips" the stylesheets elements.
Are you trying to mimick every feature already designed in browsers (T+, T-, no CSS)? Were you asked to make an accessible website or specifically to implement accessibility features? I understand this is an assignment but that's quite a waste of time IMHO, a time that would be better spent on implementation of WCAG 2.0 recommendation. (I use the "Accessiweb" methodology a lot).
My first idea was to deconstruct existing CSS like Universal IE6 does for IE6 (you just have to remove the conditional comments and aim to every browser) but #kappa solution seems better as in both cases you must have access to source code.

Why is it bad practice to use links with the javascript: "protocol"?

In the 1990s, there was a fashion to put Javascript code directly into <a> href attributes, like this:
Press me!
And then suddenly I stopped to see it. They were all replaced by things like:
Press me!
For a link whose sole purpose is to trigger Javascript code, and has no real href target, why is it encouraged to use the onclick property instead of the href property?
The execution context is different, to see this, try these links instead:
Press me! <!-- result: undefined -->
Press me! <!-- result: A -->
javascript: is executed in the global context, not as a method of the element, which is usually want you want. In most cases you're doing something with or in relation to the element you acted on, better to execute it in that context.
Also, it's just much cleaner, though I wouldn't use in-line script at all. Check out any framework for handling these things in a much cleaner way. Example in jQuery:
$('a').click(function() { alert(this.tagName); });
Actually, both methods are considered obsolete. Developers are instead encouraged to separate all JavaScript in an external JS file in order to separate logic and code from genuine markup
http://www.alistapart.com/articles/behavioralseparation
http://en.wikipedia.org/wiki/Unobtrusive_JavaScript
The reason for this is that it creates code that is easier to maintain and debug, and it also promotes web standards and accessibility. Think of it like this: Looking at your example, what if you had hundreds of links like that on a page and needed to change out the alert behavior for some other function using external JS references, you'd only need to change a single event binding in one JS file as opposed to copying and pasting a bunch of code over and over again or doing a find-and-replace.
Couple of reasons:
Bad code practice:
The HREF tag is to indicate that there is a hyperlink reference to another location. By using the same tag for a javascript function which is not actually taking the user anywhere is bad programming practice.
SEO problems:
I think web crawlers use the HREF tag to crawl throughout the web site & link all the connected parts. By putting in javascript, we break this functionality.
Breaks accessibility:
I think some screen readers will not be able to execute the javascript & might not know how to deal with the javascript while they expect a hyperlink. User will expect to see a link in the browser status bar on hover of the link while they will see a string like: "javascript:" which might confuse them etc.
You are still in 1990's:
The mainstream advice is to have your javascript in a seperate file & not mingle with the HTML of the page as was done in 1990's.
HTH.
I open lots of links in new tabs - only to see javascript:void(0). So you annoy me, as well as yourself (because Google will see the same thing).
Another reason (also mentioned by others) is that different languages should be separated into different documents. Why? Well,
Mixed languages aren't well supported
by most IDEs and validators.
Embedding CSS and JS into HTML pages
(or anything else for that matter)
pretty much destroys opportunities to
have the embedded language checked for correctness
statically. Sometimes, the embedding language as well.
(A PHP or ASP document isn't valid HTML.)
You don't want syntax
errors or inconsistencies to show up
only at runtime.
Another reason is to have a cleaner separation between
the kinds of things you need to
specify: HTML for content, CSS for
layout, JS usually for more layout
and look-and-feel. These don't map
one to one: you usually want to apply
layout to whole categories of
content elements (hence CSS) and look and feel as well
(hence jQuery). They may be changed at different
times that the content elements are changed (in fact
the content is often generated on the fly) and by
different people. So it makes sense to keep them in
separate documents as well.
Using the javascript: protocol affects accessibility, and also hurts how SEO friendly your page is.
Take note that HTML stands for Hypter Text something something... Hyper Text denotes text with links and references in it, which is what an anchor element <a> is used for.
When you use the javascript: 'protocol' you're misusing the anchor element. Since you're misusing the <a> element, things like the Google Bot and the Jaws Screen reader will have trouble 'understanding' your page, since they don't care much about your JS but care plenty about the Hyper Text ML, taking special note of the anchor hrefs.
It also affects the usability of your page when a user who does not have JavaScript enabled visits your page; you're breaking the expected functionality and behavior of links for those users. It will look like a link, but it won't act like a link because it uses the javascript protocol.
You might think "but how many people have JavaScript disabled nowadays?" but I like to phrase that idea more along the lines of "How many potential customers am I willing to turn away just because of a checkbox in their browser settings?"
It boils down to how href is an HTML attribute, and as such it belongs to your site's information, not its behavior. The JavaScript defines the behavior, but your never want it to interfere with the data/information. The epitome of this idea would be the external JavaScript file; not using onclick as an attribute, but instead as an event handler in your JavaScript file.
Short Answer: Inline Javascript is bad for the reasons that inline CSS is bad.
The worst problem is probably that it breaks expected functionality.
For example, as others has pointed out, open in new window/tab = dead link = annoyed/confused users.
I always try to use onclick instead, and add something to the URL-hash of the page to indicate the desired function to trigger and add a check at pageload to check the hash and trigger the function.
This way you get the same behavior for clicks, new tab/window and even bookmarked/sent links, and things don't get to wacky if JS is off.
In other words, something like this (very simplified):
For the link:
onclick = "doStuff()"
href = "#dostuff"
For the page:
onLoad = if(hash="dostuff") doStuff();
Also, as long as we're talking about deprecation and semantics, it's probably worth pointing out that '</a>' doesn't mean 'clickable' - it means 'anchor,' and implies a link to another page. So it would make sense to use that tag to switch to a different 'view' in your application, but not to perform a computation. The fact that you don't have a URL in your href attribute should be a sign that you shouldn't be using an anchor tag.
You can, alternately, assign a click event action to nearly any html element - maybe an <h1>, an <img>, or a <p> would be more appropriate? At any rate, as other people have mentioned, add another attribute (an 'id' perhaps) that javascript can use as a 'hook' (document.getElementById) to get to the element and assign an onclick. That way you can keep your content (HTML) presentation (CSS) and interactivity (JavaScript) separated. And the world won't end.
I typically have a landing page called "EnableJavascript.htm" that has a big message on it saying "Javascript must be enabled for this feature to work". And then I setup my anchor tags like this...
<a href="EnableJavascript.htm" onclick="funcName(); return false;">
This way, the anchor has a legitimate destination that will get overwritten by your Javascript functionality whenever possible. This will degrade gracefully. Although, now a days, I generally build web sites with complete functionality before I decide to sprinkle some Javascript into the mix (which all together eliminates the need for anchors like this).
Using onclick attribute directly in the markup is a whole other topic, but I would recommend an unobtrusive approach with a library like jQuery.
I think it has to do with what the user sees in the status bar. Typically applications should be built for failover in case javascript isn't enabled however this isn't always the case.
With all the spamming that is going on people are getting smarter and when an email looks 'phishy' more and more people are looking at the status bar to see where the link will actually take them.
Remember to add 'return false;' to the end of your link so the page doesn't jump to the top on the user (unless that's the behaviour you are looking for).

Categories

Resources