All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scout.desktop.DesktopFormController.js Maven / Gradle / Ivy

There is a newer version: 25.1.0-beta.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BSI Business Systems Integration AG - initial API and implementation
 ******************************************************************************/
scout.DesktopFormController = function(displayParent, session) {
  scout.DesktopFormController.parent.call(this, displayParent, session);
  this.desktop = displayParent;
  this._popupWindows = [];
  this._documentPopupWindowReadyHandler = this._onDocumentPopupWindowReady.bind(this);

  // must use a document-event, since when popup-window is reloading it does
  // only know the opener of its own window (and nothing about Scout).
  $(document).on('popupWindowReady', this._documentPopupWindowReadyHandler);
};
scout.inherits(scout.DesktopFormController, scout.FormController);

scout.DesktopFormController.instanceCounter = 0;

scout.DesktopFormController.prototype.render = function() {
  scout.DesktopFormController.parent.prototype.render.call(this);
  // find active form and set selected.
  var selectable;
  if (this.desktop.activeForm) {
    var form = this.session.getModelAdapter(this.desktop.activeForm);
    if (form.isDialog()) {
      // find ui selectable part
      selectable = this._findActiveSelectablePart(form);
    } else if (form.isView()) {
      selectable = form;
    }
  }
  if (!selectable) {
    this.desktop.bringOutlineToFront();
  } else {
    this.desktop.bench.activateView(selectable);
  }
  // ensure in all view stacks the last view is activated
  if (this.desktop.bench) {
    this.desktop.bench.postRender();
  }
};

/**
 * Goes up in display hierarchy to find the form to select on desktop. null if outline is selected.
 */
scout.DesktopFormController.prototype._findActiveSelectablePart = function(form) {
  if (form.parent.isView && form.parent.isDialog) {
    if (form.parent.isView()) {
      return form.parent;
    } else if (form.parent.isDialog()) {
      return this._findActiveSelectablePart(form.parent);
    }
  }
  return null;
};

/**
 * @override FormController.js
 */
scout.DesktopFormController.prototype._renderPopupWindow = function(form) {
  var windowSpecs,
    resizeToPrefSize, // flag used to resize browser-window later (see PopupWindow.js)
    bounds = scout.PopupWindow.readWindowBounds(form);

  if (bounds) {
    windowSpecs = 'left=' + bounds.x + ',top=' + bounds.y + ',width=' + bounds.width + ',height=' + bounds.height;
    resizeToPrefSize = false;
  } else {
    var $mainDocument = $(document),
      documentSize = new scout.Dimension($mainDocument.width(), $mainDocument.height());
    windowSpecs = 'left=0,top=0,width=' + documentSize.width + ',height=' + documentSize.height;
    resizeToPrefSize = true;
  }

  // Note: Chrome does not allow to position a popup outside of the primary monitor (Firefox does)
  // So the popup will always appear on the primary monitor even if we have stored the correct
  // bounds to position the popup on the secondary monitor!
  // See: https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Position_and_size_features
  windowSpecs += ',location=no,toolbar=no,menubar=no,resizable=yes';

  var popupBlockerHandler = new scout.PopupBlockerHandler(this.session),
    // form ID in URL is required for 'reload window' support
    url = 'popup-window.html?formId=' + form.id,
    // we must use '_blank' as window-name so browser-windows are never reused
    newWindow = popupBlockerHandler.openWindow(url, '_blank', windowSpecs);

  if (newWindow) {
    this._addPopupWindow(newWindow, form, resizeToPrefSize);
  } else {
    $.log.warn('Popup-blocker detected! Show link to open window manually');
    popupBlockerHandler.showNotification(function() {
      newWindow = window.open(url, '_blank', windowSpecs);
      this._addPopupWindow(newWindow, form, resizeToPrefSize);
    }.bind(this));
  }
};

scout.DesktopFormController.prototype._addPopupWindow = function(newWindow, form, resizeToPrefSize) {
  var popupWindow = new scout.PopupWindow(newWindow, form);
  popupWindow.resizeToPrefSize = resizeToPrefSize;
  popupWindow.events.on('popupWindowUnload', this._onPopupWindowUnload.bind(this));
  this._popupWindows.push(popupWindow);
  $.log.debug('Opened new popup window for form ID ' + form.id);
};

scout.DesktopFormController.prototype._onDocumentPopupWindowReady = function(event, data) {
  $.log.debug('(FormController#_onDocumentPopupWindowReady) data=' + data);
  var popupWindow;
  if (data.formId) {
    // reload (existing popup window)
    var i, formId = data.formId;
    $.log.debug('Popup window for form ID ' + formId + ' has been reloaded');
    for (i = 0; i < this._popupWindows.length; i++) {
      popupWindow = this._popupWindows[i];
      if (popupWindow.form.id === formId) {
        break;
      }
    }
    if (!popupWindow) {
      throw new Error('Couldn\'t find popupWindow reference while popup window was reloaded');
    }
  } else if (data.popupWindow) {
    // open new child window
    popupWindow = data.popupWindow;
  } else {
    // error assertion
    throw new Error('Neither property \'formId\' nor \'popupWindow\' exists on data parameter');
  }
  popupWindow._onReady();
};

scout.DesktopFormController.prototype._onPopupWindowUnload = function(popupWindow) {
  var form = popupWindow.form;
  $.log.debug('Popup window for form ID ' + form.id + ' is unloaded - don\'t know if its closed or reloaded yet');

  // this remove() is important: when a popup-window in IEis closed all references to a HTMLDivElement become
  // invalid. Every call or read on such invalid objects will cause an Error. Even though the DOM element
  // is invalid, the JQuery object which references the DOM element is still alive and occupies memory. That's
  // why we must remove JQuery objects _before_ the popup-window is closed finally.
  form.remove();

  // must do this with setTimeout because at this point window is always still open
  // Note: timeout with 0 milliseconds will not work
  setTimeout(function() {
    if (popupWindow.isClosed()) {
      $.log.debug('Popup window for form ID ' + form.id + ' has been closed');
      // FIXME awe: discuss if close is Ok or do we need the now unsupported "killed from UI" event?
      // was passiert im model wenn noch fenster / message boxen offen sind?
      form.close();
    }
  }.bind(this), 250);
};

/**
 * We only close browser windows here, since during an unload event, we cannot send
 * anything with a HTTP request anyway. So we cannot inform the server that it
 * should "kill" the forms - instead we simply render the popupWindows and forms
 * again when the page has been reloaded.
 */
scout.DesktopFormController.prototype.closePopupWindows = function() {
  this._popupWindows.forEach(function(popupWindow) {
    this._removePopupWindow(popupWindow.form);
  }, this);
  this._popupWindows = [];
};

/**
 * @override FormController.js
 */
scout.DesktopFormController.prototype._removePopupWindow = function(form) {
  var popupWindow = form.popupWindow;
  if (!popupWindow) {
    throw new Error('Form has no popupWindow reference');
  }
  delete form.popupWindow;
  scout.arrays.remove(this._popupWindows, popupWindow);
  if (form.rendered) {
    form.remove();
    popupWindow.close();
  }
};

scout.DesktopFormController.prototype.dispose = function() {
  $(document).off('popupWindowReady', this._documentPopupWindowReadyHandler);
};




© 2015 - 2025 Weber Informatics LLC | Privacy Policy