Twitter: raymondcamden


Address: Lafayette, LA, USA

Context Menu Example with jQuery Mobile

05-23-2012 32,730 views Mobile, Development, jQuery, JavaScript, HTML5 19 Comments

Yesterday a reader asked me about building context menu support for images within a jQuery Mobile operation. Turns out it's pretty easy. Obviously there is no such thing as a right-click menu on a touch device. That being said - the convention that most mobile applications use is a "taphold" listener. You touch the item with your finger and wait. In a second or two, the context menu pops up. The taphold event is trivial to use in jQuery Mobile (with a caveat I'll get to in a second), but what isn't as trivial is deciding what UI to use. jQuery Mobile will - soon - have a popup UI item. For now though I decided on the excellent SimpleDialog2 plugin by JTSage. Let's look at an example.

I've taken a few simple images and embedded them into the page. Note that each employs a class, touchableImage.

In the code block at the bottom, I register an event listener for the taphold event and fire off a call to the SimpleDialog2 control. I won't go into a lot of detail over the options, use the link above for details, but I basically wanted a non-modal window with a set of options for the image. (For now those links don't actually do anything, but you get the idea.) You can demo this yourself below. Remember that if you are not on a touch device, you're screwed, unless you use Chrome which allows you to emulate touch events now.

Here's a quick screen shot so you can see it in action.

Ok, if you want to stop reading now, you can. What follows is an interesting issue I discovered with iOS and tap events and how I debugged it using Adobe Shadow. Still here? Ok, I warned you.

One of the nice features of the SimpleDialog2 control is that you can auto-dismiss it if you click anywhere else in the DOM. The attribute, forceInput, when set to false, allows for easy dismissal of the control. I wanted to use that feature, and it worked great in Android, but on iOS, it did not. As soon as the dialog showed up it went away.

Here's where Shadow comes in. I was using Shadow to load the page and I remembered that I could use the console there too. I added a quick event listener for tap, went back to the iPad, and tested again. I saw my first tap event, I saw the taphold, and when I lifted my finger, I saw another tap event! Apparently this is (I believe) normal for iOS. You can see some discussion of this here.

So for now, I switched forceInput to true which requires the user to forcibly close the dialog, which isn't horrible I guess. I could - possibly - sniff for iOS/Android and toggle the field depending on the platform, but for now, I'm satisfied with it.

And once again - Shadow helps save the day. I know I sound like a broken record, and I know I work for Adobe, but damn, this is probably one of the best development tools I've used in a long time.

19 Comments

  • kim_ras #
    Commented on 05-23-2012 at 11:45 AM
    Hi
    First of all thanks for the quick and nice sample!! It is exactly what I need in the lag of the next version Popup's.

    One question which might be trivial but how do you reference to the object so you know what Image to "Send to Facebook"/"Send to Twitter" ...

    Again thanks for our support
    Kim
  • Commented on 05-23-2012 at 2:41 PM
    Basic idea would be:

    The taphold event is passed the item you clicked on as this. Store a copy of that in a global variable.

    Use event listeners for the 3 links. When clicked, fetch the global variable.

    Does that make sense?
  • Peter Doyle #
    Commented on 05-24-2012 at 12:21 AM
    Ray,

    When i ran the demo on my S2 i first got the 'copy image' android dialogue open. Your context menu opened below that?

    Bit unusual not sure if this just on my phone
    Tlv
    Peter
  • kim_ras #
    Commented on 05-24-2012 at 3:38 AM
    HI Ray,
    Yes it makes sense, I did see the global variable afterwards.. not a big fan of global variables for events, but easy enough to handle..
    Thanks again
    Kim
  • Commented on 05-24-2012 at 9:12 AM
    @Ray,
    Is there a stopPropgation in Phonegap? So capture the event then stop the next ("tap") event firing after the taphold? This is the way I handle adding buttons to lists in Flex to stop the list "indexChanged" event firing when I've added a button on top of a list item.
  • Commented on 05-24-2012 at 9:31 AM
    +Peter Doyle: Shoot, I see that too on my One X. Let me investigate.

    +Kim_ras: I hear ya - I think in this case it is ok though.

    +Gareth: Remember - this isn't a PG issue but a web issue. PG is using webkit to render the content. So it isn't "Does PG support it", but can we do it in JS anyway. I'll try it on iOS and let you know. (As it stands, this isn't using PG anyway - just normal web pages.)
  • Commented on 05-24-2012 at 9:39 AM
    Peter/Gareth: stopProp worked great for the Android phone. I'm updating the Gist now (give it a few seconds). Thanks.

    It did not - however - allow me to switch back the forceInput thing.
  • gaurav #
    Commented on 09-03-2012 at 5:58 AM
    how can we pass parameters to taphold event
  • Commented on 09-03-2012 at 7:59 AM
    You don't. Parameters (involving the event) are passed already. Provide more detail on what you are trying to do and maybe I can help.
  • RQX #
    Commented on 12-04-2012 at 1:33 AM
    It doesn't work on Windows Phone device!
  • Commented on 12-04-2012 at 7:02 AM
    It doesn't work how? Saying it doesn't work isn't helpful. Is it not rendering the menu in the right place? Did you add a console.log(...) to the taphold event to ensure it was firing at least? I need more details on -where- it fails.
  • RQX #
    Commented on 12-04-2012 at 6:02 PM
    On windows phone's IE browser, when taphold on a link/img/a etc. the default action is show a context menu, like "open in new tab"/"copy the link address". it won't show our simpdialog.

    If you have a windows phone mobile, you can run your demo page and you will see this problem soon.

    Thanks!
  • Commented on 12-04-2012 at 7:40 PM
    Hmpth, you got me there. Best I can recommend is posting to the jQuery Mobile forum and letting us know. I don't have access to a Windows Phone right now.
  • Commented on 05-31-2013 at 5:03 AM
    Pavan @(<a href="http://www.pavanh.com/">pavanh</a>;)

    Very nice tutorial with efficent and detailed explaination, you can also check
    this one <a href="http://www.pavanh.com/2013/02/android-context-menu... menu</a>
  • Commented on 05-31-2013 at 6:48 AM
    @pavan: To be clear, that is for native development. This blog post is about how to do it for mobile web or hybrid apps.
  • Commented on 04-08-2014 at 2:17 AM
    I do jquery only for a couple of month.

    I refer to http://raymondcamden.com/demos/2012/may/23/

    I ran this on firefox (no touchscreen) and emulated taphold by mousedown and liked it very much.

    Then i ran it on my android cellphone. But the context dialog (right click) showed up first and then the simple dialog. Can happen the sd is completely hidden behind context dialog. how to supress firing context dialog just for this single event?
  • Commented on 04-08-2014 at 10:18 AM
    Hmm. You may want to try this: http://stackoverflow.com/questions/3413683/disabli...
  • PrinceJava #
    Commented on 04-23-2014 at 10:16 AM
    Mr. Raymond Camden, please helpe me, do you can telle why it does not work this code?
    $ (document). ready (function () {
        
    $ (". various".) on ("taphold", "img", function () {
        $ (this) fancybox ().;
    });

      
    });
  • Commented on 04-23-2014 at 11:43 AM
    No, I can't, because you didn't say how it wasn't working.

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty