Merge lp:~sinzui/launchpad/progressive-enhancement-ftw into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Approved by: j.c.sackett
Approved revision: no longer in the source branch.
Merged at revision: 15180
Proposed branch: lp:~sinzui/launchpad/progressive-enhancement-ftw
Merge into: lp:launchpad
Diff against target: 646 lines (+245/-134)
17 files modified
lib/lp/app/doc/lazr-js-widgets.txt (+13/-16)
lib/lp/app/javascript/autocomplete/autocomplete.js (+0/-7)
lib/lp/app/javascript/picker/tests/test_personpicker.html (+4/-4)
lib/lp/app/javascript/picker/tests/test_picker_patcher.html (+4/-4)
lib/lp/app/javascript/tests/test_multicheckboxwidget.html (+3/-4)
lib/lp/app/templates/inline-multicheckbox-widget.pt (+10/-9)
lib/lp/app/templates/inline-picker.pt (+15/-19)
lib/lp/bugs/javascript/bugtask_index.js (+1/-1)
lib/lp/bugs/javascript/official_bug_tags.js (+11/-8)
lib/lp/bugs/javascript/tests/test_official_bug_tags.html (+133/-0)
lib/lp/bugs/javascript/tests/test_official_bug_tags.js (+49/-0)
lib/lp/bugs/templates/bugtarget-macros-filebug.pt (+1/-3)
lib/lp/bugs/templates/official-bug-target-manage-tags.pt (+1/-3)
lib/lp/bugs/tests/testfiles/sourceforge-project-fronobulator.html (+0/-45)
lib/lp/bugs/tests/testfiles/sourceforge-tracker-5570.html (+0/-3)
lib/lp/registry/stories/project/xx-project-edit.txt (+0/-3)
lib/lp/registry/templates/product-index.pt (+0/-5)
To merge this branch: bzr merge lp:~sinzui/launchpad/progressive-enhancement-ftw
Reviewer Review Type Date Requested Status
j.c.sackett (community) Approve
Richard Harding (community) code* Approve
Review via email: mp+103733@code.launchpad.net

Commit message

Avoid noscript because it contradicts progressive enhancement assumptions.

Description of the change

Several features fail for less common browsers because noscript is used
for the default markup. When progressive enhancement fails, there is no
default markup to fallback to. YUI assumes progressive enhancement works.

Over the last 3 years, we have seen IE, Opera, Konquorer and Firefox 3
break because progressive enhancement failed without fallback.

This branch fixes half of the issues which prevent users from completing
tasks.

--------------------------------------------------------------------

RULES

    Pre-implementation: wgrant
    * Remove all uses of noscript that have a YUI counterpart.
    * Remove noscript that setups up visibility state.

QA

    These acceptance tests require firefox, chromium, ie8 and knoquorer.
    Also, one browser should have js disabled to verify a plain html link
    is always available:

    Person Picker
    * Visit https://qastaging.launchpad.net/launchpad
    * Verify there is an action change the maintainer and the driver.
      The driver action also has a help link.
    * Verify that the action shows the overlay or html page.

    Person Picker and Picker Patcher
    * Visit https://blueprints.qastaging.launchpad.net/gdp/+spec/gdplaunchpad
    * Verify there the drafter and implementations status can be changed

    Multicheckbox Widget
    * Visit https://code.qastaging.launchpad.net/~sinzui/+recipe/pocket-lint-daily
    * Verify there the distribution series can be changed.

    Official bug tags
    * Visit https://bugs.qastaging.launchpad.net/launchpad/+manage-official-tags
    * Verify the plain html form is shown to non-js browsers.
    * Verify that the js form is shown to js-enabled-browsers

    Project group choose product
    * Visit https://bugs.qastaging.launchpad.net/launchpad-project/+filebug
    * Choose Launchpad, enter a summary, then choose Next.
    * In a js-enabled browser verify the URL says that you are at
      launchpad/+filebug
    * In a non-js browser verify the URL is still at launchpad-project
      and you can see Launchpad selected in the project field

    Configuration Progress
    * Visit https://qastaging.launchpad.net/launchpad/
    * In a js-enabled browser, verify the Configuration Progress is shown,
      /but/ the applications are collapsed.
    * In a non-js browser, verify the Configuration Progress is shown,
      /and/ the applications are shown too.

    File Bug Extra Options
    * Visit https://bugs.qastaging.launchpad.net/launchpad/+filebug
    * Enter 'athena' in the summary summary and choose Next.
    * In a js-enabled browser, verify extra options is collapsed.
    * In a non-js browser, verify the extra options are visible.

LINT

    lib/lp/app/doc/lazr-js-widgets.txt
    lib/lp/app/javascript/picker/tests/test_personpicker.html
    lib/lp/app/javascript/picker/tests/test_picker_patcher.html
    lib/lp/app/javascript/tests/test_multicheckboxwidget.html
    lib/lp/app/templates/inline-multicheckbox-widget.pt
    lib/lp/app/templates/inline-picker.pt
    lib/lp/bugs/javascript/official_bug_tags.js
    lib/lp/bugs/javascript/tests/test_official_bug_tags.html
    lib/lp/bugs/javascript/tests/test_official_bug_tags.js
    lib/lp/bugs/templates/bugtarget-macros-filebug.pt
    lib/lp/bugs/templates/official-bug-target-manage-tags.pt
    lib/lp/registry/templates/product-index.pt

TEST

    ./bin/test -vv -t lazr-js-widgets lp.app.tests.test_doc
    ./bin/test -vv --layer=YUItest lp.app
    ./bin/test -vv --layer=YUItest lp.bugs

IMPLEMENTATION

The picker, the patcher and multicheckbox widget all used a button for
js browsers, and an anchor for non-js browsers. All three cases were
fixed by replacing the button with the anchor and adding "lazr-btn
yui3-activator-act" to the class. Note that the inline edit picker
doctest was wrong...it never tested that the widget rendered in edit
mode with all the proper css! Two of the widget templates needed a root
element so that I could lint them.
    lib/lp/app/doc/lazr-js-widgets.txt
    lib/lp/app/javascript/picker/tests/test_personpicker.html
    lib/lp/app/javascript/picker/tests/test_picker_patcher.html
    lib/lp/app/javascript/tests/test_multicheckboxwidget.html
    lib/lp/app/templates/inline-multicheckbox-widget.pt
    lib/lp/app/templates/inline-picker.pt

I removed the noscript around the plain official bug tags html form and
added a line to the script to hide the html form when setup completes.
Alas there was no YUI test for the script, and the script had lint. I
did the minimum to hush lint and test my line of code.
    lib/lp/bugs/javascript/official_bug_tags.js
    lib/lp/bugs/javascript/tests/test_official_bug_tags.html
    lib/lp/bugs/javascript/tests/test_official_bug_tags.js
    lib/lp/bugs/templates/official-bug-target-manage-tags.pt

I removed the noscript from the product widget because it is only shown
on the project group page. It might have been needed in the past, but
users with js browsers cannot see it anyway because when you make your
selection, your browser changes the context to the real product, so Lp
was hiding the widget on a page that js users never load. See below for
the explanation of why 'unseen' is not needed.
    lib/lp/bugs/templates/bugtarget-macros-filebug.pt

The lp.app.expander module is our friend. It handles the setup and
fallback rules for blocks with the 'collapsible' class. Pages and
scripts do not need to set the initial state of visibility or add rules
to ensure non-js browsers can see the block. I removed the 'unseen'
class from +filebug extra options and the css redefines for collapsible
because the markup is visible by default. These rules are cruft that
could have been removed when we enabled lp.app.expander lp.app.expander.
    lib/lp/registry/templates/product-index.pt

To post a comment you must log in.
Revision history for this message
Richard Harding (rharding) wrote :

Thanks for this. I really love to see this noscript stuff die in a fire. A few comments and info to look into. I'm going to mark as needs fixing mainly based on our irc conversation and the alt text note below.

- wgrant brought up that a div in span tag (line #24) isn't valid. This appears to 'run deep' though in the layout and I'm worried that the activator message box bits will break if it's not a div. Can you investigate? Can we just make it another span and css that up to be a display: block to make it quick/easy to update? This will require checking the css and the js for relying on the div bit in selectors and such for both classes yui3-activator-message-box and yui3-activator-hidden

- Should we be adding alt text to the <a links? Not sure if screen readers will do title if alt not there, etc. In doing a quick google, it seems many by default will not read title, but alt. Title is handy for hover in browsers though. I see comments that adding both with the same informationis bad though. The idea is that alt says what something *is* while title says where it'll go if clicked? So for the edit links, it might be an alt says 'edit button' while the title text would be 'edit object xxx'.

- Discussed in irc the implications of having the <a tags all invisible-link, in particular for non-js users and non-graphical users.

- #239 the link goes out to egg?
- #407 if the unseen css class isn't needed is the div needed at all?

review: Needs Fixing (code*)
Revision history for this message
Curtis Hovey (sinzui) wrote :

We, well myself and former members of the registry team, tried to solve the div span issue. It is tricky work. The root issues is that HTML and Lp require all widgets to work as inline elements because they can be placed in markup that only permits inline elements, such as a paragraph. This work is out of scope for this branch. I believe we have a better chance of fixing this issue now that Lp intends to be HTML5. I think we want to switch everything to span and use inline-blocks when needed.

I agree that we want titles on the links.

Yes, we have code that declares that it uses a module that is in an egg.

The container element is needed so that lp.app.expander can find the second chunk and add the lazr-closed class.

Revision history for this message
Curtis Hovey (sinzui) wrote :

Hi Rick.

I think I already answered your first question.

I reviewed the changes I made...Lp is already providing a title for all the links. The title attribute was introduced in HTML 3.0 and enforced in HTML 3.2 in 1997. All screen readers support title because it is a valid attribute for all HTML elements. The alt attribute is historical and only used by img, applet, area, and input. We do not want to add an invalid attribute.

Yes we have two modules that import widget-position-ext, autocomplete and official_bug_tags. The calls are commented out in autocomplete, and official_bug_tag now uses WidgetPosition.CC. Maybe the code was updated to use the standard lib when .CC was moved into it. We do not need widget-position-ext. I removed the remaining calls to it. I added a test (because I already took the painful step of adding a test module) to demonstrate that the bug tag error message is shown.

As for the container element in a collapsible, it is needed so that lp.app.expander can find the second chunk and add the lazr-closed class.

Revision history for this message
Richard Harding (rharding) wrote :

Thanks Curtis, appreciate the changes.

review: Approve (code*)
Revision history for this message
j.c.sackett (jcsackett) wrote :

I have nothing to add. Noscript is terrible, and I'm happy to see it go away.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/app/doc/lazr-js-widgets.txt'
--- lib/lp/app/doc/lazr-js-widgets.txt 2012-04-10 14:01:17 +0000
+++ lib/lp/app/doc/lazr-js-widgets.txt 2012-04-28 03:06:27 +0000
@@ -249,18 +249,20 @@
249huge, the different items are shown in the normal paginated way for the user249huge, the different items are shown in the normal paginated way for the user
250to select.250to select.
251251
252 >>> owner = IArchive['owner']252 >>> ignore = login_person(product.owner)
253 >>> widget = InlineEditPickerWidget(archive, owner, default_text)253 >>> owner = IProduct['owner']
254 >>> widget = InlineEditPickerWidget(product, owner, default_text)
254 >>> print widget()255 >>> print widget()
255 <span id="edit-owner">256 <span id="edit-owner">
256 <span class="yui3-activator-data-box">257 <span class="yui3-activator-data-box">
257 <a...>Eric</a>258 <a href="/~eric" class="sprite person">Eric</a>
258 </span>259 </span>
259 <button class="lazr-btn yui3-activator-act yui3-activator-hidden">260 <span>
260 Edit261 <a class="sprite edit lazr-btn yui3-activator-act"
261 </button>262 href="http://launchpad.dev/widget/+edit"
262 <div class="yui3-activator-message-box yui3-activator-hidden"></div>263 title="">&nbsp;<span class="invisible-link">Edit</span></a>
263 </span>264 <div class="yui3-activator-message-box yui3-activator-hidden"></div>
265 </span> ...
264266
265267
266Picker headings268Picker headings
@@ -462,15 +464,10 @@
462 <span id="edit-distroseries">464 <span id="edit-distroseries">
463 <dt>465 <dt>
464 Recipe distro series466 Recipe distro series
465 <button class="lazr-btn yui3-activator-act yui3-activator-hidden"467 <a class="sprite edit lazr-btn yui3-activator-act"
466 id="edit-distroseries-btn">
467 Edit
468 </button>
469 <noscript>
470 <a class="sprite edit"
471 href="http://code.launchpad.dev/~eric/+recipe/cake_recipe/+edit"468 href="http://code.launchpad.dev/~eric/+recipe/cake_recipe/+edit"
472 title=""></a>469 id="edit-distroseries-btn"
473 </noscript>470 title="">&nbsp;<span class="invisible-link">Edit</span></a>
474 </dt>471 </dt>
475 <span class="yui3-activator-data-box">472 <span class="yui3-activator-data-box">
476 <dl id='edit-distroseries-items'>473 <dl id='edit-distroseries-items'>
477474
=== modified file 'lib/lp/app/javascript/autocomplete/autocomplete.js'
--- lib/lp/app/javascript/autocomplete/autocomplete.js 2012-03-14 12:51:18 +0000
+++ lib/lp/app/javascript/autocomplete/autocomplete.js 2012-04-28 03:06:27 +0000
@@ -661,13 +661,6 @@
661661
662 // We need to calculate the input area's caret position.662 // We need to calculate the input area's caret position.
663 Y.augment(node, Y.lazr.NodeCaretPos);663 Y.augment(node, Y.lazr.NodeCaretPos);
664
665 // Align our position to the input element.
666 //~ this.set('align', {
667 //~ node: node,
668 //~ points: [Y.WidgetPositionExt.TL, Y.WidgetPositionExt.BL]
669 //~ });
670
671 return node;664 return node;
672 },665 },
673666
674667
=== modified file 'lib/lp/app/javascript/picker/tests/test_personpicker.html'
--- lib/lp/app/javascript/picker/tests/test_personpicker.html 2012-03-14 04:41:36 +0000
+++ lib/lp/app/javascript/picker/tests/test_personpicker.html 2012-04-28 03:06:27 +0000
@@ -70,10 +70,10 @@
70 <span id="pickertest">70 <span id="pickertest">
71 <span>71 <span>
72 A picker widget test72 A picker widget test
73 <button id="edit-pickertest-btn"73 <a id="edit-pickertest-btn"
74 class="lazr-btn yui3-activator-act yui3-activator-hidden">74 class="sprite edit lazr-btn yui3-activator-act"
75 Edit75 href="/fnord/+edit-people"
76 </button>76 >&nbsp;Edit</a>
77 </span>77 </span>
78 <span class="yui3-activator-data-box">78 <span class="yui3-activator-data-box">
79 </span>79 </span>
8080
=== modified file 'lib/lp/app/javascript/picker/tests/test_picker_patcher.html'
--- lib/lp/app/javascript/picker/tests/test_picker_patcher.html 2012-03-14 04:41:36 +0000
+++ lib/lp/app/javascript/picker/tests/test_picker_patcher.html 2012-04-28 03:06:27 +0000
@@ -67,10 +67,10 @@
67 <span id="pickertest">67 <span id="pickertest">
68 <span>68 <span>
69 A picker widget test69 A picker widget test
70 <button id="edit-pickertest-btn"70 <a id="edit-pickertest-btn"
71 class="lazr-btn yui3-activator-act yui3-activator-hidden">71 class="sprite edit lazr-btn yui3-activator-act"
72 Edit72 href="/fnord/+edit-people"
73 </button>73 >&nbsp;Edit</a>
74 </span>74 </span>
75 <span class="yui3-activator-data-box">75 <span class="yui3-activator-data-box">
76 </span>76 </span>
7777
=== modified file 'lib/lp/app/javascript/tests/test_multicheckboxwidget.html'
--- lib/lp/app/javascript/tests/test_multicheckboxwidget.html 2012-03-14 04:41:36 +0000
+++ lib/lp/app/javascript/tests/test_multicheckboxwidget.html 2012-04-28 03:06:27 +0000
@@ -50,10 +50,9 @@
50 <span id="multicheckboxtest">50 <span id="multicheckboxtest">
51 <span>51 <span>
52 A multicheckbox widget test52 A multicheckbox widget test
53 <button id="edit-multicheckboxtest-btn"53 <a id="edit-multicheckboxtest-btn"
54 class="lazr-btn yui3-activator-act yui3-activator-hidden">54 class="sprite edit lazr-btn yui3-activator-act"
55 Edit55 >Edit</a>
56 </button>
57 </span>56 </span>
58 <span class="yui3-activator-data-box">57 <span class="yui3-activator-data-box">
59 <span id="edit-test-items"></span>58 <span id="edit-test-items"></span>
6059
=== modified file 'lib/lp/app/templates/inline-multicheckbox-widget.pt'
--- lib/lp/app/templates/inline-multicheckbox-widget.pt 2012-02-01 15:31:32 +0000
+++ lib/lp/app/templates/inline-multicheckbox-widget.pt 2012-04-28 03:06:27 +0000
@@ -1,18 +1,18 @@
1<tal:root
2 xmlns:tal="http://xml.zope.org/namespaces/tal"
3 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
4 omit-tag="">
1<span tal:define="items view/items|nothing"5<span tal:define="items view/items|nothing"
2 tal:attributes="id view/content_box_id">6 tal:attributes="id view/content_box_id">
3 <tal:label-open-tag replace="structure view/label_open_tag"/>7 <tal:label-open-tag replace="structure view/label_open_tag"/>
4 <span tal:replace="structure view/label"/>8 <span tal:replace="structure view/label"/>
5 <tal:has_choices condition="python:view.has_choices and view.can_write">9 <tal:has_choices condition="python:view.has_choices and view.can_write">
6 <button tal:attributes="id string:${view/content_box_id}-btn"10 <a tal:attributes="id string:${view/content_box_id}-btn;
7 class="lazr-btn yui3-activator-act yui3-activator-hidden">11 href view/edit_url;
8 Edit12 title view/edit_title"
9 </button>13 class="sprite edit lazr-btn yui3-activator-act"
14 >&nbsp;<span class="invisible-link">Edit</span></a>
10 </tal:has_choices>15 </tal:has_choices>
11 <noscript tal:condition="view/can_write">
12 <a tal:attributes="href view/edit_url;
13 title view/edit_title"
14 class="sprite edit"></a>
15 </noscript>
16 <tal:label-close-tag replace="structure view/label_close_tag"/>16 <tal:label-close-tag replace="structure view/label_close_tag"/>
17 <span class="yui3-activator-data-box">17 <span class="yui3-activator-data-box">
18 <tal:items-open-tag replace="structure view/items_open_tag"/>18 <tal:items-open-tag replace="structure view/items_open_tag"/>
@@ -48,3 +48,4 @@
48 }, window);48 }, window);
49});49});
50"/>50"/>
51</tal:root>
5152
=== modified file 'lib/lp/app/templates/inline-picker.pt'
--- lib/lp/app/templates/inline-picker.pt 2012-03-21 01:26:45 +0000
+++ lib/lp/app/templates/inline-picker.pt 2012-04-28 03:06:27 +0000
@@ -1,33 +1,28 @@
1<span tal:attributes="id view/content_box_id">1<tal:root
2 xmlns:tal="http://xml.zope.org/namespaces/tal"
3 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
4 omit-tag="">
5 <span tal:attributes="id view/content_box_id">
2 <span class="yui3-activator-data-box">6 <span class="yui3-activator-data-box">
3 <tal:attribute replace="structure view/default_html"/>7 <tal:attribute replace="structure view/default_html"/>
4 </span>8 </span>
5 <button class="lazr-btn yui3-activator-act yui3-activator-hidden">9 <span tal:condition="view/can_write">
6 Edit
7 </button>
8
9 <a tal:condition="view/help_link"
10 tal:attributes="href view/help_link"
11 target="help"
12 class="sprite maybe">&nbsp;
13 <span class="invisible-link">Driver help</span>
14 </a>
15
16 <noscript tal:condition="view/can_write">
17 <a tal:attributes="href view/edit_url;10 <a tal:attributes="href view/edit_url;
18 title view/edit_title"11 title view/edit_title"
19 class="sprite edit"></a>12 class="sprite edit lazr-btn yui3-activator-act"
13 >&nbsp;<span class="invisible-link">Edit</span></a>
14
20 <a tal:condition="view/help_link"15 <a tal:condition="view/help_link"
21 tal:attributes="href view/help_link"16 tal:attributes="href view/help_link"
22 target="help"17 target="help"
23 class="sprite maybe">&nbsp;18 class="sprite maybe">&nbsp;
24 <span class="invisible-link">Driver help</span>19 <span class="invisible-link">Driver help</span>
25 </a>20 </a>
26 </noscript>21 <div class="yui3-activator-message-box yui3-activator-hidden"></div>
27 <div class="yui3-activator-message-box yui3-activator-hidden"></div>22 </span>
28</span>23 </span>
2924
30<script tal:condition="view/can_write"25 <script tal:condition="view/can_write"
31 tal:content="structure string:26 tal:content="structure string:
32LPJS.use('lp.app.picker', 'lp.client', function(Y) {27LPJS.use('lp.app.picker', 'lp.client', function(Y) {
33 var picker_config = ${view/json_config}28 var picker_config = ${view/json_config}
@@ -41,4 +36,5 @@
41 picker_config);36 picker_config);
42 }, window);37 }, window);
43});38});
44"/>39 "/>
40</tal:root>
4541
=== modified file 'lib/lp/bugs/javascript/bugtask_index.js'
--- lib/lp/bugs/javascript/bugtask_index.js 2012-04-23 23:36:37 +0000
+++ lib/lp/bugs/javascript/bugtask_index.js 2012-04-28 03:06:27 +0000
@@ -1520,7 +1520,7 @@
15201520
15211521
1522}, "0.1", {"requires": ["base", "oop", "node", "event", "io-base",1522}, "0.1", {"requires": ["base", "oop", "node", "event", "io-base",
1523 "json-parse", "substitute", "widget-position-ext",1523 "json-parse", "substitute",
1524 "lazr.formoverlay", "lp.anim", "lazr.base",1524 "lazr.formoverlay", "lp.anim", "lazr.base",
1525 "lazr.overlay", "lazr.choiceedit", "lp.app.picker",1525 "lazr.overlay", "lazr.choiceedit", "lp.app.picker",
1526 "lp.bugs.bugtask_index.portlets.subscription",1526 "lp.bugs.bugtask_index.portlets.subscription",
15271527
=== modified file 'lib/lp/bugs/javascript/official_bug_tags.js'
--- lib/lp/bugs/javascript/official_bug_tags.js 2012-03-15 05:40:30 +0000
+++ lib/lp/bugs/javascript/official_bug_tags.js 2012-04-28 03:06:27 +0000
@@ -54,7 +54,7 @@
54 */54 */
55var sort_tags = function(tags) {55var sort_tags = function(tags) {
56 tags.sort(function(x, y) {56 tags.sort(function(x, y) {
57 if (x.tag == y.tag) {57 if (x.tag === y.tag) {
58 return 0;58 return 0;
59 } else if (x.tag > y.tag) {59 } else if (x.tag > y.tag) {
60 return 1;60 return 1;
@@ -89,7 +89,7 @@
89/**89/**
90 * Get an array of unofficial bug tags and their use count.90 * Get an array of unofficial bug tags and their use count.
91 *91 *
92 * Uses an array of objects representing used tags 92 * Uses an array of objects representing used tags
93 * embedded in the page.93 * embedded in the page.
94 *94 *
95 * @method get_other_bug_tags95 * @method get_other_bug_tags
@@ -298,21 +298,21 @@
298 var new_tag_already_official = false;298 var new_tag_already_official = false;
299 Y.each(official_tags, function(item) {299 Y.each(official_tags, function(item) {
300 new_tag_already_official = (300 new_tag_already_official = (
301 new_tag_already_official || (item.tag == new_tag));301 new_tag_already_official || (item.tag === new_tag));
302 });302 });
303 var new_tag_already_used = false;303 var new_tag_already_used = false;
304 Y.each(other_tags, function(item) {304 Y.each(other_tags, function(item) {
305 new_tag_already_used = (305 new_tag_already_used = (
306 new_tag_already_used || (item.tag == new_tag));306 new_tag_already_used || (item.tag === new_tag));
307 });307 });
308 if (new_tag_already_used) {308 if (new_tag_already_used) {
309 Y.each(other_tags, function(item) {309 Y.each(other_tags, function(item) {
310 if (item.tag == new_tag) {310 if (item.tag === new_tag) {
311 official_tags.push(item);311 official_tags.push(item);
312 }312 }
313 });313 });
314 other_tags = filter_array(other_tags, function(item) {314 other_tags = filter_array(other_tags, function(item) {
315 return item.tag != new_tag;315 return item.tag !== new_tag;
316 });316 });
317 }317 }
318 if (!new_tag_already_official && !new_tag_already_used) {318 if (!new_tag_already_official && !new_tag_already_used) {
@@ -418,7 +418,7 @@
418 Y.one('#new-tag-text').on('keypress', function(e) {418 Y.one('#new-tag-text').on('keypress', function(e) {
419 var new_value = Y.Lang.trim(Y.one('#new-tag-text').get('value'));419 var new_value = Y.Lang.trim(Y.one('#new-tag-text').get('value'));
420 Y.one('#new-tag-add').set('disabled', new_value === '');420 Y.one('#new-tag-add').set('disabled', new_value === '');
421 if (e.keyCode == 13) { // Enter == 13421 if (e.keyCode === 13) { // Enter == 13
422 on_new_tag_add();422 on_new_tag_add();
423 }423 }
424 });424 });
@@ -427,9 +427,12 @@
427 e.halt();427 e.halt();
428 save_tags();428 save_tags();
429 });429 });
430
431 // All went well, hide the plain html form.
432 Y.one('form[name=launchpadform]').setStyle('display', 'none');
430};433};
431}, "0.1", {434}, "0.1", {
432 "requires": [435 "requires": [
433 "array-extras", "node", "substitute", "base", "widget-position-ext",436 "array-extras", "node", "substitute", "base",
434 "collection", "lazr.base", "lazr.overlay"]437 "collection", "lazr.base", "lazr.overlay"]
435});438});
436439
=== added file 'lib/lp/bugs/javascript/tests/test_official_bug_tags.html'
--- lib/lp/bugs/javascript/tests/test_official_bug_tags.html 1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/javascript/tests/test_official_bug_tags.html 2012-04-28 03:06:27 +0000
@@ -0,0 +1,133 @@
1<!DOCTYPE html>
2<!--
3Copyright 2012 Canonical Ltd. This software is licensed under the
4GNU Affero General Public License version 3 (see the file LICENSE).
5-->
6
7<html>
8 <head>
9 <title>Test official_bug_tags</title>
10
11 <!-- YUI and test setup -->
12 <script type="text/javascript"
13 src="../../../../../build/js/yui/yui/yui.js">
14 </script>
15 <link rel="stylesheet"
16 href="../../../../../build/js/yui/console/assets/console-core.css" />
17 <link rel="stylesheet"
18 href="../../../../../build/js/yui/console/assets/skins/sam/console.css" />
19 <link rel="stylesheet"
20 href="../../../../../build/js/yui/test/assets/skins/sam/test.css" />
21
22 <script type="text/javascript"
23 src="../../../../../build/js/lp/app/testing/testrunner.js"></script>
24 <link rel="stylesheet" href="../../../app/javascript/testing/test.css" />
25
26 <!-- Dependencies -->
27 <script type="text/javascript" src="../../../../../build/js/yui/base/base.js"></script>
28 <script type="text/javascript" src="../../../../../build/js/yui/node/node.js"></script>
29 <script type="text/javascript" src="../../../../../build/js/yui/collection/collection.js"></script>
30 <script type="text/javascript" src="../../../../../build/js/yui/collection/array-extras.js"></script>
31 <script type="text/javascript" src="../../../../../build/js/yui/substitute/substitute.js"></script>
32 <script type="text/javascript" src="../../../../../build/js/lp/app/lazr/lazr.js"></script>
33 <script type="text/javascript" src="../../../../../build/js/lp/app/overlay/overlay.js"></script>
34
35 <!-- The module under test. -->
36 <script type="text/javascript" src="../official_bug_tags.js"></script>
37
38 <!-- The test suite. -->
39 <script type="text/javascript" src="test_official_bug_tags.js"></script>
40 </head>
41 <body class="yui3-skin-sam">
42 <ul id="suites">
43 <li>lp.bugs.official_bug_tags.test</li>
44 </ul>
45
46 <div id="fixture"></div>
47
48 <script type="text/javascript">
49 // The page must provide these three global variables.
50 var used_bug_tags = {"trivial": 1, "easy": 1};
51 var official_bug_tags = ["exception", "feature", "ui"];
52 var valid_name_pattern = "^[a-z0-9][a-z0-9\\+\\.\\-]+$";
53 </script>
54
55 <script type="text/x-template" id="form-template">
56 <div>
57 <form name="launchpadform">
58 <input type="text" name="tags" />
59 <input type="submit" name="Save" />
60 </form>
61 </div>
62
63 <table id="layout-table" class="official-tags-layout-table hidden">
64 <tr>
65 <th>Official tags</th>
66 <th></th>
67 <th>Other tags</th>
68 </tr>
69 <tr>
70 <td id="left-column" class="left-column">
71 <div class="list-scrollable-area">
72 <ul id="official-tags-list">
73 </ul>
74 </div>
75 </td>
76 <td id="middle-column" class="middle-column">
77 <input type="submit" value="&larr;"
78 id="add-official-tags" class="arrow-button"
79 disabled="true" />
80 <br />
81 <input type="submit" value="&rarr;;"
82 id="remove-official-tags" class="arrow-button"
83 disabled="true" />
84 <br />
85 <form action="+manage-official-tags" method="post" id="save-form">
86 <input type="hidden"
87 id="field-official_bug_tags"
88 name="field.official_bug_tags" />
89 <input type="hidden" name="field.actions.save" value="Save" />
90 </form>
91 </td>
92 <td id="right-column" class="right-column">
93 <div class="list-scrollable-area">
94 <ul id="other-tags-list">
95 </ul>
96 </div>
97 </td>
98 </tr>
99 <tr>
100 <td class="left-column">
101 <br />
102 <table class="input-field-layout-table">
103 <tr>
104 <td colspan="2">
105 Add a new official tag:
106 </td>
107 </tr>
108 <tr>
109 <td style="width: 100%">
110 <input type="text" id="new-tag-text" style="width: 100%" />
111 </td>
112 <td>
113 <input type="submit" value="Add" id="new-tag-add"
114 disabled="true" />
115 </td>
116 </tr>
117 </table>
118 </td>
119 <td class="middle-column">
120 </td>
121 <td class="right-column">
122 </td>
123 </tr>
124 <tr>
125 <td class="actions" colspan="3">
126 <input type="submit" value="Save" id="save-button"
127 disabled="true" />
128 </td>
129 </tr>
130 </table>
131 </script>
132 </body>
133</html>
0134
=== added file 'lib/lp/bugs/javascript/tests/test_official_bug_tags.js'
--- lib/lp/bugs/javascript/tests/test_official_bug_tags.js 1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/javascript/tests/test_official_bug_tags.js 2012-04-28 03:06:27 +0000
@@ -0,0 +1,49 @@
1YUI().use('lp.testing.runner', 'base', 'test', 'console', 'node',
2 'node-event-simulate', 'lp.bugs.official_bug_tags', function(Y) {
3
4var suite = new Y.Test.Suite("Official Bug Tags Tests");
5var module = Y.lp.bugs.official_bug_tags;
6
7
8suite.add(new Y.Test.Case({
9 name: 'Official Bug Tags',
10
11 setUp: function() {
12 this.fixture = Y.one('#fixture');
13 var tags_form = Y.Node.create(
14 Y.one('#form-template').getContent());
15 this.fixture.appendChild(tags_form);
16 },
17
18 tearDown: function() {
19 if (this.fixture !== null) {
20 this.fixture.empty();
21 }
22 delete this.fixture;
23 },
24
25 test_setup_bug_tags_table: function() {
26 // The bug tags table is visible and the html form is not.
27 module.setup_official_bug_tag_management();
28 html_form = Y.one('[name=launchpadform]');
29 tags_table = Y.one('#layout-table');
30 Y.Assert.areEqual('none', html_form.getStyle('display'));
31 Y.Assert.areEqual('block', tags_table.getStyle('display'));
32 },
33
34 test_on_new_tag_add_display_error: function() {
35 // Adding a tag with an invalid name displays a message.
36 module.setup_official_bug_tag_management();
37 Y.one('#new-tag-text').set('value', 'me!');
38 var new_tag_button = Y.one('#new-tag-add');
39 new_tag_button.set('disabled', false);
40 new_tag_button.simulate('click');
41 var message_overlay = Y.one('.official-tag-error-message');
42 Y.Assert.isNotNull(message_overlay);
43 var tag = message_overlay.one(".official-tag-error-message-value");
44 Y.Assert.isTrue(message_overlay.get('text').indexOf('me!') !== -1);
45 }
46}));
47
48Y.lp.testing.Runner.run(suite);
49});
050
=== modified file 'lib/lp/bugs/templates/bugtarget-macros-filebug.pt'
--- lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2012-04-20 01:12:05 +0000
+++ lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2012-04-28 03:06:27 +0000
@@ -44,12 +44,10 @@
44 </td>44 </td>
45 </tr>45 </tr>
4646
47 <noscript>
48 <tal:product tal:define="widget nocall:view/widgets/product|nothing"47 <tal:product tal:define="widget nocall:view/widgets/product|nothing"
49 tal:condition="widget">48 tal:condition="widget">
50 <metal:widget use-macro="context/@@launchpad_form/widget_row" />49 <metal:widget use-macro="context/@@launchpad_form/widget_row" />
51 </tal:product>50 </tal:product>
52 </noscript>
5351
54 <metal:summary tal:define="widget nocall:view/widgets/title">52 <metal:summary tal:define="widget nocall:view/widgets/title">
55 <metal:row use-macro="context/@@launchpad_form/widget_row" />53 <metal:row use-macro="context/@@launchpad_form/widget_row" />
@@ -66,7 +64,7 @@
66 <td colspan="2">64 <td colspan="2">
67 <fieldset id="filebug-extra-options" class="collapsible">65 <fieldset id="filebug-extra-options" class="collapsible">
68 <legend>Extra options</legend>66 <legend>Extra options</legend>
69 <div class="unseen">67 <div>
70 <table>68 <table>
71 <tal:status69 <tal:status
72 define="widget nocall:view/widgets/status|nothing"70 define="widget nocall:view/widgets/status|nothing"
7371
=== modified file 'lib/lp/bugs/templates/official-bug-target-manage-tags.pt'
--- lib/lp/bugs/templates/official-bug-target-manage-tags.pt 2012-02-01 15:31:32 +0000
+++ lib/lp/bugs/templates/official-bug-target-manage-tags.pt 2012-04-28 03:06:27 +0000
@@ -17,9 +17,7 @@
17 <div metal:fill-slot="main">17 <div metal:fill-slot="main">
18 <div class="yui-g">18 <div class="yui-g">
19 <div class="yui-u first">19 <div class="yui-u first">
20 <noscript>20 <div metal:use-macro="context/@@launchpad_form/form" />
21 <div metal:use-macro="context/@@launchpad_form/form" />
22 </noscript>
2321
24 <script tal:replace="structure view/tags_js_data" />22 <script tal:replace="structure view/tags_js_data" />
25 <script type="text/javascript">23 <script type="text/javascript">
2624
=== modified file 'lib/lp/bugs/tests/testfiles/sourceforge-project-fronobulator.html'
--- lib/lp/bugs/tests/testfiles/sourceforge-project-fronobulator.html 2011-12-19 14:54:37 +0000
+++ lib/lp/bugs/tests/testfiles/sourceforge-project-fronobulator.html 2012-04-28 03:06:27 +0000
@@ -23,48 +23,6 @@
2323
24 <link rel="stylesheet" type="text/css" href="http://static.sourceforge.net/css/phoneix/keepsake.css?secure=0&amp;20080417-1657" media="screen" />24 <link rel="stylesheet" type="text/css" href="http://static.sourceforge.net/css/phoneix/keepsake.css?secure=0&amp;20080417-1657" media="screen" />
25 <link rel="stylesheet" type="text/css" href="http://static.sourceforge.net/css/phoneix/print.css?secure=0&amp;20080417-1657" media="print" />25 <link rel="stylesheet" type="text/css" href="http://static.sourceforge.net/css/phoneix/print.css?secure=0&amp;20080417-1657" media="print" />
26<!-- <script>
27function utmx_section(){}function utmx(){}
28(function(){var k='1291903540',d=document,l=d.location,c=d.cookie;function f(n){
29if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return c.substring(i+n.
30length+1,j<0?c.length:j)}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;
31d.write('<sc'+'ript src="'+
32'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com'
33+'/siteopt.js?v=1&utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='
34+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+
35'" type="text/javascript" charset="utf-8"></sc'+'ript>')})();
36</script>
37<script>
38 var originalUrl = document.location.href;
39 var urlParamsTokenPos = originalUrl.indexOf('?');
40 var hashTokenPos = originalUrl.indexOf('#');
41 var hashString = '';
42
43 if(hashTokenPos > -1){
44 baseUrl = originalUrl.substring(0, hashTokenPos);
45 hashString = originalUrl.substring(hashTokenPos)
46 } else {
47 baseUrl = originalUrl;
48 }
49
50test_url = baseUrl;
51if(test_url.match("/$") == null && test_url.match(".php$") == null){
52 test_url += "/";
53}
54if(urlParamsTokenPos > -1){
55 test_url += "&";
56} else {
57 test_url += "?";
58}
59test_url += "abmode=1";
60test_url += hashString;
61
62</script>
63<script>utmx_section("Redirect Control")</script>
64<script>
65 //document.location = test_url;
66</script>
67</noscript> -->
68 <script type="text/javascript" src="http://static.sourceforge.net/include/jquery/jquery-1.2.6.min.js"></script>26 <script type="text/javascript" src="http://static.sourceforge.net/include/jquery/jquery-1.2.6.min.js"></script>
6927
7028
@@ -628,9 +586,6 @@
628</script>586</script>
629587
630<script type="text/javascript" src="//secure.quantserve.com/quant.js"></script>588<script type="text/javascript" src="//secure.quantserve.com/quant.js"></script>
631<noscript>
632<img src="//secure.quantserve.com/pixel/p-93nPV3-Eb4x22.gif" style="display: none;" border="0" height="1" width="1" alt="Quantcast"/>
633</noscript>
634<!-- End Quantcast tag -->589<!-- End Quantcast tag -->
635590
636591
637592
=== modified file 'lib/lp/bugs/tests/testfiles/sourceforge-tracker-5570.html'
--- lib/lp/bugs/tests/testfiles/sourceforge-tracker-5570.html 2011-12-19 14:54:37 +0000
+++ lib/lp/bugs/tests/testfiles/sourceforge-tracker-5570.html 2012-04-28 03:06:27 +0000
@@ -348,9 +348,6 @@
348</script>348</script>
349349
350<script type="text/javascript" src="//secure.quantserve.com/quant.js"></script>350<script type="text/javascript" src="//secure.quantserve.com/quant.js"></script>
351<noscript>
352<img src="//secure.quantserve.com/pixel/p-93nPV3-Eb4x22.gif" style="display: none;" border="0" height="1" width="1" alt="Quantcast"/>
353</noscript>
354<!-- End Quantcast tag -->351<!-- End Quantcast tag -->
355352
356353
357354
=== modified file 'lib/lp/registry/stories/project/xx-project-edit.txt'
--- lib/lp/registry/stories/project/xx-project-edit.txt 2012-01-15 13:32:27 +0000
+++ lib/lp/registry/stories/project/xx-project-edit.txt 2012-04-28 03:06:27 +0000
@@ -61,11 +61,8 @@
61 Project group information61 Project group information
62 Maintainer:62 Maintainer:
63 Sample Person63 Sample Person
64 Edit
65 Driver:64 Driver:
66 Not yet selected65 Not yet selected
67 Edit
68 Driver help
69 Bug tracker:66 Bug tracker:
70 The Mozilla.org Bug Tracker67 The Mozilla.org Bug Tracker
71 Download RDF metadata68 Download RDF metadata
7269
=== modified file 'lib/lp/registry/templates/product-index.pt'
--- lib/lp/registry/templates/product-index.pt 2012-03-20 03:03:07 +0000
+++ lib/lp/registry/templates/product-index.pt 2012-04-28 03:06:27 +0000
@@ -14,11 +14,6 @@
1414
15<head>15<head>
16 <tal:head-epilogue metal:fill-slot="head_epilogue">16 <tal:head-epilogue metal:fill-slot="head_epilogue">
17 <noscript>
18 <style type="text/css">
19 div.collapsible, div.collapsed {display: block;}
20 </style>
21 </noscript>
22 <tal:uses_launchpad_bugtracker17 <tal:uses_launchpad_bugtracker
23 condition="context/bug_tracking_usage/enumvalue:LAUNCHPAD">18 condition="context/bug_tracking_usage/enumvalue:LAUNCHPAD">
24 <script type="text/javascript">19 <script type="text/javascript">