/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'jquery',
'mage/template',
'jquery-ui-modules/widget',
'mage/translate'
], function ($, mageTemplate) {
'use strict';
$.widget('mage.loader', {
loaderStarted: 0,
options: {
icon: '',
texts: {
loaderText: $.mage.__('Please wait...'),
imgAlt: $.mage.__('Loading...')
},
template:
'
' +
'
' +
'

' +
'
<%- data.texts.loaderText %>
' +
'
' +
'
'
},
/**
* Loader creation
* @protected
*/
_create: function () {
this._bind();
},
/**
* Bind on ajax events
* @protected
*/
_bind: function () {
this._on({
'processStop': 'hide',
'processStart': 'show',
'show.loader': 'show',
'hide.loader': 'hide',
'contentUpdated.loader': '_contentUpdated'
});
},
/**
* Verify loader present after content updated
*
* This will be cleaned up by the task MAGETWO-11070
*
* @param {EventObject} e
* @private
*/
_contentUpdated: function (e) {
this.show(e);
},
/**
* Show loader
*/
show: function (e, ctx) {
this._render();
this.loaderStarted++;
this.spinner.show();
if (ctx) {
this.spinner
.css({
width: ctx.outerWidth(),
height: ctx.outerHeight(),
position: 'absolute'
})
.position({
my: 'top left',
at: 'top left',
of: ctx
});
}
return false;
},
/**
* Hide loader
*/
hide: function () {
if (this.loaderStarted > 0) {
this.loaderStarted--;
if (this.loaderStarted === 0) {
this.spinner.hide();
}
}
return false;
},
/**
* Render loader
* @protected
*/
_render: function () {
var html;
if (!this.spinnerTemplate) {
this.spinnerTemplate = mageTemplate(this.options.template);
html = $(this.spinnerTemplate({
data: this.options
}));
html.prependTo(this.element);
this.spinner = html;
}
},
/**
* Destroy loader
*/
_destroy: function () {
this.spinner.remove();
}
});
/**
* This widget takes care of registering the needed loader listeners on the body
*/
$.widget('mage.loaderAjax', {
options: {
defaultContainer: '[data-container=body]',
loadingClass: 'ajax-loading'
},
/**
* @private
*/
_create: function () {
this._bind();
// There should only be one instance of this widget, and it should be attached
// to the body only. Having it on the page twice will trigger multiple processStarts.
if (window.console && !this.element.is(this.options.defaultContainer) && $.mage.isDevMode(undefined)) {
console.warn('This widget is intended to be attached to the body, not below.');
}
},
/**
* @private
*/
_bind: function () {
$(document).on({
'ajaxSend': this._onAjaxSend.bind(this),
'ajaxComplete': this._onAjaxComplete.bind(this)
});
},
/**
* @param {Object} loaderContext
* @return {*}
* @private
*/
_getJqueryObj: function (loaderContext) {
var ctx;
// Check to see if context is jQuery object or not.
if (loaderContext) {
if (loaderContext.jquery) {
ctx = loaderContext;
} else {
ctx = $(loaderContext);
}
} else {
ctx = $('[data-container="body"]');
}
return ctx;
},
/**
* @param {jQuery.Event} e
* @param {Object} jqxhr
* @param {Object} settings
* @private
*/
_onAjaxSend: function (e, jqxhr, settings) {
var ctx;
$(this.options.defaultContainer)
.addClass(this.options.loadingClass)
.attr({
'aria-busy': true
});
if (settings && settings.showLoader) {
ctx = this._getJqueryObj(settings.loaderContext);
ctx.trigger('processStart');
// Check to make sure the loader is there on the page if not report it on the console.
// NOTE that this check should be removed before going live. It is just an aid to help
// in finding the uses of the loader that maybe broken.
if (window.console && !ctx.parents('[data-role="loader"]').length) {
console.warn('Expected to start loader but did not find one in the dom');
}
}
},
/**
* @param {jQuery.Event} e
* @param {Object} jqxhr
* @param {Object} settings
* @private
*/
_onAjaxComplete: function (e, jqxhr, settings) {
$(this.options.defaultContainer)
.removeClass(this.options.loadingClass)
.attr('aria-busy', false);
if (settings && settings.showLoader) {
this._getJqueryObj(settings.loaderContext).trigger('processStop');
}
}
});
return {
loader: $.mage.loader,
loaderAjax: $.mage.loaderAjax
};
});