Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make swipe function work dynamically on a table row?

I am developing a cross-platform mobile application using Cordova. I have an HTML page with a table. I have a button add row when clicked adds a new row to my table. I need an iOS-like swipe action to have a delete action. I used touchstart event to swipe a static row in my table. That works fine but not with dynamically created table rows. How to do this swipe action?

This is the code I have so far:

HTML

<div class="fortable">
    <table id="cashreg">
        <tr>
            <td class="tablecellbackground"><div class="del" id="d1" ><p>Delete</p></div><div id="cells" class="cells"><div class="denom"><p>Start Time</p></div><div class="cnt"><p>Select Item</p></div><div class="tots"><p>Employee</p></div><div class="tots1"><p>Price</p></div></div></td>
        </tr>
    </table>

    <input type="button" class="addmore">
</div>

JavaScript

For adding a row to the table:

$(".addmore").click(function(){
    var rows = $("#cashreg tr").length+1;
    $("#cashreg").append('<tr><td class="tablecellbackground"><div class="cells"><div class="denom"><p>Start Time</p></div><div class="cnt"><p>Select Item</p></div><div class="tots"><p>Employee</p></div><div class="tots1"><p>Price</p></div><div class="del"><p>Delete</p></div></div></td></tr>');
});

For iOS-like swipe:

window.addEventListener('load', function(){
    var el = document.getElementsByClassName('cells')[0];
    ontouch(el, function(evt, dir, phase, swipetype, distance){
        var touchreport = ''
        touchreport += '<b>Dir:</b> ' + dir + '<br />'
        touchreport += '<b>Phase:</b> ' + phase + '<br />'
        touchreport += '<b>Swipe Type:</b> ' + swipetype + '<br />'
        touchreport += '<b>Distance:</b> ' + distance + '<br />'
        if(dir=="left"){
            left=parseInt(($(".cells").css("top")).replace ( /[^\d.]/g, '' ))-distance;
            $(".cells").css("left","-"+left+"px")
        }
        if(dir=="right"){
            if($(".cells").css("left")== "-166px"){
                //left=parseInt(($(".cells").css("top")).replace ( /[^\d.]/g, '' ))-distance;
                $(".cells").css("left","0px")
            }
        }
        if(dir=="none"){
            // document.getElementById("hi").value=el.pageX;
        }
    })
}, false)

function ontouch(el, callback){
    var touchsurface = el,
    dir,
    swipeType,
    startX,
    startY,
    distX,
    distY,
    threshold = 50, //required min distance traveled to be considered swipe
    restraint = 100, // maximum distance allowed at the same time in perpendicular direction
    allowedTime = 500, // maximum time allowed to travel that distance
    elapsedTime,
    startTime,
    handletouch = callback || function(evt, dir, phase, swipetype, distance){}

    touchsurface.addEventListener('touchstart', function(e){
        var touchobj = e.changedTouches[0]
        dir = 'none'
        swipeType = 'none'
        dist = 0
        startX = touchobj.pageX
        startY = touchobj.pageY
        startTime = new Date().getTime() // record time when finger first makes contact with surface
        handletouch(e, 'none', 'start', swipeType, 0) // fire callback function with params dir="none", phase="start", swipetype="none" etc
        e.preventDefault()
    }, false)

    touchsurface.addEventListener('touchmove', function(e){
        var touchobj = e.changedTouches[0]
        distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface
        distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface
        if (Math.abs(distX) > Math.abs(distY)){ // if distance traveled horizontally is greater than vertically, consider this a horizontal movement
            dir = (distX < 0)? 'left' : 'right'
            handletouch(e, dir, 'move', swipeType, distX) // fire callback function with params dir="left|right", phase="move", swipetype="none" etc
        }
        else{ // else consider this a vertical movement
            dir = (distY < 0)? 'up' : 'down'
            handletouch(e, dir, 'move', swipeType, distY) // fire callback function with params dir="up|down", phase="move", swipetype="none" etc
        }
        e.preventDefault()
        // prevent scrolling when inside DIV
    }, false)

    touchsurface.addEventListener('touchend', function(e){
        var touchobj = e.changedTouches[0]
        distX = touchobj.pageX - startX
        elapsedTime = new Date().getTime() - startTime // get time elapsed
        if (elapsedTime <= allowedTime){ // first condition for awipe met
            if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met
                swipeType = dir // set swipeType to either "left" or "right"
            }
            else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met
                swipeType = dir // set swipeType to either "top" or "down"
            }
        }
        // Fire callback function with params dir="left|right|up|down", phase="end", swipetype=dir etc:
        handletouch(e, dir, 'end', swipeType, (dir =='left' || dir =='right')? distX : distY)
        e.preventDefault()
        if(dir=="left"){
            if(distX>-100){
                $(".cells").css("left","0px")
            }
            else if(distX<-50 && distX>-100){
                $(".cells").css("left","-166px")
            }
            else{
                $(".cells").css("left","-166px")
            }
        }
    }, false)
}

How to make this swipe apply to a newly added table row?

like image 572
Anu Avatar asked Feb 16 '16 07:02

Anu


2 Answers

You should use event delegation on() to deal with new elements added dynamically by js :

$("body").on('touchstart click','#cashreg tr', function(e){

})

Hope this helps.

like image 68
Zakaria Acharki Avatar answered Sep 20 '22 14:09

Zakaria Acharki


The problem is that you bind your cells elements with the event ontouch in the load function. It means that only the elements present on load will be bound. You need to register the ontouch event on your newly created row element as well.

With your example, you could try to use the ontouch html attribute directly, i.e.:

 <div class="cells" ontouchstart="...">

or simply bind the touch event to your body and check for the cells class in the handler:

 var el = document.getElementsByTagName('body')[0];
 ontouch(el, function(evt, dir, phase, swipetype, distance){
     if($(evt.target).hasClass("cells")){
         // your code
     }
 }); 
like image 21
Derlin Avatar answered Sep 20 '22 14:09

Derlin