1 function Panel(panelWrap) {
 
   5     self.contentDiv = $('.panel-content', panelWrap);
 
   6     self.instanceId = Math.ceil(Math.random() * 1000000000);
 
   7     $.log('new panel - wrap: ', self.wrap);
 
   9     $(document).bind('panel:unload.' + self.instanceId,
 
  10         function(event, data) {
 
  11             self.unload(event, data);
 
  14     $(document).bind('panel:contentChanged', function(event, data) {
 
  15         $.log(self, ' got changed event from: ', data);
 
  17             self.otherPanelChanged(event.target);
 
  25 Panel.prototype.callHook = function() {
 
  26     var args = $.makeArray(arguments)
 
  27     var hookName = args.splice(0,1)[0]
 
  28     var noHookAction = args.splice(0,1)[0]
 
  31     $.log('calling hook: ', hookName, 'with args: ', args);
 
  32     if(this.hooks && this.hooks[hookName])
 
  33         result = this.hooks[hookName].apply(this, args);
 
  34     else if (noHookAction instanceof Function)
 
  35         result = noHookAction(args);
 
  39 Panel.prototype.load = function (url) {
 
  40     $.log('preparing xhr load: ', this.wrap);
 
  41     $(document).trigger('panel:unload', this);
 
  43     self.current_url = url;
 
  48         success: function(data, tstat) {
 
  50             $(self.contentDiv).html(data);
 
  51             self.hooks = panel_hooks;
 
  53             self.connectToolbar();
 
  54             self.callHook('load');
 
  55             self.callHook('toolbarResized');
 
  57         error: function(request, textStatus, errorThrown) {
 
  58             $.log('ajax', url, this.target, 'error:', textStatus, errorThrown);
 
  59             $(self.contentDiv).html("<p>Wystapił błąd podczas wczytywania panelu.");
 
  64 Panel.prototype.unload = function(event, data) {
 
  65     $.log('got unload signal', this, ' target: ', data);
 
  68         $.log('unloading', this);
 
  69         $(this.contentDiv).html('');
 
  70         this.callHook('unload');
 
  71         this.hooks = null; // flush the hooks
 
  76 Panel.prototype.refresh = function(event, data) {
 
  79         $.log('hard reload for panel ', self.current_url);
 
  80         self.load(self.current_url);
 
  84     if( this.callHook('refresh', reload) )
 
  85         $('.change-notification', this.wrap).fadeOut();
 
  88 Panel.prototype.otherPanelChanged = function(other) {
 
  89     $.log('panel ', other, ' changed.');
 
  90     if(!this.callHook('dirty'))
 
  91         $('.change-notification', this.wrap).fadeIn();
 
  94 Panel.prototype.markChanged = function () {
 
  95     this.wrap.addClass('changed');
 
  98 Panel.prototype.changed = function () {
 
  99     return this.wrap.hasClass('changed');
 
 102 Panel.prototype.unmarkChanged = function () {
 
 103     this.wrap.removeClass('changed');
 
 106 Panel.prototype.saveInfo = function() {
 
 108     this.callHook('saveInfo', null, saveInfo);
 
 112 Panel.prototype.connectToolbar = function()
 
 117     // check if there is a one
 
 118     var toolbar = $("div.toolbar", this.contentDiv);
 
 119     $.log('Connecting toolbar', toolbar);
 
 120     if(toolbar.length == 0) return;
 
 122     // connect group-switch buttons
 
 123     var group_buttons = $('*.toolbar-tabs-container button', toolbar);
 
 125     $.log('Found groups:', group_buttons);
 
 127     group_buttons.each(function() {
 
 129         var group_name = group.attr('ui:group');
 
 130         $.log('Connecting group: ' + group_name);
 
 132         group.click(function() {
 
 133             // change the active group
 
 134             var active = $("*.toolbar-tabs-container button.active", toolbar);
 
 135             if (active != group) {
 
 136                 active.removeClass('active');                
 
 137                 group.addClass('active');
 
 138                 $(".toolbar-button-groups-container p", toolbar).each(function() {
 
 139                     if ( $(this).attr('ui:group') != group_name) 
 
 144                 self.callHook('toolbarResized');
 
 149     // connect action buttons
 
 150     var action_buttons = $('*.toolbar-button-groups-container button', toolbar);
 
 151     action_buttons.each(function() {
 
 152         var button = $(this);
 
 153         var hk = button.attr('ui:hotkey');
 
 156             var params = $.evalJSON(button.attr('ui:action-params'));
 
 158            $.log('JSON exception in ', button, ': ', object);
 
 159            button.attr('disabled', 'disabled');
 
 163         var callback = function() {
 
 164             editor.callScriptlet(button.attr('ui:action'), self, params);
 
 168         button.click(callback);
 
 171         if(hk) self.hotkeys[parseInt(hk)] = callback;
 
 174         if (button.attr('ui:tooltip') )
 
 176             var tooltip = button.attr('ui:tooltip');
 
 177             if(hk) tooltip += ' [Alt+'+hk+']';
 
 182                     border: "1px solid #7F7D67",
 
 184                     background: "#FBFBC6",
 
 194 Panel.prototype.hotkeyPressed = function(event)
 
 196     var callback = this.hotkeys[event.keyCode];
 
 197     if(callback) callback();
 
 200 Panel.prototype.isHotkey = function(event) {
 
 201     if( event.altKey && (this.hotkeys[event.keyCode] != null) )
 
 207 Panel.prototype.fireEvent = function(name) {
 
 208     $(document).trigger('panel:'+name, this);
 
 213     this.rootDiv = $('#panels');
 
 214     this.popupQueue = [];
 
 215     this.autosaveTimer = null;
 
 219 Editor.prototype.setupUI = function() {
 
 220     // set up the UI visually and attach callbacks
 
 223     self.rootDiv.makeHorizPanel({}); // TODO: this probably doesn't belong into jQuery
 
 224     // self.rootDiv.css('top', ($('#header').outerHeight() ) + 'px');
 
 226     $('#panels > *.panel-wrap').each(function() {
 
 227         var panelWrap = $(this);
 
 228         $.log('wrap: ', panelWrap);
 
 229         var panel = new Panel(panelWrap);
 
 230         panelWrap.data('ctrl', panel); // attach controllers to wraps
 
 231         panel.load($('.panel-toolbar select', panelWrap).val());
 
 233         $('.panel-toolbar select', panelWrap).change(function() {
 
 234             var url = $(this).val();
 
 235             panelWrap.data('ctrl').load(url);
 
 236             self.savePanelOptions();
 
 239         $('.panel-toolbar button.refresh-button', panelWrap).click(
 
 245     $(document).bind('panel:contentChanged', function() {
 
 246         self.onContentChanged.apply(self, arguments)
 
 249     $('#toolbar-button-save').click( function (event, data) { 
 
 253     $('#toolbar-button-update').click( function (event, data) {
 
 254         if (self.updateUserBranch()) {
 
 255             // commit/update can be called only after proper, save
 
 256             // this means all panels are clean, and will get refreshed
 
 257              // do this only, when there are any changes to local branch
 
 258             self.refreshPanels();
 
 262     $('#toolbar-button-commit').click( function (event, data) { 
 
 263         self.sendPullRequest();
 
 264         event.preventDefault();
 
 265         event.stopPropagation();
 
 268     self.rootDiv.bind('stopResize', function() { 
 
 269         self.savePanelOptions()
 
 273 Editor.prototype.loadConfig = function() {
 
 274     // Load options from cookie
 
 275     var defaultOptions = {
 
 291         var cookie = $.cookie('options');
 
 292         this.options = $.secureEvalJSON(cookie);
 
 294             this.options = defaultOptions;
 
 297         this.options = defaultOptions;
 
 301     this.loadPanelOptions();
 
 304 Editor.prototype.loadPanelOptions = function() {
 
 308     $('.panel-wrap', self.rootDiv).each(function(index) {
 
 309         var panelWidth = self.options.panels[index].ratio * self.rootDiv.width();
 
 310         if ($(this).hasClass('last-panel')) {
 
 320             totalWidth += panelWidth;               
 
 322         $.log('panel:', this, $(this).css('left'));
 
 323         $('.panel-toolbar select', this).val(
 
 324             $('.panel-toolbar option[name=' + self.options.panels[index].name + ']', this).attr('value')
 
 329 Editor.prototype.savePanelOptions = function() {
 
 332     $('.panel-wrap', self.rootDiv).not('.panel-content-overlay').each(function() {
 
 334             name: $('.panel-toolbar option:selected', this).attr('name'),
 
 335             ratio: $(this).width() / self.rootDiv.width()
 
 338     self.options.panels = panels;
 
 339     self.options.lastUpdate = (new Date()).getTime() / 1000;
 
 340     $.log($.toJSON(self.options));
 
 341     $.cookie('options', $.toJSON(self.options), {
 
 347 Editor.prototype.saveToBranch = function(msg) 
 
 349     var changed_panel = $('.panel-wrap.changed');
 
 351     $.log('Saving to local branch - panel:', changed_panel);
 
 353     if(!msg) msg = "Zapis z edytora platformy.";
 
 355     if( changed_panel.length == 0) {
 
 356         $.log('Nothing to save.');
 
 357         return true; /* no changes */
 
 360     if( changed_panel.length > 1) {
 
 361         alert('Błąd: więcej niż jeden panel został zmodyfikowany. Nie można zapisać.');
 
 365     saveInfo = changed_panel.data('ctrl').saveInfo();
 
 368     if(saveInfo.postData instanceof Object)
 
 369         postData = $.param(saveInfo.postData);
 
 371         postData = saveInfo.postData;
 
 373     postData += '&' + $.param({
 
 374         'commit_message': msg
 
 377     self.showPopup('save-waiting', '', -1);
 
 382         success: function(data, textStatus) {
 
 383             if (data.result != 'ok') {
 
 384                 self.showPopup('save-error', (data.errors && data.errors[0]) || 'Nieznany błąd X_X.');
 
 387                 self.refreshPanels();
 
 388                 $('#toolbar-button-save').attr('disabled', 'disabled');
 
 389                 $('#toolbar-button-commit').removeAttr('disabled');
 
 390                 $('#toolbar-button-update').removeAttr('disabled');
 
 391                 if(self.autosaveTimer)
 
 392                     clearTimeout(self.autosaveTimer);
 
 394                 if (data.warnings == null)
 
 395                     self.showPopup('save-successful');
 
 397                     self.showPopup('save-warn', data.warnings[0]);
 
 400             self.advancePopupQueue();
 
 402         error: function(rq, tstat, err) {
 
 403             self.showPopup('save-error', '- bład wewnętrzny serwera.');
 
 404             self.advancePopupQueue();
 
 413 Editor.prototype.autoSave = function() 
 
 415     this.autosaveTimer = null;
 
 416     // first check if there is anything to save
 
 418     this.saveToBranch("Automatyczny zapis z edytora platformy.");
 
 421 Editor.prototype.onContentChanged = function(event, data) {
 
 424     $('#toolbar-button-save').removeAttr('disabled');
 
 425     $('#toolbar-button-commit').attr('disabled', 'disabled');
 
 426     $('#toolbar-button-update').attr('disabled', 'disabled');
 
 428     if(this.autosaveTimer) return;
 
 429     this.autosaveTimer = setTimeout( function() {
 
 434 Editor.prototype.refreshPanels = function() {
 
 437     self.allPanels().each(function() {
 
 438         var panel = $(this).data('ctrl');
 
 439         $.log('Refreshing: ', this, panel);
 
 440         if ( panel.changed() )
 
 441             panel.unmarkChanged();
 
 448 Editor.prototype.updateUserBranch = function() {
 
 449     if( $('.panel-wrap.changed').length != 0)
 
 450         alert("There are unsaved changes - can't update.");
 
 454         url: $('#toolbar-button-update').attr('ui:ajax-action'),
 
 456         success: function(data, textStatus) {
 
 457                 switch(data.result) {
 
 459                         self.showPopup('generic-yes', 'Plik uaktualniony.');
 
 462                     case 'nothing-to-do':
 
 463                         self.showPopup('generic-info', 'Brak zmian do uaktualnienia.');
 
 466                         self.showPopup('generic-error', data.errors && data.errors[0]);
 
 469         error: function(rq, tstat, err) {
 
 470                 self.showPopup('generic-error', 'Błąd serwera: ' + err);
 
 477 Editor.prototype.sendPullRequest = function () {
 
 478     if( $('.panel-wrap.changed').length != 0)        
 
 479         alert("There are unsaved changes - can't commit.");
 
 483     /* this.showPopup('not-implemented'); */
 
 485     $.log('URL !: ', $('#toolbar-commit-form').attr('action'));
 
 488         url: $('#toolbar-commit-form').attr('action'),
 
 490         success: function(data, textStatus) {
 
 491                 switch(data.result) {
 
 493                         self.showPopup('generic-yes', 'Łączenie zmian powiodło się.');
 
 495                         if(data.localmodified)
 
 499                     case 'nothing-to-do':
 
 500                         self.showPopup('generic-info', 'Brak zmian do połaczenia.');
 
 503                         self.showPopup('generic-error', data.errors && data.errors[0]);
 
 506         error: function(rq, tstat, err) {
 
 507                 self.showPopup('generic-error', 'Błąd serwera: ' + err);
 
 510         data: {'message': $('#toolbar-commit-message').val() }
 
 514 Editor.prototype.showPopup = function(name, text, timeout)
 
 516     timeout = timeout || 4000;
 
 518     self.popupQueue.push( [name, text, timeout] )
 
 520     if( self.popupQueue.length > 1) 
 
 523     var box = $('#message-box > #' + name);
 
 524     $('*.data', box).html(text || '');
 
 528         setTimeout( $.fbind(self, self.advancePopupQueue), timeout);
 
 531 Editor.prototype.advancePopupQueue = function() {
 
 533     var elem = this.popupQueue.shift();
 
 535         var box = $('#message-box > #' + elem[0]);
 
 537         box.fadeOut(200, function()
 
 539             $('*.data', box).html();
 
 541             if( self.popupQueue.length > 0) {
 
 542                 var ibox = $('#message-box > #' + self.popupQueue[0][0]);
 
 543                 $('*.data', ibox).html(self.popupQueue[0][1]);
 
 545                 if(self.popupQueue[0][2] > 0)
 
 546                     setTimeout( $.fbind(self, self.advancePopupQueue), self.popupQueue[0][2]);
 
 552 Editor.prototype.allPanels = function() {
 
 553     return $('#' + this.rootDiv.attr('id') +' > *.panel-wrap', this.rootDiv.parent());
 
 557 Editor.prototype.registerScriptlet = function(scriptlet_id, scriptlet_func)
 
 559     // I briefly assume, that it's verified not to break the world on SS
 
 560     if (!this[scriptlet_id])
 
 561         this[scriptlet_id] = scriptlet_func;
 
 564 Editor.prototype.callScriptlet = function(scriptlet_id, panel, params) {
 
 565     var func = this[scriptlet_id]
 
 567         throw 'No scriptlet named "' + scriptlet_id + '" found.';
 
 569     return func(this, panel, params);
 
 573     $.fbind = function (self, func) {
 
 575             return func.apply(self, arguments);
 
 579     editor = new Editor();