Javascript problem with loop for hiding/showing element depending on checkbox - javascript

I'm trying to hide/show an element depending on if the corresponding checkbox is checked or not.
There are two checkbox each one corresponding to an element. The name of thos checkboxes and elements depends on a variable stored in vendorIds array.
The problem is that the code only works for ths second variable stocked in the array.
I suppose that the problem comes from the "for" loop but I'am beginner and I don't see what's wrong.
Here is the code :
<script>
jQuery(function($){
console.log(vendorIds);
for (var i=0; i<vendorIds.length; i++) {
var vendorId = vendorIds[i];
console.log(vendorId);
var vendorId = vendorIds[i];
console.log(vendorId);
var ism = 'input[name^="shipping_method['+vendorId+']"]', ismc = ism+':checked',
csa = 'input#ship-to-different-address-checkbox',
rq = '-required', vr = 'validate'+rq, w = 'woocommerce', wv = w+'-validated',
iv = '-invalid', fi = '-field', wir = w+iv+' '+w+iv+rq+fi,
b = '#wcfmd_delvery_time_'+vendorId,
livraison = 'Livraison:1';
console.log(b);
}
(function(i){
// Utility function to shows or hide checkout fields
function showHide( action='show', selector='' ){
if( action == 'show' )
$(selector).show(function(){
$(this).addClass(vr);
$(this).removeClass(wv);
$(this).removeClass(wir);
if( $(selector+' > label > abbr').html() == undefined )
$(selector+' label').append('<?php echo $required_html; ?>');
});
else
$(selector).hide(function(){
$(this).removeClass(vr);
$(this).removeClass(wv);
$(this).removeClass(wir);
if( $(selector+' > label > abbr').html() != undefined )
$(selector+' label > .required').remove();
});
}
// Initializing at start after checkout init (Based on the chosen shipping method)
setTimeout(function(){
if( $(ismc).val() == livraison ) // Choosen "livraison" (Hidding "Take away")
{
showHide('show',b);
}
else
{
showHide('hide',b);
}
}, 100);
// When shipping method is changed (Live event)
$( 'form.checkout' ).on( 'change', ism, function() {
if( $(ismc).val() == livraison )
{
showHide('show',b);
}
else
{
showHide('hide',b);
}
});
})(i);
});
</script>
Thanks in advance.
Have an nice day.
Fred

Here is the answer if one day someone need it
<script>
jQuery(document).ready(function($){
for (var i=0; i<vendorIds.length; i++) {
var vendorId = vendorIds[i];
var ism = 'input[name^="shipping_method['+vendorId+']"]', ismc = ism+':checked',
b = '#livraison_'+vendorId,
livraison = 'Livraison:1';
// When shipping method is changed (Live event)
$( 'form.checkout' ).on( 'change', ism, function(e) {
var name = e.currentTarget.name;
var dataValue = $('input[name ="'+name+'"]').attr('data-index');
var b = '#livraison_'+dataValue;
var ismc = 'input[name^="shipping_method['+dataValue+']"]:checked';
var livraison = 'Livraison:1';
if( $(ismc).val() == livraison )
{
$(b).show();
}
else
{
$(b).hide();
}
});
// Initializing at start after checkout init (Based on the chosen shipping method)
setTimeout(function(){
$( "input.shipping_method" ).each(function() {
var name = $(this).attr("name");
var type = $(this).attr("type");
var dataValue = $(this).attr('data-index');
var b = '#livraison_'+dataValue;
var ismc = 'input[name^="shipping_method['+dataValue+']"]:checked';
var livraison = 'Livraison:1';
if( ($(this).attr("type") == 'hidden') ) {
if( $(this).val() == 'Livraison:1' ) // Choosen "retrait sur place" (Hidding "Take away")
{
$(b).show();
} else
{
$(b).hide();
}
} else {
if($(this).is(':checked'))
{
if( $(this).val() == 'Livraison:1' ) // Choosen "retrait sur place" (Hidding "Take away")
{
$(b).show();
} else
{
$(b).hide();
}
}
}
});
}, 100);
}
});
</script>

Related

JS: How to enable submit button in form only if all inputs pass validation

I have a simple input that I'm using an keyup event listener on. If the input length is too short, the span element will remove the class on it that hides the element and display "Input too short".
If I have multiple inputs, how can I only enable the Submit button if all fields pass the validation.
Unfortunately, I'm thinking in a React-way and would accomplish this via state.
<style type="text/css">
.hide-first {
display: none;
}
.hide-last {
display: none;
}
</style>
<div>
<div>
<input id="first-name" />
<span id="validation-span" class="hide-first">Input too short</span>
</div>
<button>Submit</button>
</div>
<script type="text/javascript">
let firstName = document.getElementById( 'first-name' );
let span = document.getElementById( 'validation-span' );
firstName.addEventListener( 'keyup', () => {
console.log( event.target.value.length )
if ( event.target.value.length < 5 ) {
span.classList.remove( 'hide-first' )
} else {
span.classList.add( 'hide-first' )
}
} );
</script>
All your inputs could call the same validation function that checks everything except inputs that are empty. Only show the submit button if they all succeed and show the appropriate message on inputs that fail the validation.
Pseudo-code:
boolean succes = true
if username is invalid and not empty
username invalid message
success = false
if password is invalid and not empty
password invalid message
success = false
if success is true
show submit button
At first add style your button style="display:none". You can use jQuery as bellow
$( document ).ready( function () {
var _rules = {
"first-name": function ( $owner ) {
var val = $owner.val();
if ( !val ) return false;
if ( val.length < 5 ) return false;
return true;
}
};
//Validate here
function validate(total_mark) {
var mark = 0;//total mark
//Read all input value, than check rules
$( 'input' ).each( function () {
if ( 'function' !== typeof ( _rules[this.id] ) ) return;
var $owner = $( this );
var result = _rules[this.id]( $owner );
if ( !result ) {
mark -= 1;
$owner.next().removeClass( 'hide-first' );
return;
}
$owner.next().addClass( 'hide-first' );
mark += 1;
return;
} );
return mark;
};
var $btn = $( 'button' );
//Register keyup event for all input
var total_input = 1;
$( 'input' ).on( "keyup", function ( e ) {
e.preventDefault();
$btn.css( "display", "none" );
if ( validate() < total_input ) return;
$btn.css( "display", "" );
} );
} );
Something like this should work
<div>
<div>
<input id="first-name" onchange='validation()'/>
<span id ="validation-span" class="hide-first">Input too short</span>
</div>
<button id='submit-button'>
Submit
</button>
</div>
<script type="text/javascript">
function validateFirstName() {
let firstName = document.getElementById('first-name');
let span = document.getElementById('validation-span');
if (event.target.value.length < 5) {
span.classList.remove('hide-first')
return True
}
span.classList.add('hide-first')
return False
}
function validation() {
let submitButton = document.getElementById('submit-button');
submitButton.disabled = validateFirstName();
}
</script>
As you add additional fields, you should create the validation function for that field, and then running it inside validation() like:
function validation() {
let submitButton = document.getElementById('submit-button');
submitButton.disabled = validateFirstName() && validateSecondField() && validateThirdField() &&...;
}
Remember to add to the html input the onchange event listener.
Simple logic. Make a function that checks if all of the fields are validated, and call it from within the onkeyup event. A seemingly straight-forward way would be like this:
let firstName = document.getElementById('first-name'),
lastName = document.getElementById('last-name'),
company = document.getElementById('company-name');
let span = document.getElementById('validation-span'),
span1 = document.getElementById('validation-span1'),
span2 = document.getElementById('validation-span2'),
conditions = [],
length = 3;
firstName.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (event.target.value.length < 5) {
span.classList.remove('hide-first')
conditions[0] = true;
} else {
span.classList.add('hide-first')
conditions[0] = false;
}
})
lastName.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (event.target.value.length < 5) {
span1.classList.remove('hide-first')
conditions[1] = true;
} else {
span1.classList.add('hide-first')
conditions[1] = false;
}
})
company.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (event.target.value.length < 5) {
span2.classList.remove('hide-first')
conditions[2] = true;
} else {
span2.classList.add('hide-first')
conditions[2] = false;
}
})
function checkAllTrueAndActivateSubmitBtn() {
var result = true;
for(var i = 0; i < length; i++) {
if(!conditions[i]) {
result = false;
}
}
if(result) {
submitBtn.classList.add("shown"); //or whatever
}
}
but of course, the more fields you have,the more messy this becomes. A more efficient way would be to use an array for the fields, and conditions:
let IDsAndConditions = {
'first-name':{
condition: (x) => x.length >= 5,
span: 'validation-span'
},
'last-name': {
condition: (x) => x.length >= 8,
span: 'validation-span-lastName'
},
'phoneNumber':{
condition: (x) => x.match(/^-{0,1}\d+$/),//or whatever
span:"phone-span"
}
};
var conditions = [];
var num = 0;
for(var k in IDsAndConditions) {
var cur = IDsAndConditions[k];
var el = document.getElementById(k);
var span = document.getElementById(cur["span"]);
if(el && span) {
el.addEventListener('keyup', () => {
console.log(event.target.value.length)
if (!cur["condition"](event.target.value)) {
span.classList.remove('hide-first')
conditions[num] = true;
} else {
span.classList.add('hide-first')
conditions[num] = false;
}
checkAllTrueAndActivateSubmitBtn();
});
} else {
conditions[num] = true; //this is to make the validation work even if the element doesn't exist
}
num++;
}
function checkAllTrueAndActivateSubmitBtn() {
var result = true;
for(var i = 0; i < IDsAndConditions.length; i++) {
if(!conditions[i]) {
result = false;
}
}
if(result) {
submitBtn.classList.add("active"); //or whatever
} else {
submitBtn.classList.remove("active"); //even if it was active at one point, if someone changes a field to an incorrect value, it deactivates again
}
}

locaStorage and javascript loop

I have a problem with my little app,
You can see it here : http://jsfiddle.net/47bV8/
My problem is : I enter some notes then when I "clear All", and i re-enter a note,
the console returns me lsReturn == null on the refresh .
I understand Why but can't see how to solve the problem.
In fact the value of my 'var i' is not 0 after clear all (it's value is the last note i've entered so 5 if i've entered 5 notes), so when i re enter a note it's task-6, so on the refresh my first loop fails...
I tried to set var i = 0 after the localstorage.clear but it doesn't worK...
jQuery(document).ready(function() {
// Initial loading of tasks
var i = 0;
// clear All
jQuery('.clear').on('click',function(e){
e.preventDefault();
jQuery('#tasks li').remove();
localStorage.clear();
jQuery(this).data('erase', true);
});
if(localStorage.length){
for( i = 0; i < localStorage.length; i++){
var lsReturn = JSON.parse(localStorage.getItem('task-'+i));
if (lsReturn == null){ // HERE IS THE PROBLEM
var b = 0; //
}else{
jQuery("#tasks").append("<li id='task-"+i+"'>" + lsReturn.text + " <a href='#'>Delete</a></li>");
jQuery('#tasks li#task-'+i+'').css('background-color', lsReturn.color );
}
}
}else{
jQuery('header').after("<p class='error'>no messages</p>");
}
// ----------------- ADD A TASK ----------------------//
jQuery("#tasks-form").submit(function() {
if (jQuery("#task").val() != "" ) {
jQuery('#task').attr('placeholder', "Enter a note")
var text = jQuery("#task").val();
var color = jQuery('#color').val();
var allNotes = {};
var note = {};
note.text = text;
note.color = color;
allNotes['task-'+i] = note;
var lsStore = JSON.stringify(allNotes['task-'+i ]);
localStorage.setItem( "task-"+i, lsStore);
var lsStoreReturn = JSON.parse(localStorage.getItem("task-"+i, lsStore));
jQuery("#tasks").append("<li id='task-"+i+"'>"+ lsStoreReturn.text +"<a href='#'>Delete</a></li>");
jQuery('#tasks li#task-'+i+'').css('background-color', lsStoreReturn.color );
jQuery("#task").val("");
i++;
}else{
jQuery('#task').attr('placeholder', "nothing in it !")
}
return false;
});
// ----------------- REMOVE A TASK ----------------------//
jQuery("#tasks li a").live("click", function(e) {
e.preventDefault();
localStorage.removeItem(jQuery(this).parent().attr("id"));
jQuery(this).parent().remove();
// PROBLEM solved : if I remove a task #2 in a list of 4 item for example, if i refresh the list become 0, 1, 3, 4,
// so the locastorage loop doesn't find the item 2
for(i=0; i<localStorage.length; i++) { // SO I check my locastorage
if(localStorage.getItem("task-"+i) == null) { // If the task 4 doesn't exist
localStorage.setItem("task-"+i, localStorage.getItem('task-' + (i+1)));
// I do : create task-4
// and give him the value of task 5
localStorage.removeItem('task-'+ (i+1) );
// the i remove task 5
// so the loop wiil not find task 5 and give him the value of task 6 etc..
}
}
});
});​
Reset your i variable in the following way
jQuery('.clear').on('click',function(e) {
e.preventDefault();
jQuery('#tasks li').remove();
localStorage.clear();
jQuery(this).data('erase', true);
// Need to reset the index counter here.
i = 0;
});
Here is an updated/working fiddle.

Jquery form get default values

If I have code like this:
<form id="test_form">
<input type="text" value="Original value" />
</form>
Then using jQuery I run this code:
$('#test_form input').val('New value');
So input have new value, but I wanna get the old one, so I do:
$('#test_form')[0].reset();
now $('#test_form input').val() == 'Original value';
But reset method reset all form inputs and restore there default values, so how can I restore default value just in definite input?
on jQuery 1.6+
$('#test_form input').prop('defaultValue');
on older versions use .attr() instead of .prop()
You can use the defaultValue property:
this.value = this.defaultValue;
For example, the following code would reset the field to its default value when the blur event is fired:
$("#someInput").blur(function() {
this.value = this.defaultValue;
});
And here's a working example.
You could very easily build a plugin to do this, using the defaultValue property, which corresponds to the original state of the element.
$.fn.reset = function() {
this.each(function() {
this.value = this.defaultValue;
});
};
You can then call this plugin like this:
$('someSelector').reset();
Try whatever the jQuery equivalent to JavaScript's .getAttribute('value') is - the attribute does not change even if the value itself does.
I would suggest using placeholder attribute for inputs and textareas.
// Sample Usage
// $(document).ready(function(){ $.snapshot("#myForm"); }); Take shapshot
// event, function(){ $.reset("#myForm"); } Rest Form On Some Event
(function($) {
$.fn.getAttributes = function() {
var attributes = {};
if(!this.length)
return this;
$.each(this[0].attributes, function(index, attr) {
attributes[attr.name] = attr.value;
});
return attributes;
}
})(jQuery);
(function($)
{
jQuery.snapshot = function(form)
{
var form = $(form);
var elements = form.find("input, select, textarea");
if(elements && elements.length)
{
elements.each(function(){
var attributes = $(this).getAttributes();
var tagName = $(this).prop("tagName").toLowerCase();
var safe_attributes = {};
for(i in attributes)
{
var jq_attr = $(this).attr(i);
if(jq_attr != "undefined")
{
safe_attributes[i] = jq_attr;
}
}
if(tagName == "select")
{
var option = $(this).find("option:selected");
if(option && option.length)
{
var init_selected = option.attr("value");
safe_attributes['init_selected'] = init_selected;
}
}
if(tagName == "textarea")
{
var init_value = $(this).val();
safe_attributes['init_value'] = init_value;
}
$.data( $(this).get(0), "init_attr", safe_attributes );
});
}
}
jQuery.reset = function(form)
{
var form = $(form);
var elements = form.find("input, select, textarea");
var reset_btn = $('<input type="reset" name="reset" />');
form.append(reset_btn);
reset_btn.trigger("click");
reset_btn.remove();
if(elements && elements.length)
{
elements.each(function(){
var init_attributes = $(this).data("init_attr");
var attributes = $(this).getAttributes();
var tagName = $(this).prop("tagName").toLowerCase();
for(i in attributes)
{
if(i.toLowerCase() == "value" || i.toLowerCase() == "checked" || i.toLowerCase() == "selected")//if(i.toLowerCase() != "type")
{
var attr_found = false;
for(a in init_attributes)
{
if(i == a)
{
$(this).attr(a, init_attributes[a]);
attr_found = true;
}
}
if(!attr_found)
{
$(this).removeAttr(i);
}
}
}
if(tagName == "select" && 'init_selected' in init_attributes)
{
$(this).find("option:selected").removeAttr("selected");
var option = $(this).find("option[value="+init_attributes['init_selected']+"]");
if(option && option.length)
{
option.attr("selected", "selected");
}
}
if(tagName == "textarea")
{
if('init_value' in init_attributes)
{
$(this).val(init_attributes['init_value']);
}
}
$(this).trigger("change");
});
}
}
})(jQuery);

Selection row disable/reenable text selection

I have this code which selects multiple row when shift key is pressed. But whenever selection starts, the table text always gets selected, hence I tried to add disableSelection( ); to the table and re-enable it once mouseup. However, it is not working, the text still get selected. Any help is greatly appreciated.
$(".tableGrid tr").live("click", function(event) {
if( event.shiftKey ) {
$(".tableGrid").disableSelection( );
}
var tableRow = $(this).closest("tr").prevAll("tr").length + 1;
if ($(this).hasClass("rowSelected")) {
event.shiftKey ? $(this).removeClass("rowSelected") : $(".tableGrid tr").removeClass("rowSelected");
}
else {
if( !event.shiftKey ) {
$(".tableGrid tr").removeClass("rowSelected");
}
$(this).addClass("rowSelected");
}
if( event.shiftKey ) {
var start = Math.min(tableRow, lastSelected);
var end = Math.max(tableRow, lastSelected);
for( var i=start; i<end; i++ ) { $(".tableGrid").find("tr").eq(i).addClass("rowSelected"); }
}
else {
lastSelected = $(this).closest("tr").prevAll("tr").length + 1;
}
}).mouseup(function( ) {
$(".tableGrid").enableSelection( );
});
To disable text selection of a specific DOM element, you could try this:
var element = document.getElementById('content');
element.onselectstart = function () { return false; } // ie
element.onmousedown = function () { return false; } // mozilla

jQuery password generator

I have the following JS code that checks a password strength and also creates a random password as well. What I want to do is edit the code so that instead of putting the generated password inside the password field it will put it inside a span tag with say an id of randompassword. In addition that I would like it so that by default there will be a random password inside the span tag and then when the user clicks the button it will generate another one. And also move the link to be next to span tag rather than the password box.
Thanks.
Here is the code:
$.fn.passwordStrength = function( options ){
return this.each(function(){
var that = this;that.opts = {};
that.opts = $.extend({}, $.fn.passwordStrength.defaults, options);
that.div = $(that.opts.targetDiv);
that.defaultClass = that.div.attr('class');
that.percents = (that.opts.classes.length) ? 100 / that.opts.classes.length : 100;
v = $(this)
.keyup(function(){
if( typeof el == "undefined" )
this.el = $(this);
var s = getPasswordStrength (this.value);
var p = this.percents;
var t = Math.floor( s / p );
if( 100 <= s )
t = this.opts.classes.length - 1;
this.div
.removeAttr('class')
.addClass( this.defaultClass )
.addClass( this.opts.classes[ t ] );
})
.after('Generate Password')
.next()
.click(function(){
$(this).prev().val( randomPassword() ).trigger('keyup');
return false;
});
});
function getPasswordStrength(H){
var D=(H.length);
if(D>5){
D=5
}
var F=H.replace(/[0-9]/g,"");
var G=(H.length-F.length);
if(G>3){G=3}
var A=H.replace(/\W/g,"");
var C=(H.length-A.length);
if(C>3){C=3}
var B=H.replace(/[A-Z]/g,"");
var I=(H.length-B.length);
if(I>3){I=3}
var E=((D*10)-20)+(G*10)+(C*15)+(I*10);
if(E<0){E=0}
if(E>100){E=100}
return E
}
function randomPassword() {
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!##$_+?%^&)";
var size = 10;
var i = 1;
var ret = ""
while ( i <= size ) {
$max = chars.length-1;
$num = Math.floor(Math.random()*$max);
$temp = chars.substr($num, 1);
ret += $temp;
i++;
}
return ret;
}
};
$(document)
.ready(function(){
$('#password1').passwordStrength({targetDiv: '#iSM',classes : Array('weak','medium','strong')});
});
// you can use another improved version to generate password as follows
//Define
function wpiGenerateRandomNumber(length) {
var i = 0;
var numkey = "";
var randomNumber;
while( i < length) {
randomNumber = (Math.floor((Math.random() * 100)) % 94) + 33;
if ((randomNumber >=33) && (randomNumber <=47)) { continue; }
if ((randomNumber >=58) && (randomNumber <=90)) { continue; }
if ((randomNumber >=91) && (randomNumber <=122)) { continue; }
if ((randomNumber >=123) && (randomNumber <=126)) { continue; }
i++;
numkey += String.fromCharCode(randomNumber);
}
return numkey;
}
// Call
var myKey=wpiGenerateRandomNumber(10); // 10=length
alert(myKey);
// Output
2606923083
This line:
$(this).prev().val( randomPassword() ).trigger('keyup');
is inserting the value after a click. So you can change that value to stick the password wherever you want it. For example you could change it to:
$('span#randompassword').html(randomPassword());
You could also run this when the page loads to stick something in that span right away:
$(document).ready(function(){
$('span#randompassword').html(randomPassword());
});
//Very simple method to generate random number; can be use to generate random password key as well
jq(document).ready( function() {
jq("#genCodeLnk").click( function() {
d = new Date();
t = d.getTime();
jq("#cstm_invitecode").val(t);
});
});

Categories