Javascript selectors how to only get first ranking a refs - javascript

Hi there I'm fiarly new to coding. and doing some javascipt layouting. but I need to make some variables. and don't know how. I want to make a dropdown menu. for this site. bertconinx.com now in order to do the thing I want to do I need to be albe to select a href without having to change any html. let the browser go to the link and then execute some javascript so what I need to do is find a way how to select the specific a href. I need to select the head menu intem without selecting any submen Items. because they should be dropdowns on a clickevent.
I got as far as this..
a href="http://bertconinx.com/category/portrets/">Portrets</a
a href="http://bertconinx.com/category/weddings/">Weddings</a>
should load first and then should dropdown his submenu clickevents.
but slecting the a href seems trick I've tried.
var MenuEvent = document.getElementsByClassName("menu-item").getElementsByTagName("a");
But it does not work.
Any Ideas on how to select them?
thanks.

The documentNode.getElementsByClassName returns a list of items, so while you can call .getElementsByTagName on each one, you can't call the function on the list directly. What you need to do is something like
// initialize an array to hold the anchors we get, and get all menu items on the document
var firstAnchors = [],
menuItems = document.getElementsByClassName('menu-item');
// iterate through the menu items and their specific anchors, adding only the first one of each menu item to our list
for(var menuItem of menuItems){
firstAnchors.push(menuItem.getElementsByTagName('a')[0]);
}
// now, our anchors should be here
console.log(firstAnchors);

var parentMenus = [],
parentMenueElems = document.getElementById("menu-main-nav").children;
for(var parentMenueElem of parentMenueElems){
if(!parentMenueElem){continue;}
var parentMenue = {
"name": parentMenueElem.firstElementChild.text,
"anchor": parentMenueElem.firstElementChild
};
parentMenus.push(parentMenue);
}
console.log(parentMenus)
OutPut:
[
{"name":"Portrets","anchor":element},
{"name":"Weddings","anchor":element},
{"name":"Wild","anchor":element},
{"name":"Commercial Work","anchor":element},
{"name":"About","anchor":element}
]
Example: element --> Portrets
Now you can perform any event on element
parentMenus[2].anchor.click();

Related

Getting the index of an array item in vanilla javascript when new items are pushed

<label for="accTopic">Accordion Topic</label><br/>
<input type="text" name="accTopic" id="accTopic"><br/><br/>
<label for="accordionPanel">Accordion Content</label><br/>
<textarea name="accordionPanel" id="accordionPanel" rows="20" cols="50"></textarea><br>
let items = [];
function getItems() {
let accTopic = document.getElementById("accTopic").value;
let accPanel = CKEDITOR.instances.accordionPanel.getData();
items.push(
{
topic: accTopic,
panel: accPanel,
}
);
return(items);
}
Hello and thank you for looking at this. I am hoping to figure out how to get the index of the above array so I can assign to a button for editing.
Project Info:
I'm hoping to create a tool that customers can use to build an accordion without writing HTML but just pasting the HTML into the source code of CK Editor.
My obstacle is assigning the index of the array to a variable that I can reference from the HTML to edit the topic/detail of an accordion item.
Basically, if I had to talk it out, would go like this:
Accordion item created. It's the third item in the array
There is a for loop that assigns the appropriate classes, IDs and attributes to the items which allows expanding/collapsing of items
There is an 'Edit' button that allows someone to edit the accordion item, which is identified by the index of the array via an HTML attribute. This assignment would be assigned in the for... loop. If it's the third item, the index would be 2 which would trigger an edit function.
Am I off-base with this? Please let me know and thank you,
You can directly get all the items using document.querySelectorAll and get the index of the clicked element using Array#indexOf.
let items = [...document.querySelector('.accordion').querySelectorAll('.accordion-item')];
let index = items.indexOf(elem);

Not able to identify element display values

I have photo gallery type of web page. It is comprised of grid of photo thumbnails, with assigned tags beneath them.
At top of page is a list of all of the tags, formatted as buttons. User can click on one or more tag buttons to filter photos. I am using Isotope js for this filtering. This works fine.
However I want to add new feature that runs after the Isotope filtering that will hide any tag buttons that are not assigned to any of the remaining filtered photos.
My plan was to do following:
identify all visible photos
create array from visible photos' tags
use array to hide any unmatched tags
However, I am having problems identifying visible photos after I click tag buttons and Isotope does its filtering.
It seemed like it would be quite straightforward. Isotope js changes a specified element's display = "none" for the hidden photos. Eg if I inspect the element, I can see hidden elements have display = "none"
I created a 'visibletags' function that is called at end of tag button on click to find elements where display != "none":
$('.filter-button').on('click', function() {
// isotope code here
// isotope hides some photos setting their div's `display = "none"`
visibletags();
}
function visibletags(){
var imgdivs = document.querySelectorAll('.imgdiv');
var showtags = [];
for (var i=0, max=imgdivs.length; i < max; i++) {
if (window.getComputedStyle(imgdivs[i]).display != "none") {
// this should be a div that is not hidden by Isotope js
// so loop through it's tags to build array
// array will be used later to hide unmatched tags
var phototagspans = imgdivs[i].querySelectorAll('.photo-tag');
for (var j=0, max=phototagspans.length; j < max; j++) {
showtags.push(phototagspans[j].className);
}
}
}
}
But I am not able to identify the element's display value. I have tried using window.getComputedStyle(imgdivs[i]).display, imgdivs[i].display and imgdivs[i].style.display
Edited to modify question:
I tested running the 'visibletags()' function as another button on click event that I manually click after the isotope filtering is complete. This successfully gets all photo element display values. So that part of code does work.
So my question now is how to run 'visibletags()' function after the Isotope filtering in a way that it is one complete set of code?
I tried changing the 'visibletags()' function to run as $('.filter-button').mouseup(function() but didn't get filtering results.
Maybe this is now general Javascript question eg how to get on click event's results after they have been rendered?
I'm not familiar with Isotope, but you probably need to use a callback function. Check out this documentation, especially the layoutComplete part: https://isotope.metafizzy.co/events.html
In your case, the result could be something like this:
$('.filter-button').on('click', function() {
// initialize isotope
$isotope.on('layoutComplete', function() {
visibletags();
});
// other isotope code here
}

Python Selenium- Print text from a list inside an element that updates on scroll in a dropdown

I am using Selenium and Python to grab a list of company names inside a drop-down menu on a page updated with javascript. I am able to click the nav button to make the list of company names visible and can also print the text of the first 50 or so rows.
The <div class="grid-canvas"> child elements update asynchronously when scrolling through the list. I have not been able to figure out how to grab the text of the Exhibitor Column for the company names that update on the scroll.
What is the best way to handle this problem?
driver.get('https://www.expocad.com/host/fx/afassanoco/18csm/exfx.html')
try:
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "nav-btn")))
if element:
driver.find_element_by_class_name('nav-btn').click()
finally:
table = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "exhGrid")))
if table:
print(driver.find_element_by_class_name('slick-viewport').text)
Thanks in advance!
I think Selenium is overkill for this task. You can simply download XML file:
https://www.expocad.com/host/fx/afassanoco/18csm/fxdata.aspx?FileName=18csm.xml
And parse it:
import xml.etree.ElementTree as ET
tree = ET.parse("18csm.xml")
for selem in tree.getroot().iter('S'):
company_no = None
company_name = []
for telem in selem.iter('T'):
if company_no == None:
company_no = telem.attrib['v']
else:
company_name.append(telem.attrib['v'])
if company_name != []:
print(company_no, " ".join(company_name))
You can find the element and trigger a scroll event via Javascript. Wait for the other names to load, and then you should be able to read them in the same way you read the first 50:
driver.executeScript("document.getElementById('SOME_SELECTOR').scrollDown += 100");
Not sure if you need to scroll through the grid-canvas or the slick-viewport, but you should find some selector that lets you get a scroll event in. If that doesn't work, you can also try either
driver.execute_script('scrollBy(0, 250)')
or sending the Keys.ARROW_DOWN event
Either way, you can keep that up until you reach the bottom of the list.

Append and remove values in a link

So I am using http://isotope.metafizzy.co to filter out different items on a site. The menu should be a "build up" type where when one category is clicked, it filters to those categories, when the next is clicked it adds those newly clicked categories to the existing filter of categories. When its clicked a second time it should remove that categorie from the filter.
More specifically, I have href with #filter and data-filter=".category-name" I need to have a function that would add ", .another-category" to the end of data-filter value for each of the links with name="filters" (or i can use a class instead of if easier)
<ul>
<li>Kitchens</li>
<li>Bathrooms</li>
<li>Living Rooms</li>
<li>Bedrooms</li>
</ul>
I know this function is wrong and doesnt work but its just some pseudo-code
function addFilter(filter) {
names = document.getElementsByName("filters");
for (var name in names) {
name.data-filter = "existing filter, " + filter; // this should be appended to all data-filters
}
}
so basically when a link is clicked it both filters to that category only (lets say kitchens), but also adds the category to the rest of the data-filters (.bedrooms, .kitchens)
javascript or jquery or anything else i may have not realized could work. the documentation for isotope has the option to filter multiple groups of items, but I need it to filter combinations of individual items. Maybe its possible to modify their combination filters to items instead of groups?
See the following article as placed in this post. It should put you in the right direction.
http://www.queness.com/post/7050/8-jquery-methods-you-need-to-know
Stackoverflow question
jQuery - How to add HTML 5 data attributes into the DOM
Well you tagged jQuery, which makes this easy, but I only see you using JS. Anyway, here's one way and some extra info, hope it helps:
jsFiddle {with replication}
jsFiddle {without}
Script
$('li a[name="filters"]').on("click", function(e) {
e.preventDefault();
$(this).data("filter", $(this).data("filter") + ".another-category");
/* and if i wanted to do it without replicating already existing info:
var f = $(this).data("filter");
if (f.indexOf(".another-category") == -1) f += ".another-category";
$(this).data("filter", f); */
});
HTML
<ul>
<li>Kitchens</li>
<li>Bathrooms</li>
<li>Living Rooms</li>
<li>Bedrooms</li>
</ul>
X-tra NFO
jQuery.data(): Biggest Deference - Returns the value that was set
jQuery's .data(): Biggest Deference - Returns the element that was manipulated

Getting specific objects from a selected list

I think I'll have to hit myself in the head after that.
Let's say I have html like this:
<div class="some-class"></div>
<span class="some-class"></span>
Somewhere I select items like this:
var items = $(".some-class");
And somewhere later I would like to get only the divs from the items. I know I could use:
var divs = $("div.some-class");
But is there a simple way, without doing more selections or iterating through elements by .each? Something like items.someFunction("div")?
You're looking for jQuery filter:
var items = $(".some-class"),
divs = items.filter("div");

Categories