Merge lp:~adiroiban/launchpad/bug-540105 into lp:launchpad
- bug-540105
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Edwin Grubbs |
Approved revision: | no longer in the source branch. |
Merged at revision: | not available |
Proposed branch: | lp:~adiroiban/launchpad/bug-540105 |
Merge into: | lp:launchpad |
Diff against target: |
338 lines (+152/-55) 5 files modified
lib/canonical/launchpad/javascript/translations/pofile.js (+54/-40) lib/lp/app/templates/base-layout-macros.pt (+3/-0) lib/lp/translations/templates/pofile-translate.pt (+26/-8) lib/lp/translations/templates/translationmessage-translate.pt (+17/-7) lib/lp/translations/windmill/tests/test_pofile_translate.py (+52/-0) |
To merge this branch: | bzr merge lp:~adiroiban/launchpad/bug-540105 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Edwin Grubbs (community) | code | Approve | |
Review via email: mp+21552@code.launchpad.net |
Commit message
Move independent functionality in different JS sandboxes and fix
pofile.js updateNotificat
Description of the change
= Bug 540105 =
I noticed this behaviour in edge:
When entering text in the input box for a translation, this textbox does no longer get the focus by automatically selecting the checkbox dot on its left.
This leads to translators not noticing it, pressing "Save" and loosing all their translations.
== Proposed fix ==
Move independent functionality in different JS sandboxes and fix
pofile.js updateNotificat
== Pre-implementation notes ==
This branch is a hotfix for this problem.
I have opened bug 540216 and working on improving the general test coverage for pofile.js code.
== Implementation details ==
I have also fixes some other lint warnings.
== Tests ==
lp-test -t pofile_
== Demo and Q/A ==
Login as admin and go to:
https:/
In the "New translation" field, enter some text. The radio button before the text field should be now selected.
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files:
lib/canonical
== JSLint notices ==
No handlers could be found for logger "bzr"
jslint: Lint found in '/home/
Line 303 character 18: Be careful when making functions within a loop. Consider putting the function in a closure.
},
Line 310 character 18: Be careful when making functions within a loop. Consider putting the function in a closure.
}, '#' + fields[key], 'down:68+
Line 316 character 18: Be careful when making functions within a loop. Consider putting the function in a closure.
}, '#' + fields[key], 'down:48+
jslint: 1 file to lint.
Adi Roiban (adiroiban) wrote : | # |
Hi,
> Hi Adi,
>
> This is a good improvement. I ran into an annoying problem running the tests.
> The tests use the combined javascript file, but "make jsbuild" was not getting
> run automatically. I also noticed that translationmess
> pofile-translate.pt load pofile.js directly, when the <script> tag really
> should be added to lib/lp/
> the other js files in the ${lp_js} directory.
I have moved the pofile.js inclusing in base-layout-
> Since I was confused by some of your changes that I don't think were
> necessary, I'm marking this
> needs-fixing
Thanks for the review
[snip]
> > var notice = Y.one('
> >+ if (!notice) {
>
>
> Since Y.one() is expected to return null when the element is not found,
> the preferred if-statement is:
> if (notice !== null)
Thanks for this remark.
I have changed the if statement to explicitly test agains null.
Same for the other cases.
[snip]
> >+ LPS.use(
> > Y.on('domready', Y.lp.pofile.
> >- Y.on('domready', Y.lp.pofile.
> >+ });
> >+
> >+ LPS.use(
>
>
> Why are you calling LPS.use(
> should have no effect unless there is something seriously wrong with
> lp.pofile.
I moved them back in the same sandbox.
I split independent functions in different sandboxes so that the failure of one function to not affect the others.
Here is the latest diff:
=== modified file 'lib/canonical/
--- lib/canonical/
+++ lib/canonical/
@@ -59,7 +59,7 @@
self.updateNot
var notice = Y.one('
- if (!notice) {
+ if (notice == null) {
// We have no notice container on this page, this is why there is
// nothing more to be done by this function.
return;
@@ -71,7 +71,7 @@
// Check the cookie to see if the user has already dismissed
// the notification box for this session.
var already_seen = Y.Cookie.
- if (already_seen) {
+ if (already_seen !== null) {
notice.
}
@@ -79,7 +79,7 @@
// Cancel button starts out hidden. If user has JavaScript,
// then we want to show it.
- if (!cancel_button) {
+ if (cancel_button == null) {
// No cancel button was found to attach the action.
return;
}
@@ -94,7 +94,7 @@
self.setFocus = function(field) {
// if there is nofield, do nothing
- if (Y.one('#' + field)) {
+ if (Y.one('#' + field) !== null) {
Y.one('#' + field).focus();
}
};
@@ -151,7 +151,7 @@
// Copy plural text if needed
- if (Y.one('#' + translation_plural + '1')) {
+ if (Y.one('#' + translation_plural + '1') !== null) {
Edwin Grubbs (edwin-grubbs) wrote : | # |
> > Why are you calling LPS.use(
> > should have no effect unless there is something seriously wrong with
> > lp.pofile.
> I moved them back in the same sandbox.
> I split independent functions in different sandboxes so that the failure of
> one function to not affect the others.
Hi Adi,
All your changes look good. Now I understand what you were trying to do with the separate LPS calls. Since I wasn't completely certain how far up the stack an exception goes before it continues running the rest of the javascript in the page, I played around with it a little bit. Apparently, an exception halts execution of a <script> block, so you would have to have multiple <script> blocks around each LPS.use() in order to ensure that the following code is run despite an exception above it. A much clearer way to handle that would be:
LPS.use(
try {
do_something();
} catch (e) {
Y.log(e, "error");
}
do_something_
});
At least in firefox, if you call Y.log() with the second argument as "error", you will get a full stack trace in the console just like a normal uncaught exception.
Using try/catch is completely up to you.
merge-approved
BTW, calling LPS.use() multiple times does not give you separate sandboxes, since you are re-using LPS instead of creating a new YUI() object.
-Edwin
Adi Roiban (adiroiban) wrote : | # |
I added try/catch statements.
Many thanks for your review.
Do you have time to send this branch to ec2 test and land, or should I ask the ORC?
Here is the latest diff.
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -18,12 +18,28 @@
+ try {
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ try {
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ try {
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ try {
});
+ } catch (e) {
+ Y.log(e, "error");
+ }
});
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -15,11 +15,23 @@
</style>
<script type="text/
+ try {
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ try {
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ try {
});
+ } catch (e) {
+ Y.log(e, "error");
+ }
});
</script>
</div>
Adi Roiban (adiroiban) wrote : | # |
Hi Edwin,
I moved the try/catch inside the domready function call.
I did some testing on Firefox and Chromium on Ubuntu Karmic, and without the try/catch, a failing domready function call will prevent the loading of all other domready functions.
Here is the latest review.
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -18,31 +18,41 @@
- try {
- Y.on('domready', Y.lp.pofile.
- } catch (e) {
- Y.log(e, "error");
- }
- try {
- Y.on('domready', Y.lp.pofile.
- } catch (e) {
- Y.log(e, "error");
- }
- try {
- Y.on('domready', Y.lp.pofile.
- } catch (e) {
- Y.log(e, "error");
- }
- try {
- Y.on('domready', function(e) {
- Y.lp.pofile.
- });
- } catch (e) {
- Y.log(e, "error");
- }
+
+ Y.on('domready', function(e) {
+ try {
+ Y.lp.pofile.
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ });
+
+ Y.on('domready', function(e) {
+ try {
+ Y.lp.pofile.
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ });
+
+ Y.on('domready', function(e) {
+ try {
+ Y.lp.pofile.
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ });
+
+ Y.on('domready', function(e) {
+ try {
+ Y.lp.pofile.
+ } catch (e) {
+ Y.log(e, "error");
+ }
+ });
+
});
-
</script>
</div>
<div metal:fill-
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -15,23 +15,29 @@
</style>
<script type="text/
- try {
- Y.on('domready', Y.lp.pofile.
- } catch (e) {
- Y.log(e, "error");
- }
- try {
- Y.on('domready', Y.lp.pofile.
- } catch (e) {
- Y.log(e, "error");
- }
- try {
- Y.on('domready', function(e) {
- Y.lp.pofile.
- });
- } catch (e) {
- Y.log(e, "error");
- }
+ Y.on('domready', function(e) {
+ try {
+ Y.lp.pofile.
+ } catch (e) {
+ Y.log(e, "error");
...
Adi Roiban (adiroiban) wrote : | # |
Hi Edwin and thanks for the review!
I moved the try/catch in a single domready block, declared link as a local varibaled and used === to compare for null.
Here is the latests diff:
=== modified file 'lib/canonical/
--- lib/canonical/
+++ lib/canonical/
@@ -59,7 +59,7 @@
self.updateNot
var notice = Y.one('
- if (notice == null) {
+ if (notice === null) {
// We have no notice container on this page, this is why there is
// nothing more to be done by this function.
return;
@@ -79,7 +79,7 @@
// Cancel button starts out hidden. If user has JavaScript,
// then we want to show it.
- if (cancel_button == null) {
+ if (cancel_button === null) {
// No cancel button was found to attach the action.
return;
}
@@ -197,6 +197,7 @@
var initializeGloba
Y.
+ var link;
// Shift+Alt+s - Save form
if (e.shiftKey && e.altKey && e.keyCode == 83) {
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -25,25 +25,19 @@
} catch (e) {
}
- });
- Y.on('domready', function(e) {
try {
} catch (e) {
}
- });
- Y.on('domready', function(e) {
try {
} catch (e) {
}
- });
- Y.on('domready', function(e) {
try {
} catch (e) {
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -21,17 +21,13 @@
} catch (e) {
}
- });
- Y.on('domready', function(e) {
try {
} catch (e) {
}
- });
- Y.on('domready', function(e) {
try {
} catch (e) {
Preview Diff
1 | === modified file 'lib/canonical/launchpad/javascript/translations/pofile.js' | |||
2 | --- lib/canonical/launchpad/javascript/translations/pofile.js 2010-02-25 12:56:45 +0000 | |||
3 | +++ lib/canonical/launchpad/javascript/translations/pofile.js 2010-03-22 17:49:29 +0000 | |||
4 | @@ -55,10 +55,15 @@ | |||
5 | 55 | node.setStyle('display', 'none'); | 55 | node.setStyle('display', 'none'); |
6 | 56 | }); | 56 | }); |
7 | 57 | hide_anim.run(); | 57 | hide_anim.run(); |
9 | 58 | } | 58 | }; |
10 | 59 | 59 | ||
11 | 60 | self.updateNotificationBox = function(e) { | 60 | self.updateNotificationBox = function(e) { |
12 | 61 | var notice = Y.one('.important-notice-container'); | 61 | var notice = Y.one('.important-notice-container'); |
13 | 62 | if (notice === null) { | ||
14 | 63 | // We have no notice container on this page, this is why there is | ||
15 | 64 | // nothing more to be done by this function. | ||
16 | 65 | return; | ||
17 | 66 | } | ||
18 | 62 | var balloon = notice.one('.important-notice-balloon'); | 67 | var balloon = notice.one('.important-notice-balloon'); |
19 | 63 | var dismiss_notice_cookie = ('translation-docs-for-' + | 68 | var dismiss_notice_cookie = ('translation-docs-for-' + |
20 | 64 | documentation_cookie); | 69 | documentation_cookie); |
21 | @@ -66,7 +71,7 @@ | |||
22 | 66 | // Check the cookie to see if the user has already dismissed | 71 | // Check the cookie to see if the user has already dismissed |
23 | 67 | // the notification box for this session. | 72 | // the notification box for this session. |
24 | 68 | var already_seen = Y.Cookie.get(dismiss_notice_cookie, Boolean); | 73 | var already_seen = Y.Cookie.get(dismiss_notice_cookie, Boolean); |
26 | 69 | if (already_seen) { | 74 | if (already_seen !== null) { |
27 | 70 | notice.setStyle('display', 'none'); | 75 | notice.setStyle('display', 'none'); |
28 | 71 | } | 76 | } |
29 | 72 | 77 | ||
30 | @@ -74,6 +79,10 @@ | |||
31 | 74 | '.important-notice-cancel-button'); | 79 | '.important-notice-cancel-button'); |
32 | 75 | // Cancel button starts out hidden. If user has JavaScript, | 80 | // Cancel button starts out hidden. If user has JavaScript, |
33 | 76 | // then we want to show it. | 81 | // then we want to show it. |
34 | 82 | if (cancel_button === null) { | ||
35 | 83 | // No cancel button was found to attach the action. | ||
36 | 84 | return; | ||
37 | 85 | } | ||
38 | 77 | cancel_button.setStyle('visibility', 'visible'); | 86 | cancel_button.setStyle('visibility', 'visible'); |
39 | 78 | cancel_button.on('click', function(e) { | 87 | cancel_button.on('click', function(e) { |
40 | 79 | e.halt(); | 88 | e.halt(); |
41 | @@ -85,7 +94,7 @@ | |||
42 | 85 | 94 | ||
43 | 86 | self.setFocus = function(field) { | 95 | self.setFocus = function(field) { |
44 | 87 | // if there is nofield, do nothing | 96 | // if there is nofield, do nothing |
46 | 88 | if (Y.one('#' + field)) { | 97 | if (Y.one('#' + field) !== null) { |
47 | 89 | Y.one('#' + field).focus(); | 98 | Y.one('#' + field).focus(); |
48 | 90 | } | 99 | } |
49 | 91 | }; | 100 | }; |
50 | @@ -142,7 +151,7 @@ | |||
51 | 142 | original_singular, translation_singular, singular_select); | 151 | original_singular, translation_singular, singular_select); |
52 | 143 | 152 | ||
53 | 144 | // Copy plural text if needed | 153 | // Copy plural text if needed |
55 | 145 | if (Y.one('#' + translation_plural + '1')) { | 154 | if (Y.one('#' + translation_plural + '1') !== null) { |
56 | 146 | copyOriginalTextPlural( | 155 | copyOriginalTextPlural( |
57 | 147 | original_plural, translation_plural, plural_forms); | 156 | original_plural, translation_plural, plural_forms); |
58 | 148 | } | 157 | } |
59 | @@ -153,7 +162,7 @@ | |||
60 | 153 | 162 | ||
61 | 154 | var selectWidgetByID = function(widget) { | 163 | var selectWidgetByID = function(widget) { |
62 | 155 | var node = Y.one('#' + widget); | 164 | var node = Y.one('#' + widget); |
64 | 156 | if (node) { | 165 | if (node !== null) { |
65 | 157 | node.set('checked', true); | 166 | node.set('checked', true); |
66 | 158 | } | 167 | } |
67 | 159 | }; | 168 | }; |
68 | @@ -161,7 +170,7 @@ | |||
69 | 161 | 170 | ||
70 | 162 | var toggleWidget = function(widget) { | 171 | var toggleWidget = function(widget) { |
71 | 163 | var node = Y.one('#' + widget); | 172 | var node = Y.one('#' + widget); |
73 | 164 | if (node) { | 173 | if (node !== null) { |
74 | 165 | if (node.get('checked')) { | 174 | if (node.get('checked')) { |
75 | 166 | node.set('checked', false); | 175 | node.set('checked', false); |
76 | 167 | } else { | 176 | } else { |
77 | @@ -187,45 +196,50 @@ | |||
78 | 187 | 196 | ||
79 | 188 | var initializeGlobalKeyBindings = function(fields) { | 197 | var initializeGlobalKeyBindings = function(fields) { |
80 | 189 | 198 | ||
82 | 190 | Y.get('document').on("keyup", function(e) { | 199 | Y.get('document').on("keyup", function(e) { |
83 | 200 | var link; | ||
84 | 191 | // Shift+Alt+s - Save form | 201 | // Shift+Alt+s - Save form |
88 | 192 | if (e.shiftKey && e.altKey && e.keyCode == 83) { | 202 | if (e.shiftKey && e.altKey && e.keyCode == 83) { |
89 | 193 | Y.one('#save_and_continue_button').invoke('click'); | 203 | Y.one('#save_and_continue_button').invoke('click'); |
90 | 194 | } | 204 | } |
91 | 195 | // Shift+Alt+f - Go to search field | 205 | // Shift+Alt+f - Go to search field |
95 | 196 | if (e.shiftKey && e.altKey && e.keyCode == 70) { | 206 | if (e.shiftKey && e.altKey && e.keyCode == 70) { |
96 | 197 | self.setFocus('search_box'); | 207 | self.setFocus('search_box'); |
97 | 198 | } | 208 | } |
98 | 199 | // Shift+Alt+b - Go to first translation field | 209 | // Shift+Alt+b - Go to first translation field |
102 | 200 | if (e.shiftKey && e.altKey && e.keyCode == 66) { | 210 | if (e.shiftKey && e.altKey && e.keyCode == 66) { |
103 | 201 | self.setFocus(fields[0]); | 211 | self.setFocus(fields[0]); |
104 | 202 | } | 212 | } |
105 | 203 | // Shift+Alt+n - Go to next page in batch | 213 | // Shift+Alt+n - Go to next page in batch |
111 | 204 | if (e.shiftKey && e.altKey && e.keyCode == 78) { | 214 | if (e.shiftKey && e.altKey && e.keyCode == 78) { |
112 | 205 | if (link = Y.one('#batchnav_next')){ | 215 | link = Y.one('#batchnav_next'); |
113 | 206 | window.location.assign(link.get('href')) | 216 | if (link !== null){ |
114 | 207 | } | 217 | window.location.assign(link.get('href')); |
115 | 208 | } | 218 | } |
116 | 219 | } | ||
117 | 209 | // Shift+Alt+p - Go to previous page in batch | 220 | // Shift+Alt+p - Go to previous page in batch |
123 | 210 | if (e.shiftKey && e.altKey && e.keyCode == 80) { | 221 | if (e.shiftKey && e.altKey && e.keyCode == 80) { |
124 | 211 | if (link = Y.one('#batchnav_previous')){ | 222 | link = Y.one('#batchnav_previous'); |
125 | 212 | window.location.assign(link.get('href')) | 223 | if (link !== null){ |
126 | 213 | } | 224 | window.location.assign(link.get('href')); |
127 | 214 | } | 225 | } |
128 | 226 | } | ||
129 | 215 | // Shift+Alt+a - Go to first page in batch | 227 | // Shift+Alt+a - Go to first page in batch |
135 | 216 | if (e.shiftKey && e.altKey && e.keyCode == 65) { | 228 | if (e.shiftKey && e.altKey && e.keyCode == 65) { |
136 | 217 | if (link = Y.one('#batchnav_first')){ | 229 | link = Y.one('#batchnav_first'); |
137 | 218 | window.location.assign(link.get('href')) | 230 | if (link !== null){ |
138 | 219 | } | 231 | window.location.assign(link.get('href')); |
139 | 220 | } | 232 | } |
140 | 233 | } | ||
141 | 221 | // Shift+Alt+l - Go to last page in batch | 234 | // Shift+Alt+l - Go to last page in batch |
149 | 222 | if (e.shiftKey && e.altKey && e.keyCode == 76) { | 235 | if (e.shiftKey && e.altKey && e.keyCode == 76) { |
150 | 223 | if (link = Y.one('#batchnav_last')){ | 236 | link = Y.one('#batchnav_last'); |
151 | 224 | window.location.assign(link.get('href')) | 237 | if (link !== null){ |
152 | 225 | } | 238 | window.location.assign(link.get('href')); |
153 | 226 | } | 239 | } |
154 | 227 | }); | 240 | } |
155 | 228 | } | 241 | }); |
156 | 242 | }; | ||
157 | 229 | 243 | ||
158 | 230 | 244 | ||
159 | 231 | var initializeSuggestionsKeyBindings = function(stem) { | 245 | var initializeSuggestionsKeyBindings = function(stem) { |
160 | @@ -243,7 +257,7 @@ | |||
161 | 243 | Y, node.get('id')); | 257 | Y, node.get('id')); |
162 | 244 | } | 258 | } |
163 | 245 | }); | 259 | }); |
165 | 246 | } | 260 | }; |
166 | 247 | 261 | ||
167 | 248 | 262 | ||
168 | 249 | var initializeFieldsKeyBindings = function (fields) { | 263 | var initializeFieldsKeyBindings = function (fields) { |
169 | @@ -321,7 +335,7 @@ | |||
170 | 321 | singular_copy_text); | 335 | singular_copy_text); |
171 | 322 | } | 336 | } |
172 | 323 | } | 337 | } |
174 | 324 | } | 338 | }; |
175 | 325 | 339 | ||
176 | 326 | 340 | ||
177 | 327 | /** | 341 | /** |
178 | 328 | 342 | ||
179 | === modified file 'lib/lp/app/templates/base-layout-macros.pt' | |||
180 | --- lib/lp/app/templates/base-layout-macros.pt 2010-03-15 17:17:05 +0000 | |||
181 | +++ lib/lp/app/templates/base-layout-macros.pt 2010-03-22 17:49:29 +0000 | |||
182 | @@ -211,6 +211,9 @@ | |||
183 | 211 | <script type="text/javascript" | 211 | <script type="text/javascript" |
184 | 212 | tal:attributes="src string:${lp_js}/registry/team.js"></script> | 212 | tal:attributes="src string:${lp_js}/registry/team.js"></script> |
185 | 213 | 213 | ||
186 | 214 | <script type="text/javascript" | ||
187 | 215 | tal:attributes="src string:${lp_js}/translations/pofile.js"></script> | ||
188 | 216 | |||
189 | 214 | </tal:devmode> | 217 | </tal:devmode> |
190 | 215 | <tal:production condition="not:devmode"> | 218 | <tal:production condition="not:devmode"> |
191 | 216 | <script type="text/javascript" | 219 | <script type="text/javascript" |
192 | 217 | 220 | ||
193 | === modified file 'lib/lp/translations/templates/pofile-translate.pt' | |||
194 | --- lib/lp/translations/templates/pofile-translate.pt 2010-02-25 00:47:17 +0000 | |||
195 | +++ lib/lp/translations/templates/pofile-translate.pt 2010-03-22 17:49:29 +0000 | |||
196 | @@ -14,21 +14,39 @@ | |||
197 | 14 | } | 14 | } |
198 | 15 | </style> | 15 | </style> |
199 | 16 | 16 | ||
200 | 17 | <script type="text/javascript" | ||
201 | 18 | tal:condition="devmode" | ||
202 | 19 | tal:define="lp_js string:${icingroot}/build" | ||
203 | 20 | tal:attributes="src string:${lp_js}/translations/pofile.js"></script> | ||
204 | 21 | <script type="text/javascript"> | 17 | <script type="text/javascript"> |
205 | 22 | registerLaunchpadFunction(insertAllExpansionButtons); | 18 | registerLaunchpadFunction(insertAllExpansionButtons); |
206 | 23 | 19 | ||
207 | 24 | LPS.use('lp.pofile', function(Y) { | 20 | LPS.use('lp.pofile', function(Y) { |
211 | 25 | Y.on('domready', Y.lp.pofile.setupSuggestionDismissal); | 21 | |
209 | 26 | Y.on('domready', Y.lp.pofile.updateNotificationBox); | ||
210 | 27 | Y.on('domready', Y.lp.pofile.initializeKeyBindings); | ||
212 | 28 | Y.on('domready', function(e) { | 22 | Y.on('domready', function(e) { |
214 | 29 | Y.lp.pofile.setFocus(autofocus_field); | 23 | try { |
215 | 24 | Y.lp.pofile.updateNotificationBox(); | ||
216 | 25 | } catch (e) { | ||
217 | 26 | Y.log(e, "error"); | ||
218 | 27 | } | ||
219 | 28 | |||
220 | 29 | try { | ||
221 | 30 | Y.lp.pofile.setupSuggestionDismissal(); | ||
222 | 31 | } catch (e) { | ||
223 | 32 | Y.log(e, "error"); | ||
224 | 33 | } | ||
225 | 34 | |||
226 | 35 | try { | ||
227 | 36 | Y.lp.pofile.initializeKeyBindings(); | ||
228 | 37 | } catch (e) { | ||
229 | 38 | Y.log(e, "error"); | ||
230 | 39 | } | ||
231 | 40 | |||
232 | 41 | try { | ||
233 | 42 | Y.lp.pofile.setFocus(autofocus_field); | ||
234 | 43 | } catch (e) { | ||
235 | 44 | Y.log(e, "error"); | ||
236 | 45 | } | ||
237 | 30 | }); | 46 | }); |
238 | 47 | |||
239 | 31 | }); | 48 | }); |
240 | 49 | |||
241 | 32 | </script> | 50 | </script> |
242 | 33 | </div> | 51 | </div> |
243 | 34 | <div metal:fill-slot="main"> | 52 | <div metal:fill-slot="main"> |
244 | 35 | 53 | ||
245 | === modified file 'lib/lp/translations/templates/translationmessage-translate.pt' | |||
246 | --- lib/lp/translations/templates/translationmessage-translate.pt 2010-02-25 00:47:17 +0000 | |||
247 | +++ lib/lp/translations/templates/translationmessage-translate.pt 2010-03-22 17:49:29 +0000 | |||
248 | @@ -13,16 +13,26 @@ | |||
249 | 13 | color: lightgray; | 13 | color: lightgray; |
250 | 14 | } | 14 | } |
251 | 15 | </style> | 15 | </style> |
252 | 16 | <script type="text/javascript" | ||
253 | 17 | tal:condition="devmode" | ||
254 | 18 | tal:define="lp_js string:${icingroot}/build" | ||
255 | 19 | tal:attributes="src string:${lp_js}/translations/pofile.js"></script> | ||
256 | 20 | <script type="text/javascript"> | 16 | <script type="text/javascript"> |
257 | 21 | LPS.use('node', 'lp.pofile', function(Y) { | 17 | LPS.use('node', 'lp.pofile', function(Y) { |
258 | 22 | Y.on('domready', Y.lp.pofile.setupSuggestionDismissal); | ||
259 | 23 | Y.on('domready', Y.lp.pofile.initializeKeyBindings); | ||
260 | 24 | Y.on('domready', function(e) { | 18 | Y.on('domready', function(e) { |
262 | 25 | Y.lp.pofile.setFocus(autofocus_field); | 19 | try { |
263 | 20 | Y.lp.pofile.setupSuggestionDismissal(); | ||
264 | 21 | } catch (e) { | ||
265 | 22 | Y.log(e, "error"); | ||
266 | 23 | } | ||
267 | 24 | |||
268 | 25 | try { | ||
269 | 26 | Y.lp.pofile.initializeKeyBindings(); | ||
270 | 27 | } catch (e) { | ||
271 | 28 | Y.log(e, "error"); | ||
272 | 29 | } | ||
273 | 30 | |||
274 | 31 | try { | ||
275 | 32 | Y.lp.pofile.setFocus(autofocus_field); | ||
276 | 33 | } catch (e) { | ||
277 | 34 | Y.log(e, "error"); | ||
278 | 35 | } | ||
279 | 26 | }); | 36 | }); |
280 | 27 | }); | 37 | }); |
281 | 28 | </script> | 38 | </script> |
282 | 29 | 39 | ||
283 | === added file 'lib/lp/translations/windmill/tests/test_pofile_translate.py' | |||
284 | --- lib/lp/translations/windmill/tests/test_pofile_translate.py 1970-01-01 00:00:00 +0000 | |||
285 | +++ lib/lp/translations/windmill/tests/test_pofile_translate.py 2010-03-22 17:49:29 +0000 | |||
286 | @@ -0,0 +1,52 @@ | |||
287 | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the | ||
288 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
289 | 3 | |||
290 | 4 | """Tests for pofile translate pages.""" | ||
291 | 5 | |||
292 | 6 | __metaclass__ = type | ||
293 | 7 | __all__ = [] | ||
294 | 8 | |||
295 | 9 | from canonical.launchpad.windmill.testing import constants, lpuser | ||
296 | 10 | from lp.translations.windmill.testing import TranslationsWindmillLayer | ||
297 | 11 | from lp.testing import WindmillTestCase | ||
298 | 12 | |||
299 | 13 | |||
300 | 14 | class POFileNewTranslationFieldKeybindings(WindmillTestCase): | ||
301 | 15 | """Tests for keybinding actions associated to the translation field.""" | ||
302 | 16 | |||
303 | 17 | layer = TranslationsWindmillLayer | ||
304 | 18 | suite_name = 'POFile Translate' | ||
305 | 19 | |||
306 | 20 | def test_pofile_new_translation_autoselect(self): | ||
307 | 21 | """Test for automatically selecting new translation on text input. | ||
308 | 22 | |||
309 | 23 | When new text is typed into the new translation text fields, the | ||
310 | 24 | associated radio button should be automatically selected. | ||
311 | 25 | """ | ||
312 | 26 | client = self.client | ||
313 | 27 | start_url = ('http://translations.launchpad.dev:8085/' | ||
314 | 28 | 'evolution/trunk/+pots/evolution-2.2/es/+translate') | ||
315 | 29 | user = lpuser.TRANSLATIONS_ADMIN | ||
316 | 30 | new_translation_id = u'msgset_1_es_translation_0_new' | ||
317 | 31 | radiobutton_id = u'msgset_1_es_translation_0_new_select' | ||
318 | 32 | |||
319 | 33 | # Go to the translation page. | ||
320 | 34 | self.client.open(url=start_url) | ||
321 | 35 | self.client.waits.forPageLoad(timeout=constants.PAGE_LOAD) | ||
322 | 36 | user.ensure_login(self.client) | ||
323 | 37 | |||
324 | 38 | # Wait for the new translation field and it's associated radio button. | ||
325 | 39 | client.waits.forElement( | ||
326 | 40 | id=new_translation_id, timeout=constants.FOR_ELEMENT) | ||
327 | 41 | client.waits.forElement( | ||
328 | 42 | id=radiobutton_id, timeout=constants.FOR_ELEMENT) | ||
329 | 43 | |||
330 | 44 | # Check that the associated radio button is not selected. | ||
331 | 45 | client.asserts.assertNotChecked(id=radiobutton_id) | ||
332 | 46 | |||
333 | 47 | # Type a new translation. | ||
334 | 48 | client.type( | ||
335 | 49 | id=new_translation_id, text=u'New translation') | ||
336 | 50 | |||
337 | 51 | # Check that the associated radio button is selected. | ||
338 | 52 | client.asserts.assertChecked(id=radiobutton_id) |
Hi Adi,
This is a good improvement. I ran into an annoying problem running the tests. age-translate. pt and app/templates/ base-layout- macros. pt next to all
The tests use the combined javascript file, but "make jsbuild" was not getting
run automatically. I also noticed that translationmess
pofile-translate.pt load pofile.js directly, when the <script> tag really
should be added to lib/lp/
the other js files in the ${lp_js} directory.
Since I was confused by some of your changes that I don't think were
necessary, I'm marking this
needs-fixing
-Edwin
>=== modified file 'lib/canonical/ launchpad/ javascript/ translations/ pofile. js' launchpad/ javascript/ translations/ pofile. js 2010-02-25 12:56:45 +0000 launchpad/ javascript/ translations/ pofile. js 2010-03-17 17:36:08 +0000 'display' , 'none'); ficationBox = function(e) { .important- notice- container' );
>--- lib/canonical/
>+++ lib/canonical/
>@@ -55,10 +55,15 @@
> node.setStyle(
> });
> hide_anim.run();
>-}
>+};
>
> self.updateNoti
> var notice = Y.one('
>+ if (!notice) {
Since Y.one() is expected to return null when the element is not found,
the preferred if-statement is:
if (notice !== null)
>+ // We have no notice container on this page, this is why there is one('.important -notice- balloon' ); notice_ cookie = ('translation- docs-for- ' + cookie) ; notice- cancel- button' );
>+ // nothing more to be done by this function.
>+ return;
>+ }
> var balloon = notice.
> var dismiss_
> documentation_
>@@ -74,6 +79,10 @@
> '.important-
> // Cancel button starts out hidden. If user has JavaScript,
> // then we want to show it.
>+ if (!cancel_button) {
Same here.
>+ // No cancel button was found to attach the action. button. setStyle( 'visibility' , 'visible'); button. on('click' , function(e) { #batchnav_ next')) { location. assign( link.get( 'href') ) #batchnav_ next');
>+ return;
>+ }
> cancel_
> cancel_
> e.halt();
>@@ -202,30 +211,34 @@
> }
> // Shift+Alt+n - Go to next page in batch
> if (e.shiftKey && e.altKey && e.keyCode == 78) {
>- if (link = Y.one('
>- window.
>+ link = Y.one('
>+ if (link){
Same for these if-statements.
>+ window. location. assign( link.get( 'href') ); #batchnav_ previous' )){ location. assign( link.get( 'href') ) #batchnav_ previous' ); location. assign( link.get( 'href') ); #batchnav_ first') ){ location. assign( link.get( 'href') ) #batchnav_ first') ; location. assign( link.get( 'href') ); #batchnav_ last')) {
> }
> }
> // Shift+Alt+p - Go to previous page in batch
> if (e.shiftKey && e.altKey && e.keyCode == 80) {
>- if (link = Y.one('
>- window.
>+ link = Y.one('
>+ if (link){
>+ window.
> }
> }
> // Shift+Alt+a - Go to first page in batch
> if (e.shiftKey && e.altKey && e.keyCode == 65) {
>- if (link = Y.one('
>- window.
>+ link = Y.one('
>+ if (link){
>+ window.
> }
> }
> // Shift+Alt+l - Go to last page in batch
> if (e.shiftKey && e.altKey && e.keyCode == 76) {
>- if (link = Y.one('
>- ...