So I have a site that is using a select menu for the mobile navigation. I'm needing to hide a few options from the list, and have been able to so on all browsers and devices except for Safari and iPhone.
Here's the css I used to remove items 7-11 on the list:
select.select-menu option:nth-child(n+7):nth-child(-n+11){
display: none !important;}
This is working as expected in Chrome and on my android phone. However, when you view the site in Safari or on an iPhone the options are not hidden and still show up.
I've tried several options and done a lot of research on the matter and can't find a solution. I tried removing items from the list using jQuery and couldn't get that to work either.
Is there a way I can hide the options on iPhone and Safari as well?
EDIT:
Here's a fiddle:
https://jsfiddle.net/cv6rubua/3/
Only this works for me - wrap in element you need to hide it. "if-check" for not wrapping it twice if hiding connected with some action on page.
Hide for iOS with jQuery:
if( !($(this).parent().is('span')) ) $(this).wrap('<span>');
Unhide for iOS with jQuery:
if( ($(this).parent().is('span')) ) $(this).unwrap();
With Jquery you can use prop("disabled", true) together with hide(). Like this:
$(this).prop("disabled", true); // for safari
$(this).hide();
This way options will be hidden in most browsers. In Safari they will be visible but disabled.
I think this is a nice alternative.
I also had difficulties in Safari while trying to hide option in my select (from an extension) and decided to go this route.
To "hide" the option in my select I replace the option with div, and then back again to option if I want to show it again.
//if any div exists change back to option
function showAll(){
var nodesSnapshot = document.evaluate("//select/div", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < nodesSnapshot.snapshotLength; i++) {
var nodeA = nodesSnapshot.snapshotItem(i);
var elemA = document.createElement('option');
elemA.innerHTML = nodeA.innerHTML;
nodeA.parentNode.replaceChild(elemA, nodeA);
}
}
//replace all option that contain text with div
function hideSome(){
var nodesSnapshot = document.evaluate("//select/option[text()[contains(.,'HideMe')]]", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < nodesSnapshot.snapshotLength; i++) {
var nodeA = nodesSnapshot.snapshotItem(i);
var elemA = document.createElement('div');
elemA.innerHTML = nodeA.innerHTML;
nodeA.parentNode.replaceChild(elemA, nodeA);
}
}
//replace all option with div
function hideAll(){
var nodesSnapshot = document.evaluate("//select/option", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < nodesSnapshot.snapshotLength; i++) {
var nodeA = nodesSnapshot.snapshotItem(i);
var elemA = document.createElement('div');
elemA.innerHTML = nodeA.innerHTML;
nodeA.parentNode.replaceChild(elemA, nodeA);
}
}
<button onclick="showAll();">showAll</button>
<button onclick="hideSome();">hideSome</button>
<button onclick="hideAll();">hideAll</button>
<select>
<option>HideMe</option>
<option>HideMe</option>
<option>ShowMe</option>
<option>HideMe</option>
<option>ShowMe</option>
</select>
I found that removing the items rather than hiding them is easier.
$(this).remove();
You can solve this using JavaScript
var selectOption = document.querySelectorAll('.select-menu option');
for (var i = 0; i < selectOption.length; i++) {
var item = selectOption[i];
if (item.innerHTML.charAt(0) === "–") {
item.remove();
};
}
You have a number of options depending on what you want, from I have found display: none does not work on safari so here is an alternative method:
You can simply make it super small and invisible:
opacity: 0;
height: 0;
width: 0;
overflow: hidden;
This should work well, and should be supported by both chrome and safari!
Good luck!
You can't. Safari uses an overlay for dropdowns... You literally have to remove them.... There is a hack using spans as non-valid syntax... Wouldn't recommend using invalid syntax though
The solution that worked for me was to create another hidden select which all the options, and clone the relevant ones to the visible select. this way you display one the options you want to display but still keep a record of the other options in a hidden list.
Related
Might be a strange setup, but I have a number of hyperlinks on the page with the same id (yeah, I know, but it was not my choice and I cannot change that at this time plus those hyperlinks are generated dynamically).
Example:
<div id="Links">
<div class="myItem">Some text</div>
<div class="myItem">More text</div>
<div class="myItem">Even more text</div>
</div>
Now I need to attach javascript to those links dynamically (the hyperlinks are also dynamically generated). The easiest way I see is by getting all hyperlinks on the page and then check the hyperlink id to ensure I only take care of those that have id of "myLink" (I have many other hyperlinks on the page).
I thought of using getElementById but that would only grab the first element with the specified id.
am attaching javascript to those links using the following:
window.onload = function() {
var anchors = document.getElementsByTagName('a');
for(var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
if (anchor.id='myLink')
{
if (anchor.getAttribute("LinkID") != null)
{
anchor.onclick = function() {
MyFunction(this.getAttribute("LinkID"), false);
return false;
}
}
}
}
}
The above function works fine, but it creates another issue - affects the styling of other hyperlinks on the page. So I was wondering if there is a way to accomplish the same thing but without affecting other elements on the page?
This is more modern and corrects your equality test:
window.onload = function() {
var anchors = document.getElementsByTagName('a');
for(var i = 0; i < anchors.length; i++) {
if (anchor[i].id==='myLink' && anchor[i].getAttribute("LinkID") !== null)
{
anchor[i].addEventListener("click", function() {
MyFunction(this.getAttribute("LinkID"), false);
}
}
}
}
Even with your original code, I don't see anything that would interfere with styling in the code. Can you elaborate as what styling changes you were getting?
You can use an attribute selector and document.querySelector([id=<id>]) pretty reliably depending on your browser support situation: http://codepen.io/anon/pen/YwLdKj
Then, of course, loop through that result and make subsequent changes or event bindings.
If not, you could use jQuery (referenced in above code pen).
You might also use JavaScript event delegation and listen for all click events, check if the user is clicking a link with the correct id.
If a combination of tag == 'a', class == "myItem" and presence of a LinkID attribute is sufficient to identify nodes requiring a click handler they could be identified using multiple CSS selectors. If this is not possible however, a query selector not using id can create a list of nodes to be checked for id, as for example:
function callMyFunction()
{ MyFunction(this.getAttribute("LinkID"), false);
}
function addClickHandlers()
{ var list = document.querySelectorAll("a[LinkID]")
var i, node;
for( i = 0; i < list.length; ++i)
{ node = list[i];
if(node.id == "myLink")
{ node.onclick=callMyFunction;
}
}
}
See also running a selector query on descendant elements of given node if of interest.
I have a form with two select dropdowns. The first is opening times and the second is closing times. So When the user selects a opening time the closing time cannot be earlier than this.
My Jquery instead disables all the second drop down values instead of only the times earlier as can be seen here: JSFiddle.
$('#open').change(function(){
if($('#close').val()<$('#open').val()){
$('#close').prop('disabled', true);
};
})
How can I get the behaviour I want?
Try this (here is the updated jsfiddle):
$('#open').change(function(){
var that = $(this);
$('#close option').each(function() {
if($(this).val() < that.val()) {
$(this).prop('disabled',true);
} else {
$(this).prop('disabled',false);
}
});
});
It works on Chrome 36, but not on Firefox (haven't tested any browsers besides those two).
Since this behavior is unreliable, you might try dynamically adding options to the second select element based on whatever is chosen in the first select element.
EDIT
See this jsfiddle based on your original fiddle. It will let you dynamically populate the second select element.
var vals = ['00.00', '00.15', '00.30', '00.45', '01.00', '01.15', '01.15'];
for(var i = 0; i<vals.length; i++) {
$('#open').append('<option val="'+vals[i]+'">'+vals[i]+'</option>');
}
$('#open').change(function(){
$('#close').html('');
for(var i = 0; i<vals.length; i++) {
if(vals[i] >= $(this).val()) {
$('#close').append('<option>'+vals[i]+'</option>');
}
}
}).change();
Most browsers do not allow the disabling of individual <option>s in a <select>.
I would fill the second <select> whenever the first is changed.
so I'm writing an interface for updating and displaying a database table, and each row displayed on the client-side (using DataTables) has an "Edit" and "Delete" button. Every time you click on a single row's Edit, all the Edit and Delete buttons in other rows are disabled. This is the Javascript code I use to do it:
var editButtons = document.getElementsByName("EditRow");
var deleteButtons = document.getElementsByName("DeleteRow");
for (i in editButtons) {
editButtons[i].disabled = true;
}
for (i in deleteButtons) {
deleteButtons[i].disabled = true;
}
This works fine with Chrome and Firefox, but when I try it in IE9, it doesn't disable anything. I've tried many things to solve this, including grabbing the DOM objects using jQuery, but nothing has worked. Any help is appreciated.
document.getElementsByName returns a node list, which is Array-like. You should treat it as such:
var elements = document.getElementsByName('something'),
len = elements.length;
for (var i = 0; i < len; i++) {
elements[i].disabled = true;
}
Your example doesn't work in IE9, but this does:
Array.prototype.forEach.call(document.getElementsByName('EditRow'), function(el){
el.disabled = true;
});
I'm wondering if it's possible for a script to enable/disable all input elements on the page with some sort of toggle button.
I googled it but didn't find anything too useful except for this:
http://www.codetoad.com/javascript/enable_disable_form_element.asp
but I'm not sure how to edit it for the toggle.
Something like this would work:
var inputs=document.getElementsByTagName('input');
for(i=0;i<inputs.length;i++){
inputs[i].disabled=true;
}
A working example:
$().ready(function() {
$('#clicker').click(function() {
$('input').each(function() {
if ($(this).attr('disabled')) {
$(this).removeAttr('disabled');
}
else {
$(this).attr({
'disabled': 'disabled'
});
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<input type='text'></input>
<input type='text'></input>
<input type='text'></input>
<div id='clicker' style='background-color:#FF0000; height:40px; width:100px;'></div>
Here is a function to toggle all inputs on the page:
function toggle_inputs() {
var inputs = document.getElementsByTagName('input');
for (var i = inputs.length, n = 0; n < i; n++) {
inputs[n].disabled = !inputs[n].disabled;
}
}
It works by using the logical NOT operator (the exclamation point), which returns the opposite of the operand. For example, !true will return false. So by using !inputs[n].disabled, it will return the opposite of what it's currently set to, thereby toggling it.
If you need code to bind the click event to the button:
document.getElementById('your_button_id').onclick = toggle_inputs;
You can also use addEventListener, but see the linked page for more information, including compatibility with Internet Explorer. The code I gave above should work across all browsers with no trouble.
for (var i = 0; i < document.getElementyByTagName('input').length; i++) {
document.getElementsByTagName('input')[i].disabled = 'disabled';
}
http://code.google.com/p/getelementsbyclassname/
^^Robert Nyman has a "get elements by class" script. Basically you'd just assign all those input elements to the same class, and then do something like:
//Collapse all the nodes
function collapseNodesByClass(theClass){
var nodes = getElementsByClassName(theClass);
for(i = 0; i < nodes.length; i++){
nodes[i].style.display='none';
}
}
This is a piece of code I'm actually currently using to collapse everything with a given class name (it uses the script I mentioned above). But in any case I think the key to your problem is being able to refer to multiple elements at once, which that script will help you with.
Also the link in your question didn't work for me :(.
I'm a bit of a novice when it comes to Javascript, but I've managed to create this script which 'greys out' text and inputs found in a div. It accepts a boolean (show) to declare whether the elements are being hidden or reshown, as well as the name of the div(s) to hide.
It works exactly as intended in Chrome and Firefox, but IE won't do a thing. Through 'debugging' using alerts, I think the issue lies with this line:
var div = document.getElementsByName(divName);
...of the following code:
function hideAndShow(show, divName) {
var hideColor = "#DFDFDF";
// Find all matching divs and loop through
var div = document.getElementsByName(divName);
for (var count1 = 0; count1 < div.length; count1++) {
// Find and loop through all elements in div
var elements = div[count1].getElementsByTagName("*");
for (var count2 = 0; count2 < elements.length; count2++) {
if (elements[count2].tagName == "TEXTAREA" || elements[count2].tagName == "INPUT") {
elements[count2].disabled = !show; //Disable
elements[count2].style.borderColor = (show) ? "" : hideColor; // Change border colour
elements[count2].value = ""; //Clear existing text
}
}
// Change the colour of anything left, such as text
div[count1].style.color = (show) ? "" : hideColor;
alert(div[count1].id);
}
}
Can anybody please help or point me in the right direction? I'm stumped!
It's possible that IE is getting confused by your page: http://www.romantika.name/v2/javascripts-getelementsbyname-ie-vs-firefox/
afaik the IE implementation of getElementsByName actually searches on id
In IE7 at least:
// works in IE but not Chrome
<div id="test"></div>
alert(document.getElementsByName('test').length);
// doesn't work in IE, works in Chrome
<div name="test"></div>
alert(document.getElementsByName('test').length);
Libraries like jQuery deal with all this nonsense for you and make selecting DOM elements trivial.
If you want to do it in pure JS, you might want to look at providing an implementation of getElementsByClassName (see here for an example) to solve the problem.