I'm working on saving textarea value on browser refresh. When there's a change to textarea by keyboard events, the value gets stored in local storage. However, When the textarea value gets changed indirectly...like button clicks, the value doesn't get saved. That's the problem, So, I changed my event handler from onkeyup to onchange. Still, This remains a problem. Do anyone have a better idea for this. Here's the code -
<textarea id="thetext" class="" value="Write some value, and off focus this input. Refresh the browser, and see the text getting saved." onchange="saveValue(this);"></textarea><br/><br/>
<button id="thebutton" onclick="change()">Change</button>
<script>
document.getElementById("thetext").value = getSavedValue("thetext");
function saveValue(e){
var id = e.id;
var val = e.value;
localStorage.setItem(id, val);
}
function getSavedValue (v) {
if (!localStorage.getItem(v)) {
return "";
}
return localStorage.getItem(v);
};
function change() {
document.getElementById("thetext").value = "This value doesn't get saved if there's no keyboard action. But I want this to get saved on button click."
}
</script>
<style>
textarea{height:100px;width:100%}
</style>
Edit - Above code is working well on my environment.
you can do in easy way
function change() {
let newValue = "This value doesn't get saved if there's no keyboard action. But I want this to get saved on button click."
var event = new Event('input');
thetext.dispatchEvent(event);
// or
// document.getElementById("thetext").value = newValue;
// localStorage.setItem("thetext", newValue );
}
or complex usinng Object.defineProperty
thetext = document.getElementById("thetext")
thetext.value = getSavedValue("thetext");
function saveValue(e) {
console.log(e)
var id = e.id;
var val = e.value;
localStorage.setItem(id, val);
}
function getSavedValue(v) {
return localStorage.getItem(v) || "";
}
function change() {
document.getElementById("thetext").value = "This value doesn't get saved if there's no keyboard action. But I want this to get saved on button click."
}
function monitorValue(element, property) {
let descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(element), property);
Object.defineProperty(element, property, {
get: function() {
return descriptor.get.apply(this, arguments);
},
set: function() {
descriptor.set.apply(this, arguments);
// create and dispatch input event
var event = new Event('input');
element.dispatchEvent(event);
return this.value;
}
});
}
monitorValue(thetext, "value")
<style>textarea{height:80vh;width:100%}</style>
<textarea id="thetext" class=""
value="Write some value, and off focus this input. Refresh the browser, and see the text getting saved."
oninput="saveValue(this);
"></textarea><br/><br/>
<button id="thebutton" onclick="change()">Change</button>
So what you want is that, the <textarea> value be stored in the localStorage every time it's changed.
I'd prefer defining a setter property on the textarea.
var ta = document.getElementById('thetext');
Object.defineProperty(ta, 'savedValue' , {
set: (value)=> {
ta.savedValue = ta.value = value;
localStorage.setItem(ta.id, value);
}
};
thebutton.addEventListener('click', (evt)=> {
ta.savedValue = 'my sample click value';
});
ta.addEventListener('change', (evt)=> {
ta.savedValue = evt.target.value;
};
Related
How can I get the value of a button when there are many multiple buttons created? Currently on my Javascript file I have it so my search history makes a button in a list with a "value" of the city that is labeled.
When I click on the button that was made I get undefined.
function recentSearch(city) {
var addCity = document.createElement("button");
addCity.setAttribute("value", city);
addCity.textContent = city;
document.getElementById("searchHistory").append(addCity);
cities.push(city);
localStorage.setItem("searches",JSON.stringify(cities));
}
If you're adding so many buttons use event delegation. Add one listener to the parent container, add your buttons, and then, in the listener function, check to see if the clicked element is a button, and log its value.
const searchHistory = document.querySelector('#searchHistory');
// Add one listener to the container that calls `handleClick`
searchHistory.addEventListener('click', handleClick, false);
function handleClick(e) {
// Destructure the nodeName and value from
// the clicked element, and log the value if the
// element is a button
const { nodeName, value } = e.target;
if (nodeName === 'BUTTON') {
console.log(value);
}
}
function recentSearch(city) {
var addCity = document.createElement('button');
addCity.value = city;
addCity.textContent = city;
searchHistory.append(addCity);
}
const cities = ['London', 'Rome', 'New York', 'Seoul', 'Kingston'];
for (const city of cities) {
recentSearch(city);
}
<div id="searchHistory"></div>
The following code will log the value of the button to the console when it is clicked.
function recentSearch(city) {
var addCity = document.createElement("button");
addCity.setAttribute("value", city);
addCity.textContent = city;
addCity.onclick = (e)=>{
console.log(e.target.getAttribute('value'));
//or whatever other code you want to do onclick
}
document.getElementById("searchHistory").append(addCity);
cities.push(city);
localStorage.setItem("searches",JSON.stringify(cities));
}
Try using data-attributes. They make your code easier to read and provide a great way to pass along data inside of elements - and you can access their data using element.dataset.<attribute_name> - in this case e.target.dataset.value (from within the buttons click listener).
cities = []
function recentSearch(city) {
// FOR DEMO ONLY::
if (!city) city = "city " + Math.ceil(Math.random() * 1000);
var addCity = document.createElement("button");
addCity.setAttribute("data-value", city);
addCity.textContent = city;
addCity.addEventListener('click', e => {
console.log(`my city is: ${e.target.dataset.value}`);
})
document.getElementById("searchHistory").append(addCity);
cities.push(city);
// localStorage.setItem("searches",JSON.stringify(cities));
}
<div id='searchHistory'>
</div>
<button onclick='recentSearch()'>Make City</button>
Structure Concept:-
Basically, i am trying to create the modal window containing input and that modal window currently fires when the input on index page get focused for that I have used data attribute to make a link between them by assigning them same attribute value.
Javascript Concept:-
for the modal window, I have created the modal object. and model object contains a bindModal method which takes one argument and that argument is data attribute value. after taking that value bindModal method will search dom elements containing that particular value and after the search, I iterate over them using each loop.
Problem
So basically I want whenever user starts typing on the model input it should get written automatically in input on the index page.
I will appreciate you all if guys help me out to make my code more optimized and well structured and most important thing is that let me know what mistake I have done in overall work Thanks
JavaScript Code
var modal = function () {
this.toggleModal = function () {
$('#modal').toggleClass('content--inActive').promise().done(function () {
$('#modal__close').on('click',function(){
$('#modal').addClass('content--inActive');
});
});
}
this.bindModal = function (bindVal) {
var bindValue = $(document).find('[data-modal-bind = ' + bindVal + ']');
$.each(bindValue, function (index) {
var bind1 = $(this);
if(index === 1) {
var bind2 = $(this);
$(bind1).change(function (){
$(bind2).val(bind1.val());
});
}
});
}
}
var open = new modal();
$('#input_search').on('click',function(){
open.toggleModal();
open.bindModal('input');
});
Here is one way to do what you want:
var modal = function() {
this.bindModal = function(bindVal) {
var bindValue = $('[data-modal-bind = ' + bindVal + ']');
bindValue.each(function(index) {
$(this).keyup(function() {
var value = $(this).val();
bindValue.each(function(i, e) {
$(this).val(value);
});
});
});
}
}
$('#input_search').on('click', function() {
var open = new modal();
open.bindModal('input');
});
Changes done:
I cached the inputs with same binding values in bindValue variable, and then bound the the keyup event for each of them. On keyup, the value of the current input is get in value, which is then assigned to each input using the inner loop.
This makes the inputs to be in sync while typing. Hope that solves your issue.
i wanted to get the value of my textbox in javascript. this is my javascript-
<script type="text/javascript">
var submitted = false; var type;
window.onbeforeunload = function () {
if (!submitted) {
return "Are you sure you want to leave this page, your test will not be saved?"+type;
}
};
document.getElementById('form1').onsubmit = function () {
type=document.getElementById('TextBox1').value;
submitted = true;
};
</script>
no matter what i type it does not give me the value of textbox1
<script type="text/javascript">
var submitted = false; var type;
$(document).ready(function ()
{
$('#form1').submit(function ()
{
type = document.getElementById('TextBox1').value;
submitted = true;
});
window.onbeforeunload = function ()
{
if (!submitted)
{
return "Are you sure you want to leave this page, your test will not be saved?" + type;
}
};
});
</script>
if you want to display type's value in alert box then,change if(!submitted') to if(submitted) and you will receive an alert with type value.hope this will do.
This looks like just a logic problem:
When you run onsubmit, it sets submitted to true, and then it runs onbeforeunload. Right now it it basically only returns the input value if you've not run onsubmit. If you take the ! out of (!submitted), it will give you an alert with the input's value.
I am hearing a input, while input is changed i am getting value. as a initial i am passing 1 as a default. so after that the user change the value i should get the values,
But i am getting error as : undefined is not a function
what is the issue..?
here is my code :
var docLoader = function (params) {
window.container = window.container || $("#tenderContent");
return {
init : function () {
this.container = container.find("#documentscroll");
this.inputPage = container.find("#inputpage");
this.width = this.container.width();
this.height = this.container.height();
this.preload();
this.inputChange();
$(this.inputPage).bind("change paste keyup", this.inputChange);
},
preload : function () {
var that = this;
this.container.load("../common/preloader/index.html",
function(msg){
$('#mask').css({width:that.width,height:that.height});
});
},
//load page
loadPage : function (num) {
this.container.load("Doc/chapter"+num+"/index.html");
},
//input change
inputChange : function (e) {
var inputVal = e != undefined ? e.target.value : 1;
this.loadPage(inputVal); //while page load it works, getting value from input, on change i am getting error.
}
}
}
jQuery(document).ready(function($) {
docLoader().init();
$(window).resize(function(){
docLoader().init();
});
});
In this function (inputChange:) this is reference to current ($(this.inputPage)) element, that why you get error (because in element there is not method loadPage). To fix it, you need bind this (which is reference to object that located in return {}) to function, there are several ways how to do it
$(this.inputPage).bind("change paste keyup", this.inputChange.bind(this));
Or
var _this = this;
$(this.inputPage).bind("change paste keyup", function (e) {
_this.inputChange(e)
});
Or
$(this.inputPage).bind("change paste keyup", $.proxy(this.inputChange, this));
About $.proxy
i am working on a webpage that consists a JQuery item and a Knockout Item.
basically the view has a select field and a sevond view that is being updated by the select value change.
also i have a textbox search field with jquery autocomplete.
What i want to do is when i press enter after on the search box, the javascript will update the ko.observable value and trigger the ther updates yet its not working. i've managed to trigger keypress but i cant update and trigger the update..
Heres the code:
function Station(data){
var self = this;
this.userId = ko.observable(data.userid);
this.displayName = ko.observable(data.displayName);
this.email = ko.observable(data.email);
this.redirectURL = ko.computed(function(){
return "/someurl/somerequest?userId="+self.userId();
});
this.selectText = ko.computed(function(){
return self.displayName();
})
}
function currentStation(index)
{
return self.stations()[index];
}
function StationViewModel(){
var self = this;
self.stations = ko.observableArray([]);
$("#stationSelect").attr("disabled,true");
$.getJSON("#{someurl.getStationList()}",function(allData){
var mappedStations = $.map(allData,function(item)
{
return new Station(item);
});
self.stations(mappedStations);
$("#stationSelect").attr("disabled,false");
});
url = "/someurl/somerequest?userId=";
this.selectedStation = ko.observable();
this.redirectToStation = function(){
var linkToSend =
alert(self.selectedStation.redirectURL());
}
<!-- THIS IS THE CODE THAT HAS TO UPDATE THE FIELD BUT IT DOESN'T-->
this.getStation = function(event)
{
for(i = 0; i<this.stations().length;i++)
{
if(this.stations()[i].userId()==$("#search").val())
{
self.selectedStation = ko.observable(this.stations()[i]); //Am i doing it right?
}
}
};
}
<!-- This is the code That handles the click event inside the textbox. its working -->
ko.bindingHandlers.executeOnEnter = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var allBindings = allBindingsAccessor();
$(element).keypress(function (event) {
var keyCode = (event.which ? event.which : event.keyCode);
if (keyCode === 13) {
allBindings.executeOnEnter.call(viewModel);
return false;
}
return true;
});
}
};
ko.applyBindings(new StationViewModel());
</script>
Instead of
self.selectedStation = ko.observable(this.stations()[i]);
do
self.selectedStation(this.stations()[i]);
Hope this helps!
What I have done in the past to get the Enter key working is to wrap the <input> in a <form> tag
so from
<input type="text" data-bind="value:myValue"></input>
to
<form>
<input type="text" data-bind="value:myValue"></input>
</form>