Show/hide in javascript when no html access - javascript

I have this:
<div id="myid1">Text 1</div>
<div id="myid2">Text 2</div>
<div id="myid3">Text 3</div>
and I would hide all these elements by default. Then when I click on a link, I would like show all them at once. I looked for some solution in Javascript but it seem is not possible to declare multiple ID when using document.getElementById.
Precision: I seen many solution who suggest to use class instead ID. The problem is I work with an external application integrated in my site and I have access partially to html, but I can set javascript code inside a dedicated JS file.

You could create a function that retrieves several elements by their id, and simply iterate over that collection of elements to hide or show them:
function getElementsByIds(idArray) {
// initialise an array (over which we'll iterate, later)
var elements = [];
// if no arguments have been passed in, we quit here:
if (!arguments) {
return false;
}
else {
/* we're running a basic check to see if the first passed-argument
is an array; if it is, we use it: */
if (Object.prototype.toString.call(arguments[0]) === '[object Array]') {
idArray = idArray;
}
/* if a string has been passed-in (rather than an array), we
make an array of those strings: */
else if ('string' === typeof arguments[0]) {
idArray = [].slice.call(arguments);
}
// here we iterate over the array:
for (var i = 0, len = idArray.length; i < len; i++) {
// we test to see if we can retrieve an element by the id:
if (document.getElementById(idArray[i])) {
/* if we can, we add that found element to the array
we initialised earlier: */
elements.push(document.getElementById(idArray[i]));
}
}
}
// returning the elements:
return elements;
}
// here we toggle the display of the elements (between 'none' and 'block':
function toggle (elems) {
// iterating over each element in the passed-in array:
for (var i = 0, len = elems.length; i < len; i++) {
/* if the current display is (exactly) 'none', we change to 'block'
otherwise we change it to 'none': */
elems[i].style.display = elems[i].style.display === 'none' ? 'block' : 'none';
}
}
function hide (nodes) {
// iterating over the passed-in array of nodes
for (var i = 0, len = nodes.length; i < len; i++) {
// setting each of their display properties to 'none':
nodes[i].style.display = 'none';
}
}
// getting the elements:
var relevantElements = getElementsByIds('myid1','myid2','myid3'),
toggleButton = document.getElementById('buttonThatTogglesVisibilityId');
// binding the click-handling functionality of the button:
toggleButton.onclick = function(){
toggle (relevantElements);
};
// initially hiding the elements:
hide (relevantElements);
JS Fiddle demo.
References:
arguments keyword.
Array.prototype.push().
Array.protoype.slice().
document.getElementById().
Function.prototype.call().
Object.prototype.toString().
typeof.

Three options (at least):
1) Wrap them all in a parent container if this is an option. Then you can just target that, rather than the individual elements.
document.getElementById('#my_container').style.display = 'block';
2) Use a library like jQuery to target multiple IDs:
$('#myid1, #myid2, #myid3').show();
3) Use some ECMA5 magic, but it won't work in old browsers.
[].forEach.call(document.querySelectorAll('#myid1, #myid2, #myid3'), function(el) {
el.style.display = 'block'; //or whatever
});

If id="myid< increment-number >" then you can select these elements very easily.
Below code will select all elements that START WITH "myid".
$("div[id^='myid']").each(function (i, el) {
//do what ever you want here
}
See jquery doc
http://api.jquery.com/attribute-contains-selector/

Related

Native Javascript Selections

I need to use native Javascript and for some of these I need to select more than one attribute (ex. a div with a class and id). Here is a code sample of what I've got so far. The example has all single selections.
var $ = function (selector) {
var elements = [];
var doc = document, i = doc.getElementsByTagName("div"),
iTwo = doc.getElementById("some_id"), // #some_id
iThree = doc.getElementsByTagName("input"),
// ^ Lets say I wanted to select an input with ID name as well. Should it not be doc.getElementsByTagName("input").getElementById("idname")
iFour = doc.getElementsByClassName("some_class"); // some_class
elements.push(i,iTwo,iThree,iFour);
return elements;
};
Oh yes, I forgot to mention I cannot use querySelector at all...
It depends on the properties you want to select on. For example, you might pass an object like:
{tagname: 'div', class: 'foo'};
and the function might be like:
function listToArray(x) {
for (var result=[], i=0, iLen=x.length; i<iLen; i++) {
result[i] = x[i];
}
return result;
}
function getByProperties(props) {
var el, elements;
var baseProps = {id:'id', tagName:'tagName'};
var result = [];
if ('tagName' in props) {
elements = listToArray(document.getElementsByTagName(props.tagName));
} else if ('id' in props) {
elements = [document.getElementById(props.id)];
}
for (var j=0, jLen=elements.length; j<jLen; j++) {
el = elements[j];
for (var prop in props) {
// Include all with tagName as used above. Avoids case sensitivity
if (prop == 'tagName' || (props.hasOwnProperty(prop) && props[prop] == el[prop])) {
result.push(el);
}
}
}
return result;
}
// e.g.
getByProperties({tagName:'div', className:'foo'});
However it's a simplistic approach, it won't do things like child or nth selectors.
You can perhaps look at someone else's selector function (there are a few around) and follow the fork to support non–qSA browsers. These are generally based on using a regular expression to tokenise a selector, then apply the selector manually similar to the above but more extensivly.
They also allow for case sensitivity for values (e.g. tagName value) and property names to some extent, as well as map HTML attribute names to DOM property names where required (e.g. class -> className, for -> htmlFor, etc.).

document.getElementsByClassName exact match to class

There are two similar classes - 'item' and 'item one'
When I use document.getElementsByClassName('item') it returns all elements that match both classes above.
How I can get elements with 'item' class only?
The classname item one means the element has class item and class one.
So, when you do document.getElementsByClassName('item'), it returns that element too.
You should do something like this to select the elements with only the class item:
e = document.getElementsByClassName('item');
for(var i = 0; i < e.length; i++) {
// Only if there is only single class
if(e[i].className == 'item') {
// Do something with the element e[i]
alert(e[i].className);
}
}
This will check that the elements have only class item.
Live Demo
document.querySelectorAll('.item:not(.one)');
(see querySelectorAll)
The other way is to loop over the what document.getElementsByClassName('item') returns, and check if the one class is present (or not):
if(element.classList.contains('one')){
...
}
You're going to want to make your own function for exact matches, because spaces in a class means it has multiple classes. Something like:
function GetElementsByExactClassName(someclass) {
var i, length, elementlist, data = [];
// Get the list from the browser
elementlist = document.getElementsByClassName(someclass);
if (!elementlist || !(length = elementlist.length))
return [];
// Limit by elements with that specific class name only
for (i = 0; i < length; i++) {
if (elementlist[i].className == someclass)
data.push(elementlist[i]);
}
// Return the result
return data;
} // GetElementsByExactClassName
You can use Array.filter to filter the matched set to be only those with class test:
var elems = Array.filter( document.getElementsByClassName('test'), function(el){
return !!el.className.match(/\s*test\s*/);
});
Or only those with test but not one:
var elems = Array.filter( document.getElementsByClassName('test'), function(el){
return el.className.indexOf('one') < 0;
});
(Array.filter may work differently depending on your browser, and is not available in older browsers.) For best browser compatibility, jQuery would be excellent for this: $('.test:not(.one)')
If you have jQuery, it can be done using the attribute equals selector syntax like this: $('[class="item"]').
If you insist on using document.getElementsByClassName, see the other answers.

How to hide all elements of class?

I found this function:
document.getElementsByClassName = function(c){
for(var i=0,a=[],o;o=document.body.getElementsByTagName('*')[i++];){
if(RegExp('\\b'+c+'\\b','gi').test(o.className)){
a.push(o);
}
}
return a;
}
How can I hide all elements by class?
I tried:
var array = document.getElementsByClassName("hide");
for(var i = 0; i < array.length; i++)
{
$(array[i]).hide();
}
But I got error:
Could not convert JavaScript argument arg 0 [nsIDOMWindow.getComputedStyle]
jQuery allows CSS selectors to be used, doing away with the need for hand-built loops and regular expressions. To hide an element with class fooey, just do
$('.fooey').hide();
If you're using vanilla JavaScript, then:
var array = document.getElementsByClassName("hide");
for(var i = 0; i < array.length; i++)
{
array[i].style.display = 'none';
array[i].onclick = function(){
// do stuff
};
/* or:
array[i].addEventListener('click',functionToCall);
*/
}
But, given that you're using jQuery, I don't understand why you're complicating things for yourself, just use:
$('.hide').hide();
Further to the above, given your comment:
Because I must add event "click" for each element.
Simply use:
$(elementSelector).click(
function(){
// do stuff
});
Assuming you want to hide, and bind a click-event to, the same elements:
$('.hide').hide().click(
function(){
// do stuff
});
What you get from getElementsByClassName is NOT an array, but a NodeList, hence the error when trying to loop.
However, you can still loop over a NodeList using the following:
var nodeList = document.getElementsByClassName("hide");
for(var x in nodeList){}

JavaScript: Create Object from DOM

I'm trying to make a walkable DOM tree, like so:
Input:
<div>
<span>Foo</span>
<span>Bar</span>
</div>
Output (Python-like):
{'div': [{'span': 'Foo'},
{'span': 'Bar'}]}
I'd like to traverse it like so:
elements['div']['span']; // Output is "Foo".
My current code is this:
function createObject(element) {
var object = {};
if (element.childNodes.length > 0) {
for (var i = 0; i < element.childNodes.length; i++) {
object[element.tagName] = createObject(element.childNodes[i]);
}
return object;
} else {
return element.nodeValue;
}
}
But it doesn't work (the loop doesn't run). Could anyone help with this problem?
What should happen?
If no child {name: value}
if childs {name: [
{childname: childvalue}
]}
Following that logic, this is the result. Note nodeName should be used instead of tagName. Text nodes are also selected, which have nodeName #Text. If you want to only select elements, addif(element.childNodes[i].nodeType == 1)`:
function createObject(element) {
var object, childs = element.childNodes;
if (childs.length > 0) {
object = [];
for (var i = 0; i < childs.length; i++) {
//Uncomment the code if you want to ignore non-elements
// if(childs.nodeType == 1) {
object.push(createObject(childs[i]));
// }
}
return object;
} else {
object = {};
object[element.nodeName] = element.nodeValue;
return object;
}
}
Without trying to test this, it looks like the main problem is your for ... in loop - it doesn't work the same way in Javascript it does in Python.
for (child in element.childnodes)
should probably be an iterator-based loop:
for (var x=0, child; x<element.childNodes.length; x++) {
child = element.childNodes[x];
// etc
}
You'll also get text nodes you don't expect, and should check child.nodeType != Node.TEXT_NODE before recursing.
It looks like childNodes.length differs between browsers, maybe you should use hasChildNodes instead?
Also, did you use firebug (or any js debugger) to see if element was correctly filled in?
Edit : I found what is wrong. You can't create object of objects. Instead, you have to create array of objects. Check if you have childNodes, and create an object if there is none. Otherwise, create an array.
Just like your python-like output shows :-)

Get class list for element with jQuery

Is there a way in jQuery to loop through or assign to an array all of the classes that are assigned to an element?
ex.
<div class="Lorem ipsum dolor_spec sit amet">Hello World!</div>
I will be looking for a "special" class as in "dolor_spec" above. I know that I could use hasClass() but the actual class name may not necessarily be known at the time.
You can use document.getElementById('divId').className.split(/\s+/); to get you an array of class names.
Then you can iterate and find the one you want.
var classList = document.getElementById('divId').className.split(/\s+/);
for (var i = 0; i < classList.length; i++) {
if (classList[i] === 'someClass') {
//do something
}
}
jQuery does not really help you here...
var classList = $('#divId').attr('class').split(/\s+/);
$.each(classList, function(index, item) {
if (item === 'someClass') {
//do something
}
});
Why has no one simply listed.
$(element).attr("class").split(/\s+/);
EDIT: Split on /\s+/ instead of ' ' to fix #MarkAmery's objection. (Thanks #YashaOlatoto.)
On supporting browsers, you can use DOM elements' classList property.
$(element)[0].classList
It is an array-like object listing all of the classes the element has.
If you need to support old browser versions that don't support the classList property, the linked MDN page also includes a shim for it - although even the shim won't work on Internet Explorer versions below IE 8.
Here is a jQuery plugin which will return an array of all the classes the matched element(s) have
;!(function ($) {
$.fn.classes = function (callback) {
var classes = [];
$.each(this, function (i, v) {
var splitClassName = v.className.split(/\s+/);
for (var j = 0; j < splitClassName.length; j++) {
var className = splitClassName[j];
if (-1 === classes.indexOf(className)) {
classes.push(className);
}
}
});
if ('function' === typeof callback) {
for (var i in classes) {
callback(classes[i]);
}
}
return classes;
};
})(jQuery);
Use it like
$('div').classes();
In your case returns
["Lorem", "ipsum", "dolor_spec", "sit", "amet"]
You can also pass a function to the method to be called on each class
$('div').classes(
function(c) {
// do something with each class
}
);
Here is a jsFiddle I set up to demonstrate and test http://jsfiddle.net/GD8Qn/8/
Minified Javascript
;!function(e){e.fn.classes=function(t){var n=[];e.each(this,function(e,t){var r=t.className.split(/\s+/);for(var i in r){var s=r[i];if(-1===n.indexOf(s)){n.push(s)}}});if("function"===typeof t){for(var r in n){t(n[r])}}return n}}(jQuery);
You should try this one:
$("selector").prop("classList")
It returns a list of all current classes of the element.
var classList = $(element).attr('class').split(/\s+/);
$(classList).each(function(index){
//do something
});
$('div').attr('class').split(' ').each(function(cls){ console.log(cls);})
Update:
As #Ryan Leonard pointed out correctly, my answer doesn't really fix the point I made my self... You need to both trim and remove double spaces with (for example) string.replace(/ +/g, " ").. Or you could split the el.className and then remove empty values with (for example) arr.filter(Boolean).
const classes = element.className.split(' ').filter(Boolean);
or more modern
const classes = element.classList;
Old:
With all the given answers, you should never forget to user .trim() (or $.trim())
Because classes gets added and removed, it can happen that there are multiple spaces between class string.. e.g. 'class1 class2 class3'..
This would turn into ['class1', 'class2','','','', 'class3']..
When you use trim, all multiple spaces get removed..
Might this can help you too. I have used this function to get classes of childern element..
function getClickClicked(){
var clickedElement=null;
var classes = null;<--- this is array
ELEMENT.on("click",function(e){//<-- where element can div,p span, or any id also a class
clickedElement = $(e.target);
classes = clickedElement.attr("class").split(" ");
for(var i = 0; i<classes.length;i++){
console.log(classes[i]);
}
e.preventDefault();
});
}
In your case you want doler_ipsum class u can do like this now calsses[2];.
Thanks for this - I was having a similar issue, as I'm trying to programatically relate objects will hierarchical class names, even though those names might not necessarily be known to my script.
In my script, I want an <a> tag to turn help text on/off by giving the <a> tag [some_class] plus the class of toggle, and then giving it's help text the class of [some_class]_toggle. This code is successfully finding the related elements using jQuery:
$("a.toggle").toggle(function(){toggleHelp($(this), false);}, function(){toggleHelp($(this), true);});
function toggleHelp(obj, mode){
var classList = obj.attr('class').split(/\s+/);
$.each( classList, function(index, item){
if (item.indexOf("_toggle") > 0) {
var targetClass = "." + item.replace("_toggle", "");
if(mode===false){$(targetClass).removeClass("off");}
else{$(targetClass).addClass("off");}
}
});
}
Try This. This will get you the names of all the classes from all the elements of document.
$(document).ready(function() {
var currentHtml="";
$('*').each(function() {
if ($(this).hasClass('') === false) {
var class_name = $(this).attr('class');
if (class_name.match(/\s/g)){
var newClasses= class_name.split(' ');
for (var i = 0; i <= newClasses.length - 1; i++) {
if (currentHtml.indexOf(newClasses[i]) <0) {
currentHtml += "."+newClasses[i]+"<br>{<br><br>}<br>"
}
}
}
else
{
if (currentHtml.indexOf(class_name) <0) {
currentHtml += "."+class_name+"<br>{<br><br>}<br>"
}
}
}
else
{
console.log("none");
}
});
$("#Test").html(currentHtml);
});
Here is the working example: https://jsfiddle.net/raju_sumit/2xu1ujoy/3/
For getting the list of classes applied to element we can use
$('#elementID').prop('classList')
For adding or removing any classes we can follow as below.
$('#elementID').prop('classList').add('yourClassName')
$('#elementID').prop('classList').remove('yourClassName')
And for simply checking if the class is present or not we can use hasClass
I had a similar issue, for an element of type image. I needed to check whether the element was of a certain class. First I tried with:
$('<img>').hasClass("nameOfMyClass");
but I got a nice "this function is not available for this element".
Then I inspected my element on the DOM explorer and I saw a very nice attribute that I could use: className. It contained the names of all the classes of my element separated by blank spaces.
$('img').className // it contains "class1 class2 class3"
Once you get this, just split the string as usual.
In my case this worked:
var listOfClassesOfMyElement= $('img').className.split(" ");
I am assuming this would work with other kinds of elements (besides img).
Hope it helps.
javascript provides a classList attribute for a node element in dom. Simply using
element.classList
will return a object of form
DOMTokenList {0: "class1", 1: "class2", 2: "class3", length: 3, item: function, contains: function, add: function, remove: function…}
The object has functions like contains, add, remove which you can use
A bit late, but using the extend() function lets you call "hasClass()" on any element, e.g.:
var hasClass = $('#divId').hasClass('someClass');
(function($) {
$.extend({
hasClass: new function(className) {
var classAttr = $J(this).attr('class');
if (classAttr != null && classAttr != undefined) {
var classList = classAttr.split(/\s+/);
for(var ix = 0, len = classList.length;ix < len;ix++) {
if (className === classList[ix]) {
return true;
}
}
}
return false;
}
}); })(jQuery);
The question is what Jquery is designed to do.
$('.dolor_spec').each(function(){ //do stuff
And why has no one given .find() as an answer?
$('div').find('.dolor_spec').each(function(){
..
});
There is also classList for non-IE browsers:
if element.classList.contains("dolor_spec") { //do stuff

Categories

Resources