// TUTO.JS
// Custom JavaScript for FoxInCloud Web Application Site (you can override here)
// C:\PROGRAM FILES (X86)\ABAQUE\FICSAMPLES\FICTUTO\SITE\BS\TUTO.JS (included in c:\program files (x86)\abaque\ficsamples\fictuto\fictutobs.exe)
// (292 lines before localization)
// ========================================================================================================================

/****************************************************************

Welcome to your Web Application JavaScript file!
You can set FoxInCloud options below, and/or add your own JavaScript code (Prototype.js or jQuery flavors are welcome)
You share this file between tutoTest and tutoProd:
e.g. edit ...\site\tutoTest\tuto.js and, once tested OK, copy to ...\site\tutoProd\tuto.js
/!\ This file is UTF-8 encoded; use a text editor that supports UTF-8 such as Sublime Text, NotePad++ or PSpad
*****************************************************************/

jQuery.extend(FoxInCloud, {

CGI: 'tuto',
// Application script map extension (application code by default)

requestTimeoutDev: 600,
// DEVELOPMENT : request timeout delay in seconds
// when delay times out, an alert appears in HTML page and request is lost
// a faily long delay is recommended to let you enough time to debug any possible error

requestTimeoutProd: 30,
// PRODUCTION: request timeout delay in seconds
// when delay times out, an alert appears in HTML page and request is lost
// set a delay at least as long as the 'Timeout' value in your wc.ini file

requestWaitPic: true,
// Request: display server response wait indicator image
// you may change wait indicator image in your sub-class of aw.vcx!awFrm

requestWaitPicDelay: .1,
// <=0 pour afficher tout de suite
// request: delay in seconds before displaying server response wait indicator -- <=0 display right away

requestFormOpacity: .8,
// <=0 ou > 1 pour ne rien changer
// request: % opacity applied to form during request -- <=0 or > 1 to leave 100% opacity

autoBlurDelay: -1, /* 1.5 */
// <input>, <textarea>, etc.: délai en secondes pour la soumission automatique -- <=0 pour inhiber
// <input>, <textarea>, etc.: delay in seconds for auto-sumit to server -- <=0 to cancel

inputAlwaysBlur: true,
// <input type="text ..."/> (VFP textbox): toujours envoyer la valeur au serveur quand l'utilisateur sort de la zone, même si la valeur n'a pas changé
// <input type="text ..."/> (VFP textbox): always send value to server when user exits the zone, even if value has not changed

inputAlwaysBlurOnReturn: true,
// <input type="text"/> : toujours envoyer la valeur au serveur quand l'utilisateur presse la touche enter
// <input type="text"/>: always send value to server when user hits 'enter' key

inputTextDateSelector: 'input.awDate',
// <input type="text"/> affichant une date : sélecteur CSS
// <input type="text"/> displaying a date: CSS selector
// FoxInCloud (awHTML.Prg!awHTMLgen) automatically sets class="awDate" to textBoxes displaying a date

dateFormat: 'day/month', // 'day/month' || 'month/day'
// <input type="text"/> affichant une date : format de saisie
// <input type="text"/> displaying a date: input format

centuryRollover: 20,
// <input type="text"/> affichant une date : Retirer un siècle aux dates dont l'année est > année courante + this.centuryRollover
// <input type="text"/> displaying a date: Substract a century to dates whose year is > current year + this.centuryRollover

inputTextBackColor:false,
// <input type="text"/> : changer automatiquement la couleur d'arrière plan
// <input type="text"/>: change background-color automatically

gridRowChangeDelay: 0.5,
// <=0 pour envoyer tout de suite
// grid: delay in seconds before sending row change event -- <=0 to send right away

gridColChangeDelay: 0.5,
// <=0 pour envoyer tout de suite
// grid: delay in seconds before sending column change event -- <=0 to send right away

gridDateEmpty: '/ /',
// Chain displayed in grid cells having a isNull(date) or Empty(date)

gridDateTimeEmpty: '/ / ::',
// Chain displayed in grid cells having a isNull(dateTime) or Empty(dateTime)

pageEffectUser: false,
// pageFrame: run a transition effect when page is activated by user

pageEffectServer: false,
// pageFrame: run a transition effect when page is activated by server

visibleEffect: true, // V 2.10
// run an transition effect when visibility of an object changes

imgSrcEffect: true, // V 2.10
// image: run a transition effect when image source changes

effectDuration: .5, // V 2.10
// default transition effect duration in seconds

onKeyLabels: "ctrl+H, ctrl+F, ctrl+O, ctrl+S", // V 2.10
// ON KEY LABEL combinations that you use in your VFP application and you want to inhibit the default browser behavior for.
// (case insensitive)
// this coma-separated list is dynamically parsed - you can modify it at any time during the course of an event by writing in VFP:
// local loAJAX && as awAJAX of awServer.prg && full license
// =wlAJAX(@m.loAJAX) and m.loAJAX.cScriptJSadd([FoxInCloud.onKeyLabels = FoxInCloud.onKeyLabels + ", ctrl+A, ctrl+F, ctrl+S, ctrl+O, ctrl+P, ctrl+Z";])

AttribSet_: function (ebx, tcAttrib, tuVal){
// Sets the value of an HTML element's attribute - shell method to be implemented in tuto.js
// Adds the total request response time to the first line and updates the elementary response times in the label at the bottom of form
var $ebx = jQuery(ebx);
if ($ebx.hasClass('editbox') && $ebx.hasClass('ficebxevent') && tcAttrib === 'value'){
if (!tuVal) ebx.value = '';
else {
var iFirst = tuVal.indexOf('\n')
, iLast = indexOfOcc(tuVal, '\n', (tuVal.match(/\n/g) || []).length - (ebx.value.match(/\n/g) || []).length)
;
ebx.value = ''
+ tuVal.substr(0, iFirst)
+ ' (' + (new Date() - this.dRequest) + 'ms' + ') ' /* total request response time */
+ tuVal.substr(iFirst, iLast-iFirst+1)
+ ebx.value
;
}
ebx.scrollTop = 0;
return true; // return true skips the FoxInCloud default method
}
},

AjaxComplete_: function (jqXHR) {
// Displays response time in label at bottom of form and browser's console
var time = this.ExeTimeDisplay();
jQuery('.lblTime').html(time);
window.console && console.log(time); // FoxInCloud.cEvent + ': ' +
},

junk: 'junk'
});

/* ======================================================================================================
Here start the functions specific to FoxInCloud tutorial ...
You'll probably won't need this kind of sophisticated JavaScript in your FoxInCloud application
Anyhow, you might like to read this code to understand the basics ot JavaScript
note: in JavaScript (like in C or Java), ';' ends rather than continues an instruction
====================================================================================================== */


function indexOfOcc (string, char, iOcc) { /* indexOf(nth occurrence) */
var first_index = string.indexOf(char);
if (iOcc <= 1) return first_index;
else {
var length_up_to_first_index = first_index + 1
, next_occurrence = indexOfOcc(string.slice(length_up_to_first_index), char, iOcc - 1);
return (next_occurrence === -1)
? -1
: (length_up_to_first_index + next_occurrence)
;
}
}

function srceCodeDisplay(event, trgtID, srceID, code){ /* displays source code of element currently hovered on the form */
if (event.shiftKey || event.eventPhase !== 2) return;
trgtID = jQuery('#' + trgtID);
trgtID
.html(FoxInCloud.abLocalized(code)) // FoxInCloud.abLocalized(): see FoxInCloud.js
.off('scroll')
.on('scroll', function(e){jQuery(this).data(srceID, jQuery(this).scrollTop());}) // reminds scrollTop for each source element
.scrollTop(trgtID.data(srceID)||0)
;
event.stopPropagation();
};

var myCount = 1, Object_ = "";
function InsertEventCount(event, myEvent, myObject) {/* Add client-side event (.mouse*(), .key*()) to top of list *(), .key*()) en haut de la liste */
var ebx = jQuery('#event_scx-tutoinfoboxclient');
if(ebx.length && !FoxInCloud.lRequest){
var myStr = ebx.val()
, brack = myStr.indexOf('[')
, line1 = myStr.split(((brack > 0 && brack < myStr.indexOf('\n')) ? '[' : '\n'), 1)[0]
;
if (myEvent === line1){
myCount++;
myStr = line1 + '[' + myCount +']' + myStr.substr(myStr.indexOf('\n'));
} else {
myCount = 1;
myStr = myEvent + '\n' + (Object_ === myObject ? '':'\n') + myStr;
}
ebx.val(myStr);
Object_ = myObject;
}
};

function srceCodeWindow(event, html, srceFile) { /* displays source code from current HTML element into a child window */
html = html || jQuery(event.currentTarget).html();
if (html && html.indexOf('awVFPcode') > -1){
srceFile = "'" + (srceFile || '*.?cx') + "'";
var title = (false ? ''
: (FoxInCloud.lang === 'fr' ? 'Ce code source a été lu du fichier ' + srceFile + ', colorisé et localisé' // copy-paste this line to add another language support
: (FoxInCloud.lang === 'es' ? 'Este código fuente se leyó desde ' + srceFile + ', coloreada y localizada' // copy-paste this line to add another language support
: (FoxInCloud.lang === 'it' ? 'Questo codice sorgente è stato letto da ' + srceFile + ', colorato e localizzato' // copy-paste this line to add another language support
: 'This source code was read from ' + srceFile + ', colorized and localized' // default: English
))));
if (event.ctrlKey || event.metaKey) {
var win = window.open('', title);
jQuery(win.document.head).html(jQuery('<base href="' + window.location.href.substr(0, window.location.href.lastIndexOf('/')+1) + '">').add(jQuery('link[type="text/css"]').clone()));
jQuery(win.document.body).html(html);
}
else if (jQuery('body.bootstrap').length) { /* 2017-08-01 Bootstrap demo */
var modalID = "modal-srceCodeWindow", modalEl, modalBS;
html = ''
+ '<div class="modal fade" id="' + modalID + '" tabindex="-1" role="dialog" aria-hidden="true" aria-labelledby="srceCodeWindow_title">'
+ '<div class="modal-dialog modal-lg shadow-lg" role="document">'
+ '<div class="modal-content">'
+ '<div class="modal-header">'
+ '<h5 class="modal-title" id="srceCodeWindow_title">' + title + '</h5>'
+ '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" aria-hidden="true"></button>'
+ '</div>'
+ '<div class="modal-body">'
+ html
+ '</div>'
+ '</div>'
+ '</div>'
+ '</div>';
jQuery(document.body).append(html);
modalEl = document.getElementById(modalID);
modalBS = new bootstrap.Modal(modalEl, {keyboard: true, backdrop:true});
modalBS && modalBS.show();
jQuery(modalEl).on('hidden.bs.modal', function () { // http://stackoverflow.com/questions/13177426/how-to-destroy-bootstrap-modal-window-completely
modalBS.dispose();
jQuery(modalEl).remove();
});
} // else if (this.jQueryUIdialog) {}
else {
jQuery(html).dialog({
title: title
, minWidth: 800
, minHeight: 500
, maxHeight: jQuery(window).innerHeight() * .8
, show: true
, hide: true
, close: function(event, ui){jQuery(this).dialog('destroy');}
});
}
}
};

jQuery(document).ready( /* code below executes when document is ready */
function(){ /* menu in left vertical bar */
// restore jQueryUI menu > popup default positionning (modified by FoxInCloud to fit VFP behavior)
jQuery('body:not(.bootstrap) #menubar-_msysmenu').menu(
'option' // http://api.jqueryui.com/menu/#method-option
, 'position'
, {my: "left top", at: "right top"} // http://api.jqueryui.com/menu/#option-position
);
});

window.comboValues = {};
function comboValueCollect(id, value){
window.comboValues[id] = value;
};

window.spinnerValues = {};
function spinnerValueCollect(id, value){
window.spinnerValues[id] = value;
};