MDL-79863 qtype_ordering: populate GIT repository

This commit is contained in:
Gordon Bateson 2013-02-08 09:00:40 +09:00 committed by Mathew May
parent b8d5e936e6
commit 70fd1e4bc8
20 changed files with 4065 additions and 0 deletions

View File

@ -0,0 +1,231 @@
<?php
if (!isset($SAJAX_INCLUDED)) {
/*
* GLOBALS AND DEFAULTS
*
*/
$sajax_debug_mode = 0;
$sajax_export_list = array();
$sajax_request_type = "GET";
$sajax_remote_uri = "";
/*
* CODE
*
*/
function sajax_init() {
}
function sajax_get_my_uri() {
global $REQUEST_URI;
return $REQUEST_URI;
}
$sajax_remote_uri = sajax_get_my_uri();
function sajax_handle_client_request() {
global $sajax_export_list;
$mode = "";
if (! empty($_GET["rs"]))
$mode = "get";
if (!empty($_POST["rs"]))
$mode = "post";
if (empty($mode))
return;
if ($mode == "get") {
// Bust cache in the head
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// always modified
header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header ("Pragma: no-cache"); // HTTP/1.0
$func_name = $_GET["rs"];
if (! empty($_GET["rsargs"]))
$args = $_GET["rsargs"];
else
$args = array();
}
else {
$func_name = $_POST["rs"];
if (! empty($_POST["rsargs"]))
$args = $_POST["rsargs"];
else
$args = array();
}
if (! in_array($func_name, $sajax_export_list))
echo "-:$func_name not callable";
else {
echo "+:";
$result = call_user_func_array($func_name, $args);
echo $result;
}
exit;
}
function sajax_get_common_js() {
global $sajax_debug_mode;
global $sajax_request_type;
global $sajax_remote_uri;
$t = strtoupper($sajax_request_type);
if ($t != "GET" && $t != "POST")
return "// Invalid type: $t.. \n\n";
ob_start();
?>
// remote scripting library
// (c) copyright 2005 modernmethod, inc
var sajax_debug_mode = <?php echo $sajax_debug_mode ? "true" : "false"; ?>;
var sajax_request_type = "<?php echo $t; ?>";
function sajax_debug(text) {
if (sajax_debug_mode)
alert("RSD: " + text)
}
function sajax_init_object() {
sajax_debug("sajax_init_object() called..")
var A;
try {
A=new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
A=new ActiveXObject("Microsoft.XMLHTTP");
} catch (oc) {
A=null;
}
}
if(!A && typeof XMLHttpRequest != "undefined")
A = new XMLHttpRequest();
if (!A)
sajax_debug("Could not create connection object.");
return A;
}
function sajax_do_call(func_name, args) {
var i, x, n;
var uri;
var post_data;
uri = "<?php echo $sajax_remote_uri; ?>";
if (sajax_request_type == "GET") {
if (uri.indexOf("?") == -1)
uri = uri + "?rs=" + escape(func_name);
else
uri = uri + "&rs=" + escape(func_name);
for (i = 0; i < args.length-1; i++)
uri = uri + "&rsargs[]=" + escape(args[i]);
uri = uri + "&rsrnd=" + new Date().getTime();
post_data = null;
} else {
post_data = "rs=" + escape(func_name);
for (i = 0; i < args.length-1; i++)
post_data = post_data + "&rsargs[]=" + escape(args[i]);
}
x = sajax_init_object();
x.open(sajax_request_type, uri, true);
if (sajax_request_type == "POST") {
x.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
x.onreadystatechange = function() {
if (x.readyState != 4)
return;
sajax_debug("received " + x.responseText);
var status;
var data;
status = x.responseText.charAt(0);
data = x.responseText.substring(2);
if (status == "-")
alert("Error: " + data);
else
args[args.length-1](data);
}
x.send(post_data);
sajax_debug(func_name + " uri = " + uri + "/post = " + post_data);
sajax_debug(func_name + " waiting..");
delete x;
}
<?php
$html = ob_get_contents();
ob_end_clean();
return $html;
}
function sajax_show_common_js() {
echo sajax_get_common_js();
}
// javascript escape a value
function sajax_esc($val)
{
return str_replace('"', '\\\\"', $val);
}
function sajax_get_one_stub($func_name) {
ob_start();
?>
// wrapper for <?php echo $func_name; ?>
function x_<?php echo $func_name; ?>() {
sajax_do_call("<?php echo $func_name; ?>",
x_<?php echo $func_name; ?>.arguments);
}
<?php
$html = ob_get_contents();
ob_end_clean();
return $html;
}
function sajax_show_one_stub($func_name) {
echo sajax_get_one_stub($func_name);
}
function sajax_export() {
global $sajax_export_list;
$n = func_num_args();
for ($i = 0; $i < $n; $i++) {
$sajax_export_list[] = func_get_arg($i);
}
}
$sajax_js_has_been_shown = 0;
function sajax_get_javascript()
{
global $sajax_js_has_been_shown;
global $sajax_export_list;
$html = "";
if (! $sajax_js_has_been_shown) {
$html .= sajax_get_common_js();
$sajax_js_has_been_shown = 1;
}
foreach ($sajax_export_list as $func) {
$html .= sajax_get_one_stub($func);
}
return $html;
}
function sajax_show_javascript()
{
echo sajax_get_javascript();
}
$SAJAX_INCLUDED = 1;
}
?>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="question/type/ordering/db" VERSION="2007021402" COMMENT="XMLDB file for Moodle question/type/ordering">
<TABLES>
<TABLE NAME="question_ordering" COMMENT="Options for ordering questions">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="question"/>
<FIELD NAME="question" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="logical"/>
<FIELD NAME="logical" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="question" NEXT="studentsee"/>
<FIELD NAME="studentsee" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="logical" NEXT="correctfeedback"/>
<FIELD NAME="correctfeedback" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="studentsee" NEXT="partiallycorrectfeedback"/>
<FIELD NAME="partiallycorrectfeedback" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="correctfeedback" NEXT="incorrectfeedback"/>
<FIELD NAME="incorrectfeedback" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="partiallycorrectfeedback"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for question_ordering" NEXT="question"/>
<KEY NAME="question" TYPE="foreign" FIELDS="question" REFTABLE="questions" REFFIELDS="id" PREVIOUS="primary"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>

View File

@ -0,0 +1,31 @@
<?php
// This file keeps track of upgrades to
// the calculated qtype plugin
//
// Sometimes, changes between versions involve
// alterations to database structures and other
// major things that may break installations.
//
// The upgrade function in this file will attempt
// to perform all the necessary actions to upgrade
// your older installation to the current version.
//
// If there's something it cannot do itself, it
// will tell you what you need to do.
//
// The commands in here will all be database-neutral,
// using the methods of database_manager class
//
// Please do not forget to use upgrade_set_timeout()
// before any action that may take longer time to finish.
function xmldb_qtype_calculated_upgrade($oldversion) {
global $CFG, $DB;
$dbman = $DB->get_manager();
return true;
}

View File

@ -0,0 +1,112 @@
/**********************************************************
Very minorly modified from the example by Tim Taylor
http://tool-man.org/examples/sorting.html
Added Coordinate.prototype.inside( northwest, southeast );
**********************************************************/
var Coordinates = {
ORIGIN : new Coordinate(0, 0),
northwestPosition : function(element) {
var x = parseInt(element.style.left);
var y = parseInt(element.style.top);
return new Coordinate(isNaN(x) ? 0 : x, isNaN(y) ? 0 : y);
},
southeastPosition : function(element) {
return Coordinates.northwestPosition(element).plus(
new Coordinate(element.offsetWidth, element.offsetHeight));
},
northwestOffset : function(element, isRecursive) {
var offset = new Coordinate(element.offsetLeft, element.offsetTop);
if (!isRecursive) return offset;
var parent = element.offsetParent;
while (parent) {
offset = offset.plus(
new Coordinate(parent.offsetLeft, parent.offsetTop));
parent = parent.offsetParent;
}
return offset;
},
southeastOffset : function(element, isRecursive) {
return Coordinates.northwestOffset(element, isRecursive).plus(
new Coordinate(element.offsetWidth, element.offsetHeight));
},
fixEvent : function(event) {
event.windowCoordinate = new Coordinate(event.clientX, event.clientY);
}
};
function Coordinate(x, y) {
this.x = x;
this.y = y;
}
Coordinate.prototype.toString = function() {
return "(" + this.x + "," + this.y + ")";
}
Coordinate.prototype.plus = function(that) {
return new Coordinate(this.x + that.x, this.y + that.y);
}
Coordinate.prototype.minus = function(that) {
return new Coordinate(this.x - that.x, this.y - that.y);
}
Coordinate.prototype.distance = function(that) {
var deltaX = this.x - that.x;
var deltaY = this.y - that.y;
return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
}
Coordinate.prototype.max = function(that) {
var x = Math.max(this.x, that.x);
var y = Math.max(this.y, that.y);
return new Coordinate(x, y);
}
Coordinate.prototype.constrain = function(min, max) {
if (min.x > max.x || min.y > max.y) return this;
var x = this.x;
var y = this.y;
if (min.x != null) x = Math.max(x, min.x);
if (max.x != null) x = Math.min(x, max.x);
if (min.y != null) y = Math.max(y, min.y);
if (max.y != null) y = Math.min(y, max.y);
return new Coordinate(x, y);
}
Coordinate.prototype.reposition = function(element) {
element.style["top"] = this.y + "px";
element.style["left"] = this.x + "px";
}
Coordinate.prototype.equals = function(that) {
if (this == that) return true;
if (!that || that == null) return false;
return this.x == that.x && this.y == that.y;
}
// returns true of this point is inside specified box
Coordinate.prototype.inside = function(northwest, southeast) {
if ((this.x >= northwest.x) && (this.x <= southeast.x) &&
(this.y >= northwest.y) && (this.y <= southeast.y)) {
return true;
}
return false;
}

View File

@ -0,0 +1,242 @@
/*
* drag.js - click & drag DOM elements
*
* originally based on Youngpup's dom-drag.js, www.youngpup.net
*/
/**********************************************************
Further modified from the example by Tim Taylor
http://tool-man.org/examples/sorting.html
Changed onMouseMove where it calls group.onDrag and then
adjusts the offset for changes to the DOM. If the item
being moved changed parents it would be off so changed to
get the absolute offset (recursive northwestOffset).
**********************************************************/
var Drag = {
BIG_Z_INDEX : 10000,
group : null,
isDragging : false,
makeDraggable : function(group) {
group.handle = group;
group.handle.group = group;
group.minX = null;
group.minY = null;
group.maxX = null;
group.maxY = null;
group.threshold = 0;
group.thresholdY = 0;
group.thresholdX = 0;
group.onDragStart = new Function();
group.onDragEnd = new Function();
group.onDrag = new Function();
// TODO: use element.prototype.myFunc
group.setDragHandle = Drag.setDragHandle;
group.setDragThreshold = Drag.setDragThreshold;
group.setDragThresholdX = Drag.setDragThresholdX;
group.setDragThresholdY = Drag.setDragThresholdY;
group.constrain = Drag.constrain;
group.constrainVertical = Drag.constrainVertical;
group.constrainHorizontal = Drag.constrainHorizontal;
group.onmousedown = Drag.onMouseDown;
},
constrainVertical : function() {
var nwOffset = Coordinates.northwestOffset(this, true);
this.minX = nwOffset.x;
this.maxX = nwOffset.x;
},
constrainHorizontal : function() {
var nwOffset = Coordinates.northwestOffset(this, true);
this.minY = nwOffset.y;
this.maxY = nwOffset.y;
},
constrain : function(nwPosition, sePosition) {
this.minX = nwPosition.x;
this.minY = nwPosition.y;
this.maxX = sePosition.x;
this.maxY = sePosition.y;
},
setDragHandle : function(handle) {
if (handle && handle != null)
this.handle = handle;
else
this.handle = this;
this.handle.group = this;
this.onmousedown = null;
this.handle.onmousedown = Drag.onMouseDown;
},
setDragThreshold : function(threshold) {
if (isNaN(parseInt(threshold))) return;
this.threshold = threshold;
},
setDragThresholdX : function(threshold) {
if (isNaN(parseInt(threshold))) return;
this.thresholdX = threshold;
},
setDragThresholdY : function(threshold) {
if (isNaN(parseInt(threshold))) return;
this.thresholdY = threshold;
},
onMouseDown : function(event) {
event = Drag.fixEvent(event);
Drag.group = this.group;
var group = this.group;
var mouse = event.windowCoordinate;
var nwOffset = Coordinates.northwestOffset(group, true);
var nwPosition = Coordinates.northwestPosition(group);
var sePosition = Coordinates.southeastPosition(group);
var seOffset = Coordinates.southeastOffset(group, true);
group.originalOpacity = group.style.opacity;
group.originalZIndex = group.style.zIndex;
group.initialWindowCoordinate = mouse;
// TODO: need a better name, but don't yet understand how it
// participates in the magic while dragging
group.dragCoordinate = mouse;
Drag.showStatus(mouse, nwPosition, sePosition, nwOffset, seOffset);
group.onDragStart(nwPosition, sePosition, nwOffset, seOffset);
// TODO: need better constraint API
if (group.minX != null)
group.minMouseX = mouse.x - nwPosition.x +
group.minX - nwOffset.x;
if (group.maxX != null)
group.maxMouseX = group.minMouseX + group.maxX - group.minX;
if (group.minY != null)
group.minMouseY = mouse.y - nwPosition.y +
group.minY - nwOffset.y;
if (group.maxY != null)
group.maxMouseY = group.minMouseY + group.maxY - group.minY;
group.mouseMin = new Coordinate(group.minMouseX, group.minMouseY);
group.mouseMax = new Coordinate(group.maxMouseX, group.maxMouseY);
document.onmousemove = Drag.onMouseMove;
document.onmouseup = Drag.onMouseUp;
return false;
},
showStatus : function(mouse, nwPosition, sePosition, nwOffset, seOffset) {
/*window.status =
"mouse: " + mouse.toString() + " " +
"NW pos: " + nwPosition.toString() + " " +
"SE pos: " + sePosition.toString() + " " +
"NW offset: " + nwOffset.toString() + " " +
"SE offset: " + seOffset.toString();*/
},
onMouseMove : function(event) {
event = Drag.fixEvent(event);
var group = Drag.group;
var mouse = event.windowCoordinate;
var nwOffset = Coordinates.northwestOffset(group, true);
var nwPosition = Coordinates.northwestPosition(group);
var sePosition = Coordinates.southeastPosition(group);
var seOffset = Coordinates.southeastOffset(group, true);
Drag.showStatus(mouse, nwPosition, sePosition, nwOffset, seOffset);
if (!Drag.isDragging) {
if (group.threshold > 0) {
var distance = group.initialWindowCoordinate.distance(
mouse);
if (distance < group.threshold) return true;
} else if (group.thresholdY > 0) {
var deltaY = Math.abs(group.initialWindowCoordinate.y - mouse.y);
if (deltaY < group.thresholdY) return true;
} else if (group.thresholdX > 0) {
var deltaX = Math.abs(group.initialWindowCoordinate.x - mouse.x);
if (deltaX < group.thresholdX) return true;
}
Drag.isDragging = true;
group.style["zIndex"] = Drag.BIG_Z_INDEX;
group.style["opacity"] = 0.75;
}
// TODO: need better constraint API
var adjusted = mouse.constrain(group.mouseMin, group.mouseMax);
nwPosition = nwPosition.plus(adjusted.minus(group.dragCoordinate));
nwPosition.reposition(group);
group.dragCoordinate = adjusted;
// once dragging has started, the position of the group
// relative to the mouse should stay fixed. They can get out
// of sync if the DOM is manipulated while dragging, so we
// correct the error here
//
// TODO: what we really want to do is find the offset from
// our corner to the mouse coordinate and adjust to keep it
// the same
// changed to be recursive/use absolute offset for corrections
var offsetBefore = Coordinates.northwestOffset(group, true);
group.onDrag(nwPosition, sePosition, nwOffset, seOffset);
var offsetAfter = Coordinates.northwestOffset(group, true);
if (!offsetBefore.equals(offsetAfter)) {
var errorDelta = offsetBefore.minus(offsetAfter);
nwPosition = Coordinates.northwestPosition(group).plus(errorDelta);
nwPosition.reposition(group);
}
return false;
},
onMouseUp : function(event) {
event = Drag.fixEvent(event);
var group = Drag.group;
var mouse = event.windowCoordinate;
var nwOffset = Coordinates.northwestOffset(group, true);
var nwPosition = Coordinates.northwestPosition(group);
var sePosition = Coordinates.southeastPosition(group);
var seOffset = Coordinates.southeastOffset(group, true);
document.onmousemove = null;
document.onmouseup = null;
group.onDragEnd(nwPosition, sePosition, nwOffset, seOffset);
if (Drag.isDragging) {
// restoring zIndex before opacity avoids visual flicker in Firefox
group.style["zIndex"] = group.originalZIndex;
group.style["opacity"] = group.originalOpacity;
}
Drag.group = null;
Drag.isDragging = false;
return false;
},
fixEvent : function(event) {
if (typeof event == 'undefined') event = window.event;
Coordinates.fixEvent(event);
return event;
}
};

View File

@ -0,0 +1,260 @@
/**********************************************************
Adapted from the sortable lists example by Tim Taylor
http://tool-man.org/examples/sorting.html
Modified by Tom Westcott : http://www.cyberdummy.co.uk
**********************************************************/
var DragDrop = {
firstContainer : null,
lastContainer : null,
parent_id : null,
parent_group : null,
makeListContainer : function(list, group) {
// each container becomes a linked list node
if (this.firstContainer == null) {
this.firstContainer = this.lastContainer = list;
list.previousContainer = null;
list.nextContainer = null;
} else {
list.previousContainer = this.lastContainer;
list.nextContainer = null;
this.lastContainer.nextContainer = list;
this.lastContainer = list;
}
// these functions are called when an item is draged over
// a container or out of a container bounds. onDragOut
// is also called when the drag ends with an item having
// been added to the container
list.onDragOver = new Function();
list.onDragOut = new Function();
list.onDragDrop = new Function();
list.group = group;
var items = list.getElementsByTagName( "li" );
for (var i = 0; i < items.length; i++) {
DragDrop.makeItemDragable(items[i]);
}
},
serData : function ( group, theid ) {
var container = DragDrop.firstContainer;
var j = 0;
var string = "";
while (container != null) {
if(theid != null && container.id != theid)
{
container = container.nextContainer;
continue;
}
if(group != null && container.group != group)
{
container = container.nextContainer;
continue;
}
j ++;
if(j > 1)
{
string += ":";
}
string += container.id;
var items = container.getElementsByTagName( "li" );
string += "(";
for (var i = 0; i < items.length; i++) {
if(i > 0)
{
string += ",";
}
string += items[i].id;
}
string += ")";
container = container.nextContainer;
}
return string;
},
makeItemDragable : function(item) {
Drag.makeDraggable(item);
item.setDragThreshold(5);
// tracks if the item is currently outside all containers
item.isOutside = false;
item.onDragStart = DragDrop.onDragStart;
item.onDrag = DragDrop.onDrag;
item.onDragEnd = DragDrop.onDragEnd;
},
onDragStart : function(nwPosition, sePosition, nwOffset, seOffset) {
// update all container bounds, since they may have changed
// on a previous drag
//
// could be more smart about when to do this
var container = DragDrop.firstContainer;
while (container != null) {
container.northwest = Coordinates.northwestOffset( container, true );
container.southeast = Coordinates.southeastOffset( container, true );
container = container.nextContainer;
}
// item starts out over current parent
this.parentNode.onDragOver();
parent_id = this.parentNode.id;
parent_group = this.parentNode.group;
},
onDrag : function(nwPosition, sePosition, nwOffset, seOffset) {
// check if we were nowhere
if (this.isOutside) {
// check each container to see if in its bounds
var container = DragDrop.firstContainer;
while (container != null) {
if ((nwOffset.inside( container.northwest, container.southeast ) ||
seOffset.inside( container.northwest, container.southeast )) && container.group == parent_group) {
// we're inside this one
container.onDragOver();
this.isOutside = false;
// since isOutside was true, the current parent is a
// temporary clone of some previous container node and
// it needs to be removed from the document
var tempParent = this.parentNode;
tempParent.removeChild( this );
container.appendChild( this );
tempParent.parentNode.removeChild( tempParent );
break;
}
container = container.nextContainer;
}
// we're still not inside the bounds of any container
if (this.isOutside)
return;
// check if we're outside our parent's bounds
} else if (!(nwOffset.inside( this.parentNode.northwest, this.parentNode.southeast ) ||
seOffset.inside( this.parentNode.northwest, this.parentNode.southeast ))) {
this.parentNode.onDragOut();
this.isOutside = true;
// check if we're inside a new container's bounds
var container = DragDrop.firstContainer;
while (container != null) {
if ((nwOffset.inside( container.northwest, container.southeast ) ||
seOffset.inside( container.northwest, container.southeast )) && container.group == parent_group) {
// we're inside this one
container.onDragOver();
this.isOutside = false;
this.parentNode.removeChild( this );
container.appendChild( this );
break;
}
container = container.nextContainer;
}
// if we're not in any container now, make a temporary clone of
// the previous container node and add it to the document
if (this.isOutside) {
var tempParent = this.parentNode.cloneNode( false );
this.parentNode.removeChild( this );
tempParent.appendChild( this );
// body puts a border or item at bottom of page if do not have this
tempParent.style.border = 0;
document.getElementsByTagName( "body" ).item(0).appendChild( tempParent );
return;
}
}
// if we get here, we're inside some container bounds, so we do
// everything the original dragsort script did to swap us into the
// correct position
var parent = this.parentNode;
var item = this;
var next = DragUtils.nextItem(item);
while (next != null && this.offsetTop >= next.offsetTop - 2) {
var item = next;
var next = DragUtils.nextItem(item);
}
if (this != item) {
DragUtils.swap(this, next);
return;
}
var item = this;
var previous = DragUtils.previousItem(item);
while (previous != null && this.offsetTop <= previous.offsetTop + 2) {
var item = previous;
var previous = DragUtils.previousItem(item);
}
if (this != item) {
DragUtils.swap(this, item);
return;
}
},
onDragEnd : function(nwPosition, sePosition, nwOffset, seOffset) {
// if the drag ends and we're still outside all containers
// it's time to remove ourselves from the document or add
// to the trash bin
if (this.isOutside) {
var container = DragDrop.firstContainer;
while (container != null) {
if(container.id == parent_id)
{
break;
}
container = container.nextContainer;
}
this.isOutside = false;
this.parentNode.removeChild( this );
container.appendChild( this );
this.style["top"] = "0px";
this.style["left"] = "0px";
//var container = DragDrop.firstContainer;
//container.appendChild( this );
return;
}
this.parentNode.onDragOut();
this.parentNode.onDragDrop();
this.style["top"] = "0px";
this.style["left"] = "0px";
}
};
var DragUtils = {
swap : function(item1, item2) {
var parent = item1.parentNode;
parent.removeChild(item1);
parent.insertBefore(item1, item2);
item1.style["top"] = "0px";
item1.style["left"] = "0px";
},
nextItem : function(item) {
var sibling = item.nextSibling;
while (sibling != null) {
if (sibling.nodeName == item.nodeName) return sibling;
sibling = sibling.nextSibling;
}
return null;
},
previousItem : function(item) {
var sibling = item.previousSibling;
while (sibling != null) {
if (sibling.nodeName == item.nodeName) return sibling;
sibling = sibling.previousSibling;
}
return null;
}
};

View File

@ -0,0 +1,24 @@
ul.sortable li {
position: relative;
}
ul.boxy {
list-style-type: none;
padding: 4px 4px 0 4px;
margin: 0px;
font-size: 13px;
font-family: Arial, sans-serif;
border: 1px solid #ccc;
width: 360px;
float: left;
margin-left: 5px;
}
ul.boxy li {
cursor: move;
margin-bottom: 1px;
padding: 8px 2px;
border: 1px solid #CCC;
background-color: #EEE;
min-height: 20px;
border-image: initial;
}

View File

@ -0,0 +1,181 @@
<?php
if (empty($CFG->orderingquestiontypeflag)) {
$CFG->orderingquestiontypeflag = 1;
?>
<link rel="stylesheet" href="<?php echo $CFG->wwwroot . "/question/type/ordering/"; ?>dd_files/lists.css" type="text/css">
<script language="JavaScript" type="text/javascript" src="<?php echo $CFG->wwwroot . "/question/type/ordering/"; ?>dd_files/coordinates.js"></script>
<script language="JavaScript" type="text/javascript" src="<?php echo $CFG->wwwroot . "/question/type/ordering/"; ?>dd_files/drag.js"></script>
<script language="JavaScript" type="text/javascript" src="<?php echo $CFG->wwwroot . "/question/type/ordering/"; ?>dd_files/dragdrop.js"></script>
<?php
}
?>
<script language="JavaScript" type="text/javascript"><!--
function confirm(z)
{
window.status = 'Sajax version updated';
}
function onDrop_<?php echo $question->id; ?>() {
var data_<?php echo $question->id; ?> = DragDrop.serData('g_<?php echo $question->id; ?>');
x_sajax_update(data_<?php echo $question->id; ?>, confirm);
}
function onneedrun_<?php echo $question->id; ?>() {
var list_<?php echo $question->id; ?> = document.getElementById("ordering");
DragDrop.makeListContainer( list_<?php echo $question->id; ?>, 'g_<?php echo $question->id; ?>' );
list_<?php echo $question->id; ?>.onDragOver = function() { this.style["background"] = "#EEF"; };
list_<?php echo $question->id; ?>.onDragOut = function() {this.style["background"] = "none"; };
}
function getSort_<?php echo $question->id; ?>()
{
<?php echo $question->name_prefix; ?> = document.getElementById("<?php echo $question->name_prefix; ?>");
<?php echo $question->name_prefix; ?>.value = DragDrop.serData('g_<?php echo $question->id; ?>', null);
}
function showValue_<?php echo $question->id; ?>()
{
<?php echo $question->name_prefix ?> = document.getElementById("<?php echo $question->name_prefix; ?>");
alert(<?php echo $question->name_prefix; ?>.value);
}
//-->
</script>
<script type="text/javascript">
function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart":
type = "mousedown";
break;
case "touchmove":
type="mousemove";
event.preventDefault();
break;
case "touchend":
type="mouseup";
break;
default:
return;
}
var simulatedEvent = document.createEvent("MouseEvent");
//initMouseEvent(type, canBubble, cancelable, view, clickCount, screenX, screenY, clientX, clientY,
// ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init() {
for(i=0;i<document.getElementById("ordering").childNodes.length;i++) {
document.getElementById('ordering').childNodes.item(i).addEventListener("touchstart", touchHandler, false);
document.getElementById('ordering').childNodes.item(i).addEventListener("touchmove", touchHandler, false);
document.getElementById('ordering').childNodes.item(i).addEventListener("touchend", touchHandler, false);
document.getElementById('ordering').childNodes.item(i).addEventListener("touchcancel", touchHandler, false);
}
var myInterval = window.setInterval(function (a,b) {
function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart":
type = "mousedown";
break;
case "touchmove":
type="mousemove";
event.preventDefault();
break;
case "touchend":
type="mouseup";
break;
default:
return;
}
var simulatedEvent = document.createEvent("MouseEvent");
//initMouseEvent(type, canBubble, cancelable, view, clickCount, screenX, screenY, clientX, clientY,
// ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
for(i=0;i<document.getElementById("ordering").childNodes.length;i++) {
document.getElementById('ordering').childNodes.item(i).addEventListener("touchstart", touchHandler, false);
document.getElementById('ordering').childNodes.item(i).addEventListener("touchmove", touchHandler, false);
document.getElementById('ordering').childNodes.item(i).addEventListener("touchend", touchHandler, false);
document.getElementById('ordering').childNodes.item(i).addEventListener("touchcancel", touchHandler, false);
}
},500);
}
</script>
<div class="qtext">
<?php echo $questiontext; ?>
</div>
<?php /*if ($image) { ?>
<img class="qimage" src="<?php echo $image; ?>" alt="" />
<?php }*/ ?><img class="qimage" src="type/ordering/icon.gif" alt="" />
<div class="ablock clearfix">
<div class="prompt">
<?php echo $answerprompt; ?>
</div>
<div class="answer">
<ul id="ordering" class="sortable boxy">
<?php $row = 1; foreach ($anss as $answer) { ?>
<li id="<?php echo $answer->id ?>" onMouseUp="getSort_<?php echo $question->id; ?>()"><?php echo $answer->text ?></li>
<?php } ?>
</ul>
</div>
<?php if ($feedback) { ?>
<div class="feedback">
<?php echo $feedback ?>
</div>
<?php } ?>
<input type="hidden" name="<?php echo $question->name_prefix; ?>" id="<?php echo $question->name_prefix; ?>" value="" />
<?php $this->print_question_submit_buttons($question, $state, $cmoptions, $options); ?>
</div>
<iframe frameborder="0" hspace="0" vspace="0" height="1" width="1" onload="onneedrun_<?php echo $question->id; ?>();getSort_<?php echo $question->id; ?>();"></iframe>
<script>init();</script>

View File

@ -0,0 +1,151 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Defines the editing form for the multiple choice question type.
*
* @package qtype
* @subpackage ordering
* @copyright 2007 Jamie Pratt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Multiple choice editing form definition.
*
* @copyright 2007 Jamie Pratt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_ordering_edit_form extends question_edit_form {
/**
* Add question-type specific form fields.
*
* @param object $mform the form being built.
*/
public function definition_inner($mform) {
$NUMANS_START = 10;
$NUMANS_ADD = 5;
$menu = array(get_string('ordering_exactorder', 'qtype_ordering'), get_string('ordering_relativeorder', 'qtype_ordering'), get_string('ordering_contiguous', 'qtype_ordering'));
$mform->addElement('select', 'logical', get_string('ordering_logicalpossibilities', 'qtype_ordering'), $menu);
$mform->setDefault('logical', 0);
$menu1[] = "All";
for ($i=3; $i <= 20; $i++) {
$menu1[] = $i;
}
$mform->addElement('select', 'studentsee', get_string('ordering_itemsforstudent', 'qtype_ordering'), $menu1);
$mform->setDefault('studentsee', 0);
$repeated = array();
$repeated[] =& $mform->createElement('header', 'choicehdr', get_string('ordering_choiceno', 'qtype_ordering', '{no}'));
$repeated[] =& $mform->createElement('textarea', 'answer', get_string('ordering_answer', 'qtype_ordering'), 'rows="3" cols="50"');
if (isset($this->question->options)){
$countanswers = count($this->question->options->answers);
} else {
$countanswers = 0;
}
$repeatsatstart = ($NUMANS_START > ($countanswers + $NUMANS_ADD))?
$NUMANS_START : ($countanswers + $NUMANS_ADD);
$repeatedoptions = array();
$repeatedoptions['fraction']['default'] = 0;
$mform->setType('answer', PARAM_NOTAGS);
$this->repeat_elements($repeated, $repeatsatstart, $repeatedoptions, 'noanswers', 'addanswers', $NUMANS_ADD, get_string('ordering_addmoreanswers', 'qtype_ordering'));
$mform->addElement('header', 'overallfeedbackhdr', get_string('overallfeedback', 'qtype_ordering'));
$mform->addElement('htmleditor', 'correctfeedback', get_string('correctfeedback', 'qtype_ordering'));
$mform->setType('correctfeedback', PARAM_RAW);
$mform->addElement('htmleditor', 'partiallycorrectfeedback', get_string('partiallycorrectfeedback', 'qtype_ordering'));
$mform->setType('partiallycorrectfeedback', PARAM_RAW);
$mform->addElement('htmleditor', 'incorrectfeedback', get_string('incorrectfeedback', 'qtype_ordering'));
$mform->setType('incorrectfeedback', PARAM_RAW);
}
public function data_preprocessing($question) {
$question = parent::data_preprocessing($question);
//$question = $this->data_preprocessing_answers($question, true);
//$question = $this->data_preprocessing_combined_feedback($question, true);
//$question = $this->data_preprocessing_hints($question, true, true);
if (!empty($question->options)){
$answers = $question->options->answers;
if (count($answers)) {
$key = 0;
foreach ($answers as $answerkey => $answer){
$default_values['answer['.$key.']'] = $answer->answer;
$default_values['fraction['.$key.']'] = $answerkey + 1;
//$default_values['feedback['.$key.']'] = $answer->feedback;
$key++;
}
}
$default_values['studentsee'] = $question->options->studentsee;
$default_values['logical'] = $question->options->logical;
$question = (object)((array)$question + $default_values);
}
//echo "data_preprocessing";
//print_r ($question);
//die();
return $question;
//return true;
}
public function validation($data, $files) {
$errors = array();
$answers = $data['answer'];
$answercount = 0;
$totalfraction = 0;
$maxfraction = -1;
foreach ($answers as $key => $answer){
//check no of choices
$trimmedanswer = trim($answer);
if (!empty($trimmedanswer)){
$answercount++;
}
}
if ($answercount==0){
$errors['answer[0]'] = get_string('ordering_notenoughanswers', 'qtype_ordering', 2);
$errors['answer[1]'] = get_string('ordering_notenoughanswers', 'qtype_ordering', 2);
} elseif ($answercount==1){
$errors['answer[1]'] = get_string('ordering_notenoughanswers', 'qtype_ordering', 2);
}
return $errors;
}
public function qtype() {
return 'ordering';
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

111
question/type/ordering/jquery-ui.js vendored Normal file
View File

@ -0,0 +1,111 @@
/*!
* jQuery UI 1.8.16
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI
*/
(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.16",
keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({propAttr:c.fn.prop||c.fn.attr,_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=
this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,
"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":
"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,
outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a,
"tabindex"),d=isNaN(b);return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&
a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&
c.ui.isOverAxis(b,e,i)}})}})(jQuery);
;/*!
* jQuery UI Widget 1.8.16
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Widget
*/
(function(b,j){if(b.cleanData){var k=b.cleanData;b.cleanData=function(a){for(var c=0,d;(d=a[c])!=null;c++)try{b(d).triggerHandler("remove")}catch(e){}k(a)}}else{var l=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(d){}});return l.call(b(this),a,c)})}}b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=
function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):
d;if(e&&d.charAt(0)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):this.each(function(){var g=b.data(this,a);g?g.option(d||{})._init():b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=
b.extend(true,{},this.options,this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+
"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",
c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
;/*!
* jQuery UI Mouse 1.8.16
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Mouse
*
* Depends:
* jquery.ui.widget.js
*/
(function(b){var d=false;b(document).mouseup(function(){d=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(c){return a._mouseDown(c)}).bind("click."+this.widgetName,function(c){if(true===b.data(c.target,a.widgetName+".preventClickEvent")){b.removeData(c.target,a.widgetName+".preventClickEvent");c.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+
this.widgetName)},_mouseDown:function(a){if(!d){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var c=this,f=a.which==1,g=typeof this.options.cancel=="string"&&a.target.nodeName?b(a.target).closest(this.options.cancel).length:false;if(!f||g||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){c.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=
this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();return true}}true===b.data(a.target,this.widgetName+".preventClickEvent")&&b.removeData(a.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(e){return c._mouseMove(e)};this._mouseUpDelegate=function(e){return c._mouseUp(e)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return d=true}},_mouseMove:function(a){if(b.browser.msie&&
!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=
false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
;/*
* jQuery UI Sortable 1.8.16
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Sortables
*
* Depends:
* jquery.ui.core.js
* jquery.ui.mouse.js
* jquery.ui.widget.js
*/
(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable");
this.refresh();this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a===
"disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&
!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,
left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};
this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=
document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);
return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<
b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-
b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,
a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],
e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();
c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):
this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,
dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},
toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||
this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();
var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},
_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();
if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),
this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),
this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&
this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b];if(!(c.instance!=this.currentContainer&&this.currentContainer&&c.item[0]!=this.currentItem[0])){var e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=
this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=
d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||
0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",
a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-
f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=
this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==
""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=
this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a=
{top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),
10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?
document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),
10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=
this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&
this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();
var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-
this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-
this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],
this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]=
"";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",
f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,
this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",
a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},
_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.16"})})(jQuery);
;

18
question/type/ordering/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,46 @@
<?php // $Id: qtype_TEMPLATE.php,v 1.2 2006/08/25 21:40:44 Serafim Panov Exp $
/**
* The language strings for the QTYPENAME question type.
*
* @copyright &copy; 2006 YOURNAME
* @author YOUREMAILADDRESS
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package YOURPACKAGENAME
*/
$string['pluginname'] = 'Ordering';
$string['pluginname_help'] = 'Several items are displayed in a jumbled order. The items can be dragged into a meaningful order.';
$string['pluginname_link'] = 'question/type/ordering';
$string['pluginnameadding'] = 'Adding an Ordering question';
$string['pluginnameediting'] = 'Editing an Ordering question';
$string['pluginnamesummary'] = 'Put jumbled items into a meaningful order.';
$string['editingordering'] = 'Editing ordering';
$string['addingordering'] = 'Adding a Ordering';
$string['orderingsummary'] = 'Ordering summary';
$string['ordering'] = 'Ordering';
$string['ordering_exactorder'] = 'Exact order';
$string['ordering_relativeorder'] = 'Relative order';
$string['ordering_contiguous'] = 'Contiguous';
$string['ordering_logicalpossibilities'] = 'Logical possibilities';
$string['ordering_addmoreanswers'] = 'Blank for {no} more answers';
$string['ordering_choiceno'] = 'Answer {$a}';
$string['ordering_choices'] = 'Available answers';
$string['ordering_answer'] = 'Answer';
$string['ordering_itemsforstudent'] = 'How many items the student will see';
$string['correctfeedback'] = 'For any correct answer';
$string['incorrectfeedback'] = 'For any incorrect answer';
$string['overallfeedback'] = 'Overall Feedback';
$string['partiallycorrectfeedback'] = 'For any partially correct answer';
$string['ordering_notenoughanswers'] = 'not enough answers';
$string['ordering_comment'] = 'Drag and drop the items into the correct order.';
// TODO add any other requred strings.
$string['ordering_help'] = 'Ordering help';
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Serve question type files
*
* @since 2.0
* @package qtype
* @subpackage ordering
* @copyright Dongsheng Cai <dongsheng@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Checks file access for multiple choice questions.
*/
function qtype_ordering_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
global $CFG;
require_once($CFG->libdir . '/questionlib.php');
question_pluginfile($course, $context, 'qtype_ordering', $filearea, $args, $forcedownload);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

View File

@ -0,0 +1,213 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Multiple choice question definition classes.
*
* @package qtype
* @subpackage ordering
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Base class for multiple choice questions. The parts that are common to
* single select and multiple select.
*
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class qtype_ordering_base extends question_graded_automatically {
}
class qtype_ordering_question extends question_graded_automatically {
public $rightanswer;
public $truefeedback;
public $falsefeedback;
public $trueanswerid;
public $falseanswerid;
public function get_expected_data() {
return array('answer' => PARAM_INTEGER);
}
public function get_correct_response() {
return array('answer' => (int) $this->rightanswer);
}
public function summarise_response(array $response) {
}
public function classify_response(array $response) {
print_r ($response);
echo "!2!";
die();
if (!array_key_exists('answer', $response)) {
return array($this->id => question_classified_response::no_response());
}
list($fraction) = $this->grade_response($response);
if ($response['answer']) {
return array($this->id => new question_classified_response(1,
get_string('true', 'qtype_ordering'), $fraction));
} else {
return array($this->id => new question_classified_response(0,
get_string('false', 'qtype_ordering'), $fraction));
}
}
public function is_complete_response(array $response) {
global $DB;
$answer = $_POST["q".$this->id];
$orderdata = explode(",", $answer);
$responses = array();
$erroranswer = array();
foreach ($orderdata as $orderdata_) {
if (!empty($orderdata_))
list($a1,$a2,$responses[]) = explode("_", $orderdata_);
}
//print_r($responses);
$raw_grade = 0;
$questionordering = $DB->get_record ("question_ordering", array("question" => $this->id));
$questionanswers = $DB->get_records ("question_answers", array("question" => $this->id), "id");
$fractioncount = 1;
foreach ($questionanswers as $questionanswersfractiontemp) {
$questionanswers[$questionanswersfractiontemp->id]->fraction = $fractioncount;
++$fractioncount;
}
foreach ($questionanswers as $questionanswers_) {
$questionanswersfraction[$questionanswers_->fraction] = $questionanswers_->id;
}
$erroranswer['main'] = 0;
if (is_array($responses)) {
if ($questionordering->logical == 0) {
$nefr = 1;
if ($questionordering->studentsee != 0) {
foreach ($questionanswersfraction as $frkey => $frvalue) {
if (in_array($frvalue, $responses)) {
$questionanswersfractionnew [$nefr] = $frvalue;
$nefr ++;
}
}
$questionanswersfraction = $questionanswersfractionnew;
}
for ($i = 0; $i <= count($responses) - 1; $i++) {
if ($responses[$i] != $questionanswersfraction[$i + 1]) {
$erroranswer['main'] ++;
}
}
} else if ($questionordering->logical == 1) {
$erroranswer['main'] = 0;
for ($i = 0; $i <= count($responses) - 1; $i++) {
if ($i != count($responses) -1) {
if ($questionanswers[$responses[$i]]->fraction > $questionanswers[$responses[$i + 1]]->fraction) {
$erroranswer['main'] ++;
}
}
}
} else if ($questionordering->logical == 2) {
$fruits = $responses;
sort($fruits);
reset($fruits);
if ($responses[0] != $fruits[0]) {
$erroranswer['main'] ++;
}
for ($i = 0; $i <= count($responses) - 1; $i++) {
if ($i != count($responses) -1) {
if ($questionanswers[$responses[$i]]->fraction < $questionanswers[$responses[$i + 1]]->fraction) {
$raznica = $questionanswers[$responses[$i + 1]]->fraction - $questionanswers[$responses[$i]]->fraction - 1;
if ($raznica >= 1) {
$alreadycount = "false";
for ($d = 1; $d <= $raznica; $d++) {
if ($alreadycount == "false") {
if (in_array($questionanswersfraction[$questionanswers[$responses[$i]]->fraction + $d] ,$responses)) {
$alreadycount = "true";
$erroranswer['main'] ++;
}
}
}
}
} else {
$erroranswer['main'] ++;
}
}
}
}
if ($questionordering->logical == 0 || $questionordering->logical == 2)
$allcount = count($responses);
else
$allcount = count($responses) - 1;
$grade = ($allcount - $erroranswer['main']) / $allcount;
} else {
$state->raw_grade = 0;
$state->grade = 0;
}
$_SESSION['SESSION']->quiz_answer['q'.$this->id] = $grade;
return true;
}
public function is_gradable_response(array $response) {
return true;
}
public function get_validation_error(array $response) {
return '';
}
public function is_same_response(array $prevresponse, array $newresponse) {
}
public function compute_final_grade($responses, $totaltries) {
return 1;
}
public function grade_response(array $response) {
$fraction = $_SESSION['SESSION']->quiz_answer['q'.$this->id];
return array($fraction, question_state::graded_state_for_fraction($fraction));
}
public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) {
}
}

View File

@ -0,0 +1,213 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The questiontype class for the multiple choice question type.
*
* @package qtype
* @subpackage ordering
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
if (class_exists('question_type')) {
$register_questiontype = false;
} else {
$register_questiontype = true; // Moodle 2.0
require_once(__DIR__.'/legacy/20.php');
}
/**
* The multiple choice question type.
*
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_ordering extends question_type {
/*
public function get_question_options($question) {
global $DB, $OUTPUT;
$question->options = $DB->get_record('question_ordering',
array('question' => $question->id), '*', MUST_EXIST);
parent::get_question_options($question);
}
*/
public function save_question_options($question) {
global $DB, $OUTPUT;
foreach ($question->answer as $answerkey => $answervalue) {
$question->fraction[] = $answerkey + 1;
}
$result = new stdClass;
if (!$oldanswers = $DB->get_records('question_answers', array('question'=>$question->id), 'id ASC')) {
$oldanswers = array();
}
// following hack to check at least two answers exist
$answercount = 0;
foreach ($question->answer as $key=>$dataanswer) {
if ($dataanswer != "") {
$answercount++;
}
}
$answercount += count($oldanswers);
if ($answercount < 2) { // check there are at lest 2 answers for multiple choice
$result->notice = get_string("ordering_notenoughanswers", "qtype_ordering", "2");
return $result;
}
// Insert all the new answers
$totalfraction = 0;
$maxfraction = -1;
$answers = array();
foreach ($question->answer as $key => $dataanswer) {
if ($dataanswer != "") {
if ($answer = array_shift($oldanswers)) { // Existing answer, so reuse it
$answer->answer = $dataanswer;
$answer->fraction = $question->fraction[$key];
if (!$DB->update_record("question_answers", $answer)) {
$result->error = "Could not update quiz answer! (id=$answer->id)";
return $result;
}
} else {
unset($answer);
$answer->answer = $dataanswer;
$answer->question = $question->id;
$answer->fraction = number_format($question->fraction[$key], 7);
$answer->feedback = "";
//echo '<pre>';
//print_r ($answer);
if (!$answer->id = $DB->insert_record("question_answers", $answer)) {
$result->error = "Could not insert quiz answer! ";
return $result;
}
}
$answers[] = $answer->id;
if ($question->fraction[$key] > 0) { // Sanity checks
$totalfraction += $question->fraction[$key];
}
if ($question->fraction[$key] > $maxfraction) {
$maxfraction = $question->fraction[$key];
}
}
}
$update = true;
$options = $DB->get_record("question_ordering", array("question" => $question->id));
if (!$options) {
$update = false;
$options = new stdClass;
$options->question = $question->id;
}
$options->logical = $question->logical;
$options->studentsee = $question->studentsee;
$options->correctfeedback = $question->correctfeedback;
$options->partiallycorrectfeedback = $question->partiallycorrectfeedback;
$options->incorrectfeedback = $question->incorrectfeedback;
if ($update) {
if (!$DB->update_record("question_ordering", $options)) {
$result->error = "Could not update quiz ordering options! (id=$options->id)";
return $result;
}
} else {
if (!$DB->insert_record("question_ordering", $options)) {
$result->error = "Could not insert quiz ordering options!";
return $result;
}
}
// delete old answer records
if (!empty($oldanswers)) {
foreach($oldanswers as $oa) {
$DB->delete_records('question_answers', array('id' => $oa->id));
}
}
/// Perform sanity checks on fractional grades
return true;
}
public function get_question_options($question) {
global $DB, $OUTPUT;
// Get additional information from database
// and attach it to the question object
if (!$question->options = $DB->get_record('question_ordering',
array('question' => $question->id))) {
echo $OUTPUT->notification('Error: Missing question options!');
return false;
}
// Load the answers
if (!$question->options->answers = $DB->get_records('question_answers',
array('question' => $question->id), 'id ASC')) {
echo $OUTPUT->notification('Error: Missing question answers for truefalse question ' .
$question->id . '!');
return false;
}
return true;
}
/*
protected function initialise_question_instance(question_definition $question, $questiondata) {
parent::initialise_question_instance($question, $questiondata);
$answers = $questiondata->options->answers;
if ($answers[$questiondata->options->trueanswer]->fraction > 0.99) {
$question->rightanswer = true;
} else {
$question->rightanswer = false;
}
$question->truefeedback = $answers[$questiondata->options->trueanswer]->feedback;
$question->falsefeedback = $answers[$questiondata->options->falseanswer]->feedback;
$question->truefeedbackformat =
$answers[$questiondata->options->trueanswer]->feedbackformat;
$question->falsefeedbackformat =
$answers[$questiondata->options->falseanswer]->feedbackformat;
$question->trueanswerid = $questiondata->options->trueanswer;
$question->falseanswerid = $questiondata->options->falseanswer;
}
*/
public function delete_question($questionid, $contextid) {
global $DB;
$DB->delete_records('question_ordering', array('question' => $questionid));
parent::delete_question($questionid, $contextid);
}
}
// NEW LINES START
if ($register_questiontype) {
class question_ordering_qtype extends qtype_ordering {
function name() {
return 'ordering';
}
}
question_register_questiontype(new question_ordering_qtype());
}
// NEW LINES STOP

View File

@ -0,0 +1,356 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* True-false question renderer class.
*
* @package qtype
* @subpackage ordering
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Generates the output for true-false questions.
*
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_ordering_renderer extends qtype_renderer {
public function formulation_and_controls(question_attempt $qa,
question_display_options $options) {
global $DB, $CFG;
$question = $qa->get_question();
//$stemorder = $question->get_stem_order();
//$response = $qa->get_last_qt_data();
//print_r ($response);
//echo "!7!";
//$response = $qa->get_last_qt_var('answer', '');
//print_r ($_REQUEST);
/*
$inputname = $qa->get_qt_field_name('answer');
$trueattributes = array(
'type' => 'radio',
'name' => $inputname,
'value' => 1,
'id' => $inputname . 'true',
);
$falseattributes = array(
'type' => 'radio',
'name' => $inputname,
'value' => 0,
'id' => $inputname . 'false',
);
if ($options->readonly) {
$trueattributes['disabled'] = 'disabled';
$falseattributes['disabled'] = 'disabled';
}
*/
//print_r ($question);
//echo "@@@@";
//print_r ($options);
/*
// Work out which radio button to select (if any)
$truechecked = false;
$falsechecked = false;
$responsearray = array();
if ($response) {
$trueattributes['checked'] = 'checked';
$truechecked = true;
$responsearray = array('answer' => 1);
} else if ($response !== '') {
$falseattributes['checked'] = 'checked';
$falsechecked = true;
$responsearray = array('answer' => 1);
}
// Work out visual feedback for answer correctness.
$trueclass = '';
$falseclass = '';
$truefeedbackimg = '';
$falsefeedbackimg = '';
if ($options->correctness) {
if ($truechecked) {
$trueclass = ' ' . $this->feedback_class((int) $question->rightanswer);
$truefeedbackimg = $this->feedback_image((int) $question->rightanswer);
} else if ($falsechecked) {
$falseclass = ' ' . $this->feedback_class((int) (!$question->rightanswer));
$falsefeedbackimg = $this->feedback_image((int) (!$question->rightanswer));
}
}
$radiotrue = html_writer::empty_tag('input', $trueattributes) .
html_writer::tag('label', get_string('true', 'qtype_ordering'),
array('for' => $trueattributes['id']));
$radiofalse = html_writer::empty_tag('input', $falseattributes) .
html_writer::tag('label', get_string('false', 'qtype_ordering'),
array('for' => $falseattributes['id']));
$result = '';
$result .= html_writer::tag('div', $question->format_questiontext($qa),
array('class' => 'qtext'));
$result .= html_writer::start_tag('div', array('class' => 'ablock'));
$result .= html_writer::tag('div', get_string('selectone', 'qtype_ordering'),
array('class' => 'prompt'));
$result .= html_writer::start_tag('div', array('class' => 'answer'));
$result .= html_writer::tag('div', $radiotrue . ' ' . $truefeedbackimg,
array('class' => 'r0' . $trueclass));
$result .= html_writer::tag('div', $radiofalse . ' ' . $falsefeedbackimg,
array('class' => 'r1' . $falseclass));
$result .= html_writer::end_tag('div'); // answer
$result .= html_writer::end_tag('div'); // ablock
if ($qa->get_state() == question_state::$invalid) {
$result .= html_writer::nonempty_tag('div',
$question->get_validation_error($responsearray),
array('class' => 'validationerror'));
}
*/
//print_r ($this);
$data = $DB->get_record("question_ordering", array("question" => $question->id));
if ($data->studentsee == 0) $data->studentsee = 100; else $data->studentsee += 2;
//if ($CFG->dbtype == "mysql") $rand = 'RAND()'; else $rand = 'RANDOM()';
//$answers = $DB->get_records_sql("SELECT * FROM {question_answers} WHERE question = ? ORDER BY ".$rand." LIMIT ?", array($question->id, $data->studentsee));
//$answers = $DB->get_records_sql("SELECT * FROM {question_answers} WHERE question = ? ORDER BY id LIMIT ?", array($question->id, $data->studentsee));
$answers = $DB->get_records("question_answers", array("question" => $question->id), '', '*', 0, $data->studentsee);
shuffle($answers);
$result = '';
$result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/jquery.js'));
$result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/jquery-ui.js'));
$result .= html_writer::tag('style', 'ul.sortable li {
position: relative;
}
ul.boxy {
list-style-type: none;
padding: 4px 4px 0 4px;
margin: 0px;
font-size: 13px;
font-family: Arial, sans-serif;
border: 1px solid #ccc;
width: 360px;
float: left;
margin-left: 5px;
}
ul.boxy li {
cursor: move;
margin-bottom: 1px;
padding: 8px 2px;
border: 1px solid #CCC;
background-color: #EEE;
min-height: 20px;
border-image: initial;
list-style-type: none;
}
');
$result .= html_writer::tag('script', '
$(function() {
$( "#sortable" ).sortable({
update: function(event, ui) {
var ItemsOrder = $(this).sortable(\'toArray\').toString();
$(\'#q'.$question->id.'\').attr("value", ItemsOrder);
}
});
$( "#sortable" ).disableSelection();
});
$(document).ready(function() {
var ItemsOrder = $("#sortable").sortable(\'toArray\').toString();
$(\'#q'.$question->id.'\').attr("value", ItemsOrder);
});
');
$result .= html_writer::tag('div', stripslashes($question->format_questiontext($qa)),
array('class' => 'qtext'));
$result .= html_writer::start_tag('div', array('class' => 'ablock'));
$result .= html_writer::start_tag('div', array('class' => 'answer'));
$result .= html_writer::start_tag('ul', array('class' => 'boxy', 'id' => 'sortable'));
while (list($key,$value)=each($answers)) {
list($fr) = explode(".", $value->fraction);
$result .= html_writer::tag('li', stripslashes($value->answer),
array('class' => 'ui-state-default', 'id' => 'ordering_item_'.$value->id.'_'.$fr));
}
$result .= html_writer::end_tag('ul');
$result .= html_writer::end_tag('div'); // answer
$result .= html_writer::end_tag('div'); // ablock
$result .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'q'.$question->id, 'id' => 'q'.$question->id));
$result .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'answer', 'value' => '712'));
$result .= html_writer::tag('div', '', array('style' => 'clear:both;'));
$result .= html_writer::tag('script', '
function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart":
type = "mousedown";
break;
case "touchmove":
type="mousemove";
event.preventDefault();
break;
case "touchend":
type="mouseup";
break;
default:
return;
}
var simulatedEvent = document.createEvent("MouseEvent");
//initMouseEvent(type, canBubble, cancelable, view, clickCount, screenX, screenY, clientX, clientY,
// ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init() {
for(i=0;i<document.getElementById("sortable").childNodes.length;i++) {
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchstart", touchHandler, false);
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchmove", touchHandler, false);
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchend", touchHandler, false);
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchcancel", touchHandler, false);
}
var myInterval = window.setInterval(function (a,b) {
function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart":
type = "mousedown";
break;
case "touchmove":
type="mousemove";
event.preventDefault();
break;
case "touchend":
type="mouseup";
break;
default:
return;
}
var simulatedEvent = document.createEvent("MouseEvent");
//initMouseEvent(type, canBubble, cancelable, view, clickCount, screenX, screenY, clientX, clientY,
// ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
for(i=0;i<document.getElementById("sortable").childNodes.length;i++) {
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchstart", touchHandler, false);
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchmove", touchHandler, false);
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchend", touchHandler, false);
document.getElementById(\'sortable\').childNodes.item(i).addEventListener("touchcancel", touchHandler, false);
}
},500);
}
init();
');
return $result;
}
/*
public function specific_feedback(question_attempt $qa) {
$question = $qa->get_question();
$response = $qa->get_last_qt_var('answer', '');
if ($response) {
return $question->format_text($question->truefeedback, $question->truefeedbackformat,
$qa, 'question', 'answerfeedback', $question->trueanswerid);
} else if ($response !== '') {
return $question->format_text($question->falsefeedback, $question->falsefeedbackformat,
$qa, 'question', 'answerfeedback', $question->falseanswerid);
}
}
*/
public function correct_response(question_attempt $qa) {
global $DB;
$question = $qa->get_question();
$data = $DB->get_records("question_attempt_steps", array("questionattemptid" => $question->contextid), "id DESC");
$data = current($data);
if ($data->fraction >= 1) {
$feedback = get_string('correctfeedback', 'qtype_ordering');
} else if ($data->fraction > 0) {
$feedback = get_string('partiallycorrectfeedback', 'qtype_ordering') . " ".round($data->fraction, 2);
} else {
$feedback = get_string('incorrectfeedback', 'qtype_ordering');
}
return $feedback;
}
}

View File

@ -0,0 +1,29 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Version information for the multiple choice question type.
*
* @package qtype
* @subpackage multichoice
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2010090501;
//$plugin->requires = 2011060313;