JavaScript on iOS: opening an HTML select element - javascript

I'm not hopeful, but I'll ask just in case.
I would like to be able to use JavaScript to open a select element in mobile Safari for iPhone/iPad.
An extensive Google / Stack Overflow search shows that a lot of people would like to be able to do this in browsers in general, but it is not supported (why not, I wonder?). Various hacks have been suggested, from calling focus() on the select element and changing its size property to make more option elements visible, or constructing an entirely mock select element with <div> and <ul> elements. I would, however, like to use the native browser select controls in iPad and iPhone.
I wondered, just maybe, someone might know of a proprietary Apple WebKit method to do this. It would be something like:
var myselect = document.getElementsByTagName("select")[0];
myselect.open(); // this method doesn't exist
As a bonus, it'd also be handy to know of a boolean property that says whether the select element is currently open/active, or not (i.e. not just whether the element has focus). I know I can work this out by tracking click and change events, but a simple property would be useful.
Wishful thinking?
UPDATE:
I don't yet have the answer, but I've found that simulating a mousedown successfully opens a select element in Google Chrome, but not iPad or Firefox and so on:
function simulateMouseEvent(eventName, element) {
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent(eventName, true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
element.dispatchEvent(evt);
}
simulateMouseEvent("mousedown", select);
UPDATE:
I've asked a related, but different (and similarly unanswered!) question on select boxes here: Is there a DOM event that fires when an HTML select element is closed?

I have a working solution for this that works on recent versions of iOS and Android. I haven't yet tested on older versions. There are no two ways about it: this solution is a hack. But it works if implemented carefully.
In my situation I had iOS 7 like toggle switch element. I wanted the picker view for the select to be presented when the switch was turned on. In my case we did not need or want the user to see the select field itself. We merely wanted to use iOS' nice scrolly-picker interface.
I used CSS to position and stretch the select completely over the switch. I then set the opacity in CSS to something like opacity: .001; which makes it invisible for all intents and purposes. It may still work with opacity 0 but I felt leaving a little opacity there may be safer and you really can't see it all anyway. Now when the user taps the area of the screen that is displaying the switch the tap events are actually going to the select which causes the picker view to display.
On the onchange event of the select I set display: none; to completely hide the select. This means that when the user touches the switch to turn it off they are interacting with the switch itself. When the switch is toggled off I then set display: block to return the select to its active state.
My use case is narrow but the position/opacity technique should be adaptable to many use cases though you may have to have 2 select elements in cases where you want the field to be visible.
Here is a screenshot demoing the technique. The opacity is set to 0.25 in this screenshot for demo purposes. When you set it to 0.001 you can't see the select

Triggering HTML controls with JS is a very gray area, partly because of security reasons, and partly due to lack of support. Even using frameworks like jQuery, you cannot simply click() a link to follow it in the same way as click() on a button - you need to trigger a native click event at the browser level (I believe the latest version of Selenium does this, but that's a testing framework so unsuitable for this problem). Congrats on being able to achieve a partial result in Chrome! However, you will not find a universal solution that uses real select inputs.
I would suggest using a different type of control - either a vertical stack of buttons if you want to press one to activate a feature, or a stack of radio buttons backed by labels (with a little CSS) if you want a multi-choice format.

The select element needs to be visible.
If you use jQuery you can do it as follows:
$('mySelectElementSelector').focus();
On mobile it will show the default select control. On desktop just focus on the select control.

Have you tried the change() method?

Related

option element onclick event fix for chrome

I am probably wasting my time with this question but here goes.
Chrome and Opera do not handle events in option elements IE and Firefox do.
So I am wondering I some knows a workaround other than using onchange in the select element, as I have tried to work with that event and pull errors of null value.
onchange="side_nav(this.getAttibute('id'))"
The code I am using is simple id change that works sweet in anything but option elements in chrome and opera, This is the function.
function side_nav(id)
{
document.getElementById("selectedS").setAttribute("id","");
id.setAttribute("id","selectedS");
}
Like I said it works with this in the option element but only in IE and FireFox
onclick="side_nav(this)"
The function works sweet in buttons and I suspect every other element also, just not the one I am set up to use.
I suspect I will have rewrite the nav panel to fix the problem, but thought I would ask someone else there thoughts.
This is What I believe is the answer. not well written but addresses the issue with an answer.
This is a response to Chrome bug reporting. The actual post
Fist I must say after further evaluation I believe that this is not as much a bug or defect but is in how the browser handles the select and option elements. As I see this the browser sees the option element/tag more as an attribute of the select element rather than than an individual element. The select element/tag is just a multidimensional array in HTML and the option tags become attributes of the select element which is why events do not fire and is also why it is impossible to style the option element/tag. I see now that this is deep in source code and seems to be split up equally between the top four browsers. I'll put the basic select code that I have been working with but it will be of no help as it is just the norm, and as I said, it's not a bug but program design.
Thanks for the response.

Problems getting .selectedIndex to work with select boxes in JQuery Mobile framework

I have a series of select dropboxes setup, with content that dynamically updates depending upon the preceeding selection. It works fine selecting in series.
When I try to go back to the top and start again, even though I have attempted to reset all children using
my_select.selectedIndex = 0;
The child select boxes remain unchanged. I had thought it was a Javascript error, but found the JSFiddle example actually worked, but my code within JQuery mobile does not work - leading me to believe it is a JQuery Mobile related issue
You can see a JSFiddle example at http://jsfiddle.net/vinomarky/xfcdF/
Steps to replicate:
Select 'Casing' from Type
Select 5 from OD
Change Type to Tubing
The JSFiddle example behaves as it should - resetting children to "-", while my 'live' JQuery Mobile example does not
Any ideas as to why?
You're manipulating the DOM behind jQuery Mobile's back but never telling jQuery Mobile that anything has changed.
You need to call the refresh method after you change the underlying <select>:
refresh update the custom select
This is used to update the custom select to reflect the native select element's value.If the number of options in the select are different than the number of items in the custom menu, it'll rebuild the custom menu.
So you need to add things like this:
$('#od').selectmenu('refresh');
at the bottom of your change handlers. The element to refresh does, of course, depend on which change handler you're in.
Demo: http://jsfiddle.net/ambiguous/n3VXe/
Your fiddle worked fine because it didn't use jQuery Mobile at all.
Also, you shouldn't be using onchange attributes in 2012, you're loading jQuery so you should use it to bind handlers to the events you're interested in. You might want to replace all your direct DOM manipulation with jQuery as well.

Detect if an HTML select element is expanded (without manually tracking state)

I'd like to detect if a drop down is expanded or not. I don't want to use extra event handlers for click/mouseover etc because the drop-downs are dynamic and for other reasons I can't use something like jQuery live. Basically I'd like something that can given an arbitrary select element (no other attached event handlers, classes, etc), can give a true/false answer on whether it is expanded or not.
For my specific application, I am handling mouse wheel events, but don't want to handle them when a drop down is open (which would override the browser default functionality). However, I still want to handle the mouse wheel events when the mouse has hovered over the select, but has not opened it.
I looked into this before, for similar reasons. I could never find a solution other than trying to track it manually which really doesn't work. There are several ways to open/close a select (drop down) such as Alt+Dn Arrow. An open select will close if the user clicks on something outside the browser. Trying to keep track of the state of the select is an exercise in futility. Unless someone else comes along with something I missed on my hunt, you'll have to code around it as elegantly as you can.
How about when it's got focus, even if it isn't expanded? You specifically ask for expanded because you don't want to override default browser behaviour, but the browser behaviour should be to scroll through the items when the item is focussed, even if it isn't expanded, so I would say you'd be better off detecting focus.
If you're okay with that, then you can certainly easily detect when a field has focus and when it loses it, by using the JQuery focus() and blur() methods, or focusin() and focusout().
http://api.jquery.com/focus/ and http://api.jquery.com/blur/
http://api.jquery.com/focusin/ and http://api.jquery.com/focusout/
Hope that helps.
Maybe you could do something like this:
$('#dropdown').live('click', function(){
//bind mousewheel here
});
$('#dropdown').live('change', function(){
//unbind mousewheel here
})

Catching all changes to the contents of an input box using JavaScript/jQuery

I have a page with an input box, and a function that processes the value of this input box and produces piece of text. I want this text to always be up to date in relation to the contents of the input box, so I've attached a couple of event handlers to it with jQuery to catch any changes:
$('#input').bind('keyup cut paste', function(){...});
This works well in most cases. Whenever the user modifies the contents using the keyboard in any way, or right-clicks to use the cut or paste functions, the text is updated immediately. However, there are two events I still haven't figured out how catch, if it's even possible to do so:
When the user selects a of text and drags it do a different position in the input box
When the user uses the Delete action in the right-click context menu
Both of these can of course be detected by binding the change event, but the problem with that approach is that it doesn't fire until the input box loses focus. The whole point of these bindings is to have the text update in real-time as the value of the input box changes, so change is no good.
English is my second language so I could simply be bad at wording my Google searches, but so far they've turned up nothing. I haven't found any solutions to this after digging through a couple of related Stack Overflow pages either, so I'm asking here. Is there an event binding for this that I don't know of? If not, is there a different approach I could take? Or is this simply not possible with plain JavaScript?
In non-IE browsers, you can handle the input event.
In IE, you can handle the propertychange event.
Demo (works in all browsers)
It's possible this SO question (and related jsfiddle) might answer your question.
(On the linked jsfiddle, put text in the top box to test)
In other words, bind to mouseup and mousedown, etc.
If you can't find a combination of events that cover all cases, you may want to use setInterval(function() {... }, period). You could play around with the period to see how well this works.

How do I trigger the browser context menu on an element. (As if the user right-clicked)

I have the need to trigger the opening of the browser (IE, Firefox, Safari, etc) context-menu via javascript. The problem I am trying to solve, is when an overlaid element is right-clicked, the element below it shows its context menu. So if the top element is a label, when you right click, I need to show the context menu for the input element below.
I know how to keep the label's context menu from showing, but I don't know how to open a context menu arbitrarily.
Any help is appreciated!
Sorry to be the bearer of unfortunate news, but this is impossible to do with Javascript.
I don't want to frustrate you, quite the contrary, especially because you answered my own question :)
I don't think that a browser's contect menu is accessible via an ordinary script on a web page.
If what you are asking for was actually doable, then the browser makers would possibly consider this a bug and remove this behavior. Cross-browser, this behavior is very unlikely to be available today.
Why don't you capture mouse events, and whenever the mouse is directly in the area of the element below that you want to show the context menu for, push the covering element below, otherwise back on top?
That is one possiblity I could think of, basically revealing/exposing the hidden element depending on mouse position. Like cutting a hole into the overlay.
Or why don't you make the text field transparent and put the overlay below the text field entirely?
If this does not work out technically, then at least you have a point in filing bugs or enhancements against the targeted browsers.
BTW it looks like the context menu actually works if the user right-clicks directly at the position of the caret, so this might be another loophole for you to consider.
I have a possible solution that may suit your needs. It is not perfect yet, I have only done a few quick tests in a few browsers (Fox 3.6, IE7, IE8, Chrome 4, Safari 3 on xp) It will need to be tweaked and improved but its a start. Basically the idea is to remove the label on right-click mousedown so that the desired field is hit by the mouseup event and therefore fires up the context menu on the relevant field.
// Remove the contextmenu from "In-Field" Labels
base.$label.bind("contextmenu",function(e){
return false;
});
// Detect right click on "In-Field" label:
// hide label on mousedown so mouseup will target the field underneath.
base.$label.mousedown(function(e){
if ( e.which == 3 ){
var elLbl = $(this);
elLbl.hide();
var elFid = $(this).attr("for");
// bind blur event to replace the label when we are done.
$("#" + elFid ).bind("blur.infieldlabel",function(){
elLbl.show();
$("#" + elFid ).unbind("blur.infieldlabel");
});
return false;
}
});
The IE and Safari browsers experience a strange issue where you need to click in and out twice before the label will display again (something to do with event timing I think). You may be able to easily see why this is happening by looking at the code. Also noticed slight glitch sometimes in the fox after pasting into the field, on blur the label appeared for a split second when it should not. This should be a fairly simply thing to rectify if you decide to incorporate this method into your code.
You can make Your label/span element contenteditable="true" and handle any further actions with listeners. Making it contenteditable will enable normal, input-like contextmenu to show up on right click.
And if someone doesn't care for IE support:
pointer-events: none
Type the following in the console:
document.oncontextmenu = reEnable
That will print to the console the following:
reEnable()
{
return true;
}
Done, you can now use the context menu.

Categories

Resources