From 590378bdbfbd2860bf558522816fb645f8a21706 Mon Sep 17 00:00:00 2001 From: Andreas Grabs Date: Tue, 4 Dec 2012 00:26:42 +0100 Subject: [PATCH 01/18] MDL-36990 - first try of a dragdrop version --- mod/feedback/ajax.php | 53 ++++++++++++ mod/feedback/edit.php | 35 +++++++- mod/feedback/module.js | 182 ++++++++++++++++++++++++++++++++++++++++ mod/feedback/styles.css | 6 ++ 4 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 mod/feedback/ajax.php create mode 100644 mod/feedback/module.js diff --git a/mod/feedback/ajax.php b/mod/feedback/ajax.php new file mode 100644 index 00000000000..75d608736a5 --- /dev/null +++ b/mod/feedback/ajax.php @@ -0,0 +1,53 @@ +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; +} diff --git a/mod/feedback/edit.php b/mod/feedback/edit.php index b928c11e084..30006fe833a 100644 --- a/mod/feedback/edit.php +++ b/mod/feedback/edit.php @@ -157,6 +157,28 @@ $strfeedback = get_string("modulename", "feedback"); $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 @@ if ($do_show == 'edit') { } //print the inserted items $itempos = 0; + echo '
'; //The container for the dragging area + echo ''; + echo '
'; } else { echo $OUTPUT->box(get_string('no_items_available_yet', 'feedback'), 'generalbox boxaligncenter'); diff --git a/mod/feedback/module.js b/mod/feedback/module.js new file mode 100644 index 00000000000..eb31546318a --- /dev/null +++ b/mod/feedback/module.js @@ -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('') + .setStyle('cursor', 'move') + .setAttrs({ + 'src' : M.util.image_url(iconname, MOVEICON.component), + 'alt' : title, + 'class' : handleclass + }); + + var dragelement = Y.Node.create('') + .setAttribute('title', title) + dragelement.appendChild(dragicon); + return dragelement; + }; + +}; diff --git a/mod/feedback/styles.css b/mod/feedback/styles.css index c59a73c49e2..f926458a1e3 100644 --- a/mod/feedback/styles.css +++ b/mod/feedback/styles.css @@ -82,3 +82,9 @@ hr.feedback_pagebreak { background-color:#aaaaaa; border:0px; } + +ul#feedback_draglist { + list-style: none; + padding: 0; + margin: 0; +} From f94e501b2311da5662969645a6c3e73ed441dc44 Mon Sep 17 00:00:00 2001 From: Andreas Grabs Date: Tue, 4 Dec 2012 00:27:40 +0100 Subject: [PATCH 02/18] MDL-36990 - item-position text change on dragdrop --- mod/feedback/edit.php | 5 +++-- mod/feedback/module.js | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mod/feedback/edit.php b/mod/feedback/edit.php index 30006fe833a..0e2ade6086c 100644 --- a/mod/feedback/edit.php +++ b/mod/feedback/edit.php @@ -165,7 +165,8 @@ if ($do_show == 'edit') { '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')) + array('move_item', 'feedback'), + array('position', 'feedback')) ); $yuibase = $CFG->httpswwwroot.'/lib/yuilib/'.$CFG->yui3version . '/build/'; @@ -316,7 +317,7 @@ if ($do_show == 'edit') { } echo $OUTPUT->box_start('box boxalign_'.$align); echo $OUTPUT->box_start('feedback_item_commands_'.$align); - echo '