4

I have a dynamic listview built with knockout:

<ul class="menu-items-listview" id="items-list" 
    data-role="listview" data-bind="foreach: Items" >

    <li class="menu-item">
        <div class="menu-item-container">
            <div class="menu-amount-container">
                <a id="dec-button" data-bind="click:$root.decCount, visible:Count">-</a>
                <span data-bind="text: Count, visible: Count" class="item-amount-counter"></span>
                <a id="inc-button" data-bind="click:$root.incCount">+</a>
            </div>
        </div>
    </li>
</ul>

On a desktop everything works fine. On a touch device each time after the listview is refreshed first tap on a #inc-button or #dec-button would fire twice. Then everything is ok until the listview is refreshed.

Clue 1: there are two iScroll divs on the page and it seems like it may cause the problem. There are issues on the forums concerning jQuery event subscription but not knockout bindings:

  1. https://github.com/cubiq/iscroll/issues/270
  2. How can I trouble shoot click events being triggered twice?

Clue 2: after the listview refresh if I touch the screen to scroll and then push the button the action is fired once

EDIT: it's definitely an iScroll issue. I disabled the iScroll script and the actions fire once as they should

Community
  • 1
  • 1
Cubius
  • 1,294
  • 2
  • 15
  • 33
  • Can you make a fiddle? I'll test/debug it on an iPhone, if you make one. – Brigand Jul 09 '13 at 17:12
  • a wise man once told me to pick the right tool for the job, personally I always pick jQuery for event binding and knockout for DOM binding. I find that it solves a lot of my problems like this, because jQuery is awesome at event handling. – abc123 Jul 09 '13 at 17:41
  • @abc123 if I use jQuery I will have to bother about picking the right item to change its `Count` property. it means adding items' ids to the DOM and defining selectors to subscribe to clicks. and, I guess, i will have to unsubscribe and re-subscribe on listview refreshes. am I right? – Cubius Jul 09 '13 at 17:58
  • @Cubius That is all correct...except that in a jQuery click event you can always use the keywork "this". But yes, since this is sounding more and more like a single page app yes. Memory Management is very important and a key to memory leak is event bindings. – abc123 Jul 10 '13 at 01:51
  • In the iScroll config for the element, setting the option `click: false` did the trick for me. – connexo Jul 16 '15 at 06:45

1 Answers1

0

I think the approach is great, I personally would use JQuery Mobile, which has a vclick event, as from experience this is also more responsive on Android.

I have moved away from using click bindings on mobile web sites/apps. See here: In jQuery mobile, what's the diff between tap and vclick?

<ul class="menu-items-listview" id="items-list" 
    data-role="listview" data-bind="foreach: Items" >

    <li class="menu-item">
        <div class="menu-item-container">
            <div class="menu-amount-container">
                <a id="dec-button" data-bind="event: { vclick: $root.decCount }, visible:Count">-</a>
                <span data-bind="text: Count, visible: Count" class="item-amount-counter"></span>
                <a id="inc-button" data-bind="event: { vclick: $root.incCount }">+</a>
            </div>
        </div>
    </li>
</ul>

There are alternatives to this, and you can always have a stripped down version of JqM using their download builder, to just get the minimum needed for the touch specific events.

EDIT: also if the problem is solved just by using iScroll, you could try and add the CSS for iOS momentum scrolling instead? Has usually done the trick for me. Then you are avoiding one dependency at least. See here: http://johanbrook.com/browsers/native-momentum-scrolling-ios-5/

Community
  • 1
  • 1
Adam Marshall
  • 3,010
  • 9
  • 42
  • 80