Searching through a list for specific text using jQuery - javascript

I'm having trouble limiting a list to only add unique items this is what I have so far
function addTab(tabName)
{
var tabList=$("#pageContent ul").find("li").text();
if($("#pageContent ul li:contains('"+tabList+"')").length<1)
{
$("#pageContent ul").append("<li>"+tabName+"</li>");
}
else
{
}
}
but it doesn't work I'm not sure what's wrong and from what I can tell this should be the best way to do it.
I was going to use jQuery UI tabs but my layout uses floats and messes with the tabs widget

You are getting text content of all li elements and then try to select li elements that contain that specific text, this doesn't make sense, you don't even use tabName in your filtering logic, try the following using filter method.
function addTab(tabName) {
var $e = $("#pageContent ul");
var n = $e.find("li").filter(function(){
var t = this.textContent || this.innerText;
return t === tabName
}).length;
if (n === 0) {
$e.append("<li>"+tabName+"</li>");
} else {
// ...
}
}

Related

Javascript - Dynamic Expand/Collapse All

I have a jQuery Tree Report that I am trying to create 'expand/collapse all' buttons for.
The following two pieces of code are fired when the corresponding buttons are pressed and work great:
for (i = 1; i < 100; i++) {
var el = $('#dtt_2597807651112537_table tbody tr')[i - 1];
// store current level
var level = Number($(el).attr('dtt_level'));
// change icon
$(el).find('span.dtt_icon').removeClass('dtt_collapsed_span');
$(el).find('span.dtt_icon').addClass('dtt_expanded_span');
while ($($(el).next()).attr('dtt_level') != null) {
var el = $(el).next();
if ($(el).attr('dtt_level') == (level + 1)) {
// change display
el.removeClass('dtt_collapsed_tr');
el.addClass('dtt_expanded_tr');
} else if ($(el).attr('dtt_level') == level) {
break;
}
}
}
for (i = 1; i < 100; i++) {
// get related table row
var el = $('#dtt_2597807651112537_table tbody tr')[i - 1];
// store current level
var level = Number($(el).attr('dtt_level'));
// change icon
$(el).find('span.dtt_icon').addClass('dtt_collapsed_span');
$(el).find('span.dtt_icon').removeClass('dtt_expanded_span');
while ($($(el).next()).attr('dtt_level') != null) {
var el = $(el).next();
if ($(el).attr('dtt_level') > level) {
// change display
el.addClass('dtt_collapsed_tr');
el.removeClass('dtt_expanded_tr');
// change icon
$(el).find('span.dtt_icon').addClass('dtt_collapsed_span');
$(el).find('span.dtt_icon').removeClass('dtt_expanded_span');
} else if ($(el).attr('dtt_level') == level) {
break;
}
}
};
However, I was wondering if anyone had a nice way to:
1) Get the number of rows that need to be looped through - I just put 100 as a large number to prove my code worked and I don't want to just increase this to an even larger number.
2) Get the class name from the page source - The large number in "dtt_2597807651112537_table" is a report ID generated by the application. This is static for now but I want to eliminate any problems if it changes.
Thanks.
This is all wrong. Well, it's working against how jQuery works, in any case.
jQuery's credo is:
Select elements
Do stuff to them
Drop your loops. You don't need them.
For example. To toggle the icon on all span.dtt_icon in your document, do
var collapsed = true;
$("#dtt_2597807651112537_table span.dtt_icon") // select elements
.toggleClass('dtt_collapsed_span', collapsed) // do stuff to them
.toggleClass('dtt_expanded_span', !collapsed);
or, as a function that can both collapse and expand:
function toggleTree(tree, collapsed) {
$(tree).find("span.dtt_icon")
.toggleClass('dtt_collapsed_span', collapsed)
.toggleClass('dtt_expanded_span', !collapsed);
}
To collapse only the currently expanded ones...
$("#dtt_2597807651112537_table span.dtt_icon.dtt_expanded_span")
.toggleClass('dtt_collapsed_span', true)
.toggleClass('dtt_expanded_span', false);
and so on.
You can boil down your entire code into a few lines that way, and you don't need to write a single loop: Use smart element selection (via jQuery selectors and any of jQuerys find, filter and traversal functions) to single out the elements you want to manipulate and then manipulate them all at once in a single step.
To your second question. There are many ways, pick one:
use known page structure to determine the right table (e.g. $("div.main > table:first") or something to that effect)
use known table contents to determine the right table (e.g. $("table:has(span.dtt_icon)"))
use the table's other classes ($("table.treeReport") maybe?) or for example the table's ID with and a "starts-with" selector ($("table[id^=dtt_]")).
Again it's all about selecting your elements smartly. A dive into the jQuery API documentation, in this case the part about selectors, is recommended.

Remove value from a var

I am having some problems removing parts of a var.
function hotBarClick() {
var likeCount = 0;
$.each(companies, function (key, value) {
if (value.liked) {
likeCount++;
}
if (value.liked && value.alreadyliked ==false) {
var content = value.getHtmlLogo();
matchesHtml.add(content);
this.alreadyliked = true;
}
if (value.liked == false && value.alreadyliked == true) {
var discontent = value.getHtmlLogo();
matchesHtml.remove(discontent);
this.alreadyliked = false;
}
});
I am making a app based on html and javascript. You can like/dislike companies in the neighbourhood. If you liked 5 companies or touch the "hotbar" you will see a slider(owl-carousel) with the logos of the companies you liked.
My problem is that if you liked a company first and then dislike it, i cant remove the images from the slider, that were previously shown.
var matcheshtml is the var containing this infomation. You can see that in my code i add stuff by matcheshtml.add() but i cant seem to use the .remove() method here?
How do i remove the good part?
BTW: i think discontent contains the correct value

Wrap a tag around multiple instances of a string using Javascript

I’m trying to wrap multiple instances of a string found in html around a tag (span or abbr) using pure JS. I have found a way to do it by using the code:
function wrapString() {
document.body.innerHTML = document.body.innerHTML.replace(/string/g, ‘<tag>string</tag>');
};
but using this code messes with a link’s href or an input’s value so I want to exclude certain tags (A, INPUT, TEXTAREA etc.).
I have tried this:
function wrapString() {
var allElements = document.getElementsByTagName('*');
for (var i=0;i<allElements.length;i++){
if (allElements[i].tagName != "SCRIPT" && allElements[i].tagName != "A" && allElements[i].tagName != "INPUT" && allElements[i].tagName != "TEXTAREA") {
allElements[i].innerHTML = allElements[i].innerHTML.replace(/string/g, ‘<span>string</span>');
}
}
}
but it didn’t work as it gets ALL the elements containing my string (HTML, BODY, parent DIV etc.), plus it kept crushing my browser. I even tried with JQuery's ":containing" Selector but I face the same problem as I do not know what the string's container is beforehand to add it to the selector.
I want to use pure JavaScript to do that as I was planning on using it as a bookmark for quick access to any site but I welcome all answers regarding JQuery and other frameworks as well.
P.S. If something like that has already been answered I couldn't find it...
This is a quite complicated problem actually (you can read this detailed blog post about it).
You need to:
recurse on the dom tree
find all text nodes
do your replace on its data
make the modified data into dom nodes
insert the dom nodes to the tree, before the original text node
remove the original text node
Here is a demo fiddle.
And if you still need tagName based exclusions, look at this fiddle
The code:
function wrapInElement(element, replaceFrom, replaceTo) {
var index, textData, wrapData, tempDiv;
// recursion for the child nodes
if (element.childNodes.length > 0) {
for (index = 0; index < element.childNodes.length; index++) {
wrapInElement(element.childNodes[index], replaceFrom, replaceTo);
}
}
// non empty text node?
if (element.nodeType == Node.TEXT_NODE && /\S/.test(element.data)) {
// replace
textData = element.data;
wrapData = textData.replace(replaceFrom, replaceTo);
if (wrapData !== textData) {
// create a div
tempDiv = document.createElement('div');
tempDiv.innerHTML = wrapData;
// insert
while (tempDiv.firstChild) {
element.parentNode.insertBefore(tempDiv.firstChild, element);
}
// remove text node
element.parentNode.removeChild(element);
}
}
}
function wrapthis() {
var body = document.getElementsByTagName('body')[0];
wrapInElement(body, "this", "<span class='wrap'>this</span>");
}

Issue with the contains method and highlighting elements

I want to highlight an element that contains a string written in a textbox. This is the part of the code that's supposed to do it:
$("#rightContainer .magnifier").click(function () {
var a = $("#searchBox").val();
if (a != "") {
var foundin = $('div:contains(a)');
foundin.addClass("highlighted");
alert(a);
}
})
The problem is that the whole page gets highlighted. I'm assuming this happens because I have a main container which has its children containers, so the contains method selects the whole main container. Is this the case or is it because of something else, and does anyone have a better way of doing this? Thanks in advance.
The :contains selector will return any element which contains the text you're searching for, in this case "a". This has nothing to do with the variable named a. Perhaps you meant to do something like this:
$("#rightContainer .magnifier").click(function () {
var a = $("#searchBox").val();
if (a != "")
{
var foundin = $("div:contains('" + a + "')");
foundin.addClass("highlighted");
alert(a);
}
})
If I understand correctly, you only want the div highlighted which is wrapping that searchbox and not any other div. Use closest() to find that div.
$("#rightContainer .magnifier").click(function () {
var a = $("#searchBox").val();
if (a != "")
{
$("#searchBox").closest('div').addClass('highlighted');
}
})

Split ul to more ul's with jQuery

I have made a script with jQuery. The script split a list of li's, to more ul's. When the list is moer than 10 li items the list must be split in more ul's.
I have made the script in this post.
But the script is not working. What I did wrong here.
The script is for a submenu in the navigation. When the navigation li items are more than 4 than the ul of li items must be splitted in two ul's. How can I fix this script. Thanks!
submenu();
function submenu() {
$(".submenu").each(function () {
if($("li", this).length > 4){
$(this).closest(".submenu").addClass("width-2")
var submenu = $(this).closest(".submenu");
var $bigList = $(this), group;
while((group = $bigList.find('li:lt(8)').remove()).length) {
$('<ul/>').append(group).appendTo(submenu);
}
}
if($("li", this).length > 10){
$(this).closest(".submenu").addClass("width-3")
}
});
}
I'm not entirely sure I understand what you're trying to do, but this code will split each submenu UL into more submenus of the specified size while keeping all items in the original DOM order:
function splitSubmenu(maxNumItems) {
$(".submenu").each(function () {
// get all child li tags
var list$ = $(this).children("li");
var num, nextAfter$, after$ = $(this);
// as long as the current list it too long, loop
while (list$.length > maxNumItems) {
// decide how many to remove this iteration
num = Math.min(maxNumItems, list$.length - maxNumItems);
// create new UL tag, append num items to it
// and insert it into the DOM
nextAfter$ = $('<ul class="submenu">')
.append(list$.slice(maxNumItems, maxNumItems + num))
.insertAfter(after$);
// update insertion point for next loop iteration
after$ = nextAfter$;
// remove the items we just took out from the current jQuery object
list$ = list$.filter(function(index) {
return(index < maxNumItems || index >= 2 * maxNumItems);
});
}
});
}
splitSubmenu(4);
You can see it work here: http://jsfiddle.net/jfriend00/VMjvQ/.
I did not understand what you were trying to do with the additional classes so that part is not included.

Categories