Debug form local storage - javascript

I have a form (demo link below).
I've tried about 8 different methods of storing the data but it won't work.
(link retracted)
The goal is, the user visits the site and fills out the form (partially or complete). They can then login if they wish.
The next time they visit the site the form should be complete (excluding password) and the avatar should display with the one stored in local storage.
I can't figure out why nothing will display, whether it's a compatibility issue or syntax issue etc.
Problem Solved
another js script has been interfering with it causing it to fail. Resolved.

I'm not going to check your website for errors since you didn't provide any code. Instead I show you a quick and working way to save and read values from localStorage.
The values will be stored in key/value pairs while the key is the name of the input field.
HTML:
<input type="text" name="username" id="user" />
<input type="text" name="email" id="email" />
JS:
$('input').each(function() {
$(this).on('blur', function() {
localStorage.setItem($(this).attr('name'), $(this).val());
});
});
for (var i = 0; i < localStorage.length; i++){
var storageKey = localStorage.key(i),
storageValue = localStorage.getItem(storageKey);
$('input[name='+storageKey+']').val(storageValue);
}
Remeber that the for loop has to be inside of your domready function. Check the working fiddle below. Like this you have a dynamic approach for input fields - you can also do this for selects if you like to.
If you want some faster selectors you can also save the ID as key and select the input via id. Is even more dynamic.
Fiddle
Edit: As requested here is an example for checkboxes/selects. It might not be the best approach but its working.
JS:
$('.autofill').each(function () {
$(this).on('change', function () {
if ($(this).is('input')) {
if ($(this).attr('type') == 'checkbox') {
if ($(this).is(':checked')) {
localStorage.setItem($(this).attr('id'), 'checked');
} else {
localStorage.setItem($(this).attr('id'), '');
}
} else {
localStorage.setItem($(this).attr('id'), $(this).val());
}
} else if ($(this).is('select')) {
localStorage.setItem($(this).attr('id'), $(this).find('option:selected').val());
}
});
});
for (var i = 0; i < localStorage.length; i++) {
var storageKeyElement = $('#' + localStorage.key(i)),
storageKey = localStorage.key(i),
storageValue = localStorage.getItem(storageKey);
if (storageValue == 'checked') {
storageKeyElement.attr('checked', 'checked');
} else if (storageKey.indexOf('Select') > 0) {
storageKeyElement.find('option[value=' + storageValue + ']').attr('selected', 'selected');
} else {
storageKeyElement.val(storageValue);
}
}
Fiddle with Selects and Checkboxes

The problem is, you have syntax error.
Change all the mb-* variables to mb_*
For example:
var mb-username
should be
var mb_username
But you have another problems in your source code too:
<meta name="author" content="Michael Clarke"
has a missing /> closing tag.
And you have another error:
ReferenceError: applySetting is not defined
Fix these errors, and use your console to see errors.

Related

Search for Text inside div

The problem is: I have one div that wraps all my users list. I want to make a search box, but i don't want to use Ajax, so i started trying JQuery, for search the text inside the div and hide the another results. I've tried but i'm stucked on this:
//Search Box
$(document).on('input', "#search-weeazer", function(e){
console.log('input ativado')
if($(this).val().length >= 4){
// if($('#colmeia-chat').html().indexOf($(this).val()) > -1){
// console.log('Found')
// } else {
// console.log('Not Found')
// }
$('div.chat-users>div').each(function(i,div){
if($(div).html().indexOf($(div).val()) > -1){
console.log($(div).html() + ' found: ' + i);
} else {
console.log("Not Found")
}
});
}
});
Someone know how i can do this?
Thanks!
In my HTML i have this:
<div class="chat-users" style="height: 400px;">
<?php include_once('user-chat-list.php'); ?>
</div>
Inside "chat-users" i have a list with all users, loaded with php
Here is more HTMl to show the structure:
https://jsfiddle.net/jdqbnz2w/
After Question Edit
Here is an updated JSFiddle based on the JSFiddle you included showing how to implement the search with your particular use-case:
JSFiddle
Original Answer:
You're missing some pertinent information in your question, such as "what does the HTML look like that comes from user-chat-list.php?" And because of that it makes it hard to understand exactly how your code applies.
Nevertheless, here is a simple example upon what you have provided that you can modify that does what you are looking for. You can run the following code snippet to see a working example:
var $searchBox = $('#search-weeazer');
var $userDivs = $('.chat-users div');
$searchBox.on('input', function() {
var scope = this;
if (!scope.value || scope.value == '') {
$userDivs.show();
return;
}
$userDivs.each(function(i, div) {
var $div = $(div);
$div.toggle($div.text().toLowerCase().indexOf(scope.value.toLowerCase()) > -1);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Search:
<input id="search-weeazer">
<p>Users:</p>
<div class="chat-users">
<div>Tony</div>
<div>Amber</div>
<div>Ronald</div>
</div>

Problem removing input from form after adding

so I have got my form successfully adding a new input on the click of a button. However now I want to be able to remove that last addition on the click of a new button and then also feature a reset button.
this was the code I had in place, which I realise now just removes the submit button first, which obviously I dont want.
here is my javascript snippet: (note ive included the appendTo() to demonstrate the div I am successfully appending to)
$(function() {
var i = $('input').size('#temp') + 1;
$('a#add').click(function() {
$('<input type="text" value="user' + i + '" />').appendTo('#temp');
i++;
});
$('a#remove').click(function() {
if(i > 3) {
$('input:last').remove();
i--;
}
});
many thanks,
Your script will remove the last input from the page, not the last one from the div with id temp. Maybe you are removing another input from your page.
Try this:
$('a#remove').click(function() {
if(i > 3) {
$('#temp input:last').remove();
i--;
}
});
Edit:
You only close the $('a#remove').click() event handler, not the anonymous function. That may be a copy/paste error here, but may also be a problem in your code.
Edit 2:
To remove all but the original, I would recommend keeping a reference to all added inputs, as this reduces the need to traverse the DOM for each remove. So do something like this (This code is neither tested nor verified):
$(function() {
var addedInputs = [];
$('a#add').click(function() {
var newInput = $('<input type="text" value="user' + i + '" ">').appendTo('#temp');
addedInputs.push(newInput);
});
$('a#remove').click(function() {
var inputToRemove = addedInputs.pop();
inputToRemove.remove();
});
$('a#clear').click(function() {
var i,
inputToRemove;
for(i = addedInputs.length - 1;i >= 0; i -=1) {
inputToRemove = addedInputs[i];
inputToRemove.remove();
}
addedInputs = [];
});
});
Have you tried :
$("a#remove").click(function() {
if(i > 3) {
$("input[type='text']").last().remove();
i--;
}
});
This will select the inputs having type="text", take the last one and remove it.

I want to validate that user can only select only one checkbox in each row in listview

I have listview with two checkboxes in itemtemplate.
I want to validate that user can only select only one checkbox in each row.
The behaviour you're describing is accomplished using standard HTML radiobuttons. If you change your design to use these you'll get the benefit that
The user can only select a single item, no extra javascript needed
Users expect to be able to choose multiple checkboxes but only a single radiobutton IE you're working with their expectations
If you're still sure you want to use jQuery then something like this should do it.
$(':checkbox').change(function(){
if($(this).attr('checked')) {
$(this).siblings(':checkbox').attr('checked',false);
}
});
#vinit,
just a little change, you forgot the else part,
$('input:checkbox[id*=EmailCheckBox]').click(uncheckOthercheckbox);
$('input:checkbox[id*=SMSCheckBox]').click(uncheckOthercheckbox);
function uncheckOthercheckbox() {
if (this.id.indexOf("EmailCheckBox") != -1) {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("EmailCheckBox")) + "SMSCheckBox";
}
else {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("SMSCheckBox")) + "EmailCheckBox";
}
var i = "#" + otherCheckBoxId;
if (this.checked) {
$(i).removeAttr('checked');
}
else {
if ($(i).attr('checked') === false) {
$(i).attr('checked', 'checked');
}
}
}
Thanks for the reply. had also asked one of my friend and he gave me the following solution which is working fine. Posting it, if anybody needs it.-
say ur checkboxes in the 2 clumns are named EmailCheckBox and SMSCheckBox
then use this code to toggle the checkboxes in each single row:
$('input:checkbox[id*=EmailCheckBox]').click(uncheckOthercheckbox);
$('input:checkbox[id*=SMSCheckBox]').click(uncheckOthercheckbox);
function uncheckOthercheckbox() {
if (this.id.indexOf("EmailCheckBox") != -1) {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("EmailCheckBox")) + "SMSCheckBox";
}
else {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("SMSCheckBox")) + "EmailCheckBox";
}
var i = "#" + otherCheckBoxId;
if (this.checked) {
$(i).removeAttr('checked');
}
}

Simple form validation. Object-oriented

Problem statement:
It is necessary for me to write a code, whether which before form sending will check all necessary fields are filled. If not all fields are filled, it is necessary to allocate with their red colour and not to send the form.
Now the code exists in such kind:
function formsubmit(formName, reqFieldArr){
var curForm = new formObj(formName, reqFieldArr);
if(curForm.valid)
curForm.send();
else
curForm.paint();
}
function formObj(formName, reqFieldArr){
var filledCount = 0;
var fieldArr = new Array();
for(i=reqFieldArr.length-1; i>=0; i--){
fieldArr[i] = new fieldObj(formName, reqFieldArr[i]);
if(fieldArr[i].filled == true)
filledCount++;
}
if(filledCount == fieldArr.length)
this.valid = true;
else
this.valid = false;
this.paint = function(){
for(i=fieldArr.length-1; i>=0; i--){
if(fieldArr[i].filled == false)
fieldArr[i].paintInRed();
else
fieldArr[i].unPaintInRed();
}
}
this.send = function(){
document.forms[formName].submit();
}
}
function fieldObj(formName, fName){
var curField = document.forms[formName].elements[fName];
if(curField.value != '')
this.filled = true;
else
this.filled = false;
this.paintInRed = function(){
curField.addClassName('red');
}
this.unPaintInRed = function(){
curField.removeClassName('red');
}
}
Function is caused in such a way:
<input type="button" onClick="formsubmit('orderform', ['name', 'post', 'payer', 'recipient', 'good'])" value="send" />
Now the code works. But I would like to add "dynamism" in it.
That it is necessary for me: to keep an initial code essentially, to add listening form fields (only necessary for filling).
For example, when the field is allocated by red colour and the user starts it to fill, it should become white.
As a matter of fact I need to add listening of events: onChange, blur for the blank fields of the form. As it to make within the limits of an initial code.
If all my code - full nonsense, let me know about it. As to me it to change using object-oriented the approach.
Give me pure Javascript solution, please. Jquery - great lib, but it does not approach for me.
To keep your HTML clean, I suggest a slightly different strategy.
Use a framework like jQuery which makes a lot of things much more simple.
Move all the code into an external script.
Use the body.onLoad event to look up all forms and install the checking code.
Instead of hardcoding the field values, add a css class to each field that is required:
<input type="text" ... class="textField required" ...>
Note that you can have more than a single class.
When the form is submitted, examine all fields and check that all with the class required are non-empty. If they are empty, add the class error otherwise remove this class. Also consider to add a tooltip which says "Field is required" or, even better, add this text next to the field so the user can see with a single glance what is wrong.
In the CSS stylesheet, you can then define a rule how to display errors.
For the rest of the functionaly, check the jQuery docs about form events.
Has made.
function formsubmit(formName, reqFieldArr){
var curForm = new formObj(formName, reqFieldArr);
if(curForm.valid)
curForm.send();
else{
curForm.paint();
curForm.listen();
}
}
function formObj(formName, reqFieldArr){
var filledCount = 0;
var fieldArr = new Array();
for(i=reqFieldArr.length-1; i>=0; i--){
fieldArr[i] = new fieldObj(formName, reqFieldArr[i]);
if(fieldArr[i].filled == true)
filledCount++;
}
if(filledCount == fieldArr.length)
this.valid = true;
else
this.valid = false;
this.paint = function(){
for(i=fieldArr.length-1; i>=0; i--){
if(fieldArr[i].filled == false)
fieldArr[i].paintInRed();
else
fieldArr[i].unPaintInRed();
}
}
this.send = function(){
document.forms[formName].submit();
}
this.listen = function(){
for(i=fieldArr.length-1; i>=0; i--){
fieldArr[i].fieldListen();
}
}
}
function fieldObj(formName, fName){
var curField = document.forms[formName].elements[fName];
this.filled = getValueBool();
this.paintInRed = function(){
curField.addClassName('red');
}
this.unPaintInRed = function(){
curField.removeClassName('red');
}
this.fieldListen = function(){
curField.onkeyup = function(){
if(curField.value != ''){
curField.removeClassName('red');
}
else{
curField.addClassName('red');
}
}
}
function getValueBool(){
if(curField.value != '')
return true;
else
return false;
}
}
This code is not pleasant to me, but it works also I could not improve it without rewriting completely.
jQuery adds a lot of benefit for a low overhead. It has a validation plugin which is very popular. There are some alternatives as well but I have found jQuery to be the best.
Benefits
small download size
built in cross browser support
vibrant plug-in community
improved productivity
improved user experience

What is the best way to track changes in a form via javascript?

I'd like to track changes in inputs in a form via javascript. My intent is (but not limited) to
enable "save" button only when something has changed
alert if the user wants to close the page and something is not saved
Ideas?
Loop through all the input elements, and put an onchange handler on each. When that fires, set a flag which lets you know the form has changed. A basic version of that would be very easy to set up, but wouldn't be smart enough to recognize if someone changed an input from "a" to "b" and then back to "a". If it were important to catch that case, then it'd still be possible, but would take a bit more work.
Here's a basic example in jQuery:
$("#myForm")
.on("input", function() {
// do whatever you need to do when something's changed.
// perhaps set up an onExit function on the window
$('#saveButton').show();
})
;
Text form elements in JS expose a .value property and a .defaultValue property, so you can easily implement something like:
function formChanged(form) {
for (var i = 0; i < form.elements.length; i++) {
if(form.elements[i].value != form.elements[i].defaultValue) return(true);
}
return(false);
}
For checkboxes and radio buttons see whether element.checked != element.defaultChecked, and for HTML <select /> elements you'll need to loop over the select.options array and check for each option whether selected == defaultSelected.
You might want to look at using a framework like jQuery to attach handlers to the onchange event of each individual form element. These handlers can call your formChanged() code and modify the enabled property of your "save" button, and/or attach/detach an event handler for the document body's beforeunload event.
Here's a javascript & jquery method for detecting form changes that is simple. It disables the submit button until changes are made. It detects attempts to leave the page by means other than submitting the form. It accounts for "undos" by the user, it is encapsulated within a function for ease of application, and it doesn't misfire on submit. Just call the function and pass the ID of your form.
This function serializes the form once when the page is loaded, and again before the user leaves the page. If the two form states are different, the prompt is shown.
Try it out: http://jsfiddle.net/skibulk/ev5rE/
function formUnloadPrompt(formSelector) {
var formA = $(formSelector).serialize(), formB, formSubmit = false;
// Detect Form Submit
$(formSelector).submit( function(){
formSubmit = true;
});
// Handle Form Unload
window.onbeforeunload = function(){
if (formSubmit) return;
formB = $(formSelector).serialize();
if (formA != formB) return "Your changes have not been saved.";
};
// Enable & Disable Submit Button
var formToggleSubmit = function(){
formB = $(formSelector).serialize();
$(formSelector+' [type="submit"]').attr( "disabled", formA == formB);
};
formToggleSubmit();
$(formSelector).change(formToggleSubmit);
$(formSelector).keyup(formToggleSubmit);
}
// Call function on DOM Ready:
$(function(){
formUnloadPrompt('form');
});
Try
function isModifiedForm(form){
var __clone = $(form).clone();
__clone[0].reset();
return $(form).serialize() == $(__clone).serialize();
}
Hope its helps ))
If your using a web app framework (rails, ASP.NET, Cake, symfony), there should be packages for ajax validation,
http://webtecker.com/2008/03/17/list-of-ajax-form-validators/
and some wrapper on onbeforeunload() to warn users taht are about to close the form:
http://pragmatig.wordpress.com/2008/03/03/protecting-userdata-from-beeing-lost-with-jquery/
Detecting Unsaved Changes
I answered a question like this on Ars Technica, but the question was framed such that the changes needed to be detected even if the user does not blur a text field (in which case the change event never fires). I came up with a comprehensive script which:
enables submit and reset buttons if field values change
disables submit and reset buttons if the form is reset
interrupts leaving the page if form data has changed and not been submitted
supports IE 6+, Firefox 2+, Safari 3+ (and presumably Opera but I did not test)
This script depends on Prototype but could be easily adapted to another library or to stand alone.
$(document).observe('dom:loaded', function(e) {
var browser = {
trident: !!document.all && !window.opera,
webkit: (!(!!document.all && !window.opera) && !document.doctype) ||
(!!window.devicePixelRatio && !!window.getMatchedCSSRules)
};
// Select form elements that won't bubble up delegated events (eg. onchange)
var inputs = $('form_id').select('select, input[type="radio"], input[type="checkbox"]');
$('form_id').observe('submit', function(e) {
// Don't bother submitting if form not modified
if(!$('form_id').hasClassName('modified')) {
e.stop();
return false;
}
$('form_id').addClassName('saving');
});
var change = function(e) {
// Paste event fires before content has been pasted
if(e && e.type && e.type == 'paste') {
arguments.callee.defer();
return false;
}
// Check if event actually results in changed data
if(!e || e.type != 'change') {
var modified = false;
$('form_id').getElements().each(function(element) {
if(element.tagName.match(/^textarea$/i)) {
if($F(element) != element.defaultValue) {
modified = true;
}
return;
} else if(element.tagName.match(/^input$/i)) {
if(element.type.match(/^(text|hidden)$/i) && $F(element) != element.defaultValue) {
modified = true;
} else if(element.type.match(/^(checkbox|radio)$/i) && element.checked != element.defaultChecked) {
modified = true;
}
}
});
if(!modified) {
return false;
}
}
// Mark form as modified
$('form_id').addClassName('modified');
// Enable submit/reset buttons
$('reset_button_id').removeAttribute('disabled');
$('submit_button_id').removeAttribute('disabled');
// Remove event handlers as they're no longer needed
if(browser.trident) {
$('form_id').stopObserving('keyup', change);
$('form_id').stopObserving('paste', change);
} else {
$('form_id').stopObserving('input', change);
}
if(browser.webkit) {
$$('#form_id textarea').invoke('stopObserving', 'keyup', change);
$$('#form_id textarea').invoke('stopObserving', 'paste', change);
}
inputs.invoke('stopObserving', 'change', arguments.callee);
};
$('form_id').observe('reset', function(e) {
// Unset form modified, restart modified check...
$('reset_button_id').writeAttribute('disabled', true);
$('submit_button_id').writeAttribute('disabled', true);
$('form_id').removeClassName('modified');
startObservers();
});
var startObservers = (function(e) {
if(browser.trident) {
$('form_id').observe('keyup', change);
$('form_id').observe('paste', change);
} else {
$('form_id').observe('input', change);
}
// Webkit apparently doesn't fire oninput in textareas
if(browser.webkit) {
$$('#form_id textarea').invoke('observe', 'keyup', change);
$$('#form_id textarea').invoke('observe', 'paste', change);
}
inputs.invoke('observe', 'change', change);
return arguments.callee;
})();
window.onbeforeunload = function(e) {
if($('form_id').hasClassName('modified') && !$('form_id').hasClassName('saving')) {
return 'You have unsaved content, would you really like to leave the page? All your changes will be lost.';
}
};
});
I would store each fields value in a variable when the page loads, then compare those values when the user unloads the page. If any differences are detected you will know what to save and better yet, be able to specifically tell the user what data will not be saved if they exit.
// this example uses the prototype library
// also, it's not very efficient, I just threw it together
var valuesAtLoad = [];
var valuesOnCheck = [];
var isDirty = false;
var names = [];
Event.observe(window, 'load', function() {
$$('.field').each(function(i) {
valuesAtLoad.push($F(i));
});
});
var checkValues = function() {
var changes = [];
valuesOnCheck = [];
$$('.field').each(function(i) {
valuesOnCheck.push($F(i));
});
for(var i = 0; i <= valuesOnCheck.length - 1; i++ ) {
var source = valuesOnCheck[i];
var compare = valuesAtLoad[i];
if( source !== compare ) {
changes.push($$('.field')[i]);
}
}
return changes.length > 0 ? changes : [];
};
setInterval(function() { names = checkValues().pluck('id'); isDirty = names.length > 0; }, 100);
// notify the user when they exit
Event.observe(window, 'beforeunload', function(e) {
e.returnValue = isDirty ? "you have changed the following fields: \r\n" + names + "\r\n these changes will be lost if you exit. Are you sure you want to continue?" : true;
});
I've used dirtyforms.js. Works well for me.
http://mal.co.nz/code/jquery-dirty-forms/
To alert the user before closing, use unbeforeunload:
window.onbeforeunload = function() {
return "You are about to lose your form data.";
};
I did some Cross Browser Testing.
On Chrome and Safari this is nice:
<form onchange="validate()">
...
</form>
For Firefox + Chrome/Safari I go with this:
<form onkeydown="validate()">
...
<input type="checkbox" onchange="validate()">
</form>
Items like checkboxes or radiobuttons need an own onchange event listener.
Attach an event handler to each form input/select/textarea's onchange event. Setting a variable to tell you if you should enable the "save" button. Create an onunload hander that checks for a dirty form too, and when the form is submitted reset the variable:
window.onunload = checkUnsavedPage;
var isDirty = false;
var formElements = //Get a reference to all form elements
for(var i = 0; len = formElements.length; i++) {
//Add onchange event to each element to call formChanged()
}
function formChanged(event) {
isDirty = false;
document.getElementById("savebtn").disabled = "";
}
function checkUnsavedPage() {
if (isDirty) {
var isSure = confirm("you sure?");
if (!isSure) {
event.preventDefault();
}
}
}
Here's a full implementation of Dylan Beattie's suggestion:
Client/JS Framework for "Unsaved Data" Protection?
You shouldn't need to store initial values to determine if the form has changed, unless you're populating it dynamically on the client side (although, even then, you could still set up the default properties on the form elements).
You can also check out this jQuery plugin I built at jQuery track changes in forms plugin
See the demo here and download the JS here
If you are open to using jQuery, see my answer a similar question:
Disable submit button unless original form data has changed.
I had the same challenge and i was thinking of a common solution. The code below is not perfect, its from initial r&d. Following are the steps I used:
1) Move the following JS to a another file (say changeFramework.js)
2) Include it in your project by importing it
3) In your html page, whichever control needs monitoring, add the class "monitorChange"
4) The global variable 'hasChanged' will tell, if there is any change in the page you working on.
<script type="text/javascript" id="MonitorChangeFramework">
// MONITOR CHANGE FRAMEWORK
// ALL ELEMENTS WITH CLASS ".monitorChange" WILL BE REGISTERED FOR CHANGE
// ON CHANGE IT WILL RAISE A FLAG
var hasChanged;
function MonitorChange() {
hasChanged = false;
$(".monitorChange").change(function () {
hasChanged = true;
});
}
Following are the controls where I used this framework:
<textarea class="monitorChange" rows="5" cols="10" id="testArea"></textarea></br>
<div id="divDrinks">
<input type="checkbox" class="chb monitorChange" value="Tea" />Tea </br>
<input type="checkbox" class="chb monitorChange" value="Milk" checked='checked' />Milk</br>
<input type="checkbox" class="chb monitorChange" value="Coffee" />Coffee </br>
</div>
<select id="comboCar" class="monitorChange">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<button id="testButton">
test</button><a onclick="NavigateTo()">next >>> </a>
I believe there can be huge improvement in this framework. Comment/Changes/feedbacks are welcome. :)

Categories

Resources