From 2cf81209ff8adb35a8a7b2582a269a8a263c8c55 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Tue, 4 May 2010 08:29:05 +0000 Subject: [PATCH] javascript MDL-22067 Fixed errors with JavaScript openpopup and help icon popups --- lib/javascript-static.js | 306 ++++++++++++---------------------- lib/outputactions.php | 13 +- lib/outputrenderers.php | 12 +- lib/outputrequirementslib.php | 6 +- theme/base/style/core.css | 12 +- 5 files changed, 125 insertions(+), 224 deletions(-) diff --git a/lib/javascript-static.js b/lib/javascript-static.js index dce0f977e21..a72f797c9a4 100644 --- a/lib/javascript-static.js +++ b/lib/javascript-static.js @@ -169,67 +169,6 @@ M.util.CollapsibleRegion.prototype.div = null; */ M.util.CollapsibleRegion.prototype.icon = null; -/** - * Finds all help icons on the page and initiates YUI tooltips for - * each of them, which load a truncated version of the help's content - * on-the-fly asynchronously - */ -M.util.init_help_icons = function(Y) { - Y.use('io', 'yui2-dom', 'yui2-container', function(Y) { - // remove all titles, they would obscure the YUI tooltip - Y.all('span.helplink a').each(function(node) { - node.set('title', ''); - }); - - var iconspans = YAHOO.util.Dom.getElementsByClassName('helplink', 'span'); - var tooltip = new YAHOO.widget.Tooltip('help_icon_tooltip', { - context: iconspans, - showdelay: 1000, - hidedelay: 150, - autodismissdelay: 50000, - underlay: 'none', - zIndex: '1000' - }); - - tooltip.contextTriggerEvent.subscribe( - function(type, args) { - // Fetch help page contents asynchronously - // Load spinner icon while content is loading - var spinner = document.createElement('img'); - spinner.src = M.cfg.loadingicon; - - this.cfg.setProperty('text', spinner); - - var context = args[0]; - - var link = context.getElementsByTagName('a')[0]; - var thistooltip = this; - var ajaxurl = link.href + '&ajax=1'; - - - var cfg = { - method: 'get', - on: { - success: function(id, o, args) { - thistooltip.cfg.setProperty('text', o.responseText); - }, - failure: function(id, o, args) { - var debuginfo = o.statusText; - if (M.cfg.developerdebug) { - o.statusText += ' (' + ajaxurl + ')'; - } - thistooltip.cfg.setProperty('text', debuginfo); - } - } - }; - - var conn = Y.io(ajaxurl, cfg); - } - ); - }); -}; - - /** * Makes a best effort to connect back to Moodle to update a user preference, * however, there is no mechanism for finding out if the update succeeded. @@ -1219,27 +1158,25 @@ function getElementsByClassName(oElm, strTagName, name) { function openpopup(event, args) { - YAHOO.util.Event.preventDefault(event); - - if (M.help_content.instance !== null) { - var id = '#' + args.id; - M.help_content.instance.load_from_openpopup(event, args); - } else { - var fullurl = args.url; - if (!args.url.match(/https?:\/\//)) { - fullurl = M.cfg.wwwroot + args.url; - } - var windowobj = window.open(fullurl,args.name,args.options); - if (!windowobj) { - return true; - } - if (args.fullscreen) { - windowobj.moveTo(0,0); - windowobj.resizeTo(screen.availWidth,screen.availHeight); - } - windowobj.focus(); - return false; + if (event) { + YAHOO.util.Event.preventDefault(event); } + + var fullurl = args.url; + if (!args.url.match(/https?:\/\//)) { + fullurl = M.cfg.wwwroot + args.url; + } + var windowobj = window.open(fullurl,args.name,args.options); + if (!windowobj) { + return true; + } + if (args.fullscreen) { + windowobj.moveTo(0,0); + windowobj.resizeTo(screen.availWidth,screen.availHeight); + } + windowobj.focus(); + + return false; } /* This is only used on a few help pages. */ @@ -1466,132 +1403,103 @@ function hide_item(itemid) { } } -M.help_content = { +M.util.help_icon = { + Y : null, instance : null, - init : function(Y) { - Y.use('overlay', 'io', 'event-mouseenter', 'node', "*", function(Y) { + add : function(Y, properties) { + this.Y = Y; + Y.one('#'+properties.id).on('click', this.display, this, properties); + }, + display : function(event, args) { + event.preventDefault(); + if (M.util.help_icon.instance === null) { + var Y = M.util.help_icon.Y; + Y.use('overlay', 'io', 'event-mouseenter', 'node', function(Y) { + var help_content_overlay = { + overlay : null, + init : function() { - var help_content_overlay = { - overlay : null, - init : function() { - var xy = Y.one('#helpcontent').getXY(); + var closebtn = Y.Node.create(''); - // Create an overlay from markup - this.overlay = new Y.Overlay({ - srcNode : "#helpcontent", - contentBox: '#helpcontent', - width:'400px', - xy:[xy[0] + 200, xy[1] + 300] - }); - this.overlay.render(); - this.overlay.hide(); + // Create an overlay from markup + this.overlay = new Y.Overlay({ + headerContent: closebtn, + bodyContent: '', + width:'400px', + visible : false, + constrain : true + }); + this.overlay.render(Y.one(document.body)); - Y.on("click", Y.bind(this.overlay.show, this.overlay), "#show"); - Y.on("click", Y.bind(this.overlay.hide, this.overlay), "#hide"); - - var menuButton = Y.one(".helplink"), - overlaycontent = this; + closebtn.on('click', this.overlay.hide, this.overlay); - var boundingBox = this.overlay.get("boundingBox"); + var boundingBox = this.overlay.get("boundingBox"); + boundingBox.addClass('helppopup'); - // Hide the menu if the user clicks outside of its content - boundingBox.get("ownerDocument").on("mousedown", function (event) { - var oTarget = event.target; + // Hide the menu if the user clicks outside of its content + boundingBox.get("ownerDocument").on("mousedown", function (event) { + var oTarget = event.target; + var menuButton = Y.one("#"+args.id); - if (!oTarget.compareTo(menuButton) && - !menuButton.contains(oTarget) && - !oTarget.compareTo(boundingBox) && - !boundingBox.contains(oTarget)) { - overlaycontent.overlay.hide(); - } - }); - }, - - load_from_openpopup : function(event, node) { - var spinner = document.createElement('img'); - spinner.src = M.cfg.loadingicon; - this.overlay.set('bodyContent', spinner); - - var positionX = 0; - var positionY = 0; - - if (event.pageX && !Y.UA.chrome) { - positionX = event.pageX; - positionY = event.pageY; - } else if (event.pageX && !Y.UA.chrome) { - positionX = document.getElementById(node['id']).offsetLeft + 200; - positionY = document.getElementById(node['id']).offsetTop + 500; - } else { //chrome browser - positionX = event.clientX + document.body.scrollLeft ; - positionY = document.body.scrollTop; - if (event.clientX > document.body.scrollTop) { - positionY += event.clientY; - } - } - - if (Y.UA.chrome) { - positionX = event.clientX + document.body.scrollLeft ; - positionY = document.body.scrollTop; - if (event.clientX > document.body.scrollTop) { - positionY += event.clientY; - } - } - - var contentwidth = parseInt(this.overlay.get('width')); - var overlayalign = 'right'; - if (document.getElementById('page').offsetWidth <= (positionX + contentwidth )) { - overlayalign = 'left'; - } - - var WidgetPositionAlign = Y.WidgetPositionAlign; - if (overlayalign == 'right') { - this.overlay.set("align", {node:"#" + node['id'], - points:[WidgetPositionAlign.TL, WidgetPositionAlign.RC]}); - } else { - this.overlay.set("align", {node:"#" + node['id'], - points:[WidgetPositionAlign.TR, WidgetPositionAlign.LC]}); - } - - var fullurl = node.url; - if (!node.url.match(/https?:\/\//)) { - fullurl = M.cfg.wwwroot + node.url; - } - - var ajaxurl = fullurl + '&ajax=1'; - thishelpcontent = this; - - var cfg = { - method: 'get', - on: { - success: function(id, o, node) { - thishelpcontent.load_from_openpopup_callback(o.responseText); - }, - failure: function(id, o, node) { - var debuginfo = o.statusText; - if (M.cfg.developerdebug) { - o.statusText += ' (' + ajaxurl + ')'; - } - thishelpcontent.load_from_openpopup_callback('bodyContent',debuginfo); + if (!oTarget.compareTo(menuButton) && + !menuButton.contains(oTarget) && + !oTarget.compareTo(boundingBox) && + !boundingBox.contains(oTarget)) { + this.overlay.hide(); } + }, this); + }, + + display : function(event, args) { + this.overlay.set('bodyContent', Y.Node.create('')); + this.overlay.set("align", {node:"#" + args.id, points:[Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.RC]}); + + var fullurl = args.url; + if (!args.url.match(/https?:\/\//)) { + fullurl = M.cfg.wwwroot + args.url; } - }; - - var conn = Y.io(ajaxurl, cfg); - this.overlay.show(); - }, - - load_from_openpopup_callback : function(content) { - this.overlay.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE); - }, - - hideContent : function() { - help = this; - help.overlay.hide(); - } - } - help_content_overlay.init(); - M.help_content.instance = help_content_overlay; - - }); + + var ajaxurl = fullurl + '&ajax=1'; + + var cfg = { + method: 'get', + context : this, + on: { + success: function(id, o, node) { + this.display_callback(o.responseText); + }, + failure: function(id, o, node) { + var debuginfo = o.statusText; + if (M.cfg.developerdebug) { + o.statusText += ' (' + ajaxurl + ')'; + } + this.display_callback('bodyContent',debuginfo); + } + } + }; + + Y.io(ajaxurl, cfg); + this.overlay.show(); + }, + + display_callback : function(content) { + this.overlay.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE); + }, + + hideContent : function() { + help = this; + help.overlay.hide(); + } + } + help_content_overlay.init(); + M.util.help_icon.instance = help_content_overlay; + M.util.help_icon.instance.display(event, args); + }); + } else { + M.util.help_icon.instance.display(event, args); + } + }, + init : function(Y) { + this.Y = Y; } } diff --git a/lib/outputactions.php b/lib/outputactions.php index 7fbde60c57e..908ec17972c 100644 --- a/lib/outputactions.php +++ b/lib/outputactions.php @@ -96,6 +96,9 @@ class confirm_action extends component_action { * @since Moodle 2.0 */ class popup_action extends component_action { + + public $jsfunction = 'openpopup'; + /** * @var array $params An array of parameters that will be passed to the openpopup JS function */ @@ -122,7 +125,7 @@ class popup_action extends component_action { * @param array $params An array of popup parameters * @return void */ - public function __construct($event, $url, $name='popup', $params=array()) { + public function __construct($event, $url, $name='popup', $params=array()) { global $CFG; $this->name = $name; @@ -145,10 +148,7 @@ class popup_action extends component_action { } $attributes = array('url' => $url->out(false), 'name' => $name, 'options' => $this->get_js_options($params)); - if (array_key_exists('id', $params)) { - $attributes['id'] = $params['id']; - } - parent::__construct($event, 'openpopup', $attributes); + parent::__construct($event, $this->jsfunction, $attributes); } /** @@ -172,5 +172,4 @@ class popup_action extends component_action { return $jsoptions; } -} - +} \ No newline at end of file diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index faf66ee17fd..131b959c680 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -62,7 +62,7 @@ class renderer_base { * @return string */ public function render(renderable $widget) { - $rendermethod = 'render_'.get_class($widget); + $rendermethod = 'render_'.get_class($widget); if (method_exists($this, $rendermethod)) { return $this->$rendermethod($widget); } @@ -622,10 +622,6 @@ class core_renderer extends renderer_base { global $CFG, $DB; $output = $this->container_end_all(true); - - $helpcontent_body = html_writer::tag('div', '', array('class'=>'helpcontent_body')); - $output .= html_writer::tag('div', $helpcontent_body, array('id'=>'helpcontent', 'class'=>'yui3-overlay-loading')); - $this->page->requires->js_init_call('M.help_content.init'); $footer = $this->opencontainers->pop('header/footer'); @@ -649,7 +645,6 @@ class core_renderer extends renderer_base { $footer = str_replace(self::END_HTML_TOKEN, $this->page->requires->get_end_code(), $footer); $this->page->set_state(moodle_page::STATE_DONE); - return $output . $footer; } @@ -1480,7 +1475,7 @@ END; * @return string HTML fragment */ public function help_icon($identifier, $component = 'moodle', $linktext = '') { - $icon = new help_icon($identifier, $component); + $icon = new help_icon($identifier, $component); $icon->diag_strings(); if ($linktext === true) { $icon->linktext = get_string($icon->identifier, $icon->component); @@ -1527,9 +1522,10 @@ END; $attributes = array('href'=>$url, 'title'=>$title); $id = html_writer::random_id('helpicon'); $attributes['id'] = $id; - $this->add_action_handler(new popup_action('click', $url, 'popup', array('id'=>$id)), $id); $output = html_writer::tag('a', $output, $attributes); + $this->page->requires->js_init_call('M.util.help_icon.add', array(array('id'=>$id, 'url'=>$url->out(false)))); + // and finally span return html_writer::tag('span', $output, array('class' => 'helplink')); } diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 099fbcda1ca..c153c187bbf 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -241,7 +241,7 @@ class page_requirements_manager { } // accessibility stuff - $this->skip_link_to('maincontent', get_string('tocontent', 'access')); + $this->skip_link_to('maincontent', get_string('tocontent', 'access')); // to be removed soon $this->yui2_lib('dom'); // at least javascript-static.js needs to be migrated to YUI3 @@ -936,13 +936,13 @@ class page_requirements_manager { * @return string the HTML code to to at the end of the page. */ public function get_end_code() { - global $CFG; + global $CFG; // add other requested modules $output = $this->get_extra_modules_code(); // add missing YUI2 YUI - to be removed once we convert everything to YUI3! $output .= $this->get_yui2lib_code(); - + // all the other linked scripts - there should be as few as possible if ($this->jsincludes['footer']) { foreach ($this->jsincludes['footer'] as $url) { diff --git a/theme/base/style/core.css b/theme/base/style/core.css index 6ec8bda15c1..322bf6ab844 100644 --- a/theme/base/style/core.css +++ b/theme/base/style/core.css @@ -538,10 +538,8 @@ body.tag .managelink {padding: 5px;} /** * Help Content (pop-up) */ -#helpcontent { background-color: #FFE691; border: 1px solid #848484; z-index: 10; } -#show { margin-left:5px; padding:0; } -#hide { float: right; } -.closehelpbutton { border: none; background: none; } -.yui3-js-enabled .yui3-overlay-loading { top:-1000em; left:-1000em; position:absolute; display: none; } -.yui3-widget-bd { float: none; clear: both; margin: 1em;} -#helpcontent .helpheading {font-size: 1em;} + .helppopup {background-color: #FFE691; border: 1px solid #848484;} + .helppopup .yui3-widget-hd {float:right;margin:3px 3px 0 0;} + .helppopup .yui3-widget-bd {margin:0 1em 1em 1em;border-top:1px solid #FFE691;} + .helppopup .helpheading {font-size: 1em;} + .helppopup .spinner {margin:1em;} \ No newline at end of file