1

I have a generated navigation, The first n items have _ in front of them to always be at the top of list. What I want to accomplish now is to remove that _ from the front-end of the site.

I tried to do this with the jQuery code below which almost worked but it is also changing the text of other nav items.

See full mark-up on JS Fiddle: https://jsfiddle.net/1fz661o4/

Code:

$(function() {
  $('.dropdown-submenu').html($('.dropdown-submenu').html().replace(/\_/g,''));
});
4
  • And what you need? Your code works as you expected. "Other nav items" needs to be identified by an ID or a different classname, so you can only replace the _ on the nav you want. Commented Nov 17, 2016 at 16:43
  • @MarcosPérezGude If you look at the output you will see that, "Software One" and "Software Two" are now both showing up as "Software One" after the replace. Commented Nov 17, 2016 at 16:46
  • The problem of the mix of Software One and Software Two is easy solvable. You are replacing directly with an automatic loop made by jQuery. If you use your own loop and take the current element with $(this) the problem disappears. Commented Nov 17, 2016 at 16:49
  • See the answer of @Turv . I upvote it. It's exactly what I tell you in last comment. Commented Nov 17, 2016 at 16:51

6 Answers 6

3

You could just change it to loop over the anchors.

$(function() {
    $('.dropdown-submenu > a').each(function() {
        $(this).text($(this).text().replace(/\_/g, ''));
    });
});

https://jsfiddle.net/utk12jdt/1/

Sign up to request clarification or add additional context in comments.

3 Comments

The link you attached is the same that shares the OP. I edit it.
This worked but introduce a second problem. In my initial question I didn't have standalone Items in my nav, so the 'dropdown-submenu' class worked. but now that I ran this I realize that nav items without children do not have 'dropdown-submenu' class generated. so this will ignore those. Here is the updated fiddle: jsfiddle.net/95ezLehx
Instead change it to look at all anchor links in the whole dropdown menu, .dropdown a see here: jsfiddle.net/snaazdad/1
2

So basically you want to remove only the underscores in anchors that are direct children of .dropdown-submenu? In your fiddle, replace $('.dropdown-submenu') with $('.dropdown-submenu > a').

JSFiddle: https://jsfiddle.net/26qLofz8/

$(function() {
      $('.dropdown-submenu > a').html($('.dropdown-submenu > a').html().replace(/\_/g,''));
});

Edit:

after your response, the question now is clear. To prevent your <li>'s from all becoming Software one, you will need to loop over all the elements you want to replace, like so:

$(function() {
  $('.dropdown-submenu > a').each(function(i, el) {
      $(el).html($(el).html().replace(/\_/g,''));
  });
});

JSFiddle: https://jsfiddle.net/n7ms67k0/

2 Comments

Did you run your fiddle? Does exactly the same as the original and has exactly the same issue (_Software Two becomes Software One)
didn't see that comment when I posted the comment. Will edit that.
1

You can use the .html() overload with a function that provides the existing html:

$('.dropdown-submenu').html(function(index, html) { return html.replace(/\_/g,''); });

Updated fiddle: https://jsfiddle.net/1fz661o4/2/


Alternatively, you can loop over each record:

$('.dropdown-submenu').each(function() {
   $(this).html($(this).html().replace(/\_/g,''));
});

1 Comment

Both your solutions worked but another issue is introduced. Now that I ran this I realize that nav items without children do not have 'dropdown-submenu' class generated. so this will ignore those. Here is the updated fiddle: jsfiddle.net/95ezLehx
1

Simply replacing the HTML will remove any event listeners and might also cause issues in the future if you have links with underscores in the URL etc.

What you should do, is go through the elements and change the value of the text nodes. I'm not sure how to do it reliably in jQuery, but here is how you would do it with plain JavaScript DOM.

function replaceUnderscore(index, el) {
  switch (el.nodeType) {
    case 3: // text node
    el.nodeValue = el.nodeValue.replace(/_/g, '');
    break;

    case 1: // normal element
    for (var i = 0, child; child = el.childNodes[i]; i++) {
      replaceUnderscore(i, child);
    }
    break;
  }
}

To apply this to elements you found in jQuery, you just do

$('.class').each(replaceUnderscore);

Not tested but I think this should work.

That being said, do you have to do this in JavaScript? Ideally this kind should be performed on the server side instead. If it's a CMS you might be able to write a little plugin for this purpose.

Comments

0

You need to make your selector more specific. Either give it a unique class or an ID and select based on that.

<ul class="dropdown-submenu my-custom-menu">

And the jQuery would change to:

$(function() {
  var menu = $('.my-custom-menu'); // save the query since we use it twice
  menu.html(menu.html().replace(/\_/g,''));
});

NOTE: You're using ids incorrectly since they're meant to be globally unique. You shouldn't have id="row" multiple times. That's what classes are for.

3 Comments

roger that. I forgot to mention that I don't have control of class/ID generation though. This is been auto generated from the CMS am using. SparkPay to be specific.
You would use an ID if you only wanted to change a single item. In this case, OP is already correctly using a class to select all the relevant elements.
@freedomn-m the OP mentioned that their jquery selector isn't specific enough and affecting menus they don't want. an ID could make it more specific.
0

You must go through each element with the .dropdown-submenu class using the jQuery each function so you will only affect one element at a time. Your JavaScript code would look like this.

$(".dropdown-submenu").each(function() {
    //this is the current .dropdown-submenu element
    $(this).html($(this).html().replace(/\_/g,''));
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.