Mercurial > defr > drupal > scald > dnd
diff js/jquery.draganddrop.js @ 20:89fe0aca43d4
Refactored the entire interval system, and started on form behavior.
author | David Eads <eads@chicagotech.org> |
---|---|
date | Sun, 08 Mar 2009 20:29:57 -0500 |
parents | 0d557e6e73f7 |
children | 4f58fa0a9a6d |
line wrap: on
line diff
--- a/js/jquery.draganddrop.js Fri Mar 06 14:26:06 2009 -0600 +++ b/js/jquery.draganddrop.js Sun Mar 08 20:29:57 2009 -0500 @@ -1,4 +1,5 @@ -/* jQuery Drag and Drop Library for Rich Editors +/** + * jQuery Drag and Drop Library for Rich Editors * * A helper library which provides the ability to drag and drop images to Rich * Text Editors (RTEs) that use the embedded iframe + DesignMode method. DnD @@ -7,7 +8,7 @@ * * Basic usage: * - * $('img.my-class').dnd({targets: $('#my-iframe')}); + * $('img.my-draggable-class').dnd({targets: $('#my-rte-iframe')}); * * Options: * @@ -21,24 +22,34 @@ * markup to be copied when dragging and dropping, Safari (and assumably * other webkit based browsers) don't. The upshot is that the safest bet is * to parse the element's src URL. Because querystrings seem to drop - * consistently across + * consistently across browsers, encoding the id in a query string is a good + * option. * * processIframeDrop: * A callback that defines the mechanism for inserting and rendering the * dropped item in an iframe. The typical usage pattern I expect to see is * that implementers will listen for their RTE to load and then invoke DnD - * with a processIframeDrop appropriate to their editor. + * with a processIframeDrop appropriate to their editor. For performance + * reasons, this only runs once per invocation of DnD -- to compensate, we + * must pass in an idselector callback as an argument. * - * processTextAreaDrop: + * processTextAreaClick: * A callback that defines the mechanism for inserting and rendering the * clicked item in a textarea. The default function just tries to insert * some markup at the caret location in the current textarea. * + * iframeTargetClass: + * A class to add to a draggable item if it can be dragged to an iframe. + * + * textareaTargetClass: + * A class to add to a draggable item if it can be dragged to a textarea. + * + * processClass: + * A class to add to draggable items processed by DnD. + * * interval: * How often to check the iframe for a drop, in milliseconds. * - * - * * Usage notes: * * Due to cross browser flakiness, there are many many limitations on what is @@ -47,7 +58,7 @@ * To make this work, your "droppable" elements must be image tags. No ifs, ands, * or buts: image tags have the best cross browser behavior when dragging. * - * When DnD is initialized, it begins timers which periodically check your + * When DnD is invoked, it begins a timer which periodically checks your * editor iframe. If an image is dropped in, DnD takes the element and * attempts to parse it for a unique ID which you can use to do a lookup for * an "editor representation." If an editor representation is found, @@ -64,9 +75,6 @@ * system for clicking what would otherwise be dragged to insert markup into * the textarea. * - * DnD is purely a utility library: to make it work for any particular editor, - * CMS, etc: It is very unlikely it will provide much benefit out of the box. - * * Because DnD spawns so many timers, they are stored in a $.data element * attached to the parent document body. Implementers should consider clearing * the timers when building systems such as dynamic searches or paging @@ -90,34 +98,49 @@ } return false; }, - processIframeDrop: function(target, dragged, dropped, representation_id) { - // Keep a counter of how many times this element was used - var count = $.data(target, representation_id +'_count'); - if (!count) { - count = 1; - } else { - count++; - } - $.data(target, representation_id +'_count', count); - $(dropped).replaceWith('<p id="dnd-' + representation_id +'-'+ count +'">' + representation_id + '</p>'); + processIframeDrop: function(drop, id_selector) { + var representation_id = opt.idSelector(drop); + $(drop).replaceWith(representation_id).wrap('<p class="dnd-dropped"></p>'); }, - processTextAreaDrop: function(target, clicked, representation_id, e, data) { + processTextAreaClick: function(target, clicked, representation_id) { var snippet = '<div><img src="'+ representation_id +'" /></div>'; $(target).replaceSelection(snippet, true); e.preventDefault(); - } + }, + processIframeClick: function (target, clicked, representation_id) { return true; }, + + iframeTargetClass: 'dnd-iframe-target', + textareaTargetClass: 'dnd-textarea-target', + processedClass: 'dnd-processed' }, opt); // Initialize plugin var targets = opt.processTargets(opt.targets); - // Process! + // Watch iframes for changes + $(targets).filter('iframe').each(function() { + var target = this; + var t = setInterval(function() { + $('img:not(.dnd-dropped)', $(target).contents()).each(function() { + opt.processIframeDrop.call(target, this, opt.idSelector); + }); + }, opt.interval); + + // Track current active timers -- developers working with DnD + // can implement their own garbage collection for specific + // interactions, such as paging or live search. + var data = $(document).data('dnd_timers'); + if (!data) { data = {}; } + data[target.id] = t; + $(document).data('dnd_timers', data); + }); + + // Process each draggable element return this.each(function() { if ($(this).is('img')) { var element = this, $element = $(element); - // If we don't have a proper id, bail var representation_id = opt.idSelector(element); if (!representation_id) { @@ -125,42 +148,20 @@ }; // Add a special class - $(element).addClass('dnd-processed'); + $(element).addClass(opt.processedClass); - // We need to differentiate behavior based on the targets... I guess. + // We need to differentiate behavior based on the targets targets.each(function() { var target = this, $target = $(target); if ($target.is('iframe')) { - - // Indicate this element is draggy - $element.css('cursor', 'move'); - - // Watch the iframe for changes - var t = setInterval(function() { - $('img:not(.dnd-dropped)', $(target).contents()).each(function() { - var dropped = this; - if (opt.idSelector(dropped) == representation_id) { - opt.processIframeDrop(target, element, dropped, representation_id); - } - }); - }, opt.interval); - - // Track current active timers -- developers working with DnD - // can implement their own garbage collection for specific - // interactions, such as paging or live search. - var data = $(document).data('dnd_timers'); - if (data) { - data[data.length] = t; - } else { - data = new Array(); - data[0] = t; - } - $(document).data('dnd_timers', data); - + $(element).addClass(opt.iframeTargetClass); + $(element).click(function() { + opt.processIframeClick.call(target, element, representation_id); + }); } else if ($target.is('textarea')) { - $element.css('cursor', 'pointer'); - $(element).click(function(e, data) { - opt.processTextAreaDrop(target, element, representation_id, e, data); + $(element).addClass(opt.textareaTargetClass); + $(element).click(function() { + opt.processTextAreaClick.call(target, element, representation_id); }); } });