changeset 4:c2eb995212bf

TONS of fixes in this commit.
author David Eads <eads@chicagotech.org>
date Thu, 19 Feb 2009 12:33:19 -0600
parents 5df0783706f7
children dd05863db31c
files dnd-library.tpl.php dnd.module dnd_test/dnd_test.css dnd_test/dnd_test.module dnd_test/img/item-1-L.jpg dnd_test/img/item-1-M.jpg dnd_test/img/item-1-S.jpg dnd_test/img/item-1-thumb.jpg dnd_test/img/item-10-L.jpg dnd_test/img/item-10-M.jpg dnd_test/img/item-10-S.jpg dnd_test/img/item-10-thumb.jpg dnd_test/img/item-2-L.jpg dnd_test/img/item-2-M.jpg dnd_test/img/item-2-S.jpg dnd_test/img/item-2-thumb.jpg dnd_test/img/item-3-L.jpg dnd_test/img/item-3-M.jpg dnd_test/img/item-3-S.jpg dnd_test/img/item-3-thumb.jpg dnd_test/img/item-4-L.jpg dnd_test/img/item-4-M.jpg dnd_test/img/item-4-S.jpg dnd_test/img/item-4-thumb.jpg dnd_test/img/item-5-L.jpg dnd_test/img/item-5-M.jpg dnd_test/img/item-5-S.jpg dnd_test/img/item-5-thumb.jpg dnd_test/img/item-6-L.jpg dnd_test/img/item-6-M.jpg dnd_test/img/item-6-S.jpg dnd_test/img/item-6-thumb.jpg dnd_test/img/item-7-L.jpg dnd_test/img/item-7-M.jpg dnd_test/img/item-7-S.jpg dnd_test/img/item-7-thumb.jpg dnd_test/img/item-8-L.jpg dnd_test/img/item-8-M.jpg dnd_test/img/item-8-S.jpg dnd_test/img/item-8-thumb.jpg dnd_test/img/item-9-L.jpg dnd_test/img/item-9-M.jpg dnd_test/img/item-9-S.jpg dnd_test/img/item-9-thumb.jpg dnd_test/img/page-1-small.jpg dnd_test/img/page-2-small.jpg js/dnd-library.js js/dnd.js
diffstat 48 files changed, 301 insertions(+), 90 deletions(-) [+]
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');
+}
Binary file dnd_test/img/item-1-L.jpg has changed
Binary file dnd_test/img/item-1-M.jpg has changed
Binary file dnd_test/img/item-1-S.jpg has changed
Binary file dnd_test/img/item-1-thumb.jpg has changed
Binary file dnd_test/img/item-10-L.jpg has changed
Binary file dnd_test/img/item-10-M.jpg has changed
Binary file dnd_test/img/item-10-S.jpg has changed
Binary file dnd_test/img/item-10-thumb.jpg has changed
Binary file dnd_test/img/item-2-L.jpg has changed
Binary file dnd_test/img/item-2-M.jpg has changed
Binary file dnd_test/img/item-2-S.jpg has changed
Binary file dnd_test/img/item-2-thumb.jpg has changed
Binary file dnd_test/img/item-3-L.jpg has changed
Binary file dnd_test/img/item-3-M.jpg has changed
Binary file dnd_test/img/item-3-S.jpg has changed
Binary file dnd_test/img/item-3-thumb.jpg has changed
Binary file dnd_test/img/item-4-L.jpg has changed
Binary file dnd_test/img/item-4-M.jpg has changed
Binary file dnd_test/img/item-4-S.jpg has changed
Binary file dnd_test/img/item-4-thumb.jpg has changed
Binary file dnd_test/img/item-5-L.jpg has changed
Binary file dnd_test/img/item-5-M.jpg has changed
Binary file dnd_test/img/item-5-S.jpg has changed
Binary file dnd_test/img/item-5-thumb.jpg has changed
Binary file dnd_test/img/item-6-L.jpg has changed
Binary file dnd_test/img/item-6-M.jpg has changed
Binary file dnd_test/img/item-6-S.jpg has changed
Binary file dnd_test/img/item-6-thumb.jpg has changed
Binary file dnd_test/img/item-7-L.jpg has changed
Binary file dnd_test/img/item-7-M.jpg has changed
Binary file dnd_test/img/item-7-S.jpg has changed
Binary file dnd_test/img/item-7-thumb.jpg has changed
Binary file dnd_test/img/item-8-L.jpg has changed
Binary file dnd_test/img/item-8-M.jpg has changed
Binary file dnd_test/img/item-8-S.jpg has changed
Binary file dnd_test/img/item-8-thumb.jpg has changed
Binary file dnd_test/img/item-9-L.jpg has changed
Binary file dnd_test/img/item-9-M.jpg has changed
Binary file dnd_test/img/item-9-S.jpg has changed
Binary file dnd_test/img/item-9-thumb.jpg has changed
Binary file dnd_test/img/page-1-small.jpg has changed
Binary file dnd_test/img/page-2-small.jpg has changed
--- 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?