Permalink
Browse files

MDL-36990 - first try of a dragdrop version

  • Loading branch information...
grabs committed Dec 3, 2012
1 parent 8673a98 commit 590378bdbfbd2860bf558522816fb645f8a21706
Showing with 274 additions and 2 deletions.
  1. +53 −0 mod/feedback/ajax.php
  2. +33 −2 mod/feedback/edit.php
  3. +182 −0 mod/feedback/module.js
  4. +6 −0 mod/feedback/styles.css
View
@@ -0,0 +1,53 @@
+<?php
+
+if (!defined('AJAX_SCRIPT')) {
+ define('AJAX_SCRIPT', true);
+}
+
+require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
+
+$id = required_param('id', PARAM_INT);
+$action = optional_param('action', '', PARAM_ALPHA);
+$sesskey = optional_param('sesskey', false, PARAM_TEXT);
+$itemorder = optional_param('itemorder', false, PARAM_SEQUENCE);
+
+$cm = get_coursemodule_from_id('feedback', $id, 0, false, MUST_EXIST);
+$course = $DB->get_record("course", array("id"=>$cm->course), '*', MUST_EXIST);
+$feedback = $DB->get_record("feedback", array("id"=>$cm->instance), '*', MUST_EXIST);
+
+confirm_sesskey();
+
+$context = context_module::instance($cm->id);
+require_login($course, true, $cm);
+require_capability('mod/feedback:edititems', $context);
+
+$return = false;
+
+switch ($action) {
+ case 'saveitemorder':
+ $itemlist = explode(',', trim($itemorder, ','));
+ if (count($itemlist) > 0) {
+ $return = feedback_ajax_saveitemorder($itemlist, $feedback);
+ }
+ break;
+}
+
+echo json_encode($return);
+die;
+
+////////////////////////////////////////
+
+function feedback_ajax_saveitemorder($itemlist, $feedback) {
+ global $DB;
+
+ $result = true;
+ $position = 0;
+ foreach ($itemlist as $itemid) {
+ $position++;
+ $result = $result && $DB->set_field('feedback_item',
+ 'position',
+ $position,
+ array('id'=>$itemid, 'feedback'=>$feedback->id));
+ }
+ return $result;
+}
View
@@ -157,6 +157,28 @@
$PAGE->set_url('/mod/feedback/edit.php', array('id'=>$cm->id, 'do_show'=>$do_show));
$PAGE->set_heading(format_string($course->fullname));
$PAGE->set_title(format_string($feedback->name));
+
+// Adding the javascript module for the items dragdrop
+if ($do_show == 'edit') {
+ $jsmodule = array(
+ 'name' => 'mod_feedback',
+ 'fullpath' => '/mod/feedback/module.js',
+ 'requires' => array('io', 'json-parse', 'dd-constrain', 'dd-proxy', 'dd-drop'),
+ 'strings' => array(array('pluginname', 'feedback'),
+ array('move_item', 'feedback'))
+ );
+
+ $yuibase = $CFG->httpswwwroot.'/lib/yuilib/'.$CFG->yui3version . '/build/';
+ $ajaxscript = $CFG->httpswwwroot.'/mod/feedback/ajax.php';
+ $PAGE->requires->js_init_call('M.mod_feedback.init', array($cm->id,
+ sesskey(),
+ $yuibase,
+ $ajaxscript,
+ $CFG->httpswwwroot),
+ false,
+ $jsmodule);
+}
+
echo $OUTPUT->header();
/// print the tabs
@@ -265,6 +287,8 @@
}
//print the inserted items
$itempos = 0;
+ echo '<div id="feedback_dragarea">'; //The container for the dragging area
+ echo '<ul id="feedback_draglist">'; //the list what includes the draggable items
foreach ($feedbackitems as $feedbackitem) {
$itempos++;
//hiding the item to move
@@ -273,20 +297,24 @@
continue;
}
}
+ //here come the draggable items, each one in a single li-element
+ echo '<li class="feedback_itemlist generalbox" id="feedback_item_'.$feedbackitem->id.'">';
+ echo '<span class="spinnertest"> </span>';
if ($feedbackitem->dependitem > 0) {
$dependstyle = ' feedback_depend';
} else {
$dependstyle = '';
}
- echo $OUTPUT->box_start('feedback_item_box_'.$align.$dependstyle);
+ echo $OUTPUT->box_start('feedback_item_box_'.$align.$dependstyle,
+ 'feedback_item_box_'.$feedbackitem->id);
//items without value only are labels
if ($feedbackitem->hasvalue == 1 AND $feedback->autonumbering) {
$itemnr++;
echo $OUTPUT->box_start('feedback_item_number_'.$align);
echo $itemnr;
echo $OUTPUT->box_end();
}
- echo $OUTPUT->box_start('box generalbox boxalign_'.$align);
+ echo $OUTPUT->box_start('box boxalign_'.$align);
echo $OUTPUT->box_start('feedback_item_commands_'.$align);
echo '<span class="feedback_item_commands">';
echo '('.get_string('position', 'feedback').':'.$itempos .')';
@@ -401,8 +429,11 @@
echo $OUTPUT->box_end();
}
echo '<div class="clearer">&nbsp;</div>';
+ echo '</li>';
}
echo $OUTPUT->box_end();
+ echo '</ul>';
+ echo '</div>';
} else {
echo $OUTPUT->box(get_string('no_items_available_yet', 'feedback'),
'generalbox boxaligncenter');
View
@@ -0,0 +1,182 @@
+M.mod_feedback = {};
+M.mod_feedback.init = function(Y, id, sesskey, yuibase, ajaxscript, moodlebase) {
+ //Listen for all drop:over events
+ Y.DD.DDM.on('drop:over', function(e) {
+ //Get a reference to our drag and drop nodes
+ var drag = e.drag.get('node'),
+ drop = e.drop.get('node');
+
+ //Are we dropping on a li node?
+ if (drop.get('tagName').toLowerCase() === 'li') {
+ //Are we not going up?
+ if (!goingUp) {
+ drop = drop.get('nextSibling');
+ }
+ //Add the node to this list
+ e.drop.get('node').get('parentNode').insertBefore(drag, drop);
+ //Resize this nodes shim, so we can drop on it later.
+ e.drop.sizeShim();
+ }
+ });
+ //Listen for all drag:drag events
+ Y.DD.DDM.on('drag:drag', function(e) {
+ //Get the last y point
+ var y = e.target.lastXY[1];
+ //is it greater than the lastY var?
+ if (y < lastY) {
+ //We are going up
+ goingUp = true;
+ } else {
+ //We are going down.
+ goingUp = false;
+ }
+ //Cache for next check
+ lastY = y;
+ });
+ //Listen for all drag:start events
+ Y.DD.DDM.on('drag:start', function(e) {
+ //Get our drag object
+ var drag = e.target;
+ //Set some styles here
+ drag.get('node').setStyle('opacity', '.25');
+ drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
+ drag.get('dragNode').setStyles({
+ opacity: '.5',
+ borderColor: drag.get('node').getStyle('borderColor'),
+ backgroundColor: drag.get('node').getStyle('backgroundColor')
+ });
+ });
+ //Listen for a drag:end events
+ Y.DD.DDM.on('drag:end', function(e) {
+ var drag = e.target;
+ //Put our styles back
+ drag.get('node').setStyles({
+ visibility: '',
+ opacity: '1'
+ });
+
+ });
+ //Listen for all drag:drophit events
+ Y.DD.DDM.on('drag:drophit', function(e) {
+ var drop = e.drop.get('node'),
+ drag = e.drag.get('node');
+ dragnode = Y.one(drag);
+ //if we are not on an li, we must have been dropped on a ul
+ if (drop.get('tagName').toLowerCase() !== 'li') {
+ if (!drop.contains(drag)) {
+ drop.appendChild(drag);
+ }
+ myElements = '';
+ drop.get('children').each(function(v, k) {
+ myElements = myElements + ',' + get_node_id(v.get('id'));
+ });
+ var spinner = M.util.add_spinner(Y, dragnode);
+ saveposition(Y, this, id, myElements, sesskey, spinner);
+ }
+ });
+
+ //Static Vars
+ var goingUp = false, lastY = 0;
+
+ //Get the list of li's in the lists and make them draggable
+ var listitems = Y.Node.all('#feedback_dragarea ul li.feedback_itemlist');
+ listitems.each(function(v, k) { //make each item draggable
+ var dd = new Y.DD.Drag({
+ node: v,
+ target: {
+ padding: '0 0 0 20'
+ }
+ }).plug(Y.Plugin.DDProxy, {
+ moveOnEnd: false
+ }).plug(Y.Plugin.DDConstrained, {
+ constrain2node: '#feedback_dragarea' //prevent dragging outside the dragarea
+ });
+
+ item_id = get_node_id(v.get('id')); //get the id of the feedback item
+ item_box = Y.Node.one('#feedback_item_box_' + item_id); //get the current item box so we can add the drag handle
+ handletitle = M.util.get_string('move_item', 'feedback');
+ mydraghandle = get_drag_handle(handletitle, 'itemhandle');
+ v.insert(mydraghandle, item_box); //insert the new handle into the item box
+ dd.addHandle(mydraghandle); //now we add the handle to the drag object, so the box only can be moved with this handle
+ });
+ // remove all legacy move icons
+ Y.Node.all('span.feedback_item_command_moveup').each(function(v, k) {
+ v.remove();
+ });;
+ Y.Node.all('span.feedback_item_command_movedown').each(function(v, k) {
+ v.remove();
+ });;
+ Y.Node.all('span.feedback_item_command_move').each(function(v, k) {
+ v.remove();
+ });;
+
+ //Create targets for drop.
+ var droparea = Y.Node.one('#feedback_dragarea ul#feedback_draglist');
+ var tar = new Y.DD.Drop({
+ node: droparea
+ });
+
+ // here we save the new itemorder
+ function saveposition(Y, objekt, id, itemorder, sesskey, spinner){
+
+ Y.io(ajaxscript, {
+ //the needed paramaters
+ data: {action: 'saveitemorder',
+ id: id,
+ itemorder: itemorder,
+ sesskey: sesskey
+ },
+
+ timeout: 5000, //5 seconds for timeout I think it is enough
+
+ //define the events
+ on: {
+ start : function(transactionid) {
+ spinner.show();
+ },
+ success: function(transactionid, xhr) {
+ var response = xhr.response;
+ var ergebnis = Y.JSON.parse(response);
+ window.setTimeout(function(e) {
+ spinner.hide();
+ }, 250);
+ },
+ failure: function() {
+ window.setTimeout(function(e) {
+ spinner.hide();
+ }, 250);
+ }
+ }
+ });
+ };
+
+ //this returns the numeric id from the dom id
+ function get_node_id(id) {
+ return Number(id.replace(/feedback_item_/i, ''));
+ };
+
+ //this creates a new drag handle and return it as a new node
+ function get_drag_handle(title, handleclass) {
+ var MOVEICON = {
+ pix: "i/move_2d",
+ largepix: "i/dragdrop",
+ component: 'moodle'
+ };
+
+
+ var iconname = MOVEICON.pix;
+ var dragicon = Y.Node.create('<img />')
+ .setStyle('cursor', 'move')
+ .setAttrs({
+ 'src' : M.util.image_url(iconname, MOVEICON.component),
+ 'alt' : title,
+ 'class' : handleclass
+ });
+
+ var dragelement = Y.Node.create('<span></span>')
+ .setAttribute('title', title)
+ dragelement.appendChild(dragicon);
+ return dragelement;
+ };
+
+};
View
@@ -82,3 +82,9 @@ hr.feedback_pagebreak {
background-color:#aaaaaa;
border:0px;
}
+
+ul#feedback_draglist {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}

0 comments on commit 590378b

Please sign in to comment.