##// END OF EJS Templates
fixed issue #719 Journal revision ID tooltip AJAX query path is incorrect when running in a subdir
marcink -
r3160:5d7f6b22 beta
parent child Browse files
Show More
@@ -1,1957 +1,1957 b''
1 1 /**
2 2 RhodeCode JS Files
3 3 **/
4 4
5 5 if (typeof console == "undefined" || typeof console.log == "undefined"){
6 6 console = { log: function() {} }
7 7 }
8 8
9 9
10 10 var str_repeat = function(i, m) {
11 11 for (var o = []; m > 0; o[--m] = i);
12 12 return o.join('');
13 13 };
14 14
15 15 /**
16 16 * INJECT .format function into String
17 17 * Usage: "My name is {0} {1}".format("Johny","Bravo")
18 18 * Return "My name is Johny Bravo"
19 19 * Inspired by https://gist.github.com/1049426
20 20 */
21 21 String.prototype.format = function() {
22 22
23 23 function format() {
24 24 var str = this;
25 25 var len = arguments.length+1;
26 26 var safe = undefined;
27 27 var arg = undefined;
28 28
29 29 // For each {0} {1} {n...} replace with the argument in that position. If
30 30 // the argument is an object or an array it will be stringified to JSON.
31 31 for (var i=0; i < len; arg = arguments[i++]) {
32 32 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
33 33 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
34 34 }
35 35 return str;
36 36 }
37 37
38 38 // Save a reference of what may already exist under the property native.
39 39 // Allows for doing something like: if("".format.native) { /* use native */ }
40 40 format.native = String.prototype.format;
41 41
42 42 // Replace the prototype property
43 43 return format;
44 44
45 45 }();
46 46
47 47 String.prototype.strip = function(char) {
48 48 if(char === undefined){
49 49 char = '\\s';
50 50 }
51 51 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
52 52 }
53 53 String.prototype.lstrip = function(char) {
54 54 if(char === undefined){
55 55 char = '\\s';
56 56 }
57 57 return this.replace(new RegExp('^'+char+'+'),'');
58 58 }
59 59 String.prototype.rstrip = function(char) {
60 60 if(char === undefined){
61 61 char = '\\s';
62 62 }
63 63 return this.replace(new RegExp(''+char+'+$'),'');
64 64 }
65 65
66 66
67 67 if(!Array.prototype.indexOf) {
68 68 Array.prototype.indexOf = function(needle) {
69 69 for(var i = 0; i < this.length; i++) {
70 70 if(this[i] === needle) {
71 71 return i;
72 72 }
73 73 }
74 74 return -1;
75 75 };
76 76 }
77 77
78 78 // IE(CRAP) doesn't support previousElementSibling
79 79 var prevElementSibling = function( el ) {
80 80 if( el.previousElementSibling ) {
81 81 return el.previousElementSibling;
82 82 } else {
83 83 while( el = el.previousSibling ) {
84 84 if( el.nodeType === 1 ) return el;
85 85 }
86 86 }
87 87 }
88 88
89 89 var setSelectValue = function(select, val){
90 90 var selection = YUD.get(select);
91 91
92 92 // select element
93 93 for(var i=0;i<selection.options.length;i++){
94 94 if (selection.options[i].innerHTML == val) {
95 95 selection.selectedIndex = i;
96 96 break;
97 97 }
98 98 }
99 99 }
100 100
101 101
102 102 /**
103 103 * SmartColorGenerator
104 104 *
105 105 *usage::
106 106 * var CG = new ColorGenerator();
107 107 * var col = CG.getColor(key); //returns array of RGB
108 108 * 'rgb({0})'.format(col.join(',')
109 109 *
110 110 * @returns {ColorGenerator}
111 111 */
112 112 var ColorGenerator = function(){
113 113 this.GOLDEN_RATIO = 0.618033988749895;
114 114 this.CURRENT_RATIO = 0.22717784590367374 // this can be random
115 115 this.HSV_1 = 0.75;//saturation
116 116 this.HSV_2 = 0.95;
117 117 this.color;
118 118 this.cacheColorMap = {};
119 119 };
120 120
121 121 ColorGenerator.prototype = {
122 122 getColor:function(key){
123 123 if(this.cacheColorMap[key] !== undefined){
124 124 return this.cacheColorMap[key];
125 125 }
126 126 else{
127 127 this.cacheColorMap[key] = this.generateColor();
128 128 return this.cacheColorMap[key];
129 129 }
130 130 },
131 131 _hsvToRgb:function(h,s,v){
132 132 if (s == 0.0)
133 133 return [v, v, v];
134 134 i = parseInt(h * 6.0)
135 135 f = (h * 6.0) - i
136 136 p = v * (1.0 - s)
137 137 q = v * (1.0 - s * f)
138 138 t = v * (1.0 - s * (1.0 - f))
139 139 i = i % 6
140 140 if (i == 0)
141 141 return [v, t, p]
142 142 if (i == 1)
143 143 return [q, v, p]
144 144 if (i == 2)
145 145 return [p, v, t]
146 146 if (i == 3)
147 147 return [p, q, v]
148 148 if (i == 4)
149 149 return [t, p, v]
150 150 if (i == 5)
151 151 return [v, p, q]
152 152 },
153 153 generateColor:function(){
154 154 this.CURRENT_RATIO = this.CURRENT_RATIO+this.GOLDEN_RATIO;
155 155 this.CURRENT_RATIO = this.CURRENT_RATIO %= 1;
156 156 HSV_tuple = [this.CURRENT_RATIO, this.HSV_1, this.HSV_2]
157 157 RGB_tuple = this._hsvToRgb(HSV_tuple[0],HSV_tuple[1],HSV_tuple[2]);
158 158 function toRgb(v){
159 159 return ""+parseInt(v*256)
160 160 }
161 161 return [toRgb(RGB_tuple[0]),toRgb(RGB_tuple[1]),toRgb(RGB_tuple[2])];
162 162
163 163 }
164 164 }
165 165
166 166
167 167
168 168
169 169
170 170 /**
171 171 * GLOBAL YUI Shortcuts
172 172 */
173 173 var YUC = YAHOO.util.Connect;
174 174 var YUD = YAHOO.util.Dom;
175 175 var YUE = YAHOO.util.Event;
176 176 var YUQ = YAHOO.util.Selector.query;
177 177
178 178 // defines if push state is enabled for this browser ?
179 179 var push_state_enabled = Boolean(
180 180 window.history && window.history.pushState && window.history.replaceState
181 181 && !( /* disable for versions of iOS before version 4.3 (8F190) */
182 182 (/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent)
183 183 /* disable for the mercury iOS browser, or at least older versions of the webkit engine */
184 184 || (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent)
185 185 )
186 186 );
187 187
188 188 var _run_callbacks = function(callbacks){
189 189 if (callbacks !== undefined){
190 190 var _l = callbacks.length;
191 191 for (var i=0;i<_l;i++){
192 192 var func = callbacks[i];
193 193 if(typeof(func)=='function'){
194 194 try{
195 195 func();
196 196 }catch (err){};
197 197 }
198 198 }
199 199 }
200 200 }
201 201
202 202 /**
203 203 * Partial Ajax Implementation
204 204 *
205 205 * @param url: defines url to make partial request
206 206 * @param container: defines id of container to input partial result
207 207 * @param s_call: success callback function that takes o as arg
208 208 * o.tId
209 209 * o.status
210 210 * o.statusText
211 211 * o.getResponseHeader[ ]
212 212 * o.getAllResponseHeaders
213 213 * o.responseText
214 214 * o.responseXML
215 215 * o.argument
216 216 * @param f_call: failure callback
217 217 * @param args arguments
218 218 */
219 219 function ypjax(url,container,s_call,f_call,args){
220 220 var method='GET';
221 221 if(args===undefined){
222 222 args=null;
223 223 }
224 224
225 225 // Set special header for partial ajax == HTTP_X_PARTIAL_XHR
226 226 YUC.initHeader('X-PARTIAL-XHR',true);
227 227
228 228 // wrapper of passed callback
229 229 var s_wrapper = (function(o){
230 230 return function(o){
231 231 YUD.get(container).innerHTML=o.responseText;
232 232 YUD.setStyle(container,'opacity','1.0');
233 233 //execute the given original callback
234 234 if (s_call !== undefined){
235 235 s_call(o);
236 236 }
237 237 }
238 238 })()
239 239 YUD.setStyle(container,'opacity','0.3');
240 240 YUC.asyncRequest(method,url,{
241 241 success:s_wrapper,
242 242 failure:function(o){
243 243 console.log(o);
244 244 YUD.get(container).innerHTML='<span class="error_red">ERROR: {0}</span>'.format(o.status);
245 245 YUD.setStyle(container,'opacity','1.0');
246 246 },
247 247 cache:false
248 248 },args);
249 249
250 250 };
251 251
252 252 var ajaxGET = function(url,success) {
253 253 // Set special header for ajax == HTTP_X_PARTIAL_XHR
254 254 YUC.initHeader('X-PARTIAL-XHR',true);
255 255
256 256 var sUrl = url;
257 257 var callback = {
258 258 success: success,
259 259 failure: function (o) {
260 260 alert("error");
261 261 },
262 262 };
263 263
264 264 var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
265 265 return request;
266 266 };
267 267
268 268
269 269
270 270 var ajaxPOST = function(url,postData,success) {
271 271 // Set special header for ajax == HTTP_X_PARTIAL_XHR
272 272 YUC.initHeader('X-PARTIAL-XHR',true);
273 273
274 274 var toQueryString = function(o) {
275 275 if(typeof o !== 'object') {
276 276 return false;
277 277 }
278 278 var _p, _qs = [];
279 279 for(_p in o) {
280 280 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
281 281 }
282 282 return _qs.join('&');
283 283 };
284 284
285 285 var sUrl = url;
286 286 var callback = {
287 287 success: success,
288 288 failure: function (o) {
289 289 alert("error");
290 290 },
291 291 };
292 292 var postData = toQueryString(postData);
293 293 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
294 294 return request;
295 295 };
296 296
297 297
298 298 /**
299 299 * tooltip activate
300 300 */
301 301 var tooltip_activate = function(){
302 302 yt = YAHOO.yuitip.main;
303 303 YUE.onDOMReady(yt.init);
304 304 };
305 305
306 306 /**
307 307 * show more
308 308 */
309 309 var show_more_event = function(){
310 310 YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
311 311 var el = e.target;
312 312 YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
313 313 YUD.setStyle(el.parentNode,'display','none');
314 314 });
315 315 };
316 316
317 317 /**
318 318 * show changeset tooltip
319 319 */
320 320 var show_changeset_tooltip = function(){
321 321 YUE.on(YUD.getElementsByClassName('lazy-cs'), 'mouseover', function(e){
322 322 var target = e.currentTarget;
323 323 var rid = YUD.getAttribute(target,'raw_id');
324 324 var repo_name = YUD.getAttribute(target,'repo_name');
325 325 var ttid = 'tt-'+rid;
326 326 var success = function(o){
327 327 var json = JSON.parse(o.responseText);
328 328 YUD.addClass(target,'tooltip')
329 329 YUD.setAttribute(target, 'title',json['message']);
330 330 YAHOO.yuitip.main.show_yuitip(e, target);
331 331 }
332 332 if(rid && !YUD.hasClass(target, 'tooltip')){
333 333 YUD.setAttribute(target,'id',ttid);
334 334 YUD.setAttribute(target, 'title',_TM['loading...']);
335 335 YAHOO.yuitip.main.set_listeners(target);
336 336 YAHOO.yuitip.main.show_yuitip(e, target);
337 ajaxGET('/changeset_info/{0}/{1}'.format(repo_name,rid), success)
337 ajaxGET(LAZY_CS_URL.replace('__NAME__',repo_name).replace('__REV__', rid), success)
338 338 }
339 339 });
340 340 };
341 341
342 342 var onSuccessFollow = function(target){
343 343 var f = YUD.get(target.id);
344 344 var f_cnt = YUD.get('current_followers_count');
345 345
346 346 if(YUD.hasClass(f, 'follow')){
347 347 f.setAttribute('class','following');
348 348 f.setAttribute('title',_TM['Stop following this repository']);
349 349
350 350 if(f_cnt){
351 351 var cnt = Number(f_cnt.innerHTML)+1;
352 352 f_cnt.innerHTML = cnt;
353 353 }
354 354 }
355 355 else{
356 356 f.setAttribute('class','follow');
357 357 f.setAttribute('title',_TM['Start following this repository']);
358 358 if(f_cnt){
359 359 var cnt = Number(f_cnt.innerHTML)-1;
360 360 f_cnt.innerHTML = cnt;
361 361 }
362 362 }
363 363 }
364 364
365 365 var toggleFollowingUser = function(target,fallows_user_id,token,user_id){
366 366 args = 'follows_user_id='+fallows_user_id;
367 367 args+= '&amp;auth_token='+token;
368 368 if(user_id != undefined){
369 369 args+="&amp;user_id="+user_id;
370 370 }
371 371 YUC.asyncRequest('POST',TOGGLE_FOLLOW_URL,{
372 372 success:function(o){
373 373 onSuccessFollow(target);
374 374 }
375 375 },args);
376 376 return false;
377 377 }
378 378
379 379 var toggleFollowingRepo = function(target,fallows_repo_id,token,user_id){
380 380
381 381 args = 'follows_repo_id='+fallows_repo_id;
382 382 args+= '&amp;auth_token='+token;
383 383 if(user_id != undefined){
384 384 args+="&amp;user_id="+user_id;
385 385 }
386 386 YUC.asyncRequest('POST',TOGGLE_FOLLOW_URL,{
387 387 success:function(o){
388 388 onSuccessFollow(target);
389 389 }
390 390 },args);
391 391 return false;
392 392 }
393 393
394 394
395 395 /**
396 396 * TOOLTIP IMPL.
397 397 */
398 398 YAHOO.namespace('yuitip');
399 399 YAHOO.yuitip.main = {
400 400
401 401 $: YAHOO.util.Dom.get,
402 402
403 403 bgColor: '#000',
404 404 speed: 0.3,
405 405 opacity: 0.9,
406 406 offset: [15,15],
407 407 useAnim: false,
408 408 maxWidth: 600,
409 409 add_links: false,
410 410 yuitips: [],
411 411
412 412 set_listeners: function(tt){
413 413 YUE.on(tt, 'mouseover', yt.show_yuitip, tt);
414 414 YUE.on(tt, 'mousemove', yt.move_yuitip, tt);
415 415 YUE.on(tt, 'mouseout', yt.close_yuitip, tt);
416 416 },
417 417
418 418 init: function(){
419 419 yt.tipBox = yt.$('tip-box');
420 420 if(!yt.tipBox){
421 421 yt.tipBox = document.createElement('div');
422 422 document.body.appendChild(yt.tipBox);
423 423 yt.tipBox.id = 'tip-box';
424 424 }
425 425
426 426 YUD.setStyle(yt.tipBox, 'display', 'none');
427 427 YUD.setStyle(yt.tipBox, 'position', 'absolute');
428 428 if(yt.maxWidth !== null){
429 429 YUD.setStyle(yt.tipBox, 'max-width', yt.maxWidth+'px');
430 430 }
431 431
432 432 var yuitips = YUD.getElementsByClassName('tooltip');
433 433
434 434 if(yt.add_links === true){
435 435 var links = document.getElementsByTagName('a');
436 436 var linkLen = links.length;
437 437 for(i=0;i<linkLen;i++){
438 438 yuitips.push(links[i]);
439 439 }
440 440 }
441 441
442 442 var yuiLen = yuitips.length;
443 443
444 444 for(i=0;i<yuiLen;i++){
445 445 yt.set_listeners(yuitips[i]);
446 446 }
447 447 },
448 448
449 449 show_yuitip: function(e, el){
450 450 YUE.stopEvent(e);
451 451 if(el.tagName.toLowerCase() === 'img'){
452 452 yt.tipText = el.alt ? el.alt : '';
453 453 } else {
454 454 yt.tipText = el.title ? el.title : '';
455 455 }
456 456
457 457 if(yt.tipText !== ''){
458 458 // save org title
459 459 YUD.setAttribute(el, 'tt_title', yt.tipText);
460 460 // reset title to not show org tooltips
461 461 YUD.setAttribute(el, 'title', '');
462 462
463 463 yt.tipBox.innerHTML = yt.tipText;
464 464 YUD.setStyle(yt.tipBox, 'display', 'block');
465 465 if(yt.useAnim === true){
466 466 YUD.setStyle(yt.tipBox, 'opacity', '0');
467 467 var newAnim = new YAHOO.util.Anim(yt.tipBox,
468 468 {
469 469 opacity: { to: yt.opacity }
470 470 }, yt.speed, YAHOO.util.Easing.easeOut
471 471 );
472 472 newAnim.animate();
473 473 }
474 474 }
475 475 },
476 476
477 477 move_yuitip: function(e, el){
478 478 YUE.stopEvent(e);
479 479 var movePos = YUE.getXY(e);
480 480 YUD.setStyle(yt.tipBox, 'top', (movePos[1] + yt.offset[1]) + 'px');
481 481 YUD.setStyle(yt.tipBox, 'left', (movePos[0] + yt.offset[0]) + 'px');
482 482 },
483 483
484 484 close_yuitip: function(e, el){
485 485 YUE.stopEvent(e);
486 486
487 487 if(yt.useAnim === true){
488 488 var newAnim = new YAHOO.util.Anim(yt.tipBox,
489 489 {
490 490 opacity: { to: 0 }
491 491 }, yt.speed, YAHOO.util.Easing.easeOut
492 492 );
493 493 newAnim.animate();
494 494 } else {
495 495 YUD.setStyle(yt.tipBox, 'display', 'none');
496 496 }
497 497 YUD.setAttribute(el,'title', YUD.getAttribute(el, 'tt_title'));
498 498 }
499 499 }
500 500
501 501 /**
502 502 * Quick filter widget
503 503 *
504 504 * @param target: filter input target
505 505 * @param nodes: list of nodes in html we want to filter.
506 506 * @param display_element function that takes current node from nodes and
507 507 * does hide or show based on the node
508 508 *
509 509 */
510 510 var q_filter = function(target,nodes,display_element){
511 511
512 512 var nodes = nodes;
513 513 var q_filter_field = YUD.get(target);
514 514 var F = YAHOO.namespace(target);
515 515
516 516 YUE.on(q_filter_field,'click',function(){
517 517 q_filter_field.value = '';
518 518 });
519 519
520 520 YUE.on(q_filter_field,'keyup',function(e){
521 521 clearTimeout(F.filterTimeout);
522 522 F.filterTimeout = setTimeout(F.updateFilter,600);
523 523 });
524 524
525 525 F.filterTimeout = null;
526 526
527 527 var show_node = function(node){
528 528 YUD.setStyle(node,'display','')
529 529 }
530 530 var hide_node = function(node){
531 531 YUD.setStyle(node,'display','none');
532 532 }
533 533
534 534 F.updateFilter = function() {
535 535 // Reset timeout
536 536 F.filterTimeout = null;
537 537
538 538 var obsolete = [];
539 539
540 540 var req = q_filter_field.value.toLowerCase();
541 541
542 542 var l = nodes.length;
543 543 var i;
544 544 var showing = 0;
545 545
546 546 for (i=0;i<l;i++ ){
547 547 var n = nodes[i];
548 548 var target_element = display_element(n)
549 549 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
550 550 hide_node(target_element);
551 551 }
552 552 else{
553 553 show_node(target_element);
554 554 showing+=1;
555 555 }
556 556 }
557 557
558 558 // if repo_count is set update the number
559 559 var cnt = YUD.get('repo_count');
560 560 if(cnt){
561 561 YUD.get('repo_count').innerHTML = showing;
562 562 }
563 563
564 564 }
565 565 };
566 566
567 567 var tableTr = function(cls, body){
568 568 var _el = document.createElement('div');
569 569 var cont = new YAHOO.util.Element(body);
570 570 var comment_id = fromHTML(body).children[0].id.split('comment-')[1];
571 571 var id = 'comment-tr-{0}'.format(comment_id);
572 572 var _html = ('<table><tbody><tr id="{0}" class="{1}">'+
573 573 '<td class="lineno-inline new-inline"></td>'+
574 574 '<td class="lineno-inline old-inline"></td>'+
575 575 '<td>{2}</td>'+
576 576 '</tr></tbody></table>').format(id, cls, body);
577 577 _el.innerHTML = _html;
578 578 return _el.children[0].children[0].children[0];
579 579 };
580 580
581 581 /** comments **/
582 582 var removeInlineForm = function(form) {
583 583 form.parentNode.removeChild(form);
584 584 };
585 585
586 586 var createInlineForm = function(parent_tr, f_path, line) {
587 587 var tmpl = YUD.get('comment-inline-form-template').innerHTML;
588 588 tmpl = tmpl.format(f_path, line);
589 589 var form = tableTr('comment-form-inline',tmpl)
590 590
591 591 // create event for hide button
592 592 form = new YAHOO.util.Element(form);
593 593 var form_hide_button = new YAHOO.util.Element(YUD.getElementsByClassName('hide-inline-form',null,form)[0]);
594 594 form_hide_button.on('click', function(e) {
595 595 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
596 596 if(YUD.hasClass(newtr.nextElementSibling,'inline-comments-button')){
597 597 YUD.setStyle(newtr.nextElementSibling,'display','');
598 598 }
599 599 removeInlineForm(newtr);
600 600 YUD.removeClass(parent_tr, 'form-open');
601 601 YUD.removeClass(parent_tr, 'hl-comment');
602 602
603 603 });
604 604
605 605 return form
606 606 };
607 607
608 608 /**
609 609 * Inject inline comment for on given TR this tr should be always an .line
610 610 * tr containing the line. Code will detect comment, and always put the comment
611 611 * block at the very bottom
612 612 */
613 613 var injectInlineForm = function(tr){
614 614 if(!YUD.hasClass(tr, 'line')){
615 615 return
616 616 }
617 617 var submit_url = AJAX_COMMENT_URL;
618 618 var _td = YUD.getElementsByClassName('code',null,tr)[0];
619 619 if(YUD.hasClass(tr,'form-open') || YUD.hasClass(tr,'context') || YUD.hasClass(_td,'no-comment')){
620 620 return
621 621 }
622 622 YUD.addClass(tr,'form-open');
623 623 YUD.addClass(tr,'hl-comment');
624 624 var node = YUD.getElementsByClassName('full_f_path',null,tr.parentNode.parentNode.parentNode)[0];
625 625 var f_path = YUD.getAttribute(node,'path');
626 626 var lineno = getLineNo(tr);
627 627 var form = createInlineForm(tr, f_path, lineno, submit_url);
628 628
629 629 var parent = tr;
630 630 while (1){
631 631 var n = parent.nextElementSibling;
632 632 // next element are comments !
633 633 if(YUD.hasClass(n,'inline-comments')){
634 634 parent = n;
635 635 }
636 636 else{
637 637 break;
638 638 }
639 639 }
640 640 YUD.insertAfter(form,parent);
641 641 var f = YUD.get(form);
642 642 var overlay = YUD.getElementsByClassName('overlay',null,f)[0];
643 643 var _form = YUD.getElementsByClassName('inline-form',null,f)[0];
644 644
645 645 YUE.on(YUD.get(_form), 'submit',function(e){
646 646 YUE.preventDefault(e);
647 647
648 648 //ajax submit
649 649 var text = YUD.get('text_'+lineno).value;
650 650 var postData = {
651 651 'text':text,
652 652 'f_path':f_path,
653 653 'line':lineno
654 654 };
655 655
656 656 if(lineno === undefined){
657 657 alert('missing line !');
658 658 return
659 659 }
660 660 if(f_path === undefined){
661 661 alert('missing file path !');
662 662 return
663 663 }
664 664
665 665 if(text == ""){
666 666 return
667 667 }
668 668
669 669 var success = function(o){
670 670 YUD.removeClass(tr, 'form-open');
671 671 removeInlineForm(f);
672 672 var json_data = JSON.parse(o.responseText);
673 673 renderInlineComment(json_data);
674 674 };
675 675
676 676 if (YUD.hasClass(overlay,'overlay')){
677 677 var w = _form.offsetWidth;
678 678 var h = _form.offsetHeight;
679 679 YUD.setStyle(overlay,'width',w+'px');
680 680 YUD.setStyle(overlay,'height',h+'px');
681 681 }
682 682 YUD.addClass(overlay, 'submitting');
683 683
684 684 ajaxPOST(submit_url, postData, success);
685 685 });
686 686
687 687 setTimeout(function(){
688 688 // callbacks
689 689 tooltip_activate();
690 690 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
691 691 _USERS_AC_DATA, _GROUPS_AC_DATA);
692 692 var _e = YUD.get('text_'+lineno);
693 693 if(_e){
694 694 _e.focus();
695 695 }
696 696 },10)
697 697 };
698 698
699 699 var deleteComment = function(comment_id){
700 700 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
701 701 var postData = {'_method':'delete'};
702 702 var success = function(o){
703 703 var n = YUD.get('comment-tr-'+comment_id);
704 704 var root = prevElementSibling(prevElementSibling(n));
705 705 n.parentNode.removeChild(n);
706 706
707 707 // scann nodes, and attach add button to last one
708 708 placeAddButton(root);
709 709 }
710 710 ajaxPOST(url,postData,success);
711 711 }
712 712
713 713 var updateReviewers = function(reviewers_ids){
714 714 if (reviewers_ids === undefined){
715 715 var reviewers_ids = [];
716 716 var ids = YUQ('#review_members input');
717 717 for(var i=0; i<ids.length;i++){
718 718 var id = ids[i].value
719 719 reviewers_ids.push(id);
720 720 }
721 721 }
722 722 var url = AJAX_UPDATE_PULLREQUEST;
723 723 var postData = {'_method':'put',
724 724 'reviewers_ids': reviewers_ids};
725 725 var success = function(o){
726 726 window.location.reload();
727 727 }
728 728 ajaxPOST(url,postData,success);
729 729 }
730 730
731 731 var createInlineAddButton = function(tr){
732 732
733 733 var label = TRANSLATION_MAP['add another comment'];
734 734
735 735 var html_el = document.createElement('div');
736 736 YUD.addClass(html_el, 'add-comment');
737 737 html_el.innerHTML = '<span class="ui-btn">{0}</span>'.format(label);
738 738
739 739 var add = new YAHOO.util.Element(html_el);
740 740 add.on('click', function(e) {
741 741 injectInlineForm(tr);
742 742 });
743 743 return add;
744 744 };
745 745
746 746 var getLineNo = function(tr) {
747 747 var line;
748 748 var o = tr.children[0].id.split('_');
749 749 var n = tr.children[1].id.split('_');
750 750
751 751 if (n.length >= 2) {
752 752 line = n[n.length-1];
753 753 } else if (o.length >= 2) {
754 754 line = o[o.length-1];
755 755 }
756 756
757 757 return line
758 758 };
759 759
760 760 var placeAddButton = function(target_tr){
761 761 if(!target_tr){
762 762 return
763 763 }
764 764 var last_node = target_tr;
765 765 //scann
766 766 while (1){
767 767 var n = last_node.nextElementSibling;
768 768 // next element are comments !
769 769 if(YUD.hasClass(n,'inline-comments')){
770 770 last_node = n;
771 771 //also remove the comment button from previous
772 772 var comment_add_buttons = YUD.getElementsByClassName('add-comment',null,last_node);
773 773 for(var i=0;i<comment_add_buttons.length;i++){
774 774 var b = comment_add_buttons[i];
775 775 b.parentNode.removeChild(b);
776 776 }
777 777 }
778 778 else{
779 779 break;
780 780 }
781 781 }
782 782
783 783 var add = createInlineAddButton(target_tr);
784 784 // get the comment div
785 785 var comment_block = YUD.getElementsByClassName('comment',null,last_node)[0];
786 786 // attach add button
787 787 YUD.insertAfter(add,comment_block);
788 788 }
789 789
790 790 /**
791 791 * Places the inline comment into the changeset block in proper line position
792 792 */
793 793 var placeInline = function(target_container,lineno,html){
794 794 var lineid = "{0}_{1}".format(target_container,lineno);
795 795 var target_line = YUD.get(lineid);
796 796 var comment = new YAHOO.util.Element(tableTr('inline-comments',html))
797 797
798 798 // check if there are comments already !
799 799 var parent = target_line.parentNode;
800 800 var root_parent = parent;
801 801 while (1){
802 802 var n = parent.nextElementSibling;
803 803 // next element are comments !
804 804 if(YUD.hasClass(n,'inline-comments')){
805 805 parent = n;
806 806 }
807 807 else{
808 808 break;
809 809 }
810 810 }
811 811 // put in the comment at the bottom
812 812 YUD.insertAfter(comment,parent);
813 813
814 814 // scann nodes, and attach add button to last one
815 815 placeAddButton(root_parent);
816 816
817 817 return target_line;
818 818 }
819 819
820 820 /**
821 821 * make a single inline comment and place it inside
822 822 */
823 823 var renderInlineComment = function(json_data){
824 824 try{
825 825 var html = json_data['rendered_text'];
826 826 var lineno = json_data['line_no'];
827 827 var target_id = json_data['target_id'];
828 828 placeInline(target_id, lineno, html);
829 829
830 830 }catch(e){
831 831 console.log(e);
832 832 }
833 833 }
834 834
835 835 /**
836 836 * Iterates over all the inlines, and places them inside proper blocks of data
837 837 */
838 838 var renderInlineComments = function(file_comments){
839 839 for (f in file_comments){
840 840 // holding all comments for a FILE
841 841 var box = file_comments[f];
842 842
843 843 var target_id = YUD.getAttribute(box,'target_id');
844 844 // actually comments with line numbers
845 845 var comments = box.children;
846 846 for(var i=0; i<comments.length; i++){
847 847 var data = {
848 848 'rendered_text': comments[i].outerHTML,
849 849 'line_no': YUD.getAttribute(comments[i],'line'),
850 850 'target_id': target_id
851 851 }
852 852 renderInlineComment(data);
853 853 }
854 854 }
855 855 }
856 856
857 857 var removeReviewer = function(reviewer_id){
858 858 var el = YUD.get('reviewer_{0}'.format(reviewer_id));
859 859 if (el.parentNode !== undefined){
860 860 el.parentNode.removeChild(el);
861 861 }
862 862 updateReviewers();
863 863 }
864 864
865 865 var fileBrowserListeners = function(current_url, node_list_url, url_base){
866 866 var current_url_branch = +"?branch=__BRANCH__";
867 867
868 868 YUE.on('stay_at_branch','click',function(e){
869 869 if(e.target.checked){
870 870 var uri = current_url_branch;
871 871 uri = uri.replace('__BRANCH__',e.target.value);
872 872 window.location = uri;
873 873 }
874 874 else{
875 875 window.location = current_url;
876 876 }
877 877 })
878 878
879 879 var n_filter = YUD.get('node_filter');
880 880 var F = YAHOO.namespace('node_filter');
881 881
882 882 F.filterTimeout = null;
883 883 var nodes = null;
884 884
885 885 F.initFilter = function(){
886 886 YUD.setStyle('node_filter_box_loading','display','');
887 887 YUD.setStyle('search_activate_id','display','none');
888 888 YUD.setStyle('add_node_id','display','none');
889 889 YUC.initHeader('X-PARTIAL-XHR',true);
890 890 YUC.asyncRequest('GET', node_list_url, {
891 891 success:function(o){
892 892 nodes = JSON.parse(o.responseText).nodes;
893 893 YUD.setStyle('node_filter_box_loading','display','none');
894 894 YUD.setStyle('node_filter_box','display','');
895 895 n_filter.focus();
896 896 if(YUD.hasClass(n_filter,'init')){
897 897 n_filter.value = '';
898 898 YUD.removeClass(n_filter,'init');
899 899 }
900 900 },
901 901 failure:function(o){
902 902 console.log('failed to load');
903 903 }
904 904 },null);
905 905 }
906 906
907 907 F.updateFilter = function(e) {
908 908
909 909 return function(){
910 910 // Reset timeout
911 911 F.filterTimeout = null;
912 912 var query = e.target.value.toLowerCase();
913 913 var match = [];
914 914 var matches = 0;
915 915 var matches_max = 20;
916 916 if (query != ""){
917 917 for(var i=0;i<nodes.length;i++){
918 918
919 919 var pos = nodes[i].name.toLowerCase().indexOf(query)
920 920 if(query && pos != -1){
921 921
922 922 matches++
923 923 //show only certain amount to not kill browser
924 924 if (matches > matches_max){
925 925 break;
926 926 }
927 927
928 928 var n = nodes[i].name;
929 929 var t = nodes[i].type;
930 930 var n_hl = n.substring(0,pos)
931 931 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
932 932 +n.substring(pos+query.length)
933 933 var new_url = url_base.replace('__FPATH__',n);
934 934 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
935 935 }
936 936 if(match.length >= matches_max){
937 937 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['search truncated']));
938 938 }
939 939 }
940 940 }
941 941 if(query != ""){
942 942 YUD.setStyle('tbody','display','none');
943 943 YUD.setStyle('tbody_filtered','display','');
944 944
945 945 if (match.length==0){
946 946 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['no matching files']));
947 947 }
948 948
949 949 YUD.get('tbody_filtered').innerHTML = match.join("");
950 950 }
951 951 else{
952 952 YUD.setStyle('tbody','display','');
953 953 YUD.setStyle('tbody_filtered','display','none');
954 954 }
955 955
956 956 }
957 957 };
958 958
959 959 YUE.on(YUD.get('filter_activate'),'click',function(){
960 960 F.initFilter();
961 961 })
962 962 YUE.on(n_filter,'click',function(){
963 963 if(YUD.hasClass(n_filter,'init')){
964 964 n_filter.value = '';
965 965 YUD.removeClass(n_filter,'init');
966 966 }
967 967 });
968 968 YUE.on(n_filter,'keyup',function(e){
969 969 clearTimeout(F.filterTimeout);
970 970 F.filterTimeout = setTimeout(F.updateFilter(e),600);
971 971 });
972 972 };
973 973
974 974
975 975 var initCodeMirror = function(textAreadId,resetUrl){
976 976 var myCodeMirror = CodeMirror.fromTextArea(YUD.get(textAreadId),{
977 977 mode: "null",
978 978 lineNumbers:true
979 979 });
980 980 YUE.on('reset','click',function(e){
981 981 window.location=resetUrl
982 982 });
983 983
984 984 YUE.on('file_enable','click',function(){
985 985 YUD.setStyle('editor_container','display','');
986 986 YUD.setStyle('upload_file_container','display','none');
987 987 YUD.setStyle('filename_container','display','');
988 988 });
989 989
990 990 YUE.on('upload_file_enable','click',function(){
991 991 YUD.setStyle('editor_container','display','none');
992 992 YUD.setStyle('upload_file_container','display','');
993 993 YUD.setStyle('filename_container','display','none');
994 994 });
995 995 };
996 996
997 997
998 998
999 999 var getIdentNode = function(n){
1000 1000 //iterate thru nodes untill matched interesting node !
1001 1001
1002 1002 if (typeof n == 'undefined'){
1003 1003 return -1
1004 1004 }
1005 1005
1006 1006 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
1007 1007 return n
1008 1008 }
1009 1009 else{
1010 1010 return getIdentNode(n.parentNode);
1011 1011 }
1012 1012 };
1013 1013
1014 1014 var getSelectionLink = function(e) {
1015 1015
1016 1016 //get selection from start/to nodes
1017 1017 if (typeof window.getSelection != "undefined") {
1018 1018 s = window.getSelection();
1019 1019
1020 1020 from = getIdentNode(s.anchorNode);
1021 1021 till = getIdentNode(s.focusNode);
1022 1022
1023 1023 f_int = parseInt(from.id.replace('L',''));
1024 1024 t_int = parseInt(till.id.replace('L',''));
1025 1025
1026 1026 if (f_int > t_int){
1027 1027 //highlight from bottom
1028 1028 offset = -35;
1029 1029 ranges = [t_int,f_int];
1030 1030
1031 1031 }
1032 1032 else{
1033 1033 //highligth from top
1034 1034 offset = 35;
1035 1035 ranges = [f_int,t_int];
1036 1036 }
1037 1037 // if we select more than 2 lines
1038 1038 if (ranges[0] != ranges[1]){
1039 1039 if(YUD.get('linktt') == null){
1040 1040 hl_div = document.createElement('div');
1041 1041 hl_div.id = 'linktt';
1042 1042 }
1043 1043 hl_div.innerHTML = '';
1044 1044
1045 1045 anchor = '#L'+ranges[0]+'-'+ranges[1];
1046 1046 var link = document.createElement('a');
1047 1047 link.href = location.href.substring(0,location.href.indexOf('#'))+anchor;
1048 1048 link.innerHTML = _TM['Selection link'];
1049 1049 hl_div.appendChild(link);
1050 1050 YUD.get('body').appendChild(hl_div);
1051 1051
1052 1052 xy = YUD.getXY(till.id);
1053 1053
1054 1054 YUD.addClass('linktt', 'hl-tip-box');
1055 1055 YUD.setStyle('linktt','top',xy[1]+offset+'px');
1056 1056 YUD.setStyle('linktt','left',xy[0]+'px');
1057 1057 YUD.setStyle('linktt','visibility','visible');
1058 1058
1059 1059 }
1060 1060 else{
1061 1061 YUD.setStyle('linktt','visibility','hidden');
1062 1062 }
1063 1063 }
1064 1064 };
1065 1065
1066 1066 var deleteNotification = function(url, notification_id,callbacks){
1067 1067 var callback = {
1068 1068 success:function(o){
1069 1069 var obj = YUD.get(String("notification_"+notification_id));
1070 1070 if(obj.parentNode !== undefined){
1071 1071 obj.parentNode.removeChild(obj);
1072 1072 }
1073 1073 _run_callbacks(callbacks);
1074 1074 },
1075 1075 failure:function(o){
1076 1076 alert("error");
1077 1077 },
1078 1078 };
1079 1079 var postData = '_method=delete';
1080 1080 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1081 1081 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1082 1082 callback, postData);
1083 1083 };
1084 1084
1085 1085 var readNotification = function(url, notification_id,callbacks){
1086 1086 var callback = {
1087 1087 success:function(o){
1088 1088 var obj = YUD.get(String("notification_"+notification_id));
1089 1089 YUD.removeClass(obj, 'unread');
1090 1090 var r_button = YUD.getElementsByClassName('read-notification',null,obj.children[0])[0];
1091 1091
1092 1092 if(r_button.parentNode !== undefined){
1093 1093 r_button.parentNode.removeChild(r_button);
1094 1094 }
1095 1095 _run_callbacks(callbacks);
1096 1096 },
1097 1097 failure:function(o){
1098 1098 alert("error");
1099 1099 },
1100 1100 };
1101 1101 var postData = '_method=put';
1102 1102 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1103 1103 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1104 1104 callback, postData);
1105 1105 };
1106 1106
1107 1107 /** MEMBERS AUTOCOMPLETE WIDGET **/
1108 1108
1109 1109 var MembersAutoComplete = function (divid, cont, users_list, groups_list) {
1110 1110 var myUsers = users_list;
1111 1111 var myGroups = groups_list;
1112 1112
1113 1113 // Define a custom search function for the DataSource of users
1114 1114 var matchUsers = function (sQuery) {
1115 1115 // Case insensitive matching
1116 1116 var query = sQuery.toLowerCase();
1117 1117 var i = 0;
1118 1118 var l = myUsers.length;
1119 1119 var matches = [];
1120 1120
1121 1121 // Match against each name of each contact
1122 1122 for (; i < l; i++) {
1123 1123 contact = myUsers[i];
1124 1124 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1125 1125 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1126 1126 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1127 1127 matches[matches.length] = contact;
1128 1128 }
1129 1129 }
1130 1130 return matches;
1131 1131 };
1132 1132
1133 1133 // Define a custom search function for the DataSource of usersGroups
1134 1134 var matchGroups = function (sQuery) {
1135 1135 // Case insensitive matching
1136 1136 var query = sQuery.toLowerCase();
1137 1137 var i = 0;
1138 1138 var l = myGroups.length;
1139 1139 var matches = [];
1140 1140
1141 1141 // Match against each name of each contact
1142 1142 for (; i < l; i++) {
1143 1143 matched_group = myGroups[i];
1144 1144 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1145 1145 matches[matches.length] = matched_group;
1146 1146 }
1147 1147 }
1148 1148 return matches;
1149 1149 };
1150 1150
1151 1151 //match all
1152 1152 var matchAll = function (sQuery) {
1153 1153 u = matchUsers(sQuery);
1154 1154 g = matchGroups(sQuery);
1155 1155 return u.concat(g);
1156 1156 };
1157 1157
1158 1158 // DataScheme for members
1159 1159 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
1160 1160 memberDS.responseSchema = {
1161 1161 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
1162 1162 };
1163 1163
1164 1164 // DataScheme for owner
1165 1165 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1166 1166 ownerDS.responseSchema = {
1167 1167 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1168 1168 };
1169 1169
1170 1170 // Instantiate AutoComplete for perms
1171 1171 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
1172 1172 membersAC.useShadow = false;
1173 1173 membersAC.resultTypeList = false;
1174 1174 membersAC.animVert = false;
1175 1175 membersAC.animHoriz = false;
1176 1176 membersAC.animSpeed = 0.1;
1177 1177
1178 1178 // Instantiate AutoComplete for owner
1179 1179 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
1180 1180 ownerAC.useShadow = false;
1181 1181 ownerAC.resultTypeList = false;
1182 1182 ownerAC.animVert = false;
1183 1183 ownerAC.animHoriz = false;
1184 1184 ownerAC.animSpeed = 0.1;
1185 1185
1186 1186 // Helper highlight function for the formatter
1187 1187 var highlightMatch = function (full, snippet, matchindex) {
1188 1188 return full.substring(0, matchindex)
1189 1189 + "<span class='match'>"
1190 1190 + full.substr(matchindex, snippet.length)
1191 1191 + "</span>" + full.substring(matchindex + snippet.length);
1192 1192 };
1193 1193
1194 1194 // Custom formatter to highlight the matching letters
1195 1195 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
1196 1196 var query = sQuery.toLowerCase();
1197 1197 var _gravatar = function(res, em, group){
1198 1198 if (group !== undefined){
1199 1199 em = '/images/icons/group.png'
1200 1200 }
1201 1201 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1202 1202 return tmpl.format(em,res)
1203 1203 }
1204 1204 // group
1205 1205 if (oResultData.grname != undefined) {
1206 1206 var grname = oResultData.grname;
1207 1207 var grmembers = oResultData.grmembers;
1208 1208 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1209 1209 var grprefix = "{0}: ".format(_TM['Group']);
1210 1210 var grsuffix = " (" + grmembers + " )";
1211 1211 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1212 1212
1213 1213 if (grnameMatchIndex > -1) {
1214 1214 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1215 1215 }
1216 1216 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1217 1217 // Users
1218 1218 } else if (oResultData.nname != undefined) {
1219 1219 var fname = oResultData.fname || "";
1220 1220 var lname = oResultData.lname || "";
1221 1221 var nname = oResultData.nname;
1222 1222
1223 1223 // Guard against null value
1224 1224 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1225 1225 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1226 1226 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1227 1227 displayfname, displaylname, displaynname;
1228 1228
1229 1229 if (fnameMatchIndex > -1) {
1230 1230 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1231 1231 } else {
1232 1232 displayfname = fname;
1233 1233 }
1234 1234
1235 1235 if (lnameMatchIndex > -1) {
1236 1236 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1237 1237 } else {
1238 1238 displaylname = lname;
1239 1239 }
1240 1240
1241 1241 if (nnameMatchIndex > -1) {
1242 1242 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1243 1243 } else {
1244 1244 displaynname = nname ? "(" + nname + ")" : "";
1245 1245 }
1246 1246
1247 1247 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1248 1248 } else {
1249 1249 return '';
1250 1250 }
1251 1251 };
1252 1252 membersAC.formatResult = custom_formatter;
1253 1253 ownerAC.formatResult = custom_formatter;
1254 1254
1255 1255 var myHandler = function (sType, aArgs) {
1256 1256 var nextId = divid.split('perm_new_member_name_')[1];
1257 1257 var myAC = aArgs[0]; // reference back to the AC instance
1258 1258 var elLI = aArgs[1]; // reference to the selected LI element
1259 1259 var oData = aArgs[2]; // object literal of selected item's result data
1260 1260 //fill the autocomplete with value
1261 1261 if (oData.nname != undefined) {
1262 1262 //users
1263 1263 myAC.getInputEl().value = oData.nname;
1264 1264 YUD.get('perm_new_member_type_'+nextId).value = 'user';
1265 1265 } else {
1266 1266 //groups
1267 1267 myAC.getInputEl().value = oData.grname;
1268 1268 YUD.get('perm_new_member_type_'+nextId).value = 'users_group';
1269 1269 }
1270 1270 };
1271 1271
1272 1272 membersAC.itemSelectEvent.subscribe(myHandler);
1273 1273 if(ownerAC.itemSelectEvent){
1274 1274 ownerAC.itemSelectEvent.subscribe(myHandler);
1275 1275 }
1276 1276
1277 1277 return {
1278 1278 memberDS: memberDS,
1279 1279 ownerDS: ownerDS,
1280 1280 membersAC: membersAC,
1281 1281 ownerAC: ownerAC,
1282 1282 };
1283 1283 }
1284 1284
1285 1285
1286 1286 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1287 1287 var myUsers = users_list;
1288 1288 var myGroups = groups_list;
1289 1289
1290 1290 // Define a custom search function for the DataSource of users
1291 1291 var matchUsers = function (sQuery) {
1292 1292 var org_sQuery = sQuery;
1293 1293 if(this.mentionQuery == null){
1294 1294 return []
1295 1295 }
1296 1296 sQuery = this.mentionQuery;
1297 1297 // Case insensitive matching
1298 1298 var query = sQuery.toLowerCase();
1299 1299 var i = 0;
1300 1300 var l = myUsers.length;
1301 1301 var matches = [];
1302 1302
1303 1303 // Match against each name of each contact
1304 1304 for (; i < l; i++) {
1305 1305 contact = myUsers[i];
1306 1306 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1307 1307 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1308 1308 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1309 1309 matches[matches.length] = contact;
1310 1310 }
1311 1311 }
1312 1312 return matches
1313 1313 };
1314 1314
1315 1315 //match all
1316 1316 var matchAll = function (sQuery) {
1317 1317 u = matchUsers(sQuery);
1318 1318 return u
1319 1319 };
1320 1320
1321 1321 // DataScheme for owner
1322 1322 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1323 1323
1324 1324 ownerDS.responseSchema = {
1325 1325 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1326 1326 };
1327 1327
1328 1328 // Instantiate AutoComplete for mentions
1329 1329 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1330 1330 ownerAC.useShadow = false;
1331 1331 ownerAC.resultTypeList = false;
1332 1332 ownerAC.suppressInputUpdate = true;
1333 1333 ownerAC.animVert = false;
1334 1334 ownerAC.animHoriz = false;
1335 1335 ownerAC.animSpeed = 0.1;
1336 1336
1337 1337 // Helper highlight function for the formatter
1338 1338 var highlightMatch = function (full, snippet, matchindex) {
1339 1339 return full.substring(0, matchindex)
1340 1340 + "<span class='match'>"
1341 1341 + full.substr(matchindex, snippet.length)
1342 1342 + "</span>" + full.substring(matchindex + snippet.length);
1343 1343 };
1344 1344
1345 1345 // Custom formatter to highlight the matching letters
1346 1346 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1347 1347 var org_sQuery = sQuery;
1348 1348 if(this.dataSource.mentionQuery != null){
1349 1349 sQuery = this.dataSource.mentionQuery;
1350 1350 }
1351 1351
1352 1352 var query = sQuery.toLowerCase();
1353 1353 var _gravatar = function(res, em, group){
1354 1354 if (group !== undefined){
1355 1355 em = '/images/icons/group.png'
1356 1356 }
1357 1357 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1358 1358 return tmpl.format(em,res)
1359 1359 }
1360 1360 if (oResultData.nname != undefined) {
1361 1361 var fname = oResultData.fname || "";
1362 1362 var lname = oResultData.lname || "";
1363 1363 var nname = oResultData.nname;
1364 1364
1365 1365 // Guard against null value
1366 1366 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1367 1367 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1368 1368 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1369 1369 displayfname, displaylname, displaynname;
1370 1370
1371 1371 if (fnameMatchIndex > -1) {
1372 1372 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1373 1373 } else {
1374 1374 displayfname = fname;
1375 1375 }
1376 1376
1377 1377 if (lnameMatchIndex > -1) {
1378 1378 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1379 1379 } else {
1380 1380 displaylname = lname;
1381 1381 }
1382 1382
1383 1383 if (nnameMatchIndex > -1) {
1384 1384 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1385 1385 } else {
1386 1386 displaynname = nname ? "(" + nname + ")" : "";
1387 1387 }
1388 1388
1389 1389 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1390 1390 } else {
1391 1391 return '';
1392 1392 }
1393 1393 };
1394 1394
1395 1395 if(ownerAC.itemSelectEvent){
1396 1396 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1397 1397
1398 1398 var myAC = aArgs[0]; // reference back to the AC instance
1399 1399 var elLI = aArgs[1]; // reference to the selected LI element
1400 1400 var oData = aArgs[2]; // object literal of selected item's result data
1401 1401 //fill the autocomplete with value
1402 1402 if (oData.nname != undefined) {
1403 1403 //users
1404 1404 //Replace the mention name with replaced
1405 1405 var re = new RegExp();
1406 1406 var org = myAC.getInputEl().value;
1407 1407 var chunks = myAC.dataSource.chunks
1408 1408 // replace middle chunk(the search term) with actuall match
1409 1409 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1410 1410 '@'+oData.nname+' ');
1411 1411 myAC.getInputEl().value = chunks.join('')
1412 1412 YUD.get(myAC.getInputEl()).focus(); // Y U NO WORK !?
1413 1413 } else {
1414 1414 //groups
1415 1415 myAC.getInputEl().value = oData.grname;
1416 1416 YUD.get('perm_new_member_type').value = 'users_group';
1417 1417 }
1418 1418 });
1419 1419 }
1420 1420
1421 1421 // in this keybuffer we will gather current value of search !
1422 1422 // since we need to get this just when someone does `@` then we do the
1423 1423 // search
1424 1424 ownerAC.dataSource.chunks = [];
1425 1425 ownerAC.dataSource.mentionQuery = null;
1426 1426
1427 1427 ownerAC.get_mention = function(msg, max_pos) {
1428 1428 var org = msg;
1429 1429 var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$')
1430 1430 var chunks = [];
1431 1431
1432 1432
1433 1433 // cut first chunk until curret pos
1434 1434 var to_max = msg.substr(0, max_pos);
1435 1435 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1436 1436 var msg2 = to_max.substr(at_pos);
1437 1437
1438 1438 chunks.push(org.substr(0,at_pos))// prefix chunk
1439 1439 chunks.push(msg2) // search chunk
1440 1440 chunks.push(org.substr(max_pos)) // postfix chunk
1441 1441
1442 1442 // clean up msg2 for filtering and regex match
1443 1443 var msg2 = msg2.lstrip(' ').lstrip('\n');
1444 1444
1445 1445 if(re.test(msg2)){
1446 1446 var unam = re.exec(msg2)[1];
1447 1447 return [unam, chunks];
1448 1448 }
1449 1449 return [null, null];
1450 1450 };
1451 1451
1452 1452 if (ownerAC.textboxKeyUpEvent){
1453 1453 ownerAC.textboxKeyUpEvent.subscribe(function(type, args){
1454 1454
1455 1455 var ac_obj = args[0];
1456 1456 var currentMessage = args[1];
1457 1457 var currentCaretPosition = args[0]._elTextbox.selectionStart;
1458 1458
1459 1459 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1460 1460 var curr_search = null;
1461 1461 if(unam[0]){
1462 1462 curr_search = unam[0];
1463 1463 }
1464 1464
1465 1465 ownerAC.dataSource.chunks = unam[1];
1466 1466 ownerAC.dataSource.mentionQuery = curr_search;
1467 1467
1468 1468 })
1469 1469 }
1470 1470 return {
1471 1471 ownerDS: ownerDS,
1472 1472 ownerAC: ownerAC,
1473 1473 };
1474 1474 }
1475 1475
1476 1476
1477 1477 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1478 1478 var myUsers = users_list;
1479 1479 var myGroups = groups_list;
1480 1480
1481 1481 // Define a custom search function for the DataSource of users
1482 1482 var matchUsers = function (sQuery) {
1483 1483 // Case insensitive matching
1484 1484 var query = sQuery.toLowerCase();
1485 1485 var i = 0;
1486 1486 var l = myUsers.length;
1487 1487 var matches = [];
1488 1488
1489 1489 // Match against each name of each contact
1490 1490 for (; i < l; i++) {
1491 1491 contact = myUsers[i];
1492 1492 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1493 1493 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1494 1494 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1495 1495 matches[matches.length] = contact;
1496 1496 }
1497 1497 }
1498 1498 return matches;
1499 1499 };
1500 1500
1501 1501 // Define a custom search function for the DataSource of usersGroups
1502 1502 var matchGroups = function (sQuery) {
1503 1503 // Case insensitive matching
1504 1504 var query = sQuery.toLowerCase();
1505 1505 var i = 0;
1506 1506 var l = myGroups.length;
1507 1507 var matches = [];
1508 1508
1509 1509 // Match against each name of each contact
1510 1510 for (; i < l; i++) {
1511 1511 matched_group = myGroups[i];
1512 1512 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1513 1513 matches[matches.length] = matched_group;
1514 1514 }
1515 1515 }
1516 1516 return matches;
1517 1517 };
1518 1518
1519 1519 //match all
1520 1520 var matchAll = function (sQuery) {
1521 1521 u = matchUsers(sQuery);
1522 1522 return u
1523 1523 };
1524 1524
1525 1525 // DataScheme for owner
1526 1526 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1527 1527
1528 1528 ownerDS.responseSchema = {
1529 1529 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1530 1530 };
1531 1531
1532 1532 // Instantiate AutoComplete for mentions
1533 1533 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1534 1534 reviewerAC.useShadow = false;
1535 1535 reviewerAC.resultTypeList = false;
1536 1536 reviewerAC.suppressInputUpdate = true;
1537 1537 reviewerAC.animVert = false;
1538 1538 reviewerAC.animHoriz = false;
1539 1539 reviewerAC.animSpeed = 0.1;
1540 1540
1541 1541 // Helper highlight function for the formatter
1542 1542 var highlightMatch = function (full, snippet, matchindex) {
1543 1543 return full.substring(0, matchindex)
1544 1544 + "<span class='match'>"
1545 1545 + full.substr(matchindex, snippet.length)
1546 1546 + "</span>" + full.substring(matchindex + snippet.length);
1547 1547 };
1548 1548
1549 1549 // Custom formatter to highlight the matching letters
1550 1550 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1551 1551 var org_sQuery = sQuery;
1552 1552 if(this.dataSource.mentionQuery != null){
1553 1553 sQuery = this.dataSource.mentionQuery;
1554 1554 }
1555 1555
1556 1556 var query = sQuery.toLowerCase();
1557 1557 var _gravatar = function(res, em, group){
1558 1558 if (group !== undefined){
1559 1559 em = '/images/icons/group.png'
1560 1560 }
1561 1561 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1562 1562 return tmpl.format(em,res)
1563 1563 }
1564 1564 if (oResultData.nname != undefined) {
1565 1565 var fname = oResultData.fname || "";
1566 1566 var lname = oResultData.lname || "";
1567 1567 var nname = oResultData.nname;
1568 1568
1569 1569 // Guard against null value
1570 1570 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1571 1571 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1572 1572 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1573 1573 displayfname, displaylname, displaynname;
1574 1574
1575 1575 if (fnameMatchIndex > -1) {
1576 1576 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1577 1577 } else {
1578 1578 displayfname = fname;
1579 1579 }
1580 1580
1581 1581 if (lnameMatchIndex > -1) {
1582 1582 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1583 1583 } else {
1584 1584 displaylname = lname;
1585 1585 }
1586 1586
1587 1587 if (nnameMatchIndex > -1) {
1588 1588 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1589 1589 } else {
1590 1590 displaynname = nname ? "(" + nname + ")" : "";
1591 1591 }
1592 1592
1593 1593 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1594 1594 } else {
1595 1595 return '';
1596 1596 }
1597 1597 };
1598 1598
1599 1599 //members cache to catch duplicates
1600 1600 reviewerAC.dataSource.cache = [];
1601 1601 // hack into select event
1602 1602 if(reviewerAC.itemSelectEvent){
1603 1603 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1604 1604
1605 1605 var myAC = aArgs[0]; // reference back to the AC instance
1606 1606 var elLI = aArgs[1]; // reference to the selected LI element
1607 1607 var oData = aArgs[2]; // object literal of selected item's result data
1608 1608 var members = YUD.get('review_members');
1609 1609 //fill the autocomplete with value
1610 1610
1611 1611 if (oData.nname != undefined) {
1612 1612 if (myAC.dataSource.cache.indexOf(oData.id) != -1){
1613 1613 return
1614 1614 }
1615 1615
1616 1616 var tmpl = '<li id="reviewer_{2}">'+
1617 1617 '<div class="reviewers_member">'+
1618 1618 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1619 1619 '<div style="float:left">{1}</div>'+
1620 1620 '<input type="hidden" value="{2}" name="review_members" />'+
1621 1621 '<span class="delete_icon action_button" onclick="removeReviewer({2})"></span>'+
1622 1622 '</div>'+
1623 1623 '</li>'
1624 1624
1625 1625 var displayname = "{0} {1} ({2})".format(oData.fname,oData.lname,oData.nname);
1626 1626 var element = tmpl.format(oData.gravatar_lnk,displayname,oData.id);
1627 1627 members.innerHTML += element;
1628 1628 myAC.dataSource.cache.push(oData.id);
1629 1629 YUD.get('user').value = ''
1630 1630 }
1631 1631 });
1632 1632 }
1633 1633 return {
1634 1634 ownerDS: ownerDS,
1635 1635 reviewerAC: reviewerAC,
1636 1636 };
1637 1637 }
1638 1638
1639 1639
1640 1640 /**
1641 1641 * QUICK REPO MENU
1642 1642 */
1643 1643 var quick_repo_menu = function(){
1644 1644 YUE.on(YUQ('.quick_repo_menu'),'mouseenter',function(e){
1645 1645 var menu = e.currentTarget.firstElementChild.firstElementChild;
1646 1646 if(YUD.hasClass(menu,'hidden')){
1647 1647 YUD.replaceClass(e.currentTarget,'hidden', 'active');
1648 1648 YUD.replaceClass(menu, 'hidden', 'active');
1649 1649 }
1650 1650 })
1651 1651 YUE.on(YUQ('.quick_repo_menu'),'mouseleave',function(e){
1652 1652 var menu = e.currentTarget.firstElementChild.firstElementChild;
1653 1653 if(YUD.hasClass(menu,'active')){
1654 1654 YUD.replaceClass(e.currentTarget, 'active', 'hidden');
1655 1655 YUD.replaceClass(menu, 'active', 'hidden');
1656 1656 }
1657 1657 })
1658 1658 };
1659 1659
1660 1660
1661 1661 /**
1662 1662 * TABLE SORTING
1663 1663 */
1664 1664
1665 1665 // returns a node from given html;
1666 1666 var fromHTML = function(html){
1667 1667 var _html = document.createElement('element');
1668 1668 _html.innerHTML = html;
1669 1669 return _html;
1670 1670 }
1671 1671 var get_rev = function(node){
1672 1672 var n = node.firstElementChild.firstElementChild;
1673 1673
1674 1674 if (n===null){
1675 1675 return -1
1676 1676 }
1677 1677 else{
1678 1678 out = n.firstElementChild.innerHTML.split(':')[0].replace('r','');
1679 1679 return parseInt(out);
1680 1680 }
1681 1681 }
1682 1682
1683 1683 var get_name = function(node){
1684 1684 var name = node.firstElementChild.children[2].innerHTML;
1685 1685 return name
1686 1686 }
1687 1687 var get_group_name = function(node){
1688 1688 var name = node.firstElementChild.children[1].innerHTML;
1689 1689 return name
1690 1690 }
1691 1691 var get_date = function(node){
1692 1692 var date_ = YUD.getAttribute(node.firstElementChild,'date');
1693 1693 return date_
1694 1694 }
1695 1695
1696 1696 var get_age = function(node){
1697 1697 return node
1698 1698 }
1699 1699
1700 1700 var get_link = function(node){
1701 1701 return node.firstElementChild.text;
1702 1702 }
1703 1703
1704 1704 var revisionSort = function(a, b, desc, field) {
1705 1705
1706 1706 var a_ = fromHTML(a.getData(field));
1707 1707 var b_ = fromHTML(b.getData(field));
1708 1708
1709 1709 // extract revisions from string nodes
1710 1710 a_ = get_rev(a_)
1711 1711 b_ = get_rev(b_)
1712 1712
1713 1713 var comp = YAHOO.util.Sort.compare;
1714 1714 var compState = comp(a_, b_, desc);
1715 1715 return compState;
1716 1716 };
1717 1717 var ageSort = function(a, b, desc, field) {
1718 1718 var a_ = fromHTML(a.getData(field));
1719 1719 var b_ = fromHTML(b.getData(field));
1720 1720
1721 1721 // extract name from table
1722 1722 a_ = get_date(a_)
1723 1723 b_ = get_date(b_)
1724 1724
1725 1725 var comp = YAHOO.util.Sort.compare;
1726 1726 var compState = comp(a_, b_, desc);
1727 1727 return compState;
1728 1728 };
1729 1729
1730 1730 var lastLoginSort = function(a, b, desc, field) {
1731 1731 var a_ = a.getData('last_login_raw') || 0;
1732 1732 var b_ = b.getData('last_login_raw') || 0;
1733 1733
1734 1734 var comp = YAHOO.util.Sort.compare;
1735 1735 var compState = comp(a_, b_, desc);
1736 1736 return compState;
1737 1737 };
1738 1738
1739 1739 var nameSort = function(a, b, desc, field) {
1740 1740 var a_ = fromHTML(a.getData(field));
1741 1741 var b_ = fromHTML(b.getData(field));
1742 1742
1743 1743 // extract name from table
1744 1744 a_ = get_name(a_)
1745 1745 b_ = get_name(b_)
1746 1746
1747 1747 var comp = YAHOO.util.Sort.compare;
1748 1748 var compState = comp(a_, b_, desc);
1749 1749 return compState;
1750 1750 };
1751 1751
1752 1752 var permNameSort = function(a, b, desc, field) {
1753 1753 var a_ = fromHTML(a.getData(field));
1754 1754 var b_ = fromHTML(b.getData(field));
1755 1755 // extract name from table
1756 1756
1757 1757 a_ = a_.children[0].innerHTML;
1758 1758 b_ = b_.children[0].innerHTML;
1759 1759
1760 1760 var comp = YAHOO.util.Sort.compare;
1761 1761 var compState = comp(a_, b_, desc);
1762 1762 return compState;
1763 1763 };
1764 1764
1765 1765 var groupNameSort = function(a, b, desc, field) {
1766 1766 var a_ = fromHTML(a.getData(field));
1767 1767 var b_ = fromHTML(b.getData(field));
1768 1768
1769 1769 // extract name from table
1770 1770 a_ = get_group_name(a_)
1771 1771 b_ = get_group_name(b_)
1772 1772
1773 1773 var comp = YAHOO.util.Sort.compare;
1774 1774 var compState = comp(a_, b_, desc);
1775 1775 return compState;
1776 1776 };
1777 1777 var dateSort = function(a, b, desc, field) {
1778 1778 var a_ = fromHTML(a.getData(field));
1779 1779 var b_ = fromHTML(b.getData(field));
1780 1780
1781 1781 // extract name from table
1782 1782 a_ = get_date(a_)
1783 1783 b_ = get_date(b_)
1784 1784
1785 1785 var comp = YAHOO.util.Sort.compare;
1786 1786 var compState = comp(a_, b_, desc);
1787 1787 return compState;
1788 1788 };
1789 1789
1790 1790 var linkSort = function(a, b, desc, field) {
1791 1791 var a_ = fromHTML(a.getData(field));
1792 1792 var b_ = fromHTML(a.getData(field));
1793 1793
1794 1794 // extract url text from string nodes
1795 1795 a_ = get_link(a_)
1796 1796 b_ = get_link(b_)
1797 1797
1798 1798 var comp = YAHOO.util.Sort.compare;
1799 1799 var compState = comp(a_, b_, desc);
1800 1800 return compState;
1801 1801 }
1802 1802
1803 1803 var addPermAction = function(_html, users_list, groups_list){
1804 1804 var elmts = YUD.getElementsByClassName('last_new_member');
1805 1805 var last_node = elmts[elmts.length-1];
1806 1806 if (last_node){
1807 1807 var next_id = (YUD.getElementsByClassName('new_members')).length;
1808 1808 _html = _html.format(next_id);
1809 1809 last_node.innerHTML = _html;
1810 1810 YUD.setStyle(last_node, 'display', '');
1811 1811 YUD.removeClass(last_node, 'last_new_member');
1812 1812 MembersAutoComplete("perm_new_member_name_"+next_id,
1813 1813 "perm_container_"+next_id, users_list, groups_list);
1814 1814 //create new last NODE
1815 1815 var el = document.createElement('tr');
1816 1816 el.id = 'add_perm_input';
1817 1817 YUD.addClass(el,'last_new_member');
1818 1818 YUD.addClass(el,'new_members');
1819 1819 YUD.insertAfter(el, last_node);
1820 1820 }
1821 1821 }
1822 1822
1823 1823 /* Multi selectors */
1824 1824
1825 1825 var MultiSelectWidget = function(selected_id, available_id, form_id){
1826 1826
1827 1827
1828 1828 //definition of containers ID's
1829 1829 var selected_container = selected_id;
1830 1830 var available_container = available_id;
1831 1831
1832 1832 //temp container for selected storage.
1833 1833 var cache = new Array();
1834 1834 var av_cache = new Array();
1835 1835 var c = YUD.get(selected_container);
1836 1836 var ac = YUD.get(available_container);
1837 1837
1838 1838 //get only selected options for further fullfilment
1839 1839 for(var i = 0;node =c.options[i];i++){
1840 1840 if(node.selected){
1841 1841 //push selected to my temp storage left overs :)
1842 1842 cache.push(node);
1843 1843 }
1844 1844 }
1845 1845
1846 1846 //get all available options to cache
1847 1847 for(var i = 0;node =ac.options[i];i++){
1848 1848 //push selected to my temp storage left overs :)
1849 1849 av_cache.push(node);
1850 1850 }
1851 1851
1852 1852 //fill available only with those not in choosen
1853 1853 ac.options.length=0;
1854 1854 tmp_cache = new Array();
1855 1855
1856 1856 for(var i = 0;node = av_cache[i];i++){
1857 1857 var add = true;
1858 1858 for(var i2 = 0;node_2 = cache[i2];i2++){
1859 1859 if(node.value == node_2.value){
1860 1860 add=false;
1861 1861 break;
1862 1862 }
1863 1863 }
1864 1864 if(add){
1865 1865 tmp_cache.push(new Option(node.text, node.value, false, false));
1866 1866 }
1867 1867 }
1868 1868
1869 1869 for(var i = 0;node = tmp_cache[i];i++){
1870 1870 ac.options[i] = node;
1871 1871 }
1872 1872
1873 1873 function prompts_action_callback(e){
1874 1874
1875 1875 var choosen = YUD.get(selected_container);
1876 1876 var available = YUD.get(available_container);
1877 1877
1878 1878 //get checked and unchecked options from field
1879 1879 function get_checked(from_field){
1880 1880 //temp container for storage.
1881 1881 var sel_cache = new Array();
1882 1882 var oth_cache = new Array();
1883 1883
1884 1884 for(var i = 0;node = from_field.options[i];i++){
1885 1885 if(node.selected){
1886 1886 //push selected fields :)
1887 1887 sel_cache.push(node);
1888 1888 }
1889 1889 else{
1890 1890 oth_cache.push(node)
1891 1891 }
1892 1892 }
1893 1893
1894 1894 return [sel_cache,oth_cache]
1895 1895 }
1896 1896
1897 1897 //fill the field with given options
1898 1898 function fill_with(field,options){
1899 1899 //clear firtst
1900 1900 field.options.length=0;
1901 1901 for(var i = 0;node = options[i];i++){
1902 1902 field.options[i]=new Option(node.text, node.value,
1903 1903 false, false);
1904 1904 }
1905 1905
1906 1906 }
1907 1907 //adds to current field
1908 1908 function add_to(field,options){
1909 1909 for(var i = 0;node = options[i];i++){
1910 1910 field.appendChild(new Option(node.text, node.value,
1911 1911 false, false));
1912 1912 }
1913 1913 }
1914 1914
1915 1915 // add action
1916 1916 if (this.id=='add_element'){
1917 1917 var c = get_checked(available);
1918 1918 add_to(choosen,c[0]);
1919 1919 fill_with(available,c[1]);
1920 1920 }
1921 1921 // remove action
1922 1922 if (this.id=='remove_element'){
1923 1923 var c = get_checked(choosen);
1924 1924 add_to(available,c[0]);
1925 1925 fill_with(choosen,c[1]);
1926 1926 }
1927 1927 // add all elements
1928 1928 if(this.id=='add_all_elements'){
1929 1929 for(var i=0; node = available.options[i];i++){
1930 1930 choosen.appendChild(new Option(node.text,
1931 1931 node.value, false, false));
1932 1932 }
1933 1933 available.options.length = 0;
1934 1934 }
1935 1935 //remove all elements
1936 1936 if(this.id=='remove_all_elements'){
1937 1937 for(var i=0; node = choosen.options[i];i++){
1938 1938 available.appendChild(new Option(node.text,
1939 1939 node.value, false, false));
1940 1940 }
1941 1941 choosen.options.length = 0;
1942 1942 }
1943 1943
1944 1944 }
1945 1945
1946 1946 YUE.addListener(['add_element','remove_element',
1947 1947 'add_all_elements','remove_all_elements'],'click',
1948 1948 prompts_action_callback)
1949 1949 if (form_id !== undefined) {
1950 1950 YUE.addListener(form_id,'submit',function(){
1951 1951 var choosen = YUD.get(selected_container);
1952 1952 for (var i = 0; i < choosen.options.length; i++) {
1953 1953 choosen.options[i].selected = 'selected';
1954 1954 }
1955 1955 });
1956 1956 }
1957 1957 }
@@ -1,122 +1,123 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <!DOCTYPE html>
3 3 <html xmlns="http://www.w3.org/1999/xhtml">
4 4 <head>
5 5 <title>${self.title()}</title>
6 6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 7 <meta name="robots" content="index, nofollow"/>
8 8 <link rel="icon" href="${h.url('/images/icons/database_gear.png')}" type="image/png" />
9 9
10 10 ## CSS ###
11 11 <%def name="css()">
12 12 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.rhodecode_version)}" media="screen"/>
13 13 <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css', ver=c.rhodecode_version)}"/>
14 14 ## EXTRA FOR CSS
15 15 ${self.css_extra()}
16 16 </%def>
17 17 <%def name="css_extra()">
18 18 </%def>
19 19
20 20 ${self.css()}
21 21
22 22 %if c.ga_code:
23 23 <!-- Analytics -->
24 24 <script type="text/javascript">
25 25 var _gaq = _gaq || [];
26 26 _gaq.push(['_setAccount', '${c.ga_code}']);
27 27 _gaq.push(['_trackPageview']);
28 28
29 29 (function() {
30 30 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
31 31 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
32 32 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
33 33 })();
34 34 </script>
35 35 %endif
36 36
37 37 ## JAVASCRIPT ##
38 38 <%def name="js()">
39 39 <script type="text/javascript">
40 40 //JS translations map
41 41 var TRANSLATION_MAP = {
42 42 'add another comment':'${_("add another comment")}',
43 43 'Stop following this repository':"${_('Stop following this repository')}",
44 44 'Start following this repository':"${_('Start following this repository')}",
45 45 'Group':"${_('Group')}",
46 46 'members':"${_('members')}",
47 47 'loading...':"${_('loading...')}",
48 48 'search truncated': "${_('search truncated')}",
49 49 'no matching files': "${_('no matching files')}",
50 50 'Open new pull request': "${_('Open new pull request')}",
51 51 'Open new pull request for selected changesets': "${_('Open new pull request for selected changesets')}",
52 52 'Show selected changes __S -> __E': "${_('Show selected changes __S -> __E')}",
53 53 'Selection link': "${_('Selection link')}",
54 54 };
55 55 var _TM = TRANSLATION_MAP;
56 56 var TOGGLE_FOLLOW_URL = "${h.url('toggle_following')}";
57 var LAZY_CS_URL = "${h.url('changeset_info', repo_name='__NAME__', revision='__REV__')}"
57 58 </script>
58 59 <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.rhodecode_version)}"></script>
59 60 <!--[if lt IE 9]>
60 61 <script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script>
61 62 <![endif]-->
62 63 <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.rhodecode_version)}"></script>
63 64 <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.rhodecode_version)}"></script>
64 65 <script type="text/javascript" src="${h.url('/js/rhodecode.js', ver=c.rhodecode_version)}"></script>
65 66 ## EXTRA FOR JS
66 67 ${self.js_extra()}
67 68 <script type="text/javascript">
68 69 (function(window,undefined){
69 70 // Prepare
70 71 var History = window.History; // Note: We are using a capital H instead of a lower h
71 72 if ( !History.enabled ) {
72 73 // History.js is disabled for this browser.
73 74 // This is because we can optionally choose to support HTML4 browsers or not.
74 75 return false;
75 76 }
76 77 })(window);
77 78
78 79 YUE.onDOMReady(function(){
79 80 tooltip_activate();
80 81 show_more_event();
81 82 show_changeset_tooltip();
82 83
83 84 YUE.on('quick_login_link','click',function(e){
84 85 // make sure we don't redirect
85 86 YUE.preventDefault(e);
86 87
87 88 if(YUD.hasClass('quick_login_link','enabled')){
88 89 YUD.setStyle('quick_login','display','none');
89 90 YUD.removeClass('quick_login_link','enabled');
90 91 }
91 92 else{
92 93 YUD.setStyle('quick_login','display','');
93 94 YUD.addClass('quick_login_link','enabled');
94 95 var usr = YUD.get('username');
95 96 if(usr){
96 97 usr.focus();
97 98 }
98 99 }
99 100 });
100 101 })
101 102 </script>
102 103 </%def>
103 104 <%def name="js_extra()"></%def>
104 105 ${self.js()}
105 106 <%def name="head_extra()"></%def>
106 107 ${self.head_extra()}
107 108 </head>
108 109 <body id="body">
109 110 ## IE hacks
110 111 <!--[if IE 7]>
111 112 <script>YUD.addClass(document.body,'ie7')</script>
112 113 <![endif]-->
113 114 <!--[if IE 8]>
114 115 <script>YUD.addClass(document.body,'ie8')</script>
115 116 <![endif]-->
116 117 <!--[if IE 9]>
117 118 <script>YUD.addClass(document.body,'ie9')</script>
118 119 <![endif]-->
119 120
120 121 ${next.body()}
121 122 </body>
122 123 </html>
General Comments 0
You need to be logged in to leave comments. Login now