Replace all childnodes that have classname attribute in java script - javascript

I am using Selenium Webdriver for my project. I have a webpage where there are multiple menu items which in turn has sub menu items. I want to replace the classname attribute for all child elements under the nav-left-main div tag with "" (space) so that all elements are visible in the main page to click (instead of navigating to each menu->sub menu)
Basically i want to find all elements with classname under id=main and replace them with ''. How do i do that with JavaScriptExecutor in selenium webdriver?
<div id="nav-left-main">
<div>
<a class="left-nav-icons icomoon-icon-users3 " title="Users" href="#Users-tab">
<div id="Users-sub" class="nav-left-subnav">
<div id="Users-tab" class="hidden-menu">
<ul class="level3menu">
<li>
<i class="cm-icon18 iconfont-arrow-sans-right" style="margin-top:-2px;margin-left:-17px;"></i>
<a>Users</a>
<ul class="second-level-hidden-menu" style="margin-left:5px;margin- top:10px;">
<ul class="second-level-hidden-menu" style="margin-left:5px;margin-top:10px;">
<ul class="second-level-hidden-menu" style="margin-left:5px;margin-top:10px;">
</li>
</ul>
<ul>
<li>
<a id="AdminGroups" class="$item.className" title="" href="cms?action=groupList&pageTitle=Groups">Groups</a>
</li>
</ul>
<ul>
</div>
</div>
</div>

This might work for you:
var main_div = document.getElementById("nav-left-main");
var all_childs = main_div.getElementsByTagName("*"); // get all child elements
for (var i=0; i<all_childs.length; i++)
{
if ( all_childs[i].hasAttribute("class") ) all_childs[i].className = ""; // or all_childs[i].removeAttribute("class")
}

I'm assuming you're trying to write some automated tests. Consider this: if you modify the UI content, you just might affect the behavior of something else on the page (e.g. some JS assuming those class-attribute values might stop functioning).
Alternatively, inject CSS (via STYLE or LINK) that changes the appearance and visibility of those elements (hint: !important). However, even this, theoretically, is not ideal solution, because like-JS (for example) might go bananas for the same reason.
I'm not experienced in testing webpages, but isn't the point of Selenium to automate behavior of a human user? In other words, maybe the best would be to write test-code to activate the menu the same way human-user would (mouseover, etc).

Related

When hovering over an element with a certain index, change the styles of the element in another parent with the same index

I have a menu on the site in two places. One is made by text, and the other by pictures. You can click on both.
I want that when you hover over a specific item in a text menu (for example, under number 2), the picture with the same number changes (for example, under 2).
Code for text menu:
<ul>
<li class="page_item">
Test 1
</li>
<li class="page_item">
Test 2
</li>
</ul>
Code for Pictures menu:
<div class="project__card project__card-design">
<div class="project__card-design-bigelem">
</div>
<div class="project__card-design-bigelem">
</div>
<div class="project__card-design-bigelem">
</div>
</div>
Screen shot with Picture and text menu:
Screen shot with Picture and text menu
I will be grateful for any help!
Since I was looking for solutions that could identify the element with which number was highlighted. But so far I don’t even have ideas on how to do this.
All thanks in advance for any help!
If you like for this behaviour you can do this
hover: nav1 > imageNav1 ect...
You can get the index of the hover item and match that to the image nav item. Sorry for the markup, it's just to show you how you can implement it. You can also choose to do whatever after the matching is made in the mouseenter
$(".js-hover").on("mouseenter", function () {
const hoverIndex = $(this).index();
const $imageListItems = $(".image-list > li");
$imageListItems.removeClass("image-list__item--selected");
$imageListItems.eq(hoverIndex).addClass("image-list__item--selected");
});
.image-list__item--selected {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="list">
<li class="js-hover">text</li>
<li class="js-hover">text</li>
<li class="js-hover">text</li>
<li class="js-hover">text</li>
</ul>
<ul class="image-list">
<li>image1</li>
<li>image2</li>
<li>image3</li>
<li>image4</li>
</ul>
Here's a solution with pure js, works for elements that are not parents using ids.
html
<li id="child1" onmouseenter="customHover(event)" onmouseleave="handlemouseleave(event)"></li>
<div id="parent1"> </div>
<li id="child2" onmouseenter="customHover(event)" onmouseleave="handlemouseleave(event)"></li>
<div id="parent2"> </div>
<li id="child3" onmouseenter="customHover(event)" onmouseleave="handlemouseleave(event)"></li>
<div id="parent3"> </div>
and heres the js
function customHover(e){
let id = e.target.id;
let idNumber = id.slice(id.length - 1);
document.getElementById(`parent${idNumber}`).style.border = '1px solid red';
}
function handleMouseLeave(e){
let id = e.target.id;
let idNumber = id.slice(id.length - 1);
document.getElementById(`parent${idNumber}`).style.border = 'unset';//or whatever you need to change the styles back to the original
}
there are many solutions , with an without using libraries. I think you may use some jquery if possible , and if not you should search for addeventlistener (the advanced way)
https://api.jquery.com/hover/
is a good example of doing what you are trying todo .
var pageitemcount=0;
$( ".page_item" ).hover(function() {
pageitemcount++;
$.post("/mypageitemcounter.php",{pageitemcount:pageitemcount});
$(this).parent().append( $( "<span>"+pageitemcount+"</span>" ) );
});
The above part is for php , still can be used in a plugin.
If you are in wordpress environment , you have to dig into how to write wp plugins also. Trying to achieve this in an environment , and then applying the same to your custom wp plugin is the way to go. Do not change the existing plugins, or themes if possible. This may cause headaches after an update.. In wp environment, writing a custom plugin is the way to go. You should tag your question as wp-plugin if possible.

How do I move these elements in DOM

I don't want to change HTML because I want to leave the display the way it is for default view and want to move them in second view. I want to know how I can dynamically order the class of a div.
I want to do this via button click. I have adEventListener() for 'click' where I am doing something and the move logic would go inside this event listener.
I understand that I can get these divs, remove from their parents and place it where I want. But I do not know how to do these for each of them since I have multiple lis. I am struggling with the loop so that I can do these for each li. I need to do this using pure JS and not jQuery.
<ul>
<li>
<div>
<div class="a">
<div class="b">
<a class="c">
<div class="d"></div>
<div class="e">
<div class="f"></div> // this is the first item that I want to move
</div>
<div class="g"></div> // this is the second item that I want to move
</a>
</div>
<div class= "h"></div> // I want above mentioned divs to be before this div
</div>
</div>
</li>
//There are multiples lis
<li></li>
Assuming you would like to do this on load of the page, you could solve your problem with the following JQuery DOM manipulations:
$(document).ready(function(){
$("ul .a").each(function(index, element){
$current_div_a = $(element);
$div_h = $current_div_a.find(".h");
$div_f = $current_div_a.find(".f");
$div_f.clone().insertBefore($div_h);
$div_f.remove();
$div_g = $current_div_a.find(".g");
$div_g.clone().insertBefore($div_h);
$div_g.remove();
})
});
You can test it out on this demo.
I strongly advise against this way of doing it though. I guess it's also the reason why your question got some downvotes too. Just modifying your HTML keeps your code clean, maintainable and clearer for anyone else starting to work on your project. Keeping backwards compatibility for your code as much as possible will cause maintainability problems later.
I ended up using
var list = document.querySelectorAll("ul li");
for (var item of list) {
let fClass = item.querySelector(".f");
fClass.parentNode.removeChild(fClass);
let parentOfFirstChildAfterWhichIwantMyF = item.querySelector(//selector for parentOfFirstChildAfterWhichIwantMyF);
parentOfFirstChildAfterWhichIwantMyF.insertAdjacentElement("beforeend", fClass);
}

Replacing text on web page using HTML or Javascript

I am customizing an HTML page provided and hosted by a third-party, so I am severely restricted in what I can do to the page. On the page there is a navigation menu that looks like this.
<ul class='nav'>
<li class='active'>
<a href='/affiliate'>
<span id='affiliate-nav-homepage'>
<span class='default'>Home Page</span>
</span>
</a>
</li>
<li>...
Question: How can I make the above snippet display the text "Home" instead of "Home Page", if all I am allowed to do is add a <style> element in the page <head>; and add some HTML code (which may include Javascript) near the start of the page?
I have a considered going down one of these two paths, but both paths are problematic.
1) Use CSS to hide their text ("Home Page"). Add my own text ("Home") using :before or :after pseudo-selectors.
display: none is probably not a good way to hide the text, because browsers that don't understand :before and :after will still understand display: none and I will end up with no text at all.
Are there better CSS alternatives for me? Change font size to 0? change text color? Manipulate z-index somehow? It is OK if some older browsers display the text "Home Page". It is not OK if some browsers display "Home Page Home", or if some browser do not display any text at all.
-- OR --
2) Use Javascript to manipulate the DOM
The difficulty with Javascript is that I can only insert it near the start of the page body before the elements that I want to modify. I could hook an event that fires after the entire page is loaded, but I want to avoid the page text flashing (the text "Home Page" being displayed briefly and then changing to "Home"). Is there such an event and how would I hook it?
Thank you for you help.
Anti flashing fix:
.default { display: none; }
Changing text and showing, when document is ready:
body.onload = function (){
//getElementsByClassName not working in old browsers, so ...
var el = document.getElementById('affiliate-nav-homepage').getElementsByTagName('span')[0];
el.innerHTML = 'Home';
el.style.display = 'block';
};
Additional You can hide all content and show it after all javascript changes by this method.
This is not elegant solution, but as You say, You have limited options to resolve Your problem.
In JavaScript
window.addEventListener("load", function(){
document.querySelector("span.default").textContent = "Home";
//using document.querySelector to select the span with classname default
//using textContent to change the content of the node.
}, false);
In a script block will do it.
This will execute on page load. This will be executed so fast that in almost all cases you won't see text jumping.
Example:
window.addEventListener("load", function(){
document.querySelector("span.default").textContent = "Home";
}, false);
<ul class='nav'>
<li class='active'>
<a href='/affiliate'>
<span id='affiliate-nav-homepage'>
<span class='default'>Home Page</span>
</span>
</a>
</li>
</ul>
When your page loading becomes slowed by other resources, #Mateusz Mania's idea of using CSS to hide the element and bring it up again is actually pretty nice. I would suggest using opacity: 0 or visibility: hidden instead of display:none since the latter will remove the element from the page and when it becomes visible again it will make the content jump down below it.
Exploring the CSS option
#affiliate-nav-homepage:before{
content: "Home";
}
.default {
display: none;
}
<ul class='nav'>
<li class='active'>
<a href='/affiliate'>
<span id='affiliate-nav-homepage'>
<span class='default'>Home Page</span>
</span>
</a>
</li>
</ul>

How to add class to an element if a different element on the page has a certain class

jsfiddle.net/8KgRd
I'm trying to select the first header in my main container and add a class to it. But I want this to be dependent on what section of the website they are on.
For example. If they are on the "EAST Core" page, I want the header to be orange.
The HTML is populated by the backend so I can't hardcode the classes in.
HTML
<ul id="mainNav" class="nav navbar-nav">
<li class='linked'>EAST Program
</li>
<li class='active linked'>EAST Core
</li>
<li class='linked'>Get More Involved
</li>
<li class=''>Sponsors & Exhibitors
</li>
<li class=''>Newsroom
</li>
</ul>
<div id="mainbar">
<h1>This is the title I want to add a class to.</h1>
</div>
.
JAVASCRIPT
if ($("#mainNav li:nth-child(2)"): hasClass("active")) {
$("#mainbar h1:first-child").addClass("orangeHead");
};
UPDATE: Solved by:
if ( $("#mainNav li:nth-child(2)").hasClass("active") ) {
$("#mainbar h1:first-child").addClass("orangeHead");
}
One way would be:
$("#mainNav li:nth-child(2).active")
.closest("#mainNav").next()
.find("h1:first-child").addClass("orangeHead");
Another way (your original way with syntax error fixed):
// this is probably the "better" way to do it of the two
if ( $("#mainNav li:nth-child(2)").hasClass("active") ) {
$("#mainbar h1:first-child").addClass("orangeHead");
}
You can get the index of the active navigation element, and then update the other element based on this information, e.g.:
var colorClasses = ['redHead', 'orangeHead', 'blueHead', 'greyHead', 'purpleHead'],
index = $("#mainNav").children(".active").index();
$("#mainbar").addClass(colorClasses[index]);
This is a bit more modular than your code and will be easier to maintain (no need to have different code on different pages, this will work on all pages). Basically the index of the active element just needs to line-up with the index of the colors array for the class that gets added to the #mainbar element.
you can toggle the class of header depending on the active state of you li
$("#mainbar h1:first-child").toggleClass("orangeHead", $("#mainNav li:nth-child(2)").hasClass("active"));
it's interesting how you can have different ways to achieve the same result. Here is another option
toOrange = $("#mainNav").find("li").eq(1);
if( toOrange.is(".active") ){
$("#mainbar > h1").addClass("orangeHead");
}
See JSFIDDLE
I personally give preference to the .eq() method over pseudo classes, which is (arguably) faster in many cases.

Href: Target ID in Current DIV

I have a list of <li> items being generated from a CMS/DB. Each <li> has a <div> in it which contains a link to a lightbox (a hidden <div>). The link targets the id of the hidden <div> (#inline-content-print) so the javascript plugin triggers and pulls up the lightbox.
The problem I'm running into is that all of the <li>s on the page generate with the same hidden div id (I can change this to classes). So no matter which <li> href is clicked, it always pulls up the lightbox for the first <li> on the page (the first instance of the id). I need a way for the href to say "open #inline-content-print" from THIS div (the one the link being clicked lives in)".
<li>
<div class="store-buttons-bg hide-print-buttons-{tag_Hide-Print-Buttons}">
PRINT
<div style="display: none;" id="inline-content-print">
CONTENT OF LIGHTBOX
</div>
<!-- end inline-content-print -->
</div>
</li>
Any advice would be greatly appreciated.
What server side language are you using? Is it producing these list items in a loop? Is there an index on that loop? If so, this would work for you.
[Server language version of a for loop with an index variable named "i"]
<li>
<div class="store-buttons-bg hide-print-buttons-{tag_Hide-Print-Buttons}">
PRINT
<div style="display: none;" id="inline-content-print_[server language output of "i"]">
CONTENT OF LIGHTBOX
</div>
<!-- end inline-content-print -->
</div>
</li>
[server language version of an end to the for loop]
Assuming you want to do this with jQuery/Javascript, you could use something like this:
$(document).ready(function()
{
$('li a.store-button').click(function(e)
{
var lightboxElement = $(e.currentTarget).find('div');
lightboxElement.show(); // or whatever function you need to display
return false;
});
});
Which is a little script that:
Waits for the page to load.
Finds your list elements (by li object type and the class on the links)
Intercepts click events.
Finds the div element nested in the link that was clicked.
Displays (or runs another function) on the target lightbox element.

Categories

Resources