I have some bullet points which I want to show more text below them on clicking them. They are both two separate Ps that are paired together by sharing a common id. So, what I am trying to do below is to find the element with (id_same_as_this.class), so that the element with the class "expand" as well as the id that matches the clicked on P is toggled. Does that make sense?
$(document).ready(function(){
$(".expandable").click(function(){
$(this.attr('id')+"."+"expand").toggle(800);
});
});
I only ask if the above code could be made to work because it would make the expandable bullet points in my web page significantly less code intensive than a lot of the examples I have read about.
$(this.attr('id')+"."+"expand").toggle(800);
Must be
$("#" + this.id +".expand").toggle(800);
You missed the # there. That said, you shouldn't ever have a common ID. By definition IDs are meant to be unique. If you have the same ID on multiple elements, while it may work now on the browsers you try, you have no guarantee it won't break in the next rev of jQuery (or Chrome, or Konqueror, or iOS Safari). There's also no reason to do it. You could just use classes or data-* attributes.
Yes this will work but you need a # before the ID
They are both two separate Ps that are paired together by sharing a common id.
IDs are unique. Two elements can't share a common ID, as that defeats the whole purpose of having a unique identifier. JavaScript assumes that you're using valid HTML, so document.getElementById() will return only the first element with a matching id. By using non-unique IDs, things will start breaking in unpredictable ways:
$('#foo').find('.bar') // Won't search past first #foo
$('#foo .bar') // Will search past first #foo in IE8+
Try restructuring your HTML to make this task easier. Maybe you could do something like this:
<ul id="bullets">
<li>
<h2>Title</div>
<div>Text</div>
</li>
</ul>
And then use a simple event handler:
$('#bullets h2').click(function() {
$(this).next().toggle(800);
});
You don't need id values for this at all (which is good, as from the comments on hungerpain's answer, you're using the same id value on more than one element, which is invalid).
Just do this:
$(document).ready(function(){
$(".expandable").click(function(){
$(this).find(".expand").toggle(800);
});
});
That will find the element with the class expand within the expandable that was clicked. No relying on unspecified behavior of selectors.
If you really need that data on the expandable, just put it in a data-* attribute. So instead of this invalid structure:
<!-- INVALID -->
<div id="foo27" class="expandable">
<div class="expand">...</div>
</div>
<div id="foo27" class="expandable">
<div class="expand">...</div>
</div>
Do this
<!-- VALID -->
<div data-id="foo27" class="expandable">
<div class="expand">...</div>
</div>
<div data-id="foo27" class="expandable">
<div class="expand">...</div>
</div>
Use the above code to do the expansion. If you need the value, use .attr("data-id") or .data("id") to get it.
Related
Imagine that I have this HTML structure:
<div id="bodyRead">
...
<div id="List"></div>
</div>
...
<div id="bodyWrite">
...
<div id="List"></div>
</div>
As you can see, I have the #List inside two different divs (bodyRead and bodyWrite). For a lighter code, I preferred to work with id instead of class (even knowing that duplicate IDs isn't valid, the code makes more sense to me), and selecting the #List on jQuery like this:
$('#bodyRead #List').off('click').on('click', function() ...
$('#bodyWrite #List').off('click').on('click', function() ...
works. I'm always taking care of make duplicate IDs only on child divs, where I can separate them by their parent div on jQuery selector.
Is this approach very wrong? I mean, this can get me in trouble?
don't duplicate your Id even in child element .. change it to class="List"
then you can use
$('.List').on('click',function(){
var getparent = $(this).parent().attr('id');
alert(getparent);
});
and if class="List" not first level child of any of #bodyRead or #bodyWrite
add class to it
<div id="bodyRead" class="mainDiv">
<div id="bodyWrite" class="mainDiv">
and then use
$('.List').on('click',function(){
var getclosest = $(this).closest('.mainDiv').attr('id');
alert(getclosest);
});
You should expect that CSS and JavaScript (including jQuery and other frameworks) behave in accordance with the HTML specifications. ID must be unique, multiple instances of the same ID is not supported. See below:
From HTML 4.01 spec:
id = name [CS] This attribute assigns a name to an element. This name
must be unique in a document.
class = cdata-list [CS] This attribute
assigns a class name or set of class names to an element. Any number
of elements may be assigned the same class name or names. Multiple
class names must be separated by white space characters.
http://www.w3.org/TR/html401/struct/global.html#h-7.5.2
This is from the HTML 5 spec:
3.2.5.1 The id attribute
The id attribute specifies its element's unique identifier (ID). [DOM]
The value must be unique amongst all the IDs in the element's home
subtree and must contain at least one character. The value must not
contain any space characters.
There are no other restrictions on what form an ID can take; in
particular, IDs can consist of just digits, start with a digit, start
with an underscore, consist of just punctuation, etc.
An element's unique identifier can be used for a variety of purposes,
most notably as a way to link to specific parts of a document using
fragment identifiers, as a way to target an element when scripting,
and as a way to style a specific element from CSS.
Identifiers are opaque strings. Particular meanings should not be
derived from the value of the id attribute.
Well i feel this is a bad approach because the browser creates the DOM(document object model) for the page, which takes into consideration that each Id has a unique value.It would be hard to play with the duplicate Id's in javascript when you want to manipulate you need to consider parent as well as child id each time. So its better to use classes instead.
Although id selectors are meant to be unique your code will work as long as you make sure to use correct nesting. In other words #bodyRead #List and #bodyWrite #List are perfectly fine as long as you don't create ambiguity by leaving out the parent selectors to #List.
Still, using multiple identical ids on the same page is just asking for trouble. You should reconsider switching to class selectors or reevaluate if it is really worth the potential trouble of sticking with your original idea.
You certainly should not use duplicate id's in an html page. If you have a similar concept within two different div's then class makes more sense anyway. So change the List ids to classes and then you can access them like this:
$('#bodyRead .List').off('click').on('click', function() ...
$('#bodyWrite .List').off('click').on('click', function() ...
Even if your code works now due to how jQuery works, because the html specifications say not to do this, you can not know for certain that your code will continue to work in the future.
<div class="col-1-3">
<div class="click"></div>
</div>
<div class="col-1-3">
</div>
<div class="col-1-2">
</div>
Using jQuery, I need to select the col-1-2 div when a user clicks on the "click" div. I need to replace col-1-2 with col-1-3. So far, I have tried a variety of methods using parent();, next();, find(); etc. etc. Right now, I looking into:
$(".click").parent().next(".col-1-2").removeClass("col-1-2").addClass("col-1-3");
That obviously doesn't work but I am not sure where to go from here.
next will only look at the immediate next element. You need to use nextAll to test all the following siblings.
Using this instead of a selector will make sure that you are dealing with the div that was actually clicked rather than another one with the same class name.
$(this).parent().nextAll(".col-1-2").removeClass("col-1-2").addClass("col-1-3");
You may also wish to filter the results to apply the change to only the first match.
One more slightly shorter version:
$(this).parent().siblings(".col-1-2").toggleClass("col-1-2 col-1-3");
$.fn.toggleClass can be used instead or combination of removeClass + addClass: col-1-2 will be removed and col-1-3 will be added.
I have several div with the .item class and want to change the css if the id is 1
</div>
<div class="item" id="0">
</div>
$('.item').each(function(i){
var estatus = $(this).attr('id');
if (estatus == '1')
// change only item with id = 1
});
Just modify your selector...
$('#1').css('whatever', 'yep');
Please see the comments section to see why this works in this scenario, but you're gonna have bad time if selecting it in a stylesheet. I'd recommend using the method in T.J.'s answer, because of jQuery ever switch to funnelling these calls through querySelectorAll(), it will blow up).
My recommendation is to not use id attributes that start with a number.
With CSS, it's awkward to use id values starting with a digit; the simplest thing is to avoid using them.
But with what you have, you can do this:
$(".item[id='1']").css(/*...*/);
Just using #1 as a selector may work in certain select situations provided they don't rely in CSS parsing, but is invalid. If you must have an id value starting with a digit, to use it with a CSS selector, you have to escape it. The escaped version of #1 is #\31, which gets even more awkward when written as a JavaScript string: $("#\\31").css(/*...*/);.
But this works and is in-spec:
$("#\\31").css(/*...*/);
This works in jQuery as of the current version and is not in spec:
$("#1").css(/*...*/);
It could stop working at any time, however, as it's not in-spec, and breaks if you combine it with various things.
During the web development i encountered with many problems and resolved it but these problems gave me a thought which i want to share and would like to know your view.
Which One is efficient Class Or ID : Both has own specification but i think Class is more convenient over ID (if you are dealing with thousands of IDs.)
I know Id is quite efficient for DOM Traversing but what if you have hundreds of elements with IDs, How do you manage ?
Using CLASS : One class can be derived by many elements and the individual elements can be dealt by using "this" object.
I am curious to know your view OR how do you handle the project/projects when you have many-many elements with ID or Class name
<div class="example" onclick="function click(this);"> </div>
<div class="example" onclick="function click(this);"> </div>
<div class="example" onclick="function click(this);"> </div>
function click(obj){
alert(obj.classname + "We can access any individual element by using Object");
}
<div id="exm_1"> </div>
<div id="exm_2"> </div>
<div id="exm_3"> </div>
but in case of ID, we go through each ID
I liked a few guidelines that are put together by one of my managers, I would like to mention them here:
Start with the following common sense guidelines, and apply them to both JavaScript selectors and CSS selectors.
Use an ID if:
You are certain that the element only
appears once in the whole page.
The desired style or JS behavior is
specific to only one area of the
whole page.
Typical ID Examples:
Large container divs for entire
sections of the page ("#interior",
"#global-status", "#tree-container")
Links or buttons with special names
and purposes ("#add-new-report",
"#preview-popup")
Use a class if:
It is possible for the element to
appear multiple times in the same
document.
The desired style or JS
behavior is general and is applicable
to multiple elements.
Typical Class Examples:
Reusable interface patterns
(".action-links", ".title-bar",
".h1-with-border")
Element states
(".current-selected", ".highlighted")
You should follow this general guidelines:
2) Use a class when you need many elements to share some common behaviour, or when there's currently only one element but you're not sure if there will be more with the same behaviour in the future.
1) Use an Id when an element needs unique identification and you're sure there will be only one with it (think in the future code changes). There should never, never be 2 or more elements with the same id.
Hope this helps. Cheers
It seems pretty common to want to let your javascript know a particular dom node corresponds to a record in the database. So, how do you do it?
One way I've seen that's pretty common is to use a class for the type and an id for the id:
<div class="thing" id="5">
<script> myThing = select(".thing#5") </script>
There's a slight html standards issue with this though -- if you have more than one type of record on the page, you may end up duplicating IDs. But that doesn't do anything bad, does it?
An alternative is to use data attributes:
<div data-thing-id="5">
<script> myThing = select("[data-thing-id=5]") </script>
This gets around the duplicate IDs problem, but it does mean you have to deal with attributes instead of IDs, which is sometimes more difficult. What do you guys think?
Note that an ID cannot start with a digit, so:
<div class="thing" id="5">
is invalid HTML. See What are valid values for the id attribute in HTML?
In your case, I would use ID's like thing5 or thing.5.
<div class="thing" id="myapp-thing-5"/>
// Get thing on the page for a particular ID
var myThing = select("#myapp-thing-5");
// Get ID for the first thing on the page
var thing_id = /myapp-thing-(\d+)/.exec ($('.thing')[0].id)[1];
You'll be giving up some control of the DOM
True, nothing will explode, but it's bad practice. If you put duplicate ids on the page you'll basically loose the ability to be sure about what you're getting when you try to access an element by its id.
var whoKnows = document.getElementById('duplicateId');
The behavior is actually different, depending on the browser. In any case, you can use classNames for duplicate values, and you'll be avoiding the problem altogether.
The browser will try to overlook faults in your markup, but things become messy and more difficult. The best thing to do is keep your markup valid. You can describe both the type of the element and its unique database id in a className. You could even use multiple classNames to differentiate between them. There are a lot of valid possibilities:
<div class="friend04"/>
<div class="featuredFriend04" />
or
<div class="friend friend04" />
<div class="featuredFriend friend04" />
or
<div class="friend objectId04" />
<div class="groupMember objectId04" />
or
<div class="friend objectId04" />
<div class="friend objectId04" id="featured" />
These are all completely legitimate & valid snippets of XHTML. Notice how, in the last snippet, that I've still got an id working for me, which is nice. Accessing elements by their id is very quick and easy, so you definitely want to be able to leverage it when you can.
You'll already spend enough of your time in javascript making sure that you've got the right values and types. Putting duplicate ids on the page will just make things harder for you. If you can find ways to write standards-compliant markup, it has many practical benefits.
IDs should be unique according to the standards and whilst most browsers don't barf when handed duplicate IDs it would not be a good idea to rely on that always being the case.
Making the ID unique by adding a type name to the ID would work but you need to ask why you need it. Giving an element an id is very useful when the element needs to be found, getElementById is very fast. The reason its fast it that most browsers will build an index of IDs as its loads the DOM. However if you have zillions of IDs that you never actually need to use in something like getElementById then you've incurred a cost that is never paid back.
I think you may find most of the time you want the object ID in an event fired by the element or one of its children. In which case I would use an additional attribute on the element and not the ID attribute.
I would leave class attribute to do what its meant to do and not overload it with identification duties.
Considering the fact that you can have multiple classes per element, couldn't you create a unique identifier as an additional class per element? That way, there could be more than one element with the same "id" without HTML ID attribute collisions.
<div class="thing myapp-thing-5" />
<div class="thing myapp-thing-668" />
<div class="thing myapp-thing-5" />
It would be easy to then find these nodes, and find their corresponding DB record with a little string manipulation.
In HTML5, you could do it like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
window.addEventListener("DOMContentLoaded", function() {
var thing5 = document.evaluate('//*[#data-thing="5"]',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE ,null);
alert(thing5.singleNodeValue.textContent);
}, false);
</script>
</head>
<body>
<div data-thing="5">test</div>
</body>
</html>
If you set non-standard properties, be sure to either set them programmatically (as everything will be legal that way) or go through the trouble of revising the dtd !-)
But I would use an ID with a meaningful word prepending the DB-id and then use .getElementById, as every necessary informtion is at hand ...
Non-standard attributes are fine, if you're using XHTML and take the time to extend the DTD you're using to cover the new attributes. Personally, I'd just use a more unique id, like some of the other people have suggested.
I don't like John Millikin's solution. It's gonna be performance-intensive on large datasets.
An optimization on his code could be replacing the regular expression with a call to substring() since the first few characters of the id-property are constant.
I'd go with matching class and then a specific id though.
Keeping track of your data via the DOM seems shaky to me; remember, those IDs are global variables, so if there's any chance somebody else's script can find its way onto your page, it's vulnerable. For best results, load your data into an object within an anonymous function and write the table (or the big nested list of DIVs) afterwards.