chrome.storage.sync.get Error - javascript

I've been trying to use chrome.storage.sync.get for the options part of my program but I've hit a snag.
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("save").addEventListener("click", save_options);
});
function save_options() {
var priceNotif = document.getElementById('pricealert').value;
chrome.storage.sync.set({
priceAlert: priceNotif
}, function() {
// Update status to let user know options were saved.
console.log("price set: " + priceNotif);
setTimeout(function() {
status.textContent = '';
}, 750);
});
}
var test = chrome.storage.sync.get('priceAlert', function(data) {
test = data.priceAlert;
});
console.log("test price get: " + test);
The test variable is returning undefined, and how do I fix that?

if you are creating chrome extension then you can use Please confirm that you need to add needfull permission in manifest.JSON file. please refer below document.
https://developer.chrome.com/extensions/storage

Related

Office.js outlook add-in issue

I'm trying to get the Body in Outlook and then update/set it with categories. My issue is this - when I debug it - it works fine. But when I don't debug from function to function - it gets all the way to the last function and just stops - updateBody(). What's really strang is if I remove the breakpoints on each function and just set a breakpoint on last function - never gets hit, but console will write out "Starting update body". All the console.logs are writing out data as expected. Not sure what is going on. Appreciate any help! Thanks.
"use strict";
var item;
var response;
var tags;
var updatedBody;
Office.initialize = function () {
$(document).ready(function () {
// The document is ready
item = Office.context.mailbox.item;
debugger;
getBodyType();
});
}
function getBodyType() {
item.body.getTypeAsync(
function (resultBody) {
if (resultBody.status == Office.AsyncResultStatus.Failed) {
write(resultBody.error.message);
} else {
response = resultBody;
console.log('Successfully got BodyType');
console.log(response.value);
getCategories();
}
});
}
function getCategories() {
tags = "";
// Successfully got the type of item body.
// Set data of the appropriate type in body.
item.categories.getAsync(function (asyncResult) {
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
console.log("Action failed with error: " + asyncResult.error.message);
} else {
var categories = asyncResult.value;
console.log("Categories:");
categories.forEach(function (item) {
var tag = item.displayName;
tags += '#' + tag.replace(/\s/g, "") + ' ';
});
console.log('Successfully got tags');
console.log(tags);
getBody();
}
});
}
function getBody() {
var body = "";
updatedBody = "";
console.log("Starting get body");
if (response.value == Office.MailboxEnums.BodyType.Html) {
item.body.getAsync(
Office.CoercionType.Html,
{ asyncContext: "This is passed to the callback" },
function (result) {
//Replace all the # tags and update again.
body = result.value.replaceAll(/#(\w)+/g, "").trimEnd();
var domParser = new DOMParser();
var parsedHtml = domParser.parseFromString(body, "text/html");
$("body", parsedHtml).append("<div>" + tags + "</div>");
var changedString = (new XMLSerializer()).serializeToString(parsedHtml);
if (changedString != "") {
updatedBody = changedString;
}
console.log(updatedBody);
updateBody();
});
}
}
function updateBody() {
console.log("Starting update body");
item.body.setAsync(
updatedBody,
{ coercionType: Office.CoercionType.Html },
function (result2) {
console.log("Body updated");
});
}
Image - With breakpoints on each function - works as expected
Image - Without breakpoints - gets to updateBody() function.
But the string updatedBody isn't logged. It somehow skips over that
even though it's called before updateBody() on getBody()
Image - Same code run via Script Lab - works just fine as well.

simple way to run background.js file when a button on popup.html is clicked

I have been trying to run a function in my background.js file when I click a button on my popup.html file, I have tried a bunch of examples online and so far none of them have worked for me.
Here is what Ive tried:
$(".start-btn").click(function() {
var task = loadTaskFromStorage($("#select-task").val());
var checkbox = $('input[type="checkbox"]');
var autobuy = $(checkbox).prop('checked');
var delay = $("#checkout-ms").val();
var count = localStorage.getItem('count');
chrome.storage.sync.set({'task': task.cells, 'count': count}, function() {
});
chrome.storage.sync.set({'autobuy': autobuy, 'delay': delay}, function() {
});
chrome.runtime.sendMessage({'run': true);
then in the background.js file tried to do this:
chrome.runtime.onMessage.addListener(function(message, sender) {
if(!message.run) return;
finder();
});
function finder() {
//pulling json info and opening url loop
});
I want to chrome.storage.sync.get all my things that I saved in my popup.js file then run the function.. I have tried a bunch of solutions and so far none of them have worked for me...
Thank you for helping me in advance <3!
popup.js:
Accumulate the data then send it over to the background:
$(".start-btn").click(function() {
var task = loadTaskFromStorage($("#select-task").val());
var checkbox = $('input[type="checkbox"]');
var autobuy = $(checkbox).prop('checked');
var delay = $("#checkout-ms").val();
var count = localStorage.getItem('count');
chrome.runtime.sendMessage({ run: true, data: {
task: task.cells,
count,
autobuy,
delay
} });
}
background.js:
Retrieve the data sent over from the popup, store it and use it:
chrome.runtime.onMessage.addListener(function(message, sender) {
if(!message.run) return;
var data = message.data;
chrome.storage.sync.set(data, function() { /* ... */ });
console.log(data);
});

jspdf & CKEditor - .createObjectURL is not a function

While trying to use jsPDF I'm getting the error
Error in function saveAs: n(...).createObjectURL is not a function
My code is simple:
HTML
<button class="generatePdf"> click me </button>
JS
//Generate PDF
$(document).on('click', '.generatePdf', function() {
var doc = new jsPDF();
doc.text(20,20,'Some dummy text');
doc.save('print.pdf')
});
I used it in Laravel with Bower and Elixir (gulp) but I get the same error:
Error in function FileSaver#http://mrrio.github.io/jsPDF/dist/jspdf.debug.js:5875:18: get_URL(...).createObjectURL is not a function
if using
<script src="http://mrrio.github.io/jsPDF/dist/jspdf.debug.js"></script>
I am accepting alternatives to jsPdf if you got any.
It happens in both Firefox 44.0.2 and Chromium 48.0.2564.116
After reading this issue I inserted the given code
<script>(function () {
var _createObjectURL = window.URL.createObjectURL;
Object.defineProperty(window.URL, 'createObjectURL', {
set: function (value) {
console.trace('set createObjectURL')
_createObjectURL = value;
},
get: function () {
console.trace('get createObjectURL')
return _createObjectURL;
}
})
})();
(function () {
var _URL = window.URL;
Object.defineProperty(window, 'URL', {
set: function (value) {
console.trace('set URL')
_URL = value;
},
get: function () {
console.trace('get URL')
return _URL;
}
})
})(); </script>
and found out the problem was in eqneditor plugin of CKEditor. I removed the plugin and everything was working fine.
I was able to fix it with unsetting the global URL:
let oldURL = undefined;
if (URL) {
oldURL = URL;
URL = undefined;
}
// file saving code
if (oldURL) {
URL = oldURL;
}

How to for loop in casperjs

I am trying to click a 'next' button N number of times and grab the page source each time. I understand that I can run an arbitrary function on the remote website, so instead of click() I just use the remote function nextPage() How do I run the following, an arbitrary number of times:
var casper = require('casper').create();
casper.start('http://www.example.com', function() {
this.echo(this.getHTML());
this.echo('-------------------------');
var numTimes = 4, count = 2;
casper.repeat(numTimes, function() {
this.thenEvaluate(function() {
nextPage(++count);
});
this.then(function() {
this.echo(this.getHTML());
this.echo('-------------------------');
});
});
});
'i' here is an index I tried to use in a javascript for loop.
So tl;dr: I want lick 'next', print pages source, click 'next', print page source, click 'next'... continue that N number of times.
First, you can pass a value to the remote page context (i.e. to thenEvaluate function like this:
this.thenEvaluate(function(remoteCount) {
nextPage(remoteCount);
}, ++count);
However, Casper#repeat might not be a good function to use here as the loop would NOT wait for each page load and then capture the content.
You may rather devise a event based chaining.
The work-flow of the code would be:
Have a global variable (or at-least a variable accessible to the functions mentioned below) to store the count and the limit.
listen to the load.finished event and grab the HTML here and then call the next page.
A simplified code can be:
var casper = require('casper').create();
var limit = 5, count = 1;
casper.on('load.finished', function (status) {
if (status !== 'success') {
this.echo ("Failed to load page.");
}
else {
this.echo(this.getHTML());
this.echo('-------------------------');
}
if(++count > limit) {
this.echo ("Finished!");
}
else {
this.evaluate(function(remoteCount) {
nextPage(remoteCount);
// [Edit the line below was added later]
console.log(remoteCount);
return remoteCount;
}, count);
}
});
casper.start('http://www.example.com').run();
NOTE: If you pages with high load of JS processes etc. you may also want to add a wait before calling the nextPage :
this.wait(
1000, // in ms
function () {
this.evaluate(function(remoteCount) {
nextPage(remoteCount);
}, count);
}
);
[EDIT ADDED] The following event listeners will help you debug.
// help is tracing page's console.log
casper.on('remote.message', function(msg) {
console.log('[Remote Page] ' + msg);
});
// Print out all the error messages from the web page
casper.on("page.error", function(msg, trace) {
casper.echo("[Remote Page Error] " + msg, "ERROR");
casper.echo("[Remote Error trace] " + JSON.stringify(trace, undefined, 4));
});
You could try using Casper#repeat
This should do, for the most part, what you want:
var numTimes = 10, count = 1;
casper.repeat(numTimes, function() {
this.thenEvaluate(function(count) {
nextPage(count);
}, ++count);
this.then(function() {
this.echo(this.getHTML());
this.echo('-------------------------');
});
});
var global_page_links = [];
casper.then(function(){
for(var i=1; i<=5; i++){
// you just add all your links to array, and use it in casper.each()
global_page_links.push(YOUR_LINK);
}
this.each(global_page_links, function(self, link) {
if (link){
self.thenOpen(link, function() {
console.log("OPENED: "+this.getCurrentUrl());
// do here what you need, evaluate() etc.
});
}
});
});
This is answer to question, how to use for() in casperjs to launch several links

Jquery confirmation box

I'm looking to create a generic confirmation box that can be used by multiple widgets easily, but I'm running into problems with scope and was hoping for a clearer way of doing what I'm trying to do.
Currently I have the following -
(function() {
var global = this;
global.confirmationBox = function() {
config = {
container: '<div>',
message:''
}
return {
config: config,
render: function(caller) {
var jqContainer = $(config.container);
jqContainer.append(config.message);
jqContainer.dialog({
buttons: {
'Confirm': caller.confirm_action,
Cancel: caller.cancel_action
}
});
}
}
} //end confirmationBox
global.testWidget = function() {
return {
create_message: function(msg) {
var msg = confirmationBox();
msg.message = msg;
msg.render(this);
},
confirm_action: function() {
//Do approved actions here and close the confirmation box
//Currently not sure how to get the confirmation box at
//this point
},
cancel_action: function() {
//Close the confirmation box and register that action was
//cancelled with the widget. Like above, not sure how to get
//the confirmation box back to close it
}
}
}//end testWidget
})();
//Create the widget and pop up a test message
var widget = testWidget();
widget.create_message('You need to confirm this action to continue');
Currently I'm just looking to do something as simple as close the box from the within the widget, but I think I've wrapped my own brain in circles in terms of what knows what.
Anyone want to help clear my befuddled brain?
Cheers,
Sam
The resulting code:
I thought it might be useful for people who find this thread in later days looking for a solution to a similar problem to see the code that resulted from the helpful answers I got here.
As it turns out it was pretty simple in the end (as most of the frustrating mind-tangles are).
/**
* Confirmation boxes are used to confirm a request by a user such as
* wanting to delete an item
*/
global.confirmationBox = function() {
self = this;
config = {
container: '<div>',
message: '',
}
return {
set_config:config,
render_message: function(caller) {
var jqContainer = $(config.container);
jqContainer.attr('id', 'confirmation-dialog');
jqContainer.append(config.message);
jqContainer.dialog({
buttons: {
'Confirm': function() {
caller.confirm_action(this);
},
Cancel: function() {
caller.cancel_action(this);
}
}
});
}
}
} // end confirmationBox
global.testWidget = function() {
return {
create_message: function(msg) {
var msg = confirmationBox();
msg.message = msg;
msg.render(this);
},
confirm_action: function(box) {
alert('Success');
$(box).dialog('close');
},
cancel_action: function(box) {
alert('Cancelled');
$(box).dialog('close');
}
}
}//end testWidget
You could pass jqContainer to the confirm/cancel functions.
Alternately, assign jqContainer as a property of caller. Since the confirm/cancel functions are called as methods of caller, they will have access to it via this. But that limits you to tracking one dialog per widget.
Try something like this:
(function() {
var global = this;
/*****************This is new****************/
var jqContainer;
global.confirmationBox = function() {
config = {
container: '<div>',
message:''
}
return {
config: config,
render: function(caller) {
// store the container in the outer objects scope instead!!!!
jqContainer = $(config.container);
jqContainer.append(config.message);
jqContainer.dialog({
buttons: {
'Confirm': caller.confirm_action,
Cancel: caller.cancel_action
}
});
}
}
} //end confirmationBox
global.testWidget = function() {
return {
create_message: function(msg) {
var msg = confirmationBox();
msg.message = msg;
msg.render(this);
},
confirm_action: function() {
//Do approved actions here and close the confirmation box
//Currently not sure how to get the confirmation box at this point
/*******Hopefully, you would have access to jqContainer here now *****/
},
cancel_action: function() {
//Close the confirmation box and register that action was
//cancelled with the widget. Like above, not sure how to get
//the confirmation box back to close it
}
}
}//end testWidget
})();
//Create the widget and pop up a test message
var widget = testWidget();
widget.create_message('You need to confirm this action to continue');
If that doesn't work, try defining your callbacks (confirm_action, cancel_action) as private members of your object. But they should be able to access the outer scope of your main object.

Categories