From 0a0bb38019d8697654962c5321c6325eda2c6890 Mon Sep 17 00:00:00 2001 From: moodler Date: Thu, 24 Aug 2006 03:20:37 +0000 Subject: [PATCH] Ed Coyne's AJAX course format, with some cleanups done. More cleanups to come from Ed. This isn't actually working for me right now but he'll fix it now. This is completely optional and won't affect any other code right now. --- blocks/moodleblock.class.php | 27 +- course/format/topicsajax/ajaxcourse-topics.js | 220 ++++++ course/format/topicsajax/commands.php | 149 +++++ course/format/topicsajax/config.php | 13 + course/format/topicsajax/format.php | 292 ++++++++ lib/ajax/ajaxlib.php | 84 +++ lib/ajax/block_classes.js | 348 ++++++++++ lib/ajax/section-resource_classes.js | 633 ++++++++++++++++++ lib/blocklib.php | 10 +- 9 files changed, 1766 insertions(+), 10 deletions(-) create mode 100644 course/format/topicsajax/ajaxcourse-topics.js create mode 100644 course/format/topicsajax/commands.php create mode 100644 course/format/topicsajax/config.php create mode 100644 course/format/topicsajax/format.php create mode 100644 lib/ajax/ajaxlib.php create mode 100644 lib/ajax/block_classes.js create mode 100755 lib/ajax/section-resource_classes.js diff --git a/blocks/moodleblock.class.php b/blocks/moodleblock.class.php index 9ff1a0b819..4a4a2a8722 100644 --- a/blocks/moodleblock.class.php +++ b/blocks/moodleblock.class.php @@ -218,8 +218,10 @@ class block_base { * Display the block! */ function _print_block() { + global $COURSE; + // is_empty() includes a call to get_content() - if ($this->is_empty()) { + if ($this->is_empty()&&!($COURSE->javascriptportal)) { if (empty($this->edit_controls)) { // No content, no edit controls, so just shut up return; @@ -235,6 +237,11 @@ class block_base { // The full treatment, please. Include the title text. print_side_block($this->_title_html(), $this->content->text, NULL, NULL, $this->content->footer, $this->html_attributes(), $this->title); } + + //make a record of the block for the ajax course format to use + if (!empty($COURSE->javascriptportal)) { + $COURSE->javascriptportal->block_add('inst'.$this->instance->id,!$this->instance->visible); + } } } @@ -664,8 +671,11 @@ class block_list extends block_base { } function _print_block() { + global $COURSE; + // is_empty() includes a call to get_content() - if ($this->is_empty()) { + + if ($this->is_empty()&&!($COURSE->javascriptportal)) { if (empty($this->edit_controls)) { // No content, no edit controls, so just shut up return; @@ -676,10 +686,17 @@ class block_list extends block_base { } else { if ($this->hide_header() && empty($this->edit_controls)) { // Header wants to hide, no edit controls to show, so no header it is - print_side_block(NULL, '', $this->content->items, $this->content->icons, $this->content->footer, $this->html_attributes()); + print_side_block(NULL, '', $this->content->items, $this->content->icons, + $this->content->footer, $this->html_attributes()); } else { // The full treatment, please. Include the title text. - print_side_block($this->_title_html(), '', $this->content->items, $this->content->icons, $this->content->footer, $this->html_attributes(), $this->title); + print_side_block($this->_title_html(), '', $this->content->items, $this->content->icons, + $this->content->footer, $this->html_attributes(), $this->title); + } + + //make a record of the block for the ajax course format to use + if (!empty($COURSE->javascriptportal)) { + $COURSE->javascriptportal->block_add('inst'.$this->instance->id,!$this->instance->visible); } } } @@ -742,4 +759,4 @@ class block_nuke extends block_base { } } -?> \ No newline at end of file +?> diff --git a/course/format/topicsajax/ajaxcourse-topics.js b/course/format/topicsajax/ajaxcourse-topics.js new file mode 100644 index 0000000000..270455aa65 --- /dev/null +++ b/course/format/topicsajax/ajaxcourse-topics.js @@ -0,0 +1,220 @@ +/* + * Contains Main class and supporting functions for topic ajax course layout + */ + +//hide content body until done loading (manipulation looks ugly elsewise) +document.getElementById('content').style.display='none'; + +//onload object for handling scripts on page load, this insurses they run in my order +function onload_class(){ + this.scripts = new Array(); + this.debug = false; +} + +onload_class.prototype.add = function(script){ + if(this.debug)YAHOO.log("onload.add - adding "+script,"junk"); + this.scripts[this.scripts.length] = script; + } + +onload_class.prototype.load = function(){ + var scriptcount = this.scripts.length; + if(this.debug)YAHOO.log("onload.load - loading "+scriptcount+" scripts","info"); + for(i=0;i= main.connectQueue.length) + return; + + var callback = { + success: function(){ + main.connectQueue_fireNext(); + } + } + + main.connectQueueConnection = main.connect(main.connectQueue[head]['method'],main.connectQueue[head]['urlStub'],callback,main.connectQueue[head]['body']) + + main.connectQueueHead++; + } + +main_class.prototype.update_marker = function(newMarker){ + if(this.marker != null) + this.marker.toggle_highlight(); + + this.marker = newMarker; + this.marker.toggle_highlight(); + + this.connect('post','class=course&field=marker',null,'value='+this.marker.sectionId); + } + + + + +var main = new main_class(); + + +function php_portal_class(){ + //portal to php data + + this.id = null; + + //array of id's of blocks set at end of page load by php + this.blocks = new Array(); + this.imagePath = null; + + //flag for week fomat + this.isWeek = false; + + YAHOO.log("instantiated php_portal_class","info"); +} diff --git a/course/format/topicsajax/commands.php b/course/format/topicsajax/commands.php new file mode 100644 index 0000000000..3a6df6743f --- /dev/null +++ b/course/format/topicsajax/commands.php @@ -0,0 +1,149 @@ +id); + + if (!isteacher($course->id)){ + error("Not authorized to edit page!"); + } + + + switch($_SERVER['REQUEST_METHOD']){ + + + case POST: + switch($_GET['class']){ + case block: switch($_GET[field]){ + + case visible: + $dataobject->id = $_POST[instanceId]; + $dataobject->visible = $_POST[value]; + update_record('block_instance',$dataobject); + break; + + case position: + $dataobject->id = $_POST[instanceId]; + $dataobject->position = $_POST[value]; + $dataobject->weight = $_POST[weight]; + update_record('block_instance',$dataobject); + //echo("Got ".$_GET['class'].",".$_GET[field]."Posted id=".$dataobject->id." position=".$dataobject->position." weight=".$dataobject->weight); + break; + } + break; + + + case section: switch($_GET[field]){ + + case visible: + $dataobject->id = get_field('course_sections','id','course',$course->id,'section',(int)$_POST[id]); + $dataobject->visible = $_POST[value]; + update_record('course_sections',$dataobject); + break; + + + case sequence: + $dataobject->id = get_field('course_sections','id','course',$course->id,'section',(int)$_POST[id]); + $dataobject->sequence = $_POST[value]; + update_record('course_sections',$dataobject); + break; + + case all: + $dataobject->id = get_field('course_sections','id','course',$course->id,'section',(int)$_POST[id]); + $dataobject->summary = make_dangerous($_POST[summary]); + $dataobject->sequence = $_POST[sequence]; + $dataobject->visible = $_POST[visible]; + update_record('course_sections',$dataobject); + break; + + + + } + break; + + + + + case resource: switch($_GET[field]){ + + case visible: + $dataobject->id = $_POST[id]; + $dataobject->visible = $_POST[value]; + update_record('course_modules',$dataobject); + break; + + case groupmode: + $dataobject->id = $_POST[id]; + $dataobject->groupmode = $_POST[value]; + update_record('course_modules',$dataobject); + break; + + case section: + $dataobject->id = $_POST[id]; + $dataobject->section = $_POST[value]; + update_record('course_modules',$dataobject); + break; + + } + break; + + case course: switch($_GET[field]){ + + case marker: + $dataobject = NULL; + $dataobject->id = $course->id; + $dataobject->marker = $_POST[value]; + update_record('course',$dataobject); + break; + + + } + break; + + } + + + break; + case DELETE: + switch($_GET['class']){ + case block: + delete_records('block_instance','id',$_GET[instanceId]); + break; + + case section: + $dataobject->id = get_field('course_sections','id','course',$course->id,'section',(int)$_GET[id]); + $dataobject->summary = ''; + $dataobject->sequence = ''; + $dataobject->visible = '1'; + update_record('course_sections',$dataobject); + break; + + case resource: + delete_records('course_modules','id',$_GET[id]); + break; + + } + break; + } + + function make_dangerous($input){ + //the compliment to the javascript function 'make_safe' + return str_replace("_.amp._","&",$input); + } +?> diff --git a/course/format/topicsajax/config.php b/course/format/topicsajax/config.php new file mode 100644 index 0000000000..2d3eaca707 --- /dev/null +++ b/course/format/topicsajax/config.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/course/format/topicsajax/format.php b/course/format/topicsajax/format.php new file mode 100644 index 0000000000..dd6e2fe229 --- /dev/null +++ b/course/format/topicsajax/format.php @@ -0,0 +1,292 @@ +dirroot.'/mod/forum/lib.php'); + require_once($CFG->libdir.'/ajax/ajaxlib.php'); + + + $topic = optional_param('topic', -1, PARAM_INT); + + + // Bounds for block widths + define('BLOCK_L_MIN_WIDTH', 100); + define('BLOCK_L_MAX_WIDTH', 210); + define('BLOCK_R_MIN_WIDTH', 100); + define('BLOCK_R_MAX_WIDTH', 210); + + $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]), + BLOCK_L_MAX_WIDTH); + $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]), + BLOCK_R_MAX_WIDTH); + + if ($topic != -1) { + $displaysection = course_set_display($course->id, $topic); + } else { + if (isset($USER->display[$course->id])) { // for admins, mostly + $displaysection = $USER->display[$course->id]; + } else { + $displaysection = course_set_display($course->id, 0); + } + } + + if (($marker >=0) && isteacher($course->id) && confirm_sesskey()) { + $course->marker = $marker; + if (! set_field("course", "marker", $marker, "id", $course->id)) { + error("Could not mark that topic for this course"); + } + } + + $streditsummary = get_string('editsummary'); + $stradd = get_string('add'); + $stractivities = get_string('activities'); + $strshowalltopics = get_string('showalltopics'); + $strtopic = get_string('topic'); + $strgroups = get_string('groups'); + $strgroupmy = get_string('groupmy'); + $editing = $PAGE->user_is_editing(); + + if ($editing) { + $strstudents = moodle_strtolower($course->students); + $strtopichide = get_string('topichide', '', $strstudents); + $strtopicshow = get_string('topicshow', '', $strstudents); + $strmarkthistopic = get_string('markthistopic'); + $strmarkedthistopic = get_string('markedthistopic'); + $strmoveup = get_string('moveup'); + $strmovedown = get_string('movedown'); + + //use temporarily until I figure out how to add a field to the user object + $temporary_override = true; + if (!empty($USER->use_ajax) || $temporary_override ){ + /* + * if user doesnt want AJAX, than they wont get it, + * from here everything detects $COURSE->javascriptportal + */ + + $COURSE->javascriptportal = new jsportal(); + + print_require_js(Array("yui_yahoo","yui_dom","yui_event","yui_dragdrop","yui_connection","ajaxcourse_blocks","ajaxcourse_sections","ajaxcourse_topic")); + + //javascript logging facilities + if($CFG->debug)print_require_js(Array("yui_logger")); + } + + } + + +/// Layout the whole page as three big columns. + echo ''; + +/// The left column ... + + if (blocks_have_content($pageblocks, BLOCK_POS_LEFT) || $editing) { + echo ''; + } + +/// Start main column + echo ''; + + // The right column + if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT) || $editing) { + echo ''; + } + + echo '
'; + blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT); + echo ''; + + print_heading_block(get_string('topicoutline'), 'outline'); + + echo ''; + +/// If currently moving a file then show the current clipboard + if (ismoving($course->id)) { + $stractivityclipboard = strip_tags(get_string('activityclipboard', '', addslashes($USER->activitycopyname))); + $strcancel= get_string('cancel'); + echo ''; + echo ''; + echo ''; + } + +/// Print Section 0 + + $section = 0; + $thissection = $sections[$section]; + + if ($thissection->summary or $thissection->sequence or isediting($course->id)) { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + + +/// Now all the normal modules by topic +/// Everything below uses "section" terminology - each "section" is a topic. + + $timenow = time(); + $section = 1; + $sectionmenu = array(); + + while ($section <= $course->numsections) { + + if (!empty($sections[$section])) { + $thissection = $sections[$section]; + + } else { + unset($thissection); + $thissection->course = $course->id; // Create a new section structure + $thissection->section = $section; + $thissection->summary = ''; + $thissection->visible = 1; + if (!$thissection->id = insert_record('course_sections', $thissection)) { + notify('Error inserting new topic!'); + } + } + + $showsection = (isteacher($course->id) or $thissection->visible or !$course->hiddensections); + + if (!empty($displaysection) and $displaysection != $section) { + if ($showsection) { + $strsummary = strip_tags(format_string($thissection->summary,true)); + if (strlen($strsummary) < 57) { + $strsummary = ' - '.$strsummary; + } else { + $strsummary = ' - '.substr($strsummary, 0, 60).'...'; + } + $sectionmenu['topic='.$section] = s($section.$strsummary); + } + $section++; + continue; + } + + if ($showsection) { + + $currenttopic = ($course->marker == $section); + + if (!$thissection->visible) { + $sectionstyle = ' hidden'; + } else if ($currenttopic) { + $sectionstyle = ' current'; + } else { + $sectionstyle = ''; + } + + echo ''; + echo ''; + + echo ''; + + echo ''; + echo ''; + } + + $section++; + } + echo '
'; + echo $stractivityclipboard.'  ('.$strcancel.')'; + echo '
 '; + + echo '
'; + $summaryformatoptions->noclean = true; + echo format_text($thissection->summary, FORMAT_HTML, $summaryformatoptions); + + //Accessibility: added Alt, filled empty Alt-link text. + if (isediting($course->id)) { + echo ''.$streditsummary.'

'; + } + echo '
'; + + print_section($course, $thissection, $mods, $modnamesused); + + if (isediting($course->id)) { + print_section_add_menus($course, $section, $modnames); + } + + echo '
 
'.$section.''; + if (!isteacher($course->id) and !$thissection->visible) { // Hidden for students + echo get_string('notavailable'); + } else { + echo '
'; + $summaryformatoptions->noclean = true; + echo format_text($thissection->summary, FORMAT_HTML, $summaryformatoptions); + + if (isediting($course->id)) { + echo ' '. + ''.$streditsummary.'

'; + } + echo '
'; + + print_section($course, $thissection, $mods, $modnamesused); + + if (isediting($course->id)) { + print_section_add_menus($course, $section, $modnames); + } + } + echo '
'; + if ($displaysection == $section) { // Show the zoom boxes + echo ''. + ''.$strshowalltopics.'
'; + } else { + $strshowonlytopic = get_string('showonlytopic', '', $section); + echo ''. + ''.$strshowonlytopic.'
'; + } + + if (isediting($course->id)) { + if ($course->marker == $section) { // Show the "light globe" on/off + echo ''. + ''.$strmarkedthistopic.'
'; + } else { + echo ''. + ''.$strmarkthistopic.'
'; + } + + if ($thissection->visible) { // Show the hide/show eye + echo ''. + ''.$strtopichide.'
'; + } else { + echo ''. + ''.$strtopicshow.'
'; + } + + if ($section > 1) { // Add a arrow to move section up + echo ''. + ''.$strmoveup.'
'; + } + + if ($section < $course->numsections) { // Add a arrow to move section down + echo ''. + ''.$strmovedown.'
'; + } + + } + + echo '
'; + + if (!empty($sectionmenu)) { + echo '
'; + echo popup_form($CFG->wwwroot.'/course/view.php?id='.$course->id.'&', $sectionmenu, + 'sectionmenu', '', get_string('jumpto'), '', '', true); + echo '
'; + } + + + echo '
'; + blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT); + echo '
'; + + //create javascript portal code + if (!empty($COURSE->javascriptportal)) { + $COURSE->javascriptportal->print_javascript($course->id); + } + +?> diff --git a/lib/ajax/ajaxlib.php b/lib/ajax/ajaxlib.php new file mode 100644 index 0000000000..818bb8b283 --- /dev/null +++ b/lib/ajax/ajaxlib.php @@ -0,0 +1,84 @@ + "/lib/yui/yahoo/yahoo.js", + "yui_dom" => "/lib/yui/dom/dom.js", + "yui_event" => "/lib/yui/event/event.js", + "yui_dragdrop" => "/lib/yui/dragdrop/dragdrop.js", + "yui_logger" => "/lib/yui/logger/logger.js", + "yui_connection" => "/lib/yui/connection/connection.js", + "ajaxcourse_blocks" => "/lib/ajax/block_classes.js", + "ajaxcourse_sections" => "/lib/ajax/section-resource_classes.js", + "ajaxcourse_topic" => "/course/format/topicsajax/ajaxcourse-topics.js", + "ajaxcourse_week" => "/course/format/weeksajax/ajaxcourse-weeks.js" + ); + + + for ($i=0;$i\n\r"; + } else { + echo "\n\r"; + } + } + +} + +//used to create view of document to be passed to javascript on pageload +class jsportal{ + + var $currentblocksection = null; + var $blocks = array(); + var $sections = array(); + + + //takes id of block and adds it + function block_add($id,$hidden=false){ + $hidden_binary = 0; + + if ($hidden) { + $hidden_binary = 1; + } + + $this->blocks[count($this->blocks)] = Array($this->currentblocksection,$id,$hidden_binary); + } + + + function print_javascript($id) { + global $CFG; + + $blocksoutput = ''; + for ($i=0;$iblocks);$i++){ + $blocksoutput.="['".$this->blocks[$i][0]."','".$this->blocks[$i][1]."','".$this->blocks[$i][2]."']"; + if ($i != (count($this->blocks)-1)) { + $blocksoutput.=","; + } + } + + $output =""; + + echo $output; + } + +} + +?> diff --git a/lib/ajax/block_classes.js b/lib/ajax/block_classes.js new file mode 100644 index 0000000000..b78b3ce37e --- /dev/null +++ b/lib/ajax/block_classes.js @@ -0,0 +1,348 @@ +/* + * library for ajaxcourse formats, the classes and related functions for drag and drop blocks + * + * this library requires a 'main' object created in calling document + * + */ + + + //set Drag and Drop to Intersect mode: + YAHOO.util.DDM.mode = YAHOO.util.DDM.INTERSECT; + +/* + * class for draggable block, extends YAHOO.util.DDProxy + */ +function block_class(id,group,config){ + this.init_block(id,group,config); +} +YAHOO.extend(block_class, YAHOO.util.DDProxy); + +block_class.prototype.init_block = function(id, sGroup, config){ + if (!id) { return; } + + //Drag and Drop + this.init(id, sGroup, config); + this.initFrame(); + this.createFrame(); + + this.is = 'block'; + this.instanceId = this.getEl().id.replace(/inst/i,''); + + + this.addInvalidHandleType('a'); + + var s = this.getEl().style; + s.opacity = 0.76; + s.filter = "alpha(opacity=76)"; + + + // specify that this is not currently a drop target + this.isTarget = false; + + this.region = YAHOO.util.Region.getRegion(this.getEl()); + + this.type = block_class.TYPE; + + + //DHTML + this.viewbutton = null; + this.originalClass = this.getEl().className; + + this.init_buttons(); + + this.debug = false; + } + +block_class.prototype.startDrag = function(x, y) { + //operates in intersect mode + YAHOO.util.DDM.mode = YAHOO.util.DDM.INTERSECT; + + YAHOO.log(this.id + " startDrag"); + + var dragEl = this.getDragEl(); + var clickEl = this.getEl(); + + dragEl.innerHTML = clickEl.innerHTML; + dragEl.className = clickEl.className; + dragEl.style.color = this.DDM.getStyle(clickEl, "color");; + dragEl.style.backgroundColor = this.DDM.getStyle(clickEl, "backgroundColor"); + + var s = clickEl.style; + s.opacity = .1; + s.filter = "alpha(opacity=10)"; + + var targets = YAHOO.util.DDM.getRelated(this, true); + YAHOO.log(targets.length + " targets"); + + //restyle side boxes to highlight + for (var i=0; i