I am trying to remove item from localstorage or rather clear it on button click. I have written the code but on clicking on the button, it does not clear the localstorage data. this is the variable with the localstorage data
window.onbeforeunload = function() {
localStorage.setItem("first_name", $('#inputName').val());
};
EDITTED
window.onload = function() {
var name = localStorage.getItem("first_name");
if (name !== null) {
$('#inputName').val(name);
alert(name);
}
};
this is the function to clear storage
function clearStorage(){
alert('localstorage cleared!');
localStorage.removeItem('first_name');
}
the snippet of the button click code block to clear localstorage data using the key-name
<input type="text" id="inputName" placeholder="Name" required>
<button onclick="clearStorage()">clear</button>
on clicking the button in attempt to wipe out the data from the localstorage and refreshing the page, the localstorage data is still in the input value.
how to clear localstorage content is my challenge
You're successfully removing the item — and then when you refresh, you're setting it again as you leave the page, because you still have:
window.onbeforeunload = function() {
localStorage.setItem("first_name", $('#inputName').val());
};
You'll have to decide when you want to set the item. The above will always do it, even if you've cleared it previously.
Perhaps you'd be better off only setting the item when the input changes, and not in onbeforeunload. That is, getting rid of the above, and instead:
$("#inputName").on("input", function() {
localStorage.setItem("first_name", $(this).val());
});
That way, if you clear the item (remove it from local storage), it won't get added back unless you edit the field again.
The code for setting/clearing the local storage looks good. However, the input field is not real-time synched with your local storage so, if you want your input to be always up to date with your local storage value, you should update it inside the clearStorage function in this way. Also you don't need to refresh the page if you use this approach:
window.onload = function() {
var name = fetchLocalStorage();
if (name !== null) {
$('#inputName').val(name);
alert(name);
}
};
function fetchLocalStorage() {
return localStorage.getItem("first_name");
}
function clearStorage() {
// clear local storage
localStorage.removeItem('first_name');
alert('localstorage cleared!');
// update input value
var name = fetchLocalStorage();
$('#inputName').val(name);
}
function saveStorage() {
localStorage.setItem("first_name", $('#inputName').val());
}
And the HTML should be updated to:
<input type="text" id="inputName" placeholder="Name" required>
<button type="button" onclick="saveStorage()">save</button>
<button type="button" onclick="clearStorage()">clear</button>
uhm, try adding type="button" to your button...
this prevents the form submit + page reload + onbeforeunload -> where your storage item gets set every time...
https://developer.mozilla.org/en/docs/Web/HTML/Element/button#attr-type
Related
I have some code that updates controls on my page using Javascript/Ajax/Json calls.
My only problem is that sometimes the control is updated while the user is actively attempting to change the control.
For example - I will be typing in something, and the Ajax call will execute, replacing what I have typed.
Is this a way in javascript/jquery to say:
If $(this).NotBeingCurrentlyEdited ?
I know about the focus option, but how can I say "Not in focus, not being edited currently?"
You can use document.activeElement to check which element has the focus. If the element you want to change has the focus then skip the update. See example snippet below.
var val = 0;
setInterval(() => {
$('input').each((i, el) => {
if (document.activeElement !== el) {
$(el).val(val);
}
});
val++;
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="1">
<input id="2">
The way I would approach it is using a timer to determine if the textbox has recently been changed by the user. You could combine this with checking the control's focus as well once an Ajax request is received. You can either disregard updates to that field entirely when TextBoxIsBeingEdited = true or store the updates somewhere to push once the timer ticks.
var TextBoxIsBeingEdited = false;
function TextBoxEdited(){
if(TextBoxIsBeingEdited === false){
document.getElementById("TextBoxStatus").innerText = "Editing";
TextBoxIsBeingEdited = true;
setTimeout(ResetTextBoxEdited, 2000);
}
}
function ResetTextBoxEdited(){
document.getElementById("TextBoxStatus").innerText = "Not Being Edited";
TextBoxIsBeingEdited = false;
}
<input type="text" id="TextBox" oninput="TextBoxEdited()">
<br><br>
<div id="TextBoxStatus">
Not Being Edited
</div>
Is there any way to detect if user has changed from the content of one section to another in the same page?
I have a page with multiple buttons (1 form/section is opened once you click on each button), when they all are closed i can detect user is changing to another form using a click event on the button element.
My sections in this case are forms loaded when you click on every button in the page. pure jquery to load the content via ajax inside them.
The problem is when all sections are open. I need to detect when user has changed between the content of one section to another.
I have to warn the user about saving your changes in a previous form because system has a timeout for inactivity, if user didnt save his data, it is lost once user gets logout from application.
the event prompt the user to save the data of the previous form.
The only way I can think of doing this is using a mouse event, but this can sometimes be a frustrating experience.
Solved
Thanks DelightedD0D, I ended up doing this
This var saves the previous form number
var pendingForm = [];
Events which fire a possible warning
//Pressing tab is reviewed if there are unsaved changes in the previous section.
$(document).keyup(function(eventTab) {
var code = eventTab.keyCode || eventTab.which;
if (code === 9) {
checkPrevious(eventTab);
}
});
//Clicking is reviewed if there are unsaved changes in the previous section
$(document).mouseup(function(eventMouse) {
checkPrevious(eventMouse);
});
Here we establish when a form is pending or has changed
$('.formSection').on('keyup change', 'input, select, textarea', function() {
$(this).closest('.formSection').addClass('pending');
//We get the number of the form by the id
var numForm = $(this).closest('.formSection').attr('id').substr(11, 2);
if ( $.inArray(numForm , pendingForm) == -1 ) {
pendingForm.push(numForm);
}
});
//I have my own functions to save and cancel, but the idea is Save the data
//then find the formSection from previous form, remove pending class and
//remove number form from array of pending sections
$('.save').click(function() {
//save data...
var numForm = pendingForm.pop();
$('#formSection'+numForm).removeClass('pending');
});
And this function checks when user move to another form
function checkPrevious(e) {
var $target = $(e.target);
//If it is clicked somewhere within a form or a button that opens a section
if ($target.closest('.formSection').length || $target.hasClass('btnSection')) {
var isDisabled = false;
if (pendingForm.length > 0) {
prevForm = pendingForm.slice(-1).pop();
//Every submit form button has an id with a consecutive number in my case
//If disabled, that means it has errors in validation (Bootstrap)
//**I have to improve this verification yet**
isDisabled = $('#submitForm' + prevForm).is(':disabled');
}
// get any forms with changes that are not the current form or do not contain the clicked element
var $otherFormsWithChanges = $('.pending').filter(function() {
var $this = $(this);
return $this.hasClass('pending') && (!$this.is($target) || $this.has($target).length != 0);
});
// if another form has a change, thow up a message
// allow the user to go back to the form or ignore the changes
if ($otherFormsWithChanges.length > 0 && $otherFormsWithChanges.has($target).length === 0 ) {
var modalPrev = $('#modalPrev');
if ( isDisabled == false ) {
//If everything is ok, we can save
modalPrev.find('.modal-content .modal-body').html("<p>You have unsaved changes. Do you want to save previous form?</p>");
modalPrev.find(".btnSave").removeClass('hide');
} else {
modalPrev.find('.modal-content .modal-body').html("<p>You have some errors in your previous form.</p>");
modalPrev.find(".btnSave").addClass('hide');
}
$('#modalPrev').modal('show');
}
}
}
I show a modal instead of an alert with two buttons [Save] and [Cancel], every one has a function which do a save or close but both remove the previous section from the array to not be considered anymore.
You could do this by setting a class on the form when input values change then listening for clicks on the document and checking if a form other than the one being interacted with has changes. If one does, present a message to the user.
This should work:
Note that you dont have to use forms, just add the track-changes class to some parent of the inputs you have grouped together
jsFiddle example
$(document).mouseup(function(e) {
var $target = $(e.target);
// get any forms with changes that are not the current form or do not contain the clicked element
var $otherFormsWithChanges = $('.pending').filter(function() {
var $this=$(this);
return $this.hasClass('pending') && (!$this.is($target) || $this.has($target).length !=0);
});
// if another form has a change, thow up a message
// allow the user to go back to the form or ignore the changes
if ($otherFormsWithChanges.length > 0 && $otherFormsWithChanges.has($target).length===0 ) {
var c = confirm("You have unsaved changes.\n\n Click cancel to go back to the unsaved form or OK to ignore");
c ? $otherFormsWithChanges.removeClass('pending') : $otherFormsWithChanges.find('input, select, textarea').focus();
}
});
$('.track-changes').on('keyup change', 'input, select, textarea', function() {
$(this).closest('.track-changes').addClass('pending');
});
$('.save').click(function() {
// save data...
$(this).closest('.track-changes').removeClass('pending');
});
form{
padding:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>form 1</h4>
<form class="track-changes" has-changes="false" action="">
<input type="text">
some text
<br>
<button type="button" class="save">Save</button>
</form>
<h4>form 2</h4>
<form class="track-changes" has-changes="false" action="">
<input type="text">
some text
<br>
<button type="button" class="save">Save</button>
</form>
<h4>form 3</h4>
<form class="track-changes" has-changes="false" action="">
<input type="text">
some text
<br>
<button type="button" class="save">Save</button>
</form>
I have an input HTML element and want to execute a function when there was an input and if this input didn't changed for 3 seconds.
Code:
$("#search_input").on('input', function() {
input_value = $("#search_input").val();
if (input_value != "") {
setTimeout(function() {
if (input_value == $("#search_input").val()) {
alert("still the same :) -> go search");
}
}, 3000);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="form-control" id="search_input" placeholder="Search...">
The problem is that the handler refresh the input_value so it's always the same. How do you set the input_value as a local variable, so it's not refreshed?
You forgot the var declaration:
var input_value = $("#search_input").val();
while the var thing is true, it's unlikely the issue.
Looks like you want something like the link below, with the key difference being that you are setting a timeout and clearing the timeout as the input changes. By definition, the function above is always firing when input is changing so it's redundant.
Run javascript function when user finishes typing instead of on key up?
var var_name = value if it's a normal variable. Like a string or number.
Do $var_name = jQuery_object if it's a jQuery object.
I know Angular has simple syntax to display messages or update css, but what I'm trying to do is actually call a function.
<input ng-model="somefield">
<span ng-show="!somefield.length">Please enter something!</span>
<span ng-show="somefield.length">Good boy!</span>
This is my model vm.tagSearching = '' I can detect when I start typing in the input and see the value update. However once I get to the last letter, and I delete that I don't get an update.
I tried using $scope.watch
$scope.$watch('vm.tagSearching', function() {
alert('hey, var has changed!');
});
However this only fires once as the app initializes, but never again, even while typing.
Markup
<input class="tag-search-input"
type="text"
placeholder="Search Tags"
ng-model="tgs.tagSearching"
typeahead="t for t in tgs.fuzzyTagSearch($viewValue)">
Controller
function fuzzyTagSearch(word) {
console.log('fuzzyTagSearch',word);
if (word.length > 2) {
ApiFactory.getSearchResults(word).then(function(data) {
console.log('data',data.data.ticker_tags);
vm.terms = data.data.ticker_tags;
});
}
}
How would you accomplish this? I need to detect when the input is clear when the user backspaces / deletes all the letters so that I can reset the table.
You can simply set up an ng-change directive.
<input ng-model="tgs.tagSearching" ng-change="tgs.detectEmpty()">
vm.detectEmpty = function() {
if (vm.tagSearching.trim().length === 0) {
// it's empty
}
}
I have a HTML from to capture string data. I am saving those when I hit the save button via ajax. But the scope also includes saving the data on a sessionstorage once I focus out of the form field with the orange save button after it checks the value is not empty. The idea is to pre populate each form field with values stored in the session storage. Everything works fine but I just cant figure out the session storage part. The hard part is how to assign a unique key for each form field, and use that key to find and preload values in the field.
Here is my JS
$('.wrapper').remove()
function renderInput() {
var inputField = '<div class="wrapper"><input class="zoom-text-field" type="text" value=""/><span class="close">save</span></div>';
return inputField;
}
function hideZoomFiled(e, textData) {
$(e).parent().parent().children('.students-name-collection').val(textData);
console.log(textData)
$(e).parent().hide();
$('.students-name-collection').attr('disabled', false);
$(e).prop('disabled', false);
}
function disableInputField(obj) {
$('.students-name-collection').attr('disabled', false);
$(obj).attr('disabled', true);
}
$('.students-name-collection').on('focus', function () {
disableInputField(this);
$(this).next('.wrapper').focus();
$('.wrapper').remove();
$(this).parent().append(renderInput());
var textData = '';
$('.close').on('click', function () {
textData = $(this).parent().children().val();
hideZoomFiled(this, textData);
});
$('.zoom-text-field').on('blur', function(){
if($(this).val() !== ''){
//save the value in the sessionstorage
//This is where I am getting lost
}
});
});
$('#submitForm').on('click', function(){
sessionStorage.clear();
})
// on page load read the session storage and pre fill the form fields
Here is my fiddle
http://jsfiddle.net/sghoush1/ykshgrxg/5/
Here is how you can handle this, as you pointed out the main problem here is how to figure out how to save each input item, and how to place it back when the page loads. What you can do is give each item an index, from 0 to 4.
To get the index of the element you are on, you can add an selected class to it, then use that class in order to find the elements position by using .index($('.selected')), of course we can remove that class when we are done with it. This can be used as the key for the sessionStorage, then the textData is the value:
// Get the index of the input item we are on
$(this).addClass("selected");
var key = $(".students-name-collection").index($('.selected'));
$(this).removeClass("selected");
$('.close').on('click', function () {
var textData = $(this).parent().children().val();
hideZoomFiled(this, textData);
if(!!textData){
//save the value in the sessionstorage
sessionStorage.setItem(key, textData);
}
});
Then for loading them in you can use jQuerys .each and have that on the class .students-name-collection using an index of sessionStorage to give each input the correct value:
// on page load read the session storage and pre fill the form fields
$('.students-name-collection').each(function(index) {
if(sessionStorage[index])
$(this).val(sessionStorage[index])
});
Here is a Fiddle Example