I am trying to create a simple clipboard extension. I have 6 textarea objects that are used as copy/paste platforms. I want these objects to 'remember the text' for future uses (even after the extension is closed).
I this is how the textarea object was built like:
<table>
<tr>
<td>
<textarea id="container_1" class="container" rows="4" cols="50" value="" focusout="SetTextBoxString(1)"></textarea>
</td>
<td>
<textarea id="container_2" class="container" rows="4" cols="50" value="" focusout="SetTextBoxString(2)"></textarea>
</td>
</tr>
(...)
notice that the id is container + the number of the object (goes on until 6)
in the JavaScript side, I use the onload event to loop through all of these objects and get from the data from the global storage and put it in the textareas. For the input, I use the SetTextBoxString() object to "send" whats in that field to the global storage. here is the js:
var texts = [];
Load_func()
{
for (var i = 1; i <= 6; i++) {
chrome.storage.sync.get(["Txt_" + index], function (items) {
var obj = JSON.parse(items);
var txt = "Txt_" + i
texts.push(obj.txt)
document.getElementById("container_" + i).innerHTML = texts[i]
});
if (!texts[i])
{
document.getElementById("container_" + i).value = "add"
}
}
}
SetTextBoxString(index)
{
var sorcestring = "Txt_" + index;
chrome.storage.sync.set({ sorcestring : document.getElementById("container_" + index).innerHTML }, function () {
});
}
It's working fine, but when I refresh the page the text disappears. What have I done wrong?
I know it's a long question, I have done everything I can to make it shorter, no luck. I really appreciate if you will help me. thank you in advance!
sources:
How can I save information locally in my chrome extension?
You can move to using JQuery if you want, but some people believe its rather useless, I created this code in JQuery a while back for a similar project to yours, but more of a "notebook"
I cant seem to get this code to "successfully" work 100% if I use normal javascript, so unfortunately unless you want to hook big chunky ol' JQuery to your project, this answer isnt very useful.
Anyways, this code will auto adapt to how many "Inputs" you have, it saves their data and then binds it to a local storage. Im new to Extensions too, but if i had to guess why your current code isnt working, its possible your extension is trying to save the data so some unknown URL, as local storage is mostly based on websites alone, and cant be accessed by other websites (Security reasons obviously).
You can adjust this with your current code to allow it to autosave based on the change of the textarea, like you already have, but for now, its saved by the activation of a button, as seen below.
<button id="saveBtn">Save Text</button>
$(document).ready(function () {
var savesbtn = document.getElementById("saveBtn");
//FILL TEXT AREAS WITH NOTES
for (var i = 1; i < 11; i++) {
$("#container_" + i).val(localStorage.getItem("textCopy" + i)); /* Most of this simply adds a
1/2/3/4 etc if your ID is so, and saves it under that number, henceforth auto-adjusting per textarea,
henceforth only requiring 1 save, instead of many. */
}
function saveNotes() { // Saves the current value of the inputs.
// Save data to localstorage
for (var i = 1; i < 11; i++) {
localStorage.setItem("textCopy" + i, $("#container_" + i).val());
}
};
savesbtn.addEventListener("click", saveNotes);
});
If this still fails to load from local storage, your best bet is to try an alternate form of storage, be it, SQL or some other form.
Also heres a good example of how I used this (sorry if it doesnt turn out well, I havent set the dimensions correctly for every screen type, and so far it really only looks good on my screen.): https://codepen.io/SkylerSpark/pen/KjodVe
Related
I understand that this question has been asked many a times and the general consensus is that spam-bots will always figure out a way to harvest emails eventually so it is a lost cause. But I want a newly created email visible on a page that I created and I want at least something that protects it from spam-bots. Here is a simple JavaScript technique I wish to use:
$(document).ready(function() {
setEmailAddress("abc#xyz.com");
});
function setEmailAddress(emailValue) {
$("#spanTest").append($("<a>").attr("href", "javascript:location='mailto:" + obfuscateString(emailValue) + "';void 0").text(obfuscateString(emailValue)));
}
function obfuscateString(plaintext) {
var obfuscated = "";
for (var i = 0; i < plaintext.length; i++) {
obfuscated += "\\u00" + plaintext.charCodeAt(i).toString(16);
}
return obfuscated;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="spanTest"></span>
Here are the questions:
If the email abc#xyz.com is picked up from a database and passed to the method setEmailAddress then since the html crawled by the bot in the first place will not find an email, do I still need to obfuscate it on the page?
You will notice that the link text of anchor is not obfuscated. If I need to obfuscate that part too, is it possible to achieve that without using eval?
Note: I already have a Contact form on the page that uses reCaptcha but this query is for when I wish to have an email visible on the page as well.
EDIT:
After reading the comments, I think I need to emphasize on the question no. 2 above. Please see above updated code.
As you can see, I am trying to hide/obfuscate the link text as well. I understand that I need to document.write the produced result by the method obfuscateString but using eval for that is not recommended. Is there a way to obfuscate this part of text too?
So I ended up using the following:
$(document).ready(function() {
setEmailAddress("abc#xyz.com");
});
function setEmailAddress(emailValue) {
$("#spanTest").append($("<a>").attr("href", "javascript:location='mailto:" + obfuscateString(emailValue) + "';void 0").html("<img src='https://i.stack.imgur.com/CFrNW.png' />"));
}
function obfuscateString(plaintext) {
var obfuscated = "";
for (var i = 0; i < plaintext.length; i++) {
obfuscated += "\\u00" + plaintext.charCodeAt(i).toString(16);
}
return obfuscated;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="spanTest"></span>
That is, I changed the part in the code for the link text.
From this:
.text(obfuscateString(emailValue))
to
this:
.html("<img src='https://i.stack.imgur.com/CFrNW.png' />")
It will render an image (of the email) in place of text. Your suggestions are still welcome.
I've made an event in Google Tag Manager, which triggers when a specific page is loaded.
The Event label is the value of my user defined variable SearchCounter with type: Custom JavaScript.
In 'SearchCounter' I have the following JS:
function(){
var counter;
if(localStorage.getItem("count_search") === null || localStorage.getItem("count_search") === 'undefined'){
localStorage.setItem("count_search", "1");
return localStorage.getItem("count_search");
}
else{
counter = parseInt(localStorage.getItem("count_search"));
counter = counter + 1;
localStorage.setItem("count_search", counter);
return localStorage.getItem("count_search");
}
return localStorage.getItem("count_search");
}
When I don't have the item in my local storage already, it still give's me 7 instead of 1. Then I'll press F5: count_search = 17, And again f5: 27. A CTRL-F5 gives me 37.
It should be 1, 2, 3, 4, 5 etcetera.
I hope someone can help me to implement a counter-alike function in Google Tag Manager, so I can send the amount of searches to GA, when a goal has been achieved. So, When someone clicks a specific button a would like to get the value of count_search, to send it to GA within an event.
Thanks very much.
First of all this metric is given by google analytics by default so i don't see why ur trying to store it somewhere else. If you dont want the avg that google uses you can just store a custom dimension at 'Session' level with the sessionID and those in a custom report open Sessions by pageviews. Here is info about it.
On the other hand, if you insist doing it your way i think even if this works it isn't the best approach you would get a much better result storing the counter in a custom dimension at 'Session' level. (It ll overwrite the value each time for a given session and you ll end up with the last one send)
Hope it helps.
What you need to do is changing the name of the parameter saved in the localStorage. I don't know why, but count_search does not work. I tested your setup and encountered the same weird effect where the count_search item is summing up to astronomical numbers. Using a different name like thisIsMyPageViewCounter works just fine though! Probably count_search is accessed by another object in the document or window and you managed to get a value out of it by chance.
If you want to add the page view count to an event, I do not see any other way than creating both a Custom HTML Tag to set the counter and a Custom JS Variable to return the count.
This is the Custom HTML Script to be added to each page view:
<script>
(function() {
if(localStorage.getItem("thisIsMyPageViewCounter") === null || localStorage.getItem("thisIsMyPageViewCounter") === 'undefined') {
localStorage.setItem("thisIsMyPageViewCounter", 1);
} else {
var counter = 0;
counter = parseInt(localStorage.getItem("thisIsMyPageViewCounter"));
counter = counter + 1;
localStorage.setItem("thisIsMyPageViewCounter", counter);
}
})();
</script>
This is the Custom JS Variable to be added as a value to the event:
function() {
pageviewCounter = parseInt(localStorage.getItem("thisIsMyPageViewCounter"));
return pageviewCounter;
}
I hope this helps!
Not on Chrome, but on Firefox the browser just get freeze every time I make an ajax request.
Here's the deal...
The ajax request receive a huge html, where the length is more than 75,000.
<div> ... <table> ... etc ... </table> ... </div>
So I start to use replace to get something better:
var html = data.replace(/\r?\n|\r/g, '').replace(/\s{2,}/g, ' ')
Than I got 55,000 that is not enough.
So I've been searching but until now I got nothing that can help.
Here's what I tried:
1.
asyncInnerHTML(html, function(fragment){
$(tab).get(0).appendChild(fragment); // myTarget should be an element node.
});
2.
var node = document.createTextNode(html);
$(tab).get(0).innerHTML = node;
3.
$(tab).get(0).innerHTML = html;
4.
$(tab).append(html);
5.
$(tab).html(html);
The only thing that was fast what the second one, where the javascript add the nodeContent, of course that was not what I want, because I need the HTML rendered and not the html in text/string form.
I hope that someone could help me.
Anyway, thanks.
Here's a piece of code that parses out the rows from your table HTML and then adds them one at a time to give the browser more time to breathe while parsing your HTML. This parsing logic is specific to your HTML and makes some assumptions about that HTML:
function addLargeHTML(parent, h) {
var d = document.createElement("div");
var pieces = extractRows(html);
d.innerHTML = pieces.core;
var tbody = $(d).find("tbody");
$(parent).append(d);
var cntr = 0;
function next() {
if (cntr < pieces.rows.length) {
tbody.append(pieces.rows[cntr]);
++cntr;
setTimeout(next, 1);
}
}
next();
}
function extractRows(h) {
var body;
var h = h.replace(/<tbody>(.*?)<\/tbody>/, function(match, p1) {
body = p1;
return "<tbody></tbody>";
});
var rows = body.match(/<tr.*?<\/tr>/g);
return {core: h, rows: rows};
}
You can see it working in this jsFiddle (select the "Add Row by Row" button): http://jsfiddle.net/jfriend00/z7jn4p12/.
Since I could not reproduce your original problem in Firefox, I can't really say whether this would fix what you saw or not. But, it does break the HTML up into smaller pieces so if that was really the problem, this should help.
The Skype Toolbar for Firefox is an extension that detects phone numbers in web pages, and re-renders them as a clickable button that can be used to dial the number using the Skype desktop application.
So, when the HTML is rendered, the skype extension try to find shit at my code making the browser stop work for a moment.
Thanks for all help.
I am trying to update my Pathfinder Character generator to have the ability to save a character by using HTML5's web storage. I have a JavaScript file used to generate the character.
However, I'm running into a few problems. How can I make it so that only things that have been updated changed when clicking my "Update Character" button? Secondly, what would the best way to go about showing the results?
This is my current code:
function SaveCharacter() {
makeCharacter();
if (typeof(Storage) !== "undefined") {
if (localStorage.used) {
alert("used was true.");
localStorage.name = name;
}
else {
localStorage.used = true;
localStorage.name = name;
localStorage.skill_points = num_skill_points;
localStorage.spells = num_spells;
localStorage.feats = num_feats;
localStorage.hitdie = hit_die;
localStorage.wealth = wealth;
localStorage.Class = Class;
// localStorage.Scores = new Array();
// for (var i = 0; i < n; i++) {
// localStorage.Scores[i] = ability_scores[i];
// }
}
document.getElementById("result").innerHTML="Character Name: " + localStorage.name;
}
else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support web storage...";
}
}
function DeleteCharacter() {
localStorage.clear();
}
When working with this, it changes the name regardless of whether I've deleted the character or not. Also, document.getElementById("result").innerHTML="Character Name: " + localStorage.name; doesn't allow me to update several fields at once. What would be a better way to do this?
[edit] - Here is a link to the generator.
First some thoughts about what you've done:
I advice you to use the Modernizr library instead of typeof(Storage) !== "undefined" to know if localStorage is supported. It will be much more robust.
Instead of dealing with a bunch of variables, you should create something like a Character object, which will be saved into localStorage using JSON.stringify() and retrieved by using JSON.parse(). It will also make your code much more readable.
Don't use variable names like 'Class', it is too much error prone. Use something like 'category' or 'type' instead.
When I look at your page, I have this error: 'form is not defined'. So your makeCharacter() function doesn't work.
Regarding your question about showing the result, you could generate much more information within the 'result' div. You are not limited to one text.
I think a better option would be to set up the 'result' element so that you can show the data easily. For example:
<table id="result">
<tr>
<td>Name :</td>
<td id="name"></td>
</tr>
... Other characteristics
</table>
This way you can do something easy like document.getElementById('name') = character.name
Of course, this table would be hidden before the character is generated (using the 'display' css property)
No idea what I'm doing or why it isn't working. Clearly not using the right method and probably won't use the right language to explain the problem..
Photogallery... Trying to have a single html page... it has links to images... buttons on the page 'aim to' modify the path to the images by finding the name currently in the path and replacing it with the name of the gallery corresponding to the button the user clicked on...
example:
GALLERY2go : function(e) {
if(GalleryID!="landscapes")
{
var find = ''+ findGalleryID()+'';
var repl = "landscapes";
var page = document.body.innerHTML;
while (page.indexOf(find) >= 0) {
var i = page.indexOf(find);
var j = find.length;
page = page.substr(0,i) + repl + page.substr(i+j);
document.body.innerHTML = page;
var GalleryID = "landscapes";
}
}
},
There's a function higher up the page to get var find to take the value of var GalleryID:
var GalleryID = "portfolio";
function findGalleryID() {
return GalleryID
}
Clearly the first varGalleryID is global (t'was there to set a default value should I have been able to find a way of referring to it onLoad) and the one inside the function is cleared at the end of the function (I've read that much). But I don't know what any of this means.
The code, given its frailties or otherwise ridiculousness, actually does change all of the image links (and absolutely everything else called "portfolio") in the html page - hence "portfolio" becomes "landscapes"... the path to the images changes and they all update... As a JavaScript beginner I was pretty chuffed to see it worked. But you can't click on another gallery button because it's stuck in a loop of some sort. In fact, after you click the button you can't click on anything else and all of the rest of the JavaScript functionality is buggered. Perhaps I've introduced some kind of loop it never exits. If you click on portfolio when you're in portfolio you crash the browser! Anyway I'm well aware that 'my cobbled together solution' is not how it would be done by someone with any experience in writing code. They'd probably use something else with a different name that takes another lifetime to learn. I don't think I can use getElement by and refer to the class/id name and parse the filename [using lots of words I don't at all understand] because of the implications on the other parts of the script. I've tried using a div wrapper and code to launch a child html doc and that come in without disposing of the existing content or talking to the stylesheet. I'm bloody lost and don't even know where to start looking next.
The point is... And here's a plea... If any of you do reply, I fear you will reply without the making the assumption that you're talking to someone who really hasn't got a clue what AJAX and JQuery and PHP are... I have searched forums; I don't understand them. Please bear that in mind.
I'll take a stab at updating your function a bit. I recognize that a critique of the code as it stands probably won't help you solve your problem.
var currentGallery = 'landscape';
function ChangeGallery(name) {
var imgs = document.getElementsByTagName("img") // get all the img tags on the page
for (var i = 0; i < imgs.length; i++) { // loop through them
if (imgs[i].src.indexOf(currentGallery) >= 0) { // if this img tag's src contains the current gallery
imgs[i].src = imgs[i].src.replace(currentGallery, name);
}
}
currentGallery = name;
}
As to why I've done what I've done - you're correct in that the scope of the variables - whether the whole page, or only the given function, knows about it, is mixed in your given code. However, another potential problem is that if you replace everything in the html that says 'landscape' with 'portfolio', it could potentially change non-images. This code only finds images, and then replaces the src only if it contains the given keyword.