How to add class to parent in javascript? - javascript

Not jQuery as I would simply do $("this").parent().addClass("active"); but in pure javascript. This is because i don't want to mix up Javascript and jQuery on the following code:
var clickedPath = this.getElement();
clickedPath.classList.add("active");
var classes = clickedPath.getAttribute('class').match(/\d+/g) || [];
buttons.forEach(function(btn) {
var method = classes.indexOf(btn.getAttribute('data-date')) > -1 ? 'add' : 'remove';
btn.classList[method]('active');
//btn.parent().addClass("active");
});
UPDATE
This is the HTML starting case before the classes are added:
<ul>
<li>1500</li>
<li>1400
<ul>
<li>1401</li>
</ul>
</li>
</ul>
We have 2 situations:
1500 is single and doesn't have a child
1400 has a child 1401
If I am adding the class active to 1500, it's fine and I can use the code provided in the answer:
btn.parentNode.classList[method]('active');
But If I add the class to 1401, also 1400 should have it, so the followings are the two cases:
<ul>
<li class="active">1500</li>
<li>1400
<ul>
<li>1401</li>
</ul>
</li>
</ul>
Or
<ul>
<li>1500</li>
<li class="active">1400
<ul>
<li class="active">1401</li>
</ul>
</li>
</ul>

You mention " i don't want to mix up js and jQuery on the following code" but you are actually mixing vanilla DOM APIs with jQuery methods. .parent and .addClass are jQuery functions. You can code:
btn.parentNode.classList.add("active");

Also consider parentElement as an alternative to parentNode:
btn.parentElement.classList.add("active");

You need .parentNode on the element.
Something like this.
var clickedPath = this.getElement();
clickedPath.classList.add("active");
var classes = clickedPath.getAttribute('class').match(/\d+/g) || [];
buttons.forEach(function(btn) {
var method = classes.indexOf(btn.getAttribute('data-date')) > -1 ? 'add' : 'remove';
btn.classList[method]('active');
btn.parentNode.classList.add("active");
});

Related

I need jQuery to perform a task if two conditions are true

I need some help to put an if statement together using jQuery. I want to change the logo on my site, if two conditions are true.
Here is some pseudo code, hopefully explaining what i want to archive:
if(li hasClass active and data-menuid is equal to 0033){
change logo...
}
Here is a simple example of the menu structure:
<div id="menu">
<ul id="menu-primary">
<li class="menuactive" data-menuid="0011">
Test1
<ul class="menu-dropdown">
<li data-menuid="0022">Test2</li>
<li class="active" data-menuid="0033">Test3</li>
</ul>
</li>
<li data-menuid="0044">Test4</li>
<li data-menuid="0055">Test5</li>
</ul>
</div>
You can check the combination of class and Attribute Equals Selector [name="value"]
if($('li.menuactive[data-menuid="0033"]').length){
//Your code to change the logo
}
You can use $.fn.filter()
Reduce the set of matched elements to those that match the selector or pass the function's test.
var listMeetingCondition = $('li').filter(function(){
return $(this).hasClass('menuactive') && $(this).attr('data-menuid') == "0033"
});
if(listMeetingCondition.length){
//Your code to change the logo
}
if($('li:has(.menuactive[data-menuid="0033"])').length){
change logo...
}
Another workaround:
var $target = $('li', '#menu-primary');
if( $target.hasclass('active') && $target.data('menuid') == '0033' ){
// change logo
}

How to move lists

I have something like this:
<ul>
<li id="li1">1</li>
<li id="li2">2</li>
<li id="li3">3</li>
</ul>
And I wonder if there is possible to move the list number 3, to the place of the list number 1 using javascript or jquery, like this:
<ul>
<li id="li3">3</li>
<li id="li2">2</li>
<li id="li1">1</li>
</ul>
Thanks for you time!
No jQuery solution :
var list = document.getElementsByTagName('ul')[0],
items = list.getElementsByTagName('li'),
i = items.length;
while (i--) list.appendChild(items[i]);
Here is a demo : http://jsfiddle.net/wared/tJaJ9/.
Based on cookie monster's suggestion :
var list = document.getElementsByTagName('ul')[0],
i = list.children.length;
while (i--) list.appendChild(list.children[i]);
Just for fun :
var list = document.getElementsByTagName('ul')[0],
items = Array.prototype.slice.call(list.children);
while (items.length) list.appendChild(items.pop());
A jQuery one :
$('ul').append($('li').get().reverse());
You can use ajax sortable jquery plugin. One of my recommendation tutorial is Sortable Lists Using jQuery UI .
Here user can re-order list using cursor pointer.
This should do the trick for you.
var length = $('ul li').length;
while (length--) $('ul').append($('ul li')[length]);
Here is a working jsfiddle

find an element by style with jquery

How could I find an element in an HTML document using it's style properties?
here is an example:
HTML:
<ul>
<li style='z-index=1;'>e1</li>
<div style='z-index=8;'>div</div>
<li style='z-index=2;'>e2</li>
<li style='z-index=3;'>e3</li>
<li style='z-index=4;'>e4</li>
<li style='z-index=5;'>e5</li>
<ul>
The question is how do i select, for example..: the element <li> with z-index=4.
and how to select all div's with z-index=8 ...
If the style is set inline, you can use an attribute selector:
$('li[style*="z-index:4"]') //returns any li's with z-index = 4
see here. The advantage to this method is that it is very fast.
If the style is set via a stylesheet, you can access it this way:
var elem;
var elems = $("li");
for(var i=0; i<elems.length; i++) {
if($(elems[i]).css('z-index') == '4') {
elem = elems[i]; //assign elem we found
break; //exit loop early
}
}
Note Webkit browsers, (Safari, Chrome, etc), will not return a z-index value unless it is positioned as well. See this example
Also, for loop is still faster than .filter()
There isn't a style selector (how would it work, the style is a combination of inherited and explicitly stated rules), but you can filter (demo):
var things = $("li").filter(function() {
return $(this).css('z-index') == '4';
});
Now if you are using z-index to attach a piece of data to an HTML element you might have more luck using data attributes (cleaner, and searchable by Sizzle). One interpretation might look like this: (demo)
<div data-id='8'>div</div>
<ul>
<li data-id='1'>e1</li>
<li data-id='2'>e2</li>
<li data-id='3'>e3</li>
<li data-id='4'>e4</li>
<li data-id='5'>e5</li>
<ul>
<script>
alert($('[data-id=4]').text())
alert($('[data-id=8]').text())
</script>

Applying css class depending on subelements

I want to set css classes to items of a list depending of subelements matches a certain criterion or not. The structure is like in the following example:
<ul ng-controller="Navigation">
<li>Category A
<ul>
<li>a1</li>
<li>a2</li>
</ul>
</li>
<li>Category B
<ul>
<li>b1</li>
<li>b2</li>
</ul>
</li>
<li>contact</li>
</ul>
My model is the current page, say a2.html. If a link has the same href attribute as the model value, it should have a certain css class (active). This could be done with this expression:
<a href="a1.html" ng-class="{'active': currentPage == 'a1.html'}>
But this is a bit inelegant, because I have to repeat the file name (a1.html). Would it be possible to pass the current element to a function? Something like this: ng-class="getClass(currentElement)"
The next problem is, that I want to select parent elements depending on whether a child has the class active or not. If a1 in my above example is selected, then Category A should get the class active too.
Conclusion
'stewie's solution works, but I came to the conclusion that Angular is not the best tool for this job. It is not a web 'application' (the domain of Angular) but static html which should be enriched a bit.
This simple jQuery snippet does the job:
var activeLink = $("a").filter(function() {
return $(this).attr("href") == currentPage();
});
activeLink.addClass("active");
activeLink.parents("li").children("a").addClass("active");
It can be done by using a custom directive on your UL element, which would traverse the list whenever the model is changed and set the appropriate 'active' class on matching items. See this Plunker as an example. Please note that the directive can be further optimized. It's only a demonstration.
HTML:
<ul menu ng-controller="Navigation">
<li>Category A
<ul>
<li>a1</li>
<li>a2</li>
</ul>
</li>
<li>Category B
<ul>
<li>b1</li>
<li>b2</li>
</ul>
</li>
<li>contact</li>
</ul>
JS:
var app = angular.module('plunker', []);
app.controller('Navigation',
function($scope) {}
);
app.directive('menu',
function(){
return {
link: function ($scope, $element) {
var link, li;
$scope.$watch('currentPage', function(page){
activate(page);
});
function activate(page){
angular.forEach($element.find('li'), function(elm){
li = angular.element(elm);
link = li.find('a');
if(link.attr('href') === $scope.currentPage){
li.addClass('active');
li.parents('li').addClass('active');
return;
}
li.removeClass('active');
});
}
}
};
}
);
I had a look at #Stewei 's the solution for this. But writing up the solution using a directive for this just did not make sense to me. I think that the directives are only meant to be written when you are creating a component or perhaps when you are stamping out templates. Even for stamping out templates I would suggest people to use ng-include or something like unless you want the semantics that a custom element provides.
But, I believe the Angular way of doing this is to totally separate out the behavioral logic from the 'App specific' logic. I would argue that you write directives in such a way that they are independent of the controller around it.
Here is a plunkr that actually solves this, hopefully in the most "Angular way" possible. This can be further decoupled, if you could use some kind of a data model for all the link's and could possibly ng-repeat over that model. But that is a choice upto the developer. Since you mentioned that it is a static page, this solution probably suits it best.
http://plnkr.co/edit/DjaYi1ofpFKgKfhtakub?p=preview
In your original question, you did ask if you could pass a currentElement to the getClass method. I have asked this before and the answer is NO. The only place where you could pass a reference to the currentElement is in a directive controller, but that is currently out of topic.
Here is the code that achieves the task at hand.
HTML :
<div ng-controller="NavController">
<ul >
<li ng-class="getCategoryClass('A')">
Category A
<ul>
<li ng-class="getClass('a1.html','A')">a1</li>
<li ng-class="getClass('a2.html','A')">a2</li>
</ul>
</li>
<li ng-class="getCategoryClass('B')">
Category B
<ul>
<li ng-class="getClass('b1.html','B')">b1</li>
<li ng-class="getClass('b2.html','B')">b2</li>
</ul>
</li>
<li ng-class="getClass('contact.html','contact')">contact</li>
</ul>
<input ng-model="currentPage" />
<br>
currentPage: {{currentPage}}
</div>
JS :
app.controller('NavController',
function($scope) {
$scope.currentPage = "";
$scope.currentCategory = "";
$scope.pageActive = false;
$scope.getClass = function(page,category){
if( page === $scope.currentPage ) {
$scope.pageActive = true;
$scope.currentCategory = category;
return "active";
}
else{
return "";
}
};
$scope.$watch('currentPage',function(val){
$scope.pageActive = false;
});
$scope.onLinkClick = function($event){
$event.preventDefault();
};
$scope.getCategoryClass = function(category){
return $scope.currentCategory === category && $scope.pageActive ? "active" : "";
};
}
);

reorder list elements - jQuery? [duplicate]

This question already has answers here:
How may I sort a list alphabetically using jQuery?
(10 answers)
Closed 5 years ago.
Is it possible to reorder <li> elements with JavaScript or pure jQuery. So if I have a silly list like the following:
<ul>
<li>Foo</li>
<li>Bar</li>
<li>Cheese</li>
</ul>
How would I move the list elements around? Like put the list element with Cheese before the list element with Foo or move Foo to after Bar.
Is it possible? If so, how?
var ul = $("ul");
var li = ul.children("li");
li.detach().sort();
ul.append(li);
This is a simple example where <li> nodes are sorted by in some default order. I'm calling detach to avoid removing any data/events associated with the li nodes.
You can pass a function to sort, and use a custom comparator to do the sorting as well.
li.detach().sort(function(a, b) {
// use whatever comparison you want between DOM nodes a and b
});
If someone is looking to reorder elements by moving them up/down some list one step at a time...
//element to move
var $el = $(selector);
//move element down one step
if ($el.not(':last-child'))
$el.next().after($el);
//move element up one step
if ($el.not(':first-child'))
$el.prev().before($el);
//move element to top
$el.parent().prepend($el);
//move element to end
$el.parent().append($el);
One of my favorite things about jQuery is how easy it is to write tiny little add-ons so quickly.
Here, we've created a small add-on which takes an array of selectors, and uses it to order the children of the target elements.
// Create the add-on
$.fn.orderChildren = function(order) {
this.each(function() {
var el = $(this);
for(var i = order.length - 1; i >= 0; i--) {
el.prepend(el.children(order[i]));
}
});
return this;
};
// Call the add-on
$(".user").orderChildren([
".phone",
".email",
".website",
".name",
".address"
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="user">
<li class="name">Sandy</li>
<li class="phone">(234) 567-7890</li>
<li class="address">123 Hello World Street</li>
<li class="email">someone#email.com</li>
<li class="website">https://google.com</li>
</ul>
<ul class="user">
<li class="name">Jon</li>
<li class="phone">(574) 555-8777</li>
<li class="address">123 Foobar Street</li>
<li class="email">jon#email.com</li>
<li class="website">https://apple.com</li>
</ul>
<ul class="user">
<li class="name">Sarah</li>
<li class="phone">(432) 555-5477</li>
<li class="address">123 Javascript Street</li>
<li class="email">sarah#email.com</li>
<li class="website">https://microsoft.com</li>
</ul>
The function loops backwards through the array and uses .prepend so that any unselected elements are pushed to the end.
Here is a jQuery plugin to aid with this functionality: http://tinysort.sjeiti.com/
something like this?
​var li = $('ul li').map(function(){
return this;
})​.get();
$('ul').html(li.sort());
demo
I was somewhat lost you may be wanting something like this...
$('ul#list li:first').appendTo('ul#list'); // make the first to be last...
$('ul#list li:first').after('ul#list li:eq(1)'); // make first as 2nd...
$('ul#list li:contains(Foo)').appendTo('ul#list'); // make the li that has Foo to be last...
more of it here1 and here2
Have a look at jquery ui sortable
http://jqueryui.com/demos/sortable/

Categories

Resources