Storing object ID in HTML document: id vs data-id vs? - javascript

I would like to have an opinion on storing RESTful object IDs in document for accessing it later from JavaScript.
Theoretically speaking using id for addressing elements in HTML doesn't cut it anymore. Same element can be repeated twice on the page say in "Recent" and "Most Popular" queries which breaks the main point of using id.
HAML even has this nice syntax sugar:
%div[object]
becomes:
<div class="object" id="object_1">
But like I said, seems that it is not a good approach. So I am wondering what is the best way to store objects id in DOM?
Is this the current proper approach?
<div data-id="object_1">

An ID is intended to uniquely identify an element, so if you have a case where you want to identify two or more elements by some common identifier, you can use ID but it may not be the best option in your case.
You can use IDs like:
<div id="d0">Original Div</div>
<div id="d0-0">Copy of original div</div>
<div id="d1">Another original Div</div>
<div id="d1-0">Another copy of original div</div>
<div id="d1-1">Another copy of original div</div>
and get all the d1 elements using:
document.querySelectorAll('[id^=d1]');
or just d1 divs:
document.querySelectorAll('div[id^=d1]')
You could also use a class:
<div id="d0" class="d0">Original Div</div>
<div id="..." class="d0">Copy of original div</div>
<div id="d1" class="d1">Another original Div</div>
<div id="..." class="d1">Another copy of original div</div>
<div id="..." class="d1">Another copy of original div</div>
and:
document.querySelectorAll('.d1')
Or use data- attributes the same way. Whatever suits.
You can also have a kind of MVC architecture where an object stores element relationships through references based on ID or whatever. Just think outside the box a bit.

The purpose why data-selectors where introduces is because the users neednt want to use class or anyother attributes to store value.Kindly use data-selectors itself. In order to make it easy to access them use attributes selector i.e. [attribute='value']. PFB the fiddle for the same and also the example
jsfiddle
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-git2.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body onload="call()">
<div id="1" data-check='1'></div>
<div id="2" data-check='1'>sdf</div>
<div data-check='1'>sdf</div>
<div data-check='1'>sdf</div>
<div data-check='1'>sdf</div>
</body>
</html>
function call()
{
$("#1").html($('[data-check="1"]').length);
$("#2").html( document.querySelectorAll('[data-check="1"]').length);
}
Output: 5 5 sdf sdf sdf

#RobG is right by using 'class' you can get array of elements in JavaScript as-
var divs=document.getElelementsByClassName("className");
\\And you can loop through it(`divs[i]`).
AND according to #RobG and #Barmar data-* attribute is also a good option.
But here is some point(just point, not negative or positive, its totally depends on your application need) I want to discuss:
1] data-* element is HTML5's new attribute. Documentation
2] To retrieve elements in javascript, You need to use jQuery or more bit of JavaScript, coz all direct function available have specific browser support:
Like document.querySelector("CSS selector"); IE8+
document.getElementsByClassName("className"). IE9+
document.querySelectorAll("CSS selector"); etc.
So, basically for this point you need to choose according to your app need and browser compatibility.
3] Performance issue is also there on selecting by data-* attribute... Source
But, generally and if we go for latest application and selecting HTML5, data-* attribute + jQuery is a good option.

I was wondering about this too. Here's my POV using an example component.
CSS - styling across all buttons
Elements should not be referenced in JS using CSS classes because if you have multiple buttons that need to function differently, adding unique CSS classes for each component will get messy.
<div class="my-component">
JS - Grab the component when it can only appear once on a page
While browsers may handle multiple id okay, it would harm maintenance since this would be unexpected behavior from an id.
<div id="my-component">
const myComponent = document.querySelector('#my-component')
JS - Grab the component when it can appear multiple times on a page
ref or data-id could both work. ref has been popularized by React and Vue, so it may be more familiar to developers.
<div ref="my-component">
const myComponents = document.querySelectorAll('[ref="my-component"]')
or
<div data-id="my-component">
const myComponents = document.querySelectorAll('[data-id="my-component"]')

Related

How to access inner html element present in actual html via javascript

I need to get the object of second level html element in my page.
<html>
<div id="out">
jasoidjisa
<html>
<head>//This object
<div id="in">
hihisdhi
</div>
</head>
</html>
</div>
<script>
alert(document.getElementsByTagName('html'));
</script>
Help me to access this html element via js
HTML is a reserved tag name and so you can't use it in the manner in which you have used it here. Which particular value from above are you trying to get exactly ? It might make sense to use the <div> tag with a class or I'd to identify it instead. If you specify which value you are specifically looking to get I can write up a theoretical solution.
vsank7787 was totally correct. Maybe you could use iFrames instead of nested html inside a HTML document since html is a reserved keyword.

Extract all classes from body element of AJAX-ed page and replace current page's body classes

I am in the process of AJAX-ing a WordPress theme with a persistent music player. Wordpress uses dynamic classes on the <body> tag. The basic structure is as follows:
<html>
<head>
</head>
<body class="unique-class-1 unique-class-2 unique-class-3">
<div id="site-container">
<nav class="nav-primary">
Other Page 01
Other Page 02
</nav>
<div class="site-inner">
<p>Site Content Here</p>
</div>
</div>
<div id="music-player"></div>
</body>
</html>
I am currently successfully loading the content of /other-page-01/, /other-page-02/, etc, using load('/other-page-01/ #site-container'). However, I need to extract all <body> classes from the AJAX loaded page and replace the current page's <body> classes with them dynamically.
Note: Replacing the entire <body> element is not an option due to the persistent <div id="music-player">. I've tried jQuery.get(), but couldn't get it to work.
How do I extract the <body> classes from the AJAX requested page and replace the current page's <body> classes with them?
I am not very familiar with jQuery or Javascript, so the exact code would be extremely helpful. Any help is greatly appreciated.
Thanks,
Aaron
My typical solution would have been to tell you to throw the AJAX code in to a jQuery object and then read it out like normal:
$(ajaxResult).attr('class');
Interestingly though, it appears you can't do this with a <body> element.
I'd say the easiest solution (if you have control over the resulting HTML) is to just use some good ol' regex:
var matches = ajaxResult.match(/<body.*class=["']([^"']*)["'].*>/),
classes = matches && matches[1];
I say "if you have control over the resulting HTML", because this relies on the HTML being reasonably well formed.
The other method would involve parsing it as a DOMDocument and then extracting what you need, but this would take a lot more and is usually overkill in simple cases like this.
Convert the body within your returned html to a div with a specific ID, then target that id to get the classes of the body (which is now a div.)
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("#re_body").attr("class");
Of course, if the body has an id, this will conflict with it, so an arbitrary data attribute might be less likely to break.
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class");
http://jsfiddle.net/N68St/
Of course, to use this method, you'll have to switch to using $.get instead.
$.get("/other-page-01/",function(ajaxResult){
var modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
alert($(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class"));
// the following line replicates what `.load` was doing.
$(someElement).append( $("<div>").html(ajaxResult).find("#site-container") );
});

What happen if I declare the id in CSS is duplicated to id in Javascript?

In case, I already link to CSS with the same id that I use with javascript in the same HTML page. What will happen?
<html>
<head>
<title>My JavaScript page</title>
<script type="text/javascript" src="script.js">
</scrip>
<link rel="stylesheet" type="text/css" href="mystyle.css">
</head>
<body>
<h1 id="show">
</h1>
In case, id, show, has declare both in javascript and css. What will happen?
IDs are a concept of HTML to mark an element in the document as unique. Thus it may be used in the whole document only once. If you are obeying this rule, you will be fine, otherwise you will get into trouble.
Javascript and CSS are two completely different technologies. You can use the HTML ID to target the element and apply CSS styles or work with it in some way via JS. Thus, JS and CSS do not directly interfere with each other.
However, you can change the ID with javascript or move it to another element, resulting in your css not applying it's rules anymore to the initial element (or applying them to another element). Also, you can apply styling via javascript, which might interfere with css.
Other than these described problems you can use the ID in both CSS and JS at will.
If you are intending to use the same ID for two elements . It is a bad idea but if you are updating an already existing ID with Javascript there should not be any problem . Also if you are using two elements with same ID make a separate class for both of the elements and use ID for differentiating between them
<div class="one" id="diff1">
</div>
<div class="one" id="diff2">
</div>
Normally nothing is happen, its depending upon your javascript function. To set font color, alignment to use class instead of id via css. For show/hide some div content mean you can use id within your javascript or jquery function, eventhough you can use class is not a mistake.

Target a class whether or not it has a number in the name

I'm struggling a bit with this : let's say I have a class in the body <body class="video page"> and in my page I have a pagination which add a number like this <body class="video-2 page"> at each page. I would like to target the class video whether or not it has a number in order to apply some jquery if the condition is filled.
How do I do that?
You can use this attribute selector to select elements that have a class attribute starting with video-:
[class^="video-"]
But for this to work, you’d have to make sure that the video- class is the first one in the element’s class attribute (see http://jsfiddle.net/Czyep/).
It might be better to have the video class and the pagination class be separate, e.g.:
<body class="video page-2 page">
I would split the classes like class="video two page" so that you can still address both classes separately. Nevertheless you can do something like
$('body[class*=video]')
$("body").not(".video");
Should select all bodies wich end with a number. You could also do:
if($("body").is("[class$='video-'")) {}
have you tried something like this this?
$('.video,.video-'+pageNumber).dosomething()
You can use the attribute starts with selector:
$("body[class^='video']");
Assuming I have understood your question correctly I would suggest that you use concatenation in your selector.
I assume that you are aware that you have specified two classes on your body tag namely video and page or video-2 and page. And I therefore assume that page is significant in your selection and should be included in your selector.
Therefore I would use this syntax whilst not as neat as some syntax it is very clear what is going on. Obviously you would need to incorporate this into what ever logic is driving your page selection.
var suffix = "";
$(".video" + suffix + ".page").dosomething(); // select <body class="video page">
suffix = "-2";
$(".video" + suffix + ".page").dosomething(); // select <body class="video-2 page">
Note that there should be no space between the classes in the selector because they have been declared in the same tag in the html.
Had you specified something like
<body class="video"> // body wrapper
<div class="page"> // page wrapper
</div>
</body>
Then a space would be required as you are then looking to match on div page within body with class video or video-2 as appropriate.
suffix = "-2";
$(".video" + suffix + " .page").dosomething(); // select <body class="video-2"><div class="page">

Can't fire click event on the elements with same id

Could you help me to understand - where I made the mistake. I have the following html code:
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
and the following js code (using jQuery):
$('#getInfo').click(function(){
alert('test!');
});
example here
"Click" event fired only on first link element. But not on others.
I know that each ID in html page should be used only one time (but CLASS can be used a lot of times) - but it only should (not must) as I know. Is it the root of my problem?
TIA!
upd: Big thx to all for explanation!:)
Use a class for this (and return false in your handler, not inline):
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
$('.getInfo').click(function(){
alert('test!');
return false;
});
http://jsfiddle.net/Xde7K/2/
The reason you're having this problem is that elements are retrieved by ID using document.getElementById(), which can only return one element. So you only get one, whichever the browser decides to give you.
While you must, according to the W3 specifications, have only one element with a given id within any document, you can bypass this rule, and the issues arising from the consequences if document.getElementById(), if you're using jQuery, by using:
$('a[id="getInfo"]').click(function() {
alert('test!');
return false;
});
JS Fiddle demo.
But, please, don't. Respect the specs, they make everybody's life easier when they're followed. The above is a possibility, but using html correctly is much, much better for us all. And reduces the impact of any future changes within the browser engines, jQuery or JavaScript itself.
It must only be used once or it will be invalid so use a class instead, return false can also be added to your jQuery code as so: -
$('.getInfo').click(function(){
alert('test!');
return false;
});
<a href="#info-mail.net" **class**="getInfo" ....
First id's are for one element only, you should have same id for several divs.
you can make it class instead.
your example changed:
<div class="container">
<a href="#info-mail.ru" class="getInfo" >Info mail.ru</a>
</div>
<div class="container">
<a href="#info-mail.com" class="getInfo" >Info mail.com</a>
</div>
<div class="container">
<a href="#info-mail.net" class="getInfo" >Info mail.net</a>
</div>
$('.getInfo').click(function(ev){
ev.preventDefault(); //this is for canceling your code : onClick="return false;"
alert('test!');
});
You can use the same id for several element (although the page won't validate), but then you can't use the id to find the elements.
The document.getElementById method only returns a single element for the given id, so if you would want to find the other elements you would have to loop through all elements and check their id.
The Sizzle engine that jQuery uses to find the elements for a selector uses the getElementById method to find the element when given a selector like #getInfo.
I know this is an old question and as everyone suggested, there should not be elements with duplicate IDs. But sometimes it cannot be helped as someone else may have written the HTML code.
For those cases, you can just expand the selector used to force jQuery to use querySelectorAll internally instead of getElementById. Here is a sample code to do so:
$('body #getInfo').click(function(){
alert('test!');
});
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
</body>
However as David Thomas said in his answer
But, please, don't. Respect the specs, they make everybody's life easier when they're followed. The above is a possibility, but using html correctly is much, much better for us all. And reduces the impact of any future changes within the browser engines, jQuery or JavaScript itself.

Categories