- /*
- * Copyright (C) eZ Systems AS. All rights reserved.
- * For full copyright and license information view LICENSE file distributed with this source code.
- */
- YUI.add('ez-serversideviewservice', function (Y) {
- "use strict";
- /**
- * Provides the server side view service class
- *
- * @method ez-serversideviewservice
- */
- Y.namespace('eZ');
-
- var PJAX_DONE_REDIRECT = 205,
- PJAX_LOCATION_HEADER = 'PJAX-Location',
- DEFAULT_HEADERS = {'X-PJAX': 'true'};
-
- /**
- * The Server Side View Service class. It is meant to be used to load the
- * content of a server side view.
- *
- * @namespace eZ
- * @class ServerSideViewService
- * @constructor
- * @extends eZ.ViewService
- */
- Y.eZ.ServerSideViewService = Y.Base.create('serverSideViewService', Y.eZ.ViewService, [], {
- initializer: function () {
- this.on('*:submitForm', this._handleFormSubmit);
- },
-
- /**
- * Handles the `submitForm` event by preventing the original form to be
- * submitted by the browser and by submitting the form with an AJAX
- * request.
- *
- * @method _handleFormSubmit
- * @protected
- * @param {EventFacade} e
- */
- _handleFormSubmit: function (e) {
- var form = e.form,
- app = this.get('app');
-
- app.set('loading', true);
- e.originalEvent.preventDefault();
- Y.io(form.getAttribute('action'), {
- method: form.getAttribute('method'),
- headers: Y.merge(DEFAULT_HEADERS, {'Content-Type': form.get('encoding')}),
- data: e.formData,
- on: {
- success: Y.bind(this._handleFormSubmitResponse, this, e.target),
- failure: this._handleLoadFailure,
- },
- context: this,
- });
- },
-
- /**
- * Handles the response of a form submission. It detects if a
- * redirection needs to happen in the application.
- *
- * @method _handleFormSubmitResponse
- * @protected
- * @param {Y.View} view
- * @param {String} tId the transaction id
- * @param {XMLHttpRequest} response
- */
- _handleFormSubmitResponse: function (view, tId, response) {
- var app = this.get('app'),
- pjaxLocation = response.getResponseHeader(PJAX_LOCATION_HEADER);
-
- if ( response.status === PJAX_DONE_REDIRECT && pjaxLocation ) {
- app.navigate(this._getAdminRouteUri(pjaxLocation));
- } else {
- app.set('loading', false);
- this._updateView(view, response);
- }
- },
-
- /**
- * Handles the loading error.
- *
- * @method _handleLoadFailure
- * @param {String} tId
- * @param {XMLHttpRequest} response
- * @protected
- */
- _handleLoadFailure: function (tId, response) {
- var frag = Y.Node.create(response.responseText),
- notificationCount,
- errorMsg = '';
-
- this.get('app').set('loading', false);
- notificationCount = this._parseNotifications(frag);
- if ( notificationCount === 0 ) {
- errorMsg = "Failed to load '" + response.responseURL + "'";
- }
- this._error(errorMsg);
- },
-
- /**
- * Parses the notification node(s) in the PJAX response and sends the
- * corresponding notify events.
- *
- * @method _parseNotifications
- * @param {Y.Node} docFragment
- * @return {Number} the number of notifications
- * @protected
- */
- _parseNotifications: function (docFragment) {
- var notifications = docFragment.all('[data-name="notification"] li');
-
- notifications.each(this._notifyUser, this);
- return notifications.size();
- },
-
- /**
- * Updates the view attributes with the provided HTTP response
- *
- * @method _updateView
- * @private
- * @param {eZ.ServerSideView} view
- * @param {Response} response
- */
- _updateView: function (view, response) {
- this._parseResponse(response);
- view.setAttrs({
- 'title': this.get('title'),
- 'html': this.get('html'),
- });
- },
-
- /**
- * Load the content and the title of the server side view using a PJAX
- * like strategy, ie the server is supposed to response with an HTML
- * like document containing a title and the html code to use. The
- * loading is done, the next callback is called with the service itself
- * in parameter. If an error occurs, an error event is triggered.
- *
- * @method _load
- * @protected
- * @param {Function} next
- */
- _load: function (next) {
- var uri = this.get('app').get('apiRoot') + this.get('request').params.uri;
-
- Y.io(uri, {
- method: 'GET',
- headers: DEFAULT_HEADERS,
- on: {
- success: function (tId, response) {
- this._parseResponse(response);
- next(this);
- },
- failure: this._handleLoadFailure,
- },
- context: this,
- });
- },
-
- /**
- * Parses the server response
- *
- * @method _parseResponse
- * @protected
- * @param {Object} response
- */
- _parseResponse: function (response) {
- var frag = Y.Node.create(response.responseText),
- html, title;
-
- html = frag.one('[data-name="html"]');
- title = frag.one('[data-name="title"]');
-
- if ( html ) {
- this.set('html', this._rewrite(html).getContent());
- }
- if ( title ) {
- this.set('title', title.get('text'));
- }
-
- this._parseNotifications(frag);
- },
-
- /**
- * Rewrites the server side generated HTML so that it's browseable in
- * the PlatformUI application
- *
- * @method _rewrite
- * @protected
- * @param {Node} node
- * @return {Node}
- */
- _rewrite: function (node) {
- node.all('a[href]').each(function (link) {
- if ( !this._isPjaxLink(link) ) {
- return;
- }
- link.setAttribute('href', this._getAdminRouteUri(link.getAttribute('href')));
- }, this);
- return node;
- },
-
- /**
- * Returns the URI in PlatformUI App from the PJAX URI
- *
- * @method _getAdminRouteUri
- * @protected
- * @param {String} uri
- * @return {String}
- */
- _getAdminRouteUri: function (uri) {
- var app = this.get('app'),
- regexp = new RegExp('^' + app.get('apiRoot'));
-
- return app.routeUri('adminGenericRoute', {uri: uri.replace(regexp, '')});
- },
-
- /**
- * Checks whether the link can be transformed in a PJAX link.
- *
- * @method _isPjaxLink
- * @protected
- * @param {Y.Node} link
- * @return {Boolean}
- */
- _isPjaxLink: function (link) {
- var href = link.getAttribute('href');
-
- return (
- href.charAt(0) !== '#'
- && ( !link.hasAttribute('target') || link.getAttribute('target') === '_self' )
- && !href.match(/^http(s)?:\/\//)
- );
- },
-
- /**
- * Fires notify event based on a notification node in the PJAX response.
- *
- * @method _notifyUser
- * @protected
- * @param {Node} node
- */
- _notifyUser: function (node) {
- var app = this.get('app'),
- timeout = 5;
-
- if (node.getAttribute('data-state') === 'error') {
- timeout = 0;
- }
-
- // the app is not yet a bubble target of the view service,
- // so we are using the app to fire the event
- // see https://jira.ez.no/browse/EZP-23013
- app.fire('notify', {
- notification: {
- text: node.getContent(),
- state: node.getAttribute('data-state'),
- timeout: timeout
- }
- });
- },
-
- /**
- * Returns the title and the html code as an object
- *
- * @method _getViewParameters
- * @protected
- * @return {Object}
- */
- _getViewParameters: function () {
- return {
- title: this.get('title'),
- html: this.get('html'),
- };
- }
- }, {
- ATTRS: {
- /**
- * The title parsed from the pjax response.
- *
- * @attribute title
- * @default ""
- * @type String
- */
- title: {
- value: "",
- },
-
- /**
- * The html code parsed from the pjax response.
- *
- * @attribute html
- * @default ""
- * @type String
- */
- html: {
- value: ""
- },
- }
- });
- });
-
-