mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 15:22:17 +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)
|
_onFieldsTouched: function(oEvent)
|
||||||
{
|
{
|
||||||
this._super(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'});
|
this._registerBlockers();
|
||||||
$('body').trigger('register_blocker.portal.itop', {'sBlockerId': this.element.attr('id'), 'sTargetElemSelector': 'document', 'oTargetElemSelector': document, 'sEventName': 'beforeunload'});
|
|
||||||
},
|
},
|
||||||
// Overload from parent class
|
// Overload from parent class
|
||||||
_onSubmitClick: function(oEvent)
|
_onSubmitClick: function(oEvent)
|
||||||
@@ -255,7 +254,7 @@ $(function()
|
|||||||
// If everything is okay, we close the form and apply the submit rule.
|
// If everything is okay, we close the form and apply the submit rule.
|
||||||
if(oValidation.valid)
|
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
|
// Checking if we have to redirect to another page
|
||||||
if(sRuleType === 'redirect')
|
if(sRuleType === 'redirect')
|
||||||
@@ -301,7 +300,7 @@ $(function()
|
|||||||
if(me.options.field_set.field_set('option', 'touched_fields').length > 0)
|
if(me.options.field_set.field_set('option', 'touched_fields').length > 0)
|
||||||
{
|
{
|
||||||
me._disableFormBeforeLoading();
|
me._disableFormBeforeLoading();
|
||||||
$('body').trigger('unregister_blocker.portal.itop', {'sBlockerId': me.element.attr('id')});
|
me._unregisterBlockers();
|
||||||
$.post(
|
$.post(
|
||||||
me.options.endpoint,
|
me.options.endpoint,
|
||||||
{
|
{
|
||||||
@@ -434,6 +433,27 @@ $(function()
|
|||||||
window.location.href = sHomepageUrl;
|
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)
|
submit: function(oEvent)
|
||||||
{
|
{
|
||||||
this._onSubmitClick(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/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'] ~ '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 #}
|
{# Selectize for sets #}
|
||||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/selectize.js'|add_itop_version }}"></script>
|
<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
|
// 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 %}
|
{% endblock %}
|
||||||
});
|
});
|
||||||
</script>
|
</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