1 /*jslint 2 bitwise: false, 3 browser: true, 4 newcap: false, 5 nomen: false, 6 debug: true, 7 forin: true, 8 plusplus: false, 9 undef: true, 10 white: false, 11 onevar: false 12 */ 13 var sc; 14 15 /** 16 * determines if a string contains the given screen name prefixed with a @ 17 * this is mainly used for determining if a message should be considered a 'mention' 18 * @param {string} str the string to check 19 * @param {string} sn the screen name to look for 20 * @return {boolean} 21 * @member sc.helpers 22 */ 23 sc.helpers.containsScreenName = function(str, sn) { 24 25 var re = new RegExp('(?:\\s|\\b|^[[:alnum:]]|^)@('+sn+')(?:\\s|\\b|$)', 'gi'); 26 if ( re.test(str) ) { 27 return true; 28 } 29 return false; 30 31 }; 32 33 sc.helpers.extractScreenNames = function(str, tpl) { 34 // var re_uname = /(^|\s|\(\[|,|\.|\()@([a-zA-Z0-9_]+)([^a-zA-Z0-9_]|$)/gi; 35 var re_uname = /(?:^|\s|\(\[|,|\.|\()@([a-zA-Z0-9_]+)/gi; 36 var usernames = []; 37 var ms = []; 38 while (ms = re_uname.exec(str)) 39 { 40 /* 41 sometimes we can end up with a null instead of a blank string, 42 so we need to force the issue in javascript. 43 */ 44 for (var x=0; x<ms.length; x++) { 45 if (!ms[x]) { 46 ms[x] = ''; 47 } 48 } 49 50 if(ms[1] != ''){ 51 usernames.push(ms[1]); 52 } 53 } 54 return usernames; 55 }; 56 57 /** 58 * find URLs within the given string 59 * @member sc.helpers 60 */ 61 sc.helpers.extractURLs = function(str) { 62 // var wwwlinks = /(^|\s)((https?|ftp)\:\/\/)?([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?([✪a-z0-9-.]*)\.([a-z]{2,3})(\:[0-9]{2,5})?(\/([a-z0-9+\$_-]\.?)+)*\/?(\?[a-z+&\$_.-][a-z0-9;:@&%=+\/\$_.-]*)?(#[a-z_.-][a-z0-9+\$_.-]*)?(\s|$)/gi; 63 var wwwlinks = /(^|\s|\(|:)(((http(s?):\/\/)|(www\.))([\w✪]+[^\s\)<]+))/gi; 64 65 var ms = []; 66 var URLs = []; 67 while ( (ms = wwwlinks.exec(str)) !== null ) { 68 for (var x=0; x<ms.length; x++) { 69 if (!ms[x]) { 70 ms[x] = ''; 71 } 72 } 73 var last = ms[7].charAt(ms[7].length - 1); 74 if (last.search(/[\.,;\?]/) !== -1) { // if ends in common punctuation, strip 75 ms[7] = ms[7].slice(0,-1); 76 } 77 URLs.push(ms[3]+ms[7]); 78 } 79 return URLs; 80 }; 81 82 /** 83 * given as string and a mapping object, replace multiple values in the string (or vice versa) 84 * map should be of format 85 * { 86 * 'searchforme':'replacewithme', 87 * 'searchforme2':'replacewithme2', 88 * 'searchforme3':'replacewithme3' 89 * } 90 * @param {string} str 91 * @param {object} map 92 * @return {string} 93 * @member sc.helpers 94 */ 95 sc.helpers.replaceMultiple = function(str, map) { 96 for (var key in map) { 97 str = str.replace(key, map[key]); 98 } 99 return str; 100 }; 101 102 103 /** 104 * This is a port of the CodeIgniter helper "autolink" to javascript. 105 * It finds and links both web addresses and email addresses. It will ignore 106 * links within HTML (as attributes or between tag pairs) 107 * 108 * @param {string} str 109 * @param {string} type 'email', 'url', or 'both' (default is 'both') 110 * @param {boolean} extra_code a string that will be inserted verbatim into <a> tag 111 * @param {integer} maxlen the maximum length the link description can be (the string inside the <a></a> tag) 112 * @return {string} 113 * @member sc.helpers 114 */ 115 sc.helpers.autolink = function(str, type, extra_code, maxlen) { 116 if (!type) { 117 type = 'both'; 118 } 119 120 var re_nohttpurl = /((^|\s)(www\.)?([a-zA-Z_\-]+\.)(com|net|org|uk)($|\s))/gi; 121 122 var re_noemail = /(^|[\s\(:。])((http(s?):\/\/)|(www\.))([\w✪]+[^\s\)<]+)/gi; 123 var re_nourl = /(^|\s|\()([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]*)([^\s\)<]+)/gi; 124 125 var x, ms, period = ''; 126 127 if (type !== 'email') 128 { 129 while ((ms = re_nohttpurl.exec(str))) { // look for URLs without a preceding "http://" 130 /* 131 sometimes we can end up with a null instead of a blank string, 132 so we need to force the issue in javascript. 133 */ 134 for (x=0; x<ms.length; x++) { 135 if (!ms[x]) { 136 ms[x] = ''; 137 } 138 } 139 140 if (extra_code) { 141 extra_code = ' '+extra_code; 142 } else { 143 extra_code = ''; 144 } 145 146 var desc = ms[3]+ms[4]+ms[5]; 147 148 if (maxlen && maxlen > 0 && desc.length > maxlen) { 149 desc = desc.substr(0, maxlen)+'...'; 150 } 151 152 var newstr = ms[2]+'<a href="http://'+ms[3]+ms[4]+ms[5]+'"'+extra_code+'>'+desc+'</a>'+ms[6]; 153 sch.error(newstr); 154 str = str.replace(ms[0], newstr); 155 } 156 157 158 while ((ms = re_noemail.exec(str))) { 159 160 /* 161 sometimes we can end up with a null instead of a blank string, 162 so we need to force the issue in javascript. 163 */ 164 for (x=0; x<ms.length; x++) { 165 if (!ms[x]) { 166 ms[x] = ''; 167 } 168 } 169 170 if (extra_code) { 171 extra_code = ' '+extra_code; 172 } else { 173 extra_code = ''; 174 } 175 176 /* 177 if the last character is one of . , ; ?, we strip it off and 178 stick it on the end of newstr below as "period" 179 */ 180 var last = ms[6].charAt(ms[6].length - 1); 181 if (last.search(/[\.,;\?]/) !== -1) { 182 ms[6] = ms[6].slice(0,-1); 183 period = last; 184 } 185 186 187 var desc = ms[5]+ms[6]; 188 189 if (maxlen && maxlen > 0 && desc.length > maxlen) { 190 desc = desc.substr(0, maxlen)+'...'; 191 } 192 193 194 var newstr = ms[1]+'<a href="http'+ms[4]+'://'+ms[5]+ms[6]+'"'+extra_code+'>'+desc+'</a>'+period; 195 str = str.replace(ms[0], newstr); 196 } 197 } 198 199 if (type !== 'url') 200 { 201 while ((ms = re_nourl.exec(str))) 202 { 203 period = ''; 204 if ( /\./.test(ms[5]) ) { 205 period = '.'; 206 ms[5] = ms[5].slice(0, -1); 207 } 208 209 /* 210 sometimes we can end up with a null instead of a blank string, 211 so we need to force the issue in javascript. 212 */ 213 for (x=0; x<ms.length; x++) { 214 if (!ms[x]) { 215 ms[x] = ''; 216 } 217 } 218 str = str.replace(ms[0], ms[1]+'<a href="mailto:'+ms[2]+'@'+ms[3]+'.'+ms[4]+ms[5]+'">'+ms[2]+'@'+ms[3]+'.'+ms[4]+ms[5]+'</a>'+period); 219 } 220 } 221 222 return str; 223 224 225 }; 226 227 /** 228 * turns twitter style username refs ('@username') into links 229 * by default, the template used is <a href="http://twitter.com/#username#">@#username#<a/> 230 * pass the second param to give it a custom template 231 * 232 * @param {string} str 233 * @param {string} tpl default is '<a href="http://twitter.com/#username#">@#username#</a>' 234 * @return {string} 235 * @member sc.helpers 236 */ 237 sc.helpers.autolinkTwitterScreenname = function(str, tpl) { 238 if (!tpl) { 239 tpl = '<a href="http://twitter.com/#username#">@#username#</a>'; 240 } 241 242 var re_uname = /(^|\s|\(\[|,|\.|\()@([a-zA-Z0-9_]+)([^a-zA-Z0-9_]|$)/gi; 243 244 var ms = []; 245 while (ms = re_uname.exec(str)) 246 { 247 248 /* 249 sometimes we can end up with a null instead of a blank string, 250 so we need to force the issue in javascript. 251 */ 252 for (var x=0; x<ms.length; x++) { 253 if (!ms[x]) { 254 ms[x] = ''; 255 } 256 } 257 258 var repl_tpl = tpl.replace(/#username#/gi, ms[2]); 259 str = str.replace(ms[0], ms[1]+repl_tpl+ms[3]); 260 261 } 262 return str; 263 }; 264 265 266 267 /** 268 * turns twitter style hashtags ('#hashtag') into links 269 * by default, the template used is <a href="http://search.twitter.com/search?q=#hashtag_enc#">##hashtag#<a/> 270 * pass the second param to give it a custom template 271 * 272 * @param {string} str 273 * @param {string} tpl default is '<a href="http://search.twitter.com/search?q=#hashtag_enc#">##hashtag#<a/>' 274 * @return {string} 275 * @member sc.helpers 276 */ 277 sc.helpers.autolinkTwitterHashtag = function(str, tpl) { 278 if (!tpl) { 279 tpl = '<a href="http://search.twitter.com/search?q=#hashtag_enc#">##hashtag#</a>'; 280 } 281 282 var re_hashtag = /(^|\s|\()#([a-zA-Z0-9\-_\.+:=]{1,}\w)([^a-zA-Z0-9\-_+]|$)/gi; 283 284 var ms = []; 285 while (ms = re_hashtag.exec(str)) 286 { 287 288 /* 289 sometimes we can end up with a null instead of a blank string, 290 so we need to force the issue in javascript. 291 */ 292 for (var x=0; x<ms.length; x++) { 293 if (!ms[x]) { 294 ms[x] = ''; 295 } 296 } 297 298 var repl_tpl = tpl.replace(/#hashtag#/gi, ms[2]); 299 repl_tpl = repl_tpl.replace(/#hashtag_enc#/gi, encodeURIComponent(ms[2])); 300 str = str.replace(ms[0], ms[1]+repl_tpl+ms[3]); 301 302 } 303 return str; 304 }; 305 306 307 308 /** 309 * Applies autolink, autolinkTwitterScreenname, autolinkTwitterHashtag 310 * 311 * @param {string} str 312 * @param {oobject} opts 313 * 314 * Opts structure: 315 * { 316 * 'autolink': { 317 * 'type' :'both', (email, url, or both) 318 * 'extra_code':'', 319 * 'maxlen' :20 320 * }, 321 * 'screenname': { 322 * 'tpl':'' // should contain macro '#username#' 323 * }, 324 * 'hashtag': { 325 * 'tpl':'' // should contain macros '#hashtag#' and '#hashtag_enc#' 326 * } 327 * } 328 * @member sc.helpers 329 */ 330 sc.helpers.makeClickable = function(str, opts) { 331 var autolink_type, autolink_extra_code, autolink_maxlen, screenname_tpl, hashtag_tpl; 332 333 if (!opts) { 334 opts = {}; 335 } 336 337 if (opts.autolink) { 338 var autolink_type = opts.autolink.type || null; 339 var autolink_extra_code = opts.autolink.extra_code || null; 340 var autolink_maxlen = opts.autolink.maxlen || null; 341 } 342 343 if (opts.screenname) { 344 var screenname_tpl = opts.screenname.tpl || null; 345 } 346 347 if (opts.hashtag) { 348 var hashtag_tpl = opts.hashtag.tpl || null; 349 } 350 351 str = sc.helpers.autolink(str, autolink_type, autolink_extra_code, autolink_maxlen); 352 str = sc.helpers.autolinkTwitterScreenname(str, screenname_tpl); 353 str = sc.helpers.autolinkTwitterHashtag(str, hashtag_tpl); 354 return str; 355 }; 356 357 358 359 /** 360 * Simple html tag remover 361 * @param {string} str 362 * @return {string} 363 * @member sc.helpers 364 */ 365 sc.helpers.stripTags = function(str) { 366 var re = /<[^>]*>/gim; 367 str = str.replace(re, ''); 368 return str; 369 }; 370 371 372 /** 373 * Converts the following entities into regular chars: < > " ' 374 * @member sc.helpers 375 */ 376 sc.helpers.fromHTMLSpecialChars = function(str) { 377 str = str.replace(/</gi, '<'); 378 sc.helpers.dump(str); 379 str = str.replace(/>/gi, '>'); 380 sc.helpers.dump(str); 381 str = str.replace(/"/gi, '"'); 382 sc.helpers.dump(str); 383 str = str.replace(/'/gi, '\''); 384 sc.helpers.dump(str); 385 str = str.replace(/&/gi, '&'); 386 sc.helpers.dump(str); 387 return str; 388 }; 389 390 391 sc.helpers.escape_html = function(string) { 392 return sc.helpers.htmlspecialchars(string, 'ENT_QUOTES'); 393 }; 394 395 396 sc.helpers.htmlspecialchars = function(string, quote_style) { 397 // http://kevin.vanzonneveld.net 398 // + original by: Mirek Slugen 399 // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 400 // + bugfixed by: Nathan 401 // + bugfixed by: Arno 402 // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 403 // - depends on: get_html_translation_table 404 // * example 1: htmlspecialchars("<a href='test'>Test</a>", 'ENT_QUOTES'); 405 // * returns 1: '<a href='test'>Test</a>' 406 407 var histogram = {}, symbol = '', tmp_str = '', i = 0; 408 tmp_str = string.toString(); 409 410 if (false === (histogram = sc.helpers._get_html_translation_table('HTML_SPECIALCHARS', quote_style))) { 411 return false; 412 } 413 414 // first, do & 415 tmp_str = tmp_str.split('&').join(histogram['&']); 416 417 // then do the rest 418 for (symbol in histogram) { 419 if (symbol != '&') { 420 entity = histogram[symbol]; 421 tmp_str = tmp_str.split(symbol).join(entity); 422 } 423 } 424 425 return tmp_str; 426 }; 427 428 429 430 sc.helpers.htmlentities = function(string, quote_style) { 431 // http://kevin.vanzonneveld.net 432 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 433 // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 434 // + improved by: nobbler 435 // + tweaked by: Jack 436 // + bugfixed by: Onno Marsman 437 // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 438 // - depends on: get_html_translation_table 439 // * example 1: htmlentities('Kevin & van Zonneveld'); 440 // * returns 1: 'Kevin & van Zonneveld' 441 // * example 2: htmlentities("foo'bar","ENT_QUOTES"); 442 // * returns 2: 'foo'bar' 443 444 var histogram = {}, symbol = '', tmp_str = '', entity = ''; 445 tmp_str = string.toString(); 446 447 if (false === (histogram = sc.helpers._get_html_translation_table('HTML_ENTITIES', quote_style))) { 448 return false; 449 } 450 451 for (symbol in histogram) { 452 entity = histogram[symbol]; 453 tmp_str = tmp_str.split(symbol).join(entity); 454 } 455 456 return tmp_str; 457 }; 458 459 sc.helpers._get_html_translation_table = function(table, quote_style) { 460 // http://kevin.vanzonneveld.net 461 // + original by: Philip Peterson 462 // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 463 // + bugfixed by: noname 464 // + bugfixed by: Alex 465 // + bugfixed by: Marco 466 // + bugfixed by: madipta 467 // % note: It has been decided that we're not going to add global 468 // % note: dependencies to php.js. Meaning the constants are not 469 // % note: real constants, but strings instead. integers are also supported if someone 470 // % note: chooses to create the constants themselves. 471 // % note: Table from http://www.the-art-of-web.com/html/character-codes/ 472 // * example 1: get_html_translation_table('HTML_SPECIALCHARS'); 473 // * returns 1: {'"': '"', '&': '&', '<': '<', '>': '>'} 474 475 var entities = {}, histogram = {}, decimal = 0, symbol = ''; 476 var constMappingTable = {}, constMappingQuoteStyle = {}; 477 var useTable = {}, useQuoteStyle = {}; 478 479 useTable = (table ? table.toUpperCase() : 'HTML_SPECIALCHARS'); 480 useQuoteStyle = (quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT'); 481 482 // Translate arguments 483 constMappingTable[0] = 'HTML_SPECIALCHARS'; 484 constMappingTable[1] = 'HTML_ENTITIES'; 485 constMappingQuoteStyle[0] = 'ENT_NOQUOTES'; 486 constMappingQuoteStyle[2] = 'ENT_COMPAT'; 487 constMappingQuoteStyle[3] = 'ENT_QUOTES'; 488 489 // Map numbers to strings for compatibilty with PHP constants 490 if (!isNaN(useTable)) { 491 useTable = constMappingTable[useTable]; 492 } 493 if (!isNaN(useQuoteStyle)) { 494 useQuoteStyle = constMappingQuoteStyle[useQuoteStyle]; 495 } 496 497 if (useTable === 'HTML_SPECIALCHARS') { 498 // ascii decimals for better compatibility 499 entities['38'] = '&'; 500 if (useQuoteStyle !== 'ENT_NOQUOTES') { 501 entities['34'] = '"'; 502 } 503 if (useQuoteStyle === 'ENT_QUOTES') { 504 entities['39'] = '''; 505 } 506 entities['60'] = '<'; 507 entities['62'] = '>'; 508 } else if (useTable === 'HTML_ENTITIES') { 509 // ascii decimals for better compatibility 510 entities['38'] = '&'; 511 if (useQuoteStyle !== 'ENT_NOQUOTES') { 512 entities['34'] = '"'; 513 } 514 if (useQuoteStyle === 'ENT_QUOTES') { 515 entities['39'] = '''; 516 } 517 entities['60'] = '<'; 518 entities['62'] = '>'; 519 entities['160'] = ' '; 520 entities['161'] = '¡'; 521 entities['162'] = '¢'; 522 entities['163'] = '£'; 523 entities['164'] = '¤'; 524 entities['165'] = '¥'; 525 entities['166'] = '¦'; 526 entities['167'] = '§'; 527 entities['168'] = '¨'; 528 entities['169'] = '©'; 529 entities['170'] = 'ª'; 530 entities['171'] = '«'; 531 entities['172'] = '¬'; 532 entities['173'] = ''; 533 entities['174'] = '®'; 534 entities['175'] = '¯'; 535 entities['176'] = '°'; 536 entities['177'] = '±'; 537 entities['178'] = '²'; 538 entities['179'] = '³'; 539 entities['180'] = '´'; 540 entities['181'] = 'µ'; 541 entities['182'] = '¶'; 542 entities['183'] = '·'; 543 entities['184'] = '¸'; 544 entities['185'] = '¹'; 545 entities['186'] = 'º'; 546 entities['187'] = '»'; 547 entities['188'] = '¼'; 548 entities['189'] = '½'; 549 entities['190'] = '¾'; 550 entities['191'] = '¿'; 551 entities['192'] = 'À'; 552 entities['193'] = 'Á'; 553 entities['194'] = 'Â'; 554 entities['195'] = 'Ã'; 555 entities['196'] = 'Ä'; 556 entities['197'] = 'Å'; 557 entities['198'] = 'Æ'; 558 entities['199'] = 'Ç'; 559 entities['200'] = 'È'; 560 entities['201'] = 'É'; 561 entities['202'] = 'Ê'; 562 entities['203'] = 'Ë'; 563 entities['204'] = 'Ì'; 564 entities['205'] = 'Í'; 565 entities['206'] = 'Î'; 566 entities['207'] = 'Ï'; 567 entities['208'] = 'Ð'; 568 entities['209'] = 'Ñ'; 569 entities['210'] = 'Ò'; 570 entities['211'] = 'Ó'; 571 entities['212'] = 'Ô'; 572 entities['213'] = 'Õ'; 573 entities['214'] = 'Ö'; 574 entities['215'] = '×'; 575 entities['216'] = 'Ø'; 576 entities['217'] = 'Ù'; 577 entities['218'] = 'Ú'; 578 entities['219'] = 'Û'; 579 entities['220'] = 'Ü'; 580 entities['221'] = 'Ý'; 581 entities['222'] = 'Þ'; 582 entities['223'] = 'ß'; 583 entities['224'] = 'à'; 584 entities['225'] = 'á'; 585 entities['226'] = 'â'; 586 entities['227'] = 'ã'; 587 entities['228'] = 'ä'; 588 entities['229'] = 'å'; 589 entities['230'] = 'æ'; 590 entities['231'] = 'ç'; 591 entities['232'] = 'è'; 592 entities['233'] = 'é'; 593 entities['234'] = 'ê'; 594 entities['235'] = 'ë'; 595 entities['236'] = 'ì'; 596 entities['237'] = 'í'; 597 entities['238'] = 'î'; 598 entities['239'] = 'ï'; 599 entities['240'] = 'ð'; 600 entities['241'] = 'ñ'; 601 entities['242'] = 'ò'; 602 entities['243'] = 'ó'; 603 entities['244'] = 'ô'; 604 entities['245'] = 'õ'; 605 entities['246'] = 'ö'; 606 entities['247'] = '÷'; 607 entities['248'] = 'ø'; 608 entities['249'] = 'ù'; 609 entities['250'] = 'ú'; 610 entities['251'] = 'û'; 611 entities['252'] = 'ü'; 612 entities['253'] = 'ý'; 613 entities['254'] = 'þ'; 614 entities['255'] = 'ÿ'; 615 } else { 616 throw Error("Table: "+useTable+' not supported'); 617 } 618 619 // ascii decimals to real symbols 620 for (decimal in entities) { 621 symbol = String.fromCharCode(decimal); 622 histogram[symbol] = entities[decimal]; 623 } 624 625 return histogram; 626 }; 627 628 629 630 631 /** 632 * 633 * UTF-8 data encode / decode 634 * http://www.webtoolkit.info/ 635 * @namespace 636 **/ 637 sc.helpers.Utf8 = { 638 639 /** @function public method for url encoding */ 640 encode : function (string) { 641 string = string.replace(/\r\n/g,"\n"); 642 var utftext = ""; 643 644 for (var n = 0; n < string.length; n++) { 645 646 var c = string.charCodeAt(n); 647 648 if (c < 128) { 649 utftext += String.fromCharCode(c); 650 } 651 else if((c > 127) && (c < 2048)) { 652 utftext += String.fromCharCode((c >> 6) | 192); 653 utftext += String.fromCharCode((c & 63) | 128); 654 } 655 else { 656 utftext += String.fromCharCode((c >> 12) | 224); 657 utftext += String.fromCharCode(((c >> 6) & 63) | 128); 658 utftext += String.fromCharCode((c & 63) | 128); 659 } 660 661 } 662 663 return utftext; 664 }, 665 666 /** @function public method for url decoding */ 667 decode : function (utftext) { 668 var string = ""; 669 var i = 0; 670 var c = 0, c1 = 0, c2 = 0, c3 = 0; 671 672 while ( i < utftext.length ) { 673 674 c = utftext.charCodeAt(i); 675 676 if (c < 128) { 677 string += String.fromCharCode(c); 678 i++; 679 } 680 else if((c > 191) && (c < 224)) { 681 c2 = utftext.charCodeAt(i+1); 682 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); 683 i += 2; 684 } 685 else { 686 c2 = utftext.charCodeAt(i+1); 687 c3 = utftext.charCodeAt(i+2); 688 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); 689 i += 3; 690 } 691 692 } 693 694 return string; 695 } 696 697 }; 698 699 700 701 702 703 /** 704 * 705 * Javascript trim, ltrim, rtrim 706 * http://www.webtoolkit.info/ 707 * 708 **/ 709 710 sc.helpers.trim = function (str, chars) { 711 return sc.helpers.ltrim(sc.helpers.rtrim(str, chars), chars); 712 }; 713 714 sc.helpers.ltrim = function (str, chars) { 715 chars = chars || "\\s"; 716 return str.replace(new RegExp("^[" + chars + "]+", "g"), ""); 717 }; 718 719 sc.helpers.rtrim = function (str, chars) { 720 chars = chars || "\\s"; 721 return str.replace(new RegExp("[" + chars + "]+$", "g"), ""); 722 }; 723 724 725 /** 726 * @param {string} input the input string 727 * @param {number} pad_length the length to pad the string 728 * @param {string} pad_string the string to pad with 729 * @param {string} pad_type STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH. Default is STR_PAD_RIGHT 730 * @member sc.helpers 731 */ 732 sc.helpers.pad = function (input, pad_length, pad_string, pad_type) { 733 // http://kevin.vanzonneveld.net 734 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 735 // + namespaced by: Michael White (http://getsprink.com) 736 // + input by: Marco van Oort 737 // + bugfixed by: Brett Zamir (http://brett-zamir.me) 738 // * example 1: str_pad('Kevin van Zonneveld', 30, '-=', 'STR_PAD_LEFT'); 739 // * returns 1: '-=-=-=-=-=-Kevin van Zonneveld' 740 // * example 2: str_pad('Kevin van Zonneveld', 30, '-', 'STR_PAD_BOTH'); 741 // * returns 2: '------Kevin van Zonneveld-----' 742 743 var half = '', pad_to_go; 744 745 var str_pad_repeater = function (s, len) { 746 var collect = '', i; 747 748 while (collect.length < len) {collect += s;} 749 collect = collect.substr(0,len); 750 751 return collect; 752 }; 753 754 input += ''; 755 pad_string = pad_string !== undefined ? pad_string : ' '; 756 757 if (pad_type != 'STR_PAD_LEFT' && pad_type != 'STR_PAD_RIGHT' && pad_type != 'STR_PAD_BOTH') { pad_type = 'STR_PAD_RIGHT'; } 758 if ((pad_to_go = pad_length - input.length) > 0) { 759 if (pad_type == 'STR_PAD_LEFT') { input = str_pad_repeater(pad_string, pad_to_go) + input; } 760 else if (pad_type == 'STR_PAD_RIGHT') { input = input + str_pad_repeater(pad_string, pad_to_go); } 761 else if (pad_type == 'STR_PAD_BOTH') { 762 half = str_pad_repeater(pad_string, Math.ceil(pad_to_go/2)); 763 input = half + input + half; 764 input = input.substr(0, pad_length); 765 } 766 } 767 768 return input; 769 }; 770 771 772 /** 773 * @param {string} str the string in which we're converting linebreaks 774 * @param {string} [breaktag] the tag used to break up lines. defaults to <br> 775 * @returns {string} the string with linebreaks converted to breaktags 776 * @member sc.helpers 777 */ 778 sc.helpers.nl2br = function(str, breaktag) { 779 780 breaktag = breaktag || '<br>'; 781 782 str = str.replace(/(\r\n|\n\r|\r|\n)/g, breaktag+'$1'); 783 return str; 784 };