PageSourceSearch

https://kulturportal.de/module/jscript/lib/cb_ui/window.js

js kulturportal.de collected 2026-09-24 22:22:55 UTC 41,553 bytes, 1,166 lines download raw bytes

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.