REDIPS.drag documentation - Appendix A

More...

Here is list of keywords (mostly class names) used in REDIPS.drag library. Id of drag container(s) or table cell class names should be named properly to achieve needed functionality like cloning DIV elements, adding trash cell, mark cells, adding row handler or mark table as "nolayout". This post is appendix to the REDIPS.drag documentation post.

Keywords
  1. drag
  2. clone
  3. mark
  4. only
  5. single
  6. trash
  7. rowhandler / row
  8. nolayout
  9. noautoscroll

Before going to keywords details, make sure that HTML file has DOCTYPE definition at the top. This will switch browser to the strict mode needed for drag and drop functionality - otherwise REDIPS.drag library will not work properly.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">



1. drag
drag is one of the most important keywords. It is used as default name for drag container and for marking DIV elements as drag-n-drop elements. During initialization, REDIPS.drag searches inside the drag container for every DIV element with drag class name and assigns onmousedown event handler. First, here is example of how to create drag container:

<div id="drag">
    <!-- table1 -->
    <table>
     ...
    </table>
    <!-- table2 -->
    <table>
     ...
    </table>
</div>

Any table within drag container will become drag-n-drop layout. The most common problems and questions I received in using REDIPS.drag library are related to drag container size. If width and height CSS properties of drag container are not properly set and inner table comes out of drag container borders then dragged DIV element will not "see" exceeded cells. Good rule is to make drag container visible in customization process of REDIPS.drag library to avoid mentioned problem:

#drag {
    border: 1px solid lime;
}

Next main role of drag keyword is to mark DIV elements as drag elements. Every DIV element inside drag container will be able to drag and drop if drag is in class names list.

<!-- simple DIV drag element -->
<div class="drag">Drag1</div>

<!-- DIV element contains two class names -->
<div class="drag green">Drag2</div>

And finally, it's possible to have more drag containers. Elements from first drag container can't be dropped to second drag container and vice versa.

<!-- first drag container -->
<div id="drag1">
    <table>
     ...
    </table>
</div>

<!-- second drag container -->
<div id="drag2">
    <table>
     ...
    </table>
</div>

Initialization of separated drag containers is slightly different because REDIPS.drag should know names of drag containers. Here is code snippet from example08:

// reference to the REDIPS.drag library
var rd = REDIPS.drag;
// DIV container initialization
rd.init('drag1');
rd.init('drag2');



2. clone
If DIV element contains clone class name then in a moment of dragging a new DIV element will be cloned. Original DIV element will stay in table cell. Here is how to define clone type of DIV element.

<!-- clone DIV element -->
<div class="drag clone">One of Many</div>

Cloning can be further customized with climit1_X and climit2_X class names (X is integer). If needed, number of cloned DIV elements can be limited with adding climit class name. climit1 means that last DIV element will be moveable while in case of climit2 last object will stay in cell as immovable object.

<!-- allow 4 cloned elements -->
<div class="drag clone climit1_4">Clone type1</div>

<!-- allow 3 cloned elements and left original element as immovable in cell -->
<div class="drag clone climit2_3">Clone type1</div>



3. mark
By default, if table cell is marked with mark class name then this table cell will be closed (forbidden) for any DIV element. Simply said, DIV element will not be able to drop to this cell. Here is example of how to mark table cells as closed:

<tr>
    <td class="mark">You</td>
    <td class="mark">can</td>
    <td class="mark">not</td>
    <td class="mark">drop</td>
    <td class="mark">here</td>
</tr>

It is possible to define exceptions for closed cells. For example, table cell can be forbidden for every DIV element except DIV elements with defined "id".

// allow DIV element with id="g1" to enter to the marked cell with class="green"
rd.mark.exception.g1 = 'green';

To avoid class name collisions on existing page, mark class name can be renamed with the following property:

// rename "mark" class name to "my_mark"
REDIPS.drag.mark.cname = 'my_mark';

If REDIPS.drag.mark.action is set to "allow", then dropping will be possible only to the marked table cell. This means that default behaviour is inverted.

// reference to the REDIPS.drag library
var	rd = REDIPS.drag;
// allow dropping only to the marked table cells
rd.mark.action = 'allow';



4. only
Table cells marked with only class name can accept only defined DIV elements. Here is example of how to define table cells marked with only class name.

<th class="only last"></th>

Without any additional rule, only table cells will be closed for any DIV element. With the following JS lines, table cells will accept only DIV elements with id="a" and id="b".

// reference to the REDIPS.drag
var rd = REDIPS.drag;
// define table cells with class="last" to accept only
// DIV elements with id="a" and id="b"
rd.only.div.a = 'last';
rd.only.div.b = 'last';

Above rules also means that DIV elements with id="a" and id="b" will not be able to drop to any other table cell. That behaviour defines REDIPS.drag.only.other property with default value set to "deny". If DIV elements with id="a" and id="b" are allowed to enter to other table cells then set the following property:

// allow DIV element tied with "only" rule to enter to other table cells
rd.only.other = 'allow';



5. single
Table cell marked with class name single will accept only one DIV element.

<!-- accept only one DIV element to the dark table cell -->
<td class="single dark" title="Single content cell"></td>



6. trash
Table cell marked with class name trash will behave as trash can.

<td class="trash" title="Trash">Trash</td>

It is possible to rename default class name (to avoid class name collisions):

REDIPS.drag.trash_cname = 'redips_bin';

Now trash cell will be defined as follows:

<td class="redips_bin" title="Trash">Trash</td>



7. rowhandler / row
To define row handler it is needed to add row class name to the DIV element and set rowhandler class name to table cell.

<tr>
    <td class="rowhandler"><div class="drag row"></div></td>
    <td></td>
    <td></td>
    <td></td>
</tr>

Table cells marked with class name rowhandler will be closed (or forbidden) for other DIV elements. In other words, DIV elements won't have access to the "row handler" table cell.



8. nolayout
If table contains nolayout in class name list then it will be treated as ordinary table and other DIV elements will not be able to enter to such table. This option can be handy if you want to put table inside DIV element and drag as any other content.

<table class="nolayout">
 ...
</table>



9. noautoscroll
If class name of scrollable DIV container contains noautoscroll class name then autoscroll option will be disabled.

<!-- drag container -->
<div id="drag">
    <!-- scrollable div container -->
    <div id="sdc" class="noautoscroll">
        <table>
         ...
        </table>
    </div>
</div>

To make DIV container scrollable, it is needed to set overflow to "auto" and position property to something else then default "static":

/* make sdc DIV container scrollable */
#sdc {
    overflow: auto;
    position: relative;
}

Here is snippet from www.howtocreate.co.uk: Element position with scrolling offsets with explanation why is needed to set CSS position property (to something else then default "static"). If CSS position of scrollable DIV container is not set, then dragged DIV element will not have correct position below mouse pointer.

... make sure that every element with an overflow of anything other than "visible" also has a position style set to something other than the default "static". This way, they will all appear in the offsetParent chain, and can be easily subtracted in the same loop that adds the offsetLeft and offsetTop.

This entry was posted on March 13, 2012 and is filed under Drag and Drop, JavaScript

Related posts

51 Responses to REDIPS.drag documentation - Appendix A

  1. Mentalic says:

    Hi dbunic,
    I tested this using redips-drag-source.js file and found that it keeps alternating between 2 lines for Layout. First is in getScrollPosition():

    getScrollPosition = function () {
        // define local scroll position variables
        var scrollX, scrollY;
        // Netscape compliant
        if (typeof(window.pageYOffset) === 'number') {
            scrollX = window.pageXOffset;
            scrollY = window.pageYOffset;
        }
        ...
        ...
    

    ... and Recalculate Style events:

    getStyle = function (el, style_name) {
        var val; // value of requested object and property
        if (el && el.currentStyle) {
            val = el.currentStyle[style_name];
        }
        else if (el && window.getComputedStyle) {
            val = document.defaultView.getComputedStyle(el, null)[style_name];
        }
        return val;
    };
    

    Any idea how I can reduce the time spent on these two calls?
    Thanks

  2. dbunic says:

    @Mentalic - During initialization - enableDrag(), for each DIV element is called boxOffset() and getStyle() method. boxOffset calls getScrollPosition() and that causes the first part of the problem. Please see changes made on github:

    https://github.com/dbunic/REDIPS_drag/commit/705b739ac0fdc5011d207a125f0f726d2075d375

    Actually, page scroll offset is now set in calculateCells() and this method is called on window scroll event. Hope this modification will reduce call number of getScrollPosition(). You can download all 5.0.7 version code from github.

    Second part is related to getStyle(). It is called twice in enableDrag() for every DIV element. If your page doesn't containt scrollable DIV container then you can completely comment out "else if (enable_flag === 'init') {" part. This check is not necessary and can be removed from code.

  3. Mentalic says:

    Thanks a lot dbunic....I will try that out and let you know how it works.

    As an aside, I had another question. Is it possible to trap a drag and drop outside the intended container?
    For e.g., let's say I have 2 baskets with colored balls, where each colored ball is a drag element. I can drag and drop these balls between the 2 baskets. If I drag and drop one outside of these 2 boxes, I want a popup to show up to allow me to take further actions. Is it possible to trap a drop outside these 2 containers?

    Thanks again for your prompt help !

  4. dbunic says:

    @Mentalic - You can write JS code inside moved() event handler. This handler will be fired in the moment when DIV element is moved from its current position. Or you can define TD outside baskets (like space between left and right basket) and when user drops DIV element to this cell, custom JS code in dropped() event handler can show popup with question. This can be similar to "Trash" cell with modified action ...

  5. Mentalic says:

    @dbunic. Thank you. Will try that out.

    btw...there is some improvement by using v 5.0.7. I will try the other change as well and see if it improves further.

    Thanks again.

  6. Mentalic says:

    Hi dbunic,

    I am facing another issue with 'click' events. I have a click event registered on each draggable div that shows a popup when that div element is clicked. When I drag this div onto another container, I have a confirm dialog that asks if the users wants to move this element. On yes, the div is dropped into the new container and no popup shows up. On cancel, drag is cancelled, but then the onclick on the div fires and the popup shows up.

    How is the onclick suppressed when the user says 'yes' to dropping into the new container? I tried stopPropagation on window.event, but that does not seem to work.

    Any thoughts?

    Thanks

  7. dbunic says:

    @Mentalic - Events in REDIPS.drag library are actually hooks in dragging process. When you say that "click event" is registered I'm not sure if additional event is attached to your DIV element or you write JS code inside rd.event.clicked(). It would be better to use original REDIPS.event hooks instead of attaching event listeners to the DIV elements.

    Next, for showing a popup (with question drop or not), you can use rd.event.droppedBefore(). If user click to "Yes" then DIV element will be dropped to the destination cell (code inside this event handler just needs to nicely finish - nothing to call). In case of "No", just return boolean false from droppedBefore() event handler and DIV element will be returned to the source cell.

    This code will return all dropped DIV elements to the source position:

    rd.event.droppedBefore = function (targetCell) {
        return false;
    };
    
  8. Nate says:

    Hi dbunic,
    Nice piece of code.
    I was so excited to see this as I am trying to create a dynamic form creator with the ability to drag and drop elements into a table. I tried to use the merge split functionality together with the drag and drop and I got an error after merging cells together and trying to drag and element that was inside one of the cells which I merged.
    I am going to have to unfortunately abandon this until this is resolved. The error happened on line 1908: in firebug this is the error I got: "TypeError: cell_current is undefined".
    Please let me know if I am doing something wrong or it is a bug which can be fixed.
    Regards,
    Nate

  9. dbunic says:

    @Nate - REDIPS.drag and REDIPS.table are designed to work together. Please see example 24: Table editor with the following features: merge/split cells horizontally, add/delete table row, drag and drop DIV elements ...

    Merging table cells with DIV elements inside, should work without a problem (or you found a bug). If you can prepare stand alone example (zip and email) or online example (with jsfiddle), I will gladly peek to the source code and try to help.

  10. Kev says:

    I have tried to add more lines to the school example but when save is pressed, the DIVs move up by 2 rows.
    Could you help?

  11. dbunic says:

    @Kev - If your question is still relevant (sorry for delay), adding TRs to the table should work without any problem. I tried to add the following lines to the index.php of example03:

    <?php timetable('17:00', 10) ?>
    <?php timetable('18:00', 11) ?>
    

    ... and last two rows appeared (ready for accepting new DIV elements). It was possible to drop there DIV elements and to save current positions.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

In case of posting HTML tags or JavaScript code please convert special characters to HTML entities.
Especially pay attention to convert "<" character to "&lt;" entity!