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