how determine if object has child of certain element? - javascript

I have a very simple function, which I want to work only if selected object has child of certain type - in this case if it has ul nested.
I have tried with this:
var onMouseOver = function() {
if (this.getElementsByTagName('ul') > 0);{
console.log('entered');
}
}
and this:
var onMouseOver = function() {
if (this.querySelector('ul') != null);{
console.log('enter');
}
}
but it doesn't help - function still launches, even when it returnes 'null'.

You should be looking at the length property of those selectors.
var onMouseOver = function() {
if (this.querySelectorAll('ul').length > 0);{
console.log('enter');
}
}
or
var onMouseOver = function() {
if (this.getElementsByTagName('ul').length > 0);{
console.log('entered');
}
}

try this one :)
function ok(obj) {
var l = obj.children.length;
for (var i = 0; i <= l; i++) {
if (obj.children[i].tagName == "UL") {
var c = obj.children[i].children[0];
alert("child id is :-" + c.tagName);
alert("child id is :-" + c.id);
alert("child value is :-" + c.innerHTML);
break;
}
}
}
#child {
display: none;
}
<!DOCTYPE html>
<html>
<body>
<div id="Parent" onmouseover="ok(this)">Find Child ? mouse over me
<p id="child">I'm Child</p>
<ul>
<li id="list">hello</li>
</ul>
</div>
</body>
</html>

Related

OnKeyup search string and hide/show - jQuery

I'm trying to filter a list of span tags on keyup.
I've created something only it returns strange values...
https://jsfiddle.net/5u373deu/1/
function searchClients() {
var clientSearch = document.getElementById("clientSearch");
var s = clientSearch.value;
$('.select-options span:not(:contains("' + s + '"))').hide();
}
$("#clientSearch").keyup(function() {
searchClients();
});
To make it become case sensitive, you need to override your current contains
jQuery.expr[':'].contains = function(a, index, obj) {
return jQuery(a).text().toUpperCase()
.indexOf(obj[3].toUpperCase()) >= 0;
};
function searchClients() {
var clientSearch = document.getElementById("clientSearch");
var s = clientSearch.value;
$('.select-options span').show();
$('.select-options span:not(:contains("' + s + '"))').hide();
}
$("#clientSearch").keyup(function() {
searchClients();
});
span {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="select-options ps-container below ps-active-y">
<input id="clientSearch" type="text">
<span>Bitcoin</span><span>Cat</span><span>Whiskey</span><span>Table</span>
Try refreshing your display everytime :
Note that your search is case sensitive.
function searchClients() {
var clientSearch = document.getElementById("clientSearch");
var s = clientSearch.value;
$('.select-options span').show();
$('.select-options span:not(:contains("' + s + '"))').hide();
}
$("#clientSearch").keyup(function() {
searchClients();
});
span {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="select-options ps-container below ps-active-y">
<input id="clientSearch" type="text">
<span>Bitcoin</span><span>Cat</span><span>Whiskey</span><span>Table</span>
Here you go: https://jsfiddle.net/5u373deu/6/
The problem was with the fact that you were not showing all elements when the user cleared the filter text.
function searchClients() {
var clientSearch = document.getElementById("clientSearch");
var s = clientSearch.value;
$('.select-options span').show();
$('.select-options span:not(:contains("'+s+'"))').hide();
}
$("#clientSearch").keyup(function() {
searchClients();
});

How do I supplant jQuery's toggleClass method with pure JavaScript?

How can I turn this piece of jQuery code into JavaScript?
$('#element').click(function(){
$(this).toggleClass('class1 class2')
});
I have already tried the following pieces of code, but to no avail.
First one is:
var element = document.getElementById('element'),
classNum = 0; // Supposing I know that the first time there will be that class
element.onmousedown = function() {
if (classNum === 0) {
this.classList.remove("class1");
this.classList.add("class2");
classNum = 1;
}
else if (classNum === 1) {
this.classList.remove("class2");
this.classList.add("class1");
classNum = 0;
}
}
Second one is:
var element = document.getElementById('element'),
classNum = 0; // Supposing I know that the first time there will be that class
element.onmousedown = function() {
if (classNum === 0) {
this.className -= "class1";
this.classList += "class2";
classNum = 1;
}
else if (classNum === 1) {
this.classList -= "class2";
this.classList += "class1";
classNum = 0;
}
}
Any answer that doesn't suggest that I stick with jQuery will be greatly appreciated.
[EDIT]
I've tried all of your solutions, but haven't been able to get it right. I believe it's because I didn't state clearly that the element has multiple classes like so:
class="class1 class3 class4"
And what I want is basically to replace class1 with class2 and toggle between them.
Update:
In response to comments, classList.toggle is a pure javascript solution. It has nothing to do with jQuery as one comment implies. If there is a requirement to support old versions of IE then there is a shim (pollyfill) at the MDN link below. And this shim, if needed, is far superior to the accepted answer.
Using classList.toggle certainly seems like the simplest solution. Also see Can I Use classList for browser support.
element.onclick = function() {
'class1 class2'.split(' ').forEach(function(s) {
element.classList.toggle(s);
});
}
Run the snippet to try
box.onclick = function() {
'class1 class2'.split(' ').forEach(function(s) {
box.classList.toggle(s);
stdout.innerHTML = box.className;
});
}
/* alternative
box.onclick = function() {
['class1', 'class2'].forEach(function(s) {
box.classList.toggle(s);
stdout.innerHTML = box.className;
});
}
*/
.class1 { background-color: red;}
.class2 { background-color: blue;}
.class3 { width: 100px; height: 100px; border: 1px black solid;}
click me:
<div id="box" class="class1 class3"></div>
<div id="stdout"></div>
classNum is a local variable.
Every time the event handler is called, you get a new variable, which has nothing to do with the value from the last call.
You want that to be a global variable.
Or, better yet, check classList.contains instead.
From: You might not need jQuery
$(el).toggleClass(className);
Is replaced by:
if (el.classList) {
el.classList.toggle(className);
} else {
var classes = el.className.split(' ');
var existingIndex = classes.indexOf(className);
if (existingIndex >= 0)
classes.splice(existingIndex, 1);
else
classes.push(className);
el.className = classes.join(' ');
}
Then simply wrap that function call within a document.getElementById('elementId').click
See fiddle: https://jsfiddle.net/2ch8ztdk/
var s = document.getElementById('element');
s.onclick=function(){
if(s.className == "class1"){
s.className = "class2"
} else {
s.className = "class1"
}
}
Your code is close, but your classNum variable isn't iterative. Try this:
var element = document.getElementById("element");
var numCount = 0;
element.addEventListener('click', function() {
if (numCount === 0) {
this.className = "";
this.className += " class1";
numCount++;
} else {
this.className = "";
this.className += " class2";
numCount = 0;
}
});
.class1 {
color: red;
}
.class2 {
color: blue;
}
<div id="element">click me</div>
you can use classList, but it only support IE 10+
Demo
var eles = document.querySelectorAll('#element');
var classNames = 'one two';
for(var i = 0; i < eles.length; i ++){
eles[i].onclick = function(e){
toggleClass.call(this, classNames);
}
}
function toggleClass(names){
var sp = names.split(' ');
for(var i = 0; i < sp.length; i++){
this.classList.toggle(sp[i]);
}
}
UPDATED MY ANSWER TO SUPPORT MULTIPLE CLASSES PER ELEMENT
https://jsfiddle.net/pwyncL8r/2/ This will now allow the element to already have n classes and still swap only one, retaining the other classes.
HTML
<div id="div1" style="width: 100px; height: 100px;" class="backBlack left100"</div>
<input type="button" id="swapButton" value="Css Swap" />
CSS
.backBlack {
background-color: black;
}
.backRed {
background-color: red;
}
.left100 {
margin-left: 100px;
}
JS
swapButton.onclick = function() {
var curClassIsBlack = (' ' + document.getElementById("div1").className + ' ').indexOf(' backBlack ') > -1
if (curClassIsBlack) {
document.getElementById("div1").className =
document.getElementById("div1").className.replace(/(?:^|\s)backBlack(?!\S)/g, '')
document.getElementById("div1").className += " backRed";
} else {
document.getElementById("div1").className =
document.getElementById("div1").className.replace(/(?:^|\s)backRed(?!\S)/g,'')
document.getElementById("div1").className += " backBlack";
}
}

How to make expand all/collapse all button in this certain script?

i would like to ask for help in a simple task i really need to do at my work (I am a javascript newbie). I made a simple collapsible list with script provided by this guy http://code.stephenmorley.org/javascript/collapsible-lists/ but what i need right now are two simple buttons as stated in the title: expand all and collapse whole list. Do you guys know if something like that can be implemented in this certain script? Please help :)
var CollapsibleLists = new function () {
this.apply = function (_1) {
var _2 = document.getElementsByTagName("ul");
for (var _3 = 0; _3 < _2.length; _3++) {
if (_2[_3].className.match(/(^| )collapsibleList( |$)/)) {
this.applyTo(_2[_3], true);
if (!_1) {
var _4 = _2[_3].getElementsByTagName("ul");
for (var _5 = 0; _5 < _4.length; _5++) {
_4[_5].className += " collapsibleList";
}
}
}
}
};
this.applyTo = function (_6, _7) {
var _8 = _6.getElementsByTagName("li");
for (var _9 = 0; _9 < _8.length; _9++) {
if (!_7 || _6 == _8[_9].parentNode) {
if (_8[_9].addEventListener) {
_8[_9].addEventListener("mousedown", function (e) {
e.preventDefault();
}, false);
} else {
_8[_9].attachEvent("onselectstart", function () {
event.returnValue = false;
});
}
if (_8[_9].addEventListener) {
_8[_9].addEventListener("click", _a(_8[_9]), false);
} else {
_8[_9].attachEvent("onclick", _a(_8[_9]));
}
_b(_8[_9]);
}
}
};
function _a(_c) {
return function (e) {
if (!e) {
e = window.event;
}
var _d = (e.target ? e.target : e.srcElement);
while (_d.nodeName != "LI") {
_d = _d.parentNode;
}
if (_d == _c) {
_b(_c);
}
};
};
function _b(_e) {
var _f = _e.className.match(/(^| )collapsibleListClosed( |$)/);
var uls = _e.getElementsByTagName("ul");
for (var _10 = 0; _10 < uls.length; _10++) {
var li = uls[_10];
while (li.nodeName != "LI") {
li = li.parentNode;
}
if (li == _e) {
uls[_10].style.display = (_f ? "block" : "none");
}
}
_e.className = _e.className.replace(/(^| )collapsibleList(Open|Closed)( |$)/, "");
if (uls.length > 0) {
_e.className += " collapsibleList" + (_f ? "Open" : "Closed");
}
};
}();
It is important to understand why a post-order traversal is used. If you were to just iterate through from the first collapsible list li, it's 'children' may (will) change when expanded/collapsed, causing them to be undefined when you go to click() them.
In your .html
<head>
...
<script>
function listExpansion() {
var element = document.getElementById('listHeader');
if (element.innerText == 'Expand All') {
element.innerHTML = 'Collapse All';
CollapsibleLists.collapse(false);
} else {
element.innerHTML = 'Expand All';
CollapsibleLists.collapse(true);
}
}
</script>
...
</head>
<body>
<div class="header" id="listHeader" onClick="listExpansion()">Expand All</div>
<div class="content">
<ul class="collapsibleList" id="hubList"></ul>
</div>
</body>
In your collapsibleLists.js
var CollapsibleLists =
new function(){
...
// Post-order traversal of the collapsible list(s)
// if collapse is true, then all list items implode, else they explode.
this.collapse = function(collapse){
// find all elements with class collapsibleList(Open|Closed) and click them
var elements = document.getElementsByClassName('collapsibleList' + (collapse ? 'Open' : 'Closed'));
for (var i = elements.length; i--;) {
elements[i].click();
}
};
...
}();

check if a class added or removed from an html element using element.classList

i have a code which will change color of unordered lists of item on mouseover or mouseout.
(change color to light green when mouse over and light gray on mouseout)
jsfiddle here
here i have used element.classList mehtod to add or remove id from each list item depending on mouse events.
here i add or remove class randomly.but i want to remove or add by checking whether a previously added class exists or not.is there any way in javascript to check if an added class exists or not??
<html>
<head>
<style>
li {
background:lightgray;
list-style-type:none;
font-family:Ariel;
color:white;
height:30px;
width:150px;
font-size:20px;
font-weight:bold;
padding:5px;
margin:2px;
}
li.element {
background:lightgreen;
}
li.back {
background:lightgray;
}
</style>
</head>
<body>
<ul id="uls">
<li>apple</li>
<li>orange</li>
<li>pineapple</li>
<li>mange</li>
</ul>
<script>
function makeit() {
var elem = document.getElementById('uls');
elem.addEventListener('mouseover', function(e) {
var target = e.target;
if (target.tagName == "LI") {
target.classList.remove('back');
target.classList.toggle('element');
}
}, false);
elem.addEventListener('mouseout', function(e) {
var target = e.target;
if (target.tagName == "LI") {
target.classList.remove('element');
target.classList.toggle('back');
}
}, false);
}
window.onload = makeit;
</script>
</body>
</html>
If you just want to see if an element has a particular class, you can use a function like:
function hasClass(element, className) {
var re = new RegExp('(^|\\s)' + className + '(\\s|$)');
return re.test(element.className);
}
or
function hasClass(element, className) {
return (' ' + element.className + ' ').indexOf(' ' + className + ' ') >= 0;
}
You can use a regex match for element.className or you can use jQuery's own implementation : hasClass
From jQuery source (2.0.3)
function (selector) {
var className = " " + selector + " ",
i = 0,
l = this.length;
for (; i < l; i++) {
if (this[i].nodeType === 1 && (" " + this[i].className + " ").replace(/[\n\t\r]/g, " ").indexOf(className) >= 0) {
return true;
}
}
return false;
}
For more reading, you can head over to jQuery source viewer of or peep into its source at github.

pure javascript to check if something has hover (without setting on mouseover/out)

I have seen this jQuery syntax:
if($(element).is(':hover')) { do something}
Since I am not using jQuery, I am looking for the best way to do this in pure javascript.
I know I could keep a global variable and set/unset it using mouseover and mouseout, but I'm wondering if there is some way to inspect the element's native properties via the DOM instead? Maybe something like this:
if(element.style.className.hovered === true) {do something}
Also, it must be cross browser compatible.
Simply using element.matches(':hover') seems to work well for me, you can use a comprehensive polyfill for older browsers too: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
You can use querySelector for IE>=8:
const isHover = e => e.parentElement.querySelector(':hover') === e;
const myDiv = document.getElementById('mydiv');
document.addEventListener('mousemove', function checkHover() {
const hovered = isHover(myDiv);
if (hovered !== checkHover.hovered) {
console.log(hovered ? 'hovered' : 'not hovered');
checkHover.hovered = hovered;
}
});
.whyToCheckMe {position: absolute;left: 100px;top: 50px;}
<div id="mydiv">HoverMe
<div class="whyToCheckMe">Do I need to be checked too?</div>
</div>
to fallback I think it is ok #Kolink answer.
First you need to keep track of which elements are being hovered on. Here's one way of doing it:
(function() {
var matchfunc = null, prefixes = ["","ms","moz","webkit","o"], i, m;
for(i=0; i<prefixes.length; i++) {
m = prefixes[i]+(prefixes[i] ? "Matches" : "matches");
if( document.documentElement[m]) {matchfunc = m; break;}
m += "Selector";
if( document.documentElement[m]) {matchfunc = m; break;}
}
if( matchfunc) window.isHover = function(elem) {return elem[matchfunc](":hover");};
else {
window.onmouseover = function(e) {
e = e || window.event;
var t = e.srcElement || e.target;
while(t) {
t.hovering = true;
t = t.parentNode;
}
};
window.onmouseout = function(e) {
e = e || window.event;
var t = e.srcElement || e.target;
while(t) {
t.hovering = false;
t = t.parentNode;
}
};
window.isHover = function(elem) {return elem.hovering;};
}
})();
it occurred to me that one way to check if an element is being hovered over is to set an unused property in css :hover and then check if that property exists in javascript. its not a proper solution to the problem since it is not making use of a dom-native hover property, but it is the closest and most minimal solution i can think of.
<html>
<head>
<style type="text/css">
#hover_el
{
border: 0px solid blue;
height: 100px;
width: 100px;
background-color: blue;
}
#hover_el:hover
{
border: 0px dashed blue;
}
</style>
<script type='text/javascript'>
window.onload = function() {check_for_hover()};
function check_for_hover() {
var hover_element = document.getElementById('hover_el');
var hover_status = (getStyle(hover_element, 'border-style') === 'dashed') ? true : false;
document.getElementById('display').innerHTML = 'you are' + (hover_status ? '' : ' not') + ' hovering';
setTimeout(check_for_hover, 1000);
};
function getStyle(oElm, strCssRule) {
var strValue = "";
if(document.defaultView && document.defaultView.getComputedStyle) {
strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
}
else if(oElm.currentStyle) {
strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1) {
return p1.toUpperCase();
});
strValue = oElm.currentStyle[strCssRule];
}
return strValue;
};
</script>
</head>
<body>
<div id='hover_el'>hover here</div>
<div id='display'></div>
</body>
</html>
(function getStyle thanks to JavaScript get Styles)
if anyone can think of a better css property to use as a flag than solid/dashed please let me know. preferably the property would be one which is rarely used and cannot be inherited.
EDIT: CSS variable are probably better to use to check this. E.g.
const fps = 60;
setInterval(function() {
if(getComputedStyle(document.getElementById('my-div')).getPropertyValue('--hovered') == 1) {
document.getElementById('result').innerHTML = 'Yes';
} else {
document.getElementById('result').innerHTML = 'No';
};
}, 1000 / fps);
#my-div {
--hovered:0;
color: black;
}
#my-div:hover {
--hovered:1;
color: red;
}
<!DOCTYPE html>
<html>
<head>
<title>Detect if div is hovered with JS, using CSS variables</title>
</head>
<body>
<div id="my-div">Am I hovered?</div>
<div id="result"></div>
</body>
</html>
You can use an if statement with a querySelector. If you add ":hover" to the end of the selector, it will only return the element if it is being hovered. This means you can test if it returns null. It is like the element.matches(":hover) solution above, but I have had more success with this version.
Here is an example:
if (document.querySelector("body > p:hover") != null) {
console.log("hovered");
}
You can put it in an interval to run the code every time you hover:
setInterval(() => {
if (document.querySelector("body > p:hover") != null) {
console.log("hovered");
}
}, 10);

Categories