I have a button to add a photo to a webpage. The button is currently set up to input a dummy image. I'm trying to get it to allow me to select my own image and then have it save in local storage to stay on the page when it's reloaded. I've tried a few things to get this but I can't. I've been sat looking at the code trying to work it out for ages.
The two tasks are as follows:
When an image entry is added to the DOM, make an image item containing the image data, and store it in local storage.
When the file input element selection changes, use a FileReader object to convert the file to a data URL and add an image entry to the DOM using this data URL.
The add image part of the code is as follows:
function addImageEntry(key, data) {
// Create a image element
var imgElement = new Image();
imgElement.alt = "Photo entry";
imgElement.src = data;
addSection(key, imgElement);
}
function addEntryClick() {
var key = "diary" + Date.now();
var initialText = "";
var isNewEntry = true;
addTextEntry(key, initialText, isNewEntry);
}
function addPhotoClick() {
var inputElement = document.querySelector("#image input");
inputElement.click();
}
function processFile(inputChangeEvent) {
console.log("processFile called with arguments:", {
inputChangeEvent,
});
function addImage(data) {
console.log("addImage called with arguments:", {
data,
});
var key = "diary" + Date.now();
addImageEntry(key, data);
// TODO: Task 1 of 2
// Make an image item using the given data URL
// (demonstrated elsewhere in this file)
// Store the item in local storage using the given key
// (demonstrated elsewhere in this file)
var imageData = data;
var item = makeItem("image", imageData);
localStorage.setItem(key, item);
}
// Add a 'dummy' image entry
addImage(window.DUMMY_DATA_URL);
// TODO: Task 2 of 2
// Complete this function to read a file when it is selected:
// (imgElement and messageElement do not exist in this app so remove that code)
// ...then call addImage using the data URL you obtain
// ...and comment out line above using window.DUMMY_DATA_URL
// Clear the file selection (allows selecting the same file again)
inputChangeEvent.target.value = "";
}
The TODO parts is where I am working and have some comments with them. I think I have task 1 done as when the dummy image is added and the page is refreshed it still appears.
Related
I've been able to sort out the middle bit (the API seems to be called to just fine) along with the submenu displaying. Originally I thought that just the end part wasn't working but I'm now thinking that the selection part isn't either.
What am I doing wrong with the getSelection() and what do I need to do to insert a link into said selection? (to clarify, not to replace the text with a link, but to insert a link into the text)
//Open trigger to get menu
function onOpen(e) {
DocumentApp.getUi().createAddonMenu()
.addItem('Scry', 'serumVisions')
.addToUi();
}
//Installation trigger
function onInstall(e) {
onOpen(e);
}
//I'm not sure if I need to do this but in case; declare var elements first
var elements
// Get selected text (not working)
function getSelectedText() {
const selection = DocumentApp.getActiveDocument().getSelection();
if (selection) {
var elements = selection.getRangeElements();
Logger.log(elements);
} else {
var elements = "Lack of selection"
Logger.log("Lack of selection");
}
}
//Test run
// insert here
// Search Function
function searchFunction(nameTag) {
// API call + inserted Value
let URL = "https://api.scryfall.com/cards/named?exact=" + nameTag;
// Grabbing response
let response = UrlFetchApp.fetch(URL, {muteHttpExceptions: true});
let json = response.getContentText();
// Translation
let data = JSON.parse(json);
// Jackpot
let link = data.scryfall_uri;
// Output
Logger.log(link);
}
// Test run
searchFunction("Lightning Bolt");
//Let's hope this works how I think it works
function serumVisions() {
const hostText = getSelectedText();
const linkage = searchFunction(hostText);
// Unsure what class I'm supposed to use, this doesn't
const insertLink = DocumentApp.getActiveDocument().getSelection().newRichTextValue()
.setLinkUrl(linkage);
Logger.log(linkage);
}
For the first part, I tried the getSelection() and getCursor() examples from the Google documentation but they don't seem to work, they all just keep returning null.
For the inserting link bit, I read all those classes from the Spreadsheet section of the documentation, at the time I was unaware but now knowing, I haven't been able to find a version of the same task for Google Docs. Maybe it works but I'm writing it wrong as well, idk.
Modification points:
In your script, the functions of getSelectedText() and searchFunction(nameTag) return no values. I think that this might be the reason for your current issue of they all just keep returning null..
elements of var elements = selection.getRangeElements(); is not text data.
DocumentApp.getActiveDocument().getSelection() has no method of newRichTextValue().
In the case of searchFunction("Lightning Bolt");, when the script is run, this function is always run. Please be careful about this.
When these points are reflected in your script, how about the following modification?
Modified script:
Please remove searchFunction("Lightning Bolt");. And, in this case, var elements is not used. Please be careful about this.
From your script, I guessed that in your situation, you might have wanted to run serumVisions(). And also, I thought that you might have wanted to run the individual function. So, I modified your script as follows.
function getSelectedText() {
const selection = DocumentApp.getActiveDocument().getSelection();
var text = "";
if (selection) {
text = selection.getRangeElements()[0].getElement().asText().getText().trim();
Logger.log(text);
} else {
text = "Lack of selection"
Logger.log("Lack of selection");
}
return text;
}
function searchFunction(nameTag) {
let URL = "https://api.scryfall.com/cards/named?exact=" + encodeURIComponent(nameTag);
let response = UrlFetchApp.fetch(URL, { muteHttpExceptions: true });
let json = response.getContentText();
let data = JSON.parse(json);
let link = data.scryfall_uri;
Logger.log(link);
return link;
}
// Please run this function.
function serumVisions() {
const hostText = getSelectedText();
const linkage = searchFunction(hostText);
if (linkage) {
Logger.log(linkage);
DocumentApp.getActiveDocument().getSelection().getRangeElements()[0].getElement().asText().editAsText().setLinkUrl(linkage);
}
}
When you select the text of "Lightning Bolt" in the Google Document and run the function serumVisions(), the text of Lightning Bolt is retrieved, and the URL like https://scryfall.com/card/2x2/117/lightning-bolt?utm_source=api is retrieved. And, this link is set to the selected text of "Lightning Bolt".
Reference:
getSelection()
I have coded a small API gallery that fetches an image from an API, but I need to know how do I store and save an image?
My codepen: https://codepen.io/aaron_1986/pen/VwdvqWB
Below is my JavaScript code that I used to create the API gallery that fetches an image from an API and displays the image on screen.
function get_image() {
let access_key = 'YmMDTJCtZaK6veBdER5WkjyqmgGBRyH6Bpdqt7WcrM4';
let url = `https://api.unsplash.com/photos/random /?client_id=YmMDTJCtZaK6veBdER5WkjyqmgGBRyH6Bpdqt7WcrM4`;
let imageElement = document.querySelector('.image');
fetch(url)
.then(function(response){
//console.log(response.json())
return response.json();
})
.then(function(jsonData){
imageElement.src = jsonData.urls.regular;
})
}
//// Array
let selected_images = [];
document.querySelectorAll('.large-image').forEach(function(img, idx) {
img.src = "" + idx;
img.addEventListener('click', function({target: src}){
if(!selected_images.includes(src)) {
selected_images.push(src);
}
console.log(selected_images);
});
});
Below is a basic example on how to save an email and image using sessionStorage similar to the example provided by OP.
NOTE
OP mentioned they have to recreate the example site they provided (indicating some sort of assignment), however this example is not a full solution to that. This is only to answer the specific question asked by OP "how do I store and save an image?".
const _SaveData = () => {
// Get elements
let img = document.querySelector('.image'),
email = document.querySelector('#email').value;
// Validate email address format
if(!/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) {
console.log(`Invalid Email Address!`)
return
}
// Set the new data and retrive any previously stored data
let newData = {
email: email,
img: img.src
},
data = (sessionStorage.getItem("data")) ? JSON.parse(sessionStorage.getItem("data")) : []
// Update data
data = [...data, newData]
// Save data
sessionStorage.setItem("data", JSON.stringify(data))
console.log(`Data Saved!`)
}
As long as you add a field with the id email and set your Save Data! button's onclick value to _SaveData(), this will do the intended purpose. As far as recreating that site goes, there are additional things you will need to do (such as validating duplicate images/emails and generating new images upon save).
I'm learning js.
I want to show the saved li with localStorage created with appendChild when I reload the page.
<ul id="gfg">
<li>Computer Network</li>
<li>Data Structures</li>
</ul>
<button onclick="test()">Submit</button>
function test() {
var node = document.createElement('li');
node.textContent = 'Hi';
abc = document.getElementById('gfg').appendChild(node);
//localStorage
localStorage.setItem('abc', 'abc');
let a = localStorage.getItem('abc');
console.log(abc);
}
We can use a pair of functions to work with your items in the storage:
function getStorageItems() {
var data = localStorage.getItem('items');
return data ? JSON.parse(data) : null;
}
function saveStorageItem(text) {
var array = getStorageItems() || [];
array.push(text);
localStorage.setItem('items', JSON.stringify(array));
}
With this functions you can save and load an array of text (the text of each li). In the storage, we save a text, this functions also convert/parse your array to a JSON text.
We can create another function to add one li item to your page:
function addItem(text, save) {
var node = document.createElement('li');
node.textContent = text;
document.getElementById('gfg').appendChild(node);
if (save !== false)
saveStorageItem(text);
}
By default, we save in the storage the text. Only if we pass save=false, we omit the save action. In this form, we can add and save an item and also only add (without saving).
Your test function, in this form, add and save the item:
function test() {
addItem("Hi");
}
And a last function to load items from storage:
function loadFromStorage() {
var array = getStorageItems();
if (array) {
for (var i = 0; i < array.length; i++)
addItem(array[i], false);
}
}
Here we use false in addItem because only want add the item, not saving again. You can invoke loadFromStorage to load your saved items.
NOTE: here I only save the text because is the only data required to create your HTML. If you need more data, I suggest you use an object and save/load this serialized object in the same way or the HTML.
I'm working on a web application in which a user can drag and drop div elements, whose content is generated from a database, into their preferred order. I want the user to be able to, when they are finished arranging the divs, submit their list (in order) to the server and store the new order in a table. I'm using AJAX to do this, however I'm not sure if that is necessary/the proper way to do this, since I don't need to asynchronously update the page (I just need to submit the data). I've tried a variety of methods to get my array to the server in a usable format (it needs to be iterable and allow for element locations to be compared). I have tried using JSON.stringify/parse, creating a custom object, simply submitting the array on its own, and so on. Here is my code, the most relevant bits are towards the bottom by the makeRouteArray function. Ideally to accomplish this I would like to use just JavaScript (no jQuery). Finally, please excuse my messy code, I'm learning.
// get two groups of elements, those that are draggable and those that are drop targets
let draggable = document.querySelectorAll('[draggable]');
let targets = document.querySelectorAll('[data-drop-target]');
// div immediately surrounding bus routes
var busList = document.getElementById("bus-list");
const button = document.getElementById("button");
// store the id of the draggable element when drag starts
function handleDragStart(e) {
e.dataTransfer.setData("text", this.id); // sets 'text' value to equal the id of this
this.classList.add("drag-start"); // class for styling the element being dragged, sets opacity
}
function handleDragEnd(e) {
e.target.classList.remove('drag-start');
}
function handleDragEnterLeave(e) {
// should provide visual feedback to user?
}
// handles dragover event (moving your source div over the target div element)
// If drop event occurs, the function retrieves the draggable element’s id from the DataTransfer object
function handleOverDrop(e) {
e.preventDefault();
var draggedId = e.dataTransfer.getData("text"); // retrieves drag data (DOMString) for specified type
var draggedEl = document.getElementById(draggedId);
draggedEl.parentNode.insertBefore(draggedEl, this); // inserts element being dragged into list
var draggedArray = Array.from(draggedEl.parentNode.children); // creates new array which updates current location of each route
e.target.classList.remove('drag-start'); // sets opacity back to 1
// if (e.type === "drop") {
// // when dropped, update localstorage
savePage(draggedArray);
// }
}
// get each full bus-route div in #bus-list with p content as single arr item each
// called when item is dropped
function savePage(dArray) {
// honestly i can't remember what this does precisely
// but i can't seem to add to localstorage in the way i want without it
var arr = Array.prototype.map.call(dArray, function(elem) {
return elem.outerHTML;
});
localStorage.newList = JSON.stringify(arr); // have to stringify the array in order to add it to localstorage
}
// ideally it should just update the order of the bus routes to reflect local storage
// and add classes/ids to the divs etc. (hence using outerHTML)
function makePage() {
// getting the item from localstorage
var getData = localStorage.getItem("newList");
// parsing it back into an array
var parsedData = JSON.parse(getData);
// string to hold contents of array so they can be display via innerHTML
var fullList = "";
if (localStorage.getItem("newList") === null) {
return; // maybe this is wrong but if there's nothing in local storage, don't do anything
} else {
for (let i = 0; i < parsedData.length; i++) {
fullList = fullList + parsedData[i];
}
busList.innerHTML = fullList;
// reassigning targets after calling function in order to re-register event handlers
draggable = document.querySelectorAll('[draggable]');
targets = document.querySelectorAll('[data-drop-target]');
}
}
// probably better way to do this
for (let i = 0; i < draggable.length; i++) {
draggable[i].addEventListener("dragstart", handleDragStart);
draggable[i].addEventListener("dragend", handleDragEnd);
}
// drop target elements
for (let i = 0; i < targets.length; i++) {
targets[i].addEventListener("dragover", handleOverDrop);
targets[i].addEventListener("drop", handleOverDrop);
targets[i].addEventListener("dragenter", handleDragEnterLeave);
targets[i].addEventListener("dragleave", handleDragEnterLeave);
}
// rolling average: new_average_score = old_average_score * (total_users-1)/total_users + user_route_rank/total_users
// user id, column per route (score)
// session id
// submit button to save changes to db
// when submit is clicked
// get current results from either local storage or from currently ordered + displayed list
// data will be in array format
// do i need AJAX to be able to submit something other than form data to a server?
// is submitting data in this format (taken from page's HTML ordering) even possible?
// i'd prefer to not use jQuery
// how do i submit an array to the server (express) and then parse (?) it to make it useable?
// so far i have tried JSON.stringify/parse, making a custom object, just submitting array, etc.
// ultimately what i need is a data type that i can loop over and compare positions of stored elements
var makeRouteArray = function() {
var currentOrderArr = Array.from(busList.children);
var idData = currentOrderArr.map(function(el) {
return Number(el.id.slice(2));
});
return idData; // not sure if having two return statements like this is okay
};
button.addEventListener("click", function(e) {
var request = new XMLHttpRequest();
request.open('POST', '/submit', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(data);
});
makePage();
The makeRouteArray function is taking ids from an HTML ul and stripping them of the first two characters because I only want to use the numbers (the ids are structured as #r-num). An array of these numbers is what I would like to submit to the server and if possible, once on the server, return the JSON object to an array.
Thanks!
I'm quite new to using storage settings in HTML/JavaScript. I'm building a hybrid app which is a not taking app on mobile using Phonegap. I want the user to type in a note name, then the note itself, and be able to save both by placing them into a jquery mobile list and putting them back on the home screen. My problem is that I can only save one note at a time. If I try to save another one, it just overwrites the previous one. How would I go about fixing it? Also, when I try refresh the browser the note disappears. Is this normal?
Please and thank you.
Here is the saving function I used:
function storeData() {
var i;
for (i=0; i<999; i++) {
var fname = document.getElementById('fname').value;
var wtf = document.getElementById('wtf').value;
localStorage.setItem('fname', fname);
localStorage.setItem('wtf', wtf);
}
var newEl = "<li><a href='#' id='savedNote'onclick='loadData'></a></li>"
document.getElementById("savedNote").innerHTML = localStorage.getItem("fname");
//try to create a new list element in main menu for this item being stored in
// and add an onclick load function for that
};
function loadData() {
var x;
for (x=0; x<999; x++) {
document.getElementById("fname").innerHTML = localStorage.getItem('fname', fnamei);
document.getElementById("wtf").innerHTML = localStorage.getItem('wtf', wtfi);
}
};
I'm not sure why you're using a loop for your functions. The storeData function looks 999 times for the value of #fname and #wtf, and save this 999x times in localStorage.fname and localStorage.wtf
This makes absolut no sense. Same Problem with your loadData function.
A nice way to save more then one string to the localStorage, is to create a javascript object, stringify it and then save it to the localStorage.
You only need to load the data from the localStorage, if you (re)load the page. But you need to save it to the localStorage, every time something changed, to be sure that the data in the localStorage is always up to date.
For display and manipulation on the page, you use the javascript object. in my example "myData". If you change something, you update your javascript object and then save it to the localStorage.
a side note. to be sure that the user don't overwrite something with a
identical name, you should use unique ids. like i did with the timestamp.
var postID = new Date().getTime();
Here a little example to show you a possible way. It's hard to code something functionally without your html code.
// Creating a object for all Data
var myData = {};
// Fill the Object with data if there is something at the LocalStorage
if (localStorage.myData){
loadDataFromLocalStorage();
}
function createNewPost(){
// Create a ID for the Post
var postID = new Date().getTime();
// Create a Object inside the main object, for the new Post
myData[postID] = {};
// Fill the Object with the data
myData[postID].fname = document.getElementById('fname').value;
myData[postID].wtf = document.getElementById('wtf').value;
// Save it to the LocalStorage
saveDataToLocalStorage();
// Display the Listitem. with the right postID
}
function loadPost (postID){
var singlePost = myData[postID];
// Display it
}
// A Helper Function that turns the myData Object into a String and save it to the Localstorage
function saveDataToLocalStorage(){
localStorage.myData = JSON.stringify(myData);
}
// A Helper Function that turns the string from the LocalStorage into a javascript object
function loadDataFromLocalStorage(){
myData = JSON.parse(localStorage.myData);
}
// Creating a object for all Data
var myData = {};
// Fill the Object with data if there is something at the LocalStorage
if (localStorage.myData){
loadDataFromLocalStorage();
}
function createNewPost(){
// Create a ID for the Post
var postID = new Date().getTime();
// Create a Object inside the main object, for the new Post
myData[postID] = {};
// Fill the Object with the data
myData[postID].fname = document.getElementById('fname').value;
myData[postID].wtf = document.getElementById('wtf').value;
// Save it to the LocalStorage
saveDataToLocalStorage();
// Display the Listitem. with the right postID
}
function loadPost (postID){
var singlePost = myData[postID];
// Display it
}
// A Helper Function that turns the myData Object into a String and save it to the Localstorage
function saveDataToLocalStorage(){
localStorage.myData = JSON.stringify(myData);
}
// A Helper Function that turns the string from the LocalStorage into a javascript object
function loadDataFromLocalStorage(){
myData = JSON.parse(localStorage.myData);
}
Store an array.
var arrayX = [];
arrayX.push(valueY);
localStorage.setItem('localSaveArray', arrayX);