##// END OF EJS Templates
rhodecode.js: implement array.filter for backward compatibility...
Mads Kiilerich -
r4161:f5157855 rhodecode-2.2.5-gpl
parent child Browse files
Show More
@@ -1,2038 +1,2077
1 /**
1 /**
2 RhodeCode JS Files
2 RhodeCode JS Files
3 **/
3 **/
4
4
5 if (typeof console == "undefined" || typeof console.log == "undefined"){
5 if (typeof console == "undefined" || typeof console.log == "undefined"){
6 console = { log: function() {} }
6 console = { log: function() {} }
7 }
7 }
8
8
9 /**
9 /**
10 * INJECT .format function into String
10 * INJECT .format function into String
11 * Usage: "My name is {0} {1}".format("Johny","Bravo")
11 * Usage: "My name is {0} {1}".format("Johny","Bravo")
12 * Return "My name is Johny Bravo"
12 * Return "My name is Johny Bravo"
13 * Inspired by https://gist.github.com/1049426
13 * Inspired by https://gist.github.com/1049426
14 */
14 */
15 String.prototype.format = function() {
15 String.prototype.format = function() {
16 function format() {
16 function format() {
17 var str = this;
17 var str = this;
18 var len = arguments.length+1;
18 var len = arguments.length+1;
19 var safe = undefined;
19 var safe = undefined;
20 var arg = undefined;
20 var arg = undefined;
21
21
22 // For each {0} {1} {n...} replace with the argument in that position. If
22 // For each {0} {1} {n...} replace with the argument in that position. If
23 // the argument is an object or an array it will be stringified to JSON.
23 // the argument is an object or an array it will be stringified to JSON.
24 for (var i=0; i < len; arg = arguments[i++]) {
24 for (var i=0; i < len; arg = arguments[i++]) {
25 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
25 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
26 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
26 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
27 }
27 }
28 return str;
28 return str;
29 }
29 }
30
30
31 // Save a reference of what may already exist under the property native.
31 // Save a reference of what may already exist under the property native.
32 // Allows for doing something like: if("".format.native) { /* use native */ }
32 // Allows for doing something like: if("".format.native) { /* use native */ }
33 format.native = String.prototype.format;
33 format.native = String.prototype.format;
34
34
35 // Replace the prototype property
35 // Replace the prototype property
36 return format;
36 return format;
37
37
38 }();
38 }();
39
39
40 String.prototype.strip = function(char) {
40 String.prototype.strip = function(char) {
41 if(char === undefined){
41 if(char === undefined){
42 char = '\\s';
42 char = '\\s';
43 }
43 }
44 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
44 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
45 }
45 }
46
46
47 String.prototype.lstrip = function(char) {
47 String.prototype.lstrip = function(char) {
48 if(char === undefined){
48 if(char === undefined){
49 char = '\\s';
49 char = '\\s';
50 }
50 }
51 return this.replace(new RegExp('^'+char+'+'),'');
51 return this.replace(new RegExp('^'+char+'+'),'');
52 }
52 }
53
53
54 String.prototype.rstrip = function(char) {
54 String.prototype.rstrip = function(char) {
55 if(char === undefined){
55 if(char === undefined){
56 char = '\\s';
56 char = '\\s';
57 }
57 }
58 return this.replace(new RegExp(''+char+'+$'),'');
58 return this.replace(new RegExp(''+char+'+$'),'');
59 }
59 }
60
60
61
61
62 if(!Array.prototype.indexOf) {
62 if(!Array.prototype.indexOf) {
63 Array.prototype.indexOf = function(needle) {
63 Array.prototype.indexOf = function(needle) {
64 for(var i = 0; i < this.length; i++) {
64 for(var i = 0; i < this.length; i++) {
65 if(this[i] === needle) {
65 if(this[i] === needle) {
66 return i;
66 return i;
67 }
67 }
68 }
68 }
69 return -1;
69 return -1;
70 };
70 };
71 }
71 }
72
72
73 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Compatibility
74 under MIT license / public domain, see
75 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
76 if (!Array.prototype.filter)
77 {
78 Array.prototype.filter = function(fun /*, thisArg */)
79 {
80 "use strict";
81
82 if (this === void 0 || this === null)
83 throw new TypeError();
84
85 var t = Object(this);
86 var len = t.length >>> 0;
87 if (typeof fun !== "function")
88 throw new TypeError();
89
90 var res = [];
91 var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
92 for (var i = 0; i < len; i++)
93 {
94 if (i in t)
95 {
96 var val = t[i];
97
98 // NOTE: Technically this should Object.defineProperty at
99 // the next index, as push can be affected by
100 // properties on Object.prototype and Array.prototype.
101 // But that method's new, and collisions should be
102 // rare, so use the more-compatible alternative.
103 if (fun.call(thisArg, val, i, t))
104 res.push(val);
105 }
106 }
107
108 return res;
109 };
110 }
111
73 /**
112 /**
74 * A customized version of PyRoutes.JS from https://pypi.python.org/pypi/pyroutes.js/
113 * A customized version of PyRoutes.JS from https://pypi.python.org/pypi/pyroutes.js/
75 * which is copyright Stephane Klein and was made available under the BSD License.
114 * which is copyright Stephane Klein and was made available under the BSD License.
76 *
115 *
77 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
116 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
78 */
117 */
79 var pyroutes = (function() {
118 var pyroutes = (function() {
80 // access global map defined in special file pyroutes
119 // access global map defined in special file pyroutes
81 var matchlist = PROUTES_MAP;
120 var matchlist = PROUTES_MAP;
82 var sprintf = (function() {
121 var sprintf = (function() {
83 function get_type(variable) {
122 function get_type(variable) {
84 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
123 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
85 }
124 }
86 function str_repeat(input, multiplier) {
125 function str_repeat(input, multiplier) {
87 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
126 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
88 return output.join('');
127 return output.join('');
89 }
128 }
90
129
91 var str_format = function() {
130 var str_format = function() {
92 if (!str_format.cache.hasOwnProperty(arguments[0])) {
131 if (!str_format.cache.hasOwnProperty(arguments[0])) {
93 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
132 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
94 }
133 }
95 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
134 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
96 };
135 };
97
136
98 str_format.format = function(parse_tree, argv) {
137 str_format.format = function(parse_tree, argv) {
99 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
138 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
100 for (i = 0; i < tree_length; i++) {
139 for (i = 0; i < tree_length; i++) {
101 node_type = get_type(parse_tree[i]);
140 node_type = get_type(parse_tree[i]);
102 if (node_type === 'string') {
141 if (node_type === 'string') {
103 output.push(parse_tree[i]);
142 output.push(parse_tree[i]);
104 }
143 }
105 else if (node_type === 'array') {
144 else if (node_type === 'array') {
106 match = parse_tree[i]; // convenience purposes only
145 match = parse_tree[i]; // convenience purposes only
107 if (match[2]) { // keyword argument
146 if (match[2]) { // keyword argument
108 arg = argv[cursor];
147 arg = argv[cursor];
109 for (k = 0; k < match[2].length; k++) {
148 for (k = 0; k < match[2].length; k++) {
110 if (!arg.hasOwnProperty(match[2][k])) {
149 if (!arg.hasOwnProperty(match[2][k])) {
111 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
150 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
112 }
151 }
113 arg = arg[match[2][k]];
152 arg = arg[match[2][k]];
114 }
153 }
115 }
154 }
116 else if (match[1]) { // positional argument (explicit)
155 else if (match[1]) { // positional argument (explicit)
117 arg = argv[match[1]];
156 arg = argv[match[1]];
118 }
157 }
119 else { // positional argument (implicit)
158 else { // positional argument (implicit)
120 arg = argv[cursor++];
159 arg = argv[cursor++];
121 }
160 }
122
161
123 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
162 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
124 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
163 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
125 }
164 }
126 switch (match[8]) {
165 switch (match[8]) {
127 case 'b': arg = arg.toString(2); break;
166 case 'b': arg = arg.toString(2); break;
128 case 'c': arg = String.fromCharCode(arg); break;
167 case 'c': arg = String.fromCharCode(arg); break;
129 case 'd': arg = parseInt(arg, 10); break;
168 case 'd': arg = parseInt(arg, 10); break;
130 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
169 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
131 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
170 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
132 case 'o': arg = arg.toString(8); break;
171 case 'o': arg = arg.toString(8); break;
133 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
172 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
134 case 'u': arg = Math.abs(arg); break;
173 case 'u': arg = Math.abs(arg); break;
135 case 'x': arg = arg.toString(16); break;
174 case 'x': arg = arg.toString(16); break;
136 case 'X': arg = arg.toString(16).toUpperCase(); break;
175 case 'X': arg = arg.toString(16).toUpperCase(); break;
137 }
176 }
138 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
177 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
139 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
178 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
140 pad_length = match[6] - String(arg).length;
179 pad_length = match[6] - String(arg).length;
141 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
180 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
142 output.push(match[5] ? arg + pad : pad + arg);
181 output.push(match[5] ? arg + pad : pad + arg);
143 }
182 }
144 }
183 }
145 return output.join('');
184 return output.join('');
146 };
185 };
147
186
148 str_format.cache = {};
187 str_format.cache = {};
149
188
150 str_format.parse = function(fmt) {
189 str_format.parse = function(fmt) {
151 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
190 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
152 while (_fmt) {
191 while (_fmt) {
153 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
192 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
154 parse_tree.push(match[0]);
193 parse_tree.push(match[0]);
155 }
194 }
156 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
195 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
157 parse_tree.push('%');
196 parse_tree.push('%');
158 }
197 }
159 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
198 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
160 if (match[2]) {
199 if (match[2]) {
161 arg_names |= 1;
200 arg_names |= 1;
162 var field_list = [], replacement_field = match[2], field_match = [];
201 var field_list = [], replacement_field = match[2], field_match = [];
163 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
202 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
164 field_list.push(field_match[1]);
203 field_list.push(field_match[1]);
165 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
204 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
166 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
205 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
167 field_list.push(field_match[1]);
206 field_list.push(field_match[1]);
168 }
207 }
169 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
208 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
170 field_list.push(field_match[1]);
209 field_list.push(field_match[1]);
171 }
210 }
172 else {
211 else {
173 throw('[sprintf] huh?');
212 throw('[sprintf] huh?');
174 }
213 }
175 }
214 }
176 }
215 }
177 else {
216 else {
178 throw('[sprintf] huh?');
217 throw('[sprintf] huh?');
179 }
218 }
180 match[2] = field_list;
219 match[2] = field_list;
181 }
220 }
182 else {
221 else {
183 arg_names |= 2;
222 arg_names |= 2;
184 }
223 }
185 if (arg_names === 3) {
224 if (arg_names === 3) {
186 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
225 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
187 }
226 }
188 parse_tree.push(match);
227 parse_tree.push(match);
189 }
228 }
190 else {
229 else {
191 throw('[sprintf] huh?');
230 throw('[sprintf] huh?');
192 }
231 }
193 _fmt = _fmt.substring(match[0].length);
232 _fmt = _fmt.substring(match[0].length);
194 }
233 }
195 return parse_tree;
234 return parse_tree;
196 };
235 };
197
236
198 return str_format;
237 return str_format;
199 })();
238 })();
200
239
201 var vsprintf = function(fmt, argv) {
240 var vsprintf = function(fmt, argv) {
202 argv.unshift(fmt);
241 argv.unshift(fmt);
203 return sprintf.apply(null, argv);
242 return sprintf.apply(null, argv);
204 };
243 };
205 return {
244 return {
206 'url': function(route_name, params) {
245 'url': function(route_name, params) {
207 var result = route_name;
246 var result = route_name;
208 if (typeof(params) != 'object'){
247 if (typeof(params) != 'object'){
209 params = {};
248 params = {};
210 }
249 }
211 if (matchlist.hasOwnProperty(route_name)) {
250 if (matchlist.hasOwnProperty(route_name)) {
212 var route = matchlist[route_name];
251 var route = matchlist[route_name];
213 // param substitution
252 // param substitution
214 for(var i=0; i < route[1].length; i++) {
253 for(var i=0; i < route[1].length; i++) {
215 if (!params.hasOwnProperty(route[1][i]))
254 if (!params.hasOwnProperty(route[1][i]))
216 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
255 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
217 }
256 }
218 result = sprintf(route[0], params);
257 result = sprintf(route[0], params);
219
258
220 var ret = [];
259 var ret = [];
221 //extra params => GET
260 //extra params => GET
222 for(param in params){
261 for(param in params){
223 if (route[1].indexOf(param) == -1){
262 if (route[1].indexOf(param) == -1){
224 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
263 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
225 }
264 }
226 }
265 }
227 var _parts = ret.join("&");
266 var _parts = ret.join("&");
228 if(_parts){
267 if(_parts){
229 result = result +'?'+ _parts
268 result = result +'?'+ _parts
230 }
269 }
231 }
270 }
232
271
233 return result;
272 return result;
234 },
273 },
235 'register': function(route_name, route_tmpl, req_params) {
274 'register': function(route_name, route_tmpl, req_params) {
236 if (typeof(req_params) != 'object') {
275 if (typeof(req_params) != 'object') {
237 req_params = [];
276 req_params = [];
238 }
277 }
239 //fix escape
278 //fix escape
240 route_tmpl = unescape(route_tmpl);
279 route_tmpl = unescape(route_tmpl);
241 keys = [];
280 keys = [];
242 for (o in req_params){
281 for (o in req_params){
243 keys.push(req_params[o])
282 keys.push(req_params[o])
244 }
283 }
245 matchlist[route_name] = [
284 matchlist[route_name] = [
246 route_tmpl,
285 route_tmpl,
247 keys
286 keys
248 ]
287 ]
249 },
288 },
250 '_routes': function(){
289 '_routes': function(){
251 return matchlist;
290 return matchlist;
252 }
291 }
253 }
292 }
254 })();
293 })();
255
294
256
295
257 /**
296 /**
258 * GLOBAL YUI Shortcuts
297 * GLOBAL YUI Shortcuts
259 */
298 */
260 var YUC = YAHOO.util.Connect;
299 var YUC = YAHOO.util.Connect;
261 var YUD = YAHOO.util.Dom;
300 var YUD = YAHOO.util.Dom;
262 var YUE = YAHOO.util.Event;
301 var YUE = YAHOO.util.Event;
263 var YUQ = YAHOO.util.Selector.query;
302 var YUQ = YAHOO.util.Selector.query;
264
303
265 /* Invoke all functions in callbacks */
304 /* Invoke all functions in callbacks */
266 var _run_callbacks = function(callbacks){
305 var _run_callbacks = function(callbacks){
267 if (callbacks !== undefined){
306 if (callbacks !== undefined){
268 var _l = callbacks.length;
307 var _l = callbacks.length;
269 for (var i=0;i<_l;i++){
308 for (var i=0;i<_l;i++){
270 var func = callbacks[i];
309 var func = callbacks[i];
271 if(typeof(func)=='function'){
310 if(typeof(func)=='function'){
272 try{
311 try{
273 func();
312 func();
274 }catch (err){};
313 }catch (err){};
275 }
314 }
276 }
315 }
277 }
316 }
278 }
317 }
279
318
280 /**
319 /**
281 * turns objects into GET query string
320 * turns objects into GET query string
282 */
321 */
283 var _toQueryString = function(o) {
322 var _toQueryString = function(o) {
284 if(typeof o !== 'object') {
323 if(typeof o !== 'object') {
285 return false;
324 return false;
286 }
325 }
287 var _p, _qs = [];
326 var _p, _qs = [];
288 for(_p in o) {
327 for(_p in o) {
289 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
328 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
290 }
329 }
291 return _qs.join('&');
330 return _qs.join('&');
292 };
331 };
293
332
294 /**
333 /**
295 * Partial Ajax Implementation
334 * Partial Ajax Implementation
296 *
335 *
297 * @param url: defines url to make partial request
336 * @param url: defines url to make partial request
298 * @param container: defines id of container to input partial result
337 * @param container: defines id of container to input partial result
299 * @param s_call: success callback function that takes o as arg
338 * @param s_call: success callback function that takes o as arg
300 * o.tId
339 * o.tId
301 * o.status
340 * o.status
302 * o.statusText
341 * o.statusText
303 * o.getResponseHeader[ ]
342 * o.getResponseHeader[ ]
304 * o.getAllResponseHeaders
343 * o.getAllResponseHeaders
305 * o.responseText
344 * o.responseText
306 * o.responseXML
345 * o.responseXML
307 * o.argument
346 * o.argument
308 * @param f_call: failure callback
347 * @param f_call: failure callback
309 * @param args arguments
348 * @param args arguments
310 */
349 */
311 function ypjax(url,container,s_call,f_call,args){
350 function ypjax(url,container,s_call,f_call,args){
312 var method='GET';
351 var method='GET';
313 if(args===undefined){
352 if(args===undefined){
314 args=null;
353 args=null;
315 }
354 }
316 $container = $('#' + container);
355 $container = $('#' + container);
317
356
318 // Set special header for partial ajax == HTTP_X_PARTIAL_XHR
357 // Set special header for partial ajax == HTTP_X_PARTIAL_XHR
319 YUC.initHeader('X-PARTIAL-XHR',true);
358 YUC.initHeader('X-PARTIAL-XHR',true);
320
359
321 // wrapper of passed callback
360 // wrapper of passed callback
322 var s_wrapper = (function(o){
361 var s_wrapper = (function(o){
323 return function(o){
362 return function(o){
324 $container.html(o.responseText);
363 $container.html(o.responseText);
325 $container.css('opacity','1.0');
364 $container.css('opacity','1.0');
326 //execute the given original callback
365 //execute the given original callback
327 if (s_call !== undefined){
366 if (s_call !== undefined){
328 s_call(o);
367 s_call(o);
329 }
368 }
330 }
369 }
331 })()
370 })()
332 $container.css('opacity','0.3');
371 $container.css('opacity','0.3');
333 YUC.asyncRequest(method,url,{
372 YUC.asyncRequest(method,url,{
334 success:s_wrapper,
373 success:s_wrapper,
335 failure:function(o){
374 failure:function(o){
336 console.log('ypjax failure: '+o);
375 console.log('ypjax failure: '+o);
337 $container.html('<span class="error_red">ERROR: {0}</span>'.format(o.status));
376 $container.html('<span class="error_red">ERROR: {0}</span>'.format(o.status));
338 $container.css('opacity','1.0');
377 $container.css('opacity','1.0');
339 },
378 },
340 cache:false
379 cache:false
341 },args);
380 },args);
342
381
343 };
382 };
344
383
345 var ajaxGET = function(url,success) {
384 var ajaxGET = function(url,success) {
346 // Set special header for ajax == HTTP_X_PARTIAL_XHR
385 // Set special header for ajax == HTTP_X_PARTIAL_XHR
347 YUC.initHeader('X-PARTIAL-XHR',true);
386 YUC.initHeader('X-PARTIAL-XHR',true);
348
387
349 var sUrl = url;
388 var sUrl = url;
350 var callback = {
389 var callback = {
351 success: success,
390 success: success,
352 failure: function (o) {
391 failure: function (o) {
353 if (o.status != 0) {
392 if (o.status != 0) {
354 alert("error: " + o.statusText);
393 alert("error: " + o.statusText);
355 };
394 };
356 },
395 },
357 };
396 };
358
397
359 var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
398 var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
360 return request;
399 return request;
361 };
400 };
362
401
363 var ajaxPOST = function(url,postData,success) {
402 var ajaxPOST = function(url,postData,success) {
364 // Set special header for ajax == HTTP_X_PARTIAL_XHR
403 // Set special header for ajax == HTTP_X_PARTIAL_XHR
365 YUC.initHeader('X-PARTIAL-XHR',true);
404 YUC.initHeader('X-PARTIAL-XHR',true);
366
405
367 var sUrl = url;
406 var sUrl = url;
368 var callback = {
407 var callback = {
369 success: success,
408 success: success,
370 failure: function (o) {
409 failure: function (o) {
371 alert("error");
410 alert("error");
372 },
411 },
373 };
412 };
374 var postData = _toQueryString(postData);
413 var postData = _toQueryString(postData);
375 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
414 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
376 return request;
415 return request;
377 };
416 };
378
417
379
418
380 /**
419 /**
381 * activate .show_more links
420 * activate .show_more links
382 * the .show_more must have an id that is the the id of an element to hide prefixed with _
421 * the .show_more must have an id that is the the id of an element to hide prefixed with _
383 * the parentnode will be displayed
422 * the parentnode will be displayed
384 */
423 */
385 var show_more_event = function(){
424 var show_more_event = function(){
386 $('.show_more').click(function(e){
425 $('.show_more').click(function(e){
387 var el = e.currentTarget;
426 var el = e.currentTarget;
388 $('#' + el.id.substring(1)).hide();
427 $('#' + el.id.substring(1)).hide();
389 $(el.parentNode).show();
428 $(el.parentNode).show();
390 });
429 });
391 };
430 };
392
431
393 /**
432 /**
394 * activate .lazy-cs mouseover for showing changeset tooltip
433 * activate .lazy-cs mouseover for showing changeset tooltip
395 */
434 */
396 var show_changeset_tooltip = function(){
435 var show_changeset_tooltip = function(){
397 $('.lazy-cs').mouseover(function(e){
436 $('.lazy-cs').mouseover(function(e){
398 var $target = $(e.currentTarget);
437 var $target = $(e.currentTarget);
399 var rid = $target.attr('raw_id');
438 var rid = $target.attr('raw_id');
400 var repo_name = $target.attr('repo_name');
439 var repo_name = $target.attr('repo_name');
401 if(rid && !$target.hasClass('tooltip')){
440 if(rid && !$target.hasClass('tooltip')){
402 _show_tooltip(e, _TM['loading ...']);
441 _show_tooltip(e, _TM['loading ...']);
403 var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid});
442 var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid});
404 ajaxGET(url, function(o){
443 ajaxGET(url, function(o){
405 var json = JSON.parse(o.responseText);
444 var json = JSON.parse(o.responseText);
406 $target.addClass('tooltip')
445 $target.addClass('tooltip')
407 _show_tooltip(e, json['message']);
446 _show_tooltip(e, json['message']);
408 _activate_tooltip($target);
447 _activate_tooltip($target);
409 });
448 });
410 }
449 }
411 });
450 });
412 };
451 };
413
452
414 var _onSuccessFollow = function(target){
453 var _onSuccessFollow = function(target){
415 var $target = $(target);
454 var $target = $(target);
416 var $f_cnt = $('#current_followers_count');
455 var $f_cnt = $('#current_followers_count');
417 if($target.hasClass('follow')){
456 if($target.hasClass('follow')){
418 $target.attr('class', 'following');
457 $target.attr('class', 'following');
419 $target.attr('title', _TM['Stop following this repository']);
458 $target.attr('title', _TM['Stop following this repository']);
420 if($f_cnt.html()){
459 if($f_cnt.html()){
421 var cnt = Number($f_cnt.html())+1;
460 var cnt = Number($f_cnt.html())+1;
422 $f_cnt.html(cnt);
461 $f_cnt.html(cnt);
423 }
462 }
424 }
463 }
425 else{
464 else{
426 $target.attr('class', 'follow');
465 $target.attr('class', 'follow');
427 $target.attr('title', _TM['Start following this repository']);
466 $target.attr('title', _TM['Start following this repository']);
428 if($f_cnt.html()){
467 if($f_cnt.html()){
429 var cnt = Number($f_cnt.html())-1;
468 var cnt = Number($f_cnt.html())-1;
430 $f_cnt.html(cnt);
469 $f_cnt.html(cnt);
431 }
470 }
432 }
471 }
433 }
472 }
434
473
435 var toggleFollowingRepo = function(target, follows_repo_id, token, user_id){
474 var toggleFollowingRepo = function(target, follows_repo_id, token, user_id){
436 args = 'follows_repo_id='+follows_repo_id;
475 args = 'follows_repo_id='+follows_repo_id;
437 args+= '&amp;auth_token='+token;
476 args+= '&amp;auth_token='+token;
438 if(user_id != undefined){
477 if(user_id != undefined){
439 args+="&amp;user_id="+user_id;
478 args+="&amp;user_id="+user_id;
440 }
479 }
441 $.post(TOGGLE_FOLLOW_URL, args, function(data){
480 $.post(TOGGLE_FOLLOW_URL, args, function(data){
442 _onSuccessFollow(target);
481 _onSuccessFollow(target);
443 });
482 });
444 return false;
483 return false;
445 };
484 };
446
485
447 var showRepoSize = function(target, repo_name, token){
486 var showRepoSize = function(target, repo_name, token){
448 var args= 'auth_token='+token;
487 var args= 'auth_token='+token;
449
488
450 if(!$("#" + target).hasClass('loaded')){
489 if(!$("#" + target).hasClass('loaded')){
451 $("#" + target).html(_TM['Loading ...']);
490 $("#" + target).html(_TM['Loading ...']);
452 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
491 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
453 $.post(url, args, function(data) {
492 $.post(url, args, function(data) {
454 $("#" + target).html(data);
493 $("#" + target).html(data);
455 $("#" + target).addClass('loaded');
494 $("#" + target).addClass('loaded');
456 });
495 });
457 }
496 }
458 return false;
497 return false;
459 };
498 };
460
499
461 /**
500 /**
462 * tooltips
501 * tooltips
463 */
502 */
464
503
465 var tooltip_activate = function(){
504 var tooltip_activate = function(){
466 $(document).ready(_init_tooltip);
505 $(document).ready(_init_tooltip);
467 };
506 };
468
507
469 var _activate_tooltip = function($tt){
508 var _activate_tooltip = function($tt){
470 $tt.mouseover(_show_tooltip);
509 $tt.mouseover(_show_tooltip);
471 $tt.mousemove(_move_tooltip);
510 $tt.mousemove(_move_tooltip);
472 $tt.mouseout(_close_tooltip);
511 $tt.mouseout(_close_tooltip);
473 };
512 };
474
513
475 var _init_tooltip = function(){
514 var _init_tooltip = function(){
476 var $tipBox = $('#tip-box');
515 var $tipBox = $('#tip-box');
477 if(!$tipBox.length){
516 if(!$tipBox.length){
478 $tipBox = $('<div id="tip-box"></div>')
517 $tipBox = $('<div id="tip-box"></div>')
479 $(document.body).append($tipBox);
518 $(document.body).append($tipBox);
480 }
519 }
481
520
482 $tipBox.hide();
521 $tipBox.hide();
483 $tipBox.css('position', 'absolute');
522 $tipBox.css('position', 'absolute');
484 $tipBox.css('max-width', '600px');
523 $tipBox.css('max-width', '600px');
485
524
486 _activate_tooltip($('.tooltip'));
525 _activate_tooltip($('.tooltip'));
487 };
526 };
488
527
489 var _show_tooltip = function(e, tipText){
528 var _show_tooltip = function(e, tipText){
490 e.stopImmediatePropagation();
529 e.stopImmediatePropagation();
491 var el = e.currentTarget;
530 var el = e.currentTarget;
492 if(tipText){
531 if(tipText){
493 // just use it
532 // just use it
494 } else if(el.tagName.toLowerCase() === 'img'){
533 } else if(el.tagName.toLowerCase() === 'img'){
495 tipText = el.alt ? el.alt : '';
534 tipText = el.alt ? el.alt : '';
496 } else {
535 } else {
497 tipText = el.title ? el.title : '';
536 tipText = el.title ? el.title : '';
498 }
537 }
499
538
500 if(tipText !== ''){
539 if(tipText !== ''){
501 // save org title
540 // save org title
502 $(el).attr('tt_title', tipText);
541 $(el).attr('tt_title', tipText);
503 // reset title to not show org tooltips
542 // reset title to not show org tooltips
504 $(el).attr('title', '');
543 $(el).attr('title', '');
505
544
506 var $tipBox = $('#tip-box');
545 var $tipBox = $('#tip-box');
507 $tipBox.html(tipText);
546 $tipBox.html(tipText);
508 $tipBox.css('display', 'block');
547 $tipBox.css('display', 'block');
509 }
548 }
510 };
549 };
511
550
512 var _move_tooltip = function(e){
551 var _move_tooltip = function(e){
513 e.stopImmediatePropagation();
552 e.stopImmediatePropagation();
514 var $tipBox = $('#tip-box');
553 var $tipBox = $('#tip-box');
515 $tipBox.css('top', (e.pageY + 15) + 'px');
554 $tipBox.css('top', (e.pageY + 15) + 'px');
516 $tipBox.css('left', (e.pageX + 15) + 'px');
555 $tipBox.css('left', (e.pageX + 15) + 'px');
517 };
556 };
518
557
519 var _close_tooltip = function(e){
558 var _close_tooltip = function(e){
520 e.stopImmediatePropagation();
559 e.stopImmediatePropagation();
521 var $tipBox = $('#tip-box');
560 var $tipBox = $('#tip-box');
522 $tipBox.hide();
561 $tipBox.hide();
523 var el = e.currentTarget;
562 var el = e.currentTarget;
524 $(el).attr('title', $(el).attr('tt_title'));
563 $(el).attr('title', $(el).attr('tt_title'));
525 };
564 };
526
565
527 /**
566 /**
528 * Quick filter widget
567 * Quick filter widget
529 *
568 *
530 * @param target: filter input target
569 * @param target: filter input target
531 * @param nodes: list of nodes in html we want to filter.
570 * @param nodes: list of nodes in html we want to filter.
532 * @param display_element function that takes current node from nodes and
571 * @param display_element function that takes current node from nodes and
533 * does hide or show based on the node
572 * does hide or show based on the node
534 */
573 */
535 var q_filter = function(target, nodes, display_element){
574 var q_filter = function(target, nodes, display_element){
536 var nodes = nodes;
575 var nodes = nodes;
537 var $q_filter_field = $('#' + target);
576 var $q_filter_field = $('#' + target);
538 var F = YAHOO.namespace(target);
577 var F = YAHOO.namespace(target);
539
578
540 $q_filter_field.keyup(function(e){
579 $q_filter_field.keyup(function(e){
541 clearTimeout(F.filterTimeout);
580 clearTimeout(F.filterTimeout);
542 F.filterTimeout = setTimeout(F.updateFilter, 600);
581 F.filterTimeout = setTimeout(F.updateFilter, 600);
543 });
582 });
544
583
545 F.filterTimeout = null;
584 F.filterTimeout = null;
546
585
547 F.updateFilter = function() {
586 F.updateFilter = function() {
548 // Reset timeout
587 // Reset timeout
549 F.filterTimeout = null;
588 F.filterTimeout = null;
550
589
551 var obsolete = [];
590 var obsolete = [];
552
591
553 var req = $q_filter_field.val().toLowerCase();
592 var req = $q_filter_field.val().toLowerCase();
554
593
555 var l = nodes.length;
594 var l = nodes.length;
556 var i;
595 var i;
557 var showing = 0;
596 var showing = 0;
558
597
559 for (i=0; i<l; i++ ){
598 for (i=0; i<l; i++ ){
560 var n = nodes[i];
599 var n = nodes[i];
561 var target_element = display_element(n)
600 var target_element = display_element(n)
562 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
601 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
563 $(target_element).hide();
602 $(target_element).hide();
564 }
603 }
565 else{
604 else{
566 $(target_element).show();
605 $(target_element).show();
567 showing += 1;
606 showing += 1;
568 }
607 }
569 }
608 }
570
609
571 $('#repo_count').html(showing); /* FIXME: don't hardcode */
610 $('#repo_count').html(showing); /* FIXME: don't hardcode */
572 }
611 }
573 };
612 };
574
613
575 /* return jQuery expression with a tr with body in 3rd column and class cls and id named after the body */
614 /* return jQuery expression with a tr with body in 3rd column and class cls and id named after the body */
576 var _table_tr = function(cls, body){
615 var _table_tr = function(cls, body){
577 // like: <div class="comment" id="comment-8" line="o92"><div class="comment-wrapp">...
616 // like: <div class="comment" id="comment-8" line="o92"><div class="comment-wrapp">...
578 // except new inlines which are different ...
617 // except new inlines which are different ...
579 var comment_id = ($(body).attr('id') || 'comment-new').split('comment-')[1];
618 var comment_id = ($(body).attr('id') || 'comment-new').split('comment-')[1];
580 var tr_id = 'comment-tr-{0}'.format(comment_id);
619 var tr_id = 'comment-tr-{0}'.format(comment_id);
581 return $(('<tr id="{0}" class="{1}">'+
620 return $(('<tr id="{0}" class="{1}">'+
582 '<td class="lineno-inline new-inline"></td>'+
621 '<td class="lineno-inline new-inline"></td>'+
583 '<td class="lineno-inline old-inline"></td>'+
622 '<td class="lineno-inline old-inline"></td>'+
584 '<td>{2}</td>'+
623 '<td>{2}</td>'+
585 '</tr>').format(tr_id, cls, body));
624 '</tr>').format(tr_id, cls, body));
586 };
625 };
587
626
588 /** return jQuery expression with new inline form based on template **/
627 /** return jQuery expression with new inline form based on template **/
589 var _createInlineForm = function(parent_tr, f_path, line) {
628 var _createInlineForm = function(parent_tr, f_path, line) {
590 var $tmpl = $('#comment-inline-form-template').html().format(f_path, line);
629 var $tmpl = $('#comment-inline-form-template').html().format(f_path, line);
591 var $form = _table_tr('comment-form-inline', $tmpl)
630 var $form = _table_tr('comment-form-inline', $tmpl)
592
631
593 // create event for hide button
632 // create event for hide button
594 $form.find('.hide-inline-form').click(function(e) {
633 $form.find('.hide-inline-form').click(function(e) {
595 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
634 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
596 if($(newtr).next().hasClass('inline-comments-button')){
635 if($(newtr).next().hasClass('inline-comments-button')){
597 $(newtr).next().show();
636 $(newtr).next().show();
598 }
637 }
599 $(newtr).remove();
638 $(newtr).remove();
600 $(parent_tr).removeClass('form-open');
639 $(parent_tr).removeClass('form-open');
601 $(parent_tr).removeClass('hl-comment');
640 $(parent_tr).removeClass('hl-comment');
602 });
641 });
603
642
604 return $form
643 return $form
605 };
644 };
606
645
607 /**
646 /**
608 * Inject inline comment for an given TR. This tr should always be a .line .
647 * Inject inline comment for an given TR. This tr should always be a .line .
609 * The form will be inject after any comments.
648 * The form will be inject after any comments.
610 */
649 */
611 var injectInlineForm = function(tr){
650 var injectInlineForm = function(tr){
612 $tr = $(tr);
651 $tr = $(tr);
613 if(!$tr.hasClass('line')){
652 if(!$tr.hasClass('line')){
614 return
653 return
615 }
654 }
616 var submit_url = AJAX_COMMENT_URL;
655 var submit_url = AJAX_COMMENT_URL;
617 var $td = $tr.find('.code');
656 var $td = $tr.find('.code');
618 if($tr.hasClass('form-open') || $tr.hasClass('context') || $td.hasClass('no-comment')){
657 if($tr.hasClass('form-open') || $tr.hasClass('context') || $td.hasClass('no-comment')){
619 return
658 return
620 }
659 }
621 $tr.addClass('form-open hl-comment');
660 $tr.addClass('form-open hl-comment');
622 var $node = $tr.parent().parent().parent().find('.full_f_path');
661 var $node = $tr.parent().parent().parent().find('.full_f_path');
623 var f_path = $node.attr('path');
662 var f_path = $node.attr('path');
624 var lineno = _getLineNo(tr);
663 var lineno = _getLineNo(tr);
625 var $form = _createInlineForm(tr, f_path, lineno, submit_url);
664 var $form = _createInlineForm(tr, f_path, lineno, submit_url);
626
665
627 var $parent = $tr;
666 var $parent = $tr;
628 while ($parent.next().hasClass('inline-comments')){
667 while ($parent.next().hasClass('inline-comments')){
629 var $parent = $parent.next();
668 var $parent = $parent.next();
630 }
669 }
631 $form.insertAfter($parent);
670 $form.insertAfter($parent);
632 var $overlay = $form.find('.overlay');
671 var $overlay = $form.find('.overlay');
633 var $inlineform = $form.find('.inline-form');
672 var $inlineform = $form.find('.inline-form');
634
673
635 $form.submit(function(e){
674 $form.submit(function(e){
636 e.preventDefault();
675 e.preventDefault();
637
676
638 if(lineno === undefined){
677 if(lineno === undefined){
639 alert('missing line !');
678 alert('missing line !');
640 return
679 return
641 }
680 }
642 if(f_path === undefined){
681 if(f_path === undefined){
643 alert('missing file path !');
682 alert('missing file path !');
644 return
683 return
645 }
684 }
646
685
647 var text = $('#text_'+lineno).val();
686 var text = $('#text_'+lineno).val();
648 if(text == ""){
687 if(text == ""){
649 return
688 return
650 }
689 }
651
690
652 if ($overlay.hasClass('overlay')){
691 if ($overlay.hasClass('overlay')){
653 $overlay.css('width', $inlineform.offsetWidth + 'px');
692 $overlay.css('width', $inlineform.offsetWidth + 'px');
654 $overlay.css('height', $inlineform.offsetHeight + 'px');
693 $overlay.css('height', $inlineform.offsetHeight + 'px');
655 }
694 }
656 $overlay.addClass('submitting');
695 $overlay.addClass('submitting');
657
696
658 var success = function(o){
697 var success = function(o){
659 $tr.removeClass('form-open');
698 $tr.removeClass('form-open');
660 $form.remove();
699 $form.remove();
661 var json_data = JSON.parse(o.responseText);
700 var json_data = JSON.parse(o.responseText);
662 _renderInlineComment(json_data);
701 _renderInlineComment(json_data);
663 };
702 };
664 var postData = {
703 var postData = {
665 'text': text,
704 'text': text,
666 'f_path': f_path,
705 'f_path': f_path,
667 'line': lineno
706 'line': lineno
668 };
707 };
669 ajaxPOST(submit_url, postData, success);
708 ajaxPOST(submit_url, postData, success);
670 });
709 });
671
710
672 $('#preview-btn_'+lineno).click(function(e){
711 $('#preview-btn_'+lineno).click(function(e){
673 var text = $('#text_'+lineno).val();
712 var text = $('#text_'+lineno).val();
674 if(!text){
713 if(!text){
675 return
714 return
676 }
715 }
677 $('#preview-box_'+lineno).addClass('unloaded');
716 $('#preview-box_'+lineno).addClass('unloaded');
678 $('#preview-box_'+lineno).html(_TM['Loading ...']);
717 $('#preview-box_'+lineno).html(_TM['Loading ...']);
679 $('#edit-container_'+lineno).hide();
718 $('#edit-container_'+lineno).hide();
680 $('#preview-container_'+lineno).show();
719 $('#preview-container_'+lineno).show();
681
720
682 var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME});
721 var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME});
683 var post_data = {'text': text};
722 var post_data = {'text': text};
684 ajaxPOST(url, post_data, function(o){
723 ajaxPOST(url, post_data, function(o){
685 $('#preview-box_'+lineno).html(o.responseText);
724 $('#preview-box_'+lineno).html(o.responseText);
686 $('#preview-box_'+lineno).removeClass('unloaded');
725 $('#preview-box_'+lineno).removeClass('unloaded');
687 })
726 })
688 })
727 })
689 $('#edit-btn_'+lineno).click(function(e){
728 $('#edit-btn_'+lineno).click(function(e){
690 $('#edit-container_'+lineno).show();
729 $('#edit-container_'+lineno).show();
691 $('#preview-container_'+lineno).hide();
730 $('#preview-container_'+lineno).hide();
692 })
731 })
693
732
694 setTimeout(function(){
733 setTimeout(function(){
695 // callbacks
734 // callbacks
696 tooltip_activate();
735 tooltip_activate();
697 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
736 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
698 _USERS_AC_DATA, _GROUPS_AC_DATA);
737 _USERS_AC_DATA, _GROUPS_AC_DATA);
699 $('#text_'+lineno).focus();
738 $('#text_'+lineno).focus();
700 },10)
739 },10)
701 };
740 };
702
741
703 var deleteComment = function(comment_id){
742 var deleteComment = function(comment_id){
704 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
743 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
705 var postData = {'_method':'delete'};
744 var postData = {'_method':'delete'};
706 var success = function(o){
745 var success = function(o){
707 var $deleted = $('#comment-tr-'+comment_id);
746 var $deleted = $('#comment-tr-'+comment_id);
708 var $prev = $deleted.prev('tr');
747 var $prev = $deleted.prev('tr');
709 $deleted.remove();
748 $deleted.remove();
710 _placeAddButton($prev);
749 _placeAddButton($prev);
711 }
750 }
712 ajaxPOST(url,postData,success);
751 ajaxPOST(url,postData,success);
713 }
752 }
714
753
715 var _getLineNo = function(tr) {
754 var _getLineNo = function(tr) {
716 var line;
755 var line;
717 var o = $(tr).children()[0].id.split('_');
756 var o = $(tr).children()[0].id.split('_');
718 var n = $(tr).children()[1].id.split('_');
757 var n = $(tr).children()[1].id.split('_');
719
758
720 if (n.length >= 2) {
759 if (n.length >= 2) {
721 line = n[n.length-1];
760 line = n[n.length-1];
722 } else if (o.length >= 2) {
761 } else if (o.length >= 2) {
723 line = o[o.length-1];
762 line = o[o.length-1];
724 }
763 }
725
764
726 return line
765 return line
727 };
766 };
728
767
729 var _placeAddButton = function($line_tr){
768 var _placeAddButton = function($line_tr){
730 var $tr = $line_tr;
769 var $tr = $line_tr;
731 while ($tr.next().hasClass('inline-comments')){
770 while ($tr.next().hasClass('inline-comments')){
732 $tr.find('.add-comment').remove();
771 $tr.find('.add-comment').remove();
733 $tr = $tr.next();
772 $tr = $tr.next();
734 }
773 }
735 $tr.find('.add-comment').remove();
774 $tr.find('.add-comment').remove();
736 var label = TRANSLATION_MAP['Add another comment'];
775 var label = TRANSLATION_MAP['Add another comment'];
737 var $html_el = $('<div class="add-comment"><span class="ui-btn">{0}</span></div>'.format(label));
776 var $html_el = $('<div class="add-comment"><span class="ui-btn">{0}</span></div>'.format(label));
738 $html_el.click(function(e) {
777 $html_el.click(function(e) {
739 injectInlineForm($line_tr);
778 injectInlineForm($line_tr);
740 });
779 });
741 $tr.find('.comment').after($html_el);
780 $tr.find('.comment').after($html_el);
742 };
781 };
743
782
744 /**
783 /**
745 * Places the inline comment into the changeset block in proper line position
784 * Places the inline comment into the changeset block in proper line position
746 */
785 */
747 var _placeInline = function(target_id, lineno, html){
786 var _placeInline = function(target_id, lineno, html){
748 var $td = $("#{0}_{1}".format(target_id, lineno));
787 var $td = $("#{0}_{1}".format(target_id, lineno));
749
788
750 // check if there are comments already !
789 // check if there are comments already !
751 var $line_tr = $td.parent(); // the tr
790 var $line_tr = $td.parent(); // the tr
752 var $after_tr = $line_tr;
791 var $after_tr = $line_tr;
753 while ($after_tr.next().hasClass('inline-comments')){
792 while ($after_tr.next().hasClass('inline-comments')){
754 $after_tr = $after_tr.next();
793 $after_tr = $after_tr.next();
755 }
794 }
756 // put in the comment at the bottom
795 // put in the comment at the bottom
757 $after_tr.after(_table_tr('inline-comments', html));
796 $after_tr.after(_table_tr('inline-comments', html));
758
797
759 // scan nodes, and attach add button to last one
798 // scan nodes, and attach add button to last one
760 _placeAddButton($line_tr);
799 _placeAddButton($line_tr);
761 }
800 }
762
801
763 /**
802 /**
764 * make a single inline comment and place it inside
803 * make a single inline comment and place it inside
765 */
804 */
766 var _renderInlineComment = function(json_data){
805 var _renderInlineComment = function(json_data){
767 var html = json_data['rendered_text'];
806 var html = json_data['rendered_text'];
768 var lineno = json_data['line_no'];
807 var lineno = json_data['line_no'];
769 var target_id = json_data['target_id'];
808 var target_id = json_data['target_id'];
770 _placeInline(target_id, lineno, html);
809 _placeInline(target_id, lineno, html);
771 }
810 }
772
811
773 /**
812 /**
774 * Iterates over all the inlines, and places them inside proper blocks of data
813 * Iterates over all the inlines, and places them inside proper blocks of data
775 */
814 */
776 var renderInlineComments = function(file_comments){
815 var renderInlineComments = function(file_comments){
777 for (f in file_comments){
816 for (f in file_comments){
778 // holding all comments for a FILE
817 // holding all comments for a FILE
779 var box = file_comments[f];
818 var box = file_comments[f];
780
819
781 var target_id = $(box).attr('target_id');
820 var target_id = $(box).attr('target_id');
782 // actual comments with line numbers
821 // actual comments with line numbers
783 var comments = box.children;
822 var comments = box.children;
784 for(var i=0; i<comments.length; i++){
823 for(var i=0; i<comments.length; i++){
785 var data = {
824 var data = {
786 'rendered_text': comments[i].outerHTML,
825 'rendered_text': comments[i].outerHTML,
787 'line_no': $(comments[i]).attr('line'),
826 'line_no': $(comments[i]).attr('line'),
788 'target_id': target_id
827 'target_id': target_id
789 }
828 }
790 _renderInlineComment(data);
829 _renderInlineComment(data);
791 }
830 }
792 }
831 }
793 }
832 }
794
833
795 /* activate files.html stuff */
834 /* activate files.html stuff */
796 var fileBrowserListeners = function(current_url, node_list_url, url_base){
835 var fileBrowserListeners = function(current_url, node_list_url, url_base){
797 var current_url_branch = "?branch=__BRANCH__";
836 var current_url_branch = "?branch=__BRANCH__";
798
837
799 $('#stay_at_branch').on('click',function(e){
838 $('#stay_at_branch').on('click',function(e){
800 if(e.currentTarget.checked){
839 if(e.currentTarget.checked){
801 var uri = current_url_branch;
840 var uri = current_url_branch;
802 uri = uri.replace('__BRANCH__',e.currentTarget.value);
841 uri = uri.replace('__BRANCH__',e.currentTarget.value);
803 window.location = uri;
842 window.location = uri;
804 }
843 }
805 else{
844 else{
806 window.location = current_url;
845 window.location = current_url;
807 }
846 }
808 })
847 })
809
848
810 var $node_filter = $('#node_filter');
849 var $node_filter = $('#node_filter');
811
850
812 var filterTimeout = null;
851 var filterTimeout = null;
813 var nodes = null;
852 var nodes = null;
814
853
815 var initFilter = function(){
854 var initFilter = function(){
816 $('#node_filter_box_loading').show();
855 $('#node_filter_box_loading').show();
817 $('#search_activate_id').hide();
856 $('#search_activate_id').hide();
818 $('#add_node_id').hide();
857 $('#add_node_id').hide();
819 YUC.initHeader('X-PARTIAL-XHR',true);
858 YUC.initHeader('X-PARTIAL-XHR',true);
820 YUC.asyncRequest('GET', node_list_url, {
859 YUC.asyncRequest('GET', node_list_url, {
821 success:function(o){
860 success:function(o){
822 nodes = JSON.parse(o.responseText).nodes;
861 nodes = JSON.parse(o.responseText).nodes;
823 $('#node_filter_box_loading').hide();
862 $('#node_filter_box_loading').hide();
824 $('#node_filter_box').show();
863 $('#node_filter_box').show();
825 $node_filter.focus();
864 $node_filter.focus();
826 if($node_filter.hasClass('init')){
865 if($node_filter.hasClass('init')){
827 $node_filter.val('');
866 $node_filter.val('');
828 $node_filter.removeClass('init');
867 $node_filter.removeClass('init');
829 }
868 }
830 },
869 },
831 failure:function(o){
870 failure:function(o){
832 console.log('failed to load');
871 console.log('failed to load');
833 }
872 }
834 },null);
873 },null);
835 }
874 }
836
875
837 var updateFilter = function(e) {
876 var updateFilter = function(e) {
838 return function(){
877 return function(){
839 // Reset timeout
878 // Reset timeout
840 filterTimeout = null;
879 filterTimeout = null;
841 var query = e.currentTarget.value.toLowerCase();
880 var query = e.currentTarget.value.toLowerCase();
842 var match = [];
881 var match = [];
843 var matches = 0;
882 var matches = 0;
844 var matches_max = 20;
883 var matches_max = 20;
845 if (query != ""){
884 if (query != ""){
846 for(var i=0;i<nodes.length;i++){
885 for(var i=0;i<nodes.length;i++){
847 var pos = nodes[i].name.toLowerCase().indexOf(query)
886 var pos = nodes[i].name.toLowerCase().indexOf(query)
848 if(query && pos != -1){
887 if(query && pos != -1){
849 matches++
888 matches++
850 //show only certain amount to not kill browser
889 //show only certain amount to not kill browser
851 if (matches > matches_max){
890 if (matches > matches_max){
852 break;
891 break;
853 }
892 }
854
893
855 var n = nodes[i].name;
894 var n = nodes[i].name;
856 var t = nodes[i].type;
895 var t = nodes[i].type;
857 var n_hl = n.substring(0,pos)
896 var n_hl = n.substring(0,pos)
858 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
897 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
859 +n.substring(pos+query.length)
898 +n.substring(pos+query.length)
860 var new_url = url_base.replace('__FPATH__',n);
899 var new_url = url_base.replace('__FPATH__',n);
861 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
900 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
862 }
901 }
863 if(match.length >= matches_max){
902 if(match.length >= matches_max){
864 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['Search truncated']));
903 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['Search truncated']));
865 }
904 }
866 }
905 }
867 }
906 }
868 if(query != ""){
907 if(query != ""){
869 $('#tbody').hide();
908 $('#tbody').hide();
870 $('#tbody_filtered').show();
909 $('#tbody_filtered').show();
871
910
872 if (match.length==0){
911 if (match.length==0){
873 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['No matching files']));
912 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['No matching files']));
874 }
913 }
875
914
876 $('#tbody_filtered').html(match.join(""));
915 $('#tbody_filtered').html(match.join(""));
877 }
916 }
878 else{
917 else{
879 $('#tbody').show();
918 $('#tbody').show();
880 $('#tbody_filtered').hide();
919 $('#tbody_filtered').hide();
881 }
920 }
882 }
921 }
883 };
922 };
884
923
885 $('#filter_activate').click(function(){
924 $('#filter_activate').click(function(){
886 initFilter();
925 initFilter();
887 });
926 });
888 $node_filter.click(function(){
927 $node_filter.click(function(){
889 if($node_filter.hasClass('init')){
928 if($node_filter.hasClass('init')){
890 $node_filter.val('');
929 $node_filter.val('');
891 $node_filter.removeClass('init');
930 $node_filter.removeClass('init');
892 }
931 }
893 });
932 });
894 $node_filter.keyup(function(e){
933 $node_filter.keyup(function(e){
895 clearTimeout(filterTimeout);
934 clearTimeout(filterTimeout);
896 filterTimeout = setTimeout(updateFilter(e),600);
935 filterTimeout = setTimeout(updateFilter(e),600);
897 });
936 });
898 };
937 };
899
938
900
939
901 var initCodeMirror = function(textarea_id, resetUrl){
940 var initCodeMirror = function(textarea_id, resetUrl){
902 var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], {
941 var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], {
903 mode: "null",
942 mode: "null",
904 lineNumbers: true,
943 lineNumbers: true,
905 indentUnit: 4
944 indentUnit: 4
906 });
945 });
907 $('#reset').click(function(e){
946 $('#reset').click(function(e){
908 window.location=resetUrl;
947 window.location=resetUrl;
909 });
948 });
910
949
911 $('#file_enable').click(function(){
950 $('#file_enable').click(function(){
912 $('#editor_container').show();
951 $('#editor_container').show();
913 $('#upload_file_container').hide();
952 $('#upload_file_container').hide();
914 $('#filename_container').show();
953 $('#filename_container').show();
915 });
954 });
916
955
917 $('#upload_file_enable').click(function(){
956 $('#upload_file_enable').click(function(){
918 $('#editor_container').hide();
957 $('#editor_container').hide();
919 $('#upload_file_container').show();
958 $('#upload_file_container').show();
920 $('#filename_container').hide();
959 $('#filename_container').hide();
921 });
960 });
922
961
923 return myCodeMirror
962 return myCodeMirror
924 };
963 };
925
964
926 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
965 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
927 codeMirrorInstance.setOption("mode", mode);
966 codeMirrorInstance.setOption("mode", mode);
928 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
967 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
929 }
968 }
930
969
931
970
932 var _getIdentNode = function(n){
971 var _getIdentNode = function(n){
933 //iterate thrugh nodes until matching interesting node
972 //iterate thrugh nodes until matching interesting node
934
973
935 if (typeof n == 'undefined'){
974 if (typeof n == 'undefined'){
936 return -1
975 return -1
937 }
976 }
938
977
939 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
978 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
940 return n
979 return n
941 }
980 }
942 else{
981 else{
943 return _getIdentNode(n.parentNode);
982 return _getIdentNode(n.parentNode);
944 }
983 }
945 };
984 };
946
985
947 /* generate links for multi line selects that can be shown by files.html page_highlights.
986 /* generate links for multi line selects that can be shown by files.html page_highlights.
948 * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */
987 * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */
949 var getSelectionLink = function(e) {
988 var getSelectionLink = function(e) {
950 //get selection from start/to nodes
989 //get selection from start/to nodes
951 if (typeof window.getSelection != "undefined") {
990 if (typeof window.getSelection != "undefined") {
952 s = window.getSelection();
991 s = window.getSelection();
953
992
954 from = _getIdentNode(s.anchorNode);
993 from = _getIdentNode(s.anchorNode);
955 till = _getIdentNode(s.focusNode);
994 till = _getIdentNode(s.focusNode);
956
995
957 f_int = parseInt(from.id.replace('L',''));
996 f_int = parseInt(from.id.replace('L',''));
958 t_int = parseInt(till.id.replace('L',''));
997 t_int = parseInt(till.id.replace('L',''));
959
998
960 var yoffset = 35;
999 var yoffset = 35;
961 var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))];
1000 var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))];
962 if (ranges[0] > ranges[1]){
1001 if (ranges[0] > ranges[1]){
963 //highlight from bottom
1002 //highlight from bottom
964 yoffset = -yoffset;
1003 yoffset = -yoffset;
965 ranges = [ranges[1], ranges[0]];
1004 ranges = [ranges[1], ranges[0]];
966 }
1005 }
967 var $hl_div = $('div#linktt');
1006 var $hl_div = $('div#linktt');
968 // if we select more than 2 lines
1007 // if we select more than 2 lines
969 if (ranges[0] != ranges[1]){
1008 if (ranges[0] != ranges[1]){
970 if ($hl_div.length) {
1009 if ($hl_div.length) {
971 $hl_div.html('');
1010 $hl_div.html('');
972 } else {
1011 } else {
973 $hl_div = $('<div id="linktt" class="hl-tip-box">');
1012 $hl_div = $('<div id="linktt" class="hl-tip-box">');
974 $('body').prepend($hl_div);
1013 $('body').prepend($hl_div);
975 }
1014 }
976
1015
977 $hl_div.append($('<a>').html(_TM['Selection link']).attr('href', location.href.substring(0, location.href.indexOf('#')) + '#L' + ranges[0] + '-'+ranges[1]));
1016 $hl_div.append($('<a>').html(_TM['Selection link']).attr('href', location.href.substring(0, location.href.indexOf('#')) + '#L' + ranges[0] + '-'+ranges[1]));
978 xy = $(till).offset();
1017 xy = $(till).offset();
979 $hl_div.css('top', (xy.top + yoffset) + 'px').css('left', xy.left + 'px');
1018 $hl_div.css('top', (xy.top + yoffset) + 'px').css('left', xy.left + 'px');
980 $hl_div.show();
1019 $hl_div.show();
981 }
1020 }
982 else{
1021 else{
983 $hl_div.hide();
1022 $hl_div.hide();
984 }
1023 }
985 }
1024 }
986 };
1025 };
987
1026
988 var deleteNotification = function(url, notification_id, callbacks){
1027 var deleteNotification = function(url, notification_id, callbacks){
989 var callback = {
1028 var callback = {
990 success:function(o){
1029 success:function(o){
991 $("#notification_"+notification_id).remove();
1030 $("#notification_"+notification_id).remove();
992 _run_callbacks(callbacks);
1031 _run_callbacks(callbacks);
993 },
1032 },
994 failure:function(o){
1033 failure:function(o){
995 alert("error");
1034 alert("error");
996 },
1035 },
997 };
1036 };
998 var postData = '_method=delete';
1037 var postData = '_method=delete';
999 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1038 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1000 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1039 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1001 callback, postData);
1040 callback, postData);
1002 };
1041 };
1003
1042
1004 var readNotification = function(url, notification_id, callbacks){
1043 var readNotification = function(url, notification_id, callbacks){
1005 var callback = {
1044 var callback = {
1006 success:function(o){
1045 success:function(o){
1007 var $obj = $("#notification_"+notification_id);
1046 var $obj = $("#notification_"+notification_id);
1008 $obj.removeClass('unread');
1047 $obj.removeClass('unread');
1009 $obj.find('.read-notification').remove();
1048 $obj.find('.read-notification').remove();
1010 _run_callbacks(callbacks);
1049 _run_callbacks(callbacks);
1011 },
1050 },
1012 failure:function(o){
1051 failure:function(o){
1013 alert("error");
1052 alert("error");
1014 },
1053 },
1015 };
1054 };
1016 var postData = '_method=put';
1055 var postData = '_method=put';
1017 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1056 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1018 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1057 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1019 callback, postData);
1058 callback, postData);
1020 };
1059 };
1021
1060
1022 /** MEMBERS AUTOCOMPLETE WIDGET **/
1061 /** MEMBERS AUTOCOMPLETE WIDGET **/
1023
1062
1024 var _MembersAutoComplete = function (divid, cont, users_list, groups_list) {
1063 var _MembersAutoComplete = function (divid, cont, users_list, groups_list) {
1025 var myUsers = users_list;
1064 var myUsers = users_list;
1026 var myGroups = groups_list;
1065 var myGroups = groups_list;
1027
1066
1028 // Define a custom search function for the DataSource of users
1067 // Define a custom search function for the DataSource of users
1029 var matchUsers = function (sQuery) {
1068 var matchUsers = function (sQuery) {
1030 // Case insensitive matching
1069 // Case insensitive matching
1031 var query = sQuery.toLowerCase();
1070 var query = sQuery.toLowerCase();
1032 var i = 0;
1071 var i = 0;
1033 var l = myUsers.length;
1072 var l = myUsers.length;
1034 var matches = [];
1073 var matches = [];
1035
1074
1036 // Match against each name of each contact
1075 // Match against each name of each contact
1037 for (; i < l; i++) {
1076 for (; i < l; i++) {
1038 contact = myUsers[i];
1077 contact = myUsers[i];
1039 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1078 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1040 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1079 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1041 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1080 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1042 matches[matches.length] = contact;
1081 matches[matches.length] = contact;
1043 }
1082 }
1044 }
1083 }
1045 return matches;
1084 return matches;
1046 };
1085 };
1047
1086
1048 // Define a custom search function for the DataSource of userGroups
1087 // Define a custom search function for the DataSource of userGroups
1049 var matchGroups = function (sQuery) {
1088 var matchGroups = function (sQuery) {
1050 // Case insensitive matching
1089 // Case insensitive matching
1051 var query = sQuery.toLowerCase();
1090 var query = sQuery.toLowerCase();
1052 var i = 0;
1091 var i = 0;
1053 var l = myGroups.length;
1092 var l = myGroups.length;
1054 var matches = [];
1093 var matches = [];
1055
1094
1056 // Match against each name of each contact
1095 // Match against each name of each contact
1057 for (; i < l; i++) {
1096 for (; i < l; i++) {
1058 matched_group = myGroups[i];
1097 matched_group = myGroups[i];
1059 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1098 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1060 matches[matches.length] = matched_group;
1099 matches[matches.length] = matched_group;
1061 }
1100 }
1062 }
1101 }
1063 return matches;
1102 return matches;
1064 };
1103 };
1065
1104
1066 //match all
1105 //match all
1067 var matchAll = function (sQuery) {
1106 var matchAll = function (sQuery) {
1068 u = matchUsers(sQuery);
1107 u = matchUsers(sQuery);
1069 g = matchGroups(sQuery);
1108 g = matchGroups(sQuery);
1070 return u.concat(g);
1109 return u.concat(g);
1071 };
1110 };
1072
1111
1073 // DataScheme for members
1112 // DataScheme for members
1074 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
1113 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
1075 memberDS.responseSchema = {
1114 memberDS.responseSchema = {
1076 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
1115 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
1077 };
1116 };
1078
1117
1079 // DataScheme for owner
1118 // DataScheme for owner
1080 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1119 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1081 ownerDS.responseSchema = {
1120 ownerDS.responseSchema = {
1082 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1121 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1083 };
1122 };
1084
1123
1085 // Instantiate AutoComplete for perms
1124 // Instantiate AutoComplete for perms
1086 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
1125 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
1087 membersAC.useShadow = false;
1126 membersAC.useShadow = false;
1088 membersAC.resultTypeList = false;
1127 membersAC.resultTypeList = false;
1089 membersAC.animVert = false;
1128 membersAC.animVert = false;
1090 membersAC.animHoriz = false;
1129 membersAC.animHoriz = false;
1091 membersAC.animSpeed = 0.1;
1130 membersAC.animSpeed = 0.1;
1092
1131
1093 // Instantiate AutoComplete for owner
1132 // Instantiate AutoComplete for owner
1094 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
1133 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
1095 ownerAC.useShadow = false;
1134 ownerAC.useShadow = false;
1096 ownerAC.resultTypeList = false;
1135 ownerAC.resultTypeList = false;
1097 ownerAC.animVert = false;
1136 ownerAC.animVert = false;
1098 ownerAC.animHoriz = false;
1137 ownerAC.animHoriz = false;
1099 ownerAC.animSpeed = 0.1;
1138 ownerAC.animSpeed = 0.1;
1100
1139
1101 // Helper highlight function for the formatter
1140 // Helper highlight function for the formatter
1102 var highlightMatch = function (full, snippet, matchindex) {
1141 var highlightMatch = function (full, snippet, matchindex) {
1103 return full.substring(0, matchindex)
1142 return full.substring(0, matchindex)
1104 + "<span class='match'>"
1143 + "<span class='match'>"
1105 + full.substr(matchindex, snippet.length)
1144 + full.substr(matchindex, snippet.length)
1106 + "</span>" + full.substring(matchindex + snippet.length);
1145 + "</span>" + full.substring(matchindex + snippet.length);
1107 };
1146 };
1108
1147
1109 // Custom formatter to highlight the matching letters
1148 // Custom formatter to highlight the matching letters
1110 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
1149 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
1111 var query = sQuery.toLowerCase();
1150 var query = sQuery.toLowerCase();
1112 var _gravatar = function(res, em, group){
1151 var _gravatar = function(res, em, group){
1113 if (group !== undefined){
1152 if (group !== undefined){
1114 em = '/images/icons/group.png'
1153 em = '/images/icons/group.png'
1115 }
1154 }
1116 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1155 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1117 return tmpl.format(em,res)
1156 return tmpl.format(em,res)
1118 }
1157 }
1119 // group
1158 // group
1120 if (oResultData.grname != undefined) {
1159 if (oResultData.grname != undefined) {
1121 var grname = oResultData.grname;
1160 var grname = oResultData.grname;
1122 var grmembers = oResultData.grmembers;
1161 var grmembers = oResultData.grmembers;
1123 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1162 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1124 var grprefix = "{0}: ".format(_TM['Group']);
1163 var grprefix = "{0}: ".format(_TM['Group']);
1125 var grsuffix = " (" + grmembers + " )";
1164 var grsuffix = " (" + grmembers + " )";
1126 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1165 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1127
1166
1128 if (grnameMatchIndex > -1) {
1167 if (grnameMatchIndex > -1) {
1129 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1168 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1130 }
1169 }
1131 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1170 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1132 // Users
1171 // Users
1133 } else if (oResultData.nname != undefined) {
1172 } else if (oResultData.nname != undefined) {
1134 var fname = oResultData.fname || "";
1173 var fname = oResultData.fname || "";
1135 var lname = oResultData.lname || "";
1174 var lname = oResultData.lname || "";
1136 var nname = oResultData.nname;
1175 var nname = oResultData.nname;
1137
1176
1138 // Guard against null value
1177 // Guard against null value
1139 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1178 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1140 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1179 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1141 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1180 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1142 displayfname, displaylname, displaynname;
1181 displayfname, displaylname, displaynname;
1143
1182
1144 if (fnameMatchIndex > -1) {
1183 if (fnameMatchIndex > -1) {
1145 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1184 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1146 } else {
1185 } else {
1147 displayfname = fname;
1186 displayfname = fname;
1148 }
1187 }
1149
1188
1150 if (lnameMatchIndex > -1) {
1189 if (lnameMatchIndex > -1) {
1151 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1190 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1152 } else {
1191 } else {
1153 displaylname = lname;
1192 displaylname = lname;
1154 }
1193 }
1155
1194
1156 if (nnameMatchIndex > -1) {
1195 if (nnameMatchIndex > -1) {
1157 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1196 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1158 } else {
1197 } else {
1159 displaynname = nname ? "(" + nname + ")" : "";
1198 displaynname = nname ? "(" + nname + ")" : "";
1160 }
1199 }
1161
1200
1162 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1201 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1163 } else {
1202 } else {
1164 return '';
1203 return '';
1165 }
1204 }
1166 };
1205 };
1167 membersAC.formatResult = custom_formatter;
1206 membersAC.formatResult = custom_formatter;
1168 ownerAC.formatResult = custom_formatter;
1207 ownerAC.formatResult = custom_formatter;
1169
1208
1170 var myHandler = function (sType, aArgs) {
1209 var myHandler = function (sType, aArgs) {
1171 var nextId = divid.split('perm_new_member_name_')[1];
1210 var nextId = divid.split('perm_new_member_name_')[1];
1172 var myAC = aArgs[0]; // reference back to the AC instance
1211 var myAC = aArgs[0]; // reference back to the AC instance
1173 var elLI = aArgs[1]; // reference to the selected LI element
1212 var elLI = aArgs[1]; // reference to the selected LI element
1174 var oData = aArgs[2]; // object literal of selected item's result data
1213 var oData = aArgs[2]; // object literal of selected item's result data
1175 //fill the autocomplete with value
1214 //fill the autocomplete with value
1176 if (oData.nname != undefined) {
1215 if (oData.nname != undefined) {
1177 //users
1216 //users
1178 myAC.getInputEl().value = oData.nname;
1217 myAC.getInputEl().value = oData.nname;
1179 $('#perm_new_member_type_'+nextId).val('user');
1218 $('#perm_new_member_type_'+nextId).val('user');
1180 } else {
1219 } else {
1181 //groups
1220 //groups
1182 myAC.getInputEl().value = oData.grname;
1221 myAC.getInputEl().value = oData.grname;
1183 $('#perm_new_member_type_'+nextId).val('users_group');
1222 $('#perm_new_member_type_'+nextId).val('users_group');
1184 }
1223 }
1185 };
1224 };
1186
1225
1187 membersAC.itemSelectEvent.subscribe(myHandler);
1226 membersAC.itemSelectEvent.subscribe(myHandler);
1188 if(ownerAC.itemSelectEvent){
1227 if(ownerAC.itemSelectEvent){
1189 ownerAC.itemSelectEvent.subscribe(myHandler);
1228 ownerAC.itemSelectEvent.subscribe(myHandler);
1190 }
1229 }
1191
1230
1192 return {
1231 return {
1193 memberDS: memberDS,
1232 memberDS: memberDS,
1194 ownerDS: ownerDS,
1233 ownerDS: ownerDS,
1195 membersAC: membersAC,
1234 membersAC: membersAC,
1196 ownerAC: ownerAC,
1235 ownerAC: ownerAC,
1197 };
1236 };
1198 }
1237 }
1199
1238
1200 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1239 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1201 var myUsers = users_list;
1240 var myUsers = users_list;
1202 var myGroups = groups_list;
1241 var myGroups = groups_list;
1203
1242
1204 // Define a custom search function for the DataSource of users
1243 // Define a custom search function for the DataSource of users
1205 var matchUsers = function (sQuery) {
1244 var matchUsers = function (sQuery) {
1206 var org_sQuery = sQuery;
1245 var org_sQuery = sQuery;
1207 if(this.mentionQuery == null){
1246 if(this.mentionQuery == null){
1208 return []
1247 return []
1209 }
1248 }
1210 sQuery = this.mentionQuery;
1249 sQuery = this.mentionQuery;
1211 // Case insensitive matching
1250 // Case insensitive matching
1212 var query = sQuery.toLowerCase();
1251 var query = sQuery.toLowerCase();
1213 var i = 0;
1252 var i = 0;
1214 var l = myUsers.length;
1253 var l = myUsers.length;
1215 var matches = [];
1254 var matches = [];
1216
1255
1217 // Match against each name of each contact
1256 // Match against each name of each contact
1218 for (; i < l; i++) {
1257 for (; i < l; i++) {
1219 contact = myUsers[i];
1258 contact = myUsers[i];
1220 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1259 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1221 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1260 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1222 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1261 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1223 matches[matches.length] = contact;
1262 matches[matches.length] = contact;
1224 }
1263 }
1225 }
1264 }
1226 return matches
1265 return matches
1227 };
1266 };
1228
1267
1229 //match all
1268 //match all
1230 var matchAll = function (sQuery) {
1269 var matchAll = function (sQuery) {
1231 u = matchUsers(sQuery);
1270 u = matchUsers(sQuery);
1232 return u
1271 return u
1233 };
1272 };
1234
1273
1235 // DataScheme for owner
1274 // DataScheme for owner
1236 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1275 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1237
1276
1238 ownerDS.responseSchema = {
1277 ownerDS.responseSchema = {
1239 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1278 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1240 };
1279 };
1241
1280
1242 // Instantiate AutoComplete for mentions
1281 // Instantiate AutoComplete for mentions
1243 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1282 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1244 ownerAC.useShadow = false;
1283 ownerAC.useShadow = false;
1245 ownerAC.resultTypeList = false;
1284 ownerAC.resultTypeList = false;
1246 ownerAC.suppressInputUpdate = true;
1285 ownerAC.suppressInputUpdate = true;
1247 ownerAC.animVert = false;
1286 ownerAC.animVert = false;
1248 ownerAC.animHoriz = false;
1287 ownerAC.animHoriz = false;
1249 ownerAC.animSpeed = 0.1;
1288 ownerAC.animSpeed = 0.1;
1250
1289
1251 // Helper highlight function for the formatter
1290 // Helper highlight function for the formatter
1252 var highlightMatch = function (full, snippet, matchindex) {
1291 var highlightMatch = function (full, snippet, matchindex) {
1253 return full.substring(0, matchindex)
1292 return full.substring(0, matchindex)
1254 + "<span class='match'>"
1293 + "<span class='match'>"
1255 + full.substr(matchindex, snippet.length)
1294 + full.substr(matchindex, snippet.length)
1256 + "</span>" + full.substring(matchindex + snippet.length);
1295 + "</span>" + full.substring(matchindex + snippet.length);
1257 };
1296 };
1258
1297
1259 // Custom formatter to highlight the matching letters
1298 // Custom formatter to highlight the matching letters
1260 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1299 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1261 var org_sQuery = sQuery;
1300 var org_sQuery = sQuery;
1262 if(this.dataSource.mentionQuery != null){
1301 if(this.dataSource.mentionQuery != null){
1263 sQuery = this.dataSource.mentionQuery;
1302 sQuery = this.dataSource.mentionQuery;
1264 }
1303 }
1265
1304
1266 var query = sQuery.toLowerCase();
1305 var query = sQuery.toLowerCase();
1267 var _gravatar = function(res, em, group){
1306 var _gravatar = function(res, em, group){
1268 if (group !== undefined){
1307 if (group !== undefined){
1269 em = '/images/icons/group.png'
1308 em = '/images/icons/group.png'
1270 }
1309 }
1271 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1310 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1272 return tmpl.format(em,res)
1311 return tmpl.format(em,res)
1273 }
1312 }
1274 if (oResultData.nname != undefined) {
1313 if (oResultData.nname != undefined) {
1275 var fname = oResultData.fname || "";
1314 var fname = oResultData.fname || "";
1276 var lname = oResultData.lname || "";
1315 var lname = oResultData.lname || "";
1277 var nname = oResultData.nname;
1316 var nname = oResultData.nname;
1278
1317
1279 // Guard against null value
1318 // Guard against null value
1280 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1319 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1281 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1320 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1282 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1321 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1283 displayfname, displaylname, displaynname;
1322 displayfname, displaylname, displaynname;
1284
1323
1285 if (fnameMatchIndex > -1) {
1324 if (fnameMatchIndex > -1) {
1286 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1325 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1287 } else {
1326 } else {
1288 displayfname = fname;
1327 displayfname = fname;
1289 }
1328 }
1290
1329
1291 if (lnameMatchIndex > -1) {
1330 if (lnameMatchIndex > -1) {
1292 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1331 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1293 } else {
1332 } else {
1294 displaylname = lname;
1333 displaylname = lname;
1295 }
1334 }
1296
1335
1297 if (nnameMatchIndex > -1) {
1336 if (nnameMatchIndex > -1) {
1298 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1337 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1299 } else {
1338 } else {
1300 displaynname = nname ? "(" + nname + ")" : "";
1339 displaynname = nname ? "(" + nname + ")" : "";
1301 }
1340 }
1302
1341
1303 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1342 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1304 } else {
1343 } else {
1305 return '';
1344 return '';
1306 }
1345 }
1307 };
1346 };
1308
1347
1309 if(ownerAC.itemSelectEvent){
1348 if(ownerAC.itemSelectEvent){
1310 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1349 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1311
1350
1312 var myAC = aArgs[0]; // reference back to the AC instance
1351 var myAC = aArgs[0]; // reference back to the AC instance
1313 var elLI = aArgs[1]; // reference to the selected LI element
1352 var elLI = aArgs[1]; // reference to the selected LI element
1314 var oData = aArgs[2]; // object literal of selected item's result data
1353 var oData = aArgs[2]; // object literal of selected item's result data
1315 //fill the autocomplete with value
1354 //fill the autocomplete with value
1316 if (oData.nname != undefined) {
1355 if (oData.nname != undefined) {
1317 //users
1356 //users
1318 //Replace the mention name with replaced
1357 //Replace the mention name with replaced
1319 var re = new RegExp();
1358 var re = new RegExp();
1320 var org = myAC.getInputEl().value;
1359 var org = myAC.getInputEl().value;
1321 var chunks = myAC.dataSource.chunks
1360 var chunks = myAC.dataSource.chunks
1322 // replace middle chunk(the search term) with actuall match
1361 // replace middle chunk(the search term) with actuall match
1323 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1362 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1324 '@'+oData.nname+' ');
1363 '@'+oData.nname+' ');
1325 myAC.getInputEl().value = chunks.join('')
1364 myAC.getInputEl().value = chunks.join('')
1326 myAC.getInputEl().focus(); // Y U NO WORK !?
1365 myAC.getInputEl().focus(); // Y U NO WORK !?
1327 } else {
1366 } else {
1328 //groups
1367 //groups
1329 myAC.getInputEl().value = oData.grname;
1368 myAC.getInputEl().value = oData.grname;
1330 $('#perm_new_member_type').val('users_group');
1369 $('#perm_new_member_type').val('users_group');
1331 }
1370 }
1332 });
1371 });
1333 }
1372 }
1334
1373
1335 // in this keybuffer we will gather current value of search !
1374 // in this keybuffer we will gather current value of search !
1336 // since we need to get this just when someone does `@` then we do the
1375 // since we need to get this just when someone does `@` then we do the
1337 // search
1376 // search
1338 ownerAC.dataSource.chunks = [];
1377 ownerAC.dataSource.chunks = [];
1339 ownerAC.dataSource.mentionQuery = null;
1378 ownerAC.dataSource.mentionQuery = null;
1340
1379
1341 ownerAC.get_mention = function(msg, max_pos) {
1380 ownerAC.get_mention = function(msg, max_pos) {
1342 var org = msg;
1381 var org = msg;
1343 var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$')
1382 var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$')
1344 var chunks = [];
1383 var chunks = [];
1345
1384
1346 // cut first chunk until curret pos
1385 // cut first chunk until curret pos
1347 var to_max = msg.substr(0, max_pos);
1386 var to_max = msg.substr(0, max_pos);
1348 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1387 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1349 var msg2 = to_max.substr(at_pos);
1388 var msg2 = to_max.substr(at_pos);
1350
1389
1351 chunks.push(org.substr(0,at_pos))// prefix chunk
1390 chunks.push(org.substr(0,at_pos))// prefix chunk
1352 chunks.push(msg2) // search chunk
1391 chunks.push(msg2) // search chunk
1353 chunks.push(org.substr(max_pos)) // postfix chunk
1392 chunks.push(org.substr(max_pos)) // postfix chunk
1354
1393
1355 // clean up msg2 for filtering and regex match
1394 // clean up msg2 for filtering and regex match
1356 var msg2 = msg2.lstrip(' ').lstrip('\n');
1395 var msg2 = msg2.lstrip(' ').lstrip('\n');
1357
1396
1358 if(re.test(msg2)){
1397 if(re.test(msg2)){
1359 var unam = re.exec(msg2)[1];
1398 var unam = re.exec(msg2)[1];
1360 return [unam, chunks];
1399 return [unam, chunks];
1361 }
1400 }
1362 return [null, null];
1401 return [null, null];
1363 };
1402 };
1364
1403
1365 if (ownerAC.textboxKeyUpEvent){
1404 if (ownerAC.textboxKeyUpEvent){
1366 ownerAC.textboxKeyUpEvent.subscribe(function(type, args){
1405 ownerAC.textboxKeyUpEvent.subscribe(function(type, args){
1367
1406
1368 var ac_obj = args[0];
1407 var ac_obj = args[0];
1369 var currentMessage = args[1];
1408 var currentMessage = args[1];
1370 var currentCaretPosition = args[0]._elTextbox.selectionStart;
1409 var currentCaretPosition = args[0]._elTextbox.selectionStart;
1371
1410
1372 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1411 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1373 var curr_search = null;
1412 var curr_search = null;
1374 if(unam[0]){
1413 if(unam[0]){
1375 curr_search = unam[0];
1414 curr_search = unam[0];
1376 }
1415 }
1377
1416
1378 ownerAC.dataSource.chunks = unam[1];
1417 ownerAC.dataSource.chunks = unam[1];
1379 ownerAC.dataSource.mentionQuery = curr_search;
1418 ownerAC.dataSource.mentionQuery = curr_search;
1380
1419
1381 })
1420 })
1382 }
1421 }
1383 return {
1422 return {
1384 ownerDS: ownerDS,
1423 ownerDS: ownerDS,
1385 ownerAC: ownerAC,
1424 ownerAC: ownerAC,
1386 };
1425 };
1387 }
1426 }
1388
1427
1389 var addReviewMember = function(id,fname,lname,nname,gravatar_link){
1428 var addReviewMember = function(id,fname,lname,nname,gravatar_link){
1390 var tmpl = '<li id="reviewer_{2}">'+
1429 var tmpl = '<li id="reviewer_{2}">'+
1391 '<div class="reviewers_member">'+
1430 '<div class="reviewers_member">'+
1392 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1431 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1393 '<div style="float:left">{1}</div>'+
1432 '<div style="float:left">{1}</div>'+
1394 '<input type="hidden" value="{2}" name="review_members" />'+
1433 '<input type="hidden" value="{2}" name="review_members" />'+
1395 '<span class="delete_icon action_button" onclick="removeReviewMember({2})"></span>'+
1434 '<span class="delete_icon action_button" onclick="removeReviewMember({2})"></span>'+
1396 '</div>'+
1435 '</div>'+
1397 '</li>' ;
1436 '</li>' ;
1398 var displayname = "{0} {1} ({2})".format(fname,lname,nname);
1437 var displayname = "{0} {1} ({2})".format(fname,lname,nname);
1399 var element = tmpl.format(gravatar_link,displayname,id);
1438 var element = tmpl.format(gravatar_link,displayname,id);
1400 // check if we don't have this ID already in
1439 // check if we don't have this ID already in
1401 var ids = [];
1440 var ids = [];
1402 $('#review_members').find('li').each(function() {
1441 $('#review_members').find('li').each(function() {
1403 ids.push(this.id);
1442 ids.push(this.id);
1404 });
1443 });
1405 if(ids.indexOf('reviewer_'+id) == -1){
1444 if(ids.indexOf('reviewer_'+id) == -1){
1406 //only add if it's not there
1445 //only add if it's not there
1407 $('#review_members').append(element);
1446 $('#review_members').append(element);
1408 }
1447 }
1409 }
1448 }
1410
1449
1411 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1450 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1412 $('#reviewer_{0}'.format(reviewer_id)).remove();
1451 $('#reviewer_{0}'.format(reviewer_id)).remove();
1413 }
1452 }
1414
1453
1415 /* handle "Save Changes" of addReviewMember and removeReviewMember on PR */
1454 /* handle "Save Changes" of addReviewMember and removeReviewMember on PR */
1416 var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){
1455 var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){
1417 if (reviewers_ids === undefined){
1456 if (reviewers_ids === undefined){
1418 var reviewers_ids = [];
1457 var reviewers_ids = [];
1419 $('#review_members').find('input').each(function(){
1458 $('#review_members').find('input').each(function(){
1420 reviewers_ids.push(this.value);
1459 reviewers_ids.push(this.value);
1421 });
1460 });
1422 }
1461 }
1423 var url = pyroutes.url('pullrequest_update', {"repo_name":repo_name,
1462 var url = pyroutes.url('pullrequest_update', {"repo_name":repo_name,
1424 "pull_request_id": pull_request_id});
1463 "pull_request_id": pull_request_id});
1425 var postData = {'_method':'put',
1464 var postData = {'_method':'put',
1426 'reviewers_ids': reviewers_ids};
1465 'reviewers_ids': reviewers_ids};
1427 var success = function(o){
1466 var success = function(o){
1428 window.location.reload();
1467 window.location.reload();
1429 }
1468 }
1430 ajaxPOST(url,postData,success);
1469 ajaxPOST(url,postData,success);
1431 }
1470 }
1432
1471
1433 /* activate auto completion of users and groups ... but only used for users as PR reviewers */
1472 /* activate auto completion of users and groups ... but only used for users as PR reviewers */
1434 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1473 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1435 var myUsers = users_list;
1474 var myUsers = users_list;
1436 var myGroups = groups_list;
1475 var myGroups = groups_list;
1437
1476
1438 // Define a custom search function for the DataSource of users
1477 // Define a custom search function for the DataSource of users
1439 var matchUsers = function (sQuery) {
1478 var matchUsers = function (sQuery) {
1440 // Case insensitive matching
1479 // Case insensitive matching
1441 var query = sQuery.toLowerCase();
1480 var query = sQuery.toLowerCase();
1442 var i = 0;
1481 var i = 0;
1443 var l = myUsers.length;
1482 var l = myUsers.length;
1444 var matches = [];
1483 var matches = [];
1445
1484
1446 // Match against each name of each contact
1485 // Match against each name of each contact
1447 for (; i < l; i++) {
1486 for (; i < l; i++) {
1448 contact = myUsers[i];
1487 contact = myUsers[i];
1449 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1488 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1450 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1489 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1451 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1490 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1452 matches[matches.length] = contact;
1491 matches[matches.length] = contact;
1453 }
1492 }
1454 }
1493 }
1455 return matches;
1494 return matches;
1456 };
1495 };
1457
1496
1458 // Define a custom search function for the DataSource of userGroups
1497 // Define a custom search function for the DataSource of userGroups
1459 var matchGroups = function (sQuery) {
1498 var matchGroups = function (sQuery) {
1460 // Case insensitive matching
1499 // Case insensitive matching
1461 var query = sQuery.toLowerCase();
1500 var query = sQuery.toLowerCase();
1462 var i = 0;
1501 var i = 0;
1463 var l = myGroups.length;
1502 var l = myGroups.length;
1464 var matches = [];
1503 var matches = [];
1465
1504
1466 // Match against each name of each contact
1505 // Match against each name of each contact
1467 for (; i < l; i++) {
1506 for (; i < l; i++) {
1468 matched_group = myGroups[i];
1507 matched_group = myGroups[i];
1469 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1508 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1470 matches[matches.length] = matched_group;
1509 matches[matches.length] = matched_group;
1471 }
1510 }
1472 }
1511 }
1473 return matches;
1512 return matches;
1474 };
1513 };
1475
1514
1476 //match all
1515 //match all
1477 var matchAll = function (sQuery) {
1516 var matchAll = function (sQuery) {
1478 u = matchUsers(sQuery);
1517 u = matchUsers(sQuery);
1479 return u
1518 return u
1480 };
1519 };
1481
1520
1482 // DataScheme for owner
1521 // DataScheme for owner
1483 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1522 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1484
1523
1485 ownerDS.responseSchema = {
1524 ownerDS.responseSchema = {
1486 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1525 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1487 };
1526 };
1488
1527
1489 // Instantiate AutoComplete for mentions
1528 // Instantiate AutoComplete for mentions
1490 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1529 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1491 reviewerAC.useShadow = false;
1530 reviewerAC.useShadow = false;
1492 reviewerAC.resultTypeList = false;
1531 reviewerAC.resultTypeList = false;
1493 reviewerAC.suppressInputUpdate = true;
1532 reviewerAC.suppressInputUpdate = true;
1494 reviewerAC.animVert = false;
1533 reviewerAC.animVert = false;
1495 reviewerAC.animHoriz = false;
1534 reviewerAC.animHoriz = false;
1496 reviewerAC.animSpeed = 0.1;
1535 reviewerAC.animSpeed = 0.1;
1497
1536
1498 // Helper highlight function for the formatter
1537 // Helper highlight function for the formatter
1499 var highlightMatch = function (full, snippet, matchindex) {
1538 var highlightMatch = function (full, snippet, matchindex) {
1500 return full.substring(0, matchindex)
1539 return full.substring(0, matchindex)
1501 + "<span class='match'>"
1540 + "<span class='match'>"
1502 + full.substr(matchindex, snippet.length)
1541 + full.substr(matchindex, snippet.length)
1503 + "</span>" + full.substring(matchindex + snippet.length);
1542 + "</span>" + full.substring(matchindex + snippet.length);
1504 };
1543 };
1505
1544
1506 // Custom formatter to highlight the matching letters
1545 // Custom formatter to highlight the matching letters
1507 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1546 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1508 var org_sQuery = sQuery;
1547 var org_sQuery = sQuery;
1509 if(this.dataSource.mentionQuery != null){
1548 if(this.dataSource.mentionQuery != null){
1510 sQuery = this.dataSource.mentionQuery;
1549 sQuery = this.dataSource.mentionQuery;
1511 }
1550 }
1512
1551
1513 var query = sQuery.toLowerCase();
1552 var query = sQuery.toLowerCase();
1514 var _gravatar = function(res, em, group){
1553 var _gravatar = function(res, em, group){
1515 if (group !== undefined){
1554 if (group !== undefined){
1516 em = '/images/icons/group.png'
1555 em = '/images/icons/group.png'
1517 }
1556 }
1518 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1557 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1519 return tmpl.format(em,res)
1558 return tmpl.format(em,res)
1520 }
1559 }
1521 if (oResultData.nname != undefined) {
1560 if (oResultData.nname != undefined) {
1522 var fname = oResultData.fname || "";
1561 var fname = oResultData.fname || "";
1523 var lname = oResultData.lname || "";
1562 var lname = oResultData.lname || "";
1524 var nname = oResultData.nname;
1563 var nname = oResultData.nname;
1525
1564
1526 // Guard against null value
1565 // Guard against null value
1527 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1566 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1528 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1567 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1529 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1568 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1530 displayfname, displaylname, displaynname;
1569 displayfname, displaylname, displaynname;
1531
1570
1532 if (fnameMatchIndex > -1) {
1571 if (fnameMatchIndex > -1) {
1533 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1572 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1534 } else {
1573 } else {
1535 displayfname = fname;
1574 displayfname = fname;
1536 }
1575 }
1537
1576
1538 if (lnameMatchIndex > -1) {
1577 if (lnameMatchIndex > -1) {
1539 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1578 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1540 } else {
1579 } else {
1541 displaylname = lname;
1580 displaylname = lname;
1542 }
1581 }
1543
1582
1544 if (nnameMatchIndex > -1) {
1583 if (nnameMatchIndex > -1) {
1545 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1584 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1546 } else {
1585 } else {
1547 displaynname = nname ? "(" + nname + ")" : "";
1586 displaynname = nname ? "(" + nname + ")" : "";
1548 }
1587 }
1549
1588
1550 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1589 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1551 } else {
1590 } else {
1552 return '';
1591 return '';
1553 }
1592 }
1554 };
1593 };
1555
1594
1556 //members cache to catch duplicates
1595 //members cache to catch duplicates
1557 reviewerAC.dataSource.cache = [];
1596 reviewerAC.dataSource.cache = [];
1558 // hack into select event
1597 // hack into select event
1559 if(reviewerAC.itemSelectEvent){
1598 if(reviewerAC.itemSelectEvent){
1560 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1599 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1561
1600
1562 var myAC = aArgs[0]; // reference back to the AC instance
1601 var myAC = aArgs[0]; // reference back to the AC instance
1563 var elLI = aArgs[1]; // reference to the selected LI element
1602 var elLI = aArgs[1]; // reference to the selected LI element
1564 var oData = aArgs[2]; // object literal of selected item's result data
1603 var oData = aArgs[2]; // object literal of selected item's result data
1565
1604
1566 //fill the autocomplete with value
1605 //fill the autocomplete with value
1567 if (oData.nname != undefined) {
1606 if (oData.nname != undefined) {
1568 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1607 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1569 oData.gravatar_lnk);
1608 oData.gravatar_lnk);
1570 myAC.dataSource.cache.push(oData.id);
1609 myAC.dataSource.cache.push(oData.id);
1571 $('#user').val('');
1610 $('#user').val('');
1572 }
1611 }
1573 });
1612 });
1574 }
1613 }
1575 }
1614 }
1576
1615
1577 /**
1616 /**
1578 * Activate .quick_repo_menu
1617 * Activate .quick_repo_menu
1579 */
1618 */
1580 var quick_repo_menu = function(){
1619 var quick_repo_menu = function(){
1581 $(".quick_repo_menu").mouseenter(function(e) {
1620 $(".quick_repo_menu").mouseenter(function(e) {
1582 var $menu = $(e.currentTarget).children().first().children().first();
1621 var $menu = $(e.currentTarget).children().first().children().first();
1583 if($menu.hasClass('hidden')){
1622 if($menu.hasClass('hidden')){
1584 $menu.removeClass('hidden').addClass('active');
1623 $menu.removeClass('hidden').addClass('active');
1585 $(e.currentTarget).removeClass('hidden').addClass('active');
1624 $(e.currentTarget).removeClass('hidden').addClass('active');
1586 }
1625 }
1587 })
1626 })
1588 $(".quick_repo_menu").mouseleave(function(e) {
1627 $(".quick_repo_menu").mouseleave(function(e) {
1589 var $menu = $(e.currentTarget).children().first().children().first();
1628 var $menu = $(e.currentTarget).children().first().children().first();
1590 if($menu.hasClass('active')){
1629 if($menu.hasClass('active')){
1591 $menu.removeClass('active').addClass('hidden');
1630 $menu.removeClass('active').addClass('hidden');
1592 $(e.currentTarget).removeClass('active').addClass('hidden');
1631 $(e.currentTarget).removeClass('active').addClass('hidden');
1593 }
1632 }
1594 })
1633 })
1595 };
1634 };
1596
1635
1597
1636
1598 /**
1637 /**
1599 * TABLE SORTING
1638 * TABLE SORTING
1600 */
1639 */
1601
1640
1602 // returns a node from given html;
1641 // returns a node from given html;
1603 var fromHTML = function(html){
1642 var fromHTML = function(html){
1604 var _html = document.createElement('element');
1643 var _html = document.createElement('element');
1605 _html.innerHTML = html;
1644 _html.innerHTML = html;
1606 return _html;
1645 return _html;
1607 }
1646 }
1608
1647
1609 var get_rev = function(node){
1648 var get_rev = function(node){
1610 var n = node.firstElementChild.firstElementChild;
1649 var n = node.firstElementChild.firstElementChild;
1611
1650
1612 if (n===null){
1651 if (n===null){
1613 return -1
1652 return -1
1614 }
1653 }
1615 else{
1654 else{
1616 out = n.firstElementChild.innerHTML.split(':')[0].replace('r','');
1655 out = n.firstElementChild.innerHTML.split(':')[0].replace('r','');
1617 return parseInt(out);
1656 return parseInt(out);
1618 }
1657 }
1619 }
1658 }
1620
1659
1621 var get_date = function(node){
1660 var get_date = function(node){
1622 return $(node.firstElementChild).attr('date');
1661 return $(node.firstElementChild).attr('date');
1623 }
1662 }
1624
1663
1625 var revisionSort = function(a, b, desc, field) {
1664 var revisionSort = function(a, b, desc, field) {
1626 var a_ = get_rev(fromHTML(a.getData(field)));
1665 var a_ = get_rev(fromHTML(a.getData(field)));
1627 var b_ = get_rev(fromHTML(b.getData(field)));
1666 var b_ = get_rev(fromHTML(b.getData(field)));
1628
1667
1629 return YAHOO.util.Sort.compare(a_, b_, desc);
1668 return YAHOO.util.Sort.compare(a_, b_, desc);
1630 };
1669 };
1631
1670
1632 var ageSort = function(a, b, desc, field) {
1671 var ageSort = function(a, b, desc, field) {
1633 // data is like: <span class="tooltip" date="2014-06-04 18:18:55.325474" title="Wed, 04 Jun 2014 18:18:55">1 day and 23 hours ago</span>
1672 // data is like: <span class="tooltip" date="2014-06-04 18:18:55.325474" title="Wed, 04 Jun 2014 18:18:55">1 day and 23 hours ago</span>
1634 var a_ = $(a.getData(field)).attr('date');
1673 var a_ = $(a.getData(field)).attr('date');
1635 var b_ = $(b.getData(field)).attr('date');
1674 var b_ = $(b.getData(field)).attr('date');
1636
1675
1637 return YAHOO.util.Sort.compare(a_, b_, desc);
1676 return YAHOO.util.Sort.compare(a_, b_, desc);
1638 };
1677 };
1639
1678
1640 var lastLoginSort = function(a, b, desc, field) {
1679 var lastLoginSort = function(a, b, desc, field) {
1641 var a_ = a.getData('last_login_raw') || 0;
1680 var a_ = a.getData('last_login_raw') || 0;
1642 var b_ = b.getData('last_login_raw') || 0;
1681 var b_ = b.getData('last_login_raw') || 0;
1643
1682
1644 return YAHOO.util.Sort.compare(a_, b_, desc);
1683 return YAHOO.util.Sort.compare(a_, b_, desc);
1645 };
1684 };
1646
1685
1647 var nameSort = function(a, b, desc, field) {
1686 var nameSort = function(a, b, desc, field) {
1648 var a_ = a.getData('raw_name') || 0;
1687 var a_ = a.getData('raw_name') || 0;
1649 var b_ = b.getData('raw_name') || 0;
1688 var b_ = b.getData('raw_name') || 0;
1650
1689
1651 return YAHOO.util.Sort.compare(a_, b_, desc);
1690 return YAHOO.util.Sort.compare(a_, b_, desc);
1652 };
1691 };
1653
1692
1654 var dateSort = function(a, b, desc, field) {
1693 var dateSort = function(a, b, desc, field) {
1655 var a_ = get_date(fromHTML(a.getData(field)));
1694 var a_ = get_date(fromHTML(a.getData(field)));
1656 var b_ = get_date(fromHTML(b.getData(field)));
1695 var b_ = get_date(fromHTML(b.getData(field)));
1657
1696
1658 return YAHOO.util.Sort.compare(a_, b_, desc);
1697 return YAHOO.util.Sort.compare(a_, b_, desc);
1659 };
1698 };
1660
1699
1661 var addPermAction = function(_html, users_list, groups_list){
1700 var addPermAction = function(_html, users_list, groups_list){
1662 var $last_node = $('.last_new_member').last(); // empty tr between last and add
1701 var $last_node = $('.last_new_member').last(); // empty tr between last and add
1663 var next_id = $('.new_members').length;
1702 var next_id = $('.new_members').length;
1664 $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
1703 $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
1665 _MembersAutoComplete("perm_new_member_name_"+next_id,
1704 _MembersAutoComplete("perm_new_member_name_"+next_id,
1666 "perm_container_"+next_id, users_list, groups_list);
1705 "perm_container_"+next_id, users_list, groups_list);
1667 }
1706 }
1668
1707
1669 function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
1708 function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
1670 var callback = {
1709 var callback = {
1671 success: function (o) {
1710 success: function (o) {
1672 $('#' + field_id).remove();
1711 $('#' + field_id).remove();
1673 },
1712 },
1674 failure: function (o) {
1713 failure: function (o) {
1675 alert(_TM['Failed to remoke permission'] + ": " + o.status);
1714 alert(_TM['Failed to remoke permission'] + ": " + o.status);
1676 },
1715 },
1677 };
1716 };
1678 query_params = {
1717 query_params = {
1679 '_method': 'delete'
1718 '_method': 'delete'
1680 }
1719 }
1681 // put extra data into POST
1720 // put extra data into POST
1682 if (extra_data !== undefined && (typeof extra_data === 'object')){
1721 if (extra_data !== undefined && (typeof extra_data === 'object')){
1683 for(k in extra_data){
1722 for(k in extra_data){
1684 query_params[k] = extra_data[k];
1723 query_params[k] = extra_data[k];
1685 }
1724 }
1686 }
1725 }
1687
1726
1688 if (obj_type=='user'){
1727 if (obj_type=='user'){
1689 query_params['user_id'] = obj_id;
1728 query_params['user_id'] = obj_id;
1690 query_params['obj_type'] = 'user';
1729 query_params['obj_type'] = 'user';
1691 }
1730 }
1692 else if (obj_type=='user_group'){
1731 else if (obj_type=='user_group'){
1693 query_params['user_group_id'] = obj_id;
1732 query_params['user_group_id'] = obj_id;
1694 query_params['obj_type'] = 'user_group';
1733 query_params['obj_type'] = 'user_group';
1695 }
1734 }
1696
1735
1697 var request = YAHOO.util.Connect.asyncRequest('POST', url, callback,
1736 var request = YAHOO.util.Connect.asyncRequest('POST', url, callback,
1698 _toQueryString(query_params));
1737 _toQueryString(query_params));
1699 };
1738 };
1700
1739
1701 /* Multi selectors */
1740 /* Multi selectors */
1702
1741
1703 var MultiSelectWidget = function(selected_id, available_id, form_id){
1742 var MultiSelectWidget = function(selected_id, available_id, form_id){
1704 var $availableselect = $('#' + available_id);
1743 var $availableselect = $('#' + available_id);
1705 var $selectedselect = $('#' + selected_id);
1744 var $selectedselect = $('#' + selected_id);
1706
1745
1707 //fill available only with those not in selected
1746 //fill available only with those not in selected
1708 var $selectedoptions = $selectedselect.children('option');
1747 var $selectedoptions = $selectedselect.children('option');
1709 $availableselect.children('option').filter(function(i, e){
1748 $availableselect.children('option').filter(function(i, e){
1710 for(var j = 0, node; node = $selectedoptions[j]; j++){
1749 for(var j = 0, node; node = $selectedoptions[j]; j++){
1711 if(node.value == e.value){
1750 if(node.value == e.value){
1712 return true;
1751 return true;
1713 }
1752 }
1714 }
1753 }
1715 return false;
1754 return false;
1716 }).remove();
1755 }).remove();
1717
1756
1718 $('#add_element').click(function(e){
1757 $('#add_element').click(function(e){
1719 $selectedselect.append($availableselect.children('option:selected'));
1758 $selectedselect.append($availableselect.children('option:selected'));
1720 });
1759 });
1721 $('#remove_element').click(function(e){
1760 $('#remove_element').click(function(e){
1722 $availableselect.append($selectedselect.children('option:selected'));
1761 $availableselect.append($selectedselect.children('option:selected'));
1723 });
1762 });
1724 $('#add_all_elements').click(function(e){
1763 $('#add_all_elements').click(function(e){
1725 $selectedselect.append($availableselect.children('option'));
1764 $selectedselect.append($availableselect.children('option'));
1726 });
1765 });
1727 $('#remove_all_elements').click(function(e){
1766 $('#remove_all_elements').click(function(e){
1728 $availableselect.append($selectedselect.children('option'));
1767 $availableselect.append($selectedselect.children('option'));
1729 });
1768 });
1730
1769
1731 $('#'+form_id).submit(function(){
1770 $('#'+form_id).submit(function(){
1732 $selectedselect.children('option').each(function(i, e){
1771 $selectedselect.children('option').each(function(i, e){
1733 e.selected = 'selected';
1772 e.selected = 'selected';
1734 });
1773 });
1735 });
1774 });
1736 }
1775 }
1737
1776
1738 // custom paginator
1777 // custom paginator
1739 var YUI_paginator = function(links_per_page, containers){
1778 var YUI_paginator = function(links_per_page, containers){
1740
1779
1741 (function () {
1780 (function () {
1742
1781
1743 var Paginator = YAHOO.widget.Paginator,
1782 var Paginator = YAHOO.widget.Paginator,
1744 l = YAHOO.lang,
1783 l = YAHOO.lang,
1745 setId = YAHOO.util.Dom.generateId;
1784 setId = YAHOO.util.Dom.generateId;
1746
1785
1747 Paginator.ui.MyFirstPageLink = function (p) {
1786 Paginator.ui.MyFirstPageLink = function (p) {
1748 this.paginator = p;
1787 this.paginator = p;
1749
1788
1750 p.subscribe('recordOffsetChange',this.update,this,true);
1789 p.subscribe('recordOffsetChange',this.update,this,true);
1751 p.subscribe('rowsPerPageChange',this.update,this,true);
1790 p.subscribe('rowsPerPageChange',this.update,this,true);
1752 p.subscribe('totalRecordsChange',this.update,this,true);
1791 p.subscribe('totalRecordsChange',this.update,this,true);
1753 p.subscribe('destroy',this.destroy,this,true);
1792 p.subscribe('destroy',this.destroy,this,true);
1754
1793
1755 // TODO: make this work
1794 // TODO: make this work
1756 p.subscribe('firstPageLinkLabelChange',this.update,this,true);
1795 p.subscribe('firstPageLinkLabelChange',this.update,this,true);
1757 p.subscribe('firstPageLinkClassChange',this.update,this,true);
1796 p.subscribe('firstPageLinkClassChange',this.update,this,true);
1758 };
1797 };
1759
1798
1760 Paginator.ui.MyFirstPageLink.init = function (p) {
1799 Paginator.ui.MyFirstPageLink.init = function (p) {
1761 p.setAttributeConfig('firstPageLinkLabel', {
1800 p.setAttributeConfig('firstPageLinkLabel', {
1762 value : 1,
1801 value : 1,
1763 validator : l.isString
1802 validator : l.isString
1764 });
1803 });
1765 p.setAttributeConfig('firstPageLinkClass', {
1804 p.setAttributeConfig('firstPageLinkClass', {
1766 value : 'yui-pg-first',
1805 value : 'yui-pg-first',
1767 validator : l.isString
1806 validator : l.isString
1768 });
1807 });
1769 p.setAttributeConfig('firstPageLinkTitle', {
1808 p.setAttributeConfig('firstPageLinkTitle', {
1770 value : 'First Page',
1809 value : 'First Page',
1771 validator : l.isString
1810 validator : l.isString
1772 });
1811 });
1773 };
1812 };
1774
1813
1775 // Instance members and methods
1814 // Instance members and methods
1776 Paginator.ui.MyFirstPageLink.prototype = {
1815 Paginator.ui.MyFirstPageLink.prototype = {
1777 current : null,
1816 current : null,
1778 leftmost_page: null,
1817 leftmost_page: null,
1779 rightmost_page: null,
1818 rightmost_page: null,
1780 link : null,
1819 link : null,
1781 span : null,
1820 span : null,
1782 dotdot : null,
1821 dotdot : null,
1783 getPos : function(cur_page, max_page, items){
1822 getPos : function(cur_page, max_page, items){
1784 var edge = parseInt(items / 2) + 1;
1823 var edge = parseInt(items / 2) + 1;
1785 if (cur_page <= edge){
1824 if (cur_page <= edge){
1786 var radius = Math.max(parseInt(items / 2), items - cur_page);
1825 var radius = Math.max(parseInt(items / 2), items - cur_page);
1787 }
1826 }
1788 else if ((max_page - cur_page) < edge) {
1827 else if ((max_page - cur_page) < edge) {
1789 var radius = (items - 1) - (max_page - cur_page);
1828 var radius = (items - 1) - (max_page - cur_page);
1790 }
1829 }
1791 else{
1830 else{
1792 var radius = parseInt(items / 2);
1831 var radius = parseInt(items / 2);
1793 }
1832 }
1794
1833
1795 var left = Math.max(1, (cur_page - (radius)))
1834 var left = Math.max(1, (cur_page - (radius)))
1796 var right = Math.min(max_page, cur_page + (radius))
1835 var right = Math.min(max_page, cur_page + (radius))
1797 return [left, cur_page, right]
1836 return [left, cur_page, right]
1798 },
1837 },
1799 render : function (id_base) {
1838 render : function (id_base) {
1800 var p = this.paginator,
1839 var p = this.paginator,
1801 c = p.get('firstPageLinkClass'),
1840 c = p.get('firstPageLinkClass'),
1802 label = p.get('firstPageLinkLabel'),
1841 label = p.get('firstPageLinkLabel'),
1803 title = p.get('firstPageLinkTitle');
1842 title = p.get('firstPageLinkTitle');
1804
1843
1805 this.link = document.createElement('a');
1844 this.link = document.createElement('a');
1806 this.span = document.createElement('span');
1845 this.span = document.createElement('span');
1807 $(this.span).hide();
1846 $(this.span).hide();
1808
1847
1809 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1848 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1810 this.leftmost_page = _pos[0];
1849 this.leftmost_page = _pos[0];
1811 this.rightmost_page = _pos[2];
1850 this.rightmost_page = _pos[2];
1812
1851
1813 setId(this.link, id_base + '-first-link');
1852 setId(this.link, id_base + '-first-link');
1814 this.link.href = '#';
1853 this.link.href = '#';
1815 this.link.className = c;
1854 this.link.className = c;
1816 this.link.innerHTML = label;
1855 this.link.innerHTML = label;
1817 this.link.title = title;
1856 this.link.title = title;
1818 YUE.on(this.link,'click',this.onClick,this,true);
1857 YUE.on(this.link,'click',this.onClick,this,true);
1819
1858
1820 setId(this.span, id_base + '-first-span');
1859 setId(this.span, id_base + '-first-span');
1821 this.span.className = c;
1860 this.span.className = c;
1822 this.span.innerHTML = label;
1861 this.span.innerHTML = label;
1823
1862
1824 this.current = p.getCurrentPage() > 1 ? this.link : this.span;
1863 this.current = p.getCurrentPage() > 1 ? this.link : this.span;
1825 return this.current;
1864 return this.current;
1826 },
1865 },
1827 update : function (e) {
1866 update : function (e) {
1828 var p = this.paginator;
1867 var p = this.paginator;
1829 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1868 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1830 this.leftmost_page = _pos[0];
1869 this.leftmost_page = _pos[0];
1831 this.rightmost_page = _pos[2];
1870 this.rightmost_page = _pos[2];
1832
1871
1833 if (e && e.prevValue === e.newValue) {
1872 if (e && e.prevValue === e.newValue) {
1834 return;
1873 return;
1835 }
1874 }
1836
1875
1837 var par = this.current ? this.current.parentNode : null;
1876 var par = this.current ? this.current.parentNode : null;
1838 if (this.leftmost_page > 1) {
1877 if (this.leftmost_page > 1) {
1839 if (par && this.current === this.span) {
1878 if (par && this.current === this.span) {
1840 par.replaceChild(this.link,this.current);
1879 par.replaceChild(this.link,this.current);
1841 this.current = this.link;
1880 this.current = this.link;
1842 }
1881 }
1843 } else {
1882 } else {
1844 if (par && this.current === this.link) {
1883 if (par && this.current === this.link) {
1845 par.replaceChild(this.span,this.current);
1884 par.replaceChild(this.span,this.current);
1846 this.current = this.span;
1885 this.current = this.span;
1847 }
1886 }
1848 }
1887 }
1849 },
1888 },
1850 destroy : function () {
1889 destroy : function () {
1851 YUE.purgeElement(this.link);
1890 YUE.purgeElement(this.link);
1852 this.current.parentNode.removeChild(this.current);
1891 this.current.parentNode.removeChild(this.current);
1853 this.link = this.span = null;
1892 this.link = this.span = null;
1854 },
1893 },
1855 onClick : function (e) {
1894 onClick : function (e) {
1856 YUE.stopEvent(e);
1895 YUE.stopEvent(e);
1857 this.paginator.setPage(1);
1896 this.paginator.setPage(1);
1858 }
1897 }
1859 };
1898 };
1860
1899
1861 })();
1900 })();
1862
1901
1863 (function () {
1902 (function () {
1864
1903
1865 var Paginator = YAHOO.widget.Paginator,
1904 var Paginator = YAHOO.widget.Paginator,
1866 l = YAHOO.lang,
1905 l = YAHOO.lang,
1867 setId = YAHOO.util.Dom.generateId;
1906 setId = YAHOO.util.Dom.generateId;
1868
1907
1869 Paginator.ui.MyLastPageLink = function (p) {
1908 Paginator.ui.MyLastPageLink = function (p) {
1870 this.paginator = p;
1909 this.paginator = p;
1871
1910
1872 p.subscribe('recordOffsetChange',this.update,this,true);
1911 p.subscribe('recordOffsetChange',this.update,this,true);
1873 p.subscribe('rowsPerPageChange',this.update,this,true);
1912 p.subscribe('rowsPerPageChange',this.update,this,true);
1874 p.subscribe('totalRecordsChange',this.update,this,true);
1913 p.subscribe('totalRecordsChange',this.update,this,true);
1875 p.subscribe('destroy',this.destroy,this,true);
1914 p.subscribe('destroy',this.destroy,this,true);
1876
1915
1877 // TODO: make this work
1916 // TODO: make this work
1878 p.subscribe('lastPageLinkLabelChange',this.update,this,true);
1917 p.subscribe('lastPageLinkLabelChange',this.update,this,true);
1879 p.subscribe('lastPageLinkClassChange', this.update,this,true);
1918 p.subscribe('lastPageLinkClassChange', this.update,this,true);
1880 };
1919 };
1881
1920
1882 Paginator.ui.MyLastPageLink.init = function (p) {
1921 Paginator.ui.MyLastPageLink.init = function (p) {
1883 p.setAttributeConfig('lastPageLinkLabel', {
1922 p.setAttributeConfig('lastPageLinkLabel', {
1884 value : -1,
1923 value : -1,
1885 validator : l.isString
1924 validator : l.isString
1886 });
1925 });
1887 p.setAttributeConfig('lastPageLinkClass', {
1926 p.setAttributeConfig('lastPageLinkClass', {
1888 value : 'yui-pg-last',
1927 value : 'yui-pg-last',
1889 validator : l.isString
1928 validator : l.isString
1890 });
1929 });
1891 p.setAttributeConfig('lastPageLinkTitle', {
1930 p.setAttributeConfig('lastPageLinkTitle', {
1892 value : 'Last Page',
1931 value : 'Last Page',
1893 validator : l.isString
1932 validator : l.isString
1894 });
1933 });
1895
1934
1896 };
1935 };
1897
1936
1898 Paginator.ui.MyLastPageLink.prototype = {
1937 Paginator.ui.MyLastPageLink.prototype = {
1899
1938
1900 current : null,
1939 current : null,
1901 leftmost_page: null,
1940 leftmost_page: null,
1902 rightmost_page: null,
1941 rightmost_page: null,
1903 link : null,
1942 link : null,
1904 span : null,
1943 span : null,
1905 dotdot : null,
1944 dotdot : null,
1906 na : null,
1945 na : null,
1907 getPos : function(cur_page, max_page, items){
1946 getPos : function(cur_page, max_page, items){
1908 var edge = parseInt(items / 2) + 1;
1947 var edge = parseInt(items / 2) + 1;
1909 if (cur_page <= edge){
1948 if (cur_page <= edge){
1910 var radius = Math.max(parseInt(items / 2), items - cur_page);
1949 var radius = Math.max(parseInt(items / 2), items - cur_page);
1911 }
1950 }
1912 else if ((max_page - cur_page) < edge) {
1951 else if ((max_page - cur_page) < edge) {
1913 var radius = (items - 1) - (max_page - cur_page);
1952 var radius = (items - 1) - (max_page - cur_page);
1914 }
1953 }
1915 else{
1954 else{
1916 var radius = parseInt(items / 2);
1955 var radius = parseInt(items / 2);
1917 }
1956 }
1918
1957
1919 var left = Math.max(1, (cur_page - (radius)))
1958 var left = Math.max(1, (cur_page - (radius)))
1920 var right = Math.min(max_page, cur_page + (radius))
1959 var right = Math.min(max_page, cur_page + (radius))
1921 return [left, cur_page, right]
1960 return [left, cur_page, right]
1922 },
1961 },
1923 render : function (id_base) {
1962 render : function (id_base) {
1924 var p = this.paginator,
1963 var p = this.paginator,
1925 c = p.get('lastPageLinkClass'),
1964 c = p.get('lastPageLinkClass'),
1926 label = p.get('lastPageLinkLabel'),
1965 label = p.get('lastPageLinkLabel'),
1927 last = p.getTotalPages(),
1966 last = p.getTotalPages(),
1928 title = p.get('lastPageLinkTitle');
1967 title = p.get('lastPageLinkTitle');
1929
1968
1930 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1969 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1931 this.leftmost_page = _pos[0];
1970 this.leftmost_page = _pos[0];
1932 this.rightmost_page = _pos[2];
1971 this.rightmost_page = _pos[2];
1933
1972
1934 this.link = document.createElement('a');
1973 this.link = document.createElement('a');
1935 this.span = document.createElement('span');
1974 this.span = document.createElement('span');
1936 $(this.span).hide();
1975 $(this.span).hide();
1937
1976
1938 this.na = this.span.cloneNode(false);
1977 this.na = this.span.cloneNode(false);
1939
1978
1940 setId(this.link, id_base + '-last-link');
1979 setId(this.link, id_base + '-last-link');
1941 this.link.href = '#';
1980 this.link.href = '#';
1942 this.link.className = c;
1981 this.link.className = c;
1943 this.link.innerHTML = label;
1982 this.link.innerHTML = label;
1944 this.link.title = title;
1983 this.link.title = title;
1945 YUE.on(this.link,'click',this.onClick,this,true);
1984 YUE.on(this.link,'click',this.onClick,this,true);
1946
1985
1947 setId(this.span, id_base + '-last-span');
1986 setId(this.span, id_base + '-last-span');
1948 this.span.className = c;
1987 this.span.className = c;
1949 this.span.innerHTML = label;
1988 this.span.innerHTML = label;
1950
1989
1951 setId(this.na, id_base + '-last-na');
1990 setId(this.na, id_base + '-last-na');
1952
1991
1953 if (this.rightmost_page < p.getTotalPages()){
1992 if (this.rightmost_page < p.getTotalPages()){
1954 this.current = this.link;
1993 this.current = this.link;
1955 }
1994 }
1956 else{
1995 else{
1957 this.current = this.span;
1996 this.current = this.span;
1958 }
1997 }
1959
1998
1960 this.current.innerHTML = p.getTotalPages();
1999 this.current.innerHTML = p.getTotalPages();
1961 return this.current;
2000 return this.current;
1962 },
2001 },
1963
2002
1964 update : function (e) {
2003 update : function (e) {
1965 var p = this.paginator;
2004 var p = this.paginator;
1966
2005
1967 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
2006 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1968 this.leftmost_page = _pos[0];
2007 this.leftmost_page = _pos[0];
1969 this.rightmost_page = _pos[2];
2008 this.rightmost_page = _pos[2];
1970
2009
1971 if (e && e.prevValue === e.newValue) {
2010 if (e && e.prevValue === e.newValue) {
1972 return;
2011 return;
1973 }
2012 }
1974
2013
1975 var par = this.current ? this.current.parentNode : null,
2014 var par = this.current ? this.current.parentNode : null,
1976 after = this.link;
2015 after = this.link;
1977 if (par) {
2016 if (par) {
1978
2017
1979 // only show the last page if the rightmost one is
2018 // only show the last page if the rightmost one is
1980 // lower, so we don't have doubled entries at the end
2019 // lower, so we don't have doubled entries at the end
1981 if (!(this.rightmost_page < p.getTotalPages())){
2020 if (!(this.rightmost_page < p.getTotalPages())){
1982 after = this.span
2021 after = this.span
1983 }
2022 }
1984
2023
1985 if (this.current !== after) {
2024 if (this.current !== after) {
1986 par.replaceChild(after,this.current);
2025 par.replaceChild(after,this.current);
1987 this.current = after;
2026 this.current = after;
1988 }
2027 }
1989 }
2028 }
1990 this.current.innerHTML = this.paginator.getTotalPages();
2029 this.current.innerHTML = this.paginator.getTotalPages();
1991
2030
1992 },
2031 },
1993 destroy : function () {
2032 destroy : function () {
1994 YUE.purgeElement(this.link);
2033 YUE.purgeElement(this.link);
1995 this.current.parentNode.removeChild(this.current);
2034 this.current.parentNode.removeChild(this.current);
1996 this.link = this.span = null;
2035 this.link = this.span = null;
1997 },
2036 },
1998 onClick : function (e) {
2037 onClick : function (e) {
1999 YUE.stopEvent(e);
2038 YUE.stopEvent(e);
2000 this.paginator.setPage(this.paginator.getTotalPages());
2039 this.paginator.setPage(this.paginator.getTotalPages());
2001 }
2040 }
2002 };
2041 };
2003
2042
2004 })();
2043 })();
2005
2044
2006 var pagi = new YAHOO.widget.Paginator({
2045 var pagi = new YAHOO.widget.Paginator({
2007 rowsPerPage: links_per_page,
2046 rowsPerPage: links_per_page,
2008 alwaysVisible: false,
2047 alwaysVisible: false,
2009 template : "{PreviousPageLink} {MyFirstPageLink} {PageLinks} {MyLastPageLink} {NextPageLink}",
2048 template : "{PreviousPageLink} {MyFirstPageLink} {PageLinks} {MyLastPageLink} {NextPageLink}",
2010 pageLinks: 5,
2049 pageLinks: 5,
2011 containerClass: 'pagination-wh',
2050 containerClass: 'pagination-wh',
2012 currentPageClass: 'pager_curpage',
2051 currentPageClass: 'pager_curpage',
2013 pageLinkClass: 'pager_link',
2052 pageLinkClass: 'pager_link',
2014 nextPageLinkLabel: '&gt;',
2053 nextPageLinkLabel: '&gt;',
2015 previousPageLinkLabel: '&lt;',
2054 previousPageLinkLabel: '&lt;',
2016 containers:containers
2055 containers:containers
2017 })
2056 })
2018
2057
2019 return pagi
2058 return pagi
2020 }
2059 }
2021
2060
2022
2061
2023 // global hooks after DOM is loaded
2062 // global hooks after DOM is loaded
2024
2063
2025 $(document).ready(function(){
2064 $(document).ready(function(){
2026 $('.diff-collapse-button').click(function(e) {
2065 $('.diff-collapse-button').click(function(e) {
2027 var $button = $(e.currentTarget);
2066 var $button = $(e.currentTarget);
2028 var $target = $('#' + $button.attr('target'));
2067 var $target = $('#' + $button.attr('target'));
2029 if($target.hasClass('hidden')){
2068 if($target.hasClass('hidden')){
2030 $target.removeClass('hidden');
2069 $target.removeClass('hidden');
2031 $button.html("&uarr; {0} &uarr;".format(_TM['Collapse diff']));
2070 $button.html("&uarr; {0} &uarr;".format(_TM['Collapse diff']));
2032 }
2071 }
2033 else if(!$target.hasClass('hidden')){
2072 else if(!$target.hasClass('hidden')){
2034 $target.addClass('hidden');
2073 $target.addClass('hidden');
2035 $button.html("&darr; {0} &darr;".format(_TM['Expand diff']));
2074 $button.html("&darr; {0} &darr;".format(_TM['Expand diff']));
2036 }
2075 }
2037 });
2076 });
2038 });
2077 });
General Comments 0
You need to be logged in to leave comments. Login now