Detect a word and addClass to body - javascript

The jQuery below detects the word first and third in any <p> text and adds a yellow or red background to it.
$(document).ready(function(){
$("p:contains(first)").css("background-color", "yellow");
$("p:contains(third)").css("background-color", "red");
});
<p>I'm the first sentence.</p>
<p>I'm the second sentence.</p>
<p>I'm the third sentence.</p>
<p>I'm the fourth sentence.</p>
JSFiddle: https://jsfiddle.net/3p0nmw4f/1/
However, instead of highlighting the text, I want to addClass to the body of the html document like this :
<body class="first">
or
<body class="third">
I know we can achieve this using $(document.body).addClass('first'); but I'm unable to put it together.
Please help.

You could search for the closest body HTML element.
You can do this by doing the following:
$(document).ready(function(){
$("p:contains(first)").closest('body').addClass('first');
$("p:contains(third)").closest('body').addClass('third');
});
Another possibility would be to simply search for the body element as follows:
$(document).ready(function(){
if ($("p:contains(first)"))
$("body").addClass("first")
if ($("p:contains(third)"))
$("body").addClass("third")
});
Source: https://jsfiddle.net/fk05dabw/

Related

jQuery hover() and delegation

I'm creating an incremental search using jQuery, the rest of my code works fine, but when I'm trying to highlight only the element being hovered inside the search doesn't work, it starts highlighting all the others. Because the "p" tags are generated AFTER the HTML file is loaded in the browser, they need to be delegated like i wrote on the code.
How could i fix that?
$(document).on("mouseover", "p", function (e) {
e.target.classList.add("highlight");
});
You need to remove the highlight class from all other <p> elements before adding it to the element hovered on:
$(document).on("mouseover", "p", function(e) {
$("p").removeClass("highlight");
e.target.classList.add("highlight");
});
.highlight {
background: #FF0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>This is a paragraph with some text</p>
<p>This is a paragraph with some text</p>
<p>This is a paragraph with some text</p>
<p>This is a paragraph with some text</p>
<p>This is a paragraph with some text</p>

jQuery: Select grandparent's h1 tag

I'm working within a really rigid framework (NetSuite) and there's a small section that I have direct control over which is the h3 and p text below. The structure is similar to this:
<div class="grandparent">
<h1>Title Text</h1>
<div class="otherstuff">Some text</div>
<div class="parent">
<h3>Text I have control over</h3>
<p>More text I have control over</p>
</div>
</div>
I want to hide the title text and the contents of '.otherstuff' for this page. There are multiple pages similar to this so I'm looking for a clean way of getting it done.
I've tried giving the h3 tag a class, then the following:
$('h3.myclass').parent().closest('h1').css('display','none);
and variations of that but without any luck. I've looked into the .parentUntil() function but I run into the same problem. I have no problem grabbing ancestor elements but run into trouble when trying to grab elements of those ancestors.
Can anyone help me out?
EDIT: Thank you everyone for your time and effort in answering my question. I really appreciate it!
Use closest() to traverse up to the grandparent
Use find() to select the desired elements
You can use hide() in place of css('display', 'none') as they are equivalent
var grandparent = $('.myclass').closest('.grandparent');
grandparent.find('h1, .otherstuff').hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="grandparent">
<h1>Title Text</h1>
<div class="otherstuff">Some text</div>
<div class="parent">
<h3 class="myclass">Text I have control over</h3>
<p>More text I have control over</p>
</div>
</div>
I can think of two selectors that might work assuming you put .myclass back in.
$('.myclass').closest('.grandparent').find('h1').css('display','none');
or
$('.myclass').parent().siblings('h1').css('display','none');
have direct control over which is the h3
Try utilizing .parent() , .siblings()
$("h3").parent().siblings().hide(); // `$(".parent").siblings().hide();` ?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div class="grandparent">
<h1>Title Text</h1>
<div class="otherstuff">Some text</div>
<div class="parent">
<h3>Text I have control over</h3>
<p>More text I have control over</p>
</div>
</div>
You may use:
$('.myclass').closest('.grandparent').find('>h1,>.otherstuff').hide();
> is for direct descendant element.
closest() selects ancestors, what you want is siblings().
So:
$('.your_h3_class').parent().siblings('h1')
will return an array of h1 siblings of the parent div, and in your case the first item of that array is your h1.
And you can iterate through those and hide them (in case there is ever more than one)
If the title is always immediately before the div with the "otherstuff" class, then you could use this:
$('.otherstuff').prev('h1').css('display', 'none');
Documentation here: https://api.jquery.com/prev/

How to toggle specific divs with jquery

Okay so I have a very limited amount of knowledge with this and I can not find my answer anywhere. What I am trying to do is create multiple buttons that toggle information. So when the first toggle is clicked div 1 is toggled, when i click the second toggle div two opens and preferably div 1 closes. My code is very basic I am very new to this. Right now no matter what values I input into the toggle area both divs close. Thank you and I hope this makes sense.
Here is my code:
<script>
$(document).ready(function(){
$("button").click(function(){
$("div.house").toggle();
});
});
</script>
<button>Toggle</button>
<div class="house">
<p>SAMPLE TEXT ETC...</p>
</div>
<button>Toggle</button>
<div class="tumble-by">
<p>SAMPLE TEXT ETC...</p>
</div>
You can select the next sibling:
$("button").click(function(){
$(this).next().toggle();
});
In the above code, JavaScript this keyword refers to the clicked element. $(this) creates a jQuery collection and .next() method selects the very next sibling of the collection's element.
I agree too, that first you need to hide all divs:
$("button").click(function () {
$('div').hide();
$(this).next().toggle();
});
<script>
$(document).ready(function () {
$(document).on("click", ".js-toggle__button", function (e) {
$(".js-toggle__text").hide();
$(this).next(".js-toggle__text").show();
});
});
</script>
<button class="toggle__button js-toggle__button">Toggle</button>
<div class="toggle__text js-toggle__text">
<p>SAMPLE TEXT 1 ETC...</p>
</div>
<button class="toggle__button js-toggle__button">Toggle</button>
<div class="toggle__text js-toggle__text">
<p>SAMPLE TEXT 2 ETC...</p>
</div>
It's better to use uniquely defined identifiers when you accessing elements from JS (and don't use them for CSS — use separate names).
Your HTML code some day can be changed dramatically and JS will work anyway because it depends on identifiers but not on structure or on tag names.

Is there a way to check an element's attribute when using Event Delegation?

Using Event Delegation, is there a way to check the element that was fired if it has a particular attribute or specifically a class or an ID?
<ul>
<li><button>Make the first paragraph appear</button></li>
<li><button>Make the second paragraph appear</button></li>
<li><button>Make the third paragraph appear</button></li>
</ul>
<div>
<p class="first">First paragraph</p>
<p class="second">Second paragraph</p>
<p class="third">Third paragraph</p>
</div>
Let's say all the paragraphs are hidden initially and clicking on the first button, the first paragraph appears and clicking on the second button, the first paragraph is hidden and the second paragraph is displayed and when the third button is clicked, the second paragraph is hidden while keeping the first paragraph hidden as well.
My solution so far was to make a event handler for each specific button and hide the other two paragraphs while only showing one. It works but if the number of elements increased, the event handlers needed for each one would increase too. Is there a better way to do this?
If the index of buttons and paragraphs are the same then you can make use of .index():
$('button').click(function() {
var idx = $(this).index('ul li button');
$('div p').eq(idx).show().siblings('p').hide();
});
Fiddle Demo
or you can use data-* attribute if the index are different:
<ul>
<li><button data-parapgraph="first">Make the first paragraph appear</button></li>
<li><button data-parapgraph="second">Make the second paragraph appear</button></li>
<li><button data-parapgraph="third">Make the third paragraph appear</button></li>
</ul>
<div>
<p class="first">First paragraph</p>
<p class="second">Second paragraph</p>
<p class="third">Third paragraph</p>
</div>
then apply .data() to retrieve the data-* attribute:
$('button').click(function() {
var parapgraph = $(this).data('parapgraph');
$('p.' + parapgraph).show().siblings('p').hide();
});
Fiddle Demo
I think if you can make sure the position of the button and the p to be displayed are the same then you can use an index based solution like
jQuery(function ($) {
var $ts = $('div > p');
$('ul button').click(function (e) {
$ts.hide().eq($(this).parent().index()).show()
})
})
Demo: Fiddle
I would rather use <a> instead of buttons and then use the href attribute for the identifying, and use id's for paragraphs
<ul class="link-list">
<li>Make the first paragraph appear</li>
<li>Make the second paragraph appear</li>
<li>Make the third paragraph appear</li>
</ul>
<div>
<p id="first">First paragraph</p>
<p id="second">Second paragraph</p>
<p id="third">Third paragraph</p>
</div>
$('.link-list').on('click','li > a',function(){
//id would be something like #first
var id = $(this).attr('href');
//we use it as a selector (you can also use $('div.classname').find(id);
var $paragraph = $(id);
// we show our desired paragraph and hide its siblings
$paragraph.show().siblings().hide();
// make sure the browser does not follow the link/anchor
return false;
});
Fiddler

Curious about hide().after("") in jQuery

I have some code at here:
html:
<body>
<p>This is a paragraph.</p>
<button>click me</button>
</body>
Javascript:
$(document).ready(function(){
$("button").click(function(){
$("p").hide().after('<p>hello world</p>');
});
});
Actually, I've using JQuery 2.0.2 also.
In my understanding, When I click the button click me, "<p>This is paragraph<p>" will be replaced by <p>hello world</p>.
The first click is successful. However, many hello world with the growth rate of progression show after the first hello world shown. For example:
I've checked the source code by firebug, and find it is:
<p style="display: none;">This is a paragraph.</p>
<p>hello world</p>
<p style="display: none;">hello world</p>
<p>hello world</p>
<button>click me</button>
Why the first <p>hello world</p> wasn't be replaced by the new one?
Doesn't it suppose to show one p tag only?
That's cause you're creating paragraphs
<p>hello world</p>
and on every click the $('p') is a collection of all p elements on your page.
The more paragraphs you have... more appends. live demo - issue example
An element, even if set to display:none using .hide(), is still present in your document..
What you're up to is probably one of the following:
$("button").click(function(){
$("p").html('hello world');
});
$("button").click(function(){
$("p").text('hello world');
});
$("button").click(function(){
$("p").replaceWith('<p>hello world</p>');
});
$("button").click(function(){
$("p").after('<p>Hello world</p>').remove();
});
If only you want to change the text you an do like this
$(document).ready(function(){
$("button").click(function(){
$("p").html('hello world');
});
});
JS FIDDLE
after('<element/>') means generate an element and insert it after the selected element(s), you are generating and inserting an element after all the selected p element(s), on the first click you are adding 1 element, on the second click 2 elements and so on, because after each click there are more than one p elements. after doesn't replace anything.
Well, there is nothing surprising that is happening here. Actaully that is what should happen, since you are adding <p> tag after hiding the first <p> <p>This is paragraph<p>.
So your first click ends up having two <p> tag in the DOM and further clicks, adding more <p> tags. hide() does not removes the elements form the DOM; it just changes its display property. You can use replaceWith() or remove() to remove the first <p>, if you want this to work, as you needed.
$("p").after('<p>hello world</p>').remove(); //remove the selected `<p>` tag after `<p>is appended.</p>`
or
$("p").replaceWith('<p>hello world</p>');
It happens because you adding new p element after each p tag in document (even after hidden).

Categories