mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-18 23:08:46 +02:00
N°5890 - Refactor leave handler to a global helper (not portal only)
This commit is contained in:
@@ -95,8 +95,7 @@ $(function()
|
||||
_onFieldsTouched: function(oEvent)
|
||||
{
|
||||
this._super(oEvent);
|
||||
$('body').trigger('register_blocker.portal.itop', {'sBlockerId': this.element.attr('id'), 'sTargetElemSelector': '#' + this.element.closest('.modal').attr('id'), 'oTargetElemSelector': '#' + this.element.closest('.modal').attr('id'), 'sEventName': 'hide.bs.modal'});
|
||||
$('body').trigger('register_blocker.portal.itop', {'sBlockerId': this.element.attr('id'), 'sTargetElemSelector': 'document', 'oTargetElemSelector': document, 'sEventName': 'beforeunload'});
|
||||
this._registerBlockers();
|
||||
},
|
||||
// Overload from parent class
|
||||
_onSubmitClick: function(oEvent)
|
||||
@@ -255,7 +254,7 @@ $(function()
|
||||
// If everything is okay, we close the form and apply the submit rule.
|
||||
if(oValidation.valid)
|
||||
{
|
||||
$('body').trigger('unregister_blocker.portal.itop', {'sBlockerId': me.element.attr('id')});
|
||||
me._unregisterBlockers();
|
||||
|
||||
// Checking if we have to redirect to another page
|
||||
if(sRuleType === 'redirect')
|
||||
@@ -301,7 +300,7 @@ $(function()
|
||||
if(me.options.field_set.field_set('option', 'touched_fields').length > 0)
|
||||
{
|
||||
me._disableFormBeforeLoading();
|
||||
$('body').trigger('unregister_blocker.portal.itop', {'sBlockerId': me.element.attr('id')});
|
||||
me._unregisterBlockers();
|
||||
$.post(
|
||||
me.options.endpoint,
|
||||
{
|
||||
@@ -434,6 +433,27 @@ $(function()
|
||||
window.location.href = sHomepageUrl;
|
||||
}
|
||||
},
|
||||
_registerBlockers: function()
|
||||
{
|
||||
$('body').trigger('register_blocker.itop', {
|
||||
'sBlockerId': this.element.attr('id'),
|
||||
'sTargetElemSelector': '#' + this.element.closest('.modal').attr('id'),
|
||||
'oTargetElemSelector': '#' + this.element.closest('.modal').attr('id'),
|
||||
'sEventName': 'hide.bs.modal'
|
||||
});
|
||||
$('body').trigger('register_blocker.itop', {
|
||||
'sBlockerId': this.element.attr('id'),
|
||||
'sTargetElemSelector': 'document',
|
||||
'oTargetElemSelector': document,
|
||||
'sEventName': 'beforeunload'
|
||||
});
|
||||
},
|
||||
_unregisterBlockers: function()
|
||||
{
|
||||
$('body').trigger('unregister_blocker.itop', {
|
||||
'sBlockerId': this.element.attr('id')
|
||||
});
|
||||
},
|
||||
submit: function(oEvent)
|
||||
{
|
||||
this._onSubmitClick(oEvent);
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2023 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
;
|
||||
$(function()
|
||||
{
|
||||
// the widget definition, where 'itop' is the namespace,
|
||||
// 'portal_leave_handler' the widget name
|
||||
$.widget( 'itop.portal_leave_handler',
|
||||
{
|
||||
// default options
|
||||
options:
|
||||
{
|
||||
'message': 'allo la',
|
||||
},
|
||||
events: ['hide.bs.modal', 'beforeunload'],
|
||||
//[event]
|
||||
registered_blockers: {},
|
||||
// {id : {target : 'event1', target : 'event2'}}
|
||||
|
||||
// the constructor
|
||||
_create: function()
|
||||
{
|
||||
var me =this;
|
||||
this.element
|
||||
.addClass('portal_leave_handler');
|
||||
|
||||
this.element.on('register_blocker.portal.itop', function(oEvent, oData){
|
||||
me._onRegisterBlocker(oData.sBlockerId, oData.sTargetElemSelector, oData.oTargetElemSelector, oData.sEventName);
|
||||
});
|
||||
this.element.on('unregister_blocker.portal.itop', function(oEvent, oData){
|
||||
me._onUnregisterBlocker(oData.sBlockerId);
|
||||
});
|
||||
|
||||
this.element.on('hide.bs.modal', function(oEvent) {return me._onLeaveHandler(oEvent);});
|
||||
window.addEventListener('beforeunload', function(oEvent) {return me._onLeaveHandler(oEvent);});
|
||||
|
||||
this._super();
|
||||
},
|
||||
_onRegisterBlocker: function(sBlockerId, sTargetElemSelector, oTargetElemSelector, sEventName)
|
||||
{
|
||||
var aRegisteredBlock = {};
|
||||
aRegisteredBlock[sTargetElemSelector] = {'eventName': sEventName, 'selector': oTargetElemSelector};
|
||||
$.extend(
|
||||
aRegisteredBlock,
|
||||
this.registered_blockers[sBlockerId]
|
||||
);
|
||||
this.registered_blockers[sBlockerId] = aRegisteredBlock;
|
||||
},
|
||||
_onUnregisterBlocker: function(sBlockerId)
|
||||
{
|
||||
delete this.registered_blockers[sBlockerId];
|
||||
},
|
||||
_onLeaveHandler: function(oEvent)
|
||||
{
|
||||
var me = this;
|
||||
for(var aRegisteredBlocker in me.registered_blockers)
|
||||
{
|
||||
for(var sBlockerTarget in me.registered_blockers[aRegisteredBlocker])
|
||||
{
|
||||
if($(me.registered_blockers[aRegisteredBlocker][sBlockerTarget]['selector'])[0] === oEvent.target && me.registered_blockers[aRegisteredBlocker][sBlockerTarget]['eventName'].split('.')[0] === oEvent.type)
|
||||
{
|
||||
if(oEvent.type === 'beforeunload')
|
||||
{
|
||||
oEvent.returnValue = me.options.message;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var $bReturnValue = confirm(me.options.message);
|
||||
if ($bReturnValue)
|
||||
{
|
||||
$('body').trigger('unregister_blocker.portal.itop', {'sBlockerId': aRegisteredBlocker});
|
||||
}
|
||||
return $bReturnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// events bound via _bind are removed automatically
|
||||
// revert other modifications here
|
||||
_destroy: function()
|
||||
{
|
||||
this.element
|
||||
.removeClass('portal_leave_handler');
|
||||
|
||||
this._super();
|
||||
},
|
||||
// _setOptions is called with a hash of all options that are changing
|
||||
// always refresh when changing options
|
||||
_setOptions: function()
|
||||
{
|
||||
this._superApply(arguments);
|
||||
},
|
||||
// _setOption is called for each individual option that is changing
|
||||
_setOption: function( key, value )
|
||||
{
|
||||
this._super( key, value );
|
||||
},
|
||||
showOptions: function()
|
||||
{
|
||||
return this.options;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/js/typeahead.bundle.min.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/handlebars/js/handlebars.min-768ddbd.js'|add_itop_version }}"></script>
|
||||
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'js/portal_leave_handler.js'|add_itop_version }}"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/leave_handler.js'|add_itop_version }}"></script>
|
||||
|
||||
{# Selectize for sets #}
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/selectize.js'|add_itop_version }}"></script>
|
||||
@@ -539,7 +539,12 @@
|
||||
});
|
||||
|
||||
// Initialize confirmation message handler when a form with touched fields is closed
|
||||
oBodyElem.portal_leave_handler({'message': '{{ 'Portal:Form:Close:Warning'|dict_s }}'});
|
||||
oBodyElem.leave_handler({
|
||||
'message': '{{ 'Portal:Form:Close:Warning'|dict_s }}',
|
||||
'extra_events': {
|
||||
'body': ['hide.bs.modal']
|
||||
}
|
||||
});
|
||||
{% endblock %}
|
||||
});
|
||||
</script>
|
||||
|
||||
155
js/leave_handler.js
Normal file
155
js/leave_handler.js
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Leave handler
|
||||
*
|
||||
* Prevent unexcepted loose of data when leaving a modal / page by prompting a confirmation to the user
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @internal
|
||||
*/
|
||||
;
|
||||
$(function()
|
||||
{
|
||||
// the widget definition, where 'itop' is the namespace,
|
||||
// 'leave_handler' the widget name
|
||||
$.widget( 'itop.leave_handler',
|
||||
{
|
||||
// default options
|
||||
options:
|
||||
{
|
||||
'message': 'Do you really want to loose your changes?',
|
||||
'extra_events': {},
|
||||
},
|
||||
//[event]
|
||||
events: {
|
||||
'window': ['beforeunload'],
|
||||
'body': [],
|
||||
'element': []
|
||||
},
|
||||
// {id : {target : 'event1', target : 'event2'}}
|
||||
registered_blockers: {},
|
||||
|
||||
// the constructor
|
||||
_create: function()
|
||||
{
|
||||
const me =this;
|
||||
this.element
|
||||
.addClass('leave_handler');
|
||||
|
||||
this.element.on('register_blocker.itop', function(oEvent, oData){
|
||||
me._onRegisterBlocker(oData.sBlockerId, oData.sTargetElemSelector, oData.oTargetElemSelector, oData.sEventName);
|
||||
});
|
||||
this.element.on('unregister_blocker.itop', function(oEvent, oData){
|
||||
me._onUnregisterBlocker(oData.sBlockerId);
|
||||
});
|
||||
|
||||
// Merge default events with extra events from the consumer
|
||||
// Note: There is no native way yet to recursively merge objects with arrays (and no duplicate)
|
||||
for (const sTarget in this.options.extra_events) {
|
||||
for (const sEvent of this.options.extra_events[sTarget]) {
|
||||
// Ignore event already present
|
||||
if (this.events[sTarget] === undefined || this.events[sTarget].indexOf(sEvent) !== -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.events[sTarget].push(sEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// Register listeners for all events
|
||||
for (const sTarget in this.events) {
|
||||
if (sTarget === 'window') {
|
||||
for (const sEvent of this.events[sTarget]) {
|
||||
window.addEventListener(sEvent, function(oEvent) {
|
||||
return me._onLeaveHandler(oEvent);
|
||||
});
|
||||
}
|
||||
} else if (sTarget === 'body') {
|
||||
for (const sEvent of this.events[sTarget]) {
|
||||
$('body').on(sEvent, function(oEvent) {
|
||||
return me._onLeaveHandler(oEvent);
|
||||
});
|
||||
}
|
||||
} else if (sTarget === 'element') {
|
||||
for (const sEvent of this.events[sTarget]) {
|
||||
this.element.on(sEvent, function(oEvent) {
|
||||
return me._onLeaveHandler(oEvent);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._super();
|
||||
},
|
||||
_onRegisterBlocker: function(sBlockerId, sTargetElemSelector, oTargetElemSelector, sEventName)
|
||||
{
|
||||
let aRegisteredBlock = {};
|
||||
aRegisteredBlock[sTargetElemSelector] = {'eventName': sEventName, 'selector': oTargetElemSelector};
|
||||
$.extend(
|
||||
aRegisteredBlock,
|
||||
this.registered_blockers[sBlockerId]
|
||||
);
|
||||
this.registered_blockers[sBlockerId] = aRegisteredBlock;
|
||||
},
|
||||
_onUnregisterBlocker: function(sBlockerId)
|
||||
{
|
||||
delete this.registered_blockers[sBlockerId];
|
||||
},
|
||||
_onLeaveHandler: function(oEvent)
|
||||
{
|
||||
const me = this;
|
||||
for(const aRegisteredBlocker in me.registered_blockers)
|
||||
{
|
||||
for(const sBlockerTarget in me.registered_blockers[aRegisteredBlocker])
|
||||
{
|
||||
if($(me.registered_blockers[aRegisteredBlocker][sBlockerTarget]['selector'])[0] === oEvent.target && me.registered_blockers[aRegisteredBlocker][sBlockerTarget]['eventName'].split('.')[0] === oEvent.type)
|
||||
{
|
||||
if(oEvent.type === 'beforeunload')
|
||||
{
|
||||
oEvent.returnValue = me.options.message;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
const $bReturnValue = confirm(me.options.message);
|
||||
if ($bReturnValue)
|
||||
{
|
||||
$('body').trigger('unregister_blocker.itop', {'sBlockerId': aRegisteredBlocker});
|
||||
}
|
||||
return $bReturnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// events bound via _bind are removed automatically
|
||||
// revert other modifications here
|
||||
_destroy: function()
|
||||
{
|
||||
this.element
|
||||
.removeClass('leave_handler');
|
||||
|
||||
this._super();
|
||||
},
|
||||
// _setOptions is called with a hash of all options that are changing
|
||||
// always refresh when changing options
|
||||
_setOptions: function()
|
||||
{
|
||||
this._superApply(arguments);
|
||||
},
|
||||
// _setOption is called for each individual option that is changing
|
||||
_setOption: function( key, value )
|
||||
{
|
||||
this._super( key, value );
|
||||
},
|
||||
showOptions: function()
|
||||
{
|
||||
return this.options;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user