Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(569)

Side by Side Diff: appengine/monorail/static/js/graveyard/common.js

Issue 1868553004: Open Source Monorail (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /* Copyright 2016 The Chromium Authors. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style
4 * license that can be found in the LICENSE file or at
5 * https://developers.google.com/open-source/licenses/bsd
6 */
7
8 //------------------------------------------------------------------------
9 // This file contains common utilities and basic javascript infrastructure.
10 //
11 // Notes:
12 // * Press 'D' to toggle debug mode.
13 //
14 // Functions:
15 //
16 // - Assertions
17 // DEPRECATED: Use assert.js
18 // AssertTrue(): assert an expression. Throws an exception if false.
19 // Fail(): Throws an exception. (Mark block of code that should be unreachable)
20 // AssertEquals(): assert that two values are equal.
21 // AssertType(): assert that a value has a particular type
22 //
23 // - Cookies
24 // SetCookie(): Sets a cookie.
25 // ExpireCookie(): Expires a cookie.
26 // GetCookie(): Gets a cookie value.
27 //
28 // - Dynamic HTML/DOM utilities
29 // MaybeGetElement(): get an element by its id
30 // GetElement(): get an element by its id
31 // GetParentNode(): Get the parent of an element
32 // GetAttribute(): Get attribute value of a DOM node
33 // GetInnerHTML(): get the inner HTML of a node
34 // SetCssStyle(): Sets a CSS property of a node.
35 // GetStyleProperty(): Get CSS property from a style attribute string
36 // GetCellIndex(): Get the index of a table cell in a table row
37 // ShowElement(): Show/hide element by setting the "display" css property.
38 // ShowBlockElement(): Show/hide block element
39 // SetButtonText(): Set the text of a button element.
40 // AppendNewElement(): Create and append a html element to a parent node.
41 // CreateDIV(): Create a DIV element and append to the document.
42 // HasClass(): check if element has a given class
43 // AddClass(): add a class to an element
44 // RemoveClass(): remove a class from an element
45 //
46 // - Window/Screen utiltiies
47 // GetPageOffsetLeft(): get the X page offset of an element
48 // GetPageOffsetTop(): get the Y page offset of an element
49 // GetPageOffset(): get the X and Y page offsets of an element
50 // GetPageOffsetRight() : get X page offset of the right side of an element
51 // GetPageOffsetRight() : get Y page offset of the bottom of an element
52 // GetScrollTop(): get the vertical scrolling pos of a window.
53 // GetScrollLeft(): get the horizontal scrolling pos of a window
54 // IsScrollAtEnd(): check if window scrollbar has reached its maximum offset
55 // ScrollTo(): scroll window to a position
56 // ScrollIntoView(): scroll window so that an element is in view.
57 // GetWindowWidth(): get width of a window.
58 // GetWindowHeight(): get height of a window
59 // GetAvailScreenWidth(): get available screen width
60 // GetAvailScreenHeight(): get available screen height
61 // GetNiceWindowHeight(): get a nice height for a new browser window.
62 // Open{External/Internal}Window(): open a separate window
63 // CloseWindow(): close a window
64 //
65 // - DOM walking utilities
66 // AnnotateTerms(): find terms in a node and decorate them with some tag
67 // AnnotateText(): find terms in a text node and decorate them with some tag
68 //
69 // - String utilties
70 // HtmlEscape(): html escapes a string
71 // HtmlUnescape(): remove html-escaping.
72 // QuoteEscape(): escape " quotes.
73 // CollapseWhitespace(): collapse multiple whitespace into one whitespace.
74 // Trim(): trim whitespace on ends of string
75 // IsEmpty(): check if CollapseWhiteSpace(String) == ""
76 // IsLetterOrDigit(): check if a character is a letter or a digit
77 // ConvertEOLToLF(): normalize the new-lines of a string.
78 // HtmlEscapeInsertWbrs(): HtmlEscapes and inserts <wbr>s (word break tags)
79 // after every n non-space chars and/or after or before certain special chars
80 //
81 // - TextArea utilities
82 // GetCursorPos(): finds the cursor position of a textfield
83 // SetCursorPos(): sets the cursor position in a textfield
84 //
85 // - Array utilities
86 // FindInArray(): do a linear search to find an element value.
87 // DeleteArrayElement(): return a new array with a specific value removed.
88 // CloneObject(): clone an object, copying its values recursively.
89 // CloneEvent(): clone an event; cannot use CloneObject because it
90 // suffers from infinite recursion
91 //
92 // - Formatting utilities
93 // PrintArray(): used to print/generate HTML by combining static text
94 // and dynamic strings.
95 // ImageHtml(): create html for an img tag
96 // FormatJSLink(): formats a link that invokes js code when clicked.
97 // MakeId3(): formats an id that has two id numbers, eg, foo_3_7
98 //
99 // - Timeouts
100 // SafeTimeout(): sets a timeout with protection against ugly JS-errors
101 // CancelTimeout(): cancels a timeout with a given ID
102 // CancelAllTimeouts(): cancels all timeouts on a given window
103 //
104 // - Miscellaneous
105 // IsDefined(): returns true if argument is not undefined
106 //------------------------------------------------------------------------
107
108 // browser detection
109 function BR_AgentContains_(str) {
110 if (str in BR_AgentContains_cache_) {
111 return BR_AgentContains_cache_[str];
112 }
113
114 return BR_AgentContains_cache_[str] =
115 (navigator.userAgent.toLowerCase().indexOf(str) != -1);
116 }
117 // We cache the results of the indexOf operation. This gets us a 10x benefit in
118 // Gecko, 8x in Safari and 4x in MSIE for all of the browser checks
119 var BR_AgentContains_cache_ = {};
120
121 function BR_IsIE() {
122 return (BR_AgentContains_('msie') || BR_AgentContains_('trident')) &&
123 !window.opera;
124 }
125
126 function BR_IsKonqueror() {
127 return BR_AgentContains_('konqueror');
128 }
129
130 function BR_IsSafari() {
131 return BR_AgentContains_('safari') || BR_IsKonqueror();
132 }
133
134 function BR_IsNav() {
135 return !BR_IsIE() &&
136 !BR_IsSafari() &&
137 BR_AgentContains_('mozilla');
138 }
139
140 var BACKSPACE_KEYCODE = 8;
141 var COMMA_KEYCODE = 188; // ',' key
142 var DEBUG_KEYCODE = 68; // 'D' key
143 var DELETE_KEYCODE = 46;
144 var DOWN_KEYCODE = 40; // DOWN arrow key
145 var ENTER_KEYCODE = 13; // ENTER key
146 var ESC_KEYCODE = 27; // ESC key
147 var LEFT_KEYCODE = 37; // LEFT arrow key
148 var RIGHT_KEYCODE = 39; // RIGHT arrow key
149 var SPACE_KEYCODE = 32; // space bar
150 var TAB_KEYCODE = 9; // TAB key
151 var UP_KEYCODE = 38; // UP arrow key
152 var SHIFT_KEYCODE = 16;
153 var PAGE_DOWN_KEYCODE = 34;
154 var PAGE_UP_KEYCODE = 33;
155
156 var MAX_EMAIL_ADDRESS_LENGTH = 320; // 64 + '@' + 255
157 var MAX_SIGNATURE_LENGTH = 1000; // 1000 chars of maximum signature
158
159 //------------------------------------------------------------------------
160 // Assertions
161 // DEPRECATED: Use assert.js
162 //------------------------------------------------------------------------
163 /**
164 * DEPRECATED: Use assert.js
165 */
166 function raise(msg) {
167 if (typeof Error != 'undefined') {
168 throw new Error(msg || 'Assertion Failed');
169 } else {
170 throw (msg);
171 }
172 }
173
174 /**
175 * DEPRECATED: Use assert.js
176 *
177 * Fail() is useful for marking logic paths that should
178 * not be reached. For example, if you have a class that uses
179 * ints for enums:
180 *
181 * MyClass.ENUM_FOO = 1;
182 * MyClass.ENUM_BAR = 2;
183 * MyClass.ENUM_BAZ = 3;
184 *
185 * And a switch statement elsewhere in your code that
186 * has cases for each of these enums, then you can
187 * "protect" your code as follows:
188 *
189 * switch(type) {
190 * case MyClass.ENUM_FOO: doFooThing(); break;
191 * case MyClass.ENUM_BAR: doBarThing(); break;
192 * case MyClass.ENUM_BAZ: doBazThing(); break;
193 * default:
194 * Fail("No enum in MyClass with value: " + type);
195 * }
196 *
197 * This way, if someone introduces a new value for this enum
198 * without noticing this switch statement, then the code will
199 * fail if the logic allows it to reach the switch with the
200 * new value, alerting the developer that he should add a
201 * case to the switch to handle the new value he has introduced.
202 *
203 * @param {string} opt_msg to display for failure
204 * DEFAULT: "Assertion failed"
205 */
206 function Fail(opt_msg) {
207 opt_msg = opt_msg || 'Assertion failed';
208 if (IsDefined(DumpError)) DumpError(opt_msg + '\n');
209 raise(opt_msg);
210 }
211
212 /**
213 * DEPRECATED: Use assert.js
214 *
215 * Asserts that an expression is true (non-zero and non-null).
216 *
217 * Note that it is critical not to pass logic
218 * with side-effects as the expression for AssertTrue
219 * because if the assertions are removed by the
220 * JSCompiler, then the expression will be removed
221 * as well, in which case the side-effects will
222 * be lost. So instead of this:
223 *
224 * AssertTrue( criticalComputation() );
225 *
226 * Do this:
227 *
228 * var result = criticalComputation();
229 * AssertTrue(result);
230 *
231 * @param expression to evaluate
232 * @param {string} opt_msg to display if the assertion fails
233 *
234 */
235 function AssertTrue(expression, opt_msg) {
236 if (!expression) {
237 opt_msg = opt_msg || 'Assertion failed';
238 Fail(opt_msg);
239 }
240 }
241
242 /**
243 * DEPRECATED: Use assert.js
244 *
245 * Asserts that a value is of the provided type.
246 *
247 * AssertType(6, Number);
248 * AssertType("ijk", String);
249 * AssertType([], Array);
250 * AssertType({}, Object);
251 * AssertType(ICAL_Date.now(), ICAL_Date);
252 *
253 * @param value
254 * @param type A constructor function
255 * @param {string} opt_msg to display if the assertion fails
256 */
257 function AssertType(value, type, opt_msg) {
258 // for backwards compatability only
259 if (typeof value == type) return;
260
261 if (value || value == "") {
262 try {
263 if (type == AssertTypeMap[typeof value] || value instanceof type) return;
264 } catch (e) { /* failure, type was an illegal argument to instanceof */ }
265 }
266 var makeMsg = opt_msg === undefined;
267 if (makeMsg) {
268 if (typeof type == 'function') {
269 var match = type.toString().match(/^\s*function\s+([^\s\{]+)/);
270 if (match) type = match[1];
271 }
272 opt_msg = "AssertType failed: <" + value + "> not typeof "+ type;
273 }
274 Fail(opt_msg);
275 }
276
277 var AssertTypeMap = {
278 'string' : String,
279 'number' : Number,
280 'boolean' : Boolean
281 };
282
283 var EXPIRED_COOKIE_VALUE = 'EXPIRED';
284
285
286 //------------------------------------------------------------------------
287 // Window/screen utilities
288 // TODO: these should be renamed (e.g. GetWindowWidth to GetWindowInnerWidth
289 // and moved to geom.js)
290 //------------------------------------------------------------------------
291 // Get page offset of an element
292 function GetPageOffsetLeft(el) {
293 var x = el.offsetLeft;
294 if (el.offsetParent != null)
295 x += GetPageOffsetLeft(el.offsetParent);
296 return x;
297 }
298
299 // Get page offset of an element
300 function GetPageOffsetTop(el) {
301 var y = el.offsetTop;
302 if (el.offsetParent != null)
303 y += GetPageOffsetTop(el.offsetParent);
304 return y;
305 }
306
307 // Get page offset of an element
308 function GetPageOffset(el) {
309 var x = el.offsetLeft;
310 var y = el.offsetTop;
311 if (el.offsetParent != null) {
312 var pos = GetPageOffset(el.offsetParent);
313 x += pos.x;
314 y += pos.y;
315 }
316 return {x: x, y: y};
317 }
318
319 // Get the y position scroll offset.
320 function GetScrollTop(win) {
321 return GetWindowPropertyByBrowser_(win, getScrollTopGetters_);
322 }
323
324 var getScrollTopGetters_ = {
325 ieQuirks_: function(win) {
326 return win.document.body.scrollTop;
327 },
328 ieStandards_: function(win) {
329 return win.document.documentElement.scrollTop;
330 },
331 dom_: function(win) {
332 return win.pageYOffset;
333 }
334 };
335
336 // Get the x position scroll offset.
337 function GetScrollLeft(win) {
338 return GetWindowPropertyByBrowser_(win, getScrollLeftGetters_);
339 }
340
341 var getScrollLeftGetters_ = {
342 ieQuirks_: function(win) {
343 return win.document.body.scrollLeft;
344 },
345 ieStandards_: function(win) {
346 return win.document.documentElement.scrollLeft;
347 },
348 dom_: function(win) {
349 return win.pageXOffset;
350 }
351 };
352
353 // Scroll so that as far as possible the entire element is in view.
354 var ALIGN_BOTTOM = 'b';
355 var ALIGN_MIDDLE = 'm';
356 var ALIGN_TOP = 't';
357
358 var getWindowWidthGetters_ = {
359 ieQuirks_: function(win) {
360 return win.document.body.clientWidth;
361 },
362 ieStandards_: function(win) {
363 return win.document.documentElement.clientWidth;
364 },
365 dom_: function(win) {
366 return win.innerWidth;
367 }
368 };
369
370 function GetWindowHeight(win) {
371 return GetWindowPropertyByBrowser_(win, getWindowHeightGetters_);
372 }
373
374 var getWindowHeightGetters_ = {
375 ieQuirks_: function(win) {
376 return win.document.body.clientHeight;
377 },
378 ieStandards_: function(win) {
379 return win.document.documentElement.clientHeight;
380 },
381 dom_: function(win) {
382 return win.innerHeight;
383 }
384 };
385
386 /**
387 * Allows the easy use of different getters for IE quirks mode, IE standards
388 * mode and fully DOM-compliant browers.
389 *
390 * @param win window to get the property for
391 * @param getters object with various getters. Invoked with the passed window.
392 * There are three properties:
393 * - ieStandards_: IE 6.0 standards mode
394 * - ieQuirks_: IE 6.0 quirks mode and IE 5.5 and older
395 * - dom_: Mozilla, Safari and other fully DOM compliant browsers
396 *
397 * @private
398 */
399 function GetWindowPropertyByBrowser_(win, getters) {
400 try {
401 if (BR_IsSafari()) {
402 return getters.dom_(win);
403 } else if (!window.opera &&
404 "compatMode" in win.document &&
405 win.document.compatMode == "CSS1Compat") {
406 return getters.ieStandards_(win);
407 } else if (BR_IsIE()) {
408 return getters.ieQuirks_(win);
409 }
410 } catch (e) {
411 // Ignore for now and fall back to DOM method
412 }
413
414 return getters.dom_(win);
415 }
416
417 function GetAvailScreenWidth(win) {
418 return win.screen.availWidth;
419 }
420
421 // Used for horizontally centering a new window of the given width in the
422 // available screen. Set the new window's distance from the left of the screen
423 // equal to this function's return value.
424 // Params: width: the width of the new window
425 // Returns: the distance from the left edge of the screen for the new window to
426 // be horizontally centered
427 function GetCenteringLeft(win, width) {
428 return (win.screen.availWidth - width) >> 1;
429 }
430
431 // Used for vertically centering a new window of the given height in the
432 // available screen. Set the new window's distance from the top of the screen
433 // equal to this function's return value.
434 // Params: height: the height of the new window
435 // Returns: the distance from the top edge of the screen for the new window to
436 // be vertically aligned.
437 function GetCenteringTop(win, height) {
438 return (win.screen.availHeight - height) >> 1;
439 }
440
441 /**
442 * Opens a child popup window that has no browser toolbar/decorations.
443 * (Copied from caribou's common.js library with small modifications.)
444 *
445 * @param url the URL for the new window (Note: this will be unique-ified)
446 * @param opt_name the name of the new window
447 * @param opt_width the width of the new window
448 * @param opt_height the height of the new window
449 * @param opt_center if true, the new window is centered in the available screen
450 * @param opt_hide_scrollbars if true, the window hides the scrollbars
451 * @param opt_noresize if true, makes window unresizable
452 * @param opt_blocked_msg message warning that the popup has been blocked
453 * @return {Window} a reference to the new child window
454 */
455 function Popup(url, opt_name, opt_width, opt_height, opt_center,
456 opt_hide_scrollbars, opt_noresize, opt_blocked_msg) {
457 if (!opt_height) {
458 opt_height = Math.floor(GetWindowHeight(window.top) * 0.8);
459 }
460 if (!opt_width) {
461 opt_width = Math.min(GetAvailScreenWidth(window), opt_height);
462 }
463
464 var features = "resizable=" + (opt_noresize ? "no" : "yes") + "," +
465 "scrollbars=" + (opt_hide_scrollbars ? "no" : "yes") + "," +
466 "width=" + opt_width + ",height=" + opt_height;
467 if (opt_center) {
468 features += ",left=" + GetCenteringLeft(window, opt_width) + "," +
469 "top=" + GetCenteringTop(window, opt_height);
470 }
471 return OpenWindow(window, url, opt_name, features, opt_blocked_msg);
472 }
473
474 /**
475 * Opens a new window. Returns the new window handle. Tries to open the new
476 * window using top.open() first. If that doesn't work, then tries win.open().
477 * If that still doesn't work, prints an alert.
478 * (Copied from caribou's common.js library with small modifications.)
479 *
480 * @param win the parent window from which to open the new child window
481 * @param url the URL for the new window (Note: this will be unique-ified)
482 * @param opt_name the name of the new window
483 * @param opt_features the properties of the new window
484 * @param opt_blocked_msg message warning that the popup has been blocked
485 * @return {Window} a reference to the new child window
486 */
487 function OpenWindow(win, url, opt_name, opt_features, opt_blocked_msg) {
488 var newwin = OpenWindowHelper(top, url, opt_name, opt_features);
489 if (!newwin || newwin.closed || !newwin.focus) {
490 newwin = OpenWindowHelper(win, url, opt_name, opt_features);
491 }
492 if (!newwin || newwin.closed || !newwin.focus) {
493 if (opt_blocked_msg) alert(opt_blocked_msg);
494 } else {
495 // Make sure that the window has the focus
496 newwin.focus();
497 }
498 return newwin;
499 }
500
501 /*
502 * Helper for OpenWindow().
503 * (Copied from caribou's common.js library with small modifications.)
504 */
505 function OpenWindowHelper(win, url, name, features) {
506 var newwin;
507 if (features) {
508 newwin = win.open(url, name, features);
509 } else if (name) {
510 newwin = win.open(url, name);
511 } else {
512 newwin = win.open(url);
513 }
514 return newwin;
515 }
516
517 //------------------------------------------------------------------------
518 // String utilities
519 //------------------------------------------------------------------------
520 // Do html escaping
521 var amp_re_ = /&/g;
522 var lt_re_ = /</g;
523 var gt_re_ = />/g;
524
525 // converts multiple ws chars to a single space, and strips
526 // leading and trailing ws
527 var spc_re_ = /\s+/g;
528 var beg_spc_re_ = /^ /;
529 var end_spc_re_ = / $/;
530
531 var newline_re_ = /\r?\n/g;
532 var spctab_re_ = /[ \t]+/g;
533 var nbsp_re_ = /\xa0/g;
534
535 // URL-decodes the string. We need to specially handle '+'s because
536 // the javascript library doesn't properly convert them to spaces
537 var plus_re_ = /\+/g;
538
539 // Converts any instances of "\r" or "\r\n" style EOLs into "\n" (Line Feed),
540 // and also trim the extra newlines and whitespaces at the end.
541 var eol_re_ = /\r\n?/g;
542 var trailingspc_re_ = /[\n\t ]+$/;
543
544 // Converts a string to its canonicalized label form.
545 var illegal_chars_re_ = /[ \/(){}&|\\\"\000]/g;
546
547 //------------------------------------------------------------------------
548 // TextArea utilities
549 //------------------------------------------------------------------------
550
551 // Gets the cursor pos in a text area. Returns -1 if the cursor pos cannot
552 // be determined or if the cursor out of the textfield.
553 function GetCursorPos(win, textfield) {
554 try {
555 if (IsDefined(textfield.selectionEnd)) {
556 // Mozilla directly supports this
557 return textfield.selectionEnd;
558
559 } else if (win.document.selection && win.document.selection.createRange) {
560 // IE doesn't export an accessor for the endpoints of a selection.
561 // Instead, it uses the TextRange object, which has an extremely obtuse
562 // API. Here's what seems to work:
563
564 // (1) Obtain a textfield from the current selection (cursor)
565 var tr = win.document.selection.createRange();
566
567 // Check if the current selection is in the textfield
568 if (tr.parentElement() != textfield) {
569 return -1;
570 }
571
572 // (2) Make a text range encompassing the textfield
573 var tr2 = tr.duplicate();
574 tr2.moveToElementText(textfield);
575
576 // (3) Move the end of the copy to the beginning of the selection
577 tr2.setEndPoint("EndToStart", tr);
578
579 // (4) The span of the textrange copy is equivalent to the cursor pos
580 var cursor = tr2.text.length;
581
582 // Finally, perform a sanity check to make sure the cursor is in the
583 // textfield. IE sometimes screws this up when the window is activated
584 if (cursor > textfield.value.length) {
585 return -1;
586 }
587 return cursor;
588 } else {
589 Debug("Unable to get cursor position for: " + navigator.userAgent);
590
591 // Just return the size of the textfield
592 // TODO: Investigate how to get cursor pos in Safari!
593 return textfield.value.length;
594 }
595 } catch (e) {
596 DumpException(e, "Cannot get cursor pos");
597 }
598
599 return -1;
600 }
601
602 function SetCursorPos(win, textfield, pos) {
603 if (IsDefined(textfield.selectionEnd) &&
604 IsDefined(textfield.selectionStart)) {
605 // Mozilla directly supports this
606 textfield.selectionStart = pos;
607 textfield.selectionEnd = pos;
608
609 } else if (win.document.selection && textfield.createTextRange) {
610 // IE has textranges. A textfield's textrange encompasses the
611 // entire textfield's text by default
612 var sel = textfield.createTextRange();
613
614 sel.collapse(true);
615 sel.move("character", pos);
616 sel.select();
617 }
618 }
619
620 //------------------------------------------------------------------------
621 // Array utilities
622 //------------------------------------------------------------------------
623 // Find an item in an array, returns the key, or -1 if not found
624 function FindInArray(array, x) {
625 for (var i = 0; i < array.length; i++) {
626 if (array[i] == x) {
627 return i;
628 }
629 }
630 return -1;
631 }
632
633 // Delete an element from an array
634 function DeleteArrayElement(array, x) {
635 var i = 0;
636 while (i < array.length && array[i] != x)
637 i++;
638 array.splice(i, 1);
639 }
640
641 // Clean up email address:
642 // - remove extra spaces
643 // - Surround name with quotes if it contains special characters
644 // to check if we need " quotes
645 // Note: do not use /g in the regular expression, otherwise the
646 // regular expression cannot be reusable.
647 var specialchars_re_ = /[()<>@,;:\\\".\[\]]/;
648
649 //------------------------------------------------------------------------
650 // Timeouts
651 //
652 // It is easy to forget to put a try/catch block around a timeout function,
653 // and the result is an ugly user visible javascript error.
654 // Also, it would be nice if a timeout associated with a window is
655 // automatically cancelled when the user navigates away from that window.
656 //
657 // When storing timeouts in a window, we can't let that variable be renamed
658 // since the window could be top.js, and renaming such a property could
659 // clash with any of the variables/functions defined in top.js.
660 //------------------------------------------------------------------------
661 /**
662 * Sets a timeout safely.
663 * @param win the window object. If null is passed in, then a timeout if set
664 * on the js frame. If the window is closed, or freed, the timeout is
665 * automaticaaly cancelled
666 * @param fn the callback function: fn(win) will be called.
667 * @param ms number of ms the callback should be called later
668 */
669 function SafeTimeout(win, fn, ms) {
670 if (!win) win = window;
671 if (!win._tm) {
672 win._tm = [];
673 }
674 var timeoutfn = SafeTimeoutFunction_(win, fn);
675 var id = win.setTimeout(timeoutfn, ms);
676
677 // Save the id so that it can be removed from the _tm array
678 timeoutfn.id = id;
679
680 // Safe the timeout in the _tm array
681 win._tm[id] = 1;
682
683 return id;
684 }
685
686 /** Creates a callback function for a timeout*/
687 function SafeTimeoutFunction_(win, fn) {
688 var timeoutfn = function() {
689 try {
690 fn(win);
691
692 var t = win._tm;
693 if (t) {
694 delete t[timeoutfn.id];
695 }
696 } catch (e) {
697 DumpException(e);
698 }
699 };
700 return timeoutfn;
701 }
702
703 //------------------------------------------------------------------------
704 // Misc
705 //------------------------------------------------------------------------
706 // Check if a value is defined
707 function IsDefined(value) {
708 return (typeof value) != 'undefined';
709 }
710
711 function GetKeyCode(event) {
712 var code;
713 if (event.keyCode) {
714 code = event.keyCode;
715 } else if (event.which) {
716 code = event.which;
717 }
718 return code;
719 }
OLDNEW
« no previous file with comments | « appengine/monorail/static/js/framework/project-name-check.js ('k') | appengine/monorail/static/js/graveyard/geom.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698