Do Something when a Child Element is Not Present - javascript

I'm trying to remove a toggle function from the page when a childElement is not present. This has to be done in vanilla javascript. Unfortunately, can not use jQuery. Here's what's going on.
when I run this in the console
let content = document.getElementById('productItemRates-1');
console.log(content.firstElementChild);
Code snippet is returned for checking if childElement is present:
<div class="product-rate-card">
<div class="product-rate-card-title">
<strong>Clean Power</strong>
<button type="button" class="card-btn-plain card-tooltip" data-toggle="modal" data-target="#PK1" data-original-title="" title="">
</button>
</div>
</div>
Which is the firstElementChild: div.product-rate-card
What I'm trying to do:
Define logic to only remove the toggle button from all locations on the page (not specific to element) if the specific firstElementChild: .product-rate-card is not present in the ParentID: productItemRates-1. There are other references of the childElement: .product-rate-card found in other parentsIDs within the page. Also, order logic wont work because other childElements can take it's place when it is not present.
Used the below code to test removal, that worked, just can't figure out the conditioning logic.
document.querySelectorAll(".product-rates-toggle").forEach(el => el.remove());
Appreciate any guidance..

// replace document to content
if (!document.querySelector(".product-rate-card")) {
for (const el of document.querySelectorAll(".product-rates-toggle")) {
el.remove();
}
}

Based on a comment of yours:
const toggleratecard = document.querySelector("#productItemRates-1");
if (toggleratecard.querySelector('.product-rate-card') === null) {
toggleratecard.querySelectorAll(".product-rates-toggle").forEach(el => el.remove()); }
}
Unfortunately your question does not offer any information as to where the toggle is that needs to be removed. My answer assumes it's in the toggleratecard. You can replace that with document if all the toggle on the whole page need to be removed.
Also, from what you write, it isn't entirely clear if the element, if present, must be the first element child.

Related

When a div with a class contains a certain text, hide another text

How can I add a class to a div when another div on the same page contains a specific word?
My html is:
window.addEventListener("load", () => { let b = document.getElementsByClassName('aw-property-data-item')[0].innerHTML; b.includes("Verhuurd"); document.querySelector(".nf-form-cont").classList.add("displaynone"); });
<div class="aw-property-data-item">
<p><strong>Status:</strong> Verhuurd</p>
</div>
<div id="nf-form-7-cont" class="nf-form-cont">
form content goes here
</div>
This works, the class displaynone is added.
On objects that contain "Te Huur" rather than "Verhuurd" the class displaynone is also added. This should not be the case, but I can't figure out why this is happening. Any advice is very much appreciated!
b.includes("Verhuurd"); document.querySelector(".nf-form-cont").classList.add("displaynone");
You are just adding the class in any case here, you did not make this dependent on any condition.
This should be something like
if( b.includes("Verhuurd") ) { document.querySelector(".nf-form-cont").classList.add("displaynone"); }
Your includes() is probably matching "huur" and therefore including divs that contain "Te huur" as well as the ones you're looking for. Consider making it more specific with another condition to exclude divs that you don't want.
window.addEventListener("load", () => {
let b = document.getElementsByClassName('aw-property-data-item')[0].innerHTML;
if (b.includes("Verhuurd") && !b.includes("Te")) {
document.querySelector(".nf-form-cont").classList.add("displaynone");
}
});

BootstrapToggle switch conditionally switch state

I'm trying to use bootstraptoggle in one of my pages. The initial state is off / disabled.
The page loads several boolean values and stores them as hidden text. Then I have a script which looks them up via their IDs. Upon that hidden text it should toggle the slider.
I was able to get the hidden text and make the conditional check but I'm not able to toggle the slider for some reason.
Here is my code:
$(document).ready(function () {
var flags = [];
var userID = '',
toggleSlider = '';
flags = document.querySelectorAll('*[id^="activeFlag_"]');
flags.forEach(function (flag) {
userID = flag.id.split('_')[1];
// This is where i search for the hidden text
if (flag.firstChild.data == 'True') {
// Nothing works here.
$('#activeToggle_' + userID).bootstrapToggle('toggle');
}
});
});
And this is the html code that I need to work with:
<p id="activeFlag_#user1">#item.activeFlag</p>
<div class="checkbox">
<label>
<input id="activeToggle_user1" type="checkbox" data-toggle="toggle" data-on="Enabled" data-off="Disabled">
</label>
</div>
Your code is too opaque without any data example.
However one thing could be a cause of its problem:
if (flag.firstChild.data == 'True') {
Try to replace it with:
if (flag.firstElementChild.data == 'True') {
Here you could find explanation:
The firstChild property returns the first child node of the specified node, as a Node object.
The difference between this property and firstElementChild, is that firstChild returns the first child node as an element node, a text node or a comment node (depending on which one's first), while firstElementChild returns the first child node as an element node (ignores text and comment nodes).
Note: Whitespace inside elements is considered as text, and text is considered as nodes (See "More Examples").
Update after example code was added
For the example code you provided, you should change the split argument:
userID = flag.id.split('_')[1];
to:
userID = flag.id.split('_#')[1];
Thanks to twain for initial jsfiddle. I have updated it accordingly: jsfiddle
I guess the problem is, that the following part does not use the correct id for the toggle $('#activeToggle_' + userID).bootstrapToggle('toggle');
Your html ID is activeToggle_user1, but the js part above will probably resolve to #activeToggle_1. So the text user is missing here.
I created a working fiddle here: https://jsfiddle.net/pbcrh5d2/
Ok, for some reason asp.net and javascript have a problem with coping together. I used asp.net to provide javascript to build the strings.
So I switched to the raw id that is used in the table.

Remove any specific html code using javascript

In the past I used Google Developer Console to delete some specific divs on a page. I could do it manually of course but in some cases where the divs where many I had to use the console. I had a single line code that did the job (I found it while searching the internet) but I lost my note.
So how can I delete using javascript any html code (by copy pasting the code).
Something like:
elements = $('<div ... </div>');
elements.remove();
OR
$('<div ... </div>').remove();
Any ideas? I am not an expert in javascript (obviously) and I've been searching stackoverflow for hours without finding anything that works.
UPDATE: I think some people might get confused with my question. Google developer console accepts javascript command lines. So even though I ask for javascript I will use the code on the google developer console.
UPDATE 2 :
Here is an example of a div I need to delete. Keep in mind I want to copy paste the entire code in the javascript code. Not just identify the div.
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
It's the data-entry-status="declined" that makes that div unique so I can't just identify the div using an id selector or a class selector. I need to put the entrire thing there and remove it.
I tried:
$('<div class="entry-status-overlay" data-entry-status="declined"><div class="entry-status-overlay__inner"><span class="entry-status-overlay__title">Declined</span></div></div>').remove();
It didn't remove the div.
Try to search the dom by its outerHTML.
function deleteDomByHtml(html){
html=html.replace(/\s/g,'');
$("*").each(function(){
if(this.outerHTML.replace(/\s/g,'')===html){
$(this).remove();
}
});
}
And try this line on this page:
deleteDomByHtml(`<span class="-img _glyph">Stack Overflow</span>`);
You cannot do by simply pasting the code. That will remove all the div element.
You may need a specific selector like id,class or child to specific parent to remove the element from the dom.
Consider this case the divs have common class but the data-entry-status is different. So you can get the dom using a selector and then check the dataset property.
For demo I have put it inside setTimeout to show the difference. In application you can avoid it
setTimeout(function() {
document.querySelectorAll('.entry-status-overlay').forEach(function(item) {
let getStatus = item.dataset.entryStatus;
if (getStatus === 'declined') {
item.remove()
}
})
}, 2000)
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div class="entry-status-overlay" data-entry-status="accepted">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">accepted</span>
</div>
</div>
Just add any attribute with [] and it will remove the element.
$('[class="entry-status-overlay"]').remove();
/*OR*/
$('[data-entry-status="declined"]').remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
function del(){
var h = document.body.outerHTML;
h = h.match('<div>...</div>');
h.length--;
return h;
}
I guess this will work just give it a try... i tried on browser console and it worked, this way you can match the exact you want.
I might as well add my take on this. Try running this in your console and see the question vanish.
// convert the whole page into string
let thePage = document.body.innerHTML,
string = [].map.call( thePage, function(node){
return node.textContent || node.innerText || "";
}).join("");
// I get some string. in this scenario the Question or you can set one yourself
let replacableCode = document.getElementsByClassName('post-layout')[0].innerHTML,
string2 = [].map.call( replacableCode, function(node){
return node.textContent || node.innerText || "";
}).join("");
// replace whole page with the removed innerHTML string with blank
document.body.innerHTML = thePage.replace(replacableCode,'');
If you want to identify divs with that particular data attribute, you can use a data-attribute selector. In the example below, I've used a button and click event to make the demo more visual, but in the console the only line you'd need would be:
$('div[data-entry-status="declined"]').remove();
$(function() {
$("#testbutton").click(function() {
$('div[data-entry-status="declined"]').remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div id="x">Some other div</div>
<button type="button" id="testbutton">Click me to test removing the div</button>
See https://api.jquery.com/category/selectors/attribute-selectors/ for documentation of attribute selectors.
P.S. Your idea to paste some raw HTML into the jQuery constructor and then execute "remove" on it cannot work - you're telling jQuery to create an object based on a HTML string, which is, as far as it's concerned, a new set of HTML. It does not try to match that to something existing on the page, even if that exact HTML is in the DOM somewhere, it pays it no attention. It treats what you just gave it as being totally independent. So then when you run .remove() on that new HTML...that HTML was never added to the page, so it cannot be removed. Therefore .remove() has no effect in that situation.

work on all <span> at the current <div> then check for the value of an attribute of the <span>

i am kinda stuck with my javascript, I am making a greasemonkey script for a site, that restricts me to use plain-old javascript only. For now, my script currently does is, search for all the tables, and table row with ProjectTable-row then for each ProjectTable-row look for a div with ProjectTable-status, if that div is not found, it will delete the whole row.
it works great.
document.getElementById("gmSomeID").onclick = function showAlert() {
console.log('invoked');
var projectDescriptions = document.querySelectorAll('tr.ProjectTable-row'),
projectDescriptions = Array.prototype.slice.call(projectDescriptions);
projectDescriptions.forEach(function(el) {
if (el.querySelector('div.ProjectTable-status')) {
} else {
el.parentNode.removeChild(el);
}
});
}
but, now I do not know how to work on the current div and loop on all span inside it. I am still 2 steps short.
Loop on all span
Search for all span which contains data-content="apple" if none of the span has this attribute, then delete it.
Something like this:
For a HTML tag like this:
<div class="ProjectTable-status">
<span data-content="apple">
</span>
</div>
this will not be deleted data-content is apple.
For a HTML tag like this:
<div class="ProjectTable-status">
<span data-content="banana">
</span>
</div>
this will be deleted, no span has data-content="apple".
For HTML code like this:
<div class="ProjectTable-status">
<span data-content="banana"></span>
<span data-content="apple"></span>
</div>
this will NOT be deleted, the div contains at least 1 span that has data-content of apple.
I have no idea, how to proceed now and really tired or trying anything, i do not even know how to check for attribute value.
Hope someone can guide or put me at the right path.
Thanks!
Starting with what you provided, I've just slightly refactored it to check for an "apple" span within each div as it loops through. Using continue, we can execute the next iteration of the loop without deleting the div element if we find that it contains an "apple" span. This code is not tested, but just what came off the top of my head, so it might need some tweaking.
document.getElementById("gmSomeID").onclick = function showAlert() {
console.log('invoked');
var projectDescriptions = document.querySelectorAll('tr.ProjectTable-row'),
projectDescriptions = Array.prototype.slice.call(projectDescriptions);
//pointer to work with current div
var currentDiv;
projectDescriptions.forEach(function(el) {
currentDiv = el.querySelector('div.ProjectTable-status');
//do we have a div?
if (currentDiv) {
//look for an apple within the div
if(currentDiv.querySelector('span[data-content="apple"]')){
//go to the next iteration of the loop without delete
continue;
}
}
//if we made it this far, we didn't find an apple
el.parentNode.removeChild(el);
});
};

Javascript show/hide - I don't want it to hide the entire element

This is probably a fairly easy question, but I'm new to JavaScript and jquery....
I have a website with a basic show/hide toggle. The show/hide function I'm using is here:
http://andylangton.co.uk/articles/javascript/jquery-show-hide-multiple-elements/
So here's my question..... I would really like the first 5-10 words of the toggled section to always be visible. Is there some way I can change it so that it doesn't hide the entire element, but hides all but the first few words of the element?
Here's a screenshot of what I would like it to do:
http://answers.alchemycs.com/mobile/images/capture.jpg
There are many different implementation possibilities:
You can divide the contents up into the first part and the second part (two separate spans or divs inside your main object) and hide only the child object that represents the second part, not hide the parent object.
Rather than hide the object at all, you can set its height to only show the first part (with overflow: hidden)
Change the contents of the main object to only have the first part as the contents (requires you to maintain the full contents somewhere else so you can restore it when expanded again).
Here's a working example of option 1: http://jsfiddle.net/jfriend00/CTzsP/.
You'd need to either:
Put in a span/etc. after the first n words, and only hide that part, or
Change the viewable region, or
Replace or toggle the span/etc. with the "collapsed" view.
The last is a bit more customizable; using two separate elements allows trivial games to be played (showing an image, for example, like a little curly arrow) without modifying adding/removing DOM elements.
I tend towards the last because it's simple and obvious, but that's a personal preference, and really isn't as true as it used to be.
You can do some plugin authoring,I did a sample demo here ,based on your screenshot
<div class="toggle">ShowHide</div>
<div class="content">some content some content some content some content some content <br/> some content some content some content </div>
<div class="toggle">ShowHide</div>
<div class="content">some content some content some content some content some content <br/> some content some content some content </div>
here is javascript/jquery code
jQuery.fn.myToggle = function(selector, count) {
var methods = {
toggle: function(selector, count) {
if ($(selector).is(':visible')) {
var span = $('<span>');
span.text($(selector).text().substr(0, count) + "...");
span.insertAfter($(selector));
$(selector).hide();
}
else {
$(selector).show();
$(selector).next('span').hide();
}
}
};
$(this).each(function() {
methods.toggle($(this).next(selector), count);
$(this).click(function(evt) {
methods.toggle($(this).next(selector), count);
});
});
};
$(function() {
$('.toggle').myToggle('.content', 3);
});
Here is a solution using css properties only instead of mangling the dom.
http://jsfiddle.net/AYre3/4/
Now if you want some sort of animation happening as well you'll probably need to do a bit of measurement along the way.

Categories