So i'm trying to make my schools navigation bar a little bit more mobile friendly.
If you navigate to
www.jpc.wa.edu.au
on a mobile device, and click on the menu item "Resources" - A drop down menu opens up with two options. Mousing over these with a desktop computer gives you another menu to the right of the first. This works fine on a large screen. However, anything that has a resolution lower than roughly 1460px, such as most tablets, phones, or even laptops, the new menu gets cut off and you have to pan the window left to view it. I would like to avoid this problem completely by simply positioning the second submenu to the left of the first submenu on smaller screens.
Determining screen size I can do.
if(window.innerWidth<1460)
Works perfectly fine. The problem i'm having is that I can't seem to access the second submenus left property to modify the menus position from my javascript
In my CSS, I set it by using the following selector
#horizonMenu
But when I try to use this selector in Javascript using
document.querySelector("#horizonMenu").style.left
But that doesn't seem to return any values.
What am I doing wrong guys? Or should I just take a whole different strategy to fixing this problem?
Edit: I've now changed horizonMenu to a class. Alas, my problem seems to persist :(
The problem is that you have multiple elements with the ID horizonMenu. You should only have a single element with a given ID. When you query #horizonMenu, it is returning the Community -> Pastoral Care menu, which does not have a left value. You should use classes instead, as you can have multiple elements share a class, or change the id to something unique so you can access what you intend to access.
Take a look at the following links
Change an element's class with JavaScript and http://www.kirupa.com/html5/setting_css_styles_using_javascript.htm
Also please check the position attribute for the elements, see below example:
https://jsfiddle.net/masoodalam78/e3erq6j4/
var elementObj = document.querySelector("#menu");
elementObj.style.backgroundColor = "blue";
elementObj.left = "200px";
style property is the representation of the style attribute. Since you are setting the CSS property in your CSS file, the left property returns an empty string. Also properties of the style object do not show the computed values. For getting the computed value you should use window.getComputedStyle() function.
window.getComputedStyle(document.querySelector("#horizonMenu"), null)
.getPropertyValue('left')
For setting the property value you can code:
document.querySelector("#horizonMenu").style.left = '...';
Note that you can consider using CSS media queries instead of using JavaScript.
Okay. so it may have been a combination of a few things.
I followed JBzd's advice to change the menu to a class.
I also stopped using querySelector() and instead am using querySelectorAll() - storing what's returned as a variable and accessing the correct menus by using varaible[1] and variable[2]
I am now able to access the left property of the menu by using
variable[x].style.left = '162px'
Thanks for all the help everyone :)
Related
There is a website with the following div:
<div class="x" style="user-select: none; filter: blur(4px);">
under this div there are a lot of other divs. I would like to know if there is any possibility to delete only this DIV with javascript. So only that one gets deleted and all the divs underneath remain.
I want to get rid of this DIV becouse this div blurs an part of the website text. Just changing the blur(4px) wont work the website has some kind of protection what refreshes this part back to original.
the reason i am searching for an possibility in javascript is because i want to automate this in the browser.(Just deleting DIV manually under developer mode works)
so far i got the following:
var div = document.getElementsByClassName('page-content');
div.remove(); //(but this does not work)
getElementsByClassName() returns a collection. Only single objects have remove() method. You have to apply one of the following:
Use brackets to specify an index of the object you want to get:
div[0].remove()
Use item() method passing the index as well:
div.item(0).remove()
Both ways are equivalent.
As an alternative, you may call querySelector() method:
const div = document.querySelector('.page-content')
It returns a single object (according to the passed CSS selector) so you can use:
div.remove()
Edit:
To remove only the covering div, you may use replaceWith() method and pass the child nodes of that div as an argument:
div.replaceWith(...div.childNodes)
If you want to keep only element nodes, use children property:
div.replaceWith(...div.children)
A value in tab header changed through JS value is not persisting on #media breakpoint/accordion screen - although the one in the tabbed content area is persisting.
The js code:
function check_1_input(X, Y) {
var ids=X.split("_"); console.log(' X '+X+' id '+ids[1]);
var PX=document.getElementById(X);
var PY=document.getElementById(Y);
PX.childNodes[0].textContent = "Changed";
PY.childNodes[0].textContent = "Changed";
}
which makes the changes is at the end of the html - not sure why it only works in that location.
The fiddle is
https://jsfiddle.net/PhilB/077dbf37/10/
The problem you're having is that you're using element IDs in your check_1_input function. The responsive tab plugin clones your tab elements on initialization to have both horizontal and vertical tabs with different classes that get hidden or exposed based on the media width, but it keeps the IDs the same. Since your function is looking for elements using getElementById, it will only find the first one.
Ultimately, you end up with two different elements with the same ID, which is bad practice. Using a class as the selector instead of the ID fixes the problem. I used jQuery to select the classes instead of ID's since you have jQuery loaded. You may consider removing the ID's all together in the tab elements, since the responsive tab plugin is always going to clone them and result in an invalid DOM (two elements with the same ID).
See my updated version of your fiddle here.
I'm working within a setup that I have no control over:
Parent->Iframe->Iframe->My document
How do I access an element that is on the parent from within my document?
These are all on the same domain, so no cross-domain issues. I can do this with either straight up JS or jQuery.
I've been searching around, but haven't found any examples of someone trying to access an element on the top from the bottom through multiple iframes!
The solution, in case anyone else comes across this:
var p = $("#Viewport",window.top.document);
alert(p.attr('name'));
Just use window.top, like:
console.log(top.document.getElementById('someInputId').value);
Notice that window in implicit, so you can leave it off. Of course, you will have to change 'someInputId' to an input id on your top page to see if this works. Use .innerHTML instead of .value if you are testing against an Element that is not an input.
I believe you will be able to access this via window.parent, as thus:
window.parent.document.getElementById('target-element');
There are a couple of ways I could do this (That I'm aware of).
Test css display
if ($('#foo').css('display') == 'none')
Test the visibility
if ($('#foo').is(':visible'))
In the visibility I can check if the element is there.
Elements are considered visible if they consume space in the document.
Visible elements have a width or height that is greater than zero.
Elements with visibility: hidden or opacity: 0 are considered visible,
since they still consume space in the layout.
Source
But, note that in both I can't test the visibility (by the user) because:
Hiding an element can be done by setting the display property to
"none" or the visibility property to "hidden". However, notice that
these two methods produce different results:
visibility: hidden hides an element, but it will still take up the same
space as before. The element will be hidden, but still affect the
layout.
display: none hides an element, and it will not take up any space. The
element will be hidden, and the page will be displayed as if the
element is not there:
Source
So in neither of the examples I test if the element is visible in all senses for the user.
So my question is:
What're the differences between the two if's codes from above?
What's the best way to test if an element is visible to the user:
Should I have to use something like:
if ($('#foo').is(':visible') &&
$('#foo').css('opacity') > 0 &&
$('#foo').css('visibility') != 'hidden')
I think your best bet is to implement a custom function like below and test/improve as new things come up,
$.fn.isReallyVisible = function () { //rename function name as you like..
return (this.css('display') != 'none' &&
this.css('visibility') != 'hidden' &&
this.css('opacity') > 0);
}
The above should be cross browser proof as we are using jQuery .css function (specifically for opacity).
DEMO
The difference between the two is that being hidden using "visible" attribute leaves the element on the page, just not actually displayed. So, it's spacing will be taken into account when the page renders the rest of the display.
It seems that doing it the other way actually stops the element from being put onto the page, which can change how other elements on the page are laid out.
usually testing the visible part is enough from my experience, but if you are wanting to be more complete, then yeah you would have to check using "&&" conditions on multiple attributes.
It really all depends on how clean the code you are using is, and how well tested the rest of the UI aspect of the system is.
The other thing to consider is what is the purpose of the test. Are you testing code that you wrote, or how the browser is using Javascript to render the page? You want to be testing the code that you are creating, and rely on the fact that the browser works (because if the browser stops working, then the whole thing is unreliable anyway). So if your code tells the element to set some attribute, then checking for that attribute is all the testing you need to do. Anything on top of that can only really be proven by testing outside of the code itself (as in manualy looking at the page and other things like that).
If you want to see if an element exists in the DOM you could just do this:
$.fn.exists = function () {
return this.length > 0;
}
Usage:
$('#myid').exists();
I am working on a project where I am building a treeview and in some cases my tree could have a 1000+ child nodes. The problem is its really slow on like a IE7 machine.
I'm not doing any kind of animation or anything, just simply trying to hide the next UL in the item using JQuery's toggle feature. Does anyone have any ideas of how to improve the performance?
Thanks!!
If toggle is slow, you can set css styles directly via jquery like:
$(".tree_item").click(function(){
//check the next ul if it is expanded or not
if(this.next('ul:hidden').length == 0){
//if expanded hide it
this.next('ul').css('display', 'none');
}else{
//if not shown, show it
this.next('ul').css('display', 'block');
}
});
such approach would help. I don't know if it would work faster but give it a try...
Sinan.
I'm not surprised at all that this is slow if your treeview is that big. Silverlight 3 handles this problem with UI Virtualization.
You'll have to roll your own in javascript, but it shouldn't be that hard. Just make a huge blank div that's the size of what the rendered tree would have been, and put it inside a scrollable div, and then only render what should show up. Change it on the onscroll event.
You can try to build at start your own tree object from DOM document.
Just iterate through all elements and nest them in standard attributes and variables. You can make additional parent and children pointers using $(element).get(0).parent = $(parent).get(0);
Then if you want to get specified elements use $.map function.
We used it to prepare something like firebug on a project. It rebuilded all 5000+ nodes portal in 3 sec and provided fast access on ie6+
I've found that .toggle(showOrHide) is fast. It was added in jQuery 1.3 and really makes a difference on large collections (50+ elements) in IE8 if animation is not required. The current visibility state can be obtained from the first element, e.g.:
var isVisible = $('.myClass').first().is(':visible');
$('.myClass').toggle(!isVisible);