Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7822349
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 2, 20262026-06-02T07:54:21+00:00 2026-06-02T07:54:21+00:00

I’ve found a script that seems perfect for my needs, but it uses IDs,

  • 0

I’ve found a script that seems perfect for my needs, but it uses IDs, rather than classes to create ipad-friendly drag & drop elements.

I really need it to use classes, as the draggable elements could potentially be in the thousands.

[edit] I’m not that great at javascript and am having difficulties in understanding how I could alter the script to use classes instead of IDs.

I have also contacted the script author, but have had no reply from him.

I’m offering this bounty as I’ve not had any response to my original query.

Please could someone change the script below so that it uses classes? [/edit]

Below is the script in its entirety, and here is the script page (API was not helpful to me in being able to use classes vs id).

// webkitdragdrop.js v1.0, Mon May 15 2010
//
// Copyright (c) 2010 Tommaso Buvoli (http://www.tommasobuvoli.com)
// No Extra Libraries are required, simply download this file, add it to your pages!
//
// To See this library in action, grab an ipad and head over to http://www.gotproject.com
// webkitdragdrop is freely distributable under the terms of an MIT-style license.


//Description
// Because this library was designed to run without requiring any other libraries, several basic helper functions were implemented
// 6 helper functons in this webkit_tools class have been taked directly from Prototype 1.6.1 (http://prototypejs.org/) (c) 2005-2009 Sam Stephenson

var webkit_tools = 
{
    //$ function - simply a more robust getElementById

    $:function(e)
    {
        if(typeof(e) == 'string')
        {
            return document.getElementById(e);
        }
        return e;
    },

    //extend function - copies the values of b into a (Shallow copy)

    extend:function(a,b)
    {
        for (var key in b)
        {
            a[key] = b[key];    
        }   
        return a;
    },

    //empty function - used as defaut for events

    empty:function()
    {

    },

    //remove null values from an array

    compact:function(a)
    {
        var b = []
        var l = a.length;
        for(var i = 0; i < l; i ++)
        {
            if(a[i] !== null)
            {
                b.push(a[i]);
            }
        }
        return b;
    },

    //DESCRIPTION
    //  This function was taken from the internet (http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/) and returns 
    //  the computed style of an element independantly from the browser
    //INPUT
    //  oELM (DOM ELEMENT) element whose style should be extracted
    //  strCssRule element

    getCalculatedStyle:function(oElm, strCssRule)
    {
        var strValue = "";
        if(document.defaultView && document.defaultView.getComputedStyle){
            strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
        }
        else if(oElm.currentStyle){
            strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
                return p1.toUpperCase();
            });
            strValue = oElm.currentStyle[strCssRule];
        }
        return strValue;
    },

    //bindAsEventListener function - used to bind events

    bindAsEventListener:function(f,object) 
    {
        var __method = f;
        return function(event) {
            __method.call(object, event || window.event);
        };
    },

    //cumulative offset - courtesy of Prototype (http://www.prototypejs.org)

    cumulativeOffset:function(element) 
    {
        var valueT = 0, valueL = 0;
        do {
          valueT += element.offsetTop  || 0;
          valueL += element.offsetLeft || 0;
          if (element.offsetParent == document.body)
            if (element.style.position == 'absolute') break;

          element = element.offsetParent;
        } while (element);

        return {left : valueL, top : valueT};
    },

    //getDimensions - courtesy of Prototype (http://www.prototypejs.org)

    getDimensions: function(element) 
    {
        var display = element.style.display;
        if (display != 'none' && display != null) // Safari bug
          return {width: element.offsetWidth, height: element.offsetHeight};

        var els = element.style;
        var originalVisibility = els.visibility;
        var originalPosition = els.position;
        var originalDisplay = els.display;
        els.visibility = 'hidden';
        if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
          els.position = 'absolute';
        els.display = 'block';
        var originalWidth = element.clientWidth;
        var originalHeight = element.clientHeight;
        els.display = originalDisplay;
        els.position = originalPosition;
        els.visibility = originalVisibility;
        return {width: originalWidth, height: originalHeight};
    },

    //hasClassName - courtesy of Prototype (http://www.prototypejs.org)

    hasClassName: function(element, className) 
    {
        var elementClassName = element.className;
        return (elementClassName.length > 0 && (elementClassName == className ||
        new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
    },

    //addClassName - courtesy of Prototype (http://www.prototypejs.org)

    addClassName: function(element, className) 
    {
        if (!this.hasClassName(element, className))
            element.className += (element.className ? ' ' : '') + className;
        return element;
    },

    //removeClassName - courtesy of Prototype (http://www.prototypejs.org)

    removeClassName: function(element, className) 
    {
        element.className = this.strip(element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' '));
        return element;
    },

    //strip - courtesy of Prototype (http://www.prototypejs.org)

    strip:function(s)
    {
        return s.replace(/^\s+/, '').replace(/\s+$/, '');
    }

}

//Description
// Droppable fire events when a draggable is dropped on them

var webkit_droppables = function()
{
    this.initialize = function()
    {
        this.droppables = [];
        this.droppableRegions = [];
    }

    this.add = function(root, instance_props)
    {
        root = webkit_tools.$(root);
        var default_props = {accept : [], hoverClass : null, onDrop : webkit_tools.empty, onOver : webkit_tools.empty, onOut : webkit_tools.empty};
        default_props = webkit_tools.extend(default_props, instance_props || {});
        this.droppables.push({r : root, p : default_props});        
    }

    this.remove = function(root)
    {
        root = webkit_tools.$(root);
        var d = this.droppables;
        var i = d.length;
        while(i--)
        {
            if(d[i].r == root)
            {
                d[i] = null;
                this.droppables = webkit_tools.compact(d);
                return true;
            }
        }
        return false;
    }

    //calculate position and size of all droppables

    this.prepare = function()
    {
        var d = this.droppables;
        var i = d.length;
        var dR = [];
        var r = null;

        while(i--)
        {
            r = d[i].r;         
            if(r.style.display != 'none')
            {
                dR.push({i : i, size : webkit_tools.getDimensions(r), offset : webkit_tools.cumulativeOffset(r)})           
            }
        }

        this.droppableRegions = dR;
    }

    this.finalize = function(x,y,r,e)
    {
        var indices = this.isOver(x,y);
        var index = this.maxZIndex(indices);
        var over = this.process(index,r);
        if(over)
        {
            this.drop(index, r,e);
        }
        this.process(-1,r);
        return over;    
    }

    this.check = function(x,y,r)
    {
        var indices = this.isOver(x,y);
        var index = this.maxZIndex(indices);
        return this.process(index,r);       
    }

    this.isOver = function(x, y)
    {
        var dR = this.droppableRegions;
        var i = dR.length;
        var active = [];
        var r = 0;
        var maxX = 0;
        var minX = 0;
        var maxY = 0;
        var minY = 0;

        while(i--)
        {
            r = dR[i];

            minY = r.offset.top;
            maxY = minY + r.size.height;

            if((y > minY) && (y < maxY))
            {
                minX = r.offset.left;
                maxX = minX + r.size.width;

                if((x > minX) && (x < maxX))
                {
                    active.push(r.i);
                }           
            }       
        }

        return active;  
    }

    this.maxZIndex = function(indices)
    {
        var d = this.droppables;
        var l = indices.length;
        var index = -1;

        var maxZ = -100000000;
        var curZ = 0;

        while(l--)
        {
            curZ = parseInt(d[indices[l]].r.style.zIndex || 0);
            if(curZ > maxZ)
            {
                maxZ = curZ;
                index = indices[l];     
            }   
        }

        return index;   
    }

    this.process = function(index, draggableRoot)
    {
        //only perform update if a change has occured
        if(this.lastIndex != index)
        {
            //remove previous
            if(this.lastIndex != null)
            {
                var d = this.droppables[this.lastIndex]
                var p = d.p;
                var r = d.r;

                if(p.hoverClass)
                {
                    webkit_tools.removeClassName(r,p.hoverClass);
                }
                p.onOut();
                this.lastIndex = null;
                this.lastOutput = false;
            }

            //add new
            if(index != -1)
            {
                var d = this.droppables[index]
                var p = d.p;
                var r = d.r;

                if(this.hasClassNames(draggableRoot, p.accept))
                {
                    if(p.hoverClass)
                    {
                        webkit_tools.addClassName(r,p.hoverClass);
                    }
                    p.onOver();             
                    this.lastIndex = index;
                    this.lastOutput = true; 
                }
            }   
        }
        return this.lastOutput;
    }

    this.drop = function(index, r, e)
    {
        if(index != -1)
        {
            this.droppables[index].p.onDrop(r,e);
        }
    }

    this.hasClassNames = function(r, names)
    {
        var l = names.length;
        if(l == 0){return true}
        while(l--)
        {
            if(webkit_tools.hasClassName(r,names[l]))
            {
                return true;
            }
        }
        return false;
    }

    this.initialize();
}

webkit_drop = new webkit_droppables();

//Description
//webkit draggable - allows users to drag elements with their hands

var webkit_draggable = function(r, ip)
{
    this.initialize = function(root, instance_props)
    {
        this.root = webkit_tools.$(root);
        var default_props = {scroll : false, revert : false, handle : this.root, zIndex : 1000, onStart : webkit_tools.empty, onEnd : webkit_tools.empty};      

        this.p = webkit_tools.extend(default_props, instance_props || {});
        default_props.handle = webkit_tools.$(default_props.handle);
        this.prepare();
        this.bindEvents();
    }

    this.prepare = function()
    {
        var rs = this.root.style;

        //set position
        if(webkit_tools.getCalculatedStyle(this.root,'position') != 'absolute')
        {
            rs.position = 'relative';
        }

        //set top, right, bottom, left
        rs.top = rs.top || '0px';
        rs.left = rs.left || '0px';
        rs.right = "";
        rs.bottom = "";     

        //set zindex;
        rs.zIndex = rs.zIndex || '0';
    }

    this.bindEvents = function()
    {
        var handle = this.p.handle;

        this.ts = webkit_tools.bindAsEventListener(this.touchStart, this);
        this.tm = webkit_tools.bindAsEventListener(this.touchMove, this);
        this.te = webkit_tools.bindAsEventListener(this.touchEnd, this);        

        handle.addEventListener("touchstart", this.ts, false);
        handle.addEventListener("touchmove", this.tm, false);
        handle.addEventListener("touchend", this.te, false);
    }   

    this.destroy = function()
    {
        var handle = this.p.handle;

        handle.removeEventListener("touchstart", this.ts);
        handle.removeEventListener("touchmove", this.tm);
        handle.removeEventListener("touchend", this.te);    
    }

    this.set = function(key, value)
    {
        this.p[key] = value;
    }

    this.touchStart = function(event)
    {
        //prepare needed variables
        var p = this.p;
        var r = this.root;
        var rs = r.style;
        var t = event.targetTouches[0];     

        //get position of touch
        touchX = t.pageX;
        touchY = t.pageY;

        //set base values for position of root
        rs.top = this.root.style.top || '0px';
        rs.left = this.root.style.left || '0px';
        rs.bottom = null;
        rs.right = null;

        var rootP = webkit_tools.cumulativeOffset(r);
        var cp = this.getPosition();

        //save event properties
        p.rx = cp.x;
        p.ry = cp.y;        
        p.tx = touchX;
        p.ty = touchY;
        p.z = parseInt(this.root.style.zIndex);

        //boost zIndex
        rs.zIndex = p.zIndex;
        webkit_drop.prepare();
        p.onStart();
    }

    this.touchMove = function(event)
    {
        event.preventDefault();
        event.stopPropagation();

        //prepare needed variables
        var p = this.p;
        var r = this.root;
        var rs = r.style;
        var t = event.targetTouches[0];
        if(t == null){return}

        var curX = t.pageX;
        var curY = t.pageY;

        var delX = curX - p.tx;
        var delY = curY - p.ty;

        rs.left = p.rx + delX + 'px';
        rs.top  = p.ry + delY + 'px';

        //scroll window
        if(p.scroll)
        {
            s = this.getScroll(curX, curY);
            if((s[0] != 0) || (s[1] != 0))
            {
                window.scrollTo(window.scrollX + s[0], window.scrollY + s[1]);
            }
        }

        //check droppables
        webkit_drop.check(curX, curY, r);

        //save position for touchEnd
        this.lastCurX = curX;
        this.lastCurY = curY;
    }

    this.touchEnd = function(event)
    {
        var r = this.root;
        var p = this.p;
        var dropped = webkit_drop.finalize(this.lastCurX, this.lastCurY, r, event);

        if(((p.revert) && (!dropped)) || (p.revert === 'always'))
        {
            //revert root
            var rs = r.style;
            rs.top = (p.ry + 'px');
            rs.left = (p.rx + 'px');
        }

        r.style.zIndex = this.p.z;
        this.p.onEnd();
    }

    this.getPosition = function()
    {
        var rs = this.root.style;
        return {x : parseInt(rs.left || 0), y : parseInt(rs.top  || 0)}
    }

    this.getScroll = function(pX, pY)
    {
        //read window variables
        var sX = window.scrollX;
        var sY = window.scrollY;

        var wX = window.innerWidth;
        var wY = window.innerHeight;

        //set contants      
        var scroll_amount = 10; //how many pixels to scroll
        var scroll_sensitivity = 100; //how many pixels from border to start scrolling from.

        var delX = 0;
        var delY = 0;       

        //process vertical y scroll
        if(pY - sY < scroll_sensitivity)
        {
            delY = -scroll_amount;
        }
        else
        if((sY + wY) - pY < scroll_sensitivity)
        {
            delY = scroll_amount;
        }

        //process horizontal x scroll
        if(pX - sX < scroll_sensitivity)
        {
            delX = -scroll_amount;
        }
        else
        if((sX + wX) - pX < scroll_sensitivity)
        {
            delX = scroll_amount;
        }

        return [delX, delY]
    }

    //contructor
    this.initialize(r, ip);
}

//Description
//webkit_click class. manages click events for draggables

var webkit_click = function(r, ip)
{
    this.initialize = function(root, instance_props)
    {
        var default_props = {onClick : webkit_tools.empty};

        this.root = webkit_tools.$(root);
        this.p = webkit_tools.extend(default_props, instance_props || {});
        this.bindEvents();
    }

    this.bindEvents = function()
    {
        var root = this.root;

        //bind events to local scope
        this.ts = webkit_tools.bindAsEventListener(this.touchStart,this);
        this.tm = webkit_tools.bindAsEventListener(this.touchMove,this);
        this.te = webkit_tools.bindAsEventListener(this.touchEnd,this);

        //add Listeners
        root.addEventListener("touchstart", this.ts, false);
        root.addEventListener("touchmove", this.tm, false);
        root.addEventListener("touchend", this.te, false);

        this.bound = true;  
    }   

    this.touchStart = function()
    {
        this.moved = false;
        if(this.bound == false)
        {
            this.root.addEventListener("touchmove", this.tm, false);
            this.bound = true;
        }
    }

    this.touchMove = function()
    {
        this.moved = true;
        this.root.removeEventListener("touchmove", this.tm);
        this.bound = false;
    }

    this.touchEnd = function()
    {
        if(this.moved == false)
        {
            this.p.onClick();
        }
    }

    this.setEvent = function(f)
    {
        if(typeof(f) == 'function')
        {
            this.p.onClick = f;
        }
    }

    this.unbind = function()
    {
        var root = this.root;
        root.removeEventListener("touchstart", this.ts);
        root.removeEventListener("touchmove", this.tm);
        root.removeEventListener("touchend", this.te);
    }

    //call constructor
    this.initialize(r, ip);
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-02T07:54:22+00:00Added an answer on June 2, 2026 at 7:54 am

    If your classnames are unique, the solution is rather simple. You can change the $ function to get by class name instead of by id:

    var webkit_tools = 
    {
        //$ function - simply a more robust getElementById
    
        $:function(e)
        {
            if(typeof(e) == 'string')
            {
                return document.getElementsByClassName(e)[0];
                // return document.getElementById(e);
            }
            return e;
        },
        ... snipped ...
    

    I’ve verified the above solution works (dragging and dropping) on my iPhone, but again, if the classnames are not unique, some added work will be in order based on the script’s current implementation.

    ~~~EDIT~~~

    In re-reading your request, you state that there will in fact NOT be unique classnames, hence the need for some sort of “bulk” drag/drop functionality. I’ve modified/extended the framework to support this. You can find the source for the modified version here:

    https://gist.github.com/2474416

    I had to change the API slightly. The dropabble API is unchanged, so passing a classname will simply add/remove the whole list of elements matching the classname passed. The clickable/draggable API was not so easy. To avoid a harsh rewrite, I updated the initialize methods for draggable/clickable to take an element ref rather than id or classname.

    Correspondingly, I added a bulk_draggable(clazzname, options) and bulk_clickable(clazzname, options) function that basically iterates over the matched elements and calls the corresponding initializers. These functions return an array of draggables/clickables (one for each matched element).

    Let me know if the “new” API is unclear. I did this rather quickly and lightly tested the happy paths, but can’t invest and substantial amount of time rewriting the entire script.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a French site that I want to parse, but am running into
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I'm trying to create an if statement in PHP that prevents a single post
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I want to count how many characters a certain string has in PHP, but
Basically, what I'm trying to create is a page of div tags, each has
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I've got a string that has curly quotes in it. I'd like to replace
I am doing a simple coin flipping experiment for class that involves flipping a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.