Merge lp:~rharding/launchpad/port_inlinehelp_907443 into lp:launchpad

Proposed by Richard Harding on 2012-01-03
Status: Merged
Approved by: Richard Harding on 2012-01-05
Approved revision: no longer in the source branch.
Merged at revision: 14647
Proposed branch: lp:~rharding/launchpad/port_inlinehelp_907443
Merge into: lp:launchpad
Diff against target: 732 lines (+338/-234)
14 files modified
buildout-templates/bin/combine-css.in (+1/-0)
lib/lp/app/javascript/inlinehelp/assets/inlinehelp-core.css (+16/-0)
lib/lp/app/javascript/inlinehelp/assets/skins/sam/inlinehelp-skin.css (+3/-0)
lib/lp/app/javascript/inlinehelp/inlinehelp.js (+132/-0)
lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.html (+31/-0)
lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.js (+138/-0)
lib/lp/app/javascript/overlay/overlay.js (+2/-2)
lib/lp/app/templates/base-layout-macros.pt (+3/-6)
lib/lp/bugs/javascript/buglisting.js (+2/-2)
lib/lp/bugs/javascript/tests/test_buglisting.html (+2/-7)
lib/lp/bugs/javascript/tests/test_buglisting.js (+1/-1)
lib/lp/registry/javascript/structural-subscription.js (+5/-9)
lib/lp/registry/javascript/tests/test_structural_subscription.html (+2/-0)
lib/lp/services/inlinehelp/javascript/inlinehelp.js (+0/-207)
To merge this branch: bzr merge lp:~rharding/launchpad/port_inlinehelp_907443
Reviewer Review Type Date Requested Status
Deryck Hodge (community) 2012-01-03 Approve on 2012-01-05
Review via email: mp+87384@code.launchpad.net

Commit Message

[r=deryck][bug=907443] Port the inlinehelp javascript from mochikit to YUI in lp.app.inlinehelp.

Description of the Change

= Summary =
Move the inline help javascript to YUI. This is in an effort to move towards an all YUI code base as part of Bug #294656.

== Proposed Fix ==
Add a new lp.app.inlinehelp module that can be used for showing the inline help.

== Implementation Details ==
The inlinehelp module adds an InlineHelpOverlay that extends the PrettyOverlay. The iframe for the help content is loaded into that overlay. This brings some consistency to the overlay used.

The init_help method call will build an event delegate on the <body> tag of the page. This helps keep only one event binding for the entire page regardless of how many help objects there are on the page. It can be called over and over as content changes via ajax or other dynamic methods.

== Tests ==
google-chrome lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.html

== Demo and Q/A ==
Click on any help icon (question mark) and the help for that should load centered on the page. A prime example is the heat help during the bug listings. Clicking on the heat icon should load up a scrolling overlay with the help information for bug heat.

== Lint ==
Linting changed files:
  lib/lp/app/javascript/inlinehelp/inlinehelp.js
  lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.js
  lib/lp/app/templates/base-layout-macros.pt

To post a comment you must log in.
Deryck Hodge (deryck) wrote :

This looks really nice overall! It's nice to have this moved off to YUI and have some test coverage. A double win!

There are some minor issues I'd like you to fix up, but will approve the MP, assuming you'll do these.

 * Outdated copyright heading in inlinehelp-skin.css
 * All comments should be formatted as proper sentences.
    (You have lots of lower-case started sentences, with
     no ending punctuation.)

These are, of course, minor things.

One thing I noticed that I'm not sure of, lib/lp/bugs/javascript/tests/test_buglisting.html stubs out a fake initInlineHelp. Since you're work removes this method, should this test fake be updated somehow, just to be consistent?

Otherwise, consider yourself approved! :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildout-templates/bin/combine-css.in'
2--- buildout-templates/bin/combine-css.in 2011-12-06 20:10:56 +0000
3+++ buildout-templates/bin/combine-css.in 2012-01-06 12:41:30 +0000
4@@ -35,6 +35,7 @@
5 'build/autocomplete/assets/skins/sam/autocomplete.css',
6 'build/overlay/assets/skins/sam/pretty-overlay.css',
7 'build/formoverlay/assets/formoverlay-core.css',
8+ 'build/inlinehelp/assets/inlinehelp-core.css',
9 'build/indicator/assets/indicator-core.css',
10 'build/confirmationoverlay/assets/confirmationoverlay-core.css',
11 'build/picker/assets/skins/sam/picker.css',
12
13=== added directory 'lib/lp/app/javascript/inlinehelp'
14=== removed symlink 'lib/lp/app/javascript/inlinehelp'
15=== target was u'../../../lp/services/inlinehelp/javascript'
16=== added directory 'lib/lp/app/javascript/inlinehelp/assets'
17=== added file 'lib/lp/app/javascript/inlinehelp/assets/inlinehelp-core.css'
18--- lib/lp/app/javascript/inlinehelp/assets/inlinehelp-core.css 1970-01-01 00:00:00 +0000
19+++ lib/lp/app/javascript/inlinehelp/assets/inlinehelp-core.css 2012-01-06 12:41:30 +0000
20@@ -0,0 +1,16 @@
21+.yui3-inlinehelp-overlay {
22+ width: 600px;
23+}
24+
25+.yui3-inlinehelp-overlay iframe {
26+ width: 100%;
27+ height: 300px;
28+ border: 0;
29+ padding: 0;
30+ margin: 0;
31+ margin-top: 1em;
32+}
33+
34+.yui3-inlinehelp-overlay-hidden {
35+ visibility: hidden;
36+}
37
38=== added directory 'lib/lp/app/javascript/inlinehelp/assets/skins'
39=== added directory 'lib/lp/app/javascript/inlinehelp/assets/skins/sam'
40=== added file 'lib/lp/app/javascript/inlinehelp/assets/skins/sam/inlinehelp-skin.css'
41--- lib/lp/app/javascript/inlinehelp/assets/skins/sam/inlinehelp-skin.css 1970-01-01 00:00:00 +0000
42+++ lib/lp/app/javascript/inlinehelp/assets/skins/sam/inlinehelp-skin.css 2012-01-06 12:41:30 +0000
43@@ -0,0 +1,3 @@
44+/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
45+
46+/* Placeholder for skinning of the InlineHelp Overlay Widget */
47
48=== added file 'lib/lp/app/javascript/inlinehelp/inlinehelp.js'
49--- lib/lp/app/javascript/inlinehelp/inlinehelp.js 1970-01-01 00:00:00 +0000
50+++ lib/lp/app/javascript/inlinehelp/inlinehelp.js 2012-01-06 12:41:30 +0000
51@@ -0,0 +1,132 @@
52+/**
53+ * Copyright 2011 Canonical Ltd. This software is licensed under the
54+ * GNU Affero General Public License version 3 (see the file LICENSE).
55+ *
56+ * @module lp.app.inlinehelp
57+ *
58+ * Usage:
59+ * lp.app.inlinehelp.init_help();
60+ *
61+ */
62+YUI.add('lp.app.inlinehelp', function (Y) {
63+
64+ var module = Y.namespace('lp.app.inlinehelp');
65+ var HELP_LINK_SELECTOR = 'a[target=help]';
66+ var HELP_CSS = 'help';
67+ var CLICK_DELEGATE = false;
68+
69+ /**
70+ * Handle the clicking of a help link in the body.
71+ * This is a delegated handler so this == the object clicked.
72+ *
73+ * @method _show_help
74+ * @private
75+ */
76+ module._show_help = function (e) {
77+ e.preventDefault();
78+ var target_link = e.currentTarget;
79+
80+ // init the overlay and show it
81+ var overlay = new module.InlineHelpOverlay({
82+ 'contentUrl': target_link.get('href'),
83+ 'centered': true,
84+ 'constrain': true,
85+ // we need our help overlay to have a higher zindex than usual
86+ // overlays so that any help on them appear above them
87+ 'zIndex': 1050
88+ });
89+ overlay.render();
90+ };
91+
92+ /**
93+ * The single entry point used to bind the buttons for launching help.
94+ *
95+ * @method init_help
96+ * @public
97+ */
98+ module.init_help = function () {
99+ // Find the help links.
100+ var links = Y.all(HELP_LINK_SELECTOR);
101+
102+ // Add the help class.
103+ links.addClass(HELP_CSS);
104+
105+ // Bind the click events but unbind it first in case we're re-running
106+ // init more than once (say on ajax loading of new help content).
107+ var body = Y.one('body');
108+ if (CLICK_DELEGATE !== false) {
109+ CLICK_DELEGATE.detach();
110+ }
111+ CLICK_DELEGATE = body.delegate(
112+ 'click',
113+ module._show_help,
114+ HELP_LINK_SELECTOR
115+ );
116+ };
117+
118+ module.InlineHelpOverlay = Y.Base.create(
119+ 'inlinehelp-overlay',
120+ Y.lazr.PrettyOverlay,
121+ [],
122+ {
123+ /**
124+ * Generate the iframe used for displaying help content in the
125+ * overlay.
126+ *
127+ * @method _getContent
128+ * @private
129+ */
130+ _getContent: function () {
131+ var help_page = Y.Node.create('<iframe/>');
132+ help_page.set('src', this.get('contentUrl'));
133+
134+ // Use the overlay bodyContent as the home of the iframe.
135+ this.set('bodyContent', help_page);
136+ },
137+
138+ initializer: function (cfg) {
139+ this._getContent();
140+ },
141+
142+ hide: function() {
143+ this.constructor.superclass.hide.call(this);
144+ this.get('boundingBox').setStyle('display', 'none');
145+ },
146+
147+ show: function() {
148+ this.constructor.superclass.show.call(this);
149+ this.get('boundingBox').setStyle('display', 'block');
150+ }
151+ },
152+ {
153+ ATTRS: {
154+ /**
155+ * URI of the location of the help content.
156+ *
157+ * This is loaded into our iFrame and should be a full page vs
158+ * a data payload.
159+ *
160+ * @attribute contentUrl
161+ * @type string
162+ * @default ''
163+ */
164+ contentUrl: {
165+ value: ''
166+ },
167+
168+ /**
169+ * There's no multi steps so hard code the underlying overlays
170+ * bar to false.
171+ *
172+ * @attribute progressbar
173+ * @type bool
174+ * @default false
175+ */
176+ progressbar: {
177+ value: false
178+ }
179+ }
180+ }
181+ );
182+
183+}, "0.1", { "requires": ['lazr.overlay', 'io', 'log'] });
184
185=== added directory 'lib/lp/app/javascript/inlinehelp/tests'
186=== added file 'lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.html'
187--- lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.html 1970-01-01 00:00:00 +0000
188+++ lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.html 2012-01-06 12:41:30 +0000
189@@ -0,0 +1,31 @@
190+<!--
191+Copyright 2011 Canonical Ltd. This software is licensed under the
192+GNU Affero General Public License version 3 (see the file LICENSE).
193+-->
194+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
195+<html>
196+ <head>
197+ <title>Test InlineHelp </title>
198+ <!-- YUI and test setup -->
199+ <script type="text/javascript"
200+ src="../../../../../canonical/launchpad/icing/yui/yui/yui.js">
201+ </script>
202+ <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
203+ <script type="text/javascript"
204+ src="../../../../app/javascript/testing/testrunner.js"></script>
205+
206+ <script type="text/javascript" src="../../overlay/overlay.js"></script>
207+
208+ <!-- The module under test -->
209+ <script type="text/javascript" src="../inlinehelp.js"></script>
210+
211+ <!-- The test suite -->
212+ <script type="text/javascript" src="test_inlinehelp.js"></script>
213+ </head>
214+ <body class="yui3-skin-sam">
215+ <ul id="suites">
216+ <li>lp.app.inlinehelp.test</li>
217+ </ul>
218+ </body>
219+</html>
220+
221
222=== added file 'lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.js'
223--- lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.js 1970-01-01 00:00:00 +0000
224+++ lib/lp/app/javascript/inlinehelp/tests/test_inlinehelp.js 2012-01-06 12:41:30 +0000
225@@ -0,0 +1,138 @@
226+/* Copyright (c) 2011, Canonical Ltd. All rights reserved. */
227+
228+YUI.add('lp.app.inlinehelp.test', function (Y) {
229+
230+ var suite = new Y.Test.Suite('InlineHelp Tests');
231+ var Assert = Y.Assert;
232+ var test_module = Y.namespace('lp.app.inlinehelp.test');
233+
234+ suite.add(new Y.Test.Case({
235+ name: 'inlinehelp.init_help',
236+
237+ setUp: function () {
238+ var link_html = Y.Node.create(
239+ '<a href="/+help-bugs/bug-heat.html" target="help"/>');
240+ Y.one('body').appendChild(link_html);
241+ },
242+
243+ tearDown: function () {
244+ Y.all('a[target="help"]').remove();
245+ Y.one('body').detach('click');
246+ Y.all('.pretty-overlay-window').remove();
247+ },
248+
249+ test_adding_css_class: function () {
250+ // calling init help should add a help css class to all links with
251+ // target=help
252+ var called = false;
253+ Y.lp.app.inlinehelp.init_help();
254+ Y.all('a[target="help"]').each(function (node) {
255+ called = true;
256+ Y.Assert.isTrue(node.hasClass('help'),
257+ 'Each link should have the class "help"');
258+ });
259+
260+ Y.Assert.isTrue(called, 'We should have called our class check');
261+ },
262+
263+ test_binding_click_link: function () {
264+ // calling init help should a delegated click handler for the help
265+ // links
266+
267+ // we need to mock out the inlinehelp.show_help function to add a
268+ // callable to run tests for us when clicked
269+ var orig_show_help = Y.lp.app.inlinehelp._show_help;
270+ var called = false;
271+
272+ Y.lp.app.inlinehelp._show_help = function (e) {
273+ e.preventDefault();
274+ called = true;
275+
276+ Y.Assert.areEqual(e.target.get('target'), 'help',
277+ 'The event target should be our <a> with target = help');
278+ };
279+
280+ Y.lp.app.inlinehelp.init_help();
281+
282+ Y.one('a[target="help"]').simulate('click');
283+ Y.Assert.isTrue(
284+ called,
285+ 'We should have called our show_help function'
286+ );
287+
288+ // restore the original show_help method for future tests
289+ Y.lp.app.inlinehelp._show_help = orig_show_help;
290+ },
291+
292+ test_binding_click_only_once: function () {
293+ //verify that multiple calls to init_help only causes one click
294+ //event to fire
295+ var orig_show_help = Y.lp.app.inlinehelp._show_help;
296+ var called = 0;
297+
298+ Y.lp.app.inlinehelp._show_help = function (e) {
299+ e.preventDefault();
300+ called = called + 1;
301+ };
302+
303+ Y.lp.app.inlinehelp.init_help();
304+ Y.lp.app.inlinehelp.init_help();
305+ Y.lp.app.inlinehelp.init_help();
306+ Y.lp.app.inlinehelp.init_help();
307+
308+ Y.one('a[target="help"]').simulate('click');
309+ Y.Assert.areEqual(
310+ called,
311+ 1,
312+ 'We should have called our show_help function only once'
313+ );
314+ // restore the original show_help method for future tests
315+ Y.lp.app.inlinehelp._show_help = orig_show_help;
316+ },
317+
318+ test_click_gets_overlay: function () {
319+ // clicking on the link should get us an overlay
320+ Y.lp.app.inlinehelp.init_help();
321+ Y.one('a[target="help"]').simulate('click');
322+ Y.Assert.isObject(Y.one('.yui3-inlinehelp-overlay'),
323+ 'Should find a node for the overlay');
324+ },
325+
326+ test_click_get_content: function () {
327+ // if the contentUrl exists, we should get content. Fudge the ajax
328+ // response to return some known html.
329+ var orig_show_help = Y.lp.app.inlinehelp._show_help;
330+ var good_html =
331+ '<iframe src="file:///+help-bugs/bug-heat.html"></iframe>';
332+
333+ Y.lp.app.inlinehelp._show_help = function (e) {
334+ e.preventDefault();
335+ var target_link = e.target;
336+
337+ // init the overlay and show it
338+ overlay = new Y.lp.app.inlinehelp.InlineHelpOverlay({
339+ 'contentUrl': target_link.get('href')
340+ });
341+ overlay.render();
342+ };
343+
344+ Y.lp.app.inlinehelp.init_help();
345+ Y.one('a[target="help"]').simulate('click');
346+
347+ Y.Assert.areEqual(
348+ good_html,
349+ Y.one('.yui3-widget-bd').get('innerHTML'),
350+ 'The body content should be an iframe with our link target'
351+ );
352+
353+ Y.lp.app.inlinehelp._show_help = orig_show_help;
354+ }
355+ }));
356+
357+test_module.suite = suite;
358+
359+}, '0.1', {
360+ 'requires': ['node', 'console', 'test', 'lp.app.inlinehelp',
361+ 'node-event-simulate'
362+ ]
363+});
364
365=== modified file 'lib/lp/app/javascript/overlay/overlay.js'
366--- lib/lp/app/javascript/overlay/overlay.js 2011-06-29 14:56:15 +0000
367+++ lib/lp/app/javascript/overlay/overlay.js 2012-01-06 12:41:30 +0000
368@@ -31,10 +31,10 @@
369 * @class PrettyOverlay
370 * @namespace lazr
371 */
372- var PrettyOverlay = function() {
373+ var PrettyOverlay = function(cfg) {
374 // Check whether the callsite has set a zIndex... if not, set it
375 // to 1000, as the YUI.overlay default is zero.
376- if (arguments[0] && arguments[0].zIndex === undefined){
377+ if (cfg && arguments[0].zIndex === undefined){
378 arguments[0].zIndex = 1000;
379 }
380 PrettyOverlay.superclass.constructor.apply(this, arguments);
381
382=== modified file 'lib/lp/app/templates/base-layout-macros.pt'
383--- lib/lp/app/templates/base-layout-macros.pt 2012-01-03 07:15:56 +0000
384+++ lib/lp/app/templates/base-layout-macros.pt 2012-01-06 12:41:30 +0000
385@@ -115,10 +115,11 @@
386 </script>
387
388 <script id="base-layout-load-scripts" type="text/javascript">
389- LPS.use('node', 'event-delegate', 'lp', 'lp.app.links', 'lp.app.longpoll', function(Y) {
390+ LPS.use('node', 'event-delegate', 'lp', 'lp.app.links', 'lp.app.longpoll',
391+ 'lp.app.inlinehelp', function(Y) {
392 Y.on('load', function(e) {
393 sortables_init();
394- initInlineHelp();
395+ Y.lp.app.inlinehelp.init_help();
396 Y.lp.activate_collapsibles();
397 activateFoldables();
398 activateConstrainBugExpiration();
399@@ -132,10 +133,6 @@
400 Y.later(0, Y.lp.app.longpoll, Y.lp.app.longpoll.setupLongPollManager);
401 }, window);
402
403- // Hook up the function that dismisses the help window if we click
404- // anywhere outside of it.
405- Y.on('click', handleClickOnPage, window);
406-
407 Y.on('lp:context:web_link:changed', function(e) {
408 window.location = e.new_value;
409 });
410
411=== modified file 'lib/lp/bugs/javascript/buglisting.js'
412--- lib/lp/bugs/javascript/buglisting.js 2011-12-16 18:25:29 +0000
413+++ lib/lp/bugs/javascript/buglisting.js 2012-01-06 12:41:30 +0000
414@@ -122,7 +122,7 @@
415 module.BugListingNavigator,
416 Y.lp.app.listing_navigator.ListingNavigator, {
417 _bindUI: function () {
418- initInlineHelp();
419+ Y.lp.app.inlinehelp.init_help();
420 },
421
422 initializer: function(config) {
423@@ -224,5 +224,5 @@
424
425 }, "0.1", {
426 "requires": [
427- "history", "node", 'lp.app.listing_navigator']
428+ "history", "node", 'lp.app.listing_navigator', 'lp.app.inlinehelp']
429 });
430
431=== modified file 'lib/lp/bugs/javascript/tests/test_buglisting.html'
432--- lib/lp/bugs/javascript/tests/test_buglisting.html 2011-12-15 17:09:48 +0000
433+++ lib/lp/bugs/javascript/tests/test_buglisting.html 2012-01-06 12:41:30 +0000
434@@ -1,13 +1,6 @@
435 <html>
436 <head>
437 <title>Bug task listing</title>
438- <script type="text/javascript">
439- // this is a fake out of the global help overlay tool we need to call
440- var initInlineHelp = function () {
441- return;
442- };
443- </script>
444-
445 <!-- YUI and test setup -->
446 <script type="text/javascript"
447 src="../../../../canonical/launchpad/icing/yui/yui/yui.js">
448@@ -24,6 +17,8 @@
449 <script type="text/javascript"
450 src="../../../app/javascript/effects/effects.js"></script>
451 <script type="text/javascript"
452+ src="../../../app/javascript/inlinehelp/inlinehelp.js"></script>
453+ <script type="text/javascript"
454 src="../../../app/javascript/errors.js"></script>
455 <script type="text/javascript"
456 src="../../../app/javascript/expander.js"></script>
457
458=== modified file 'lib/lp/bugs/javascript/tests/test_buglisting.js'
459--- lib/lp/bugs/javascript/tests/test_buglisting.js 2011-12-14 19:23:02 +0000
460+++ lib/lp/bugs/javascript/tests/test_buglisting.js 2012-01-06 12:41:30 +0000
461@@ -2,7 +2,7 @@
462 base: '../../../../canonical/launchpad/icing/yui/',
463 filter: 'raw', combine: false, fetchCSS: false
464 }).use('test', 'console', 'lp.bugs.buglisting', 'lp.testing.mockio',
465- 'lp.testing.assert',
466+ 'lp.testing.assert', 'lp.app.inlinehelp',
467 function(Y) {
468
469 var suite = new Y.Test.Suite("lp.bugs.buglisting Tests");
470
471=== modified file 'lib/lp/registry/javascript/structural-subscription.js'
472--- lib/lp/registry/javascript/structural-subscription.js 2011-12-13 23:52:09 +0000
473+++ lib/lp/registry/javascript/structural-subscription.js 2012-01-06 12:41:30 +0000
474@@ -1133,10 +1133,8 @@
475 Y.one('#subscription-overlay-title')
476 .set('text', 'Edit subscription for '+title+' bugs');
477
478- // We need to initialize the help links. They may have already been
479- // initialized except for the ones we added, so setupHelpTrigger
480- // is idempotent. Notice that this is old MochiKit code.
481- forEach(findHelpLinks(), setupHelpTrigger);
482+ // We need to initialize the help links.
483+ Y.lp.app.inlinehelp.init_help();
484 namespace._add_subscription_overlay.show();
485 }
486
487@@ -1817,10 +1815,8 @@
488 var save_subscription = make_add_subscription_handler(success_callback);
489 create_overlay(config.content_box, overlay_id, submit_button,
490 save_subscription, success_callback);
491- // We need to initialize the help links. They may have already been
492- // initialized except for the ones we added, so setupHelpTrigger
493- // is idempotent. Notice that this is old MochiKit code.
494- forEach(findHelpLinks(), setupHelpTrigger);
495+ // We need to initialize the help links.
496+ Y.lp.app.inlinehelp.init_help();
497 namespace._add_subscription_overlay.show();
498 return overlay_id;
499 }
500@@ -1870,5 +1866,5 @@
501
502 }, '0.1', {requires: [
503 'dom', 'node', 'lp.anim', 'lazr.formoverlay', 'lazr.overlay',
504- 'lazr.effects', 'lp.app.errors', 'lp.client', 'gallery-accordion'
505+ 'lazr.effects', 'lp.app.errors', 'lp.client', 'gallery-accordion', 'lp.app.inlinehelp'
506 ]});
507
508=== modified file 'lib/lp/registry/javascript/tests/test_structural_subscription.html'
509--- lib/lp/registry/javascript/tests/test_structural_subscription.html 2011-08-10 08:43:17 +0000
510+++ lib/lp/registry/javascript/tests/test_structural_subscription.html 2012-01-06 12:41:30 +0000
511@@ -27,6 +27,8 @@
512 <script type="text/javascript"
513 src="../../../app/javascript/extras/extras.js"></script>
514 <script type="text/javascript"
515+ src="../../../app/javascript/inlinehelp/inlinehelp.js"></script>
516+ <script type="text/javascript"
517 src="../../../contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion.js">
518 </script>
519 <script type="text/javascript"
520
521=== removed directory 'lib/lp/services/inlinehelp/javascript'
522=== removed file 'lib/lp/services/inlinehelp/javascript/inlinehelp.js'
523--- lib/lp/services/inlinehelp/javascript/inlinehelp.js 2011-03-17 23:25:23 +0000
524+++ lib/lp/services/inlinehelp/javascript/inlinehelp.js 1970-01-01 00:00:00 +0000
525@@ -1,207 +0,0 @@
526-/*
527- * Copyright 2009 Canonical Ltd. This software is licensed under the
528- * GNU Affero General Public License version 3 (see the file LICENSE).
529- *
530- * This script defines functions for popping up a 'Help' dialog for an
531- * external site. All links that have a 'target="help"' attribute will
532- * be turned into pop-up help links. A single popup is present on the
533- * screen at a time - opening another help link will open a new dialog,
534- * and clicking on the same link again closes the dialog.
535- *
536- * This library depends on the MochiKit JavaScript library v1.4+.
537- *
538- */
539-
540-
541-/*
542- * Page Setup
543- */
544-
545-
546-function initInlineHelp() {
547- /*
548- Activate the popup help system by connecting all of the actionable
549- page elements.
550- */
551- // The button is inserted in the page dynamically:
552- // Changed from an <input type=button> to a <button> since
553- // IE8 doesn't handle style.css's input{visibility:inherit} correctly.
554- $('help-close').innerHTML =
555- '<button id="help-close-btn">Close</button>';
556- forEach(findHelpLinks(), setupHelpTrigger);
557- initHelpPane();
558-}
559-
560-function findHelpLinks() {
561- /*
562- Return all of the links in the document that have a target="help"
563- attribute value.
564- */
565- has_help_target = function (elem) {
566- return getNodeAttribute(elem, 'target') == 'help';
567- };
568- return filter(has_help_target,
569- currentDocument().getElementsByTagName('a'));
570-}
571-
572-function setupHelpTrigger(elem) {
573- /*
574- Turn the specified element into a proper help link: add the
575- 'class="help"' attribute if it is missing, and connect the
576- necessary event handlers.
577- */
578- // We want this to be idempotent, so we treat the 'help' class as a
579- // marker.
580- if (!hasElementClass(elem, 'help')) {
581- addElementClass(elem, 'help');
582- connect(elem, 'onclick', handleClickOnHelp);
583- }
584-}
585-
586-
587-/*
588- * Functions for using the help window.
589- */
590-
591-
592-// We need to keep track of last element that triggered a help window.
593-var last_help_trigger = null;
594-
595-
596-function initHelpPane() {
597- /*
598- Link the popup help pane to its events, set its visibility, etc.
599- */
600- connect('help-close-btn', 'onclick', handleClickOnClose);
601- dismissHelp();
602-}
603-
604-function showHelpFor(trigger) {
605- /*
606- Show the help popup for a particular trigger element.
607- */
608-
609- // Assume we are using an <iframe> for the help.
610- // Also assume an <a> tag is the source, and we want to target the
611- // <iframe> at its href.
612-
613- // Let our "Loading..." background gif show through.
614- makeInvisible('help-pane-content');
615-
616- // Set our 'onload' event handler *outside* of the MochiKit.Signal
617- // framework. Normally we should not do this, but we need
618- // to work around a bug where the 'onload' signal falls silent
619- // for all events after the first.
620- $('help-pane-content').onload = handleHelpLoaded;
621-
622- setNodeAttribute('help-pane-content', 'src', trigger.href);
623-
624- var help_pane = $('help-pane');
625-
626- /* The help pane is positioned in the center of the screen: */
627- var viewport_dim = getViewportDimensions();
628- var help_pane_dim = elementDimensions('help-pane');
629- var pos_x = Math.round(viewport_dim.w / 2) - (help_pane_dim.w / 2);
630- var pos_y = Math.round(viewport_dim.h / 2) - (help_pane_dim.h / 2);
631- var viewport_pos = getViewportPosition();
632- pos_y += viewport_pos.y;
633- setElementPosition(help_pane, new Coordinates(pos_x, pos_y));
634- makeVisible(help_pane);
635-
636- // XXX mars 2008-05-19
637- // Work-around for MochiKit bug #274. The previous call to
638- // setElementPosition() sets "style=none;" as a side-effect!!!
639- setStyle(help_pane, {'display': ''});
640-}
641-
642-function dismissHelp() {
643- makeInvisible('help-pane');
644-}
645-
646-function handleClickOnHelp(event) {
647- // We don't want <a> tags to navigate.
648- event.stop();
649- var trigger = event.src();
650-
651- if (!isVisible('help-pane')) {
652- showHelpFor(trigger);
653- } else if (trigger == last_help_trigger) {
654- // Clicking on the same link that opened a help window closes it
655- // again.
656- dismissHelp();
657- } else {
658- // The user clicked on a different help link, so open it instead.
659- dismissHelp();
660- showHelpFor(trigger);
661- }
662- last_help_trigger = trigger;
663-}
664-
665-function handleClickOnClose(event) {
666- // Prevent the <a> tag from navigating.
667- event.stop();
668- dismissHelp();
669-}
670-
671-function handleHelpLoaded(event) {
672- /*
673- Show the help contents after the help <iframe> has finished
674- loading.
675- */
676- makeVisible('help-pane-content');
677-}
678-
679-function handleClickOnPage(event) {
680- /*
681- Check to see if a click was inside a help window. If it wasn't,
682- and the window is open, then dismiss it.
683- */
684- var help = $('help-pane');
685- if (isVisible(help) &&
686- !isInside(event.mouse().page, help)) {
687- dismissHelp();
688- }
689-}
690-
691-
692-/*
693- * Helpers and utility functions.
694- */
695-
696-
697-function toggleVisible(elem) {
698- toggleElementClass("invisible", elem);
699-}
700-
701-function makeVisible(elem) {
702- removeElementClass(elem, "invisible");
703-}
704-
705-function makeInvisible(elem) {
706- addElementClass(elem, "invisible");
707-}
708-
709-function isVisible(elem) {
710- // You may also want to check for:
711- // getElement(elem).style.display == "none"
712- return !hasElementClass(elem, "invisible");
713-}
714-
715-function isInside(point, element) {
716- /*
717- Is 'point' inside the supplied 'element'?
718- */
719- return intersect(point,
720- getElementPosition(element),
721- getElementDimensions(element));
722-}
723-
724-function intersect(point, dim_point, dimensions) {
725- /*
726- Is 'point' inside the box draw by 'dimensions' at point 'dim_point'?
727- */
728- return ((point.x > dim_point.x) &&
729- (point.x < dim_point.x + dimensions.w) &&
730- (point.y > dim_point.y) &&
731- (point.y < dim_point.y + dimensions.h));
732-}