Skip to content

Commit

Permalink
MDL-21402 new js_writer abstraction + otehr minor improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
skodak committed Jan 20, 2010
1 parent f5de8ee commit 227255b
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 80 deletions.
106 changes: 34 additions & 72 deletions lib/ajax/ajaxlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ class page_requirements_manager {
* @var array of moodle_url
*/
protected $css_urls = array();

/**
* List of requested event handlers
* @var array
*/
protected $eventhandlers = array();

protected $variablesinitialised = array('mstr' => 1); // 'mstr' is special. See string_for_js.

protected $headdone = false;
Expand Down Expand Up @@ -196,7 +201,7 @@ protected function add_yui2_modules() {
* @param moodle_page $page
* @param core_renderer $output
*/
protected function init_requirements_data(moodle_page $page, core_renderer $output) {
protected function init_requirements_data(moodle_page $page, core_renderer $renderer) {
global $CFG;

// JavaScript should always work with $CFG->httpswwwroot rather than $CFG->wwwroot.
Expand All @@ -208,7 +213,7 @@ protected function init_requirements_data(moodle_page $page, core_renderer $outp
$config = array(
'wwwroot' => $CFG->httpswwwroot, // Yes, really. See above.
'sesskey' => sesskey(),
'loadingicon' => $output->pix_url('i/loading_small', 'moodle')->out(false),
'loadingicon' => $renderer->pix_url('i/loading_small', 'moodle')->out(false),
'themerev' => theme_get_revision(),
'theme' => $page->theme->name,
'yui2loaderBase' => $this->yui2loader->base,
Expand All @@ -223,6 +228,7 @@ protected function init_requirements_data(moodle_page $page, core_renderer $outp
$config['developerdebug'] = true;
}
$this->data_for_js('moodle_cfg', $config)->in_head();
$this->data_for_js('yui3loader', null)->in_head();

if (debugging('', DEBUG_DEVELOPER)) {
$this->yui2_lib('logger');
Expand Down Expand Up @@ -586,12 +592,22 @@ public function data_for_js($variable, $data) {
* @param string $event A valid DOM event (click, mousedown, change etc.)
* @param string $function The name of the function to call
* @param array $arguments An optional array of argument parameters to pass to the function
* @return required_event_handler The event_handler object
* @return void
*/
public function event_handler($selector, $event, $function, array $arguments = null) {
$requirement = new required_event_handler($this, $selector, $event, $function, $arguments);
$this->requiredjscode[] = $requirement;
return $requirement;
$this->eventhandlers[] = array('selector'=>$selector, 'event'=>$event, 'function'=>$function, 'arguments'=>$arguments);
}

/**
* Returns code needed for registering of event handlers.
* @return string JS code
*/
protected function get_event_handler_code() {
$output = '';
foreach ($this->eventhandlers as $h) {
$output .= js_writer::event_handler($h['selector'], $h['event'], $h['function'], $h['arguments']);
}
return $output;
}

/**
Expand Down Expand Up @@ -717,10 +733,10 @@ protected function get_css_code() {
*
* @return string the HTML code to to inside the <head> tag.
*/
public function get_head_code(moodle_page $page, core_renderer $output) {
public function get_head_code(moodle_page $page, core_renderer $renderer) {
// note: the $page and $output are not stored here because it would
// create circular references in memory which prevents garbage collection
$this->init_requirements_data($page, $output);
$this->init_requirements_data($page, $renderer);

// yui3 JS and CSS is always loaded first - it is cached in browser
$output = $this->get_yui3lib_headcode();
Expand Down Expand Up @@ -784,7 +800,8 @@ public function get_end_code() {

// set up global YUI3 loader object - this should contain all code needed by plugins
// note: in JavaScript just use "YUI(yui3loader).use('overlay', function(Y) { .... });"
$output .= $this->data_for_js('yui3loader', $this->json_yui3loader)->now();
// this needs to be done before including any other script
$output .= html_writer::script(js_writer::set_variable('yui3loader', $this->json_yui3loader, false));

// now print all the stuff that was added through ->requires
$output .= $this->get_linked_resources_code(self::WHEN_AT_END);
Expand All @@ -798,16 +815,18 @@ public function get_end_code() {
$inyuijs = $this->get_javascript_code(self::WHEN_IN_YUI, ' ');
$ondomreadyjs = $this->get_javascript_code(self::WHEN_ON_DOM_READY, ' ');
$jsinit = $this->get_javascript_init_code();

//TODO: do we really need the global "Y" defined in javasecript-static.js?
// The problem is that we can not rely on it to be fully initialised
$handlersjs = $this->get_event_handler_code();

// the global Y can be used only after it is fully loaded, that means
// from code executed from the following block
$js .= <<<EOD
Y = YUI(yui3loader).use('node-base', function(Y) {
$inyuijs ;
Y.on('domready', function() {
$ondomreadyjs
});
$jsinit
$handlersjs
});
EOD;

Expand Down Expand Up @@ -1128,15 +1147,7 @@ public function __construct(page_requirements_manager $manager, $function, $argu
}

public function get_js_code() {
$quotedargs = array();
foreach ($this->arguments as $arg) {
$quotedargs[] = json_encode($arg);
}
$js = $this->function . '(' . implode(', ', $quotedargs) . ');';
if ($this->delay) {
$js = 'setTimeout(function() { ' . $js . ' }, ' . ($this->delay * 1000) . ');';
}
return $js . "\n";
return js_writer::function_call($this->function, $this->arguments, $this->delay);
}

/**
Expand Down Expand Up @@ -1203,56 +1214,7 @@ public function __construct(page_requirements_manager $manager, $variable, $data
}

public function get_js_code() {
$prefix = 'var ';
if (strpos($this->variable, '.') || strpos($this->variable, '[')) {
$prefix = '';
}
return $prefix . $this->variable . ' = ' . $this->data . ";\n";
}
}

/**
* This class represents a Javascript event handler, listening for a
* specific Event to occur on a DOM element identified by a given selector.
* Do not use {@link in_head()}, etc.
*
* @copyright 2009 Nicolas Connault
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.0
*/
class required_event_handler extends required_js_code {
protected $selector;
protected $event;
protected $function;
protected $args = array();

/**
* Constructor. Normally the class and its subclasses should not be created directly.
* Client code should create them via the page_requirements_manager
* method {@link page_requirements_manager::data_for_js()}.
*
* @param page_requirements_manager $manager the page_requirements_manager we are associated with.
* @param mixed $selector standard YUI selector for elemnts, may be array or string, element id is in the form "#idvalue"
* @param string $event A valid DOM event (click, mousedown, change etc.)
* @param string $function The name of the function to call
* @param array $arguments An optional array of argument parameters to pass to the function
*/
public function __construct(page_requirements_manager $manager, $selector, $event, $function, array $args = null) {
parent::__construct($manager);
$this->when = page_requirements_manager::WHEN_IN_YUI;
$this->selector = $selector;
$this->event = $event;
$this->function = $function;
$this->args = $args;
}

public function get_js_code() {
$selector = json_encode($this->selector);
$output = "Y.on('$this->event', $this->function, $selector, null";
if (!empty($this->args)) {
$output .= ', ' . json_encode($this->args);
}
return $output . ");\n";
return js_writer::set_variable($this->variable, $this->data) . "\n";
}
}

Expand Down
69 changes: 68 additions & 1 deletion lib/outputcomponents.php
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,8 @@ public function add_action(component_action $action) {
}
}

// ==== HTML writer and helper classes, will be probably moved elsewhere ======

// ==== HTML writer and helper classes, will be probably moved elsewhere ======

/**
* Simple html output class
Expand Down Expand Up @@ -552,6 +552,73 @@ public static function script($jscode) {
}
}

// ==== JS writer and helper classes, will be probably moved elsewhere ======

/**
* Simple javascript output class
* @copyright 2010 Petr Skoda
*/
class js_writer {
/**
* Returns javascript code calling the function
* @param string $function function name, can be complex lin Y.Event.purgeElement
* @param array $arguments parameters
* @param int $delay execution delay in seconds
* @return string JS code fragment
*/
public function function_call($function, array $arguments = null, $delay=0) {
$arguments = array_map('json_encode', $arguments);
$arguments = implode(', ', $arguments);
$js = "$function($arguments);";

if ($delay) {
$delay = $delay * 1000; // in miliseconds
$js = "setTimeout(function() { $js }, $delay);";
}
return $js . "\n";
}

/**
* Returns code setting value to variable
* @param string $name
* @param mixed $value json serialised value
* @param bool $usevar add var definition, ignored for nested properties
* @return string JS code fragment
*/
public function set_variable($name, $value, $usevar=true) {
$output = '';

if ($usevar) {
if (strpos($name, '.')) {
$output .= '';
} else {
$output .= 'var ';
}
}

$output .= "$name = ".json_encode($value).";";

return $output;
}

/**
* Writes event handler attaching code
* @param mixed $selector standard YUI selector for elemnts, may be array or string, element id is in the form "#idvalue"
* @param string $event A valid DOM event (click, mousedown, change etc.)
* @param string $function The name of the function to call
* @param array $arguments An optional array of argument parameters to pass to the function
* @return string JS code fragment
*/
public function event_handler($selector, $event, $function, array $arguments = null) {
$selector = json_encode($selector);
$output = "Y.on('$event', $function, $selector, null";
if (!empty($arguments)) {
$output .= ', ' . json_encode($arguments);
}
return $output . ");\n";
}
}


// ===============================================================================================
// TODO: Following components will be refactored soon
Expand Down
2 changes: 1 addition & 1 deletion mod/imscp/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function imscp_print_content($imscp, $cm, $course) {
echo '</div>';
echo '<div id="imscp_navpanel"></div>';

echo $PAGE->requires->js_function_call('imscp_init')->now();
echo js_writer::function_call('imscp_init');
return;
}

Expand Down
4 changes: 3 additions & 1 deletion mod/lesson/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -2921,11 +2921,13 @@ public function get_page_form($type, $arguments) {
* @return array
*/
public function get_add_page_type_links($previd) {
global $OUTPUT;

$links = array();

foreach ($this->types as $type) {
if (($link = $type->add_page_link($previd)) instanceof html_link) {
$links[] = $link;
$links[] = $OUTPUT->link($link);
}
}

Expand Down
6 changes: 3 additions & 3 deletions mod/lesson/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,9 @@ function lesson_clock_block_contents($cmid, $lesson, $timer, $page) {
$content .= '</div>';

$clocksettings = array('starttime'=>$timer->starttime, 'servertime'=>time(),'testlength'=>($lesson->maxtime * 60));
$content .= $page->requires->data_for_js('clocksettings', $clocksettings)->now();
$content .= $page->requires->js('/mod/lesson/timer.js')->now();
$content .= $page->requires->js_function_call('show_clock')->now();
$page->requires->data_for_js('clocksettings', $clocksettings);
$page->requires->js('/mod/lesson/timer.js');
$page->requires->js_function_call('show_clock');

$bc = new block_contents();
$bc->title = get_string('timeremaining', 'lesson');
Expand Down
2 changes: 1 addition & 1 deletion mod/quiz/attempt.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
// A quiz page with a lot of questions can take a long time to load, and we
// want the protection afforded by init_quiz_form immediately, so include the
// JS now.
echo $PAGE->requires->js_function_call('init_quiz_form')->now();
echo js_writer::function_call('init_quiz_form');
echo '<div>';

/// Print all the questions
Expand Down
2 changes: 1 addition & 1 deletion mod/quiz/attemptlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,7 @@ protected function get_end_bits() {
$output = '';
$output .= '<a href="' . s($this->attemptobj->summary_url()) . '" class="endtestlink">' . get_string('endtest', 'quiz') . '</a>';
$output .= $this->attemptobj->get_timer_html();
$output .= $PAGE->requires->js_function_call('quiz_init_attempt_nav')->now();
$output .= js_writer::function_call('quiz_init_attempt_nav');
return $output;
}
}
Expand Down

0 comments on commit 227255b

Please sign in to comment.