1// $Id: tiki-jquery.js 42029 2012-06-22 16:39:32Z robertplummer $ 2// JavaScript glue for jQuery in Tiki 3// 4// Tiki 6 - $ is now initialised in jquery.js 5// but let's keep $jq available too for legacy custom code 6 7var $jq = $, 8$window = $(window) 9$document = $(document); 10 11// Escape a string for use as a jQuery selector value, for example an id or a class 12function escapeJquery(str) { 13 return str.replace(/([\!"#\$%&'\(\)\*\+,\.\/:;\?@\[\\\]\^`\{\|\}\~=>])/g, "\\$1"); 14} 15 16// Check / Uncheck all Checkboxes - overriden from tiki-js.js 17function switchCheckboxes (tform, elements_name, state) { 18 // checkboxes need to have the same name elements_name 19 // e.g. <input type="checkbox" name="my_ename[]">, will arrive as Array in php. 20 $(tform).contents().find('input[name="' + escapeJquery(elements_name) + '"]:visible').attr('checked', state).change(); 21} 22 23 24// override existing show/hide routines here 25 26// add id's of any elements that don't like being animated here 27var jqNoAnimElements = ['help_sections', 'ajaxLoading']; 28 29function show(foo, f, section) { 30 if ($.inArray(foo, jqNoAnimElements) > -1 || typeof jqueryTiki === 'undefined') { // exceptions that don't animate reliably 31 $("#" + foo).show(); 32 } else if ($("#" + foo).hasClass("tabcontent")) { // different anim prefs for tabs 33 showJQ("#" + foo, jqueryTiki.effect_tabs, jqueryTiki.effect_tabs_speed, jqueryTiki.effect_tabs_direction); 34 } else { 35 if ($.browser.webkit && !jqueryTiki.effect && $("#role_main #" + foo).length) { // safari/chrome does strange things with default amination in central column 36 showJQ("#" + foo, "slide", jqueryTiki.effect_speed, jqueryTiki.effect_direction); 37 } else { 38 showJQ("#" + foo, jqueryTiki.effect, jqueryTiki.effect_speed, jqueryTiki.effect_direction); 39 } 40 } 41 if (f) {setCookie(foo, "o", section);} 42} 43 44function hide(foo, f, section) { 45 if ($.inArray(foo, jqNoAnimElements) > -1 || typeof jqueryTiki === 'undefined') { // exceptions 46 $("#" + foo).hide(); 47 } else if ($("#" + foo).hasClass("tabcontent")) { 48 hideJQ("#" + foo, jqueryTiki.effect_tabs, jqueryTiki.effect_tabs_speed, jqueryTiki.effect_tabs_direction); 49 } else { 50 hideJQ("#" + foo, jqueryTiki.effect, jqueryTiki.effect_speed, jqueryTiki.effect_direction); 51 } 52 if (f) { 53// var wasnot = getCookie(foo, section, 'x') == 'x'; 54 setCookie(foo, "c", section); 55// if (wasnot) { 56// history.go(0); // used to reload the page with all menu items closed - broken since 3.x 57// } 58 } 59} 60 61// flip function... unfortunately didn't use show/hide (ay?) 62function flip(foo, style) { 63 if (style && style !== 'block' || foo === 'help_sections' || foo === 'fgalexplorer' || typeof jqueryTiki === 'undefined') { // TODO find a better way? 64 $("#" + foo).toggle(); // inlines don't animate reliably (yet) (also help) 65 if ($("#" + foo).css('display') === 'none') { 66 setSessionVar('show_' + escape(foo), 'n'); 67 } else { 68 setSessionVar('show_' + escape(foo), 'y'); 69 } 70 } else { 71 if ($("#" + foo).css("display") === "none") { 72 setSessionVar('show_' + escape(foo), 'y'); 73 show(foo); 74 } 75 else { 76 setSessionVar('show_' + escape(foo), 'n'); 77 hide(foo); 78 } 79 } 80} 81 82// handle JQ effects 83function showJQ(selector, effect, speed, dir) { 84 if (effect === 'none') { 85 $(selector).show(); 86 } else if (effect === '' || effect === 'normal') { 87 $(selector).show(400); // jquery 1.4 no longer seems to understand 'nnormal' as a speed 88 } else if (effect == 'slide') { 89 // With jquery 1.4.2 (and less) and IE7, the function slidedown is buggy 90 // See: http://dev.jquery.com/ticket/3120 91 if ($.browser.msie && parseInt($.browser.version, 10) == 7) { 92 $(selector).show(speed); 93 } else { 94 $(selector).slideDown(speed); 95 } 96 } else if (effect === 'fade') { 97 $(selector).fadeIn(speed); 98 } else if (effect.match(/(.*)_ui$/).length > 1) { 99 $(selector).show(effect.match(/(.*)_ui$/)[1], {direction: dir}, speed); 100 } else { 101 $(selector).show(); 102 } 103} 104 105function hideJQ(selector, effect, speed, dir) { 106 if (effect === 'none') { 107 $(selector).hide(); 108 } else if (effect === '' || effect === 'normal') { 109 $(selector).hide(400); // jquery 1.4 no longer seems to understand 'nnormal' as a speed 110 } else if (effect === 'slide') {
111 $(selector).slideUp(speed); 112 } else if (effect === 'fade') { 113 $(selector).fadeOut(speed); 114 } else if (effect.match(/(.*)_ui$/).length > 1) { 115 $(selector).hide(effect.match(/(.*)_ui$/)[1], {direction: dir}, speed); 116 } else { 117 $(selector).hide(); 118 } 119} 120 121// override overlib 122function convertOverlib(element, tip, params) { // process modified overlib event fn to cluetip from {popup} smarty func 123 124 if ($(element).data('processed') || typeof $(element).cluetip != "function") {return false;} 125 if (typeof params == "undefined") {params = [];} 126 127 var options = {}; 128 options.clickThrough = true; 129 for (var param = 0; param < params.length; param++) { 130 var val = "", pam; 131 var i = params[param].indexOf("="); 132 if (i > -1) { 133 var arr = params[param].split("=", 2); 134 pam = params[param].substring(0, i).toLowerCase(); 135 val = params[param].substring(i+1); 136 } else { 137 pam = params[param].toLowerCase(); 138 } 139 switch (pam) { 140 case "sticky": 141 options.sticky = true; 142 break; 143 case "fullhtml": 144 options.cluetipClass = 'fullhtml'; 145 break; 146 case "background": 147 options.cluetipClass = 'fullhtml'; 148 tip = '<div style="background-image: url(' + val + '); height:' + options.height + 'px">' + tip + '</div>'; 149 break; 150 case "onclick": 151 options.activation = 'click'; 152 options.clickThrough = false; 153 break; 154 case "width": 155 options.width = val; 156 break; 157 case "height": 158 options.height = val; 159 break; 160 default: 161 break; 162 } 163 } 164 165 options.splitTitle = '|'; 166 options.showTitle = false; 167 options.cluezIndex = 400; 168 options.dropShadow = true; 169 options.fx = {open: 'fadeIn', openSpeed: 'fast'}; 170 options.closeText = 'x'; 171 options.closePosition = 'title'; 172 options.mouseOutClose = true; 173 //options.positionBy = 'mouse'; // TODO - add a param for this one if desired 174 175 // attach new tip 176 177 if (element.tipWidth) { 178 options.width = element.tipWidth; 179 } else if (!options.width || options.width === 'auto') { 180 // hack to calculate div width 181 var $el = $("<div />") 182 .css('display', 'none') 183 .insertBefore("#main") 184 .html(tip); 185 186 if ($el.width() > $window.width()) { 187 $el.width($window.width() * 0.8); 188 } 189 options.width = $el.width() + 26; // add space for css padding 190 $el.remove(); 191 192 element.tipWidth = options.width; 193 } 194 195 var prefix = "|"; 196 $(element).attr('title', prefix + tip); 197 198 if (options.activation !== 'click') { 199 options.hoverIntent = {sensitivity: 3, interval: 50, timeout: 0}; 200 } 201 $(element).data('processed', true); 202 203//options.sticky = true; //useful for css work 204 $(element).cluetip(options); 205 206 if (options.activation === 'click') { 207 $(element).trigger('click'); 208 } else { 209 $(element).trigger('mouseover'); 210 } 211 setTimeout(function () {$("#cluetip").show();}, 200); // IE doesn't necessarily display 212 $(element).attr("title", ""); // remove temporary title attribute to avoid built in browser tips 213 return false; 214} 215 216function nd() { 217 $("#cluetip").hide(); 218} 219 220// ajax loading indicator 221 222function ajaxLoadingShow(destName) { 223 var $dest, $loading, pos, x, y, w, h; 224 225 if (typeof destName === 'string') { 226 $dest = $('#' + destName); 227 } else { 228 $dest = $(destName); 229 } 230 if ($dest.length === 0 || $dest.parents(":hidden").length > 0) { 231 return; 232 } 233 $loading = $('#ajaxLoading'); 234 235 // find area of destination element 236 pos = $dest.offset(); 237 // clip to page 238 if (pos.left + $dest.width() > $window.width()) { 239 w = $window.width() - pos.left; 240 } else { 241 w = $dest.width(); 242 } 243 if (pos.top + $dest.height() > $window.height()) { 244 h = $window.height() - pos.top; 245 } else { 246 h = $dest.height(); 247 } 248 x = pos.left + (w / 2) - ($loading.width() / 2); 249 y = pos.top + (h / 2) - ($loading.height() / 2); 250 251 252 // position loading div 253 $loading.css('left', x).css('top', y); 254 // now BG 255 x = pos.left + ccsValueToInteger($dest.css("margin-left")); 256 y = pos.top + ccsValueToInteger($dest.css("margin-top")); 257 w = ccsValueToInteger($dest.css("padding-left")) + $dest.width() + ccsValueToInteger($dest.css("padding-right")); 258 h = ccsValueToInteger($dest.css("padding-top")) + $dest.height() + ccsValueToInteger($dest.css("padding-bottom")); 259 $('#ajaxLoadingBG').css('left', pos.left).css('top', pos.top).width(w).height(h).fadeIn("fast"); 260 261 show('ajaxLoading'); 262 263 264} 265 266function ajaxLoadingHide() { 267 hide('ajaxLoading'); 268 $('#ajaxLoadingBG').fadeOut("fast"); 269} 270 271 272function checkDuplicateRows( button, columnSelector, rowSelector ) { 273 if (typeof columnSelector === 'undefined') { 274 columnSelector = "td"; 275 } 276 if (typeof rowSelector === 'undefined') { 277 rowSelector = "table:first tr:not(:first)"; 278 } 279 var $rows = $(button).parents(rowSelector); 280 $rows.each(function( ix, el ){ 281 if ($("input:checked", el).length === 0) { 282 var $el = $(el); 283 var line = $el.find(columnSelector).text(); 284 $rows.each(function( ix, el ){ 285 if ($el[0] !== el && $("input:checked", el).length === 0) { 286 if (line === $(el).find(columnSelector).text()) { 287 $(":checkbox:first", el).attr("checked", true); 288 } 289 } 290 }); 291 } 292 }); 293} 294 295function setUpClueTips() { 296 var ctOptions = {splitTitle: '|', cluezIndex: 2000, width: 'auto', fx: {open: 'fadeIn', openSpeed: 'fast'}, 297 clickThrough: true, hoverIntent: {sensitivity: 3, interval: 100, timeout: 0}}; 298 299 $.cluetip.setup = {insertionType: 'insertBefore', insertionElement: '#main'}; 300 301 $('.tips[title!=""]').cluetip($.extend(ctOptions, {})); 302 $('.titletips[title!=""]').cluetip($.extend(ctOptions, {}));
303 $('.tikihelp[title!=""]').cluetip($.extend(ctOptions, {splitTitle: ':'})); // , width: '150px' 304 305 // unused? 306 $('.stickytips').cluetip($.extend(ctOptions, {showTitle: false, sticky: false, local: true, hideLocal: true, activation: 'click', cluetipClass: 'fullhtml'})); 307 308 // repeats for "tiki" buttons as you cannot set the class and title on the same element with that function (it seems?) 309 //$('span.button.tips a').cluetip({splitTitle: '|', showTitle: false, width: '150px', cluezIndex: 400, fx: {open: 'fadeIn', openSpeed: 'fast'}, clickThrough: true}); 310 //$('span.button.titletips a').cluetip({splitTitle: '|', cluezIndex: 400, fx: {open: 'fadeIn', openSpeed: 'fast'}, clickThrough: true}); 311 // TODO after 5.0 - these need changes in the {button} Smarty fn 312} 313 314$(function() { // JQuery's DOM is ready event - before onload 315 if (!window.jqueryTiki) window.jqueryTiki = {}; 316 317 // tooltip functions and setup 318 if (jqueryTiki.tooltips) { // apply "cluetips" to all .tips class anchors 319 320 setUpClueTips(); 321 322 } // end cluetip setup 323 324 // Reflections 325 if (jqueryTiki.replection) { 326 $("img.reflect").reflect({}); 327 } 328 329 // superfish setup (CSS menu effects) 330 if (jqueryTiki.superfish) { 331 $('ul.cssmenu_horiz').supersubs({ 332 minWidth: 11, // minimum width of sub-menus in em units 333 maxWidth: 20, // maximum width of sub-menus in em units 334 extraWidth: 1 // extra width can ensure lines don't sometimes turn over 335 // due to slight rounding differences and font-family 336 }); 337 $('ul.cssmenu_vert').supersubs({ 338 minWidth: 11, // minimum width of sub-menus in em units 339 maxWidth: 20, // maximum width of sub-menus in em units 340 extraWidth: 1 // extra width can ensure lines don't sometimes turn over 341 // due to slight rounding differences and font-family 342 }); 343 $('ul.cssmenu_horiz').superfish({ 344 animation: {opacity:'show', height:'show'}, // fade-in and slide-down animation 345 speed: 'fast', // faster animation speed 346 onShow: function(){ 347 $(this).moveToWithinWindow(); 348 } 349 }); 350 $('ul.cssmenu_vert').superfish({ 351 animation: {opacity:'show', height:'show'}, // fade-in and slide-down animation 352 speed: 'fast', // faster animation speed 353 onShow: function(){ 354 $(this).moveToWithinWindow(); 355 } 356 }); 357 } 358 359 // tablesorter setup (sortable tables?) 360 if (jqueryTiki.tablesorter) { 361 $('.sortable').tablesorter({ 362 widthFixed: true // ?? 363// widgets: ['zebra'], // stripes (coming soon) 364 }); 365 } 366 367 // ColorBox setup (Shadowbox, actually "<any>box" replacement) 368 if (jqueryTiki.colorbox) { 369 $().bind('cbox_complete', function(){ 370 $("#cboxTitle").wrapInner("<div></div>"); 371 }); 372 373 // Tiki defaults for ColorBox 374 375 // for every link containing 'shadowbox' or 'colorbox' in rel attribute 376 $("a[rel*='box']").colorbox({ 377 transition: "elastic", 378 maxHeight:"95%", 379 maxWidth:"95%", 380 overlayClose: true, 381 title: true, 382 current: jqueryTiki.cboxCurrent 383 }); 384 385 // now, first let suppose that we want to display images in ColorBox by default: 386 387 // this matches rel containg type=img or no type= specified 388 $("a[rel*='box'][rel*='type=img'], a[rel*='box'][rel!='type=']").colorbox({ 389 photo: true 390 }); 391 // rel containg slideshow (this one must be without #col1) 392 $("a[rel*='box'][rel*='slideshow']").colorbox({ 393 photo: true, 394 slideshow: true, 395 slideshowSpeed: 3500, 396 preloading: false, 397 width: "100%", 398 height: "100%" 399 }); 400 // this are the defaults matching all *box links which are not obviously links to images... 401 // (if we need to support more, add here... otherwise it is possible to override with type=iframe in rel attribute of a link) 402 // (from here one to speed it up, matches any link in #col1 only - the main content column) 403 404 $("#col1 a[rel*='box']:not([rel*='type=img']):not([href*='display']):not([href*='preview']):not([href*='thumb']):not([rel*='slideshow']):not([href*='image']):not([href$='\.jpg']):not([href$='\.jpeg']):not([href$='\.png']):not([href$='\.gif'])").colorbox({ 405 iframe: true, 406 width: "95%", 407 height: "95%" 408 }); 409 // hrefs starting with ftp(s) 410 $("#col1 a[rel*='box'][href^='ftp://'], #col1 a[rel*='box'][href^='ftps://']").colorbox({ 411 iframe: true, 412 width: "95%", 413 height: "95%" 414 }); 415 // rel containg type=flash 416 $("#col1 a[rel*='box'][rel*='type=flash']").colorbox({ 417 flash: true, 418 iframe: false 419 }); 420 // rel with type=iframe (if someone needs to override anything above) 421 $("#col1 a[rel*='box'][rel*='type=iframe']").colorbox({ 422 iframe: true 423 }); 424 // inline content: hrefs starting with # 425 $("#col1 a[rel*='box'][href^='#']").colorbox({ 426 inline: true, 427 width: "50%", 428 height: "50%", 429 href: function(){ 430 return $(this).attr('href'); 431 } 432 }); 433 434 // titles (for captions): 435 436 // by default get title from the title attribute of the link (in all columns) 437 $("a[rel*='box'][title]").colorbox({ 438 title: function(){ 439 return $(this).attr('title'); 440 } 441 }); 442 // but prefer the title from title attribute of a wrapped image if any (in all columns) 443 $("a[rel*='box'] img[title]").colorbox({ 444 title: function(){ 445 return $(this).attr('title'); 446 }, 447 photo: true, // and if you take title from the image you need photo 448 href: function(){ // and href as well (for colobox 1.3.6 tiki 5.0) 449 return $(this).parent().attr("href"); 450 } 451 }); 452 453 /* Shadowbox params compatibility extracted using regexp functions */ 454 var re, ret; 455 // rel containg title param overrides title attribute of the link (shadowbox compatible) 456 $("#col1 a[rel*='box'][rel*='title=']").colorbox({ 457 title: function () { 458 re = /(title=([^;\"]+))/i; 459 ret = $(this).attr("rel").match(re); 460 return ret[2]; 461 } 462 }); 463 // rel containg height param (shadowbox compatible) 464 $("#col1 a[rel*='box'][rel*='height=']").colorbox({ 465 height: function () { 466 re = /(height=([^;\"]+))/i; 467 ret = $(this).attr("rel").match(re); 468 return ret[2]; 469 } 470 }); 471 // rel containg width param (shadowbox compatible) 472 $("#col1 a[rel*='box'][rel*='width=']").colorbox({ 473 width: function () { 474 re = /(width=([^;\"]+))/i; 475 ret = $(this).attr("rel").match(re); 476 return ret[2]; 477 } 478 }); 479 480 // links generated by the {COLORBOX} plugin 481 if (jqueryTiki.colorbox) { 482 $("a[rel^='shadowbox[colorbox']").each(function () {$(this).attr('savedTitle', $(this).attr('title'));}); 483 if (jqueryTiki.tooltips) { 484 $("a[rel^='shadowbox[colorbox']").cluetip({ 485 splitTitle: '<br />', 486 cluezIndex: 400, 487 width: 'auto', 488 fx: {open: 'fadeIn', openSpeed: 'fast'}, 489 clickThrough: true 490 }); 491 } 492 $("a[rel^='shadowbox[colorbox']").colorbox({ 493 title: function() { 494 return $(this).attr('savedTitle'); // this fix not required is colorbox was disabled 495 } 496 }); 497 } 498 499 } // end if (jqueryTiki.colorbox) 500
501 // make all selects into ui selectmenus depending on $prefs['jquery_ui_selectmenu_all'] 502 if (jqueryTiki.selectmenu) { 503 var $smenus, hidden = []; 504 if (jqueryTiki.selectmenuAll) { 505 $smenus = $("select") 506 } else { 507 $smenus = $("select.selectmenu"); 508 } 509 if ($smenus.length) { 510 $smenus.each ( function () { 511 $.merge( hidden, $(this).parents("fieldset:hidden:last, div:hidden:last")); 512 }); 513 hidden = $.unique($(hidden)); 514 hidden.show(); 515 $smenus.tiki("selectmenu"); 516 hidden.hide(); 517 } 518 } 519 520 $( function() { 521 $("#keepOpenCbx").click(function() { 522 if (this.checked) { 523 setCookie("fgalKeepOpen", "1"); 524 } else { 525 setCookie("fgalKeepOpen", ""); 526 } 527 }) 528 var keepopen = getCookie("fgalKeepOpen"); 529 if (keepopen) { 530 $("#keepOpenCbx").attr("checked", "checked"); 531 } else { 532 $("#keepOpenCbx").removeAttr("checked"); 533 } 534 }); 535 // end fgal fns 536 537 538 $.paginationHelper(); 539}); // end $document.ready 540 541//For ajax/custom search 542$document.bind('pageSearchReady', function() { 543 $.paginationHelper(); 544}); 545 546// moved from tiki-list_file_gallery.tpl in tiki 6 547function checkClose() { 548 if (!$("#keepOpenCbx").attr("checked")) { 549 window.close(); 550 } else { 551 window.blur(); 552 if (window.opener) { 553 window.opener.focus(); 554 } 555 } 556}; 557 558 559/* Autocomplete assistants */ 560 561function parseAutoJSON(data) { 562 var parsed = []; 563 return $.map(data, function(row) { 564 return { 565 data: row, 566 value: row, 567 result: row 568 }; 569 }); 570} 571 572/// jquery ui dialog replacements for popup form code 573/// need to keep the old non-jq version in tiki-js.js as jq-ui is optional (Tiki 4.0) 574/// TODO refactor for 4.n 575 576/* wikiplugin editor */ 577function popupPluginForm(area_id, type, index, pageName, pluginArgs, bodyContent, edit_icon, selectedMod){ 578 if (!$.ui) { 579 alert("dev notice: no jq.ui here?"); 580 return popup_plugin_form(area_id, type, index, pageName, pluginArgs, bodyContent, edit_icon); // ?? 581 } 582 if ($("#" + area_id).length && $("#" + area_id)[0].createTextRange) { // save selection for IE 583 storeTASelection(area_id); 584 } 585
586 var container = $('<div class="plugin"></div>'); 587 588 if (!index) { 589 index = 0; 590 } 591 if (!pageName) { 592 pageName = ''; 593 } 594 var textarea = $('#' + area_id)[0]; 595 var replaceText = false; 596 597 if (!pluginArgs && !bodyContent) { 598 pluginArgs = {}; 599 bodyContent = ""; 600 601 dialogSelectElement( area_id, '{' + type.toUpperCase(), '{' + type.toUpperCase() + '}' ) ; 602 var sel = getTASelection( textarea ); 603 if (sel && sel.length > 0) { 604 sel = sel.replace(/^\s\s*/, "").replace(/\s\s*$/g, ""); // trim 605 //alert(sel.length); 606 if (sel.length > 0 && sel.substring(0, 1) === '{') { // whole plugin selected 607 var l = type.length; 608 if (sel.substring(1, l + 1).toUpperCase() === type.toUpperCase()) { // same plugin 609 var rx = new RegExp("{" + type + "[\\(]?([\\s\\S^\\)]*?)[\\)]?}([\\s\\S]*){" + type + "}", "mi"); // using \s\S matches all chars including lineends 610 var m = sel.match(rx); 611 if (!m) { 612 rx = new RegExp("{" + type + "[\\(]?([\\s\\S^\\)]*?)[\\)]?}([\\s\\S]*)", "mi"); // no closing tag 613 m = sel.match(rx); 614 } 615 if (m) { 616 var paramStr = m[1]; 617 bodyContent = m[2]; 618 619 var pm = paramStr.match(/([^=]*)=\"([^\"]*)\"\s?/gi); 620 if (pm) { 621 for (var i = 0; i < pm.length; i++) { 622 var ar = pm[i].split("="); 623 if (ar.length) { // add cleaned vals to params object 624 pluginArgs[ar[0].replace(/^[,\s\"\(\)]*/g, "")] = ar[1].replace(/^[,\s\"\(\)]*/g, "").replace(/[,\s\"\(\)]*$/g, ""); 625 } 626 } 627 } 628 } 629 replaceText = sel; 630 } else { 631 if (!confirm("You appear to have selected text for a different plugin, do you wish to continue?")) { 632 return false; 633 } 634 bodyContent = sel; 635 replaceText = true; 636 } 637 } else { // not (this) plugin 638 if (type == 'mouseover') { // For MOUSEOVER, we want the selected text as label instead of body 639 bodyContent = ''; 640 pluginArgs = {}; 641 pluginArgs['label'] = sel; 642 } else { 643 bodyContent = sel; 644 } 645 replaceText = true; 646 } 647 } else { // no selection 648 replaceText = false; 649 } 650 } 651 var form = build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod); 652 653 //with PluginModule, if the user selects another module while the edit form is open 654 //replace the form with a new one with fields to match the parameters for the module selected 655 $(form).find('tr select[name="params[module]"]').change(function() { 656 var npluginArgs = $.parseJSON($(form).find('input[name="args"][type="hidden"]').val()); 657 //this is the newly selected module 658 var selectedMod = $(form).find('tr select[name="params[module]"]').val(); 659 $('div.plugin input[name="type"][value="' + type + '"]').parent().parent().remove(); 660 popupPluginForm(area_id, type, index, pageName, npluginArgs, bodyContent, edit_icon, selectedMod); 661 }); 662 var $form = $(form).find('tr input[type=submit]').remove(); 663 664 container.append(form); 665 document.body.appendChild(container[0]); 666 667 handlePluginFieldsHierarchy(type); 668 669 var pfc = container.find('table tr').length; // number of rows (plugin form contents) 670 var t = container.find('textarea:visible').length; 671 if (t) {pfc += t * 3;} 672 if (pfc > 9) {pfc = 9;} 673 if (pfc < 2) {pfc = 2;} 674 pfc = pfc / 10; // factor to scale dialog height 675 676 var btns = {}; 677 var closeText = tr("Close"); 678 btns[closeText] = function() { 679 $(this).dialog("close"); 680 }; 681 682 btns[replaceText ? tr("Replace") : edit_icon ? tr("Submit") : tr("Insert")] = function() { 683 var meta = tiki_plugins[type]; 684 var params = []; 685 var edit = edit_icon; 686 // whether empty required params exist or not 687 var emptyRequiredParam = false; 688 689 for (var i = 0; i < form.elements.length; i++) { 690 var element = form.elements[i].name; 691 692 var matches = element.match(/params\[(.*)\]/); 693 694 if (matches === null) { 695 // it's not a parameter, skip 696 continue; 697 } 698 var param = matches[1]; 699 700 var val = form.elements[i].value; 701 702 // check if fields that are required and visible are not empty 703 if (meta.params[param]) { 704 if (meta.params[param].required) { 705 if (val === '' && $(form.elements[i]).is(':visible')) { 706 $(form.elements[i]).css('border-color', 'red'); 707 if ($(form.elements[i]).next('.required_param').length === 0) { 708 $(form.elements[i]).after('<div class="required_param" style="font-size: x-small; color: red;">(required)</div>'); 709 } 710 emptyRequiredParam = true; 711 } 712 else { 713 // remove required feedback if present 714 $(form.elements[i]).css('border-color', ''); 715 $(form.elements[i]).next('.required_param').remove(); 716 } 717 } 718 } 719 720 if (val !== '') { 721 params.push(param + '="' + val + '"'); 722 } 723 } 724 725 if (emptyRequiredParam) { 726 return false;
727 } 728 729 var blob, pluginContentTextarea = $("[name=content]", form), pluginContentTextareaEditor = syntaxHighlighter.get(pluginContentTextarea); 730 var cont = (pluginContentTextareaEditor ? pluginContentTextareaEditor.getValue() : pluginContentTextarea.val()); 731 732 if (cont.length > 0) { 733 blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' + cont + '{' + type.toUpperCase() + '}'; 734 } else { 735 blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}'; 736 } 737 738 if (edit) { 739 container.children('form').submit(); 740 } else { 741 insertAt(area_id, blob, false, false, replaceText); 742 } 743 $(this).dialog("close"); 744 $('div.plugin input[name="type"][value="' + type + '"]').parent().parent().remove(); 745 746 return false; 747 }; 748 749 var heading = container.find('h3').hide(); 750 751 try { 752 if (container.dialog) { 753 container.dialog('destroy'); 754 } 755 } catch( e ) { 756 // IE throws errors destroying a non-existant dialog 757 } 758 container.dialog({ 759 width: $window.width() * 0.6, 760 height: $window.height() * pfc, 761 zIndex: 10000, 762 title: heading.text(), 763 autoOpen: false, 764 close: function() { 765 $('div.plugin input[name="type"][value="' + type + '"]').parent().parent().remove(); 766 767 var ta = $('#' + area_id); 768 if (ta) {ta.focus();} 769 } 770 }).dialog('option', 'buttons', btns).dialog("open"); 771 772 773 //This allows users to create plugin snippets for any plugin using the jQuery event 'plugin_#type#_ready' for document 774 $document 775 .trigger({ 776 type: 'plugin_' + type + '_ready', 777 container: container, 778 arguments: arguments, 779 btns: btns 780 }) 781 .trigger({ 782 type: 'plugin_ready', 783 container: container, 784 arguments: arguments, 785 btns: btns, 786 type: type 787 }); 788} 789 790/* 791 * Hides all children fields in a wiki-plugin form and 792 * add javascript events to display them when the appropriate 793 * values are selected in the parent fields. 794 */ 795function handlePluginFieldsHierarchy(type) { 796 var pluginParams = tiki_plugins[type]['params']; 797 798 var parents = {}; 799 800 $.each(pluginParams, function(paramName, paramValues) { 801 if (paramValues.parent) { 802 var $parent = $('[name$="params[' + paramValues.parent.name + ']"]', '.wikiplugin_edit'); 803 804 $('.wikiplugin_edit').find('#param_' + paramName).addClass('parent_' + paramValues.parent.name + '_' + paramValues.parent.value); 805 806 if ($parent.val() != paramValues.parent.value) { 807 $('.wikiplugin_edit').find('#param_' + paramName).hide(); 808 } 809 810 if (!parents[paramValues.parent.name]) { 811 parents[paramValues.parent.name] = {}; 812 parents[paramValues.parent.name]['children'] = []; 813 parents[paramValues.parent.name]['parentElement'] = $parent; 814 } 815 816 parents[paramValues.parent.name]['children'].push(paramName); 817 } 818 }); 819 820 $.each(parents, function(parentName, parent) { 821 parent.parentElement.change(function() { 822 $.each(parent.children, function() { 823 $('.wikiplugin_edit #param_' + this).hide(); 824 }); 825 $('.wikiplugin_edit .parent_' + parentName + '_' + this.value).show(); 826 }); 827 }); 828} 829 830/* 831 * JS only textarea fullscreen function (for Tiki 5+) 832 */ 833 834$(function() { // if in translation-diff-mode go fullscreen automatically 835 if ($("#diff_outer").length && !$.trim($(".wikipreview .wikitext").html()).length) { // but not if previewing (TODO better) 836 toggleFullScreen("editwiki"); 837 } 838}); 839 840function toggleFullScreen(area_id) { 841 var textarea = $("#" + area_id); 842 843 //codemirror interation and preservation 844 var textareaEditor = syntaxHighlighter.get(textarea); 845 if (textareaEditor) { 846 syntaxHighlighter.fullscreen(textarea); 847 return; 848 } 849 850 $('.TextArea-fullscreen').add(textarea).css('height', ''); 851 852 //removes wiki command buttons (save, cancel, preview) from fullscreen view 853 $('.TextArea-fullscreen .wikiaction').remove(); 854 855 var textareaParent = textarea.parent().parent().toggleClass('TextArea-fullscreen'); 856 $('body').toggleClass('noScroll'); 857 $('.tabs,.rbox-title').toggle(); 858 859 if (textareaParent.hasClass('TextArea-fullscreen')) { 860 var win = $window 861 .data('cm-resize', true), 862 screen = $('.TextArea-fullscreen'), 863 toolbar = $('#editwiki_toolbar'); 864 865 win.resize(function() { 866 if (win.data('cm-resize') && screen) { 867 screen.css('height', win.height() + 'px'); 868 869 textarea 870 .css('height', ((win.height() - toolbar.height()) - 30) + 'px'); 871 } 872 }) 873 .resize(); 874
875 //adds wiki command buttons (save, cancel, preview) from fullscreen view 876 $('#role_main input.wikiaction').clone().appendTo('.TextArea-fullscreen'); 877 } else { 878 $window.removeData('cm-resize'); 879 } 880} 881 882/* Simple tiki plugin for jQuery 883 * Helpers for autocomplete and sheet 884 */ 885var xhrCache = {}, lastXhr; // for jq-ui autocomplete 886 887$.fn.tiki = function(func, type, options) { 888 var opts = {}, opt; 889 switch (func) { 890 case "autocomplete": 891 if (jqueryTiki.autocomplete) { 892 if (typeof type === 'undefined') { // func and type given 893 // setup error - alert here? 894 return null; 895 } 896 options = options || {}; 897 var requestData = {}; 898 899 var url = ""; 900 switch (type) { 901 case "pagename": 902 url = "tiki-listpages.php?listonly"; 903 break; 904 case "groupname": 905 url = "tiki-ajax_services.php?listonly=groups"; 906 break; 907 case "username": 908 url = "tiki-ajax_services.php?listonly=users"; 909 break; 910 case "usersandcontacts": 911 url = "tiki-ajax_services.php?listonly=usersandcontacts"; 912 break; 913 case "userrealname": 914 url = "tiki-ajax_services.php?listonly=userrealnames"; 915 break; 916 case "tag": 917 url = "tiki-ajax_services.php?listonly=tags&separator=+"; 918 break; 919 case "icon": 920 url = "tiki-ajax_services.php?listonly=icons&max=" + (opts.max ? opts.max: 10); 921 opts.formatItem = function(data, i, n, value) { 922 var ps = value.lastIndexOf("/"); 923 var pd = value.lastIndexOf("."); 924 return "<img src='" + value + "' /> " + value.substring(ps + 1, pd).replace(/_/m, " "); 925 }; 926 opts.formatResult = function(data, value) { 927 return value; 928 }; 929 break; 930 case 'trackername': 931 url = "tiki-ajax_services.php?listonly=trackername"; 932 break; 933 case 'trackervalue': 934 if (typeof options.fieldId === "undefined") { 935 // error 936 return null; 937 } 938 $.extend( requestData, options ); 939 options = {}; 940 url = "list-tracker_field_values_ajax.php"; 941 break; 942 } 943 $.extend( opts, { // default options for autocompletes in tiki 944 minLength: 2, 945 source: function( request, response ) { 946 if (options.tiki_replace_term) { 947 request.term = options.tiki_replace_term.apply(null, [request.term]); 948 } 949 var cacheKey = "ac." + type + "." + request.term; 950 if ( cacheKey in xhrCache ) { 951 response( xhrCache[ cacheKey ] ); 952 return; 953 } 954 request.q = request.term; 955 $.extend( request, requestData ); 956 lastXhr = $.getJSON( url, request, function( data, status, xhr ) { 957 xhrCache[ cacheKey ] = data; 958 if ( xhr === lastXhr ) { 959 response( data ); 960 } 961 }); 962 } 963 }); 964 $.extend(opts, options); 965 966 return this.each(function() { 967 $(this).autocomplete(opts); 968// .click( function () { 969// $(".ac_results").hide(); // hide the drop down if input clicked on again 970// }); 971 }); 972 } 973 break; 974 case "carousel": 975 if (jqueryTiki.carousel) { 976 opts = { 977 imagePath: "lib/jquery/infinitecarousel/images/", 978 autoPilot: true 979 }; 980 $.extend(opts, options); 981 return this.each(function() { 982 $(this).infiniteCarousel(opts); 983 }); 984 } 985 break; 986 case "datepicker": 987 case "datetimepicker": 988 if (jqueryTiki.ui) { 989 switch (type) { 990 case "jscalendar": // replacements for jscalendar 991 // timestamp result goes in the options.altField 992 if (typeof options.altField === "undefined") { 993 alert("jQuery.ui datepicker jscalendar replacement setup error: options.altField not set for " + $(this).attr("id")); 994 debugger; 995 } 996 opts = { 997 showOn: "both", 998 buttonImage: "img/icons/calendar.png", 999 buttonImageOnly: true, 1000 dateFormat: "yy-mm-dd", 1001 showButtonPanel: true, 1002 altFormat: "@", 1003 onClose: function(dateText, inst) { 1004 $.datepicker._updateAlternate(inst); // make sure the hidden field is up to date 1005 var timestamp = parseInt($(inst.settings.altField).val() / 1000, 10); 1006 if (!timestamp) { 1007 $.datepicker._setDateFromField(inst); // seems to need reminding when starting empty 1008 $.datepicker._updateAlternate(inst); 1009 timestamp = parseInt($(inst.settings.altField).val() / 1000, 10); 1010 } 1011 if (timestamp && inst.settings && inst.settings.timepicker) { // if it's a datetimepicker add on the time 1012 var time = inst.settings.timepicker.hour * 3600 + 1013 inst.settings.timepicker.minute * 60 + 1014 inst.settings.timepicker.second; 1015 timestamp += time; 1016 } 1017 $(inst.settings.altField).val(timestamp ? timestamp : ""); 1018 } 1019 }; 1020 break; 1021 default: 1022 opts = { 1023 showOn: "both", 1024 buttonImage: "img/icons/calendar.png", 1025 buttonImageOnly: true, 1026 dateFormat: "yy-mm-dd", 1027 showButtonPanel: true 1028 }; 1029 break; 1030 } 1031 $.extend(opts, options); 1032 if (func === "datetimepicker") { 1033 return this.each(function() { 1034 $(this).datetimepicker(opts); 1035 }); 1036 } else { 1037 return this.each(function() { 1038 $(this).datepicker(opts); 1039 }); 1040 } 1041 } 1042 break; 1043 case "accordion": 1044 if (jqueryTiki.ui) { 1045 opts = { 1046 autoHeight: false, 1047 collapsible: true, 1048 navigation: true 1049// change: function(event, ui) { 1050// // sadly accordion active property is broken in 1.7, but fix is coming in 1.8 so TODO
1051// setCookie(ui, ui.options.active, "accordion"); 1052// } 1053 }; 1054 $.extend(opts, options); 1055 return this.each(function() { 1056 $(this).accordion(opts); 1057 }); 1058 } 1059 break; 1060 case "selectmenu": 1061 if (jqueryTiki.selectmenu) { 1062 opts = { 1063 style: 'dropdown', 1064 wrapperElement: "<span />" 1065 }; 1066 $.extend(opts, options); 1067 return this.each(function() { 1068 $(this).selectmenu(opts); 1069 }); 1070 } 1071 break; 1072 } // end switch(func) 1073}; 1074 1075/****************************** 1076 * Functions for dialog tools * 1077 ******************************/ 1078 1079// shared 1080 1081window.dialogData = []; 1082var dialogDiv; 1083 1084function displayDialog( ignored, list, area_id ) { 1085 var i, item, el, obj, tit = ""; 1086 1087 var $is_cked = $('#cke_contents_' + area_id).length !== 0; 1088 1089 if (!dialogDiv) { 1090 dialogDiv = document.createElement('div'); 1091 document.body.appendChild( dialogDiv ); 1092 } 1093 $(dialogDiv).empty(); 1094 1095 for( i = 0; i < window.dialogData[list].length; i++ ) { 1096 item = window.dialogData[list][i]; 1097 if (item.indexOf("<") === 0) { // form element 1098 el = $(item); 1099 $(dialogDiv).append( el ); 1100 } else if (item.indexOf("{") === 0) { 1101 try { 1102 //obj = JSON.parse(item); // safer, but need json2.js lib 1103 obj = eval("("+item+")"); 1104 } catch (e) { 1105 alert(e.name + ' - ' + e.message); 1106 } 1107 } else if (item.length > 0) { 1108 tit = item; 1109 } 1110 } 1111 1112 // Selection will be unavailable after context menu shows up - in IE, lock it now. 1113 if ( typeof CKEDITOR !== "undefined" && CKEDITOR.env.ie ) { 1114 var editor = CKEDITOR.instances[area_id]; 1115 var selection = editor.getSelection(); 1116 if (selection) {selection.lock();} 1117 } else if ($("#" + area_id)[0].createTextRange) { // save selection for IE 1118 storeTASelection(area_id); 1119 } 1120 1121 if (!obj) { obj = {}; } 1122 if (!obj.width) {obj.width = 210;} 1123 obj.bgiframe = true; 1124 obj.autoOpen = false; 1125 obj.zIndex = 10000; 1126 try { 1127 if ($(dialogDiv).dialog) { 1128 $(dialogDiv).dialog('destroy'); 1129 } 1130 } catch( e ) { 1131 // IE throws errors destroying a non-existant dialog 1132 } 1133 $(dialogDiv).dialog(obj).dialog('option', 'title', tit).dialog('open'); 1134 1135 return false; 1136} 1137 1138window.pickerData = []; 1139var pickerDiv = {}; 1140 1141function displayPicker( closeTo, list, area_id, isSheet, styleType ) { 1142 $('div.toolbars-picker').remove(); // simple toggle 1143 var $closeTo = $(closeTo); 1144 1145 if ($closeTo.hasClass('toolbars-picker-open')) { 1146 $('.toolbars-picker-open').removeClass('toolbars-picker-open'); 1147 return false; 1148 } 1149 1150 $closeTo.addClass('toolbars-picker-open'); 1151 var textarea = $('#' + area_id); 1152 1153 var coord = $closeTo.offset(); 1154 coord.bottom = coord.top + $closeTo.height(); 1155 1156 pickerDiv = $('<div class="toolbars-picker ' + list + '" />') 1157 .css('left', coord.left + 'px') 1158 .css('top', (coord.bottom + 8) + 'px') 1159 .appendTo('body'); 1160 1161 var prepareLink = function(ins, disp ) { 1162 disp = $(disp); 1163 1164 var link = $( '<a href="#" />' ).append(disp); 1165 1166 if (disp.attr('reset') && isSheet) { 1167 var bgColor = $('div.tiki_sheet:first').css(styleType); 1168 var color = $('div.tiki_sheet:first').css(styleType == 'color' ? 'background-color' : 'color'); 1169 disp 1170 .css('background-color', bgColor) 1171 .css('color', color); 1172 1173 link 1174 .addClass('toolbars-picker-reset'); 1175 } 1176 1177 if ( isSheet ) { 1178 link 1179 .click(function() { 1180 var I = $(closeTo).attr('instance'); 1181 I = parseInt( I ? I : 0, 10 ); 1182 1183 if (disp.attr('reset')) { 1184 $.sheet.instance[I].cellChangeStyle(styleType, ''); 1185 } else { 1186 $.sheet.instance[I].cellChangeStyle(styleType, disp.css('background-color')); 1187 } 1188 1189 $closeTo.click(); 1190 return false; 1191 }); 1192 } else { 1193 link.click(function() { 1194 insertAt(area_id, ins); 1195 1196 var textarea = $('#' + area_id); 1197 // quick fix for Firefox 3.5 losing selection on changes to popup 1198 if (typeof textarea.selectionStart != 'undefined') { 1199 var tempSelectionStart = textarea.selectionStart; 1200 var tempSelectionEnd = textarea.selectionEnd; 1201 } 1202 1203 $closeTo.click(); 1204 1205 // quick fix for Firefox 3.5 losing selection on changes to popup 1206 if (typeof textarea.selectionStart != 'undefined' && textarea.selectionStart != tempSelectionStart) { 1207 textarea.selectionStart = tempSelectionStart; 1208 } 1209 if (typeof textarea.selectionEnd != 'undefined' && textarea.selectionEnd != tempSelectionEnd) { 1210 textarea.selectionEnd = tempSelectionEnd; 1211 } 1212 1213 return false;
1214 }); 1215 } 1216 return link; 1217 }; 1218 var chr, $a; 1219 for( var i in window.pickerData[list] ) { 1220 chr = window.pickerData[list][i]; 1221 if (list === "specialchar") { 1222 chr = $("<span>" + chr + "</span>"); 1223 } 1224 $a = prepareLink( i, chr ); 1225 if ($a.length) { 1226 pickerDiv.append($a); 1227 } 1228 } 1229 1230 return false; 1231} 1232 1233 1234function dialogSelectElement( area_id, elementStart, elementEnd ) { 1235 if ($('#cke_contents_' + area_id).length !== 0) {return;} // TODO for ckeditor 1236 1237 var $textarea = $('#' + area_id); 1238 var textareaEditor = syntaxHighlighter.get($textarea); 1239 var val = ( textareaEditor ? textareaEditor.getValue() : $textarea.val() ); 1240 var pairs = [], pos = 0, s = 0, e = 0; 1241 1242 while (s > -1 && e > -1) { // positions of start/end markers 1243 s = val.indexOf(elementStart, e); 1244 if (s > -1) { 1245 e = val.indexOf(elementEnd, s + elementStart.length); 1246 if (e > -1) { 1247 e += elementEnd.length; 1248 pairs[pairs.length] = [ s, e ]; 1249 } 1250 } 1251 } 1252 1253 (textareaEditor ? textareaEditor : $textarea[0]).focus(); 1254 1255 var selection = ( textareaEditor ? syntaxHighlighter.selection(textareaEditor, true) : $textarea.selection() ); 1256 1257 s = selection.start; 1258 e = selection.end; 1259 var st = $textarea.attr('scrollTop'); 1260 1261 for (var i = 0; i < pairs.length; i++) { 1262 if (s >= pairs[i][0] && e <= pairs[i][1]) { 1263 setSelectionRange($textarea[0], pairs[i][0], pairs[i][1]); 1264 break; 1265 } 1266 } 1267 1268} 1269 1270 1271function dialogSharedClose( area_id, dialog ) { 1272 $(dialog).dialog("close"); 1273} 1274 1275// Internal Link 1276 1277function dialogInternalLinkOpen( area_id ) { 1278 $("#tbWLinkPage").tiki("autocomplete", "pagename"); 1279 dialogSelectElement( area_id, '((', '))' ) ; 1280 var s = getTASelection($('#' + area_id)[0]); 1281 var m = /\((.*)\(([^\|]*)\|?([^\|]*)\|?([^\|]*)\|?\)\)/g.exec(s); 1282 if (m && m.length > 4) { 1283 if ($("#tbWLinkRel")) { 1284 $("#tbWLinkRel").val(m[1]); 1285 } 1286 $("#tbWLinkPage").val(m[2]); 1287 if (m[4]) { 1288 if ($("#tbWLinkAnchor")) { 1289 $("#tbWLinkAnchor").val(m[3]); 1290 } 1291 $("#tbWLinkDesc").val(m[4]); 1292 } else { 1293 $("#tbWLinkDesc").val(m[3]); 1294 } 1295 } else { 1296 $("#tbWLinkDesc").val(s); 1297 if ($("#tbWLinkAnchor")) { 1298 $("#tbWLinkAnchor").val(""); 1299 } 1300 } 1301} 1302 1303function dialogInternalLinkInsert( area_id, dialog ) { 1304 if (!$("#tbWLinkPage").val()) { 1305 alert(tr("Please enter a page name")); 1306 return; 1307 } 1308 var s = "("; 1309 if ($("#tbWLinkRel") && $("#tbWLinkRel").val()) { 1310 s += $("#tbWLinkRel").val(); 1311 } 1312 s += "(" + $("#tbWLinkPage").val(); 1313 if ($("#tbWLinkAnchor") && $("#tbWLinkAnchor").val()) { 1314 s += "|" + ($("#tbWLinkAnchor").val().indexOf("#") !== 0 ? "#" : "") + $("#tbWLinkAnchor").val(); 1315 } 1316 if ($("#tbWLinkDesc").val()) { 1317 s += "|" + $("#tbWLinkDesc").val(); 1318 } 1319 s += "))"; 1320 insertAt(area_id, s, false, false, true); 1321 1322 dialogSharedClose( area_id, dialog ); 1323 1324} 1325 1326// External Link 1327 1328function dialogExternalLinkOpen( area_id ) { 1329 $("#tbWLinkPage").tiki("autocomplete", "pagename"); 1330 dialogSelectElement( area_id, '[', ']' ) ; 1331 var s = getTASelection($('#' + area_id)[0]); 1332 var m = /\[([^\|]*)\|?([^\|]*)\|?([^\|]*)\]/g.exec(s); 1333 if (m && m.length > 3) { 1334 $("#tbLinkURL").val(m[1]); 1335 $("#tbLinkDesc").val(m[2]); 1336 if (m[3]) { 1337 if ($("#tbLinkNoCache") && m[3] == "nocache") { 1338 $("#tbLinkNoCache").attr("checked", "checked"); 1339 } else { 1340 $("#tbLinkRel").val(m[3]); 1341 } 1342 } else { 1343 $("#tbWLinkDesc").val(m[3]); 1344 } 1345 } else { 1346 if (s.match(/(http|https|ftp)([^ ]+)/ig) == s) { // v simple URL match 1347 $("#tbLinkURL").val(s); 1348 } else { 1349 $("#tbLinkDesc").val(s); 1350 } 1351 } 1352 if (!$("#tbLinkURL").val()) { 1353 $("#tbLinkURL").val("http://"); 1354 } 1355} 1356 1357function dialogExternalLinkInsert(area_id, dialog) { 1358 1359 var s = "[" + $("#tbLinkURL").val(); 1360 if ($("#tbLinkDesc").val()) { 1361 s += "|" + $("#tbLinkDesc").val(); 1362 } 1363 if ($("#tbLinkRel").val()) { 1364 s += "|" + $("#tbLinkRel").val(); 1365 } 1366 if ($("#tbLinkNoCache") && $("#tbLinkNoCache").attr("checked")) { 1367 s += "|nocache"; 1368 } 1369 s += "]"; 1370 insertAt(area_id, s, false, false, true); 1371 1372 dialogSharedClose( area_id, dialog ); 1373 1374} 1375 1376// Table 1377 1378function dialogTableOpen(area_id, dialog) { 1379 1380 dialogSelectElement( area_id, '||', '||' ) ; 1381 1382 dialog = $(dialog); 1383 1384 var s = getTASelection($('#' + area_id)[0]); 1385 var m = /\|\|([\s\S]*?)\|\|/mg.exec(s); 1386 var vals = [], rows = 3, cols = 3, c, r, i, j; 1387 if (m) { 1388 m = m[1]; 1389 m = m.split("\n"); 1390 rows = 0; 1391 cols = 1; 1392 for (i = 0; i < m.length; i++) { 1393 var a2 = m[i].split("|"); 1394 var a = []; 1395 for (j = 0; j < a2.length; j++) { // links can have | chars in 1396 if (a2[j].indexOf("[") > -1 && a2[j].indexOf("[[") == -1 && a2[j].indexOf("]") == -1) { // external link 1397 a[a.length] = a2[j]; 1398 j++; 1399 var k = true; 1400 while (j < a2.length && k) { 1401 a[a.length - 1] += "|" + a2[j]; 1402 if (a2[j].indexOf("]") > -1) { // closed 1403 k = false;
1404 } else { 1405 j++; 1406 } 1407 } 1408 } else if (a2[j].search(/\(\S*\(/) > -1 && a2[j].indexOf("))") == -1) { 1409 a[a.length] = a2[j]; 1410 j++; 1411 k = true; 1412 while (j < a2.length && k) { 1413 a[a.length - 1] += "|" + a2[j]; 1414 if (a2[j].indexOf("))") > -1) { // closed 1415 k = false; 1416 } else { 1417 j++; 1418 } 1419 } 1420 } else { 1421 a[a.length] = a2[j]; 1422 } 1423 } 1424 vals[vals.length] = a; 1425 if (a.length > cols) { 1426 cols = a.length; 1427 } 1428 if (a.length) { 1429 rows++; 1430 } 1431 } 1432 } 1433 for (r = 1; r <= rows; r++) { 1434 for (c = 1; c <= cols; c++) { 1435 var v = ""; 1436 if (vals.length) { 1437 if (vals[r - 1] && vals[r - 1][c - 1]) { 1438 v = vals[r - 1][c - 1]; 1439 } else { 1440 v = " "; 1441 } 1442 } else { 1443 v = " "; //row " + r + ",col " + c + ""; 1444 } 1445 var el = $("<input type=\"text\" id=\"tbTableR" + r + "C" + c + "\" class=\"ui-widget-content ui-corner-all\" size=\"10\" style=\"width:" + (90 / cols) + "%\" />") 1446 .val($.trim(v)) 1447 .appendTo(dialog); 1448 } 1449 if (r == 1) { 1450 el = $("<img src=\"img/icons/add.png\" />") 1451 .click(function() { 1452 dialog.data("cols", dialog.data("cols") + 1); 1453 for (r = 1; r <= dialog.data("rows"); r++) { 1454 v = ""; 1455 var el = $("<input type=\"text\" id=\"tbTableR" + r + "C" + dialog.data("cols") + "\" class=\"ui-widget-content ui-corner-all\" size=\"10\" style=\"width:" + (90 / dialog.data("cols")) + "%\" />") 1456 .val(v); 1457 $("#tbTableR" + r + "C" + (dialog.data("cols") - 1)).after(el); 1458 } 1459 dialog.find("input").width(90 / dialog.data("cols") + "%"); 1460 }) 1461 .appendTo(dialog); 1462 } 1463 dialog.append("<br />"); 1464 } 1465 el = $("<img src=\"img/icons/add.png\" />") 1466 .click(function() { 1467 dialog.data("rows", dialog.data("rows") + 1); 1468 for (c = 1; c <= dialog.data("cols"); c++) { 1469 v = ""; 1470 var el = $("<input type=\"text\" id=\"tbTableR" + dialog.data("rows") + "C" + c + "\" class=\"ui-widget-content ui-corner-all\" size=\"10\" value=\"" + v + "\" style=\"width:" + (90 / dialog.data("cols")) + "%\" />") 1471 .insertBefore(this); 1472 } 1473 $(this).before("<br />"); 1474 dialog.dialog("option", "height", (dialog.data("rows") + 1) * 1.2 * $("#tbTableR1C1").height() + 130); 1475 }) 1476 .appendTo(dialog); 1477 1478 dialog 1479 .data('rows', rows) 1480 .data('cols', cols) 1481 .dialog("option", "width", (cols + 1) * 120 + 50) 1482 .dialog("option", "position", "center"); 1483 1484 $("#tbTableR1C1").focus(); 1485} 1486 1487function dialogTableInsert(area_id, dialog) { 1488 var s = "||", rows, cols, c, r, rows2 = 1, cols2 = 1; 1489 dialog = $(dialog); 1490 1491 rows = dialog.data('rows') || 3; 1492 cols = dialog.data('cols') || 3; 1493 for (r = 1; r <= rows; r++) { 1494 for (c = 1; c <= cols; c++) { 1495 if ($.trim($("#tbTableR" + r + "C" + c).val())) { 1496 if (r > rows2) { 1497 rows2 = r; 1498 } 1499 if (c > cols2) { 1500 cols2 = c; 1501 } 1502 } 1503 } 1504 } 1505 for (r = 1; r <= rows2; r++) { 1506 for (c = 1; c <= cols2; c++) { 1507 var tableData = $("#tbTableR" + r + "C" + c).val(); 1508 s += tableData; 1509 if (c < cols2) { 1510 s += (tableData ? '|' : ' | '); 1511 } 1512 } 1513 if (r < rows2) { 1514 s += "\n"; 1515 } 1516 } 1517 s += "||"; 1518 insertAt(area_id, s, false, false, true); 1519 1520 dialogSharedClose( area_id, dialog ); 1521} 1522 1523// Find 1524 1525function dialogFindOpen(area_id) { 1526 1527 var s = getTASelection($('#' + area_id)[0]); 1528 $("#tbFindSearch").val(s).focus(); 1529} 1530 1531function dialogFindFind( area_id ) { 1532 var ta = $('#' + area_id); 1533 var findInput = $("#tbFindSearch").removeClass("ui-state-error"); 1534 1535 var $textareaEditor = syntaxHighlighter.get(ta); //codemirror functionality 1536 if ($textareaEditor) { 1537 syntaxHighlighter.find($textareaEditor, findInput.val()); 1538 } 1539 else { //standard functionality 1540 var s, opt, str, re, p = 0, m; 1541 s = findInput.val(); 1542 opt = ""; 1543 if ($("#tbFindCase").attr("checked")) { 1544 opt += "i"; 1545 } 1546 str = ta.val(); 1547 re = new RegExp(s, opt); 1548 p = getCaretPos(ta[0]); 1549 if (p && p < str.length) { 1550 m = re.exec(str.substring(p)); 1551 } 1552 else { 1553 p = 0; 1554 } 1555 if (!m) { 1556 m = re.exec(str); 1557 p = 0; 1558 } 1559 if (m) { 1560 setSelectionRange(ta[0], m.index + p, m.index + s.length + p); 1561 } 1562 else { 1563 findInput.addClass("ui-state-error"); 1564 } 1565 } 1566} 1567 1568// Replace 1569 1570function dialogReplaceOpen(area_id) { 1571 1572 var s = getTASelection($('#' + area_id)[0]); 1573 $("#tbReplaceSearch").val(s).focus(); 1574 1575} 1576 1577function dialogReplaceReplace( area_id ) { 1578 var findInput = $("#tbReplaceSearch").removeClass("ui-state-error"); 1579 var s = findInput.val(); 1580 var r = $("#tbReplaceReplace").val(); 1581 var opt = ""; 1582 if ($("#tbReplaceAll").attr("checked")) { 1583 opt += "g"; 1584 } 1585 if ($("#tbReplaceCase").attr("checked")) { 1586 opt += "i"; 1587 } 1588 var ta = $('#' + area_id); 1589 var str = ta.val(); 1590 var re = new RegExp(s,opt); 1591 1592 var textareaEditor = syntaxHighlighter.get(ta); //codemirror functionality 1593 if (textareaEditor) { 1594 syntaxHighlighter.replace(textareaEditor, s, r); 1595 } 1596 else { //standard functionality 1597 ta.val(str.replace(re, r)); 1598 } 1599 1600} 1601 1602 1603(function($) { 1604 /** 1605 * Adds annotations to the content of text in ''container'' based on the 1606 * content found in selected dts. 1607 * 1608 * Used in comments.tpl 1609 */ 1610 $.fn.addnotes = function( container ) { 1611 return this.each(function(){ 1612 var comment = this; 1613 var text = $('dt:contains("note")', comment).next('dd').text(); 1614 var title = $('h6:first', comment).clone(); 1615 var body = $('.body:first', comment).clone(); 1616 body.find('dt:contains("note")').closest('dl').remove(); 1617 1618 if( text.length > 0 ) {
1619 var parents = container.find(':contains("' + text + '")').parent(); 1620 var node = container.find(':contains("' + text + '")').not(parents) 1621 .addClass('note-editor-text') 1622 .each( function() { 1623 var child = $('dl.note-list',this); 1624 if( ! child.length ) { 1625 child = $('<dl class="note-list"/>') 1626 .appendTo(this) 1627 .hide(); 1628 1629 $(this).click( function() { 1630 child.toggle(); 1631 } ); 1632 } 1633 1634 child.append( title ) 1635 .append( $('<dd/>').append(body) ); 1636 } ); 1637 } 1638 }); 1639 }; 1640 1641 /** 1642 * Convert a zone to a note editor by attaching handlers on mouse events. 1643 */ 1644 $.fn.noteeditor = function (editlink, link) { 1645 var hiddenParents = null; 1646 var annote = $(link) 1647 .click( function( e ) { 1648 e.preventDefault(); 1649 1650 var $block = $('<div/>'); 1651 var annotation = $(this).attr('annotation'); 1652 $(this).fadeOut(100); 1653 1654 $block.load(editlink.attr('href'), function () { 1655 var msg = ""; 1656 if (annotation.length < 20) { 1657 msg = tr("The text you have selected is quite short. Select a longer piece to ensure the note is associated with the correct text.") + "<br />"; 1658 } 1659 1660 msg = "<p class='description comment-info'>" + msg + tr("Tip: Leave the first line as it is, starting with \";note:\". This is required") + "</p>"; 1661 $block.prepend($(msg)); 1662 $('textarea', this) 1663 .val(';note:' + annotation + "\n\n").focus(); 1664 1665 $('form', this).submit(function () { 1666 $.post($(this).attr('action'), $(this).serialize(), function () { 1667 $block.dialog('destroy'); 1668 }); 1669 return false; 1670 }); 1671 1672 $block.dialog({ 1673 modal: true, 1674 width: 500, 1675 height: 400 1676 }); 1677 }); 1678 } ) 1679 .appendTo(document.body); 1680 1681 $(this).mouseup(function( e ) { 1682 var range; 1683 if( window.getSelection && window.getSelection().rangeCount ) { 1684 range = window.getSelection().getRangeAt(0); 1685 } else if( window.selection ) { 1686 range = window.selection.getRangeAt(0); 1687 } 1688 1689 if( range ) { 1690 var str = $.trim( range.toString() ); 1691 1692 if( str.length && -1 === str.indexOf( "\n" ) ) { 1693 annote.attr('annotation', str); 1694 annote.fadeIn(100).position( { 1695 of: e, 1696 at: 'bottom left', 1697 my: 'top left', 1698 offset: '20 20' 1699 } ); 1700 } else { 1701 if (annote.css("display") != "none") { 1702 annote.fadeOut(100); 1703 } 1704 if ($("form.comments").css("display") == "none") { 1705 $("form.comments").show(); 1706 } 1707 if (hiddenParents) { 1708 hiddenParents.hide(); 1709 hiddenParents = null; 1710 } 1711 } 1712 } 1713 }); 1714 }; 1715 1716 $.fn.browse_tree = function () { 1717 this.each(function () { 1718 $('.treenode:not(.done)', this) 1719 .addClass('done') 1720 .each(function () { 1721 if (getCookie($('ul:first', this).attr('data-id'), $('ul:first', this).attr('data-prefix')) !== 'o') { 1722 $('ul:first', this).css('display', 'none'); 1723 } 1724 if ($('ul:first', this).length) { 1725 var dir = $('ul:first', this).css('display') === 'block' ? 's' : 'e'; 1726 $(this).prepend('<span class="flipper ui-icon ui-icon-triangle-1-' + dir + '" style="float: left;"/>'); 1727 } else { 1728 $(this).prepend('<span style="float:left;width:16px;height:16px;"/>'); 1729 } 1730 }); 1731 1732 $('.flipper:not(.done)') 1733 .addClass('done') 1734 .css('cursor', 'pointer') 1735 .click(function () { 1736 var body = $(this).parent().find('ul:first'); 1737 if ('block' === body.css('display')) { 1738 $(this).removeClass('ui-icon-triangle-1-s').addClass('ui-icon-triangle-1-e'); 1739 body.hide('fast'); 1740 setCookie(body.data("id"), "", body.data("prefix")); 1741 } else { 1742 $(this).removeClass('ui-icon-triangle-1-e').addClass('ui-icon-triangle-1-s'); 1743 body.show('fast'); 1744 setCookie(body.data("id"), "o", body.data("prefix")); 1745 } 1746 }); 1747 }); 1748 1749 return this; 1750 }; 1751 1752 var fancy_filter_create_token = function(value, label) { 1753 var close, token; 1754 1755 close = $('<span class="ui-icon ui-icon-close"/>') 1756 .click(function () { 1757 var ed = $(this).parent().parent(); 1758 $(this).parent().remove(); 1759 ed.change(); 1760 return false; 1761 }); 1762 1763 token = $('<span class="token"/>') 1764 .attr('data-value', value) 1765 .text(label) 1766 .attr('contenteditable', false) 1767 .disableSelection()
1768 .append(close); 1769 1770 return token[0]; 1771 }; 1772 1773 var fancy_filter_build_init = function(editable, str, options) { 1774 if (str === '') { 1775 str = ' '; 1776 } 1777 1778 editable.html(str.replace(/(\d+)/g, '<span>$1</span>')); 1779 1780 if (options && options.map) { 1781 editable.find('span').each(function () { 1782 var val = $(this).text(); 1783 $(this).replaceWith(fancy_filter_create_token(val, options.map[val] ? options.map[val] : val)); 1784 }); 1785 } 1786 }; 1787 1788 $jq.fn.fancy_filter = function (operation, options) { 1789 this.each(function () { 1790 switch (operation) { 1791 case 'init': 1792 var editable = $('<div class="fancyfilter"/>'), input = this; 1793 1794 if (editable[0].contentEditable !== null) { 1795 fancy_filter_build_init(editable, $(this).val(), options); 1796 editable.attr('contenteditable', true); 1797 $(this).after(editable).hide(); 1798 } 1799 1800 editable 1801 .keyup(function() { 1802 $(this).change(); 1803 $(this).mouseup(); 1804 }) 1805 .change(function () { 1806 $(input).val($('<span/>') 1807 .html(editable.html()) 1808 .find('span').each(function() { 1809 $(this).replaceWith(' ' + $(this).attr('data-value') + ' '); 1810 }) 1811 .end().text().replace(/\s+/g, ' ')); 1812 }) 1813 .mouseup(function () { 1814 input.lastRange = window.getSelection().getRangeAt(0); 1815 }); 1816 1817 break; 1818 case 'add': 1819 var node = fancy_filter_create_token(options.token, options.label); 1820 if (this.lastRange) { 1821 this.lastRange.deleteContents(); 1822 this.lastRange.insertNode(node); 1823 this.lastRange.insertNode(document.createTextNode(options.join)); 1824 } else { 1825 $(this).next().append(options.join).append(node); 1826 } 1827 $(this).next().change(); 1828 break; 1829 } 1830 }); 1831 1832 return this; 1833 }; 1834 1835 $.fn.drawGraph = function () { 1836 this.each(function () { 1837 var $this = $(this); 1838 var width = $this.width(); 1839 var height = Math.ceil( width * 9 / 16 ); 1840 var nodes = $this.data('graph-nodes'); 1841 var edges = $this.data('graph-edges'); 1842 1843 var g = new Graph; 1844 $.each(nodes, function (k, i) { 1845 g.addNode(i); 1846 }); 1847 $.each(edges, function (k, i) { 1848 var style = { directed: true }; 1849 if( i.preserve ) { 1850 style.color = 'red'; 1851 } 1852 g.addEdge( i.from, i.to, style ); 1853 }); 1854 1855 var layouter = new Graph.Layout.Spring(g); 1856 layouter.layout(); 1857 1858 var renderer = new Graph.Renderer.Raphael($this.attr('id'), g, width, height ); 1859 renderer.draw(); 1860 }); 1861 1862 return this; 1863 }; 1864 1865 /** 1866 * Handle textarea and input text selections 1867 * Code from: 1868 * 1869 * jQuery Autocomplete plugin 1.1 1870 * Copyright (c) 2009 Jörn Zaefferer 1871 * 1872 * Dual licensed under the MIT and GPL licenses: 1873 * http://www.opensource.org/licenses/mit-license.php 1874 * http://www.gnu.org/licenses/gpl.html 1875 * 1876 * Now deprecated and replaced in Tiki 7 by jquery-ui autocomplete 1877 */ 1878 $.fn.selection = function(start, end) { 1879 if (start !== undefined) { 1880 if (end === undefined) { 1881 end = start; 1882 } 1883 return this.each(function() { 1884 if( this.createTextRange ){ 1885 var selRange = this.createTextRange(); 1886 if (start == end) { 1887 selRange.move("character", start); 1888 selRange.select(); 1889 } else { 1890 selRange.collapse(true); 1891 selRange.moveStart("character", start); 1892 selRange.moveEnd("character", end - start); // moveEnd is relative 1893 selRange.select(); 1894 } 1895 } else if( this.setSelectionRange ){ 1896 this.setSelectionRange(start, end); 1897 } else if( this.selectionStart ){ 1898 this.selectionStart = start; 1899 this.selectionEnd = end; 1900 } 1901 }); 1902 } 1903 var field = this[0]; 1904 if ( field.createTextRange ) { 1905 // from http://the-stickman.com/web-development/javascript/finding-selection-cursor-position-in-a-textarea-in-internet-explorer/ 1906 // The current selection 1907 var range = document.selection.createRange(); 1908 // We'll use this as a 'dummy' 1909 var stored_range = range.duplicate(); 1910 // Select all text 1911 stored_range.moveToElementText( field ); 1912 // Now move 'dummy' end point to end point of original range 1913 stored_range.setEndPoint( 'EndToEnd', range ); 1914 // Now we can calculate start and end points 1915 var selectionStart = stored_range.text.length - range.text.length; 1916 var selectionEnd = selectionStart + range.text.length; 1917 return { 1918 start: selectionStart, 1919 end: selectionEnd 1920 } 1921 1922 } else if( field.selectionStart !== undefined ){ 1923 return { 1924 start: field.selectionStart, 1925 end: field.selectionEnd 1926 } 1927 } 1928 }; 1929 1930 $.fn.comment_toggle = function () { 1931 this.each(function () { 1932 var $target = $(this.hash); 1933 $target.hide(); 1934 1935 $(this).click(function () { 1936 if ($target.is(':visible')) { 1937 $target.hide(function () { 1938 $(this).empty(); 1939 }); 1940 } else { 1941 $target.comment_load($(this).attr('href')); 1942 } 1943 1944 return false;
1945 }); 1946 }); 1947 1948 return this; 1949 }; 1950 1951 $.fn.comment_load = function (url) { 1952 $('#top .note-list').remove(); 1953 1954 this.each(function () { 1955 var comment_container = this; 1956 $(this).load(url, function (response, status) { 1957 $(this).show(); 1958 $('.comment.inline dt:contains("note")', this) 1959 .closest('.comment') 1960 .addnotes( $('#top') ); 1961 1962 $('#top').noteeditor($('.comment-form:last a', comment_container), '#note-editor-comment'); 1963 1964 $('.comment-form a', this).click(function () { 1965 $(this).parent().empty().removeClass('button').load($(this).attr('href'), function () { 1966 $('form', this).submit(function () { 1967 var form = this, errors; 1968 $.post($(form).attr('action'), $(this).serialize(), function (data, st) { 1969 if (data.threadId) { 1970 $(comment_container).empty().comment_load(url); 1971 } else { 1972 errors = $('ol.errors', form).empty(); 1973 if (! errors.length) { 1974 $(':submit', form).after(errors = $('<ol class="errors"/>')); 1975 } 1976 1977 $.each(data.errors, function (k, v) { 1978 errors.append($('<li/>').text(v)); 1979 }); 1980 } 1981 }, 'json'); 1982 return false; 1983 }); 1984 }); 1985 return false; 1986 }); 1987 1988 $('.button.comment-form.autoshow a').click(); // allow autoshowing of comment forms through autoshow css class 1989 1990 $('.confirm-prompt', this).requireConfirm({ 1991 success: function (data) { 1992 if (data.status === 'DONE') { 1993 $(comment_container).empty().comment_load(url); 1994 } 1995 } 1996 }); 1997 }); 1998 }); 1999 2000 return this; 2001 }; 2002 2003 $.fn.input_csv = function (operation, separator, value) { 2004 this.each(function () { 2005 var values = $(this).val().split(separator); 2006 if (values[0] === '') { 2007 values.shift(); 2008 } 2009 2010 if (operation === 'add') { 2011 values.push(value); 2012 } else if (operation === 'delete') { 2013 value = String(value); 2014 while (-1 !== $.inArray(value, values)) { 2015 values.splice($.inArray(value, values), 1); 2016 } 2017 } 2018 2019 $(this).val(values.join(separator)); 2020 }); 2021 2022 return this; 2023 }; 2024 2025 $.service = function (controller, action, query) { 2026 var append = ''; 2027 2028 if (query) { 2029 append = '?' + $.map(query, function (v, k) { 2030 return k + '=' + escape(v); 2031 }).join('&'); 2032 } 2033 2034 if (action) { 2035 return 'tiki-' + controller + '-' + action + append; 2036 } else { 2037 return 'tiki-' + controller + append; 2038 } 2039 }; 2040 2041 $.fn.serviceDialog = function (options) { 2042 this.each(function () { 2043 var $dialog = $('<div/>'), origin = this, buttons = {}; 2044 $(this).append($dialog).data('serviceDialog', $dialog); 2045 2046 buttons[tr('OK')] = function () { 2047 $dialog.find('form:visible').submit(); 2048 }; 2049 buttons[tr('Cancel')] = function () { 2050 $dialog 2051 .dialog('close') 2052 .dialog('destroy'); 2053 }; 2054 2055 $dialog.dialog({ 2056 title: options.title, 2057 minWidth: 500, 2058 height: (options.fullscreen ? $window.height() - 20 : 600), 2059 width: (options.fullscreen ? $window.width() - 20 : null), 2060 close: function () { 2061 if (options.close) { 2062 options.close.apply([], this); 2063 } 2064 $(this).dialog('destroy'); 2065 }, 2066 buttons: buttons, 2067 modal: options.modal, 2068 zIndex: options.zIndex 2069 }); 2070 2071 $dialog.loadService(options.data, $.extend(options, {origin: origin})); 2072 }); 2073 2074 return this; 2075 }; 2076 $.fn.loadService = function (data, options) { 2077 var $dialog = this, controller = options.controller, action = options.action, url; 2078 2079 if (data && data.controller) { 2080 controller = data.controller; 2081 } 2082 2083 if (data && data.action) { 2084 action = data.action; 2085 } 2086 2087 if (options.origin && $(options.origin).is('a')) { 2088 url = $(options.origin).attr('href'); 2089 } else { 2090 url = $.service(controller, action); 2091 } 2092 2093 $dialog.load(url, data, function (data) { 2094 $dialog.find('form .submit').hide(); 2095 2096 $dialog.find('form:not(.no-ajax)').submit(function (e) { 2097 var form = this, act; 2098 act = $(form).attr('action'); 2099 2100 if (! act) { 2101 act = url; 2102 } 2103 2104 $.ajax(act, { 2105 type: 'POST', 2106 dataType: 'json', 2107 data: $(form).serialize(), 2108 success: function (data) { 2109 data = (data ? data : {}); 2110 2111 if (data.FORWARD) { 2112 $dialog.loadService(data.FORWARD, options); 2113 } else { 2114 $dialog.dialog('destroy'); 2115 } 2116 2117 if (options.success) { 2118 options.success.apply(options.origin, [data]); 2119 } 2120 }, 2121 error: function (jqxhr) { 2122 $(form.name).showError(jqxhr); 2123 } 2124 }); 2125 2126 return false;
2127 }); 2128 2129 if (options.load) { 2130 options.load.apply($dialog[0], [data]); 2131 } 2132 2133 $('.confirm-prompt', this).requireConfirm({ 2134 success: function (data) { 2135 if (data.FORWARD) { 2136 $dialog.loadService(data.FORWARD, options); 2137 } else { 2138 $dialog.loadService(options.data, options); 2139 } 2140 } 2141 }); 2142 }); 2143 }; 2144 2145 $.fn.requireConfirm = function (options) { 2146 this.click(function (e) { 2147 e.preventDefault(); 2148 var message = options.message, link = this; 2149 2150 if (! message) { 2151 message = $(this).data('confirm'); 2152 } 2153 2154 if (confirm (message)) { 2155 $.ajax($(this).attr('href'), { 2156 type: 'POST', 2157 dataType: 'json', 2158 data: { 2159 'confirm': 1 2160 }, 2161 success: function (data) { 2162 options.success.apply(link, [data]); 2163 }, 2164 error: function (jqxhr) { 2165 $(link).closest('form').showError(jqxhr); 2166 } 2167 }); 2168 } 2169 return false; 2170 }); 2171 2172 return this; 2173 }; 2174 2175 $.fn.showError = function (message) { 2176 if (message.responseText) { 2177 var data = $.parseJSON(message.responseText); 2178 message = data.message; 2179 } 2180 this.each(function () { 2181 var validate = $(this).closest('form').validate(), errors = {}, field; 2182 2183 if (validate) { 2184 if (! $(this).attr('name')) { 2185 $(this).attr('name', $(this).attr('id')); 2186 } 2187 2188 field = $(this).attr('name'); 2189 2190 var parts; 2191 if (parts = message.match(/^<!--field\[([^\]]+)\]-->(.*)$/)) { 2192 field = parts[1]; 2193 message = parts[2]; 2194 } 2195 2196 errors[field] = message; 2197 validate.showErrors(errors); 2198 2199 setTimeout(function () { 2200 $('#error_report li').filter(function () { 2201 return $(this).text() === message; 2202 }).remove(); 2203 2204 if ($('#error_report ul').is(':empty')) { 2205 $('#error_report').empty(); 2206 } 2207 }, 100); 2208 } 2209 }); 2210 2211 return this; 2212 }; 2213 2214 $.fn.clearError = function () { 2215 this.each(function () { 2216 $(this).closest('form').find('label.error[for="' + $(this).attr('name') + '"]').remove(); 2217 }); 2218 2219 return this; 2220 }; 2221 2222 $.fn.object_selector = function (filter, threshold) { 2223 var input = this; 2224 this.each(function () { 2225 var $spinner = $(this).parent().modal(" "); 2226 $.getJSON('tiki-searchindex.php', { 2227 filter: filter 2228 }, function (data) { 2229 var $select = $('<select/>'), $autocomplete = $('<input type="text"/>'); 2230 $(input).wrap('<div class="object_selector"/>'); 2231 $(input).hide(); 2232 $select.append('<option/>'); 2233 $.each(data, function (key, value) { 2234 $select.append($('<option/>').attr('value', value.object_type + ':' + value.object_id).text(value.title)); 2235 }); 2236 2237 $(input).after($select); 2238 $select.change(function () { 2239 $(input).data('label', $select.find('option:selected').text()); 2240 $(input).val($select.val()).change(); 2241 }); 2242 2243 if (jqueryTiki.selectmenu) { 2244 var $hidden = $select.parents("fieldset:hidden:last").show(); 2245 $select.css("font-size", $.browser.webkit ? "1.4em" : "1.1em") // not sure why webkit is so different, it just is :( 2246 .attr("id", input.attr("id") + "_sel") // bug in selectmenu when no id 2247 .tiki("selectmenu"); 2248 $hidden.hide(); 2249 } 2250 $spinner.modal(); 2251 2252 if ($select.children().length > threshold) { 2253 var filterField = $('<input type="text"/>').width(120).css('marginRight', '1em'); 2254 2255 $(input).after(filterField); 2256 filterField.wrap('<label/>').before(tr('Search:')+ ' '); 2257 2258 filterField.keypress(function (e) { 2259 var field = this; 2260 2261 if (e.which === 0 || e.which === 13) { 2262 return false; 2263 } 2264 2265 if (this.searching) { 2266 clearTimeout(this.searching); 2267 this.searching = null; 2268 } 2269 2270 if (this.ajax) { 2271 this.ajax.abort(); 2272 this.ajax = null; 2273 $spinner.modal(); 2274 } 2275 2276 if (jqueryTiki.selectmenu) { 2277 $select.selectmenu('open'); 2278 $(field).focus(); 2279 } 2280 2281 this.searching = setTimeout(function () { 2282 var loaded = $(field).val(); 2283 if (!loaded || loaded === " ") { // let them get the whole list back? 2284 loaded = "*"; 2285 } 2286 if ((loaded === "*" || loaded.length >= 3) && loaded !== $select.data('loaded')) { 2287 $spinner = $(field).parent().modal(" "); 2288 field.ajax = $.getJSON('tiki-searchindex.php', { 2289 filter: $.extend(filter, {autocomplete: loaded}) 2290 }, function (data) { 2291 $select.empty(); 2292 $select.data('loaded', loaded); 2293 $select.append('<option/>'); 2294 $.each(data, function (key, value) { 2295 $select.append($('<option/>').attr('value', value.object_type + ':' + value.object_id).text(value.title)); 2296 }); 2297 if (jqueryTiki.selectmenu) { 2298 $select.tiki("selectmenu"); 2299 $select.selectmenu('open'); 2300 $(field).focus(); 2301 } 2302 $spinner.modal(); 2303 }); 2304 } 2305 }, 500); 2306 }); 2307 } 2308 }); 2309 }); 2310 2311 return this; 2312 }; 2313 2314 $.fn.sortList = function () { 2315 var list = $(this), items = list.children('li').get(); 2316 2317 items.sort(function(a, b) { 2318 var compA = $(a).text().toUpperCase(); 2319 var compB = $(b).text().toUpperCase(); 2320 return (compA < compB) ? -1 : (compA > compB) ? 1 : 0; 2321 }) 2322 2323 $.each(items, function(idx, itm) { 2324 list.append(itm); 2325 }); 2326 }; 2327 $.localStorage = { 2328 store: function (key, value) { 2329 if (window.localStorage) { 2330 window.localStorage[key] = $.toJSON(favoriteList); 2331 } 2332 }, 2333 load: function (key, callback, fetch) { 2334 if (window.localStorage && window.localStorage[key]) { 2335 callback($.parseJSON(window.localStorage[key])); 2336 } else { 2337 fetch(function (data) { 2338 window.localStorage[key] = $.toJSON(data); 2339 callback(data); 2340 }); 2341 } 2342 } 2343 }; 2344 2345 var favoriteList = []; 2346 $.fn.favoriteToggle = function () { 2347 this.find('a') 2348 .each(function () { 2349 var type, obj, isFavorite, link = this; 2350 type = $(this).queryParam('type'); 2351 obj = $(this).queryParam('object'); 2352 2353 2354 function isFavorite() { 2355 var ret = false;
2356 $.each(favoriteList, function (k, v) { 2357 if (v === type + ':' + obj) { 2358 ret = true; 2359 return false; 2360 } 2361 }); 2362 2363 return ret; 2364 } 2365 2366 $(this).empty(); 2367 $(this).append(tr('Favorite')); 2368 $(this).prepend($('<img style="vertical-align: top; margin-right: .2em;" />').attr('src', isFavorite() ? 'img/icons/star.png' : 'img/icons/star_grey.png')); 2369 // Toggle class of closest surrounding div for css customization 2370 if (isFavorite()) { 2371 $(this).closest('div').addClass( 'favorite_selected' ); 2372 $(this).closest('div').removeClass( 'favorite_unselected' ); 2373 } else { 2374 $(this).closest('div').addClass( 'favorite_unselected' ); 2375 $(this).closest('div').removeClass( 'favorite_selected' ); 2376 } 2377 $(this) 2378 .filter(':not(".register")') 2379 .addClass('register') 2380 .click(function () { 2381 $.getJSON($(this).attr('href'), { 2382 target: isFavorite() ? 0 : 1 2383 }, function (data) { 2384 favoriteList = data.list; 2385 $.localStorage.store('favorites', favoriteList); 2386 2387 $(link).parent().favoriteToggle(); 2388 }); 2389 return false; 2390 }); 2391 }); 2392 2393 return this; 2394 }; 2395 2396 $.fn.queryParam = function (name) { 2397 name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); 2398 var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"); 2399 var results = regex.exec(this[0].href); 2400 2401 if(results == null) { 2402 return ""; 2403 } else { 2404 return decodeURIComponent(results[1].replace(/\+/g, " ")); 2405 } 2406 }; 2407 2408 $(function () { 2409 var list = $('.favorite-toggle'); 2410 2411 if (list.length > 0) { 2412 $.localStorage.load( 2413 'favorites', 2414 function (data) { 2415 favoriteList = data; 2416 list 2417 .favoriteToggle() 2418 .removeClass('favorite-toggle'); 2419 }, 2420 function (recv) { 2421 $.getJSON($.service('favorite', 'list'), recv); 2422 } 2423 ); 2424 } 2425 }); 2426 2427 $.ajaxSetup({ 2428 complete: function () { 2429 $('.favorite-toggle') 2430 .favoriteToggle() 2431 .removeClass('favorite-toggle'); 2432 } 2433 }); 2434 2435 /** 2436 * Show a loading spinner on top of a button (or whatever) 2437 * 2438 * @param empty or jq object $spinner if empty, spinner is added and returned and element "disabled" 2439 * if spinner then spinner is removed and element returned to normal 2440 * 2441 * @return jq object $spinner being shown or null when removing 2442 */ 2443 2444 $.fn.showBusy = function( $spinner ) { 2445 if (!$spinner) { 2446 var pos = $(this).position(); 2447 $spinner = $("<img src='img/spinner.gif' alt='" + tr("Wait") + "' class='ajax-spinner' />"). 2448 css({ 2449 "position": "absolute", 2450 "top": pos.top + ($(this).height() / 2), 2451 "left": pos.left + ($(this).width() / 2) - 8 2452 }).data("target", this); 2453 $(this).parent().find(".ajax-spinner").remove(); 2454 $(this).parent().append($spinner); 2455 $(this).attr("disabled", true).css("opacity", 0.5); 2456 return $spinner; 2457 } else { 2458 $($spinner.data("target")).attr("disabled", false).css("opacity", 1); 2459 $spinner.remove(); 2460 return null; 2461 } 2462 } 2463 2464})($jq); 2465 2466// Prevent memory leaks in IE 2467// Window isn't included so as not to unbind existing unload events 2468// More info: 2469// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ 2470if ( window.attachEvent && !window.addEventListener ) { 2471 window.attachEvent("onunload", function() { 2472 for ( var id in jQuery.cache ) { 2473 var item = jQuery.cache[ id ]; 2474 if ( item.handle ) { 2475 if ( item.handle.elem === window ) { 2476 for ( var type in item.events ) { 2477 if ( type !== "unload" ) { 2478 // Try/Catch is to handle iframes being unloaded, see #4280 2479 try { 2480 jQuery.event.remove( item.handle.elem, type ); 2481 } catch(e) {} 2482 } 2483 } 2484 } else { 2485 // Try/Catch is to handle iframes being unloaded, see #4280 2486 try { 2487 jQuery.event.remove( item.handle.elem ); 2488 } catch(e) {} 2489 } 2490 } 2491 } 2492 }); 2493} 2494 2495$.modal = function(msg) { 2496 return $('body').modal(msg, { 2497 isEverything: true 2498 }); 2499}; 2500 2501//Makes modal over window or object so ajax can load and user can't prevent action 2502$.fn.modal = function(msg, s) { 2503 var obj = $(this); 2504 var lastModal = obj.attr('lastModal'); 2505 2506 if (!lastModal) { 2507 lastModal = Math.floor(Math.random() * 1000); 2508 obj.attr('lastModal', lastModal); 2509 } 2510 2511 var mid = obj.height() / 2 + obj.offset().top; 2512 if (mid > $window.height()) { 2513 mid = ($window.height() - obj.offset().top) / 2 + obj.offset().top; 2514 } 2515 s = $.extend({ 2516 isEverything: false, 2517 top: obj.offset().top, 2518 left: obj.offset().left, 2519 height: obj.height(), //we try to get height here 2520 width: obj.width(), 2521 middle: (mid), 2522 center: (obj.width() / 2 + obj.offset().left) 2523 }, s); 2524 2525 var modal = $('body').find('#modal_' + lastModal); 2526 var spinner = $('<img src="img/spinner.gif" />'); 2527 2528 if (!msg) { 2529 modal 2530 .fadeOut(function() { 2531 $(this).remove(); 2532 }); 2533 obj.removeAttr('lastModal'); 2534 return; 2535 } 2536 2537 if (modal.length) { 2538 modal 2539 .find('.dialog') 2540 .html(spinner) 2541 .append(msg); 2542 return; 2543 } 2544
2545 modal = $('<div>' + 2546 '<div class="dialog"></div>' + 2547 '<div class="mask"></div>' + 2548 '</div>') 2549 .addClass('boxes') 2550 .attr('id', 'modal_' + lastModal) 2551 .prependTo('body'); 2552 2553 var size = {}; 2554 2555 if (s.isEverything) { //if the modal includes the whole page 2556 s = $.extend(s, { 2557 top: 0, 2558 left: 0, 2559 height: $document.height(), 2560 width: $window.width(), 2561 middle: $window.height() / 2, 2562 center: $window.width() / 2 2563 }); 2564 } 2565 2566 //Set height and width to mask to fill up the whole screen or the single element 2567 modal.find('.mask') 2568 .css('width', s.width + 'px') 2569 .css('height', s.height + 'px') 2570 .css('top', s.top + 'px') 2571 .css('left', s.left + 'px') 2572 .css('position', 'absolute') 2573 .fadeTo(1,0.01) 2574 .fadeTo(1000,0.8); 2575 2576 var dialog = modal.find('.dialog'); 2577 dialog 2578 .append(spinner) 2579 .append(msg) 2580 .css('top', (s.middle - dialog.height() / 2) + 'px') 2581 .css('left', (s.center - dialog.width() / 2) + 'px') 2582 .css('position', 'absolute'); 2583 2584 if (s.isEverything) { 2585 dialog 2586 .css('top', (s.middle - dialog.height() / 2) + 'px') 2587 .css('left', (s.center - dialog.width() / 2) + 'px') 2588 .css('position', 'fixed'); 2589 } 2590 2591 return obj; 2592}; 2593 2594//makes the width of an input change to the value 2595$.fn.valWidth = function() { 2596 var me = $(this); 2597 return me.ready(function() { 2598 var h = me.height(); 2599 if (!h) { 2600 h = me.offsetParent().css("font-size"); 2601 if (h) { 2602 h = parseInt(h.replace("px", "")); 2603 } 2604 } 2605 me.keyup(function() { 2606 var width = me.val().length * h; 2607 2608 me 2609 .stop() 2610 .animate({ 2611 width: (width > h ? width : h) 2612 }, 200); 2613 }) 2614 .keyup(); 2615 }); 2616}; 2617 2618//For making pagination have the ability to enter page/offset number and go 2619$.paginationHelper = function() { 2620 $('.pagenums').each(function() { 2621 var me = $(this); 2622 var step = me.find('input.pagenumstep'); 2623 var endOffset = (me.find('input.pagenumend').val() - 1) * step.data('step'); 2624 var url = step.data('url'); 2625 var offset_jsvar = step.data('offset_jsvar'); 2626 2627 me.find('span.pagenumstep').replaceWith( 2628 $('<input type="text" style="font-size: inherit; " />') 2629 .val(step.val()) 2630 .change(function() { 2631 var newOffset = step.data('step') * ($(this).val() - 1); 2632 2633 if (newOffset >= 0) { 2634 //make sure the offset isn't too high 2635 newOffset = (newOffset > endOffset ? endOffset : newOffset); 2636 2637 //THis is for custom/ajax search handling 2638 window[offset_jsvar] = newOffset; 2639 if (step[0]) { 2640 if (step.attr('onclick')) { 2641 step[0].onclick(); 2642 return; 2643 } 2644 } 2645 2646 //if the above behavior isn't there, we update location 2647 document.location = url + "offset=" + newOffset; 2648 } 2649 }) 2650 .keyup(function(e) { 2651 switch(e.which) { 2652 case 13: $(this).blur(); 2653 } 2654 }) 2655 .valWidth() 2656 ); 2657 }); 2658}; 2659 2660//a sudo "onvisible" event 2661$.fn.visible = function(fn, isOne) { 2662 if (fn) { 2663 $(this).each(function() { 2664 var me = $(this); 2665 if (isOne) { 2666 me.one('visible', fn); 2667 } else { 2668 me.bind('visible', fn); 2669 } 2670 2671 function visibilityHelper() { 2672 if (!me.is(':visible')) { 2673 setTimeout(visibilityHelper, 500); 2674 } else { 2675 me.trigger('visible'); 2676 } 2677 } 2678 2679 visibilityHelper(); 2680 }); 2681 } else { 2682 $(this).trigger('visible'); 2683 } 2684 2685 return this; 2686}; 2687 2688$.download = function(url, data, method){ 2689 //url and data options required 2690 if( url && data ){ 2691 //data can be string of parameters or array/object 2692 data = typeof data == 'string' ? data : jQuery.param(data); 2693 //split params into form inputs 2694 var inputs = ''; 2695 jQuery.each(data.split('&'), function(){ 2696 var pair = this.split('='); 2697 inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />'; 2698 }); 2699 //send request 2700 jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>') 2701 .appendTo('body').submit().remove(); 2702 }; 2703}; 2704 2705$.uiIcon = function(type) { 2706 return $('<div style="width: 1.4em; height: 1.4em; margin: .2em; display: inline-block; cursor: pointer;">' + 2707 '<span class="ui-icon ui-icon-' + type + '"> </span>' + 2708 '</div>') 2709 .hover(function(){ 2710 $(this).addClass('ui-state-highlight'); 2711 }, function() { 2712 $(this).removeClass('ui-state-highlight'); 2713 }); 2714}; 2715 2716$.uiIconButton = function(type) { 2717 return $.uiIcon(type).addClass('ui-state-default ui-corner-all'); 2718}; 2719 2720$.rangySupported = function(fn) { 2721 if (window.rangy) { 2722 rangy.init(); 2723 var cssClassApplierModule = rangy.modules.CssClassApplier; 2724 return fn(); 2725 } 2726}; 2727 2728$.fn.rangy = function(fn) { 2729 var me = $(this); 2730 $.rangySupported(function() { 2731 $document.mouseup(function(e) { 2732 if (me.data('rangyBusy')) return; 2733 2734 var selection = rangy.getSelection(); 2735 var html = selection.toHtml(); 2736 var text = selection.toString(); 2737 2738 if (text.length > 3 && rangy.isUnique(me[0], text)) { 2739 if (fn) 2740 if ($.isFunction(fn)) 2741 fn({ 2742 text: text, 2743 x: e.pageX, 2744 y: e.pageY 2745 }); 2746 } 2747 }); 2748 }); 2749 return this; 2750}; 2751 2752$.fn.rangyRestore = function(phrase, fn) { 2753 var me = $(this); 2754 $.rangySupported(function() { 2755 phrase = rangy.setPhrase(me[0], phrase); 2756
2757 if (fn) 2758 if ($.isFunction(fn)) 2759 fn(phrase); 2760 }); 2761 return this; 2762}; 2763 2764$.fn.rangyRestoreSelection = function(phrase, fn) { 2765 var me = $(this); 2766 $.rangySupported(function() { 2767 phrase = rangy.setPhraseSelection(me[0], phrase); 2768 2769 if (fn) 2770 if ($.isFunction(fn)) 2771 fn(phrase); 2772 }); 2773 return this; 2774}; 2775 2776$.fn.ajaxEditDraw = function(options) { 2777 var me = $(this).attr('href', 'tiki-ajax_services.php'); 2778 2779 //defaults 2780 options = $.extend({ 2781 saved: function() {}, 2782 closed: function() {} 2783 }, options); 2784 2785 $.modal(tr('Loading editor')); 2786 2787 me.serviceDialog({ 2788 title: me.attr('title'), 2789 data: { 2790 controller: 'draw', 2791 action: 'edit', 2792 fileId: me.data('fileid'), 2793 galleryId: me.data('galleryid'), 2794 raw: true 2795 }, 2796 modal: true, 2797 zIndex: 9999, 2798 fullscreen: true, 2799 load: function (data) { 2800 //prevent from happeneing over and over again 2801 if (me.data('drawLoaded')) return false; 2802 2803 me.data('drawLoaded', true); 2804 2805 me.drawing = $('#tiki_draw') 2806 .loadDraw({ 2807 fileId: me.data('fileid'), 2808 galleryId: me.data('galleryid'), 2809 name: me.data('name'), 2810 data: $('#fileData').val() 2811 }) 2812 .bind('savedDraw', function(e, o) { 2813 me.data('drawLoaded', false); 2814 me.drawing.parent().dialog('destroy'); 2815 me.drawing.remove(); 2816 2817 //update the image that did exist in the page with the new one that now exists 2818 var img = $('.pluginImg' + me.data('fileid')).show(); 2819 var w = img.width(), h = img.height(); 2820 2821 if (img.hasClass('regImage')) { 2822 var replacement = $('<div />') 2823 .attr('class', img.attr('class')) 2824 .attr('style', img.attr('style')) 2825 .attr('id', img.attr('id')) 2826 .insertAfter(img); 2827 2828 img.remove(); 2829 img = replacement; 2830 } 2831 2832 $('<div class=\"svgImage\" />') 2833 .load('tiki-download_file.php?fileId=' + o.fileId + '&display', function() { 2834 2835 $(this) 2836 .css('position', 'absolute') 2837 .fadeTo(0, 0.01) 2838 .prependTo('body') 2839 .find('img,svg') 2840 .scaleImg({ 2841 width: w, 2842 height: h 2843 }); 2844 2845 img.html($(this).html()); 2846 2847 $(this).remove(); 2848 }); 2849 2850 if (!options.saved) return; 2851 2852 options.saved(o.fileId); 2853 }) 2854 .submit(function() { 2855 me.drawing.saveDraw(); 2856 return false; 2857 }) 2858 .bind('loadedDraw', function() { 2859 //kill the padding around the dialog so it looks like svg-edit is one single box 2860 me.drawing 2861 .parent() 2862 .css('padding', '0px'); 2863 2864 var serviceDialog = me.data('serviceDialog'); 2865 if (serviceDialog) { 2866 var drawFrame = $('#svgedit'); 2867 serviceDialog 2868 .bind('dialogresize', function() { 2869 drawFrame.height(serviceDialog.height() - 4); 2870 }) 2871 .trigger('dialogresize'); 2872 } 2873 2874 $.modal(); 2875 }); 2876 2877 me.drawing.find('#drawMenu').remove(); 2878 }, 2879 close: function() { 2880 if (me.data('drawLoaded')) { 2881 me.data('drawLoaded', false); 2882 me.drawing.remove(); 2883 2884 if (!options.closed) return; 2885 options.closed(me); 2886 } 2887 } 2888 }); 2889 2890 return false; 2891}; 2892 2893$.notify = function(msg, settings) { 2894 settings = $.extend({ 2895 speed: 10000 2896 },settings); 2897 2898 var notify = $('#notify'); 2899 2900 if (!notify.length) { 2901 notify = $('<div id="notify" />') 2902 .css('top', '5px') 2903 .css('right', '5px') 2904 .css('position', 'fixed') 2905 .css('z-index', 9999999) 2906 .css('padding', '5px') 2907 .width($window.width() / 5) 2908 .prependTo('body'); 2909 } 2910 2911 var note = $('<div class="notify ui-state-error ui-corner-all ui-widget ui-widget-content" />') 2912 .append(msg) 2913 .css('padding', '5px') 2914 .css('margin', '5px') 2915 .mousedown(function() { 2916 return false; 2917 }) 2918 .hover(function() { 2919 $(this) 2920 .stop() 2921 .fadeTo(500, 0.3) 2922 }, function() { 2923 $(this) 2924 .stop() 2925 .fadeTo(500, 1) 2926 }) 2927 .prependTo(notify); 2928 2929 setTimeout(function() { 2930 note 2931 .fadeOut() 2932 .slideUp(); 2933 2934 //added outside of fadeOut to ensure removal 2935 setTimeout(function() { 2936 note.remove(); 2937 }, 1000); 2938 2939 }, settings.speed); 2940}; 2941 2942/** 2943* Close (user) sidebar column(s) if no modules are displayed. 2944* Modules can be hidden at runtime. So, check after the page/DOM model is loaded. 2945*/ 2946$(function () { 2947 2948 // Do final client side adjustment of the sidebars
2949 ///////////////////////////////////////// 2950 var maincol = 'col1'; 2951 2952 // Hide left side panel, if no modules are displayed 2953 var left_mods = document.getElementById('left_modules'); 2954 if (left_mods != null) { 2955 if (isEmptyText(left_mods.innerHTML)) { 2956 var col = document.getElementById('col2'); 2957 if (col != null) { 2958 col.style.display = "none" 2959 } 2960 document.getElementById(maincol).style.marginLeft = '0'; 2961 2962 var toggle = document.getElementById("showhide_left_column") 2963 if (toggle != null) { 2964 toggle.style.display = "none"; 2965 } 2966 } 2967 } 2968 2969 // Hide right side panel, if no modules are displayed 2970 var right_mods = document.getElementById('right_modules'); 2971 if (right_mods != null) { 2972 2973 // alert("right_mods.innerHTML=" + right_mods.innerHTML); 2974 //alert("right_mods.innerText=" + right_mods.innerText); 2975 2976 if (isEmptyText(right_mods.innerHTML)) { 2977 var col = document.getElementById('col3'); 2978 if (col != null) { 2979 col.style.display = "none" 2980 } 2981 document.getElementById(maincol).style.marginRight = '0'; 2982 2983 var toggle = document.getElementById("showhide_right_column") 2984 if (toggle != null) { 2985 toggle.style.display = "none"; 2986 } 2987 } 2988 } 2989 2990 // FF does not support obj.innerText. So, analyze innerHTML, which all browsers seem to support 2991 function isEmptyText(html) { 2992 2993 // Strip HTML tags
2994 ///////////////////////// 2995 var strInputCode = html; 2996 2997 // Replace coded-< with <, and coded-> with > 2998 strInputCode = strInputCode.replace(/&(lt|gt);/g, function (strMatch, p1) { 2999 return (p1 == "lt") ? "<" : ">"; 3000 }); 3001 // Strip tags 3002 var strTagStrippedText = strInputCode.replace(/<\/?[^>]+(>|$)/g, ""); 3003 3004 // Trim whitespace 3005 var text = strTagStrippedText.replace(/^\s+|\s+$/g, ""); 3006 3007 return text == null || text.length == 0; 3008 } 3009}); 3010 3011$.trackerForm = function (trackerId, itemId, remove) { 3012 if (itemId && !remove) { 3013 return $('<form id="editItemForm" method="get" action="tiki-view_tracker_item.php" enctype="multipart/form-data" novalidate="novalidate" />') 3014 .append('<input type="hidden" name="trackerId" value="' + trackerId + '" />') 3015 .append('<input type="hidden" name="itemId" value="' + itemId + '" />') 3016 .append('<input type="hidden" name="save" value="Save" />'); 3017 } else if (!remove) { 3018 return $('<form id="newItemForm" method="get" action="tiki-view_tracker.php" enctype="multipart/form-data" novalidate="novalidate" />') 3019 .append('<input type="hidden" name="trackerId" value="' + trackerId + '" />') 3020 .append('<input type="hidden" name="save" value="Save" />') 3021 .append('<input type="hidden" name="viewitem" value="new" />'); 3022 } else { 3023 return $('<form id="deleteItemForm" method="get" action="tiki-view_tracker.php" enctype="multipart/form-data" novalidate="novalidate" />') 3024 .append('<input type="hidden" name="trackerId" value="' + trackerId + '" />') 3025 .append('<input type="hidden" name="remove" value="' + itemId + '" />') 3026 .append('<input type="hidden" name="force" value="y" />'); 3027 } 3028}; 3029 3030// try and reposition the menu ul within the browser window 3031$.fn.moveToWithinWindow = function() { 3032 var $el = $(this); 3033 h = $el.height(), 3034 w = $el.width(), 3035 o = $el.offset(), 3036 po = $el.parent().offset(), 3037 st = $window.scrollTop(), 3038 sl = $window.scrollLeft(), 3039 wh = $window.height(), 3040 ww = $window.width(); 3041 3042 if (w + o.left > sl + ww) {
3043 $el.animate({'left': sl + ww - w - po.left}, 'fast'); 3044 } 3045 if (h + o.top > st + wh) { 3046 $el.animate({'top': st + wh - (h > wh ? wh : h) - po.top}, 'fast'); 3047 } else if (o.top < st) { 3048 $el.animate({'top': st - po.top}, 'fast'); 3049 } 3050}; 3051 3052$.fn.scaleImg = function (max) { 3053 $(this).each(function() { 3054 //Here we want to make sure that the displayed contents is the right size 3055 var img = $(this), 3056 actual = { 3057 height: img.height(), 3058 width: img.width() 3059 }, 3060 original = $(this).clone(), 3061 parent = img.parent(); 3062 3063 var winner = ''; 3064 3065 if (actual.height > max.height) { 3066 winner = 'height'; 3067 } else if (actual.width > max.width) { 3068 winner = 'width'; 3069 } 3070 3071 //if there is no winner, there is no need to resize 3072 if (winner) { 3073 //we resize both images and svg, we check svg first 3074 var g = img.find('g'); 3075 if (g.length) { 3076 img 3077 .attr('preserveAspectRatio', 'xMinYMin meet'); 3078 3079 parent 3080 .css('overflow', 'hidden') 3081 .width(max.width) 3082 .height(max.height); 3083 3084 g.attr('transform', 'scale( ' + (100 / (actual[winner] / max[winner]) * 0.01) + ' )'); 3085 } else { 3086 //now we resize regular images 3087 if (actual.height > actual.width) { 3088 var h = max.height; 3089 var w = Math.ceil(actual.width / actual.height * max.height); 3090 } else { 3091 var w = max.width; 3092 var h = Math.ceil(actual.height / actual.width * max.width); 3093 } 3094 img.css({ height: h, width: w }); 3095 } 3096 3097 img 3098 .css('cursor', "url(img/icons/zoom.gif),auto") 3099 .click(function () { 3100 $('<div/>').append(original).dialog({ 3101 modal: true, 3102 width: Math.min($(window).width(), actual.width + 20), 3103 height: Math.min($(window).height(), actual.height + 50) 3104 }); 3105 return false; 3106 }); 3107 } 3108 }); 3109 3110 return this; 3111};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.