Skip to content

Commit

Permalink
Ticking off items now sends AJAX updates back to server
Browse files Browse the repository at this point in the history
  • Loading branch information
davosmith committed May 10, 2011
1 parent 381e294 commit 9deb4b7
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 10 deletions.
33 changes: 24 additions & 9 deletions mod/checklist/locallib.php
Expand Up @@ -661,20 +661,24 @@ function view_progressbar() {
echo '<div style="display:block; float:left; width:150px;" class="checklist_progress_heading">';
echo get_string('percentcomplete','checklist').':&nbsp;';
echo '</div>';
echo '<span id="checklistprogressrequired">';
echo '<div class="checklist_progress_outer">';
echo '<div class="checklist_progress_inner" style="width:'.$percentcomplete.'%; background-image: url('.$CFG->wwwroot.'/mod/checklist/images/progress.gif);" >&nbsp;</div>';
echo '</div>';
echo '<span class="checklist_progress_percent">&nbsp;'.sprintf('%0d',$percentcomplete).'% </span>';
echo '</span>';
echo '<br style="clear:both"/>';
}

echo '<div style="display:block; float:left; width:150px;" class="checklist_progress_heading">';
echo get_string('percentcompleteall','checklist').':&nbsp;';
echo '</div>';
echo '<span id="checklistprogressall">';
echo '<div class="checklist_progress_outer">';
echo '<div class="checklist_progress_inner" style="width:'.$allpercentcomplete.'%; background-image: url('.$CFG->wwwroot.'/mod/checklist/images/progress.gif);" >&nbsp;</div>';
echo '</div>';
echo '<span class="checklist_progress_percent">&nbsp;'.sprintf('%0d',$allpercentcomplete).'% </span>';
echo '</span>';
echo '<br style="clear:both"/>';
}

Expand Down Expand Up @@ -771,6 +775,15 @@ function view_items($viewother = false, $userreport = false) {
}
echo '</form>';
}

if (!$viewother) {
// Load the Javascript required to send changes back to the server (without clicking 'save')
require_js(array('yui_yahoo', 'yui_dom', 'yui_event', 'yui_connection'));
require_js($CFG->wwwroot.'/mod/checklist/updatechecks.js');
$updatechecksurl = $CFG->wwwroot.'/mod/checklist/updatechecks.php';
echo '<script type="text/javascript">mod_checklist.set_server("'.$updatechecksurl.'","'.sesskey().'","'.$this->cm->id.'");</script>';
}

echo '<form action="'.$thispage.'" method="post">';
echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
echo '<input type="hidden" name="action" value="updatechecks" />';
Expand Down Expand Up @@ -860,8 +873,10 @@ function view_items($viewother = false, $userreport = false) {
$spacerimg = $CFG->wwwroot.'/mod/checklist/images/check_spacer.gif';
} elseif ($item->itemoptional == CHECKLIST_OPTIONAL_YES) {
$optional = ' class="itemoptional '.$itemcolour.'" ';
$checkclass = ' itemoptional';
} else {
$optional = ' class="'.$itemcolour.'" ';
$checkclass = '';
}
echo '<li>';
if ($showteachermark) {
Expand All @@ -888,7 +903,7 @@ function view_items($viewother = false, $userreport = false) {
if ($item->itemoptional == CHECKLIST_OPTIONAL_HEADING) {
//echo '<img src="'.$spacerimg.'" alt="" title="" />';
} else {
echo '<input type="checkbox" name="items[]" id='.$itemname.$checked.' value="'.$item->id.'" />';
echo '<input class="checklistitem'.$checkclass.'" type="checkbox" name="items[]" id='.$itemname.$checked.' value="'.$item->id.'" />';
}
}
echo '<label for='.$itemname.$optional.'>'.s($item->displaytext).'</label>';
Expand Down Expand Up @@ -953,7 +968,7 @@ function view_items($viewother = false, $userreport = false) {
echo '<li>';
echo '<div style="float: left;">';
if ($showcheckbox) {
echo '<input type="checkbox" name="items[]" id='.$itemname.$checked.' disabled="disabled" value="'.$useritem->id.'" />';
echo '<input class="checklistitem itemoptional" type="checkbox" name="items[]" id='.$itemname.$checked.' disabled="disabled" value="'.$useritem->id.'" />';
}
echo '<form style="display:inline" action="'.$thispage.'" method="post">';
echo '<input type="hidden" name="action" value="updateitem" />';
Expand All @@ -978,7 +993,7 @@ function view_items($viewother = false, $userreport = false) {
} else {
echo '<li>';
if ($showcheckbox) {
echo '<input type="checkbox" name="items[]" id='.$itemname.$checked.' value="'.$useritem->id.'" />';
echo '<input class="checklistitem itemoptional" type="checkbox" name="items[]" id='.$itemname.$checked.' value="'.$useritem->id.'" />';
}
$splittext = explode("\n",s($useritem->displaytext),2);
$splittext[] = '';
Expand Down Expand Up @@ -1041,7 +1056,7 @@ function view_items($viewother = false, $userreport = false) {
echo '</ol>';

if ($updateform) {
echo '<input type="submit" name="submit" value="'.get_string('savechecks','checklist').'" />';
echo '<input id="checklistsavechecks" type="submit" name="submit" value="'.get_string('savechecks','checklist').'" />';
echo '<input type="hidden" name="sortby" value="'.$this->sortby.'" />';
if ($viewother) {
echo '<input type="submit" name="savenext" value="'.get_string('saveandnext').'" />';
Expand Down Expand Up @@ -2350,8 +2365,8 @@ function ajaxupdatechecks($changechecks) {

$newchecks = array();
foreach ($this->items as $item) {
if (array_key_exists($item->id, $newchecks)) {
if ($newchecks[$item->id]) {
if (array_key_exists($item->id, $changechecks)) {
if ($changechecks[$item->id]) {
// Include in array if new status is true
$newchecks[] = $item->id;
}
Expand All @@ -2364,8 +2379,8 @@ function ajaxupdatechecks($changechecks) {
}
if ($this->useritems) {
foreach ($this->useritems as $item) {
if (array_key_exists($item->id, $newchecks)) {
if ($newchecks[$item->id]) {
if (array_key_exists($item->id, $changechecks)) {
if ($changechecks[$item->id]) {
// Include in array if new status is true
$newchecks[] = $item->id;
}
Expand All @@ -2378,7 +2393,7 @@ function ajaxupdatechecks($changechecks) {
}
}

updatechecks($newchecks);
$this->updatechecks($newchecks);
}

function updatechecks($newchecks) {
Expand Down
156 changes: 156 additions & 0 deletions mod/checklist/updatechecks.js
@@ -0,0 +1,156 @@
mod_checklist = {

serverurl: null,
sesskey: null,
cmid: null,
updatelist: null,
updatetimeout: null,
requiredcount: 0,
optionalcount: 0,
requiredchecked: 0,
optionalchecked: 0,

set_server: function (url, sesskey, cmid) {
this.serverurl = url;
this.sesskey = sesskey;
this.cmid = cmid;
},

init: function() {
var YE = YAHOO.util.Event;
var YD = YAHOO.util.Dom;

this.updatelist = new Array();

var checklist = YAHOO.util.Dom.get('checklistouter');
var items = checklist.getElementsByClassName('checklistitem');
for (var i=0; i<items.length; i++) {
YE.addListener(items[i], 'click', function (e) {
mod_checklist.check_click(this, e);
});
if (YD.hasClass(items[i], 'itemoptional')) {
this.optionalcount++;
if (items[i].checked) {
this.optionalchecked++;
}
} else {
this.requiredcount++;
if (items[i].checked) {
this.requiredchecked++;
}
}
}
YD.setStyle('checklistsavechecks', 'display', 'none');
window.onunload = function(e) {
mod_checklist.send_update_batch(true);
};
},

check_click: function(el, e) {
var YD = YAHOO.util.Dom;

// Update progress bar
var change = -1;
if (el.checked) {
change = 1;
}
if (YD.hasClass(el, 'itemoptional')) {
this.optionalchecked += change;
} else {
this.requiredchecked += change;
}
this.update_progress_bar();

// Save check to list for updating
this.update_server(el.value, el.checked);
},

update_progress_bar: function() {
var YD = YAHOO.util.Dom;
var prall = YD.get('checklistprogressall');
var prreq = YD.get('checklistprogressrequired');

var allpercent = (this.optionalchecked + this.requiredchecked) * 100.0 / (this.optionalcount + this.requiredcount);
var inner = prall.getElementsByClassName('checklist_progress_inner')[0];
YD.setStyle(inner, 'width', allpercent+'%');
var disppercent = prall.getElementsByClassName('checklist_progress_percent')[0];
disppercent.innerHTML = '&nbsp;'+allpercent.toFixed(0)+'% ';

if (prreq) {
var reqpercent = this.requiredchecked * 100.0 / this.requiredcount;
var inner = prreq.getElementsByClassName('checklist_progress_inner')[0];
YD.setStyle(inner, 'width', reqpercent+'%');
var disppercent = prreq.getElementsByClassName('checklist_progress_percent')[0];
disppercent.innerHTML = '&nbsp;'+reqpercent.toFixed(0)+'% ';
}

},

update_server: function(itemid, state) {
for (var i=0; i<this.updatelist.length; i++) {
if (this.updatelist[i].itemid == itemid) {
if (this.updatelist[i].state != state) {
this.updatelist.splice(i, 1);
}
return;
}
}

this.updatelist.push({'itemid':itemid, 'state':state});

if (this.updatetimeout) {
clearTimeout(this.updatetimeout);
}
this.updatetimeout = setTimeout(function() {
mod_checklist.send_update_batch(false);
}, 1000);
},

send_update_batch: function(unload) {
// Send all updates after 1 second of inactivity (or on page unload)
if (this.updatetimeout) {
clearTimeout(this.updatetimeout);
this.updatetimeout = null;
}

if (this.updatelist.length == 0) {
return;
}

var params = new Array();
for (var i=0; i<this.updatelist.length; i++) {
var val = this.updatelist[i].state ? 1 : 0;
params.push('items['+this.updatelist[i].itemid+']='+val);
}
params.push('sesskey='+this.sesskey);
params.push('id='+this.cmid);
params = params.join('&');

// Clear the list of updates to send
this.updatelist = new Array();

// Send message to server
if (!unload) {
var callback= {
success: function(o) {
if (o.responseText != 'OK') {
alert(o.responseText);
}
},
failure: function(o) {
alert(o.statusText);
},
timeout: 5000
};

var YC = YAHOO.util.Connect;
YC.asyncRequest('POST', this.serverurl, callback, params);
} else {
// Nasty hack to make it save everything on unload
var beacon = new Image();
beacon.src = this.serverurl + '?' + params;
}
}
}

YAHOO.util.Event.onDOMReady(function() { mod_checklist.init() });
3 changes: 2 additions & 1 deletion mod/checklist/updatechecks.php
Expand Up @@ -72,9 +72,10 @@
}
if (!$items || !is_array($items)) {
echo 'Error: invalid (or missing) items list';
die();
}

if (!is_empty($items)) {
if (!empty($items)) {
$chk = new checklist_class($cm->id, $userid, $checklist, $cm, $course);
$chk->ajaxupdatechecks($items);
}
Expand Down

0 comments on commit 9deb4b7

Please sign in to comment.