Mercurial > defr > drupal > scald > dnd
changeset 4:c2eb995212bf
TONS of fixes in this commit.
line wrap: on
line diff
--- a/dnd-library.tpl.php Tue Feb 17 15:46:36 2009 -0600 +++ b/dnd-library.tpl.php Thu Feb 19 12:33:19 2009 -0600 @@ -1,9 +1,9 @@ -<div id="<?php print $library_id; ?>"> +<div id="<?php print $library_id; ?>" class="dnd-library-wrapper"> <div class="header"> <?php print $header; ?> </div> <div class="library"> - <?php print implode('', $items); ?> + <?php print $library; ?> </div> <div class="footer"> <?php print $footer; ?>
--- a/dnd.module Tue Feb 17 15:46:36 2009 -0600 +++ b/dnd.module Thu Feb 19 12:33:19 2009 -0600 @@ -77,8 +77,8 @@ function dnd_process_textarea($element, $form_state) { if ($element['#dnd-enabled']) { - drupal_add_js(drupal_get_path('module', 'dnd') .'/js/dnd.js'); - drupal_add_js(drupal_get_path('module', 'dnd') .'/js/dnd-library.js'); + drupal_add_js(drupal_get_path('module', 'dnd') .'/js/dnd.js', 'footer'); + drupal_add_js(drupal_get_path('module', 'dnd') .'/js/dnd-library.js', 'footer'); $settings = array(); @@ -126,18 +126,16 @@ // We must remove some Drupal escaping $json = json_decode(str_replace(array('\x3c', '\x3e', '\x26'), array("<", ">", "&"), $request->data), TRUE); - foreach ($json['library'] as $id=>$item) { - $editor_representations[$id] = filter_xss_admin($item['editor']); - $library_representations[$id] = filter_xss_admin($item['library']); + // Generate an array of editor representations to add + foreach ($json['editor_representations'] as $editor_id=>$editor_item) { + $editor_representations[$editor_id] = filter_xss_admin($editor_item); } + // Store editor representations in Drupal setting + drupal_add_js(array('dndEditorRepresentations' => $editor_representations,), 'setting'); + $variables['library_id'] = $settings['library_id']; - $variables['header'] = filter_xss_admin($json['header']); - $variables['items'] = $library_representations; - $variables['footer'] = filter_xss_admin($json['footer']); - - // Store editor representations in Drupal setting - drupal_add_js(array( - 'dndEditorRepresentations' => $editor_representations, - ), 'setting'); + $variables['header'] = filter_xss_admin($json['header']); + $variables['library'] = filter_xss_admin($json['library']); + $variables['footer'] = filter_xss_admin($json['footer']); }
--- a/dnd_test/dnd_test.css Tue Feb 17 15:46:36 2009 -0600 +++ b/dnd_test/dnd_test.css Thu Feb 19 12:33:19 2009 -0600 @@ -1,25 +1,122 @@ +/* This is bad stuff! */ .body-field-wrapper { float: left; width: 100%; } - -#edit-body-dnd-library { +.dnd-library-wrapper { float: left; - width: 15%; - text-align: center; + width: 220px; + margin-right: 20px; + margin-top: 1em; + border: 1px solid #aaa; } -#edit-body-dnd-library img { - display: block; - margin: 2px auto; +.dnd-library-wrapper .header { + padding: 1px 4px; + background-color: #ccc; } -#edit-body-dnd-library .library a { - color: #000; - display: block; - padding: 4px; - margin-bottom: 6px; - text-decoration: none; +.dnd-library-wrapper .header h3 { + font-size: 12px; + font-weight: bold; +} +.dnd-library-wrapper .footer { + float: left; + width: 100%; + border-top: 1px solid #aaa; + background-color: #ccc; +} +.dnd-library-wrapper .pager { + font-weight: bold; + padding: 0 5px; } #edit-body-wrapper { float: left; - width: 85%; + width: 700px; } +.dnd-library-wrapper .editor-item { + float: left; + width: 220px; + border-top: 1px solid #aaa; + margin-bottom: 1px; +} +.dnd-library-wrapper .editor-item > div { + padding: 5px 4px; +} +.dnd-library-wrapper div.image { + float: left; + width: 64px; + padding-left: 6px; + line-height: 1; +} +.dnd-library-wrapper div.meta { + float: left; + width: 110px; +} +.dnd-library-wrapper .title { + font-weight: bold; +} +.dnd-library-wrapper .date, .dnd-library-wrapper .author { + font-size: .75em; +} +.dnd-library-wrapper .editor-item .sizes { + float: left; + width: 18px; +} +.dnd-library-wrapper .editor-item .sizes ul { + list-style-type: none; + margin: 0; +} +.dnd-library-wrapper .editor-item .sizes ul li { + background: none; + list-style-type: none; + padding: 0; + margin: 0; +} +.dnd-library-wrapper .editor-item .sizes a { + float: left; + display: block; + font-size: 9px; + line-height: 9px; + margin-bottom: 2px; + width: 19px; + text-align: center; +} +.dnd-library-wrapper .editor-item .sizes a:link, +.dnd-library-wrapper .editor-item .sizes a:visited, +.dnd-library-wrapper .editor-item .sizes a:active { + border: 1px solid #888; + color: #fff; + cursor: move; + text-align: center; +} +.dnd-library-wrapper .editor-item .sizes a:hover, +.dnd-library-wrapper .editor-item .sizes a.dnd-inserted:link, +.dnd-library-wrapper .editor-item .sizes a.dnd-inserted:visited, +.dnd-library-wrapper .editor-item .sizes a.dnd-inserted:active { + border: 1px solid #555; + color: #fff; + text-decoration: none; +} +.dnd-library-wrapper .editor-item .sizes a:hover span, +.dnd-library-wrapper .editor-item .sizes a.dnd-inserted span { + background-color: #555; +} + +.dnd-library-wrapper .editor-item .sizes a span { + display: block; + background-color: #888; +} +.dnd-library-wrapper .editor-item .sizes a.size-S span { + margin: 3px; + padding: 2px 0; +} +.dnd-library-wrapper .editor-item .sizes a.size-M span { + margin: 2px; + padding: 3px 0; +} +.dnd-library-wrapper .editor-item .sizes a.size-L span { + margin: 1px; + padding: 4px 0; +} +.dnd-library-wrapper .editor-item.dnd-child-inserted { + background-color: #ffd; +}
--- a/dnd_test/dnd_test.module Tue Feb 17 15:46:36 2009 -0600 +++ b/dnd_test/dnd_test.module Thu Feb 19 12:33:19 2009 -0600 @@ -1,5 +1,8 @@ <?php +/** + * Implementation of hook_menu(). + */ function dnd_test_menu() { $items = array(); $items['dnd-test/library'] = array( @@ -10,10 +13,19 @@ return $items; } +/** + * Implementation of hook_perm(). + */ function dnd_test_perm() { return array('access dnd test library'); } + +/** + * Implementation of hook_form_alter(). + * + * This demonstrates how to attach Drag and Drop to a given textarea. + */ function dnd_test_form_alter(&$form, &$form_state) { if ($form['#id'] == 'node-form' && $form['type']['#value'] == 'page') { drupal_add_css(drupal_get_path('module', 'dnd_test') .'/dnd_test.css'); @@ -26,21 +38,92 @@ } } +/** + * Implementation of hook_theme(). + */ +function dnd_test_theme() { + return array( + 'dnd_editor_item' => array( + 'arguments' => array('i' => NULL, 'size' => NULL), + 'template' => 'dnd-editor-item', + ), + 'dnd_library_item' => array( + 'arguments' => array('i' => NULL), + 'template' => 'dnd-library-item', + ), + ); +} + +/** + * Page call back that returns some JSON + */ function dnd_test_library() { + $page = ($_GET['page']) ? $_GET['page'] : 1; + $test_library = dnd_test_generate_library($page); + return drupal_json(array( + 'header' => '<h3>'. t('Test library: Page @page', array('@page' => $page)) .'</h3>', + 'library' => $test_library['library'], + 'editor_representations' => $test_library['editor_representations'], + 'footer' => '<div class="pager">'. l(t('1'), 'dnd-test/library') . ' '. l(t('2'), 'dnd-test/library', array('query' => array('page' => 2))) .'</div>', + )); +} - $var = array( - 'header' => '<h3>Test library</h3>', - 'footer' => '<div class="pager">'. l(1, 'dnd-test/library') . ' '. l(2, 'dnd-test/library', array('query' => array('page' => 2))) .'</div>', +/** + * Create contrived output + */ +function dnd_test_generate_library($page = 1, $limit = 5) { + $start = ($page * $limit) - ($limit); + $end = $page * $limit; + + $library = ''; + $editor_representations = array(); + for ($i=$start + 1; $i < $end + 1; $i++) { + $library .= theme('dnd_library_item', $i); + $editor_representations += dnd_editor_items($i); + } + return array( + 'library' => $library, + 'editor_representations' => $editor_representations, ); - $modifier = ($_GET['page'] == 2) ? 'page-2' : 'page-1'; - for ($i=1; $i < 6; $i++) { - $library = '<div class="row"><a href="" class="drop" id="image-'. $i .'-'. $modifier .'">'. theme('image', drupal_get_path('module', 'dnd_test') .'/img/'. $modifier .'-small.jpg') .'Image '. $i .'</a></div>'; - $editor = theme('image', drupal_get_path('module', 'dnd_test') .'/img/'. $modifier .'-large.jpg'); - $var['library']['image-'. $i .'-'. $modifier] = array( - 'library' => $library, - 'editor' => $editor, - ); +} + +/** + * Theme wrapper that spins out multiple library representations for a given + * editor representation. This is because we want to demonstrate how to allow + * for multiple versions (i.e. different sizes) of a single item + */ +function dnd_editor_items($i) { + $item = array(); + foreach(array(t('S'), t('M'), t('L')) as $size) { + $item['item-'. $i .'-'. $size] = theme('dnd_editor_item', $i, $size); } - drupal_json($var); - exit(); + return $item; } + +/** + * Completely contrived edit item theme function + */ +function template_preprocess_dnd_library_item(&$variables) { + $i = $variables['i']; + $variables['image'] = theme('image', drupal_get_path('module', 'dnd_test') .'/img/item-'. $i .'-thumb.jpg'); + $variables['title'] = t('Lorem Ipsum @count', array('@count' => $i)); + $variables['date'] = 'Feb 18 2009'; + $variables['author'] = 'David Eads'; + foreach(array(t('S'), t('M'), t('L')) as $size) { + $sizes[] = l('<span>'. $size .'</span>', '', array( + 'html' => TRUE, + 'attributes' => array( + 'class' => 'drop size-'. $size, + 'id' => 'item-'. $i .'-'. $size, + ), + 'query' => array('dnd_id' => 'item-'. $i .'-'. $size), + )); + } + $variables['sizes'] = '<ul><li>'. implode('</li><li>', $sizes) .'</li></ul>'; +} + + +function template_preprocess_dnd_editor_item(&$variables) { + list($i, $size) = array($variables['i'], $variables['size']); + $variables['image'] = theme('image', drupal_get_path('module', 'dnd_test') .'/img/item-'. $i .'-'. $size .'.jpg'); +}
--- a/js/dnd-library.js Tue Feb 17 15:46:36 2009 -0600 +++ b/js/dnd-library.js Thu Feb 19 12:33:19 2009 -0600 @@ -1,64 +1,93 @@ Drupal.behaviors.dndLibrary = function(context) { - var libraries = Drupal.settings.dndEnabledLibraries; + $('.dnd-library-wrapper:not(.dnd-processed)', context).each(function() { + var $this = $(this); - // Loop over libraries keyed by the textarea they are associated with - for (var textarea_id in libraries) { + // This is a bad hack to lop off '-dnd-library' from the id to get the editor name + var editor = this.id.slice(0, -12); - var library = $('#' + textarea_id + '-dnd-library'); + // Attempt to attach library + //Drupal.behaviors.dndLibrary.attach_library(false, Drupal.wysiwyg.instances[editor]); - // Ajax pager: This seems like it is bad to be here - $('.pager a', library).click(function(e, data) { + // Bind Drag and Drop plugin invocation to wywsiwygAttach event + $('#' + editor).bind('wysiwygAttach', Drupal.behaviors.dndLibrary.attach_library); + + // @TODO track and clear intervals to save memory at the cost of + // more processing? + $('#' + editor).bind('wysiwygDetach', Drupal.behaviors.dndLibrary.detach_library); + + // Ajax pager + $('.pager a', $this).click(function(e, data) { $.getJSON(this.href, function(data) { - $('.library', library).html(''); - for (item in data.library) { - $('.library', library).append(data.library[item].library); - Drupal.settings.dndEditorRepresentations[item] = data.library[item].editor; - Drupal.behaviors.dndLibrary(context); // Durn event reattachment + $('.header', $this).html(data.header); + $('.library', $this).html(data.library); + //$('.footer', $this).html(data.footer); + for (editor_id in data.editor_representations) { + Drupal.settings.dndEditorRepresentations[editor_id] = data.editor_representations[editor_id]; } + var params = Drupal.wysiwyg.instances[editor]; + $('#' + editor).trigger('wysiwygAttach', params); }); return false; }); - // Bind Drag and Drop plugin invocation to wywsiwygAttach event - $('#' + textarea_id).bind('wysiwygAttach', function(e, data) { - var settings = { - renderRepresentation: function(target, drop, representation_id) { - console.log(representation_id); - return Drupal.settings.dndEditorRepresentations[representation_id]; - } - } - settings = $.extend(settings, libraries[textarea_id]); + $this.addClass('dnd-processed'); + }); +} - // Get editor attachment function - var editor_fn = 'attach_' + data.editor; - if ($.isFunction(window.Drupal.behaviors.dndLibrary[editor_fn])) { - window.Drupal.behaviors.dndLibrary[editor_fn](data, settings); - } - }); +Drupal.behaviors.dndLibrary.attach_library = function(e, data) { + var settings = { + renderRepresentation: function(target, drop, representation_id) { + return Drupal.settings.dndEditorRepresentations[representation_id]; + } + } + settings = $.extend(settings, Drupal.settings.dndEnabledLibraries[data.field]); - // @TODO track and clear intervals to save memory at the cost of - // more processing? - $('#' + textarea_id).bind('wysiwygDetach', function(e, data) { - console.log('detach'); - }); + var editor_fn = 'attach_' + data.editor; + if ($.isFunction(window.Drupal.behaviors.dndLibrary[editor_fn])) { + window.Drupal.behaviors.dndLibrary[editor_fn](data, settings); } } +Drupal.behaviors.dndLibrary.detach_library = function(e, data) { + console.log('detach'); +} + + Drupal.behaviors.dndLibrary.attach_tinymce = function(data, settings) { - var tiny = tinyMCE.getInstanceById(data.field); - $('#'+ data.field +'-wrapper iframe').load(function() { - settings = $.extend({ - targets: $('#'+ data.field +'-wrapper iframe'), - insertAfter: '<p><span id="__caret">_</span></p>', - postprocessDrop: function() { - // Get our special span, select it, delete it, and hope the caret - // resets correctly. - tiny.selection.select(tiny.dom.get('__caret')); - tiny.execCommand('Delete', false, null); - tiny.dom.remove('__caret'); + + var tiny_instance = tinyMCE.getInstanceById(data.field); + + // If the Tiny instance exists, attach directly, otherwise wait until Tiny + // has registered a new instance. + if (tiny_instance) { + Drupal.behaviors.dndLibrary._attach_tinymce(data, settings, tiny_instance); + } else { + var t = setInterval(function() { + var tiny_instance = tinyMCE.getInstanceById(data.field); + if (tiny_instance) { + Drupal.behaviors.dndLibrary._attach_tinymce(data, settings, tiny_instance); + clearInterval(t); } - }, settings); + }, 100); + } +} - $(settings.drop_selector).dnd(settings); - }); +Drupal.behaviors.dndLibrary._attach_tinymce = function(data, settings, tiny_instance) { + settings = $.extend({ + targets: $('#'+ data.field +'-wrapper iframe'), + insertAfter: '<p><span id="__caret">_</span></p>', + postprocessDrop: function(target, drop, element) { + // Get our special span, select it, delete it, and hope the caret + // resets correctly. + tiny_instance.selection.select(tiny_instance.dom.get('__caret')); + tiny_instance.execCommand('Delete', false, null); + tiny_instance.dom.remove('__caret'); + + // Add some classes to the library items + $(element).addClass('dnd-inserted'); + $(element).parents('.editor-item').addClass('dnd-child-inserted'); + } + }, settings); + + $(settings.drop_selector).dnd(settings); }
--- a/js/dnd.js Tue Feb 17 15:46:36 2009 -0600 +++ b/js/dnd.js Thu Feb 19 12:33:19 2009 -0600 @@ -85,10 +85,11 @@ (function($) { $.fn.dnd = function(opt) { opt = $.extend({}, { - dropWrapper: '<p class="dnd-inserted"></p>', + dropWrapper: '<p class="dnd-dropped"></p>', insertBefore: '', insertAfter: '', processedClass: 'dnd-processed', + disableClick: true, processTargets: function(targets) { return targets.each(function() { @@ -145,12 +146,15 @@ return $('#'+ element_id, $(target).contents()); }, - postprocessDrop: function(target, drop) { return; } + postprocessDrop: function(target, drop, element) { + $(element).addClass('dnd-inserted'); + } }, opt); // Initialize plugin var targets = opt.processTargets(opt.targets); + if (opt.disableClick) { this.click(function() { return false; }) } // Process! return this.each(function() { @@ -182,7 +186,7 @@ .after(opt.insertAfter) .wrap(opt.dropWrapper) .replaceWith(opt.renderRepresentation(target, drop, representation_id)); - opt.postprocessDrop(target, drop); + opt.postprocessDrop(target, drop, element); } }, 100); // @TODO track the timer with $.data() so we can clear it?