use variable for class starting with a prefix to remove it - javascript

Here is my situation,
I have some list class with the below attributes:
icon-search-icon menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-188
I'd like a variable to be able to select class starting with icon- for some specfific purposes ( cloning this class to the child element).
For the variabla to select the class starting with icon- I have try multiple solution including:
var prefix_icon = $("div[class^='icon-'],div[class*=' icon-']")
which doesn't seem to works...
does any one have any solutions by any chance ? it will be lovely.
Thanks a lot
--- EDIT --
The variable seems to work on my console, waht does not seems to work is when calling it.
What im trying to do is to remove all classes from the parent item having icon-, and cloning this icon- class to the child element of each list item.
The Html is like below:
<ul id="menu-fly-out" class="drawer">
<li id="menu-item-188" class="icon-search-icon menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-188"> .
</li>
<li id="menu-item-189" class="icon-search-icon menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-189"> .
</li>
<li id="menu-item-190" class="icon-search-icon menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-190"> .
</li>
</ul>
to do that then i have the my variable:
var prefix_icon = $("drawer > li[class^='icon-'],drawer > li[class*=' icon-']");
and I"m trying to use the below to remove the class starting with icon- frmo the parent and copying into its child:
$('.drawer > li > a').each(function () {
$('.drawer > li').removeClass(prefix_icon),
$(this).addClass(prefix_icon)
}),
Without success so far...
Really appreciate any helps !

There's no quick fix for this - you have to basically parse the class names of the parent li element, add the relevant ones to the child a element and then remove them from the li.
I trimmed the class names down to something easier to read, for this example.
// find all the list item elements that match the given selector...
var $iconListItems = $("ul.drawer > li[class^='icon-'], ul.drawer > li[class*=' icon-']");
// parse each list item, removing the classes that begin with "icon-" and adding them to the child link element...
$iconListItems.each(function() {
// habit - keep a local reference to the jQuery object so we don't have to keep constructing it
var $this = $(this);
// find the first link inside this list item
var $link = $(this).find("a").eq(0);
// start at the end and work backwards to avoid indexing issues when we remove things
for (var i = this.classList.length - 1; i >= 0; i--) {
if (this.classList[i].indexOf("icon-") == 0) {
// this class name begins with "icon-" so remove it and add it to the link (if it's not already there)
$link.addClass(this.classList[i]);
$this.removeClass(this.classList[i])
}
}
console.log("item: " + $this.attr("class"));
console.log("link: " + $link.attr("class"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="menu-fly-out" class="drawer">
<li id="menu-item-188" class="icon-search-icon menu-item-188">
</li>
<li id="menu-item-189" class="icon-something-else-icon menu-item-189">
</li>
<li id="menu-item-190" class="menu-item-190 icon-more-icons-icon">
</li>
</ul>

Related

Navigation menu items conflict

The problem is with 2nd and 3rd menu item. Whenever I click the 3rd menu item, the 2nd menu item automatically gets selected/active along with the 3rd one. However, this doesn't happen with other menu items.
For instance(when clicking on the third menu item);
<ul id="menu-1" class="navmenu">
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-464">
list item 1
</li>
<li class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-456 current_page_item menu-item-466">
list item 2
</li>
<li class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-446">
list item 3
</li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-448">
list item 4
</li>
</ul>
Note: I have no clue where those different class on click are coming from.
I tried to add an active class on click and style accordingly but this didn't work. For instance;
JQuery(function(){
jQuery('.navmenu li').on('click', function(){
jQuery(this).addClass('active').siblings().removeClass('active');
});
});
Here is the css :
.navmenu .current_page_item>a, .navmenu .current_page_ancestor>a, .navmenu .current-menu-item>a, .navmenu .current-menu-ancestor>a {
outline: none;
background-color: #7CD0AE;
color: #fff;
}
It's strange why the class on 2nd menu item has current-menu-item and current-page-item indexed when i click on the third one.
Do you have the CSS to look at? A github or jsfiddle of the relevant code would make it lot easier to help.
I replicated what you have here, and if you hover over each list item you can see they have the correct link. Seems like it's probably in the css, or else something not shared here.
https://jsfiddle.net/xpvt214o/814134/
The code below is because they make me add code when I link a jsfiddle
// find elements
var banner = $("#banner-message")
var button = $("button")
// handle click and add class
button.on("click", function(){
banner.addClass("alt")
})
JQuery(function(){
jQuery('.navmenu li').on('click', function(){
jQuery(this).addClass('active').siblings().removeClass('active');
});

Jquery - Filtering cascaded list based on class (Seprate list and nested list)

This is my sample HTML trying achieve some filtering logic for business functionality. We have a Complex structure HTML and i just hard coded some sample HTML to make some example out of it
<ol class="list_1">
<li class="page_1">one</li>
<li class="page_1">two</li>
<li><span class="ing_page_1">three
</span><ol class="list_2">
<li class="page_1">sub 1</li>
<li class="page__1">sub 2</li>
<li class="page__2">sub 3</li>
</ol>
</li>
<li class="page_2">four</li>
<li class="page_2">five</li>
</ol>
Am trying to Filter the list to get below results(DOM Elements).
Query to get DOM elements as results so i can add some attribute for each list
List 1 and its pages(List 1 - One, Two , Three , Four , Five)
List 2 and its pages(List 2 - Sub 1,Sub 2 , Sub 3)
Class 'ing_page_1' also belongs to page 1 but when i have nested structure i have some special class created with ing_ to process some other logic and it is a constant
have added my fiddle(https://jsfiddle.net/pjagana/ubk8ngha/6/) with console statements as my filter always result in sub list as well. Any help would be helpful
You must iterate through all immediate child lis and remove non span (or attr*=ing_page) then get the text.
Maybe you can try this:
function getList(parent) {
var temp = parent + " and its pages (" + parent + " - ";
$("." + parent + ' > li').each(function() { // Find all immediate li children
// Create a clone
var $clone = $(this).clone();
// remove non-span elements and remove them so only span elements would be left (you can replace this with ':not([class&=ing_page])' or something similar if needed)
$clone.find(':not(span)').remove();
// clean the text
temp += $.trim($clone.text().replace(/\s{2,}/gim, " "));
if ($(this).is(':not(:last-child)'))
temp += ", ";
});
return temp + ")";
}
console.log(getList('list_1') + "\n" + getList('list_2'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ol class="list_1">
<li class="page_1">one</li>
<li class="page_1">two</li>
<li>
<span class="ing_page_1">three</span>
<ol class="list_2">
<li class="page_1">sub 1</li>
<li class="page__1">sub 2</li>
<li class="page__2">sub 3</li>
</ol>
</li>
<li class="page_2">four</li>
<li class="page_2">five</li>
</ol>

To add class="current" Dynamically

I have Menu list which contains Sub-Menu as shown in the code below.
<li class="current">
<span class="icon4"></span>Subscriptions
<ul class="sub-menu">
<li>View Subscriptions
</li>
<li class="#((ViewBag.PageName == " Subscription ") ? "active " : " ")">Manage Subscription Plans
</li>
</ul>
</li>
<li class="current">
<span class="icon5"></span>Administration
<ul class="sub-menu">
<li class="#((ViewBag.PageName == " AssetPage ") ? "active " : " ")">Assets
</li>
<li>Configure Text
</li>
<li>Error Log
</li>
<li>Product Settings
</li>
</ul>
</li>
<li class="current">
<span class="icon6"></span>Promo Codes
<ul class="sub-menu">
<li>Manage Promo Code
</li>
<li>Used Promo Code
</li>
</ul>
</li>
Here Subscription,Administration,Promo Codes are Menu Lists which contains Sub-Menu Lists under them.
The thing is I want to apply class=current dynamically when a user clicks on Subscription,Administration,Promo Codes`.
And I am doing this in LayoutPage of MVC.
Any help will be appreciated.
Here you have a working solution: https://jsfiddle.net/c4h3sup9/
You have to use a little bit of Javascript for that.
You have to give the listitems a other class name like in my example "operator"
document.body.addEventListener("click", function(e){
if(e.target && e.target.className == "operator"){
var actives = document.getElementsByClassName("active");
actives[0].setAttribute("class", "operator");
e.target.setAttribute("class", "active");
}
});
for this example you need to assing one element as active from the beginning.
Note:
LI elements are never parents of UL.
The order is:
Unordered List (Plural) -> List item (Singular, Child).
You might want to correct that as it is not standard conform.
To add the class name to the parent <li> element, give the main links a class name. Assuming you also want to remove it from any <li> elements that already have it, also give them a class name
<li class="container">
<span class="icon4"></span>Subscriptions
and the script will be
$('.mainmenu').click(function() {
$('.container').removeClass('current'); // remove any previous
$(this).closest('.container').addClass('current');
});
In addition, if when you navigate to one of the views with this layout, and what to add the class name to the appropriate element, then you can give the <li> elements an id attribute
<li id="subscriptions" class="container">
....
</li>
<li id="administration" class="container">
....
and in the GET method, pass the value of the id to the view (e.g. using ViewBag
public ActionResult ConfigureText()
{
ViewBag.Menu = "administration";
....
return View(...);
}
and add a script that runs when the page first loads
var menu = '#ViewBag.Menu";
$('#' + menu).addClass('current');

How to insert after a specific element but before another element

Explaining by example:
<li data-owner="1"></li>
<li data-id="1"></li>
<li data-id="2"></li>
(insert here)
<li data-owner="2"></li>
I want to insert between data-owner="1" and data-owner="2", and insert last - just above data-owner="2".
This do my first requirement:
$('li[data-owner="1"]').after('<li data-id="3"></li>');
But this will insert here:
<li data-owner="1"></li>
(insert here)
<li data-id="1"></li>
<li data-id="2"></li>
<li data-owner="2"></li>
Is there a way to make it insert after one element, and then move down until it finds another element and insert before that? Or find the next element li[data-owner] after a specific element li[data-owner="2"] and insert before that?
I cannot use $('li[data-owner="2"]').before('<li data-id="3"></li>'); because I do not know the specific value of data-owner of the element I want to insert before.
You are going to want to find the next list element with a data id, and then place your insertion before that element. This can be done using nextAll. The example is broken out to show the steps clearer as opposed to being simply chained.
var owner = 1;
var currentOwner = $('li[data-owner='+owner+']');
var nextOwner = currentOwner.nextAll('li[data-owner]:first');
nextOwner.before('<li data-id="3">(insert: li data-id="3")</li>');
//1-liner: $('li[data-owner=1']').nextAll('li[data-owner]:first').before('<li data-id="3">(insert)</li>')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li data-owner="1">data-owner="1"</li>
<li data-id="1">data-id="1"</li>
<li data-id="2">data-id="2"</li>
<li data-owner="2">data-owner="2"</li>
Something along these lines?
<ul>
<li data-owner="1">a</li>
<li data-id="1">b</li>
<li data-id="2">c</li>
<li data-owner="2">d</li>
</ul>
javascript:
var owner_flag = 0;
jQuery("li[data-owner]").each(function(){
if(owner_flag == 1)
{
owner_flag == 0;
jQuery(this).before('<li data-id="3">next</li>');
}
if(jQuery(this).attr("data-owner") == "1")
{
owner_flag = 1;
}
});
https://jsfiddle.net/u7m5mkL6/

jQuery - Building a tree style list

My DOM is as follows
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
</ul>
</li>
</ul>
My jQuery in a in the bottom of the page is:
$("#Browse").click(function() {
$("#browse-one").html('<div class="ui-widget">Loading...</div>');
$("#browse-one").load('../api/browse.php?do=getFirst');
});
This script goes into the database and spits out raw LIs. After this runs the DOM is modified as follows
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
<li id="one-1" data-id="1">SOMETHING</li>
<li id="one-2" data-id="2">SOMETHING</li>
<li id="one-3" data-id="3">SOMETHING</li>
<li id="one-4" data-id="4">SOMETHING</li>
.
.
.
<li id="one-N" data-id="N">SOMETHING</li>
</ul>
</li>
</ul>
What is the proper jqueryish way to track clicks on these LIs. I want to extract the data-id of the clicked element and make a second API call to construct part two of the tree. For example if data-id="1"'s LI is clicked the DOM should be:
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
<li id="one-1" data-id="1">SOMETHING
<ul id="Something Here">
<li id="two-1" data-id="1">HMM</li>
<li id="two-2" data-id="2">HMM</li>
<li id="two-3" data-id="3">HMM</li>
.
.
.
<li id="two-M" data-id="M">HMM</li>
</ul>
</li>
<li id="one-2" data-id="2">SOMETHING</li>
<li id="one-3" data-id="3">SOMETHING</li>
<li id="one-4" data-id="4">SOMETHING</li>
.
.
.
<li id="one-N" data-id="N">SOMETHING</li>
</ul>
</li>
</ul>
Im having trouble thinking of how i'de keep each of the inner UL's IDs unique. Sure I can do the "LEVEL-ID" as in "two-1" but I feel this is hackish and not the proper jquery way.
EDIT:
But now how do I track the children's clicks?? This doesn't seem valid but I hope you understand wht I'm trying to do
$("#Browse").click(function() {
$("#locations-browse").html('<div class="ui-widget">Loading...</div>');
$("#locations-browse").load('../api/browse.php?do=getFirst');
//Child is tracked
$("#locations-browse").delegate("li","click",function(evt){
var inner = $(this).append("<ul></ul>");
inner.html('<div class="ui-widget">Loading...</div>');
inner.load('../api/browse.php?do=getSecond');
$(this).delegate("li","click", function(evt) {
alert("Child ". $(this).data("id") . " is clicked";
});
});
});
EDIT 2:
Hmm this still is not working:
$("#Browse").click(function() {
$("#locations-browse").html('<div class="ui-widget">Loading...</div>');
$("#locations-browse").load('../api/browse.php?do=getFirst');
//Child is tracked
$("#locations-browse").delegate("li","click",function(evt){
$(this).append("<ul></ul>");
$(this).children("ul").load('../api/browse.php?do=getSecond?location-id='.$(this).data("id"));
$(this).delegate("li","click", function(evt) {
alert($(this).data("id"));
});
});
});
Delegate the event via li#Browse and reference the data-id attribute relative to the event's contextual element.
$('#Browse').on('click', 'li', function(evt) {
alert($(this).data('id'));
});
Incidentally, there's several out-of-the-box plugins that do what you need, just in case you didn't want to build you own, e.g. YUI Treeview or the one I wrote.

Categories