hide all divs that contain a phrase inside them - javascript

I'd like to hide (remove) all <div> that contain a certain string. Like a filter. Think of it having the functionality of a browser add-on.
Basically anything that is
Within a tag within the div, or
Immediately inside the div (but not a tag)
Any ideas of how to best do this efficiently? Ideally I'd like a way to have the browser respond well to this by not only hiding the div, but removing it in such a way that the page has no large blank spaces.
I'm really not super fluent in javascript, so thought I'd see if I could get some pointers here. (And is better to use straight JS or JQuery?)
thanks!

First, make a plan:
Find all the nodes that have the phrase. This SO Q will help.
For each node you find, go up the dom tree until you find the first enclosing div to remove. See JQuery dom transversal helpers
Then remove the appropriate divs. You may want to animate their removal, use jquery for that too.
Re: Use jquery? Up to you. If you want your code to work on multiple browsers then jquery will help. Your problem can be solved with or without jquery.
Good luck.

Try my JQuery plugin searchEngine
Syntax
$(selector).searchengine(textFilter,action,caseSensitive)
For your case , invoke it as following :
var myTxt="dfvdf...."
$('div').searchengine(myTxt,'remove',false);
If you want to remove also all <p> that contains myTxt :
$('div,p').searchengine(myTxt,'remove',false);
if you want to hide it instead of removing it :
$('div').searchengine(myTxt,'hide',false);
if you want to show it after that :
$('div').searchengine(myTxt,'show',false);
and so forth
Demo : http://jsfiddle.net/abdennour/k3x53/1/

Hacked together from this answer: Get all visible DIVs on a page with javascript?
This is fairly simple with jQuery, but you requested non-jquery so I will give it a quick go:
function removeDivs(withString) {
var divs = document.getElementsByTagName("DIV");
for(var i = 0; i < divs.length; i++) {
div = divs[i];
if (div.style.display != "none" && div.innerHTML.indexOf(withString) > -1) {
div.style.display = "none";
}
}
}
I would note that you said "phrase inside them", but did not specify the level to which you wanted to find out that the phrase is inside. In the case of nested divs, this will hide all the divs as far up as it can go that have the phrase in their innerHTML. In other words, since innerHTML contains all the contained divs, any div containing a div that has the phrase in it will also be hidden, and so forth on up the tree.
Another note, this is not efficient at all in that it probably will end up redundantly hiding divs that don't need to be hidden.
If I were to do it, I would use jQuery and try to get something a little more efficient...it would be re-inventing the wheel not to IMHO (unless there are technical restrictions or browser restrictions that prevent jQuery from running).

Related

DOM manipulation performance when toggle visibility

I have bunch of images in a wrapper div. I need to hide all of them except the one user clicks on.
What is the most performance concise way of doing that?
Should I apply class on all of them to hide them all and than filter out the one that was clicked and show only that one or should I loop over them all hiding them as loop progresses with exception of the one that was clicked or something else?
Tnx
In modern desktop browsers you won't see any difference. Browsers are tuned so that they are blazing fast in rendering any changes is DOM three. Guts tell me that it might be sligtly faster to loop through all images and set visibility depending on item clicked using style attribute and not using class. In that way you have to process only N elements and no external CSS files are involved. If you hide all and show the element with was clicked, you process N + 1 elements.
In your situation I would use solution that is fastest, more managable and clean from the developers standpoint as there won't be much difference in the final result if you use one method or another.
PS: If you're using jquery, you can use the following:
Lets say, your div has id='test-div', and there are several images in it. All these images can be accessed as:
$('#test-div img')
Now, lets assume you know the id of image which got clicked. Lets assume id='my-image'.
You can execute the following to hide all other images (except 'my-image'):
$('#test-div img').not('#my-image').addClass('hide')
One of the most performant ways would be to let CSS do the visibility. It sounds to me like you're only displaying one at a time, in which case you can do it with two DOM operations by using classes;
// scope above
var lastClicked = null;
// then in click listener, 1st param `e`
if (lastClicked) lastClicked.className = ''; // remove visible class
lastClicked = e.target; // get clicked node
lastClicked.className = 'visible'; // add visible class
I'm assuming event.target but depending how the listener is attached, you might want to use this or some other logic. Further, if you expect element.classList support, you can use add and remove from that.
Example CSS of how to show only nodes with class token visible.
selector:not(.visible) {
display: none;
}

How do I hide an element with the same markup via jquery?

I have two custom dropdown lists that have the same markup. I need to have only one show at a time. Right now, I'm able to open both at the same time. Both should also close when I click off the list.
The same markup for both lists is required, so I can't use unique ID's or additional classes to make this happen.
Here is a link to my fiddle example: http://jsfiddle.net/dg7Lc/29/
Any help would be greatly appreciated, thanks!
-D
Consider adding a data attribute such as 'active' via jquery when you click on one of them, then hide all those that have that attribute.
$('.custom-select').eq(0).hide() will hide the first one.
Use .show() instead of .hide() to show (obviously) and change the index to (1) to get the second one.
First thought would be if you could wrap a span or div around either or both and use that to get around the "same markup" limitation. Other than that, though, I'd suggest using order in page - use .next() and .prev() to get between them, and something like
$("div.custom-select").get(0)
or
$("div.custom-select").get(1)
to select them from outside.
edit: if you can run them off of something like an onmouseover, onchange, or whatnot, it's even easier - the one that's changing will be passed into the function as the "this" parameter. Just hide both, and show this, or show both and hide this.
edit2: similarly, once you have one of them hidden properly - well, that one will be hidden, and respond to the ":hidden" selector. Use that to distinguish between them (and save the distinction as a jquery variable) before you go showing or hiding anything else
Hide the first:
$('.custom-select').first().hide();
Hide the second:
$('.custom-select').last().hide();
And then put these lines of code where needed.
http://jsfiddle.net/dg7Lc/31/
Basically, closing the others:
$('.custom-select').not(this).find('ul').slideUp('fast');
And for closing when clicking outside the box, I used this piece of code but it's a bit dirty:
$("body").click(function(e) {
var should = true;
for($e = $(e.target); should && $e.length; $e = $e.parent()) {
should = !$e.is(".custom-select");
}
if(should) {
$('.custom-select').find('ul').slideUp('fast');
}
});
You can bind a click to the document, that looks to see if they clicked on the custom-select or the document outside it and hides any open lists as it should:
$(document).click(function(ev){
if(!$(ev.target).is('.custom-select span')){ $('.custom-select').find('ul').slideUp('fast'); }
});
Updated JSFiddle

Replace part of innerHTML without reloading embedded videos

I have a div with id #test that contains lots of html, including some youtube-embeds etc.
Somewhere in this div there is this text: "[test]"
I need to replace that text with "(works!)".
The normal way of doing this would of course be:
document.getElementById("test").innerHTML = document.getElementById("test").replace("[test]","(works!)");
But the problem is that if i do that the youtube-embeds will reload, which is not acceptable.
Is there a way to do this?
You will have to target the specific elements rather than the parent block. Since the DOM is changing the videos are repainted to the DOM.
Maybe TextNode (textContent) will help you, MSDN documentation IE9, other browsers also should support it
Change your page so that
[test]
becomes
<span id="replace-me">[test]</span>
now use the following js to find and change it
document.getElementById('replace-me').text = '(works!)';
If you need to change more than one place, then use a class instead of an id and use document.getElementsByClassName and iterate over the returned elements and change them one by one.
Alternatively, you can use jQuery and do it even simpler like this:
$('#replace-me').text('(works!)');
Now for this single replacement using jQuery is probably overkill, but if you need to change multiple places (by class name), jQuery would definitely come in handy :)

Change name of a html class

I use a website, which shows information i have no use for, so i tried to hide some of it with Stylish, an addon for Chrome to insert custom CSS.
I will try to explain better.
<div class="splitscreenleft"> <div id="toplevel"
<div class="splitscreenleft"> <div id="coursesection"
I want to hide one of those. Everything above splitscreenleft is the same on both. So the only difference is the div id below.
I must somehow hide one of the two classes based on the name of the div below it i think.
Any solutions to this problem?
You should be able to do this either via CSS or JavaScript.
You probably don't even need to search the children out. You can probably just pick the first or second one that appears on the page and style that. To do via CSS, use the first-of-type selector - http://www.w3.org/TR/css3-selectors/#first-of-type-pseudo
div.splitscreenleft:first-of-type { display: none; }
To do this via JavaScript, you can find the parent object and then hide it:
document.getElementById("toplevel").parentNode.style.display = 'none';
You should be able to do it similarly in jQuery:
$(".splitscreenleft:has(#toplevel)").hide();​
This can be accomplish by CSS, using structural pseudo-classes alone:
.parentClassName .className :nth-child(n) { display: none; }
Where n is the element you want to select. In your case you have two elements with the same class. To hide the first one, just replace n with 1, or 2 to hide the second one. You get the idea.
If you can't get access to jQuery with JS (haven't tried in chrome), you could always say
$('#topLevel').parent().hide();
the code below can change the class you defined in style sheet.
document.getElementById("testPara").className = "yourclass";

Getting last-child of a div in IE8?

Is there another way to get the last child of a div element other than using div:last-child, which does not work in IE8 at least?
In jQuery it's easy:
$("div :last-child")
In pure CSS it can't be done.
Otherwise you're stuck with traversing the DOM in Javascript.
Also note the difference:
"div :last-child": every last child of a div; and
"div:last-child": every div that is a last child.
Unfortunately, I know not a way to do this in CSS without using :last-child, which (as you stated) fails in IE.
If you're talking about javascript, then it's possible using Node.lastChild:
var div = document.getElementById("mydiv");
var lastChild = div.lastChild;
Use jQuery to find the appropriate elements: $("div:last-child").addClass("last-child");
Then use CSS to specify the presentation: div .last-child { /* your rules */ }
You can assign a class 'last' programmatically and select that one or use javascript. You might also have a shot by using some of Microsofts IE only css script thingies. But I do not know much about them, also do not consider that as an option.
I do this with pure JavaScript by looping back through the nodes from the lastChild of the target element. If there is whitespace in your HTML, the lastChild may be a text node, so we loop until we find an element node (node type 1) or until we run out of nodes (previousSibling will return null).
For example, to find the last element in a page, I loop back from the lastChild of the body:
var targetElement = document.getElementsByTagName("body")[0],
lastChildElement = targetElement.lastChild;
while (lastChildElement && lastChildElement.nodeType !== 1) {
lastChildElement = lastChildElement.previousSibling;
}
if (lastChildElement) {
// Do something
}
If there is no element inside the body, lastChildElement will exit this loop as null.
There are some cases in which you definitely don't want to use $("div:last-child") out of the box. One important thing to note is that this won't cater for changes to the DOM after that call - e.g. if a new element is added as the last child, you'll need to update things. It's not just a case of repeating the earlier call, either; you'll need to reverse the initial call on the previous last child.
If you're doing anything vaguely dynamic, be wary of this. the CSS pseudo-class is definitely the superior solution, it just has a horrible lack of support in IE. If your design can cope with the loss of last-child support in IE, and you're using progressive enrichment, I'd highly recommend the CSS approach over JS.
Fast Forward >> 4 years later (2013)
It is now possible with CSS v3 (CSS3) and is supported by all major browsers (with IE being >= version 9).
If you travel back in time with IE <= version 8, then jQuery version < 1.x will sort you out (just as the other answers have pointed out).
Read more http://www.w3schools.com/cssref/sel_last-child.asp
var divs = $("id").getElementsByTagName('div');
var lastChild = divs[divs.length-1];

Categories

Resources