1/* This file is part of cbui. 2 * Copyright © 2010-2012 stiftung kulturserver.de ggmbh <[email protected]> 3 * 4 * cbui is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * cbui is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with cbui. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18/** 19 * a frame where widgets can be grouped. It introduces a new event "change" which 20 * is triggered whenever a child widget is either shown or hidden and on "ready". 21 * Frames support fading in and out slowly via additional parameters for show() 22 * and hide(). They can also slide up and down in the same way. 23 */ 24jQuery.CbWidget.frame = jQuery.CbWidget.widget.extend({ 25 /** 26 * show the frame, using an optional delay (in milliseconds) 27 * @param options optional parameters containing "delay" 28 * @return this 29 */ 30 handleShow:function (options) { 31 var self = this, 32 base = this.base; 33 34 options = options || {delay:0}; 35 36 this.element().fadeIn(options.delay, function () { 37 // jQuery tends to stop at an unprecise value (like 0.98423421 instead 38 // of 1.0), which can cause problems with certain contents of this 39 // element. 40 self.element().css('opacity', 1.0); 41 42 base.call(self, options); 43 }); 44 45 return this; 46 }, 47 /** 48 * hide the frame, using an optional delay (in milliseconds) 49 * @param options optional parameters containing "delay" 50 * @return this 51 */ 52 handleHide:function (options) { 53 var self = this, 54 base = this.base; // base may change due to other functions being executed in between 55 56 options = options || {delay:0}; 57 58 this.element().fadeOut(options.delay, function () { 59 // jQuery tends to stop at an unprecise value (like 0.98423421 instead 60 // of 1.0), which can cause problems with certain contents of this 61 // element. 62 self.element().css('opacity', 0.0); 63 64 base.call(self, options); 65 }); 66 67 return this; 68 }, 69 /** 70 * slide up the element, using the delay. Will trigger "hide" 71 * @param delay the time to be taken for sliding the widget up 72 * @return this 73 */ 74 slideUp:function (delay) { 75 var self = this; 76 this.element().slideUp(delay, function () { 77 self.hide(); 78 }); 79 return this; 80 }, 81 /** 82 * slide down the element, using the delay. Will trigger "show" 83 * @param delay the time to be taken for sliding the widget down 84 * @return this 85 */ 86 slideDown:function (delay) { 87 var self = this; 88 this.element().slideDown(delay, function () { 89 self.show(); 90 }); 91 return this; 92 }, 93 constructor:function (element) { 94 this.base(element); 95 var title = this.element().attr('title'); 96 if (title) 97 this.texts.title = title; 98 var self = this; 99 this.throwChange = function () { 100 self.change(); 101 }; 102 103 /* Binding the change event when ready. 104 * This is not done by handleReady as you may wish to override the 105 * configuration for various widgets on a per-window base. Binding the 106 * change event, however is so universal that we make it mandatory for 107 * all frames. Of course you can unbind it from window.handleLoad if you 108 * know what you're doing. 109 */ 110 this.ready(function () { 111 self.bindChange(); 112 }); 113 }, 114 changeLanguage:function (bricks) { 115 this.base(bricks); 116 if (this.texts.title) { 117 this.element().attr('title', bricks[this.texts.title]); 118 } 119 // changing the language is a change as the sizes of texts may have changed 120 return this.change(); 121 }, 122 /** 123 * bind the "change" event of the frame to all "show" and "hide" 124 * events of its inner widgets so that we have a chance to auto
124position 125 * the frame (or do other interesting things) when its widgets change. 126 * 127 * This doesn't work for adding or removing widgets as we have no way 128 * of finding out about that. You'll have to call this method manually when 129 * doing that in order to bind the new widgets' events. 130 */ 131 bindChange:function () { 132 var self = this; 133 jQuery('[class*="__CbUi"]', this.element()).each(function () { 134 var widget = jQuery(this).CbWidget(); 135 if (widget) { 136 widget.unbind('show', self.throwChange); 137 widget.unbind('hide', self.throwChange); 138 widget.show(self.throwChange); 139 widget.hide(self.throwChange); 140 } 141 }); 142 return this.change(); // being ready is also a change, but it happens only once 143 } 144}, { 145 init:function () { 146 /* 147 * "change" is triggered when the widget or some subwidget has changed its appearance 148 * In this case the layout may have to be recalculated. 149 */ 150 jQuery.CbEvent(this, 'change'); 151 return this.base(); 152 } 153 154}); 155 156/** 157 * Base class for all kinds of "window-like" things. Windows are supposed to be 158 * contained in a DOM element (the "frame") and may have various widgets whose 159 * life cycles are managed by the window. When calling open() window's structure 160 * is loaded from a 'template' using AJAX. After that it's widgets and 161 * validators are instantiated. Before and after that hooks are called to allow 162 * for customization in derived classes. 163 * 164 * In order for this to work you need to include: 165 * - jquery.js 166 * - base2.js 167 * - cbShadow.js (if the shadow feature is to be used) 168 * - cb_ui/validate.js (if there are any validated input fields) 169 * - cb_ui/widget.js (if there are any widgets in the window) 170 * - some styles for __CbUi* - otherwise it'll look strange 171 * 172 * TODO: refactor to get more convenient smaller classes 173 */ 174jQuery.CbWidget.window = jQuery.CbWidget.frame.extend({ 175 /** 176 * create a window. 177 * @param loadOptions Options for loading the template: 178 * - element the frame for the window. Can be omitted, then a new one is 179 * created and appended to <body>. 180 * - template a URL to load the structure from 181 * - postParams POST parameters to be passed when loading the template 182 * @param options Options you might want to refer to later. The base window uses: 183 * - 'width' and 'height': to determine its initial dimensions. 184 * - 'layerFrame': if set, have the window floating on top of existing content, 185 * otherwise just append it to <body>. 186 * - 'modal': if set, put a semi-transparent layer over the whole document 187 * before adding the window - prevents any interaction with other elements 188 * - 'layerColor' and 'layerOpacity': properties of the modal layer 189 * - 'overlayClose': if set, close the window when clicking on the modal layer or pressing escape 190 * - 'showShadow': create a shadow for the window if possible 191 * Obviously some combinations don't make sense. Results for those are undefined. 192 */ 193 constructor:function (loadOptions, options) { 194 195 this.options = jQuery.extend({template:'/module/jscript/lib/cb_ui/templates/cb_ui_window.html', cls:'__CbUiWindow'}, jQuery.CbWidget.window.defaultOptions, options); 196 197 var element = loadOptions.element; 198 var elCls = "__CbUiFrame "; 199 if (loadOptions.cls !== undefined) 200 elCls += loadOptions.cls; 201 if (!element) { 202 // any falsy value is accepted as "create automatically". In some 203 // circumstances we get null, in others undefined. Both make sense. 204 element = jQuery(document.createElement('div')).addClass(elCls); 205 jQuery(document.createElement('div')).appendTo(element); 206 this.insertElement = loadOptions.insertElement !== undefined ? loadOptions.insertElement : true; 207 } 208 209 this.base(element); 210 this.template = loadOptions.template; 211 this.postParams = loadOptions.postParams; 212 this.zoom = false; 213 this.viewState = 'tiles'; 214 return this; 215 }, 216 /** 217 * Open the window. 218 * @param params if contains "delay" which is set to > 0 the window will fade in slowly in <delay> milliseconds. 219 */ 220 open:function (params, callback) { 221 var options = jQuery.extend({}, this.options, params); 222 var self = this; 223 if (options.modal) { 224 var layer = jQuery(document.createElement('div')).addClass('__CbUiLayer'); 225 226 //if there is a modal layer already, make all additional layers transparent 227 228 //special check for displayed editor elements in older implementations 229 var noEditorsDisplayed = true; 230 var editors = jQuery('.page-edit'); 231 for (var i = 0;i < editors.length;i++) { 232 if (editors[i].offsetWidth != 0 && $(editors[i]).css('visibility') != 'hidden') { 233 noEditorsDisplayed = false;
234 break; 235 } 236 } 237 ; 238 var opacity = jQuery('.__CbUiLayer:not(.__CbUiLoader)').length == 0 && noEditorsDisplayed ? options.layerOpacity : 0; 239 240 layer.appendTo('body').fadeTo(options.delay, options.layerOpacity, function () { 241 try { 242 self.layer = jQuery(layer).css({ 243 'background-color':self.options.layerColor, 244 // jQuery tends to stop at an unprecise value (like 0.98423421 245 // instead of 1.0), which can cause problems with certain 246 // contents of this element. 247 'opacity':opacity 248 }); 249 250 if (options.overlayClose) { 251 self.layer.click(function () { 252 self.close(true); 253 }); 254 } 255 256 self.loadFrame(options, callback); 257 } catch (err) { 258 /* ignore to avoid fading loop created by jquery not being able 259 * to finish its work after calling the callback. 260 */ 261 } 262 }); 263 } else { 264 this.loadFrame(options, callback); 265 } 266 267 return this; 268 }, 269 /** 270 * Close the window and destroy all its widgets. 271 * @param params if contains "delay" which is set to > 0 the window will fade out slowly in <delay> milliseconds. 272 */ 273 close:function (params) { 274 var options = jQuery.extend({}, params || {}, this.options); 275 var self = this; 276 277 if (options.modal) { 278 self.layer.fadeOut(options.delay); 279 } 280 281 this.hide(function () { 282 self.destroy(); 283 }); 284 285 if (typeof options.onClose === 'function') 286 options.onClose(); 287 return this.trigger('hide', options); 288 }, 289 /** 290 * immediately destroy everything without any fading 291 */ 292 handleDestroy:function () { 293 var self = this; 294 jQuery(window).unbind('resize.window' + this.base2ID); 295 296 jQuery('[class*="__CbUi"]', this.element()).each(function () { 297 var widget = jQuery(this).CbWidget(); 298 if (widget && widget != self) { 299 widget.destroy(); 300 } 301 }); 302 303 if (this.options.modal) 304 this.layer.remove(); 305 306 if (this.insertElement) 307 this.element().remove(); 308 309 return this.base(); 310 }, 311 /** 312 * Validate all validatable widgets in the window (those with a class __CbValidate*). 313 */ 314 validateInput:function () { 315 var valid = true; 316 var self = this; 317 jQuery('[class*="__CbValidate"]', this.element()).each(function () { 318 if (!jQuery(this).CbWidget().isValidationSuspended()) { 319 var widget_valid = jQuery(this).CbWidget().validate(); 320 if (!widget_valid) { 321 self.trigger('error', {element:this}); 322 valid = false; 323 } 324 } 325 }); 326 if (valid) 327 self.valid(); 328 return valid; 329 }, 330 /** 331 * Passes the ready event and the configuration options on to all 332 * child widgets. It's recommended to use this for final configuration 333 * as it happens after the widgets have been instantiated and translated, 334 * but before the window is shown.
335 * @param options The options to be used for configuration. Those are 336 * the ones passed to the constructor and open(). 337 */ 338 handleReady:function (options) { 339 var self = this; 340 jQuery('[class*="__CbUi"]', this.element()).each(function () { 341 var widget = jQuery(this).CbWidget(); 342 if (widget && widget != self) 343 widget.trigger('ready', options); 344 }); 345 346 if ($('.fullscreen-switch').length) { 347 if (self.zoom) 348 self.doZoom(self); 349 $('.fullscreen-switch').on('click', function () { 350 self.setZoom(self, options); 351 }); 352 } 353 354 return this.base(); 355 }, 356 setSupportButton:function (options) { 357 if (options.hideSupport) 358 $('.main-navi .support').hide(); 359 }, 360 //set the corresponding support context as the support button link 361 setSupportLink:function (options) { 362 if (options.supportUrl) { 363 $('.main-navi .support').attr('href', options.supportUrl); 364 } 365 }, 366 /** 367 * called after loading the frame. This method is considered private. 368 * @param options the options for loading the window. Will be passed on to 369 * show and close and will be used to determine if the shadow is to be shown. 370 * @param callback Function to be called when done. 371 */ 372 postLoadFrame:function (options, callback) { 373 374 if (this.insertElement) { 375 this.element().appendTo('body'); 376 } 377 378 if (options.layerFrame) { 379 // Let css handle the size if we want a reponsive window 380 if (!options.responsive) { 381 // Style changes are more reliable when applied after an element has 382 // been appended to the DOM. 383 this.element().height(options.height); 384 this.element().width(options.width); 385 } 386 387 } 388 389 this.refreshElement(); 390 391 if (options.showShadow) { 392 addShadow(this.element()); 393 } 394 this.load(); 395 var self = this; 396 var hidden = this.element().find('.__CbUiHiddenTemplates').remove(); 397 jQuery.CbWidgetRegistry.apply(this.element(), function () { 398 if (hidden) 399 self.element().append(hidden); // don't apply widgets to hidden templates 400 self.trigger('show', options); 401 self.trigger('ready', options); 402 403 if (options.overlayClose) { 404 self.element().keypress(function (key) { 405 if (key.keyCode == 27) 406 self.close(options); 407 }); 408 } 409 if (callback !== undefined) 410 callback(); 411 }); 412 413 //insert the window caption into the frame header 414 if (options.windowCaption) { 415 $('.window-caption').text(options.windowCaption); 416 } else { 417 $('.window-caption').hide(); 418 } 419 420 return this; 421 }, 422 /** 423 * called by open(); loads the structure and instantiates the widgets. 424 * Don't call it from outside. Use open() and close(). 425 */ 426 loadFrame:function (options, callback) { 427 428 var self = this; 429 if (options.layerFrame) 430 this.element().addClass('__CbUiLayerFrame'); 431 this.element().hide(); // don't fire the event here 432 433 // load and generate global cbui window with content div, that will hold specific content 434 var $inner = $(this.element().children().eq(0)); 435 436 // if avoidFrame flag is not set and we have a base + inner template defined, 437 // place the content in this element within a CbUiFrame 438 if (!options.avoidFrame && options.template && self.template) { 439 loadContent($inner, options.template, function () { 440 loadContent($(self.element().find('.__CbUiContent')), self.template); 441 }); 442 } else { 443 loadContent($(self.element()), self.template); 444 } 445 446 function loadContent(el, tpl, clbk) { 447 if (el && tpl) { 448 clbk = typeof clbk === 'function' ? clbk : function () { 449 $(document).ready(function () { 450 self.postLoadFrame(options, callback); 451 }) 452 }; 453 el.load(tpl, self.postParams ? self.postParams : null, clbk); 454 } else { 455 self.postLoadFrame(options, callback); 456 } 457 } 458 ; 459 return self; 460 }, 461 /** 462 * center the widget in horizontal direction. 463 * @return this 464 */ 465 centerX:function () { 466 this.moveToX(Math.max(Math.floor(jQuery(window).width() / 2 - this.width() / 2), 0)); 467 return this; 468 }, 469 /** 470 * center the widget in vertical direction. 471 * @return this 472 */ 473 centerY:function () { 474 this.moveToY(Math.max(Math.floor(jQuery(window).height() / 2 - this.height() / 2), 0)); 475 return this; 476 }, 477 /** 478 * center the widget in both directions. 479 * @return this 480 */ 481 center:function () { 482 this.centerX(); 483 this.centerY(); 484 return this; 485 }, 486 /** 487 * automatically position the window with the given method when 488 * a, "change" is triggered 489 * b, the browser window is resized 490 * @param method the method to be called to position the window 491 * @param params the parameters to be passed to the positioning method 492 * @return this 493 */ 494 autoposition:function (method, params) { 495 var self = this; 496 this.change(function () { 497 self[method](params); 498 });
499 jQuery(window).bind('resize.window' + this.base2ID, function () { 500 self[method](params); 501 }); 502 return this; 503 }, 504 /** 505 * automatically center in horizontal direction on change 506 * @return this 507 */ 508 autocenterX:function () { 509 return this.autoposition('centerX'); 510 }, 511 /** 512 * automatically center in vertical direction on change 513 * @return this 514 */ 515 autocenterY:function () { 516 return this.autoposition('centerY'); 517 }, 518 /** 519 * automatically center in both directions on change 520 * @return this 521 */ 522 autocenter:function () { 523 return this.autoposition('center'); 524 }, 525 /** 526 * if no explicit height given: 527 * resize the window to fit its content in vertical direction. 528 */ 529 resizeY:function (y) { 530 if (y !== undefined) 531 return this.base(y); 532 var height = (this.element().children()[0]).clientHeight; 533 this.element().height(height); 534 return this; 535 }, 536 /** 537 * if no explicit width given: 538 * resize the window to fit its content in horizontal direction. 539 */ 540 resizeX:function (x) { 541 if (x !== undefined) 542 return this.base(x); 543 var width = this.element().children()[0].clientWidth; 544 this.element().width(width); 545 return this; 546 }, 547 /** 548 * automatically resize to fit in vertical direction on change 549 * @return this 550 */ 551 autoresizeY:function () { 552 return this.autoposition('resizeY'); 553 }, 554 /** 555 * automatically resize to fit in horizontal direction on change 556 * @return this 557 */ 558 autoresizeX:function () { 559 return this.autoposition('resizeX'); 560 }, 561 /** 562 * automatically resize to fit in both directions on change 563 * @return this 564 */ 565 autoresize:function () { 566 return this.autoposition('resize'); 567 }, 568 /** 569 * call zoom function corresponding to current zoom state 570 */ 571 setZoom:function (self, options) { 572 if (self.zoom) { 573 self.undoZoom(self, options); 574 } else { 575 self.doZoom(self); 576 } 577 }, 578 /** 579 * zoom to fullscreen 580 */ 581 doZoom:function (self) { 582 $('div.__CbUiFrame').addClass('fullscreen'); 583 $('.__CbUiContent').css({'width':'98%', 'max-width':'98%'}); 584 $('.__CbUiFrame').css({'top':0, 'left':0, 'width':'100%', 'height':'100%'}); 585 $('.__CbUiHeader').css({'display':'none'}); 586 $('.pix-form-content-container').height($('.__CbUiFrame').height() - 45); 587 var scrollBarHeightReduction = $('.select-bar').height() ? 196 : 160; 588 $('.pix-scrollbar-container, .pix-viewport').height($('.__CbUiFrame').height() - scrollBarHeightReduction); 589 self.zoom = true; 590 }, 591 /** 592 * unzoom to standard window 593 */ 594 undoZoom:function (self, options) { 595 $('div.__CbUiFrame').removeClass('fullscreen'); 596 $('.__CbUiContent').css({'width':'', 'max-width':''}); 597 $('.__CbUiFrame').css({'top':Math.max(0, (window.innerHeight - options.height) / 2), 'left':(window.innerWidth - options.width) / 2 + 'px', 'width':options.width + 'px', 'height':options.height + 'px'}); 598 $('.__CbUiHeader').css({'display':'block'}); 599 $('.pix-form-content-container').height(530); 600 var scrollBarHeight = $('.select-bar').height() ? 379 : 415; 601 $('.pix-scrollbar-container, .pix-viewport').height(scrollBarHeight); 602 self.zoom = false; 603 } 604}, { 605 init:function () { 606 /** 607 * load is called after the template has been loaded, but before 608 * the widgets are initialized. 609 */ 610 jQuery.CbEvent(this, 'load'); 611 612 /** 613 * error is called when a widget cannot be validated. 614 */ 615 jQuery.CbEvent(this, 'error'); 616 617 /** 618 * called when all widgets have passed validation. 619 */ 620 jQuery.CbEvent(this, 'valid'); 621 this.base(); 622 }, 623 /** 624 * Handle a click on an element <button> as follows: 625 * 1. if we're already handling a previous click call 626 * <alreadyHandlingCallback>. 627 * 2. Try to validate <subject>, either with validate() or validateInput(). 628 * This can be a window or a single widget. 629 * 3. If valid add <submitClass> to <button> and call <callback>, 630 * else call <invalidCallback> 631 * All callbacks are called in the same scope and with the same arguments as 632 * the button.click(), but adding, as a last argument a function that, if 633 * called: 634 * a, removes <submitClass> from the button
635 * b, resets the "handling" state so that 1. won't call 636 * <alreadyHandlingCallback> anymore. 637 * 638 * This is the recommended way to submit data. If you do it with a primitive 639 * click handler the user may click twice, submitting the data twice which 640 * may lead to unexpected results. 641 */ 642 onceOnClickIfValid:function (button, subject, callback, invalidCallback, 643 alreadyHandlingCallback, submitClass) { 644 var handling = false; 645 console.log(button); 646 button.click(function () { 647 console.log('click'); 648 var args = [].concat.apply([], arguments); 649 args.push(function () { 650 handling = false; 651 button.removeClass(submitClass); 652 }); 653 if (!handling) { 654 console.log('not handling'); 655 if ((typeof subject.validateInput === 'function' && subject.validateInput()) || 656 (typeof subject.validate === 'function' && subject.validate())) { 657 handling = true; 658 button.addClass(submitClass); 659 callback.apply(this, args); 660 console.log('all fine'); 661 } else if (invalidCallback !== undefined) { 662 console.log('invalid callback'); 663 invalidCallback.apply(this, args); 664 } 665 } else if (alreadyHandlingCallback !== undefined) { 666 console.log('alreadyHandlingCallback'); 667 alreadyHandlingCallback.apply(this, args); 668 } 669 }); 670 }, 671 defaultOptions:{ 672 'showShadow':false, 673 'modal':true, 674 'layerColor':'#000000', 675 'layerFrame':true, 676 'layerOpacity':0.25, 677 'overlayClose':false, 678 'width':680, 679 'height':590, 680 'delay':0, 681 'supportUrl':'/support/', //TODO: set real general support url 682 'hideSupport':false, 683 'responsive':false, 684 'avoidFrame':false 685 } 686}); 687 688/** 689 * Language choice window. Will call jQuery.CbWidgetRegistry.changeLanguage 690 * when an option is clicked. 691 */ 692jQuery.CbWidget.language_window = jQuery.CbWidget.window.extend({ 693 constructor:function (loadOptions, options) { 694 this.base(jQuery.extend({ 695 template:'/module/jscript/lib/cb_ui/templates/language_window.html', 696 cls:'__CbUiLanguageWindow' 697 }, loadOptions), jQuery.extend({ 698 modal:true // not modal by default as it's expected to be placed on top of another modal window 699 }, options)); 700 this.options.supportUrl = '/support/language'; 701 return this.autocenter(); 702 }, 703 open:function (params, callback) { 704 jQuery.CbWidgetRegistry.retrofitProjects(); 705 var self = this; 706 var base = this.base; 707 jQuery.getJSON('/module/lib/framework/getMlLanguages.php', { 708 projects:jQuery.CbWidgetRegistry.projects 709 }, function (data) { 710 self.languages = data; 711 base.call(self, params, typeof callback == 'function' ? callback : function () { 712 }); 713 }); 714 return this; 715 }, 716 handleLoad:function (params) { 717 var list = this.element().find('.__CbUiLangChooseList'); 718 jQuery.each(this.languages, function (i, language) { 719 // For reference purposes, langChooseList is defined in button.js 720 jQuery.CbWidget.langChooseList.addOption(list, language.locale, language.name, language.id); 721 }); 722 return this.base(params); 723 }, 724 handleReady:function (options) { 725 726 this.setSupportLink(options); 727 728 //call parent method and apply current context and options 729 jQuery.CbWidget.window.prototype.handleReady.call(this, options); 730 731 } 732 733}); 734 735/** 736 * Text window, holds cbml translation texts 737 * and is able to translate CbUi based templates on the fly. 738 * @type @exp;jQuery@pro;CbWidget@pro;window@call;extend 739 */ 740jQuery.CbWidget.text_window = jQuery.CbWidget.window.extend({ 741 constructor:function (loadOptions, options, texts) { 742 this.base(jQuery.extend({'cls':'__CbUiTextWindow'}, loadOptions), options); // creates an empty "texts" member 743 if (texts) 744 this.texts = jQuery.extend(this.texts, texts); 745 return this; 746 }, 747 handleReady:function (params) { 748 this.setSupportLink(this.options); 749 }, 750 isTranslatable:function (pattern) { 751 return pattern.substr(0, 3) == 'ml_'; 752 }, 753 getLabels:function () { 754 var labels = []; 755 var self = this; 756 jQuery.each(this.texts, function (label, value) { 757 if (self.isTranslatable(label)) { 758 if (typeof (value) == 'object') { 759 jQuery.merge(labels, value); 760 } else { 761 labels.push(value); 762 } 763 } 764 }); 765 return labels; 766 }, 767 changeLanguage:function (bricks) { 768 this.base(bricks); 769 var self = this; 770 var indices = {}; 771 if (self.texts) { 772 var doReplace = function (method, el) { 773 jQuery.each(self.texts, function (pattern, replacement) { 774 if (replacement != null && typeof (replacement) == 'object') { 775 if (!indices[pattern]) 776 indices[pattern] = 0; 777 var regex = new RegExp('{' + pattern.toUpperCase() + '}'); 778 do { 779 var val = replacement[indices[pattern]]; 780 var oldtext = el[method](); 781 var newtext = oldtext.replace(regex, 782 self.isTranslatable(pattern) ? bricks[val] : val); 783 el[method](newtext); 784 } while (oldtext != newtext && replacement.length > ++indices[pattern]); 785 } else { 786 replacement = replacement ? replacement : ''; 787 el[method](el[method]().replace( 788 new RegExp('{' + pattern.toUpperCase() + '}', 'g'), 789 self.isTranslatable(pattern) ? bricks[replacement] : replacement)); 790 } 791 }); 792 } 793 794 self.element().find('.__CbUiReplaceText, .__CbUiReplaceHtml, .__CbUiReplaceVal').each(function () { 795 var el = jQuery(this); 796 if (el.hasClass('__CbUiReplaceText')) { 797 doReplace('text', el); 798 } else if (el.hasClass('__CbUiReplaceHtml')) { 799 doReplace('html', el); 800 } else if (el.hasClass('__CbUiReplaceVal')) { 801 doReplace('val', el); 802 } 803 }); 804 } 805 return this; 806 } 807 808}
808); 809 810/** 811 * Dialogue window. 812 * @type @exp;jQuery@pro;CbWidget@pro;text_window@call;extend 813 */ 814jQuery.CbWidget.dialogue_window = jQuery.CbWidget.text_window.extend({ 815 constructor:function (loadOptions, options, data) { 816 this.base(jQuery.extend({ 817 template:false, 818 cls:'__CbUiDialogWindow' 819 }, loadOptions), jQuery.extend({ 820 id_prefix:'#', 821 modal:true, 822 avoidFrame:true, 823 responsive:true, 824 templateString:'' 825 }, options), data); 826 jQuery.CbWidgetRegistry.projects = options.projects; 827 jQuery.CbWidgetRegistry.language = options.language; 828 this.current_page = this.options.start_page; 829 this.autocenter(); 830 this.options.supportUrl = ''; 831 }, 832 translateTemplateString:function (callback) { 833 var self = this; 834 if (self.options.templateString) { 835 self.element().find('div').html(self.options.templateString); 836 jQuery.CbWidgetRegistry.apply(self.element(), function () { 837 self.element().find('.__CbUiOkButton').off('click.dialogWindow').on('click.dialogWindow', function () { 838 self.handleHide(); 839 }); 840 self.layer.off('.dialogWindow').on('keydown.dialogWindow', function (e) { 841 if (e && e.which === 27) { 842 self.handleHide(); 843 } 844 }); 845 $(self.element()).off('keydown.dialogWindow').on('keydown.dialogWindow', function (e) { 846 if (e && e.which === 27) { 847 self.handleHide(); 848 } 849 }); 850 if (callback) 851 callback(); 852 }); 853 } 854 else { 855 if (callback) 856 callback(); 857 } 858 }, 859 handleHide:function () { 860 this.layer.stop().fadeOut(100, function () { 861 jQuery(this).detach(); 862 }); 863 this.element().detach(); 864 $(window).off('keydown.dialogWindow'); 865 return this; 866 }, 867 handleError:function (error) { 868 var self = this; 869 if (!this.layer) { 870 this.open({delay:0}, function () { 871 self.translateTemplateString(function () { 872 self.handleError(error); 873 }) 874 }); 875 return; 876 } 877 this.layer.appendTo('body').show(); 878 var $el = $(this.element()); 879 var isOpen = $el.is(':visible'); 880 $el.find('.__CbUiOkButton').off('click.dialogWindow').on('click.dialogWindow', function () { 881 self.handleHide(); 882 }); 883 $el.appendTo('body'); 884 $el.show(); 885 $el.find('.error-dialog-login-message-container').hide(); 886 $el.find('.error-dialog-message-container').show(); 887 if (error && error.message) { 888 self.translateTemplateString(); 889 if (isOpen) { 890 $el.find('.error-dialog-error-container').append(error.message).show(); 891 } 892 else { 893 $el.find('.error-dialog-error-container').html(error.message).show(); 894 } 895 } 896 jQuery(window).trigger('resize'); 897 return this; 898 }, 899 handleSessionTimeOut:function () { 900 var self = this; 901 if (!this.layer) { 902 this.open({delay:0}, function () { 903 self.translateTemplateString(function () { 904 self.handleSessionTimeOut(); 905 }) 906 }); 907 return; 908 } 909 var $el = $(this.element()); 910 this.layer.appendTo('body').show(); 911 $el.appendTo('body'); 912 $el.show(); 913 $el.find('.error-dialog-login-message-container').show(); 914 $el.find('.error-dialog-message-container').hide(); 915 $el.find('.error-dialog-error-container').hide(); 916 $el.find('.__CbUiOkButton').off('click.dialogWindow').on('click.dialogWindow', function () { 917 self.handleHide(); 918 }); 919 jQuery(window).trigger('resize'); 920 return this; 921 }, 922 showMessage:function (message, caption, onOKCallback) { 923 var self = this; 924 if (!this.layer) { 925 this.open({delay:0}, function () { 926 self.translateTemplateString(function () { 927 self.showMessage(message, caption, onOKCallback) 928 }) 929 }); 930 return; 931 }
932 var $el = $(this.element()); 933 this.layer.appendTo('body').show(); 934 $el.appendTo('body'); 935 $el.show(); 936 if (caption) { 937 $el.find('.message-dialog-heading').show().html(caption); 938 } 939 else { 940 $el.find('.message-dialog-heading').hide(); 941 } 942 $el.find('.__CbUiOkButton').off('click.dialogWindow').on('click.dialogWindow', function () { 943 if (onOKCallback) 944 onOKCallback(); 945 self.handleHide(); 946 }).show(); 947 $el.find('.message-dialog-message').html(message); 948 $el.find('.__CbUiCancelButton').hide(); 949 jQuery(window).trigger('resize'); 950 self.addEvents(); 951 }, 952 showConfirm:function (caption, message, callback, cancelCallback, okText, cancelText) { 953 var self = this; 954 var $el = $(this.element()); 955 if (!this.layer) { 956 this.open({ 957 delay:0 958 }, function () { 959 self.translateTemplateString(function () { 960 self.showConfirm(caption, message, callback, cancelCallback, okText, cancelText); 961 }); 962 }); 963 return; 964 } 965 self.showMessage(message, caption); 966 $el.find('.__CbUiOkButton') 967 .html(okText ? okText : 'ok') 968 .off('click.dialogWindow') 969 .on('click.dialogWindow', function () { 970 if (callback) 971 callback(); 972 self.handleHide(); 973 }); 974 $el.find('.__CbUiCancelButton') 975 .html(cancelText ? cancelText : 'abbrechen') 976 .off('click.dialogWindow').on('click.dialogWindow', function () { 977 if (cancelCallback) 978 cancelCallback(); 979 self.handleHide(); 980 }).show(); 981 jQuery(window).trigger('resize'); 982 self.addEvents(); 983 }, 984 showStrongConfirm:function (caption, message, callback, cancelCallback, okText, cancelText) { 985 var self = this; 986 var $el = $(this.element()); 987 if (!this.layer) { 988 this.open({ 989 delay:0 990 }, function () { 991 self.translateTemplateString(function () { 992 self.showConfirm(caption, message, callback, cancelCallback, okText, cancelText); 993 }); 994 }); 995 return; 996 } 997 self.showMessage(message, caption); 998 $el.find('.__CbUiOkButton') 999 .html(okText ? okText : 'ok') 1000 .off('click.dialogWindow') 1001 .on('click.dialogWindow', function () { 1002 if (callback) 1003 callback(); 1004 self.handleHide(); 1005 }); 1006 $el.find('.__CbUiCancelButton') 1007 .html(cancelText ? cancelText : 'abbrechen') 1008 .off('click.dialogWindow').on('click.dialogWindow', function () { 1009 if (cancelCallback) 1010 cancelCallback(); 1011 self.handleHide(); 1012 }).show(); 1013 jQuery(window).trigger('resize'); 1014 self.addEvents(); 1015 1016 console.log("#####"); 1017 console.log($el); 1018 }, 1019 prompt:function (caption, message, onOKCallback, defaultValue) { 1020 var self = this; 1021 var $el = $(this.element()); 1022 if (!this.layer) { 1023 this.open({delay:0}, function () { 1024 self.translateTemplateString(function () { 1025 self.prompt(caption, message, onOKCallback, defaultValue) 1026 }) 1027 }); 1028 return; 1029 } 1030 self.layer.appendTo('body').show(); 1031 $el.appendTo('body'); 1032 $el.show(); 1033 self.autocenter(); 1034 if (caption) { 1035 $el.find('.message-dialog-heading').show().html(caption); 1036 } 1037 else { 1038 $el.find('.message-dialog-heading').hide(); 1039 } 1040 $el.find('#CbUiPromptInput').val(defaultValue ? defaultValue : ''); 1041 $el.find('.__CbUiOkButton').off('click.dialogWindow').on('click.dialogWindow', function () { 1042 if (onOKCallback) 1043 onOKCallback($el.find('#CbUiPromptInput').val()); 1044 self.handleHide(); 1045 }).show(); 1046 $el.find('.message-dialog-message').html(message); 1047 $el.find('.__CbUiCancelButton').off('click.dialogWindow').on('click.dialogWindow', function () { 1048 self.handleHide(); 1049 }).show(); 1050 jQuery(window).trigger('resize'); 1051 self.addEvents(); 1052 }, 1053 promptAdditionalContent:function (caption, message, onOKCallback, defaultValue, additionalContent) { 1054 var self = this;
1055 var $el = $(this.element()); 1056 if (!this.layer) { 1057 this.open({delay:0}, function () { 1058 self.translateTemplateString(function () { 1059 self.promptAdditionalContent(caption, message, onOKCallback, defaultValue, additionalContent) 1060 }) 1061 }); 1062 return; 1063 } 1064 self.layer.appendTo('body').show(); 1065 $el.appendTo('body'); 1066 $el.show(); 1067 self.autocenter(); 1068 if (caption) { 1069 $el.find('.message-dialog-heading').show().html(caption); 1070 } 1071 else { 1072 $el.find('.message-dialog-heading').hide(); 1073 } 1074 $el.find('#CbUiPromptInput').val(defaultValue ? defaultValue : ''); 1075 $el.find('.__CbUiOkButton').off('click.dialogWindow').on('click.dialogWindow', function () { 1076 if (onOKCallback) 1077 onOKCallback($el.find('#CbUiPromptInput').val()); 1078 self.handleHide(); 1079 }).show(); 1080 $el.find('.message-dialog-additional-content').html(additionalContent); 1081 $el.find('.message-dialog-message').html(message); 1082 $el.find('.__CbUiCancelButton').off('click.dialogWindow').on('click.dialogWindow', function () { 1083 self.handleHide(); 1084 }).show(); 1085 jQuery(window).trigger('resize'); 1086 self.addEvents(); 1087 }, 1088 addEvents:function () { 1089 var self = this; 1090 var $el = $(this.element()); 1091 $(window).off('keydown.dialogWindow').on('keydown.dialogWindow', function (e) { 1092 if (e && e.which === 27) { 1093 self.handleHide(); 1094 } 1095 if (e && e.which === 13) { 1096 $el.find('.__CbUiOkButton').trigger('click'); 1097 self.handleHide(); 1098 } 1099 }); 1100 }, 1101 appError:function (error) { 1102 this.handleError(error); 1103 } 1104}); 1105 1106/** 1107 * Error window, shows error dialogue. 1108 * @type @exp;jQuery@pro;CbWidget@pro;dialogue_window@call;extend 1109 */ 1110jQuery.CbWidget.error_window = jQuery.CbWidget.dialogue_window.extend({ 1111 constructor:function (loadOptions, options, data) { 1112 this.base(loadOptions, jQuery.extend({ 1113 templateString:'<div class="error-dialog-window">' + 1114 ' <div class="error-dialog-padding error-dialog-heading __CbUiText">error_dialog_heading</div>' + 1115 ' <div class="error-dialog-content">' + 1116 ' <div class="error-dialog-message-container __CbUiText">error_dialog_description</div>' + 1117 ' <div class="error-dialog-login-message-container __CbUiText">an_session_timeout_error_occurred</div>' + 1118 ' <div class="error-dialog-error-container __CbUiText"></div>' + 1119 ' <div class="error-abort-container"><a class="__CbUiOkButton __CbUiTextButton __CbUiText">_ok</a></div>' + 1120 ' </div>' + 1121 '</div>' 1122 }, options), data); 1123 } 1124}); 1125 1126/** 1127 * Message window, shows message dialogue. 1128 * @type @exp;jQuery@pro;CbWidget@pro;dialogue_window@call;extend 1129 */ 1130jQuery.CbWidget.message_window = jQuery.CbWidget.dialogue_window.extend({ 1131 constructor:function (loadOptions, options, data) { 1132 this.base(loadOptions, jQuery.extend({ 1133 templateString:'<div class="message-dialog-window">' + 1134 ' <div class="message-dialog-padding message-dialog-heading __CbUiText">message_heading</div>' + 1135 ' <div class="message-dialog-content">' + 1136 ' <div class="message-dialog-message __CbUiText">message_text</div>' + 1137 ' <div class="message-abort-container">' + 1138 '<a class="__CbUiCancelButton __CbUiTextButton __CbUiText">_cancel</a>' + 1139 '<a class="__CbUiOkButton __CbUiTextButton __CbUiText">_ok</a></div>' + 1140 ' </div>' + 1141 '</div>' 1142 }, options), data); 1143 } 1144}); 1145 1146/** 1147 * Prompt window, shows prompt dialogue. 1148 * @type @exp;jQuery@pro;CbWidget@pro;dialogue_window@call;extend 1149 */ 1150jQuery.CbWidget.prompt_window = jQuery.CbWidget.dialogue_window.extend({ 1151 constructor:function (loadOptions, options, data) { 1152 this.base(loadOptions, jQuery.extend({ 1153 templateString:'<div class="message-dialog-window">' + 1154 ' <div class="message-dialog-padding message-dialog-heading __CbUiText">cbui_prompt_heading</div>' + 1155 ' <div class="message-dialog-content">' + 1156 ' <div class="message-dialog-message __CbUiText">cbui_prompt_message</div>' + 1157 ' <div class="message-dialog-input">' + 1158 '<input class="__CbUiInput" placeholder="cbui_prompt_placeholder" type="text" name="CbUiPromptInput" id="CbUiPromptInput" autofocus></div>' + 1159 ' <div class="message-abort-container">' + 1160 '<a class="__CbUiCancelButton __CbUiTextButton __CbUiText">_cancel</a>' + 1161 '<a class="__CbUiOkButton __CbUiTextButton __CbUiText">_ok</a></div>' + 1162 ' </div>' + 1163 '</div>' 1164 }, options), data); 1165 } 1166});
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.