Am trying to put together a form validation script, and i hit a snag when i wanted to have callback functions in my validation rules. The validation rules are defined in the html using data attributes
here the html
<div class="clearfix">
<input type="text" name="first_name" placeholder="First Name" id="_fname" data-required='yes' />
<span class="form-validation-status"></span>
<div class="form-error-msg"></div>
</div>
<div class="clearfix">
<input type="text" name="last_name" placeholder="Last Name" id="_lname" data-required='yes' />
<span class="form-validation-status"></span>
<div class="form-error-msg"></div>
</div>
<div class="clearfix">
<input type="text" name="email"
placeholder="Email Address" id="_email"
data-required='yes' data-has-callback="yes"
data-callback="email_check"
/>
<span class="form-validation-status"></span>
<div class="form-error-msg"></div>
</div>
<div class="clearfix">
<input type="text" name="username"
placeholder="Username" id="_username"
data-required='yes' data-has-callback="yes"
data-callback="username_check"
/>
<span class="form-validation-status"></span>
<div class="form-error-msg"></div>
</div>
<div class="clearfix">
<input type="password" name="password" placeholder="Password" id="_password" data-required='yes'/>
<span class="form-validation-status"></span>
<div class="form-error-msg"></div>
</div>
<div class="clearfix">
<input type="password" name="confpass" placeholder="Confirm Password" id="_confpass" data-required='yes' />
<span class="form-validation-status"></span>
<div class="form-error-msg"></div>
</div>
<div class="clearfix">
<input type="submit" value="Sign Up" class="btn btn-large btn-primary" id="signup-btn" />
</div>
I've been able to deal with the required rule, but i cant seem to figure what to do for the callbacks, this the javascript
var required_fields = $("input[data-required='yes']");
var has_callbac =$("input[data-has-callback='yes']");
/* VALIDATE REQUIRED FIELDS */
$.each(required_fields,function(index,item){
var field = $(item);
var status = field.next();
var field_name = field.attr("placeholder");
var error_msg = "The "+field_name+" cannot be empty";
var form_error = field.siblings('span.form-validation-status').next();
field.blur(function() {
var _field_val = ($(this).val());
form_error.html('');
status.removeClass('error-status');
if(_field_val == ""){
validation_errors++;
status.addClass('error-status');
form_error.html(error_msg);
}else {
status.addClass('ok-status');
validation_errors= validation_errors + 1 - 2;
}
});
});
/* VALIDATE FIELDS WITH CALLBACKS */
$.each(has_callbac,function(index,item) {
var field = $(item);
var status = field.next();
var form_error = field.siblings('span.form-validation-status').next();
var callback = field.attr("data-callback");
var callback_func = callback+"()";
var test = typeof callback_func;
//i got confused at this point
console.log(test);
});
Please help me out.
If these callback functions are global, you can simply do:
var callback = field.attr("data-callback");
window[callback]();
Or, if your callback would like to have the field in question set as the this value, then you'd do:
var callback = field.attr("data-callback");
window[callback].call(field); //and of course tack on any other parameters you have
If you've defined these callbacks as properties of some other object, then you'd do the same thing:
var callbackHolder = {
callback1: function() { },
callback2: function() { }
};
var callback = field.attr("data-callback");
callbackHolder[callback]();
you have this:
var callback = field.attr('data-callback');
Extend it to this:
// check if the value is a function in the global scope
if('function' == typeof(window[callback])) {
callback();
}
If the functions are not in the global scope, you may need to modify that logic.
EDIT:
If you are working in the local scope, you may benefit from adding a generic validation function such as:
(function($){
$.fn.form_validation=function(){
var rules = {
callback_one: function(fieldvalue) {
var response = {
'code':'failed',
'reason':'Missing or incomplete'
};
//some validation here
return response;
}, ...
}
var rule = '', args = [];
if(arguments.length > 0) {
if('object' === typeof(arguments[0])) {
args = arguments;
} else if('undefined' !== typeof(rules[arguments[0]])) {
args = Array.prototype.slice.call(arguments);
args.shift();
rule = arguments[0];
}
}
rules[ rule ].apply( this, args );
}
}($));
Then you could call something like:
var result = $.form_validation(callback,data);
within your $.each()
NOTE: untested - just a starting point to separate our your code into controllable modules rather than bring it all inline in case you need to reuse your validation or edit your code inline.
Related
I am having 6 bootstrap cards where the details of the card are id, image, content.on clicking the card I am getting the details of the card into the local storage and from that, I am extracting the ids into another array named styleIds I want these styleIds values to sent as value to the input field as onload of body
My js code:
var styles = []
var styleIds = []
function getStyle(id) {
if (styles.length > 0) {
var data = { id: id, image: $("#img_"+id).attr('src'),content: $("#cont_" + id).text() }
var x = JSON.stringify(data)
var index = styles.indexOf(x)
if (index == -1) {
styles.push(x)
}
else {
styles.splice(index, 1)
}
}
else {
var data = { id: id, image: $("#img_"+id).attr('src'),content: $("#cont_" + id).text() }
var x = JSON.stringify(data)
styles.push(x)
}
localStorage.setItem("styles", JSON.stringify(styles))
styleIds = styles.map(element => JSON.parse(element).id);
console.log(styleIds)
assample();
}
function assample() {
$("#style").val(styleIds);
console.log(styleIds)
}
function initStyles() {
var storedNames = JSON.parse(localStorage.getItem("styles") || '[]');
styleIds = storedNames.map(element => JSON.parse(element).id);
}
My form code is:
<body onload = "sample();initGoals();issample();assample();initStyles();">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" required>
</div>
<div class="form-group">
<input type="text" name="room" id="name" value=" ">
</div>
<div class="form-group" >
<input type="text" name="goal" id="goal" value=" ">
</div>
<div class="form-group" >
<input type="text" name="style" id="style" value=" ">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" name="email" class="form-control" required>
</div>
<div class="form-group">
<label for="password2">Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<input type="submit" value="Register" class="btn btn-secondary btn-block">
</form>
The cards are on one page and the form is the another web page so in the styles page the styleIds array is getting the ids butwhen I navigate to the form page the values are getting as a value for the field in the form what is the mistake I did?
Make sure you're calling the functions in the correct order. Also, I would suggest renaming your function names so that you don't get confused.
You can change your onload to just call one function and later care about the order.
<body onload = "doSomething()">
and in the script:
function doSomething() {
sample();
initGoals();
issample();
initStyles();
assample();
}
I' trying to build a form in which the users can change the values of two password inputs, one for a password and a second one to verify the password.
So in order to make the user aware of what he types and to make sure both of his/her password match with one another and tried to implemente a method in which he can just check a checkbox to show his password.
The current javascript method works with just one input but I would like to have it working with both input and not just one. I would like as well to show the password of both input without having to check their own corresponding checkbox(for example if a check one checkbox it should display text in both inputs).
This is the current javascript method that I have:
// First Code //
function addEvent (el, event, callback) {
if ('addEventListener' in el) {
el.addEventListener(event, callback, false);
} else {
el['e' + event + callback] = callback;
el[event + callback] = function () {
el['e' + event + callback](window.event);
};
el.attachEvent('on' + event, el[event + callback]);
}
}
function removeEvent(el, event, callback) {
if ('removeEventListener' in el) {
el.removeEventListener(event, callback, false);
} else {
el.detachEvent('on' + event, el[event + callback]);
el[event + callback] = null;
el['e' + event + callback] = null;
}
}
// Second Code //
(function() {
var pwd = document.getElementById('password');
var chk = document.getElementById('showpass');
addEvent(chk, 'change', function(e) {
var target = e.target || e.srcElement;
try {
if (target.checked) {
password.type = 'text';
} else {
password.type = 'password';
}
} catch(error) {
alert('This browser cannot switch type');
}
});
}());
<!-- First Password -->
<div class="form-group">
<label for="password">Password</label>
<div class="input-group date">
<div class="input-group-addon">
<i class="fa fa-lock" aria-hidden="true"></i>
</div>
<input type="password" name="password" value="" id="password" class="form-control">
<div class="input-group-addon"><input type="checkbox" id="showpass"></div>
</div>
</div>
<!-- Second Password -->
<div class="form-group">
<label for="password2">Confirm Password</label>
<div class="input-group date">
<div class="input-group-addon">
<i class="fa fa-lock" aria-hidden="true"></i>
</div>
<input type="password" name="password2" value="" id="password2" class="form-control">
<div class="input-group-addon"><input type="checkbox" id="showpass"></div>
</div>
</div>
Thanks in advance.
Change the type of both inputs at once:
var pwd = document.getElementById('password');
var confirm = document.getElementById('password2');
...
if (target.checked) {
pwd.type = 'text';
confirm.type = 'text';
} else {
pwd.type = 'password';
confirm.type = 'password';
}
Added a little fiddle to toggle the password type.
https://jsfiddle.net/xpvt214o/321232/
JS
var $vp = $('.vp');
$vp.on('click', function() {
var $target = $(this).siblings('input[name*="password"]');
if ($target.attr('type') == "password") {$target.attr('type','text');}
else {$target.attr('type','password');}
});
HTML
<div style="width:100%;float:left;margin:0 0 16px 0;">
<p>Password 1</p>
<input type="password" name="password" val="" />
<span class="vp">View password</span>
</div>
<div style="width:100%;float:left;margin:0 0 16px 0;">
<p>Password 2</p>
<input type="password" name="password2" val="" />
<span class="vp">View password</span>
</div>
The function looks for the click event of the span "vp" and get's its sibling input element, checks the type attribute and toggles it to and from text/password. The name of the inputs must contain "password" (in lowercase).
Html - Delivery address has to give the entered value to billing address. The javascript and html are in separate files
Other js features are working fine, but its just this one that doesn't seem to work
<div class="textinput">
<label for="deladdress">Delivery Address: </label>
<input id="deladdress" type="text" name="Delivery Address" />
</div>
<div id="buttoncheckarea">
<input id="CheckDelivery" type="checkbox" name="CheckDelivery">
<label id="diff" for="CheckDelivery">Same as delivery address?</label>
</div>
<div class="textinput">
<label for="postcode">Postcode: </label>
<input id="postcode" type="text" name="postcode" />
</div>
<div class="textinput">
<label for="billaddress">Billing Address: </label>
<input id="billaddress" type="text" name="Billing Address" />
</div>
javascript
function deliveryfunc() {
var delivery = document.getElementById("deladdress").value;
var billing = document.getElementById("billaddress").value;
//var checkbox = document.getElementById("CheckDelivery").checked;
if (document.getElementsByName("CheckDelivery").checked == true) {
billing = delivery;
}
}
function init () {
var order = document.getElementById("ordForm");
order.onsubmit = ordervalidation;
order.onclick = radiobuttoncheck;
var checkbutton = document.getElementsByName("CheckDelivery");
checkbutton.onclick = deliveryfunc;
}
window.onload = init;
Try updating your deliveryfunc as below:
function deliveryfunc() {
var delivery = document.getElementById("deladdress");
var billing = document.getElementById("billaddress");
if (document.getElementById("CheckDelivery").checked == true) {
billing.value = delivery.value;
}
}
function init () {
var order = document.getElementById("ordForm");
order.onsubmit = ordervalidation;
order.onclick = radiobuttoncheck;
var checkbutton = document.getElementById("CheckDelivery");
checkbutton.onclick = deliveryfunc;
}
window.onload = init;
I wanted to check the pass and repass both are same or not?
but the problem is onkeyup event is not calling the check function.
path of javascript file is also proper.
<form class="form-horizontal" name="signUp" >
<div class="form-group">
<!-- Username -->
<label for="username" class="lbl-content">
Username</label>
<div class="col-sm-10">
<input type="text" id="inputUsername" name="inputUsername" class="input-txt" placeholder="Username"
autofocus required />
</div>
</div>
<div class="form-group">
<label for="password" class="lbl-content">
Password</label>
<div class="">
<input type="password" id="inputPassword" name="inputPassword" class="input-txt"
placeholder="password" required />
</div>
</div>
<!-- Re password -->
<div class="form-group">
<label for="re-password" class="lbl-content">
Re-Password</label>
<div class="">
<input type="password" id="inputRepassword" name="inputRepassword" class="input-txt"
placeholder="re-password" onkeyup="return check()" required />
<span id="confirmMessage" class="confirmMessage"></span>
</div>
</div>
</form>
JavaScript function in which i am checking the pass and repass values..
function check() {
var pass = document.getElementById('inputPassword').value;
var repass = document.getElementById('inputRepassword').value;
var msg = document.getElementById('confirmMessage').value;
if (pass1 == repass1) {
document.getElementById('inputRepassword').style.backgroundColor = green;
document.getElementById('confirmMessage').innerHTML = "Password Match";
alert("hello");
document.getElementById('msg').innerHTML = "pass match";
return true;
}
else {
document.getElementById('inputRepassword').style.backgroundColor = red;
document.getElementById('confirmMessage').innerHTML = "Password did not match";
return false;
}
}
Please help me. Where am I wrong?
Error may be cause by below two line as green and red is not javascript key word
document.getElementById('inputRepassword').style.backgroundColor = green;
document.getElementById('inputRepassword').style.backgroundColor = red;
insted of this you need to pass this value as string "green" and "red". so code will be
document.getElementById('inputRepassword').style.backgroundColor = "green";
document.getElementById('inputRepassword').style.backgroundColor = "red";
You made some typos, here is your code fixed: http://jsfiddle.net/gaus7uhm/
function check() {
var pass = document.getElementById('inputPassword').value;
var repass = document.getElementById('inputRepassword').value;
var msg = document.getElementById('confirmMessage').value;
if (pass == repass) {
document.getElementById('inputRepassword').style.backgroundColor = 'green';
document.getElementById('confirmMessage').innerHTML = "Password Match";
alert("hello");
document.getElementById('msg').innerHTML = "pass match";
return true;
} else {
document.getElementById('inputRepassword').style.backgroundColor = 'red';
document.getElementById('confirmMessage').innerHTML = "Password did not match";
return false;
}
}
Here are all the changes I made to your code:
pass1 => pass
repass1 => repass
red => "red" (you need to pass a string, not a variable)
green => "green"
Another way to fix the red/"red" problem is to declare these variables at the beginning:
var red = '#711',
green = '#171';
This way you can customize your colors and you won't have to search in your code where you set the colours.
For some reason i'm having trouble passing an object to observable array.
function CalendarViewModel() {
var self = this;
self.event = {
name : ko.observable(""),
adress : ko.observable(""),
startTime : ko.observable(""),
endTime : ko.observable("")
}
self.events = ko.observableArray([
])
self.addEvent = function (event) {
self.events.push(event);
alert(self.events.length)
alert(self.events[0].name());
}
my view:
<fieldset class="add-event-fieldset">
<div data-bind="with: event">
<legend>Add Event</legend>
<div style="text-align: center;">
<label class="title-label">What </label>
</div>
<div>
<label>Name: </label>
<input type="text" name="whatTxtBox" data-bind="value: name" />
</div>
<div>
<label>Where: </label>
<input type="text" name="whereTxtBox" data-bind="value: adress" />
</div>
<div style="text-align: center;">
<label class="title-label">When </label>
</div>
<div>
<label>start: </label>
<input type="text" id="startHourTxtBox" data-bind="value: startTime" />
</div>
<div>
<label>end: </label>
<input type="text" id="endHourTxtBox" data-bind="value: endTime" />
</div>
</div>
<input type="hidden" name="" id="hiddenDay" />
<button id="btnAddNewEvent" data-bind="click: $root.addEvent">+</button>
</fieldset>
The alerts show that the array is always empty, please explain what i'm doing wrong thanks.
Your observable array usage e.g self.events.push(event); is correct (because observable array implements push), only your alerts are wrong.
The correct calls would be
alert(self.events().length)
alert(self.events()[0].name());
Because you need to call the observable array as a function like the regular ko.observable to get its underlying value the array itself.
However you are currently adding to whole CalendarViewModel to the array because the btnAddNewEvent is outside of yourwith binding so the current context will be your main view model.
One way to solve it: just add the self.event to the array, so:
self.addEvent = function()
{
self.events.push(self.event);
alert(self.events().length)
alert(self.events()[0].name());
}
But this can cause problems later when you want to add another element because you will end up referencing the same element, so the right solution is copy the properties somewhere:
So I would create a constructor function for your event class:
var Event = function(data) {
var self = this;
self.name = ko.observable(data.name()),
self.adress = ko.observable(data.adress()),
self.startTime = ko.observable(data.startTime()),
self.endTime = ko.observable(data.endTime())
}
And push a new event in the addEvent
self.events.push(new Event(self.event));
Try
self.events().length
and
self.events()[0].name()
instead.
Just updating a little on nemesev answer. You really don't have to pass data as an argument
var Event = function() {
var self = this;
self.name = ko.observable();
self.adress = ko.observable();
self.startTime = ko.observable();
self.endTime = ko.observable();
};
And call it like
self.events.push(new Event());