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
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 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";
}
}
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();
}
};
...
}();
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.
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);