mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-21 00:02:17 +02:00
Customer portal : Sticky form button when form is to long to be fully displayed in the screen
SVN:trunk[4077]
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
{# Object brick create layout #}
|
||||
|
||||
{% set sFormId = (form.id is defined and form.id is not null) ? form.id : 'object_form' %}
|
||||
{% set sFormIdSanitized = sFormId|replace({'-': ''}) %}
|
||||
{% set tIsModal = (tIsModal is defined and tIsModal == true) ? true : false %}
|
||||
|
||||
<form id="{{ sFormId }}" method="POST" action="{{ form.renderer.GetEndpoint()|raw }}">
|
||||
@@ -43,23 +44,65 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
var oFieldSet = $('#{{ sFormId }} > .form_fields').field_set({{ form.fieldset|json_encode()|raw }});
|
||||
|
||||
// Form field set declaration
|
||||
var oFieldSet_{{ sFormIdSanitized }} = $('#{{ sFormId }} > .form_fields').field_set({{ form.fieldset|json_encode()|raw }});
|
||||
// Form handler declaration
|
||||
$('#{{ sFormId }}').portal_form_handler({
|
||||
formmanager_class: "{{ form.formmanager_class|escape('js') }}",
|
||||
formmanager_data: {{ form.formmanager_data|json_encode()|raw }},
|
||||
field_set: oFieldSet,
|
||||
field_set: oFieldSet_{{ sFormIdSanitized }},
|
||||
submit_btn_selector: $('#{{ sFormId }}').parent().find('.form_btn_submit, .form_btn_transition'),
|
||||
cancel_btn_selector: $('#{{ sFormId }}').parent().find('.form_btn_cancel'),
|
||||
submit_url: {% if form.submit_callback is not null %}"{{ form.submit_callback }}"{% else %}null{% endif %},
|
||||
cancel_url: {% if form.cancel_callback is not null %}"{{ form.cancel_callback }}"{% else %}null{% endif %},
|
||||
endpoint: "{{ form.renderer.GetEndpoint()|raw }}",
|
||||
is_modal: {% if tIsModal is defined and tIsModal == true %}true{% else %}false{% endif %}
|
||||
is_modal: {% if tIsModal == true %}true{% else %}false{% endif %}
|
||||
});
|
||||
|
||||
{% if tIsModal is defined and tIsModal == true %}
|
||||
// Sticky buttons handler
|
||||
// Note : This pattern if to prevent performance issues
|
||||
// - Cloning buttons
|
||||
var oNormalRegularButtons_{{ sFormIdSanitized }} = $('#{{ sFormId }} .form_btn_regular');
|
||||
var oStickyRegularButtons_{{ sFormIdSanitized }} = oNormalRegularButtons_{{ sFormIdSanitized }}.clone(true, true);
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.addClass('sticky');
|
||||
{% if tIsModal == true %}
|
||||
$('#{{ sFormId }}').closest('.modal').append(oStickyRegularButtons_{{ sFormIdSanitized }});
|
||||
{% else %}
|
||||
$('#{{ sFormId }}').closest('#main-content').append(oStickyRegularButtons_{{ sFormIdSanitized }});
|
||||
{% endif %}
|
||||
// - Global timeout for any
|
||||
var oScrollTimeout;
|
||||
// - Scroll handler
|
||||
scrollHandler_{{ sFormIdSanitized }} = function () {
|
||||
if($('#{{ sFormId }} .form_buttons').visible())
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.addClass('closed');
|
||||
}
|
||||
else
|
||||
{
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.removeClass('closed');
|
||||
}
|
||||
};
|
||||
// - Event binding
|
||||
$({% if tIsModal == true %}'.modal.in'{% else %}window{% endif %}).off('scroll').on('scroll', function () {
|
||||
if (oScrollTimeout) {
|
||||
// Clear the timeout, if one is pending
|
||||
clearTimeout(oScrollTimeout);
|
||||
oScrollTimeout = null;
|
||||
}
|
||||
oScrollTimeout = setTimeout(scrollHandler_{{ sFormIdSanitized }}, 50);
|
||||
});
|
||||
// - First time call
|
||||
scrollHandler_{{ sFormIdSanitized }}();
|
||||
|
||||
{% if tIsModal == true %}
|
||||
// Scroll top (because sometimes when several modals have been opened)
|
||||
$('#{{ sFormId }}').closest('.modal').scrollTop(0);
|
||||
$('#{{ sFormId }}').closest('.modal').find('.modal-footer').hide();
|
||||
// Remove sticky button when closing modal
|
||||
$('#{{ sFormId }}').closest('.modal').on('hidden.bs.modal', function () {
|
||||
oStickyRegularButtons_{{ sFormIdSanitized }}.remove();
|
||||
});
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
@@ -58,6 +58,8 @@
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] }}js/jquery.fileupload.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/latinise/latinise.min.js"></script>
|
||||
{# Visible.js to check if an element is visible on screen #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/jquery-visible/js/jquery.visible.min.js"></script>
|
||||
{# Moment.js #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] }}lib/moment/js/moment.min.js"></script>
|
||||
{# Datatables #}
|
||||
@@ -209,7 +211,7 @@
|
||||
<div class="logo">
|
||||
{# This is a debug helper to know in which screen size we are #}
|
||||
{% if app['debug'] %}
|
||||
<div>Debug : Taille <span class="hidden-sm hidden-md hidden-lg">XS</span><span class="hidden-xs hidden-md hidden-lg">SM</span><span class="hidden-xs hidden-sm hidden-lg">MD</span><span class="hidden-xs hidden-sm hidden-md">LG</span></div>
|
||||
<div style="position: fixed; bottom: 0px; left: 0px; z-index: 9999;">Debug : Taille <span class="hidden-sm hidden-md hidden-lg">XS</span><span class="hidden-xs hidden-md hidden-lg">SM</span><span class="hidden-xs hidden-sm hidden-lg">MD</span><span class="hidden-xs hidden-sm hidden-md">LG</span></div>
|
||||
{% endif %}
|
||||
<a href="{{ app.url_generator.generate('p_home') }}" title="{{ app['combodo.portal.instance.conf'].properties.name|dict_s }}">
|
||||
<img src="{{ app['combodo.portal.instance.conf'].properties.logo }}" alt="{{ app['combodo.portal.instance.conf'].properties.name|dict_s }}" />
|
||||
@@ -223,12 +225,12 @@
|
||||
<div class="container-fluid" id="main-wrapper">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-9 col-md-10 col-sm-offset-3 col-md-offset-2">
|
||||
<section class="row row-eq-height-sm" id="main-header">
|
||||
<section class="row" id="main-header">
|
||||
{% block pMainHeader %}
|
||||
{% endblock %}
|
||||
</section>
|
||||
|
||||
<section class="row row-eq-height-sm" id="main-content">
|
||||
<section class="row" id="main-content">
|
||||
{% block pMainContent %}
|
||||
{% endblock %}
|
||||
</section>
|
||||
|
||||
@@ -638,18 +638,6 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
bottom: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
#drag_overlay.drag_in{
|
||||
animation: show-drop-zone 0.3s ease-out forwards;
|
||||
-webkit-animation: show-drop-zone 0.3s ease-out forwards;
|
||||
-moz-animation: show-drop-zone 0.3s ease-out forwards;
|
||||
-ms-animation: show-drop-zone 0.3s ease-out forwards;
|
||||
}
|
||||
#drag_overlay.drag_out{
|
||||
animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
-webkit-animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
-moz-animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
-ms-animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
}
|
||||
#drag_overlay .overlay_content{
|
||||
margin-top: 5em;
|
||||
width: 100%;
|
||||
@@ -661,56 +649,71 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
#drag_overlay .overlay_content .message{
|
||||
font-size: 1.5em;
|
||||
}
|
||||
@keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
/* Attachments drag & drop zone, only for none mobile devices */
|
||||
@media (min-width: 768px){
|
||||
#drag_overlay.drag_in{
|
||||
animation: show-drop-zone 0.3s ease-out forwards;
|
||||
-webkit-animation: show-drop-zone 0.3s ease-out forwards;
|
||||
-moz-animation: show-drop-zone 0.3s ease-out forwards;
|
||||
-ms-animation: show-drop-zone 0.3s ease-out forwards;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
#drag_overlay.drag_out{
|
||||
animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
-webkit-animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
-moz-animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
-ms-animation: hide-drop-zone 0.3s ease-out forwards;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
@keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@-ms-keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
@-webkit-keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
@-moz-keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
@-ms-keyframes show-drop-zone{
|
||||
100% {
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
@keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
}
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
@-webkit-keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@-moz-keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
@-moz-keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
}
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
}
|
||||
}
|
||||
@-ms-keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
@-ms-keyframes hide-drop-zone{
|
||||
0% {
|
||||
height: 20%;
|
||||
}
|
||||
100% {
|
||||
height: 0%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,6 +729,9 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
.form_buttons .form_btn_transitions{
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.form_btn_regular.sticky{
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 768px){
|
||||
.form_buttons .form_btn_transitions{
|
||||
float: left !important;
|
||||
@@ -736,6 +742,40 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
|
||||
.form_buttons .form_btn_regular btn{
|
||||
width: inherit;
|
||||
}
|
||||
/* Making regular button sticky */
|
||||
.form_btn_regular.sticky{
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
padding: 15px;
|
||||
background-color: #FFF; /* TODO : SASS this to panel bg */
|
||||
border: 1px solid #DDD; /* TODO : SASS this to panel border */
|
||||
border-radius: 4px; /* TODO : SASS this to panel border */
|
||||
transition: bottom 0.3s;
|
||||
}
|
||||
.form_btn_regular.sticky.closed{
|
||||
bottom: -80px;
|
||||
}
|
||||
/* - For regular layout */
|
||||
#main-content .form_btn_regular.sticky{
|
||||
right: 15px; /* TODO : SASS this to col-xs-12 padding */
|
||||
}
|
||||
/* - For modal layout */
|
||||
.modal.in .form_btn_regular.sticky{
|
||||
margin-left: 61%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
/* - For modal layout */
|
||||
.modal.in .form_btn_regular.sticky{
|
||||
margin-left: 70%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
/* - For modal layout */
|
||||
.modal.in .form_btn_regular.sticky{
|
||||
margin-left: 73%;
|
||||
}
|
||||
}
|
||||
|
||||
/* CKEditor : Adding BS error feedback */
|
||||
|
||||
@@ -65,7 +65,7 @@ $oApp->register(new Silex\Provider\TwigServiceProvider(), array(
|
||||
));
|
||||
|
||||
// Configuring Silex application
|
||||
$oApp['debug'] = false;
|
||||
$oApp['debug'] = true;
|
||||
$oApp['combodo.absolute_url'] = utils::GetAbsoluteUrlAppRoot();
|
||||
$oApp['combodo.portal.base.absolute_url'] = utils::GetAbsoluteUrlAppRoot() . 'env-' . utils::GetCurrentEnvironment() . '/itop-portal-base/portal/web/';
|
||||
$oApp['combodo.portal.instance.absolute_url'] = utils::GetAbsoluteUrlAppRoot() . 'env-' . utils::GetCurrentEnvironment() . '/' . PORTAL_MODULE_ID . '/';
|
||||
|
||||
@@ -125,59 +125,67 @@ $(function()
|
||||
|
||||
// Scrolling to top so the user can see messages
|
||||
$('body').scrollTop(0);
|
||||
}
|
||||
|
||||
// If everything is okay, we close the form and reload it.
|
||||
if(oValidation.valid)
|
||||
{
|
||||
if(me.options.is_modal)
|
||||
// If everything is okay, we close the form and reload it.
|
||||
if(oValidation.valid)
|
||||
{
|
||||
me.element.closest('.modal').modal('hide');
|
||||
}
|
||||
|
||||
// Checking if we have to redirect to another page
|
||||
if(oValidation.redirection !== undefined)
|
||||
{
|
||||
var oRedirection = oValidation.redirection;
|
||||
var bRedirectionAjax = (oRedirection.ajax !== undefined) ? oRedirection.ajax : false;
|
||||
var sUrl = null;
|
||||
|
||||
// URL priority order :
|
||||
// redirection.url > me.option.submit_url > redirection.alternative_url
|
||||
if(oRedirection.url !== undefined)
|
||||
if(me.options.is_modal)
|
||||
{
|
||||
sUrl = oRedirection.url;
|
||||
me.element.closest('.modal').modal('hide');
|
||||
}
|
||||
|
||||
// Checking if we have to redirect to another page
|
||||
if(oValidation.redirection !== undefined)
|
||||
{
|
||||
var oRedirection = oValidation.redirection;
|
||||
var bRedirectionAjax = (oRedirection.ajax !== undefined) ? oRedirection.ajax : false;
|
||||
var sUrl = null;
|
||||
|
||||
// URL priority order :
|
||||
// redirection.url > me.option.submit_url > redirection.alternative_url
|
||||
if(oRedirection.url !== undefined)
|
||||
{
|
||||
sUrl = oRedirection.url;
|
||||
}
|
||||
else if(me.options.submit_url !== null)
|
||||
{
|
||||
sUrl = me.options.submit_url;
|
||||
}
|
||||
else if(oRedirection.alternative_url !== undefined)
|
||||
{
|
||||
sUrl = oRedirection.alternative_url;
|
||||
}
|
||||
|
||||
if(sUrl !== null)
|
||||
{
|
||||
if(bRedirectionAjax)
|
||||
{
|
||||
// Creating a new modal
|
||||
var oModalElem = $('#modal-for-all').clone();
|
||||
oModalElem.attr('id', '').appendTo('body');
|
||||
// Loading content
|
||||
oModalElem.find('.modal-content').html($('#page_overlay .overlay_content').html());
|
||||
oModalElem.find('.modal-content').load(sUrl);
|
||||
oModalElem.modal('show');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Showing loader while redirecting, otherwise user tend to click somewhere in the page.
|
||||
// Note : We use a timeout because .always() is called right after here and will hide the loader
|
||||
setTimeout(function(){ me._disableFormBeforeLoading(); }, 50);
|
||||
// Redirecting after a few ms so the user can see what happend
|
||||
setTimeout(function() { location.href = sUrl; }, 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(me.options.submit_url !== null)
|
||||
{
|
||||
sUrl = me.options.submit_url;
|
||||
// Showing loader while redirecting, otherwise user tend to click somewhere in the page.
|
||||
// Note : We use a timeout because .always() is called right after here and will hide the loader
|
||||
setTimeout(function(){ me._disableFormBeforeLoading(); }, 50);
|
||||
// Redirecting after a few ms so the user can see what happend
|
||||
setTimeout(function() { location.href = me.options.submit_url; }, 400);
|
||||
}
|
||||
else if(oRedirection.alternative_url !== undefined)
|
||||
{
|
||||
sUrl = oRedirection.alternative_url;
|
||||
}
|
||||
|
||||
if(sUrl !== null)
|
||||
{
|
||||
if(bRedirectionAjax)
|
||||
{
|
||||
// Creating a new modal
|
||||
var oModalElem = $('#modal-for-all').clone();
|
||||
oModalElem.attr('id', '').appendTo('body');
|
||||
// Loading content
|
||||
oModalElem.find('.modal-content').html($('#page_overlay .overlay_content').html());
|
||||
oModalElem.find('.modal-content').load(sUrl);
|
||||
oModalElem.modal('show');
|
||||
}
|
||||
else
|
||||
{
|
||||
setTimeout(function() { location.href = sUrl; }, 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(me.options.submit_url !== null)
|
||||
{
|
||||
setTimeout(function() { location.href = me.options.submit_url; }, 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
datamodels/2.x/itop-portal-base/portal/web/lib/jquery-visible/js/jquery.visible.min.js
vendored
Normal file
1
datamodels/2.x/itop-portal-base/portal/web/lib/jquery-visible/js/jquery.visible.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(t){var i=t(window);t.fn.visible=function(t,e,o){if(!(this.length<1)){var r=this.length>1?this.eq(0):this,n=r.get(0),f=i.width(),h=i.height(),o=o?o:"both",l=e===!0?n.offsetWidth*n.offsetHeight:!0;if("function"==typeof n.getBoundingClientRect){var g=n.getBoundingClientRect(),u=g.top>=0&&g.top<h,s=g.bottom>0&&g.bottom<=h,c=g.left>=0&&g.left<f,a=g.right>0&&g.right<=f,v=t?u||s:u&&s,b=t?c||a:c&&a;if("both"===o)return l&&v&&b;if("vertical"===o)return l&&v;if("horizontal"===o)return l&&b}else{var d=i.scrollTop(),p=d+h,w=i.scrollLeft(),m=w+f,y=r.offset(),z=y.top,B=z+r.height(),C=y.left,R=C+r.width(),j=t===!0?B:z,q=t===!0?z:B,H=t===!0?R:C,L=t===!0?C:R;if("both"===o)return!!l&&p>=q&&j>=d&&m>=L&&H>=w;if("vertical"===o)return!!l&&p>=q&&j>=d;if("horizontal"===o)return!!l&&m>=L&&H>=w}}}}(jQuery);
|
||||
Reference in New Issue
Block a user