I'm adjusting a form in a website that has several parts. The goal is when we load the page, the initial input appears and the other inputs just appear after the one before has an adequate value.
On the first page everything seems ok (I added a few more inputs to the original), when I pass on to the second page the first input seems to appear and suddenly disappear, not allowing the user to fill out the value and thus leaving the page blank.
I can't understand what's making the loading problem. Below is the code.
passo3.ejs
<div class="row">
<div class="col-sm-12">
<div class="jumbotron">
<!-- <h1><%= __('calculadora.title') %></h1> -->
<h2><%= __('calculadora.subtitle_3_revestimentos') %></h2>
</div>
</div>
<div class="alert alert-dark" style="display:none;"></div>
<div class="alert alert-info" style="display:none;"></div>
<div class="alert alert-warning" style="display:none;"></div>
<div class="alert alert-danger" style="display:none;"></div>
<div class="progress">
<div class="progress-bar progress-bar-dark" role="progressbar" aria-valuenow="4" aria-valuemin="0" aria-valuemax="100" style="width: <%= progressBar %>%"></div>
</div>
<div class="form-group col-sm-12 form-inline"></div>
<div class="form-group col-sm-1 form-inline col-margin"></div>
<div class="form-group col-sm-5 form-inline form-option-div">
<!-- image depends on option in step 1-->
<div class="btn-image-div-absolute d-flex align-items-end">
<img src="/img/calculadora_p3/fachada_<%= lang %>.png" class="btn-image-absolute rounded mx-auto image_overlay image_base">
<img src="/img/calculadora_p3/fachada_ac.png" class="btn-image-absolute rounded mx-auto image_overlay ac" style="display:none;">
<img src="/img/calculadora_p3/fachada_af.png" class="btn-image-absolute rounded mx-auto image_overlay af" style="display:none;">
</div>
</div>
<div class="form-group col-sm-5 form-option-div">
<h3 class="form-subtitle"><%= __('calculadora.cobertura') %></h3>
<!-- 10 -->
<% var _Q = {
tabindex: 1,
number: "10",
name: "rev_tipo",
hiddenOnStart: false,
errorInput: false,
additionalClasses: "form-control",
units: ""
}; %>
<% include ./_question_typeB.ejs %>
<!-- 10A -->
<% _Q = {
tabindex: 2,
number: "10A",
name: "rev_outro",
hiddenOnStart: true,
errorInput: true,
additionalClasses: "valid_number",
units: "[kg/m<sup>2</sup>]"
}; %>
<% include ./_question_typeA.ejs %>
<!-- 11 -->
<% _Q = {
tabindex: 3,
number: "11",
name: "afmc",
hiddenOnStart: true,
errorInput: true,
additionalClasses: "valid_selectize_number",
units: "a<sub>c</sub> [m]"
}; %>
<% include ./_question_typeB.ejs %>
<div class="part2" style="display:none;">
<h3 class="form-subtitle"><%= __('calculadora.fachada') %></h3>
<!-- [9] 12 (20) -->
<% _Q = {
tabindex: 4,
number: "12",
name: "ori_rev_fachada",
hiddenOnStart: false,
errorInput: false,
additionalClasses: "form-control",
units: ""
}; %>
<% include ./_question_typeB.ejs %>
<!-- [10] 9 (31) -->
<% _Q = {
tabindex: 5,
number: "13",
name: "n_fachadas_abertas",
hiddenOnStart: true,
errorInput: false,
additionalClasses: "form-control",
units: ""
}; %>
<% include ./_question_typeB.ejs %>
<!-- [11] 10 (32) -->
<% _Q = {
tabindex: 6,
number: "14",
name: "n_empenas_abertas",
hiddenOnStart: true,
errorInput: false,
additionalClasses: "form-control",
units: ""
}; %>
<% include ./_question_typeB.ejs %>
<!-- [12] 11 (9) -->
<% _Q = {
tabindex: 7,
number: "15",
name: "rev_fachada",
hiddenOnStart: true,
errorInput: false,
additionalClasses: "form-control",
units: ""
}; %>
<% include ./_question_typeB.ejs %>
<!-- 13 (10) -->
<% _Q = {
tabindex: 8,
number: "16",
name: "afmf",
hiddenOnStart: true,
errorInput: true,
additionalClasses: "valid_selectize_number",
units: "a<sub>f</sub> [m]"
}; %>
<% include ./_question_typeB.ejs %>
</div> <!-- part 2 -->
<div class="btn_submit_div" style="display:none;">
<button tabindex="10" type="button" class="btn_submit btn btn-dark btn-md"><%= __('calculadora.seguinte') %></button>
</div>
</div><!-- form group -->
</div><!-- row -->
<div style="height: 70px; width:100%">
</div>
<input type="hidden" name="step" value="<%= step %>">
<input type="hidden" name="arq" value="<%= calcData.arq %>">
<input type="hidden" name="vao" value="<%= calcData.vao %>">
<input type="hidden" name="h1" value="<%= calcData.h1 %>">
<input type="hidden" name="hc" value="<%= calcData.hc %>">
<div class="calculadora_inputs">
<% if( typeof report != "undefined" ){ %>
<form id="form_calculadora" name="form_calculadora" action="/calculadora" method="GET">
<input id="reportId" type="hidden" class="" name="reportId" value="<%= report._id %>">
<input id="nextStep" type="hidden" class="" name="nextStep" value="<%= +report.step +1 %>">
<% } %>
<input type="hidden" name="v" value="<%= calcData.v %>"><!-- calculated on server with step 2 inputs, needs to be here to be included in query string inputs -->
<input type="hidden" class="sync_rev_tipo required" name="rev_tipo">
<input type="hidden" class="sync_rev_outro required" name="rev_outro">
<input type="hidden" class="sync_afmc required" name="afmc">
<input type="hidden" class="sync_n_fachadas_abertas required" name="n_fachadas_abertas">
<input type="hidden" class="sync_n_empenas_abertas required" name="n_empenas_abertas">
<input type="hidden" class="sync_rev_fachada required" name="rev_fachada">
<input type="hidden" class="sync_ori_rev_fachada required" name="ori_rev_fachada">
<input type="hidden" class="sync_afmf required" name="afmf">
<% if( typeof report != "undefined" ){ %>
</form>
<% } %>
</div>
</div>
<script>resetCalculatorText = "<%= __('resetCalculatorText') %>";</script>
<script src="/js/calculadora_passo<%= step %>.js"></script>
_question_typeB.ejs
<%
var _visible = '', _errorPop = '', _errorPopClass='', _additionalClasses='', _selectOptions=[];
if( _Q.hiddenOnStart ) {
_visible=`style="display:none"`;
}
if( _Q.errorInput ){
let _content = __(`calculadora.q${_Q.number}.errorText`);
_errorPop=`data-toggle="popover" data-trigger="manual" data-placement="left" data-content="${_content}" data-html="true" data-container=".calculator-input-group.step${_Q.number}"`;
_errorPopClass = 'error-popover';
}
if( _Q.additionalClasses ){
_additionalClasses = _Q.additionalClasses;
}
if( __(`calculadora.q${_Q.number}.selectOptions`) ){
_selectOptions = __(`calculadora.q${_Q.number}.selectOptions`);
}
%>
<h4 class="input_label step<%= _Q.number %>" <%- _visible %>><%= __(`calculadora.q${_Q.number}.inputLabel`) %></h4>
<div class="input-group calculator-input-group step<%= _Q.number %>" <%- _visible %>>
<% console.log(_Q.units) %>
<% if( _Q.units ){ %>
<a class="<%= _errorPopClass %>"" <%- _errorPop %> >
<div class="input-group-prepend">
<span class="input-group-text calculator-input-prepend"><%- _Q.units %></span>
</div>
</a>
<% } %>
<select data-tab="<%= _Q.tabindex %>" class="sync_<%= _Q.name %> middle calculator-input <%= _errorPopClass %> <%- _additionalClasses %>" placeholder="<%= __(`calculadora.q${_Q.number}.inputPlaceholder`) %>" title="<%= __(`calculadora.q${_Q.number}.inputTitle`) %>" aria-label="<%= __(`calculadora.q${_Q.number}.inputTitle`) %>">
<% console.log(_selectOptions.length) %>
<% if( _selectOptions.length ){ %>
<option selected disabled><%- __(`calculadora.escolhaUmaOpcao`) %></option>
<% _selectOptions.forEach(function( eachOption){ %>
<option value="<%= eachOption.val %>"><%- eachOption.title %></option>
<% }) %>
<% } %>
</select>
<div class="input-group-append">
<span class="input-group-text calculator-input-append">
<a tabindex="99" class="btn btn-sm btn-link btn-block" data-html="true" data-toggle="popover" data-container="body" data-placement="left" title="<%= __(`calculadora.q${_Q.number}.helperTitle`) %>" data-content="<%= __(`calculadora.q${_Q.number}.helperContent`) %>"><i class="far fa-question-circle fa-lg"></i></a>
</span>
</div>
</div>
calculadora_passo3.js
//store the instance of the selectize components
var $selectize_8;
var selectizeControl_8;
var $selectize_13;
var selectizeControl_13;
$(document).ready(function() {
//initialization
function _init(){
//add a property to help icon on Afmc so it can be added dynamicaly to help popover when clicked
//after this add the event to the help button to get the aria-described with the id of the popover and manipulate the content
//replacing ${1} by data-par1 value. Because this can be used anywhere i'm adding this event to main calculadoraFrontEnd.js file
let afmc = (+$('[name="v"]').val() ).toFixed(2);
let afmf = +$('[name="h1"]').val()-0.5;
console.log(afmc);
console.log(afmf);
$('.step11 .input-group-append .btn-link').attr('data-par1', afmc );
//same for afmf on step 16
$('.step16 .input-group-append .btn-link').attr('data-par1', afmf );
scrollTo($('header'));
}
//populate select box
function populateSelect_8(){
//destroy select if already exists
if( selectizeControl_8){
selectizeControl_8.destroy();
}
//initiate the selectize component and store it's instance
$selectize_8 = $('select.sync_afmc').selectize( {
options: calcularAfastamentoMadreCobertura(),
valueField: 'val',
labelField: 'title',
searchField: 'title',
sortField: function(item1, item2) {
return item1.value - item2.value;
},
createOnBlur: true,
create: true,
openOnFocus: true,
onChange: function(input){
//prevent clear method (input becomes null) to trigger "not a number" again
if(!input) return;
let length_v = $('[name="v"]').val();//calcularComprimentoViga();
//ignore +2 place decimals
let ratio = Math.round((length_v / input)*100)/100;
//check if the input exists in the original options calculation function
let originalOptions = calcularAfastamentoMadreCobertura();
let originalOption = false;
if (originalOptions.filter(function(option) { return option.val === input; }).length > 0) {
originalOption= true;
}
if( !$.isNumeric(input) || (Math.floor(ratio) != ratio && !originalOption ) ) {
//showMessage("Error - Not valid number", "alert-danger");
showMessage( $(this.$wrapper[0]) );
//clear last added value
selectizeControl_8.clear();
//remove last added value from list
selectizeControl_8.removeOption(input);
//reopen dropdown
selectizeControl_8.open();
}else{
//clear error message
clearMessage( $(this.$wrapper[0]) );
}
},
onInitialize: function(){
$(this.$wrapper[0]).find(":input").attr('tabindex', $(this.$wrapper[0]).parent().find('.selectized').data('tab') ) ;
},
onFocus: function(){
showOnlyTheRightImage("ac");
},
render: {
item: function(item, escape) {
return '<div>' +
(item.title ? '<span class="selectize_title">' + escape(item.title) + '</span>' : '') +
'</div>';
},
option: function(item, escape) {
return '<div>' +
'<span class="selectize_title"><strong>' + (item.title ? escape(item.title) : escape(item.val)) + '</strong>' +
(item.subtitle ? '<span class="selectize_subtitle"> ' + escape(item.subtitle) + '</span>' : '') + '</span>'
'</div>';
},
}
});//options
//store object instnace so we can handle events
selectizeControl_8 = $selectize_8[0].selectize;
}//function
//populate select box
function populateSelect_13(){
let af_array = [];
//destroy select if already exists
if( selectizeControl_13){
selectizeControl_13.destroy();
}
//initiate the selectize component and store it's instance
$selectize_13 = $('select.sync_afmf').selectize( {
options: calcularAfastamentoMadresFachada(),
valueField: 'val',
labelField: 'title',
searchField: 'title',
sortField: function(item1, item2) {
return item1.value - item2.value;
},
createOnBlur: true,
create: true,
openOnFocus: true,
onChange: function(input){
//prevent clear method (input becomes null) to trigger "not a number" again
if(!input) return
//h from form inputs
let length_h = parseFloat( $('[name="h1"]').val() );
//ignore +2 place decimals
let ratio = Math.round((length_h / input)*100)/100;
//check if the input exists in the original options calculation function
let originalOptions = calcularAfastamentoMadresFachada();
let originalOption = false;
if (originalOptions.filter(function(option) { return option.val === input; }).length > 0) {
originalOption= true;
}
if( !$.isNumeric(input) || (Math.floor(ratio) != ratio && !originalOption ) ) {
showMessage( $(this.$wrapper[0]) );
//clear last added value
selectizeControl_13.clear();
//remove last added value from list
selectizeControl_13.removeOption(input);
//reopen dropdown
selectizeControl_13.open();
}else{
//clear error message
clearMessage( $(this.$wrapper[0]) );
}
},
onInitialize: function(){
$(this.$wrapper[0]).find(":input").attr('tabindex', $(this.$wrapper[0]).parent().find('.selectized').data('tab') ) ;
},
onFocus: function(){
showOnlyTheRightImage("af");
},
render: {
item: function(item, escape) {
return '<div>' +
(item.title ? '<span class="selectize_title">' + escape(item.title) + '</span>' : '') +
'</div>';
},
option: function(item, escape) {
return '<div>' +
'<span class="selectize_title"><strong>' + (item.title ? escape(item.title) : escape(item.val)) + '</strong>' +
(item.subtitle ? '<span class="selectize_subtitle"> ' + escape(item.subtitle) + '</span>' : '') + '</span>'
'</div>';
},
}
});//options
//store object instnace so we can handle events
selectizeControl_13 = $selectize_13[0].selectize;
}//function
//allow only numbers and decimal point
$('.group_option_inputs_div').keypress('div.valid_selectize_number', function(e) {
//only allow number and dot characters
if ( (e.which < 48 || e.which > 57) && e.which !== 46) {
e.preventDefault();
}
//dont allow paste
}).on('paste', function(e) {
e.preventDefault();
});
$('.calculator-input').on('focus', function(){
//hide all except base image
$('.image_overlay').not('.image_base').hide();
});
//FLOW -------------------------------------------------------
// Step 10 only to show 10A
$('[name="rev_tipo"]').on('input', function(){
//if valid activate next input
if( $(this).val() == '6' ){
$('.step10A').show();
}else{
$('.step10A').hide();
//also clear rev_outro input (only for option 6 - outro)
$('.sync_rev_outro').val('').trigger("change");
}
});
// Step 10, 10A
$('[name="rev_tipo"], [name="rev_outro"]').on('input', function(){
let tipo = $('[name="rev_tipo"]').val();
let outro = $('[name="rev_outro"]').val();
let valid = true;
//nothing selected or "other" without specifing what "other" is
if( tipo == '' || (tipo == '6' && outro == '') ){
valid = false;
}
//if valid activate next input
if( !valid ){
$('.step10, .step11, .step12, .step13, .step14, .step15, .step16').hide();
$('.btn_submit_div').hide();
}else{
$('.step10').show().trigger("input");
populateSelect_8();
//scrollTo( $('.step8') );
}
});
// step 8
$('[name="afmc"]').on('input', function(){
if($(this).val() == ''){
$('.step11, .step12, .step13, .step14, .step15, .step16').hide();
$('.btn_submit_div').hide();
}else{
//show parte 2 of form
$('.part2').show();
$('.step11').show().trigger("input");
//scrollTo( $('.step9') );
}
});
// step [9] 12 (10)
$('[name="ori_rev_fachada"]').on('input', function(){
$('.step12, .step13, .step14, .step15, .step16').hide();
$('.btn_submit_div').hide();
if( $(this).val() != ''){
if( $(this).val() == '0' || $(this).val() == '1' ){
$('.step12').show().trigger("input");
}else{
$('.sync_rev_fachada').val('');
$('.sync_n_empenas_abertas').val('');
$('.sync_n_fachadas_abertas').val('');
//also clear afmf input (only for option 0 - vertical)
$('.sync_afmf').val('');
$('.btn_submit_div').show();
//scrollTo( $('.btn_submit_div') );
}
}
});
// step [10] 9 (31)
$('[name="n_fachadas_abertas"]').on('input', function(){
$('.step13, .step14, .step15, .step16').hide();
$('.btn_submit_div').hide();
if($(this).val() != ''){
$('.step13').show().trigger("input");
//scrollTo( $('.step10') );
}
});
// step [11] 10 (32)
$('[name="n_empenas_abertas"]').on('input', function(){
$('.step14, .step15, .step16').hide();
$('.btn_submit_div').hide();
if( $(this).val() != ''){
$('.step14').show().trigger("input");
}
});
// step [12] 11 (9)
$('[name="rev_fachada"]').on('input', function(){
if( $(this).val() == ''){
$('.step15, .step16').hide();
$('.btn_submit_div').hide();
}else{
//if orientação do revestimento = horizontal, afmf will not be required
if( $('.sync_ori_rev_fachada').val() == '1' ){
$('.sync_afmf').val('');
$('.step15').hide();
$('.btn_submit_div').show();
//scrollTo( $('.btn_submit_div') );
}else{
populateSelect_13();
$('.step15').show().trigger("input");
$('.btn_submit_div').hide();
}
//scrollTo( $('.step12') );
}
});
// step 13 (10)
$('[name="afmf"]').on('input', function(){
if( $(this).val() == ''){
$('.btn_submit_div').hide();
}else{
$('.btn_submit_div').show();
//scrollTo( $('.btn_submit_div') );
}
});
//------------------------------------------------------------
function calcularAfastamentoMadreCobertura(){
let rev = $('[name="rev_tipo"]').val(); //defined in this form
let arq = $('[name="arq"]').val();
let vao = $('[name="vao"]').val();
let h = $('[name="h"]').val();
let hc = $('[name="hc"]').val();
let ret = [];
let A = 1.0; //caso para arq = 2 e 3
let B = 3.0; //caso o revestimento da cobertura seja qq tipo de sandwich
if(arq == "1"){
A = 0.5;
}else if(arq == "4"){
A = 2.0;
}
if(rev == "0"){//Chapa Simples - Bac Acier
B = 2.0;
}else if(rev == "1" || rev == "6" ){//fotovoltaico e outro
B = 1.6;
}
//suggest more values
let variation = [0, 1, 2];
//this will be the suggested options available to the user in the select box
let suggested = [];
//calculate options and add them to suggested array
for(let i=0; i<variation.length; i++){
let distanciaViga = Math.sqrt( (vao * A)**2 + (hc - h)**2 ) - 0.5;
let afmc = distanciaViga / ( Math.ceil( (distanciaViga / B) + variation[i] ) );
let result = parseFloat( afmc ).toFixed(2);
suggested.push({val:result, title:result });
}
return suggested;
}
function calcularAfastamentoMadresFachada(){
//tipo de revestimento da fachada ( 0=chapa simples, 1=painael sandwich, 2=outro)
let rev_fachada = $('[name="rev_fachada"]').val();
//altura dos pilares
let h = $('[name="h"]').val();
//look for values close to this (don't know why this specifically)
let ret = [];
let constant = 3; //other cases then "chapa simples"
if( rev_fachada === '0') constant = 2;
let calc = parseFloat( (h - 0.5) / Math.ceil( (h - 0.5)/constant ) ).toFixed(2);
ret.push({val:calc , title:calc})
return ret;
}
//hide all overlay images except the one with the specific class to the question on focus
function showOnlyTheRightImage(specificClass){
$('.image_overlay').not('.image_base').hide();
$('.image_overlay.'+specificClass).show();
}
//initialize stuff
setTimeout(function() {
_init();
}, 10);//only enough for this to be last
});//document ready
Thanks for your help
Related
I have a well-runing good code before, my guess is in datepicker..it started to show that error when i played around and testing clicking on datepicker.
I know that exceeding stack size meaning that I have some kind of infinite recursive of-never-returning-back-to-the-base or whatsoever, can you show me how to fix this?
I mean, the error is quite random, sometimes when you change the date it's okay, sometimes it just stopped. it's not always crashing when you change date on the datepicker.
I never get the error on other place other than datepicker section (start and end date) and before I make the datepicker it was okay.
here's the screenshot of error message on console rooted from jquery.min.js
and bootstrap.datepicker.js
The HTML-counterpart (HTML and JS is separated) is just basic form
Here's my JS code
$F.loadView(function() {
"use strict";
return {
title: 'Master Discount - HelloBill',
viewtitle: 'Master Discount',
urlController: 'discount/',
urlControllerHardware: 'hardware/',
urlControllerLicense: 'license/',
afterLoad: function(param) {
var self = this;
var th = this.parent;
var post = '';
var txt = 'inserted';
//bwt munculin judul
if (param.param[0]) {
$('#topic').text('Update ' + self.viewtitle);
txt = 'updated';
getUpdateData(param, self, txt);
post = param.param[0];
$('#judul_detail').removeClass("looptemplate");
} else {
$('#topic').text('Add ' + self.viewtitle);
}
//mengeluarkan detail barang2 yg akan didiskon
$('#Type').change(function(){
if($('#Type').val()){
$('#judul_detail').removeClass("looptemplate");
if($('#Type').val() == 'Hardware') {
// self.refreshTableTes(9, "Hardware");
self.refreshTableHardware(param, self, txt);
}
else {
// self.refreshTableTes(12, "License");
self.refreshTableLicense(param, self, txt);
}
} else {
$('#judul_detail').addClass("looptemplate");
$('#Body').empty();
}
});
//Datepicker
Date.prototype.addDays = function(days) {
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
}
Date.prototype.reFormat = function() {
var twoDigitMonth = ((this.getMonth()+1) < 10) ? '0'+(this.getMonth()+1) : (this.getMonth()+1);
var currentDate = this.getFullYear() + "-" + twoDigitMonth + "-" + this.getDate();
return currentDate;
}
var fullDate1 = new Date();
var dumDate1 = '';
$('#StartDate').datepicker({
format: 'yyyy-mm-dd',
autoclose: false,
startDate: fullDate1.reFormat()
// beforeShowDay: NotBeforeToday
}).on('changeDate', function(selected) {
var startDate = new Date(selected.date.valueOf());
$('#EndDate').datepicker('setStartDate', startDate);
// alert(dumDate1);
// alert($('#EndDate').val());
if(startDate > dumDate1 || $('#EndDate').val() == '') {
// $('#EndDate').val($(this).val());
$('#EndDate').datepicker('setDate', startDate);
}
dumDate1 = new Date(selected.date.valueOf());
});
var fullDate2 = new Date();
var dumDate2 = '';
$('#EndDate').datepicker({
format: 'yyyy-mm-dd',
autoclose: false,
startDate: fullDate2.reFormat()
// beforeShowDay: NotBeforeToday
}).on('changeDate', function(selected) {
var startDate = new Date(selected.date.valueOf());
if(startDate < dumDate2 || $('#StartDate').val() == '') {
$('#EndDate').datepicker('setStartDate', startDate);
$('#StartDate').datepicker('setDate', startDate);
// $('#EndDate.day').css('background-color', 'coral');
}
dumDate2 = new Date(selected.date.valueOf());
});
//Discount Percentage or Value
$('input.terikat').keyup(function(){
if($(this).val()) {
$('input.terikat').not(this).val('');
}
});
var numbersOnly = document.getElementsByClassName('numbers-only');
for(var i = 0 ; i < numbersOnly.length ; i++) {
numbersOnly[i].addEventListener('keydown', function(e) {
var key = e.keyCode ? e.keyCode : e.which;
if (!( [8, 9, 13, 27, 46, 110, 190].indexOf(key) !== -1 ||
(key == 65 && ( e.ctrlKey || e.metaKey ) ) ||
(key >= 35 && key <= 40) ||
(key >= 48 && key <= 57 && !(e.shiftKey || e.altKey)) ||
(key >= 96 && key <= 105)
)) e.preventDefault();
});
}
//Discount Start Date and End Date
var dur = document.getElementById("StartDate");
var dur2 = document.getElementById("EndDate");
var checkboxDuration = document.getElementById("duration");
dur.disabled = true;
dur2.disabled = true;
dur.style.backgroundColor = "Gainsboro";
dur2.style.backgroundColor = "Gainsboro";
$("#duration").click(function(){
if(checkboxDuration.checked){
dur.disabled = false;
dur2.disabled = false;
dur.style.backgroundColor = "white";
dur2.style.backgroundColor = "white";
} else {
dur.disabled = true;
dur2.disabled = true;
dur.style.backgroundColor = "Gainsboro";
dur2.style.backgroundColor = "Gainsboro";
}
});
//Mengatur checkbox yang select all
$('#select_all').click(function(){
if($(this).prop("checked") == true){
$(".selectedItem").prop("checked", true);
}
else{
$(".selectedItem").prop("checked", false);
}
});
//Submit Form
$('#action').submit(function(e) {
e.preventDefault();
var ser = $F.serialize('#action');
console.log(ser);
//insert ke tabel diskon dan detail diskon
$F.service({
type: 'post',
url: 'discount/action',
data: JSON.stringify(ser),
success: function(data){
if(data != null) {
if(data.Status == 0) {
$F.popup.show({
content: data.Message
});
$('.modal-content').attr("style", "width : 250px");
setTimeout(function() {
window.location = $F.config.get('baseUri') + '#/master/discount';
$('.popup-close-button').click();
}, 1500);
} else {
var err = '';
for (var field in data.Errors) {
err += data.Errors[field].ID + ' : ' + data.Errors[field].Message + '</br>';
}
}
} else {
DZ.showAlertWarning("Something is wrong, no data is " + txt, "#error_insert_update", 0);
}
}
}); //tutup service (insert diskon dan detail diskon)
});
}, refreshTableHardware: function (param, self, jenis) {
$F.service({
url:self.urlControllerHardware+"getAllData",
type: 'GET',
success: function(data){
if(data != null) {
var x = data.length;
var body = $("#Body");
var depan = '<div class="form-group"><div class="col-md-4 col-sm-4 col-xs-4"></div><div class="col-md-8 col-sm-8 col-xs-8">';
var belakang = '</div></div>';
body.empty();
for(var i = 0; i < x; i++){
var temp = depan + '<input type="checkbox" class="selectedItem" name="Item[]" id="detail-'+i+'" value="' + data[i].HardwareID + '"> <label for="detail-'+i+'">' + data[i].HardwareName + '</label>' + belakang;
body.append(temp);
}
if(jenis == 'updated') {getDetailData(param, self);}
} else {
DZ.showAlertWarning("Cannot fetch the data, no services is available for now", "#Body", 0);
}
}
})
}, refreshTableLicense: function (param, self, jenis) {
$F.service({
url:self.urlControllerLicense+"getAllData",
type: 'GET',
success: function(data){
if(data != null) {
var x = data.length;
var body = $("#Body");
var depan = '<div class="form-group"><div class="col-md-4 col-sm-4 col-xs-4"></div><div class="col-md-8 col-sm-8 col-xs-8">';
var belakang = '</div></div>';
body.empty();
for(var i = 0; i < x; i++){
var temp = depan + '<input type="checkbox" class="selectedItem" name="Item[]" id="detail-'+i+'" value="' + data[i].LicenseID + '"> <label for="detail-'+i+'">' + data[i].LicenseName + '</label>' + belakang;
body.append(temp);
}
if(jenis == 'updated') getDetailData(param, self);
} else {
DZ.showAlertWarning("Cannot fetch the data, no services is available for now", "#Body", 0);
}
}
})
}
};
function NotBeforeToday(date)
{
var now = new Date();//this gets the current date and time
if (date.getFullYear() == now.getFullYear() && date.getMonth() == now.getMonth() && date.getDate() > now.getDate())
return [true];
if (date.getFullYear() >= now.getFullYear() && date.getMonth() > now.getMonth())
return [true];
if (date.getFullYear() > now.getFullYear())
return [true];
return [false];
}
function getUpdateData(param, self, jenis) {
$F.service({
type: 'get',
url: self.urlController + 'getUpdateData/' + param.param[0],
success: function(data) {
if(data != null) {
var item = data.Discount[0];
$('#DiscountID').val(item.DiscountID);
$('#DiscountCode').val(item.DiscountCode);
$('#DiscountName').val(item.DiscountName);
$('#Description').val(item.Description);
$('#Type').val(item.Type);
if(item.Type == 'Hardware') self.refreshTableHardware(param, self, jenis);
else self.refreshTableLicense(param, self, jenis);
// getDetailData(param, self);
$('#Percentage').val(item.DiscountPercentage);
$('#Value').val(item.DiscountValue);
if(item.StartDate && item.EndDate) {
// alert(item.StartDate);
// alert(item.EndDate);
$('#duration').prop("checked", true);
$('#StartDate').prop("disabled", false);
$('#StartDate').css("background-color", "white");
$('#EndDate').prop("disabled", false);
$('#EndDate').css("background-color", "white");
var i = item.StartDate;
var j = item.EndDate;
// $('#Period').val(i + ' - ' + j);
$('#StartDate').val(i);
$('#EndDate').val(j);
}
} else {
DZ.showAlertWarning("Cannot fetch the data, no services is available for now", "#error", 0);
}
}
});
}
function getDetailData(param, self) {
$F.service({
type: 'get',
url: self.urlController + 'getDetailData/' + param.param[0],
success: function(data) {
if(data != null) {
var x = data.Discount.length;
var select = $('.selectedItem');
for(var i = 0; i < x; i++) {
var discount = data.Discount[i];
var item='';
if(discount.HardwareID) {
item = discount.HardwareID;
} else {
item = discount.LicenseID;
}
// alert(item);
select.each(function(){
// alert($(this).val());
if($(this).val() == item) {
// alert(item);
$(this).attr("checked", "checked");
}
// else alert(item);
});
}
} else {
DZ.showAlertWarning("Cannot fetch the data, no services is available for now", "#Body", 0);
}
}
});
}
}());
Here's the snippet I prepare, I reduce some of the code but retain the main feature (including the datepicker itself).
$(document).ready(function() {
//Datepicker
Date.prototype.addDays = function(days) {
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
}
Date.prototype.reFormat = function() {
var twoDigitMonth = ((this.getMonth() + 1) < 10) ? '0' + (this.getMonth() + 1) : (this.getMonth() + 1);
var currentDate = this.getFullYear() + "-" + twoDigitMonth + "-" + this.getDate();
return currentDate;
}
var fullDate1 = new Date();
var dumDate1 = '';
$('#StartDate').datepicker({
format: 'yyyy-mm-dd',
autoclose: false,
startDate: fullDate1.reFormat()
// beforeShowDay: NotBeforeToday
}).on('changeDate', function(selected) {
var startDate = new Date(selected.date.valueOf());
$('#EndDate').datepicker('setStartDate', startDate);
// alert(dumDate1);
// alert($('#EndDate').val());
if (startDate > dumDate1 || $('#EndDate').val() == '') {
// $('#EndDate').val($(this).val());
$('#EndDate').datepicker('setDate', startDate);
}
dumDate1 = new Date(selected.date.valueOf());
});
var fullDate2 = new Date();
var dumDate2 = '';
$('#EndDate').datepicker({
format: 'yyyy-mm-dd',
autoclose: false,
startDate: fullDate2.reFormat()
// beforeShowDay: NotBeforeToday
}).on('changeDate', function(selected) {
var startDate = new Date(selected.date.valueOf());
if (startDate < dumDate2 || $('#StartDate').val() == '') {
$('#EndDate').datepicker('setStartDate', startDate);
$('#StartDate').datepicker('setDate', startDate);
// $('#EndDate.day').css('background-color', 'coral');
}
dumDate2 = new Date(selected.date.valueOf());
});
//Discount Start Date and End Date
var dur = document.getElementById("StartDate");
var dur2 = document.getElementById("EndDate");
var checkboxDuration = document.getElementById("duration");
dur.disabled = true;
dur2.disabled = true;
dur.style.backgroundColor = "Gainsboro";
dur2.style.backgroundColor = "Gainsboro";
$("#duration").click(function() {
if (checkboxDuration.checked) {
dur.disabled = false;
dur2.disabled = false;
dur.style.backgroundColor = "white";
dur2.style.backgroundColor = "white";
// $("#Period").css("border-color", "Aqua");
} else {
dur.disabled = true;
dur2.disabled = true;
dur.style.backgroundColor = "Gainsboro";
dur2.style.backgroundColor = "Gainsboro";
// $("#Period").css("border-color", "coral");
}
});
//Discount Percentage or Value
$('input.terikat').keyup(function() {
if ($(this).val()) {
$('input.terikat').not(this).val('');
}
});
var numbersOnly = document.getElementsByClassName('numbers-only');
for (var i = 0; i < numbersOnly.length; i++) {
numbersOnly[i].addEventListener('keydown', function(e) {
var key = e.keyCode ? e.keyCode : e.which;
if (!([8, 9, 13, 27, 46, 110, 190].indexOf(key) !== -1 ||
(key == 65 && (e.ctrlKey || e.metaKey)) ||
(key >= 35 && key <= 40) ||
(key >= 48 && key <= 57 && !(e.shiftKey || e.altKey)) ||
(key >= 96 && key <= 105)
)) e.preventDefault();
});
}
});
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.4.1/css/bootstrap-datepicker3.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.4.1/js/bootstrap-datepicker.min.js"></script>
<script type="text/javascript">
function minmax(value, min, max) {
if (parseInt(value) < min)
return 0;
else if (parseInt(value) > max)
return 100;
else return value;
}
</script>
<h5 class="panel-title text-center title-content" id="topic"></h5>
<form class="form-horizontal" role="form" id="action" action="#" method="post" enctype="multipart/form-data">
<div class="modal-body">
<div id="error"></div>
<div class="form-group">
<div class="col-md-8 col-sm-8 col-xs-8">
<input type="hidden" class="form-control" id="DiscountID" name="DiscountID" />
</div>
</div>
<div class="form-group">
<label for="DiscountCode" class="col-md-4 col-sm-4 col-xs-4 control-label">Discount Code</label>
<div class="col-md-8 col-sm-8 col-xs-8">
<input type="text" class="form-control" id="DiscountCode" name="DiscountCode">
</div>
</div>
<div class="form-group">
<label for="DiscountName" class="col-md-4 col-sm-4 col-xs-4 control-label">Discount Name</label>
<div class="col-md-8 col-sm-8 col-xs-8">
<input type="text" class="form-control" id="DiscountName" name="DiscountName">
</div>
</div>
<div class="form-group">
<label for="Description" class="col-md-4 col-sm-4 col-xs-4 control-label">Discount Info</label>
<div class="col-md-8 col-sm-8 col-xs-8">
<textarea type="text" class="form-control" id="Description" name="Description" rows="3"></textarea>
</div>
</div>
<div class="form-group">
<div class="col-md-2 col-sm-2 col-xs-2"></div>
<div class="col-md-10 col-sm-10 col-xs-10 text-center">Discount is calculated by</div>
<label for="persen" class="col-md-4 col-sm-4 col-xs-4 control-label">
<!-- <input type="radio" id="persen" checked> -->
Percentage
</label>
<div class="col-md-3 col-sm-3 col-xs-3">
<input type="number" min="0" max="100" onkeyup="this.value = minmax(this.value, 0, 100)" class="form-control numbers-only terikat" id="Percentage" name="Percentage">
</div>
<label for="value" class="col-md-2 col-sm-2 col-xs-2 control-label">
<!-- <input type="radio" id="value"> -->
Value
</label>
<div class="col-md-3 col-sm-3 col-xs-3">
<input type="text" class="form-control numbers-only terikat" id="Value" name="Value">
</div>
</div>
<div class="form-group">
<div class="col-md-2 col-sm-2 col-xs-2"></div>
<label for="duration" class="col-md-10 col-sm-10 col-xs-10 text-center">
<input type="checkbox" id="duration"> Discount has limited duration
</label>
<label for="Period" class="col-md-4 col-sm-4 col-xs-4 control-label">Period</label>
<div class="col-md-4 col-sm-4 col-xs-4">
<div class="input-prepend input-group">
<span class="add-on input-group-addon"><i class="glyphicon glyphicon-calendar fa fa-calendar"></i></span>
<input type="text" class="form-control dur" id="StartDate" name="StartDate" readonly="">
</div>
</div>
<div class="col-md-4 col-sm-4 col-xs-4">
<!-- <div class="input-prepend input-group"> -->
<!-- <span class="add-on input-group-addon"><i class="glyphicon glyphicon-calendar fa fa-calendar"></i></span> -->
<input type="text" class="form-control dur" id="EndDate" name="EndDate" readonly="">
<!-- </div> -->
</div>
</div>
<div class="form-group">
<label for="Type" class="col-md-4 col-sm-4 col-xs-4 control-label">Discount Type</label>
<div class="col-md-8 col-sm-8 col-xs-8">
<select class="form-control" id="Type" name="Type">
<option selected disabled hidden>Please select</option>
<option value="Hardware">Hardware</option>
<option value="License">License</option>
</select>
</div>
</div>
<div class="form-group looptemplate" id="judul_detail">
<div class="col-md-4 col-sm-4 col-xs-4"></div>
<label class="col-md-4 col-sm-4 col-xs-4">
Select the item(s) whose discount will applied to:
</label>
<div class="col-md-4 col-sm-4 col-xs-4 text-right">
<input type="checkbox" class="control-label" id="select_all">
<label for="select_all">Select All</label>
</div>
<div class="col-md-2 col-sm-2 col-xs-2"></div>
</div>
<div id="Body"></div>
</div>
<div class="modal-footer">
<div id="error_insert_update"></div>
<button type="submit" class="btn btn-primary">
<i class="fa fa-save"></i> Save Change
</button>
<a type="button" href="#/master/discount" class="btn btn-success btn-addon m-b-sm">
<i class="fa fa-arrow-left"></i> Back
</a>
</div>
</form>
This is actually due to the change in Bootstrap 3 in the box-sizing to border-box. However, the problem is a from a couple of things:
1. Our height/width methods are subtracting the border width from the box, even though box-sizing is set to border-box.
2. The autosize module is doing a get/set from inside of an after listener. This wasn't breaking before because it was always setting maxHeight to the same value, so it never called the after listener
The fix, of course, is the one I sent up (which is to not fire the _syncHeight method if event.src == 'ui'), but we should also look into fixing our width/height methods as well to account for border-box being set.
Ok I have a drop down menu that is dynamically generated by .jsp and populated with data fetched from database.2 dropdown list and 2 datepicker
The problem that I am having is with a JS validation, am not so good with JavaScript but for the purposes of my mini project I have to work with it anyway....
The problem is that with JS I am checking if a user has selected two drop-down fields and two date pickers so the form can be submitted and the list of the searching should be shows below the button else display a warning message indicating that the drop-downs and date pickers have not been filled.
Where should I do the validation of those 4 fields? How to use the'EXECUTE' to call the class from 'SelectOperation.java'(as per attached).
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hibernate.Session;
import entityBeans.AccessLevel;
import entityBeans.Business;
import entityBeans.CustomerBranch;
import entityBeans.Menu;
import entityBeans.TransactionLog;
import entityBeans.User;
import cmnUtilities.CmnConstants;
public class SelectOperation {
Session session = ConnectionMySQL.getInstance().getConnection();
private static SelectOperation selectData = new SelectOperation();
private SelectOperation()
{
}
public User Select_login_User(String user_id)
{
User loginUser = null;
try
{
loginUser = (User)session.get(User.class,user_id.trim());
}
catch(Exception exception)
{
exception.printStackTrace();
}
return loginUser;
}
public User Chech_User_existence(String user_id)
{
User CheckUser = null;
try
{
CheckUser = (User)session.get(User.class,user_id.trim());
}
catch(Exception exception)
{
exception.printStackTrace();
}
return CheckUser;
}
public List<List<Menu>> Select_User_Menu(int Access_id)
{
List<Menu> UserMenu = null;
List<List<Menu>> Menus = new ArrayList<List<Menu>>();
AccessLevel acl = null ;
try
{
if(session.isOpen())
{
// acl = (AccessLevel)session.get(AccessLevel.class,Access_id.trim());
// StringBuffer AccessLevel = formatedMenuIds(acl.getMenuId());
// System.out.println(AccessLevel);
//UserMenu = (List<Menu>)session.createQuery("from Menu where menuId in ("+menuIds+")").list();
UserMenu = (List<Menu>)session.createQuery("from Menu where menuAccLevel >='"+Access_id+"'").list();
List<Menu> MainModule = new ArrayList<Menu>();
List<Menu> SubModule = new ArrayList<Menu>();
for(Menu seperateMenu : UserMenu)
{
if((seperateMenu.getMenuId().length()) == CmnConstants.MAIN_MENU)
{
MainModule.add(seperateMenu);
}
if((seperateMenu.getMenuId().length()) == CmnConstants.SUB_MENU)
{
SubModule.add(seperateMenu);
}
}
for(Menu disp1 : MainModule)
{
List<Menu> finaly = new ArrayList<Menu>();
finaly.add(disp1);
for(Menu disp2 : SubModule)
{
if(disp2.getMenuId().startsWith(disp1.getMenuId()))
{
finaly.add(disp2);
}
}
Menus.add(finaly);
}
System.out.println(Menus);
}
else
{
System.out.println("session closed");
}
}
catch(Exception exception)
{
exception.printStackTrace();
}
return Menus;
}
//METHOD RETURNS ALL ACCESS LEVEL CODE AND IT'S DESCRIPTION
public List<AccessLevel> getAllAccessLevel()
{
List<AccessLevel> accessList = null;
try
{
accessList = (List<AccessLevel>)session.createQuery("from AccessLevel").list();
System.out.println(accessList);
}
catch(Exception exception)
{
exception.printStackTrace();
}
return accessList;
}
//METHOD TO SELECT ALL BRANCH IDS
public List<CustomerBranch> getAllCustomerBranch()
{
List<CustomerBranch> branchList = null;
try
{
branchList = (List<CustomerBranch>)session.createQuery("from CustomerBranch").list();
System.out.println(branchList);
}
catch(Exception exception)
{
exception.printStackTrace();
}
return branchList;
}
//METHOD TO SELECT ALL TRANSACTION_LOG DETAILS
public List<TransactionLog> getAllTransactionLog()
{
List<TransactionLog> TxnList = null;
try
{
TxnList = (List<TransactionLog>)session.createQuery("from TransactionLog").list();
System.out.println(TxnList);
}
catch(Exception exception)
{
exception.printStackTrace();
}
return TxnList;
}
//METHOD TO SELECT ALL BUSINESS
public List<Business> getAllBusiness()
{
List<Business> BusinessList = null;
try
{
BusinessList = (List<Business>)session.createQuery("from Business").list();
System.out.println(BusinessList);
}
catch(Exception exception)
{
exception.printStackTrace();
}
return BusinessList;
}
public Business SelectBusiness_Id(String business_id)
{
Business CheckBusiness_id = null;
try
{
CheckBusiness_id = (Business)session.get(Business.class,business_id.trim());
}
catch(Exception exception)
{
exception.printStackTrace();
}
return CheckBusiness_id;
}
public CustomerBranch SelectBranch_Id(String branch_id)
{
CustomerBranch CheckBranch_id = null;
try
{
CheckBranch_id = (CustomerBranch)session.get(CustomerBranch.class,branch_id.trim());
}
catch(Exception exception)
{
exception.printStackTrace();
}
return CheckBranch_id;
}
public TransactionLog FromDateSel(String txn_date)
{
TransactionLog transDateFrom = null;
try
{
transDateFrom = (TransactionLog)session.get(TransactionLog.class,txn_date.trim());
}
catch(Exception exception)
{
exception.printStackTrace();
}
return transDateFrom;
}
public TransactionLog ToDateSel(String txn_date)
{
TransactionLog transDateTo = null;
try
{
transDateTo = (TransactionLog)session.get(TransactionLog.class,txn_date.trim());
}
catch(Exception exception)
{
exception.printStackTrace();
}
return transDateTo;
}
// Will returns all menu ids
/*public StringBuffer formatedMenuIds(String text)
{
String[] val = text.split(",");
StringBuffer sb = new StringBuffer();
for(String cc :val)
{
sb.append("'"+cc+"'"+",");
}
if(sb.toString().endsWith(","))
{
sb.delete(sb.length()-1, sb.length());
}
return sb;
}*/
public static SelectOperation getInstance()
{
return selectData;
}
}
I think i just need so more javascript to do this i just dont know how. Thanks for your help in advance.
<% #page import = "allDatabaseOperations.SelectOperation" %>
<% #page import = "java.util.List" %>
<% #page import = "entityBeans.TransactionLog" %>
<% #page import = "entityBeans.Business" %>
<% #page import = "entityBeans.CustomerBranch" %>
<% #page language = "java"
contentType = "text/html; charset=ISO-8859-1"
pageEncoding = "ISO-8859-1" %>
< !DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< link rel = "stylesheet"
href = "../styles/style.css"
type = "text/css" / >
<%
List < TransactionLog > Allbranches = SelectOperation.getInstance().getAllTransactionLog();
List < Business > Businesslevel = SelectOperation.getInstance().getAllBusiness();
List < CustomerBranch > CustBranch = SelectOperation.getInstance().getAllCustomerBranch(); %>
< link rel = "stylesheet"
href = "//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" >
< script src = "//code.jquery.com/jquery-1.10.2.js" > < /script>
<script src="/ / code.jquery.com / ui / 1.11.4 / jquery - ui.js "></script>
<link rel="
stylesheet " href=" / WebContent / styles / style.css ">
<script>
$(function() {
$( "#
fromdate " ).datepicker({
showOn: "
button ",
buttonImage: ".. / .. / images / calendar.png ",
buttonImageOnly: true,
buttonText: "
Select date "
});
});
$(function() {
$( "#
todate " ).datepicker({
showOn: "
button ",
buttonImage: ".. / .. / images / calendar.png ",
buttonImageOnly: true,
buttonText: "
Select date "
});
});
</script>
</head>
<body>
<form>
<table align="
center " style="
background - color: #F5D0A9;
padding: 70px;
border - top: 1px;
">
<tr>
<%-- added by Maihani on 181115(Wed) --%>
<td>
Business Id :-
</td>
<%--<td> <input type="
text " name="
BusinessId " size = "
46 "/> --%>
<td> <select name="
Business ">
<%for(Business business : Businesslevel) {%>
<option value=" <%= business.getBusinessId() %> "><%=business.getBusinessName()%></option>
<%}
%>
</select><%-- </td>--%>
</td>
</tr>
<td>
Branch Id :
</td>
<td>
<select name="
CustomerBranch ">
<%for(CustomerBranch custBranch : CustBranch) {%>
<option value=" <%= custBranch.getBranchId() %> "><%=custBranch.getBranchName()%></option>
<%}
%>
</select>
</td>
</tr>
<tr>
<td>
From Date :
</td>
<td>
<%-- <input type="
text " name="
BrachId " size = "
46 "/> --%>
<input type="
text " id="
fromdate ">
</td>
</tr>
<tr>
<td>
To Date :
</td>
<td>
<%--<input type="
text " name="
BrachId " size = "
46 "/> --%>
<input type="
text " id="
todate ">
</td>
</tr>
<tr>
<td>
</td>
<td align="
center "><input type="
submit " value="
Search Transaction "/></td>
</tr>
<tr >
<td colspan="
2 ">
<table align="
center ">
<tr bgcolor="
#333333">
<td><font color= "#FFFFFF" > User ID < /font></td >
< td > < font color = "#FFFFFF" > Branch ID < /font></td >
< td > < font color = "#FFFFFF" > Transaction Code < /font></td >
< td > < font color = "#FFFFFF" > Transaction Date < /font></td >
< td > < font color = "#FFFFFF" > Transaction Time < /font></td >
< /tr>
<%for(TransactionLog txn : Allbranches){%>
<tr bgcolor="#F2F2F2">
<td><%=txn.getUserId()%></td >
< td > <%= txn.getBranchId() %> < /td>
<td><%=txn.getTxnCode() %></td >
< td > <%= txn.getTxnDate() %> < /td>
<td><%=txn.getTxnTime() %></td >
< /tr>
<%} %>
</table >
< /td>
<td></td >
< /tr>
</table >
< /form>
</body >
< /html>
On the submit button, you can call a JavaScript function that in turn validates the values of your 4 input types and based on the validation result, you can continue with the form submit or show error message
<input type="submit" onclick="validateForm()" value="Search Transaction" />
<script>
function validateForm(){
var ip1 = $("#firstdropdownId").val();
var ip2 = $("#otherdropdownId").val();
var date1 = $("#firstdateId").val();
var date2 = $("#otherdateId").val();
if(ip1 == null || ip1.length.trim() == 0 || ip2 == null || ip2.length.trim() == 0 || idt1 == null || dt1.length.trim() == 0 || dt2 == null || dt2.length.trim() == 0){
$("#errorMessageDiv").show();
return false;
}
else{
$("#errorMessageDiv").hide();
return true;
}
}
</script>
Or if you want to validate from java end, you can make an ajax call by passing the parameters as the input values, which will return the validate status of your form.
I know this question has been asked previously in this forum. However I have a problem when implementing the code.
I want the system to check if the ID number is a valid South African ID number and get the customer's age, gender and date of birth as well.
JavaScript file in my view:
<script type='text/javascript'>
//<![CDATA[
$(window).load(function () {
function Validate() {
// first clear any left over error messages
$('#error p').remove();
// store the error div, to save typing
var error = $('#error');
var idNumber = $('#idnumber').val();
// assume everything is correct and if it later turns out not to be, just set this to false
var correct = true;
//Ref: http://www.sadev.co.za/content/what-south-african-id-number-made
// SA ID Number have to be 13 digits, so check the length
if (idNumber.length != 13 || !isNumber(idNumber)) {
error.append('<p>ID number does not appear to be authentic - input not a valid number</p>');
correct = false;
}
// get first 6 digits as a valid date
var tempDate = new Date(idNumber.substring(0, 2), idNumber.substring(2, 4) - 1, idNumber.substring(4, 6));
var id_date = tempDate.getDate();
var id_month = tempDate.getMonth();
var id_year = tempDate.getFullYear();
var fullDate = id_date + "-" + (id_month + 1) + "-" + id_year;
if (!((tempDate.getYear() == idNumber.substring(0, 2)) && (id_month == idNumber.substring(2, 4)-1) && (id_date == idNumber.substring(4, 6)))) {
error.append('<p>ID number does not appear to be authentic - date part not valid</p>');
correct = false;
}
// get the gender
var genderCode = idNumber.substring(6, 10);
var gender = parseInt(genderCode) < 5000 ? "Female" : "Male";
// get country ID for citzenship
var citzenship = parseInt(idNumber.substring(10, 11)) == 0 ? "Yes" : "No";
// apply Luhn formula for check-digits
var tempTotal = 0;
var checkSum = 0;
var multiplier = 1;
for (var i = 0; i < 13; ++i) {
tempTotal = parseInt(idNumber.charAt(i)) * multiplier;
if (tempTotal > 9) {
tempTotal = parseInt(tempTotal.toString().charAt(0)) + parseInt(tempTotal.toString().charAt(1));
}
checkSum = checkSum + tempTotal;
multiplier = (multiplier % 2 == 0) ? 1 : 2;
}
if ((checkSum % 10) != 0) {
error.append('<p>ID number does not appear to be authentic - check digit is not valid</p>');
correct = false;
};
// if no error found, hide the error message
if (correct) {
error.css('display', 'none');
// clear the result div
$('#result').empty();
// and put together a result message
$('#result').append('<p>South African ID Number: ' + idNumber + '</p><p>Birth Date: ' + fullDate + '</p><p>Gender: ' + gender + '</p><p>SA Citizen: ' + citzenship + '</p>');
}
// otherwise, show the error
else {
error.css('display', 'block');
}
return false;
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
$('#idCheck').submit(Validate);
});//]]>
</script>
This is where I want ID number to be entered:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h4>
#ViewBag.Error
#ViewBag.amount#ViewBag.interest#ViewBag.total
</h4>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div id="page-wrapper">
<div class="container-fluid">
<div class="row">
<form role="form">
<div class="form-group">
<div class="row">
<div class="col-md-2">
#Html.LabelFor(m => m.idNumber, "ID Number*")
</div>
<div class="col-md-3">
#Html.ValidationMessageFor(m => m.idNumber)
#Html.TextBoxFor(m => m.idNumber, new {#placeholder = "ID Number", style = "width: 200px;", #class = "form-control"})
</div>
</div>
This is the code that was suggested for the customer to enter his ID number
<div id="error"></div>
<form id="idCheck">
<p>
Enter the ID Number: <input id="idnumber"/>
</p>
<p>
<input type="submit" value="Check"/>
</p>
</form>
<div id="result"></div>
When I try to insert this code out of my #using(Html.BeginForm()) it works perfectly, however when I put it in place of the #Html.TextBoxFor(m => m.idNumber, new {#placeholder = "ID Number", style = "width: 200px;", #class = "form-control"}) it doesn't work.
Any idea why and how I can fix that?
How can we make the checkboxes persist for a user even when he reloads the page?
Please if you have the Javascript expertise can you help me with the relevant AJAX calls or give me some further guidance so I can pursue the answer on my own.
Every three boxes the user checks a new set of three boxes will show. How can we keep these AJAX induced boxes from disappearing?
habits/_form.html.erb
<label id="<%= #habit.id %>" class="habit-id"> Missed: </label>
<% #habit.levels.each_with_index do |level, index| %>
<% if #habit.current_level >= (index + 1) %>
<p>
<label id="<%= level.id %>" class="level-id"> Level <%= index + 1 %>: </label>
<%= check_box_tag nil, true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 1, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 2, {class: "habit-check"} %>
</p>
<% end %>
<% end %>
habit.js
$(document).ready(function() {
var handleChange = function() {
habit = $(this).parent().prev().attr("id");
level = $('label', $(this).parent()).attr("id");
if ($(this).is(":checked")) {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed",
method: "POST"
});
localStorage.setItem("habit_"+habit+"_"+level, true);
} else {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
method: "DELETE"
});
localStorage.setItem("habit_"+habit+"_"+level, true);
}
if (!$('input[type="checkbox"]:not(:checked)', $(this).parent()).length) {
/* this is just an example, you will have to ammend this */
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(".habit-check").on('change',handleChange);
}
}
$(".habit-check").on('change',handleChange);
});
habit.rb
class Habit < ActiveRecord::Base
belongs_to :user
has_many :comments, as: :commentable
has_many :levels
serialize :committed, Array
validates :date_started, presence: true
before_save :current_level
acts_as_taggable
scope :private_submit, -> { where(private_submit: true) }
scope :public_submit, -> { where(private_submit: false) }
attr_accessor :missed_one, :missed_two, :missed_three
def save_with_current_level
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.save
end
def self.committed_for_today
today_name = Date::DAYNAMES[Date.today.wday].downcase
ids = all.select { |h| h.committed.include? today_name }.map(&:id)
where(id: ids)
end
def current_level_strike
levels[current_level - 1] # remember arrays indexes start at 0
end
def current_level
return 0 unless date_started
def committed_wdays
committed.map do |day|
Date::DAYNAMES.index(day.titleize)
end
end
def n_days
((date_started.to_date)..Date.today).count do |date|
committed_wdays.include? date.wday
end - self.missed_days
end
case n_days
when 0..9
1
when 10..24
2
when 25..44
3
when 45..69
4
when 70..99
5
else
6
end
end
end
days_missed_controller
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days - 1
habit.save
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end
Here's the gist of it: https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2
Please let me know if you need any further explanation, code, or pictures. Thank you so much for your time!
Looking at your code, shouldnt one of the setItem calls on localstorage set checkbox value to false
if ($(this).is(":checked")) {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed",
method: "POST"
});
localStorage.setItem("habit_"+habit+"_"+level, true);
} else {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
method: "DELETE"
});
localStorage.setItem("habit_"+habit+"_"+level, false);//<--- ? ?
}
i made a quick fiddle to show how you can pass objects into localStorage, and load them later.
When you first load the page, check if user has something saved, if so, skip ajax requests etc, and simply create the rows based on the info on localStorage.
http://jsfiddle.net/rainerpl/s39c9fws/18/
<div id="container">
<div class="row" id="row_1">
<span class="label">Row 1:</span>
<input type="checkbox" name="test" id="check_1" value="1" />
<input type="checkbox" name="test" id="check_2" value="1" />
<input type="checkbox" name="test" id="check_3" value="1" />
</div>
</div>
<input type="button" value="clear saved values" onclick="localStorage.setItem('checkbox_rows', false)"/>
<input type="button" value="add new row" onclick="addNewRow()"/>
var saveChecks = function() {
var rows = $(".row"), saveObj = [], alreadySavedRows = localStorage.getItem("checkbox_rows");
if ( alreadySavedRows ) {alreadySavedRows = JSON.parse(alreadySavedRows);}
console.log("saveChecks", rows.length);
if ( alreadySavedRows && alreadySavedRows.length ) {saveObj = alreadySavedRows;}
var replacePreviousRow = function(row_obj) {
var i;
for ( i = 0; i < saveObj.length; i++ ) {
if ( saveObj[i].row_id == row_obj.row_id ) {
// console.log("replaced previous", row_obj);
saveObj[i] = row_obj;return true;
}
}
return false;
}
$.each(rows, function( key, val ) {
var
checks = $(val).find("input[type='checkbox']"),
rowObj = {"row_id": $(val).attr("id"), "checkboxes": []};
;
rowObj.label = $(val).find(".label").text();
$.each(checks, function( key, check ) {
check= $(check);
rowObj.checkboxes.push({
check_id: check.attr("id"),
checked: check.prop('checked'),
value: check.attr("value")
});
});
// console.log("rowObj before", rowObj);
if ( !replacePreviousRow(rowObj ) ) { saveObj.push(rowObj);}
});
//console.log("saveObj", saveObj);
localStorage.setItem( "checkbox_rows", JSON.stringify(saveObj) );
}
var container = $("#container");
var loadChecks = function() {
var rows = localStorage.getItem("checkbox_rows"), i, j, row, check, rowElem, checkElem;
if ( !rows ) {return false;}
rows = JSON.parse(rows);
if ( !rows || !rows.length ) {return false;}
//console.log("rows:", rows);
for ( i = 0; i < rows.length; i++ ) {
row = rows[i];
//remove any previously existing rows
$("#" + row.row_id).remove();
rowElem = $("<div class='row'></div>");
rowElem.attr("id", row.row_id);
container.append(rowElem);
rowElem = $("#" + row.row_id );
rowElem.append("<span class='label'>"+row.label+"</span>");
for ( j = 0; j < row.checkboxes.length; j++ ) {
check = row.checkboxes[j];
checkElem = $("<input type='checkbox' name='test'/>");
checkElem.attr("id", check.check_id);
rowElem.append(checkElem);
checkElem = $("#" + check.check_id);
checkElem.attr("id", check.check_id);
checkElem.attr("value", check.value);
checkElem.prop("checked", check.checked);
}
}
}
window.addNewRow = function() {
var rowElem = $("<div class='row'></div>"), i, row_id, checkElem;
row_id = Math.round(1000*Math.random());
rowElem.attr("id", "row_" + row_id );
rowElem.append("<span class='label'>Row id:" + row_id +"</span>");
for (i = 0; i < Math.ceil( Math.random() * 10 ); i++ ) {
checkElem = $("<input type='checkbox' name='test' />");
checkElem.attr("id", "check_" + row_id + "_" + i );
checkElem.val(i);
rowElem.append(checkElem);
}
container.append(rowElem);
setTimeout(saveChecks, 100);
}
$().ready(function() {
console.log("ready");
setTimeout( loadChecks, 30);
$("body").on("click", ".row", function(evt) {
var row = $(evt.currentTarget), notChecked = row.find("input:not(:checked)").length, id;
console.log("evt",notChecked);
if ( !notChecked ) {
id = Math.ceil( 1000 * Math.random() );
row.append("<input type='checkbox' name='test' id='check_"+id+"' value='1' />");
}
saveChecks();
});
});
I'm trying to submit a javscript generated value.
The script is:
var save = function () {
var left = document.getElementById("left"); //Get a select box
var result = document.exchange; //get the form
result.value = ""; //set it's value to ""
for (i = 0; i < right.length; i++) {
result.value = result.value + "," + left.options[i].value; //set it's value to the values of the select box, divided by commas.
}
result.submit(); //submit the form
}
But my form only submits this:
{
"utf8" = > "✓",
"authenticity_token" = > "9gf3upm65ugEhsNvdcaykjdlg7xZbOyTiWJs79SnY3A=",
"timespan_id" = > {
"name" = > ["",
""]
},
"subgroup_id" = > "369141985"
}
The form is generated by my Rails. It looks like this:
<%= form_tag(subgroup_change_timespans_path(#subgroup), {
id: 'exchange',
name: 'exchange'
}) do %> <% timespans_array = #subgroup.timespans.all.map { | timespan | [timespan.name, timespan.id]
} %> <%= select(: timespan_id, : name, options_for_select(timespans_array), {}, {: multiple = > true,
: style = > "width: 300px; background-color: #9FE",
: width = > "300",
: size = > 20,
: id = > "left"
}) %> <%= link_to "<<", {
anchor: "",
remote: true
}, {
id: "toleft",
w_command: "add_timespan",
w_auth: form_authenticity_token,
w_controller: "subgroups",
w_id: #subgroup.id.to_s
} %> <%= link_to ">>", {
anchor: "",
remote: true
}, {
id: "toright",
w_command: "rem_timespan",
w_auth: form_authenticity_token,
w_controller: "subgroups",
w_id: #subgroup.id.to_s
} %> <% timespans_array = Timespan.all.map { | timespan | [timespan.name, timespan.id]
} %> <%= select(: timespan_id, : name, options_for_select(timespans_array), {}, {: multiple = > true,
: style = > "width: 300px; background-color: #F99",
: width = > "300",
: size = > 20,
: id = > "right"
}) %> <%= link_to "save", {
anchor: "",
remote: true
}, {
id: "save"
} %> <% end %>
But as I told you:
It just submits the names of two hidden fields:
<input name="timespan_id[name][]" type="hidden" value="" />
<input name="timespan_id[name][]" type="hidden" value="" />
I think, there is something wrong with these two. But I don't get what.
Do you have any Ideas?
#Малъ Скрылевъ: It has to be this way.
The form should look like this:
I found a Solution for my Problem:
I had to put the select boxes outside of the form, which removed the this parameter:
"timespan_id" = > {
"name" = > ["",
""]
Then I added a hidden_field_tag called 'string' inside the form.
Then at last, I changed my save function to:
var save=function()
{
var left = document.getElementById("left");
var result;
result="";
for(i=0;i<left.length;i++)
{
result = result+","+left.options[i].value;
}
var string=document.getElementById("string");
alert(result);
string.value=result;
document.exchange.submit();
}