How to update React localstorage? - javascript

I have a website that does one of two things. If you have never been to the site, it asks for info, which is stored in localstorage, and then it takes you to the main content. If you have filled out the info before, then it takes you straight to the main content. This is all done in one page.
Currently, my main content page only works upon page reload. This is because React does not have localstorage data to load the main content. It is only rendering the page on load. As stated, this is all to happen on the same page.
<script type="text/babel">
var Weatherapp = React.createClass({
render: function(){
var weatherplace = localStorage.getItem('yourlocation');
var weatherplaceshared = localStorage.getItem('yourlocation').replace(/,/g, ", ");
var weathervane = new XMLHttpRequest();
weathervane.open('GET', 'http://api.openweathermap.org/data/2.5/weather?q='+weatherplace+'&appid=stuff', false);
weathervane.send(null);
var runthru = JSON.parse(weathervane.response);
var weathervalue = runthru.main.temp;
var weatherimage = runthru.weather[0].icon;
var weatherimageplace = "http://openweathermap.org/img/w/"+weatherimage+".png";
return (
<div id="weatherapp_container">
<div id="weatherapp_location">{weatherplaceshared}</div>
<div id="weatherapp_icon"><img src={weatherimageplace}/></div>
<div id="weatherapp_temperature"><p>{weathervalue}°F</p></div>
</div>
)}
});
ReactDOM.render(<Weatherapp />, document.getElementById('weatherapp'));
</script>
I want to restart the render function on a click event. To that end, I have changed my code like so. Note, the submitsuestado is the button that activates my function once input is stored for the first time.
render: function(){
document.getElementById('submitsuestado').addEventListener('click', function(){
var yourcity = document.getElementById('suciudad').value;
var yourstate = document.getElementById('suestate').value;
localStorage.setItem('yourlocation', yourcity+","+yourstate);
From there I duplicate the rest of the code on top. However, this does not work. I am trying to understand where the error lies, and what I might do to make sure that Weatherapp runs both on page load with local storage data stored, as well as on a fresh page where the local storage data is just recently put.

your click event just save value into localstorage, it didn't change the state of your component, so react will not render. if your want to render your component, just try to put your button into your component, and use setState to change the state of your component.

Related

Manipulating a Button's link in JS

I am attempting to manipulate the hyperlink of a button and I'm getting nowhere with this and not sure where I am going wrong.
The Code:
<link rel="stylesheet" href="https://cdn.site.td/Calendar.css">
<script type="text/javascript" src="https://cdn.site.td/Calendar.js"></script>
<div id="the-calendar"></div>
<script>
document.addEventListener("DOMContentLoaded", function() {
var options = {
fullNames : false
};
var myCalendar = new Calendar(document.getElementById('the-calendar'), options);
});
</script>
This generates an event calendar that is loaded on a separate website. It works perfectly when loading it on a separate domain except for one thing. There is a more info button for events and when you click that it attempts to go to:
/folder/folder/folder/event-name-1
So of course, when I generate it on a separate domain it attempts that same folder path except with the current domain. Therefore it goes nowhere since the folders are not the same on both domains.
I want to add an onClick event to the button to manipulate the path of the hyperlink.
The button is:
<button class="calendar-icon-info-action">More info</button>
Keep in mind this button is not generated until the initial script above loads and populates the page with the HTML for the calendar.
So once the calendar is loaded, I need each more info link for each event to be manipulated to add the original domain path. I would need a variable to store the original path because that will not change too.
So to recap more info leads generates:
/folder/folder/folder/event-name-1
I want this stored in a variable and then another var for the domain stored together so it becomes something like this:
var a = "domain.tld";
var b = "/folder/folder/folder/event-name-1";
var c = a + b;
document.getElementsByClassName("calendar-icon-info-action")[0].addEventListener("click", function(){
document.getElementsByClassName("calendar-icon-info-action")[0].href = var c;
});
The href attribute is applicable only for a tags (links). Since you have a <button>, what you could do is intercept and block the original event, and redirect the page to the desired URL.
Something like this:
document.getElementsByClassName("calendar-icon-info-action")[0].addEventListener("click", function(event){
// This will stop the original event:
event.preventDefault();
// This will open your desired URL:
window.location.href = c
});
If you have multiple buttons and want to update the event of all of them, you could loop the buttons:
document.querySelectorAll(".calendar-icon-info-action").forEach((elem) => elem.addEventListener("click", function(event){
event.preventDefault();
window.location.href = c;
}))
For future reference, if you had links instead of buttons, and wanted to change the href attribute, the proper way to do is:
document.getElementsByClassName("calendar-icon-info-action")[0].setAttribute('href', 'your-url-here')

How to re-render a full page with <Link> tag in react-router-dom

please help me about a problem i had with Link in react-router-dom like this:
window.addEventListener("scroll", function() {
const theEle = document.getElementById("id-of-div");
const eleTop = theEle.offsetTop;
const eleBottom = eleTop + theEle.offsetHeight;
console.log("the element of new page", eleTop, eleBottom)
});
So when i put the above script in page X, in page Y i have an
<a href='/x'>Link to page X<a>
if i clicked it in page Y then of course you will go to page X and scroll the mouse, window detect the mouse scroll and log out the result
But if i used a Link tag in react-router-dom then there would be an error saying can't get offsetTop of 'id-of-div'
<Link to='/x'>Link to page X</Link>
I wonder is there a way to force Link to do the job without using an a tag, because i really don't want the user re-render page x everytimes they go from page Y to X.
Obviously if you render other page, the id-of-div is not rendered anymore (it gets removed from the DOM) so actually you can't check it's offsetTop.
One of the solutions would be to check inside if the id-of-div exists:
window.addEventListener("scroll", function() {
const theEle = document.getElementById("id-of-div");
if (theEle) {
const eleTop = theEle.offsetTop;
const eleBottom = eleTop + theEle.offsetHeight;
console.log("the element of new page", eleTop, eleBottom);
}
});
However more flexible solution would be to connect the listener not with the window, but to the parent wrapper in that page where x. But keep in mind that it can be impossible in particular cases (depends on your components structure).

window.onload function is called on page load and also every time I close an overlay

I have some JS code that I am trying to debug, and the problem is that the window.onload function is being called way more often than I expect it to. Here is my JS code:
var trueCountApp = (function(){
window.onload = function(){openRulesOverlay()};
document.getElementById("open-rules-overlay-button").onclick = function(){openRulesOverlay()};
document.getElementById("select-rules-button").onclick = function(){saveRuleSelections()};
function openRulesOverlay(){
let blackjackRules;
if(sessionStorage.blackjackRules){
blackjackRules = JSON.parse(sessionStorage.blackjackRules);
for(let i=0; i<blackjackRules.length;i++){
document.getElementsByClassName("rule")[i].value = blackjackRules[i];
}
}
document.getElementById("rules_overlay").style.display = "block";
}
function saveRuleSelections(){
let blackjackRules = [];
let rules = document.getElementsByClassName("rule");
for(let i=0; i<rules.length;i++){
blackjackRules.push(rules[i].value);
}
let jsonBlackjackRules = JSON.stringify(blackjackRules);
sessionStorage.setItem("blackjackRules", jsonBlackjackRules);
document.getElementById("rules_overlay").style.display = "none";
}
})();
There are 2 buttons on my page: one opens an overlay, and the other closes an overlay. I also wanted to run some code a single time when the page is first loaded, and I just used the openRulesOverlay() function that I had already written as a placeholder for the code I want to run. What I expected to happen was for the page to load, openRulesOverlay() would run once, then the buttons would work as normal from there. However, it seems that the window.onload function is running anytime the overlay gets closed. Why is this happening?
Note: I did not include the html code because I didn't think it was relevant to this problem. Let me know if I need to include it.
Simple fix in my particular case: the default button type is "submit", so the page would load, the form would open, and then when I pressed a button to close the form, it was essentially reloading the page and opening the form again. Just needed to change button type to "button".

Unable to append local storage data across the domain

I have a massive problem, with little time to resolve it. I am creating my first mobile app for property search as a university project (its not based on real properties)
I tried using different keys it does not work, Im not getting the basics.
Basically I have a Jquery mobile app with many external pages which have details for a property, these pages have the same id but on different documents, When a user clicks the button to save, I want the title and the url of the page to be saved in local storage and to be retrieved by a third page called my favorites. The problem I am having is that when I go on each page and click save, it overrides what was already in local storage and it seems like each page has its own storage and as a result my favorites page always has only one favorite (the latest one), rather than a favorite list appending every time I click save. Here is my code:
<div data-role="header" id="samplePlacePage_hd">
<h4 id="hutRef">add#redHut456</h4>
</div>
<div data-role="main" id="samplePlacePage_cont">
<div id="image">
<img src="images/redhut.jpeg" height="200px" width="100%" alt="Hut">
</div>
<div id="place_title">
<p id="hutHeading">Stunning Red Hut in Central Red Beach</p>
</div>
<div>
<h4 style="float: left;">Rent: $2950pw</h4>
<h4 style="float: right;">Deposit: 5500</h4>
</div>
(Same code on both pages)
This was the function I had in my script file:
$(document).on("pagecreate",function (argument) {
var favoritesPlaces = [];
var heading = document.getElementById('hutHeading').innerText;
var ref = document.getElementById('hutRef').innerText;
var refLink = ref.replace("add#","");
document.getElementById('hutFav').onclick = function () {
var newFav = {
title: heading,
link: refLink
};
favoritesPlaces.push(newFav);
console.log(favoritesPlaces);
localStorage.setItem("favorites",JSON.stringify(favoritesPlaces));
}
})
Please help
Thanks
Two additional considerations for you: checking the favorite has not been added already, and allowing the user to have multiple tabs open on pages from your site - adding one page as a favorite should not interfere with adding a different page as a favorite. And not to forget, if the local storage item does not exist create a new one :)
Basically I suggest retrieving local storage, checking for duplicates, updating and saving back to local storage all occur in a single click handler, E.G. by rearranging your code and adding a few lines:
$(document).on("pagecreate",function () {
document.getElementById('hutFav').onclick = function () {
var favoritesPlaces = localStorage.getItem("favorites");
var heading = document.getElementById('hutHeading').innerText;
var ref = document.getElementById('hutRef').innerText;
var refLink = ref.replace("add#","");
var newFav = {
title: heading,
link: refLink
};
favoritesPlaces = favoritesPlaces || '[]'; // string
favoritesPlaces = JSON.parse(favoritesPlaces); // array
if( !favoritesPlaces.some( fave => fave.link === refLink)) {
favoritesPlaces.push( newFav)
console.log(favoritesPlaces);
localStorage.setItem("favorites",JSON.stringify(favoritesPlaces));
}
else {
console.log("already a favorite");
}
}
})
(tested)
Note that clearing localStorage on any page clears it for all pages across a site. Once cleared, its cleared on all pages, there are no more favorites, and any page can be added again without being a duplicate. If a "remove this page from favorites" button is needed, a new function needs to be written to do it.

Call YUI3 script before onSubmit() of Button on Wicket Framework

My requirement is on Click of "Submit" button -
loop through "< li >" elements on HTML page, get the objectURL from each
"< li >" element, load the image on to Canvas and get dataURL from
it. Store these dataURLs inside hidden field on HTML page.
Then retrieve the dataURLs from Hidden fields, convert them to byte
array and proceed with further processing.
I targeted to achieve below way...
1.Using YUI3 java script (submitBehavior_js.js) to achieve the first part. Used ("click" event)
submitButton.add(new submitBehavior_js('click',parameters));
2.Overriding onSubmit() method of "Submit" button to achieve second part.
onSubmit(target,form)
{
String[] imgArray = null;
imgdata = hiddenImageData.getValue();
imgArray = imgData.split(',');
.........
}
I have gone through several threads and with my practical experience, onSubmit() java code is invoked before submitBehavior_js.js and so, the hidden fields didn't have any image data.
So, I tried to invoke the java script using "mouseup" event instead of "click". This was working perfectly fine and java script is running before the onSubmit() on wicket controller.
However, my code is adaptive web and it should work across browsers on mobile platforms. Evidently "mouseup" din't come to my rescue. I tried to use "touchend" and "gesturemoveend" events as suggested by YUI3 documentation, but in both cases onSubmit() wicket java code is executed before the javascript.
Then, I tried to invoke javascript as below:
onSubmit(target, form)
{
target.appendJavaScript("new submitBehavior_js('click',<<parameters>>)");
System.out.println("Inside Submit method in wicket");
String[] imgArray = null;
imgdata = hiddenImageData.getValue();
imgArray = imgData.split(',');
.........
}
With above piece of code, control is going to java script from Wicket controller but comes back to java code before executing the onLoad() of Canvas element. Here is my java script snippet...myCanvas is an hidden element on HTML(style=display:none)
alert("Start here");
var imgArray[];
var lineCtr = 0;
for each LI List item (Say I have 2 items)
{
var imageObjectURL = node.get('children').getAttribute('href')
image = new Image()
image.onLoad = function() {
alert("Inside onload of image to canvas");
var canvas = document.getElementById("#myCanvas");
var ctx = canvas.getContext('2d');
ctx.fillRectangle('white');
ctx.drawImage(image,700,600,0,0);
var data = ctx.toDataUrl();
imgArray[lineCtr] = data;
Y.one("#hiddenImageData").setAttribute('value',imgArray);
lineCtr = lineCtr + 1;
alert("finished here");
}
image.src = imageObjectURL;
alert("after assigning object URL. Completed List item");
}
The order of display/alert is as follows:
alert - Start here
alert - after assigning object URL. Completed List item
alert - after assigning object URL. Completed List item
JAVA Sysout - Inside Submit method in wicket
alert - Inside onload of image to canvas
alert - finished here
alert - Inside onload of image to canvas
alert - finished here
Because on load of Canvas element is executed after the java code, obviously the hidden Image Data variable has null values....and I am losing the captured/uploaded images by User.
Any reason for this weird behavior? or May be my understanding is wrong? Also, a better way to accomplish my task.
Appreciate your time and help!!
Do your JavaScript you want to do in an IAjaxCallListener like i showed in this answer. This way you make sure it is executed before the onSubmit() login is executed.

Categories

Resources