So I'm trying to make a chrome extension to store stuff like "Name " and to list them as buttons so I can share current page to anyone from the list. Right now, I'm trying to write/read from chrome.storage (cloud) but my JS isn't really doing anything! The code seems fine, it just doesn't do anything!
window.load = myJs;
function myJs() {
document.addEventListener('DOMContentLoaded', function () {
var link = document.getElementById('get');
link.addEventListener('click', function () {
function getValues() {
chrome.storage.local.get('Name', function (result) {
Name = result;
alert(result);
});
}
});
});
document.addEventListener('DOMContentLoaded', function () {
var link = document.getElementById('savechanges');
link.addEventListener('click', function () {
function saveChanges() {
var newname = getElementById("newname");
var newemail = getElementById("newmail");
if (!newname) {
message('Error: No name specified');
return;
}
if (!newemail) {
message('Error: No E-mail specified');
return;
}
chrome.storage.sync.set({
'Name': newname
}, {
'Email': newemail
}, function () {
message('New contact added');
window.location.href = "popup.html";
});
}
});
});
}
So my extension has 2 pages, one for adding new people with 2 inputs, and one for grabing the values (at least for now, I plan on listing them as button as soon as I find out how)
Here is the html from both
page.html
<body>
<input type="text" id="newname" placeholder="Enter new contact name">
<input type="text" id="newemail" placeholder="Enter new contact email">
<button name="Add" id="savechanges" class="m-btn">Add new contact</button>
<script src="popup.js"></script>
</body>
popup.html
<body>
<button type="button" id="get" class="m-btn">Get</button>
<script src="popup.js"></script>
<input type="submit" name="add" value="Add" class="m-btn">
</body>
For one, your event listeners are declaring two local functions, getValues and saveChanges, that are never called. You can just remove these outer function declarations and let the body of these two functions be the body of the event handlers, like so:
document.addEventListener('DOMContentLoaded', function () {
var link = document.getElementById('get');
link.addEventListener('click', function () {
chrome.storage.local.get('Name', function (result) {
// Check chrome.runtime.lastError to see if there was an error
Name = result;
alert(result);
});
});
});
You should be able to inspect your popup / background pages to debug your scripts in the Sources tab in Chrome's developer tools. I would set some breakpoints in these event handlers and ensure they are getting hit properly.
For two, StorageArea.set(object items, function callback) is the signature of the set method. To set two values, you want to pass a single object instead of two different objects:
chrome.storage.sync.set({
'Name': newname,
'Email': newemail
}, function() {
// Check chrome.runtime.lastError to see if there was an error
...
});
Lastly, there's no real reason to use window.onload (I think you meant to use window.onload here, right?) or two different DOMContentLoaded listeners; why not consolidate them into one (not forgetting to check for getElementById returning null, since it seems like you're sharing this script between the two pages)?
Edit: also, you appear to be mixing sync/local storage for your set/get respectively.
Related
I am creating a DApp using meteor in which a templateVar displays an account address.
Using a web3 function in JavaScript I defined the updateInterface() method as seen below as updateInterface()
However, since the method is a loop I can't seem to trigger the event inside Template.foo.events. The method works as I am able to alert(res) alert the result onto the screen.
Could somebody point me in the right direction? cheers
EDIT: added the template.oncreated function and also the function updateInterface() is placed outside the oncreated, helper and events methods.
Template.foo.onCreated(function fooOnCreated() {
this.account= new ReactiveVar(0);
});
Template.foo.helpers({
account() {
var template = Template.instance();
myContract = web3.eth.contract(ABIArray).at(contractAddress);
var result = web3.eth.getCoinbase(function(err, res) {
TemplateVar.set(template, "person", res);
});
},
});
Template.foo.events({
// not sure what to place here
});
var account = web3.eth.accounts[0];
var accountInterval = setInterval(function() {
if (web3.eth.accounts[0] !== account) {
account = web3.eth.accounts[0];
updateInterface();
}
}, 100);
function updateInterface() {
var template = Template.instance();
var result = web3.eth.getCoinbase(function(err, res) {
alert(res);
TemplateVar.set(template, "account", res);
});
}
The problem with events is that it requires an event, whereas the metamask detection function detects a change in account every 100 milliseconds, I am not sure where to place the updateInterface() method.
TemplateVar points here.
<head>
<body>
<div id="section">
{{>foo}}
</div>
</body>
</head>
<template name="foo">
<div id="location">
<p>Currently logged in as: {{account}} {{TemplateVar.get
"account"}} </p>
</div>
</template>
I think you should put the interval loop inside of the onCreated and instead of checking account !== web3.eth.accounts[0] you should check self.account.get() = web3.eth.accounts[0]
like this
Template.foo.onCreated(function fooOnCreated() {
this.account= new ReactiveVar(0);
this.account.set(web3.eth.accounts[0]);
var self = this;
var accountInterval = setInterval(function() {
if (web3.eth.accounts[0] !== self.account.get()) {
self.account.set(web3.eth.accounts[0]);
}
}, 500);
});
and because it is a ReactiveVar you don't have to call the update function. The template should update automatically as the value is used in it.
I have not tested it but I think it should work like this
I have created a Single Page App, and this is my first one so maybe I'm on the wrong path.
I am using master-page in which I'm loading two other pages. Also, I'm using javascript modules so that I can use private variables and functions.
In the master-page, or Mail.html, I start the signalr connection, and I initialize the modules.
In the inbox sub-page I'm waiting "mail" from the server, and in the outbox I'm displaying all sent messages. In order to accomplish this I'm using two different modules (Inbox and Outbox).
My issue occurs when I load the second page (in this example Outbox) after inbox.html is loaded, in this scenario
signalr still works which is strange because that connection is used just in the Inbox page, in that module.
I've tried many things to prevent this, like unloading the current page before loading the next one, and I've also tried removing the scripts, starting a connection just in the inbox page, but nothing helps.
Also, I can't find where exactly is this function stored in the DOM when Outbox.html is loaded.
Here is my code:
Mail.html
<html>
<head>
//scripts
//css
</head>
<body>
<div class="page" id="Inbox">Inbox</div>
<div class="page" id="Outbox">Outbox</div>
<div id="loadPage">
</div>
<script type="text/javascript">
var SignalRHub = $.connection.hubs;
$.connection.hub.start();
var MailModule = {};
$('body').off('click', '.page').on('click', '.page', function () {
MailModule = {};
if ($(this).attr('id') == 'Inbox') {
$("#loadPage").empty().load("/Home/Inbox", function () {
MailModule.Inbox.Init();
});
}
if ($(this).attr('id') == 'Outbox') {
$("#loadPage").empty().load("/Home/Outbox", function () {
MailModule.Outbox.Init();
});
}
});
</script>
<body>
</html>
Inbox.html
<div id="items"></div>
<script>
(function (mail, $) {
mail.Inbox = (function () {
var ReceiveMail = function () {
// This is still active when there is new 'mail' from server
// even though I'm not on this page
SignalRHub.client.receiveMail = function (UserName, Title){
$("#items").append("<p>"+UserName+"-"+Title+"</p>");
}
};
var init = function () {
ReceiveMail();
};
return {
Init: init
};
}());
}(window.MailModule = window.MailModule || {}, jQuery));
</script>
Outbox.html
<div id="items"></div>
<script>
(function (mail, $) {
mail.Outbox = (function () {
var GetSend = function () {
$.get("URL", { UserId: UserId }, function (result) {
$("#items").append("<p>"+result[0].UserName+"-"+result[0].Title+"</p>");
}
};
var init = function () {
GetSend();
};
return {
Init: init
};
}());
}(window.MailModule = window.MailModule || {}, jQuery));
</script>
Note: Maybe this pattern is not right, and I'll be grateful if you give me a lead on how I can accomplish a better one
I am creating a simple function that warns the user when they are about to close out of a web page. I am using the window.onbeforeonload function is javascript. What I am doing is that, I set a variable to false because of the evil window.onbeforeonload function.
function funky() {
var submitFormOkay = false;
window.onbeforeunload = function () {
if (submitFormOkay == false) {
return "You are about to leave this order form. You will lose any information...";
}
}
}
In my html, this is what I am doing
<input type="submit" id="submit_button" onclick="submitFormOkay = true;">
My question however is that I need a way to fire the function funky().
I know I could use an onclick but if I do what is going to set the value of submitFormOkay.
Any help would be appreciated.
Why not make submitFormOkay a parameter of the function funky, and just call it with the given parameter?
<input type="submit" id="submit_button" onclick="funky(true);">
And in the JS file:
function funky(submitFormOkay) {
window.onbeforeunload = function () {
if (submitFormOkay == false) {
return "You are about to leave this order form. You will lose any information...";
}
}
}
Without changing your HTML, I'd do this instead:
window.onbeforeunload = (function(w) {
w.submitFormOkay = false;
return function() {
if (!w.submitFormOkay) {
return "You are about to leave this order form. You will lose any information...";
}
};
})(window);
A problem with ngmiceli's solution is that window.onbeforeunload's callback never gets defined until the user is okay to leave the page.
I am fairly new to using javascript and here is what I have so far:
<!-- this is to disable the submit button and then re-enable it after 3 sec -->
<script type="text/javascript">
function enable()
{
var x = document.LAYOUTFORM.getElementById("create_button");
setTimeout(x.removeAttribute("disabled"), 3000);
}
</script>
And for the button I have this:
<INPUT TYPE="SUBMIT" VALUE=" Create PDF " class="FORMBUTTON" ID="create_button" onclick="javascript:this.disabled=true;javascript:enable();">
I have messed with this for hours and most of you will look at it and know what is wrong immediately. My form ID and name is LAYOUTFORM. Can anyone tell me what I am doing wrong here?
For bonus points I would also like the text of the button to temporarily change to "Creating..." while it is disabled, and then back to Create PDF again.
Simplest way:
<input ... onclick="lockoutSubmit(this)">
In your javascript:
function lockoutSubmit(button) {
var oldValue = button.value;
button.setAttribute('disabled', true);
button.value = '...processing...';
setTimeout(function(){
button.value = oldValue;
button.removeAttribute('disabled');
}, 3000)
}
Drop the LAYOUTFORM between document and getElementById.
Just an fyi, using firebug, chrome developer tools, or whatever the equivalent tools are for IE, you can monkey with your javascript on the console. Console.log will also output text and even objects (in CDT) which you can inspect. Very useful for exploring :)
Several problems. First, in the onclick attribute, you use javascript: which is for URLs. Stuff inside the onclick attribute is already evaluated as code. Second, the code in your setTimeout should either be string or a function name. You should do something more like this:
HTML:
<INPUT TYPE="SUBMIT" VALUE=" Create PDF " class="FORMBUTTON" ID="create_button" onclick="disable();">
JavaScript:
<script type="text/javascript">
function disable() {
x=document.getElementById("createbutton");
x.disabled=true;
x.value="Creating...";
setTimeout(enable, 3000);
}
function enable() {
x.disabled=false;
x.value=" Create PDF ";
}
</script>
You can access the button either by id that is globally unique
or by the name unique to the enclosing form
So you have to either
var x = document.getElementById("create_button");
or
var x = document.LAYOUTFORM.elements["create_button_name"];
(Assuming create_button_name is the name of the button:
<input type="submit" value=" Create PDF " id="create_button" name="create_button_name" class="formButton" onclick="javascript:this.disabled=true;javascript:enable();">
)
The first parameter of the setTimeout should be a function:
setTimeout(removeAttr, 3000);
function removeAttr() {
x.removeAttribute("disabled")
}
BTW, HTML need not be (and should not be, for readability etc) all uppercase.
There are two main problems with your JavaScript:
The .getElementById() method belongs to document, not to your form (or any other) element.
setTimeout() expects the first parameter to be a function (or a string, but there's almost never a situation when using a string is appropriate).
Try this:
function enable() {
var x = document.getElementById("create_button");
setTimeout(function() {
x.removeAttribute("disabled");
}, 3000);
}
You may like to combine the disabling and re-enabling into a single function:
<INPUT TYPE="SUBMIT" ... onclick="temporaryDisable(this);">
function temporaryDisable(el) {
el.disabled = true;
setTimeout(function() {
el.disabled = false;
}, 3000);
}
Note that you don't need to use .removeAttribute(), you can just set the .disabled property directly (like you were already doing when you disabled the element).
EDIT: Just saw the "bonus points" part of your question. You just need to set the .value property:
function temporaryDisable(el) {
var oldLabel = el.value;
el.value = "Creating...";
el.disabled = true;
setTimeout(function() {
el.disabled = false;
el.value = oldLabel;
}, 3000);
}
<script type="text/javascript">
function disDelay(obj){
obj.setAttribute('disabled','disabled');
setTimeout(function(){obj.removeAttribute('disabled')},30000)
}
</script>
<input type="submit" value="Submit" onclick="disDelay(this)">
http://www.webdeveloper.com/forum/showthread.php?164239-Temporarily-Disable-Submit-Button
I'm trying to figure out how to pass arguments to an anonymous function in JavaScript.
Check out this sample code and I think you will see what I mean:
<input type="button" value="Click me" id="myButton" />
<script type="text/javascript">
var myButton = document.getElementById("myButton");
var myMessage = "it's working";
myButton.onclick = function(myMessage) { alert(myMessage); };
</script>
When clicking the button the message: it's working should appear. However the myMessage variable inside the anonymous function is null.
jQuery uses a lot of anonymous functions, what is the best way to pass that argument?
Your specific case can simply be corrected to be working:
<script type="text/javascript">
var myButton = document.getElementById("myButton");
var myMessage = "it's working";
myButton.onclick = function() { alert(myMessage); };
</script>
This example will work because the anonymous function created and assigned as a handler to element will have access to variables defined in the context where it was created.
For the record, a handler (that you assign through setting onxxx property) expects single argument to take that is event object being passed by the DOM, and you cannot force passing other argument in there
What you've done doesn't work because you're binding an event to a function. As such, it's the event which defines the parameters that will be called when the event is raised (i.e. JavaScript doesn't know about your parameter in the function you've bound to onclick so can't pass anything into it).
You could do this however:
<input type="button" value="Click me" id="myButton"/>
<script type="text/javascript">
var myButton = document.getElementById("myButton");
var myMessage = "it's working";
var myDelegate = function(message) {
alert(message);
}
myButton.onclick = function() {
myDelegate(myMessage);
};
</script>
The following is a method for using closures to address the issue to which you refer. It also takes into account the fact that may which to change the message over time without affecting the binding. And it uses jQuery to be succinct.
var msg = (function(message){
var _message = message;
return {
say:function(){alert(_message)},
change:function(message){_message = message}
};
})("My Message");
$("#myButton").click(msg.say);
By removing the parameter from the anonymous function will be available in the body.
myButton.onclick = function() { alert(myMessage); };
For more info search for 'javascript closures'
Event handlers expect one parameter which is the event that was fired. You happen to be renaming that to 'myMessage' and therefore you are alerting the event object rather than your message.
A closure can allow you to reference the variable you have defined outside the function however if you are using Jquery you may want to look at its event specific API e.g.
http://docs.jquery.com/Events/bind#typedatafn
This has an option for passing in your own data.
<input type="button" value="Click me" id="myButton" />
<script type="text/javascript">
var myButton = document.getElementById("myButton");
myButton.myMessage = "it's working";
myButton.onclick = function() { alert(this.myMessage); };
</script>
This works in my test suite which includes everything from IE6+. The anonymous function is aware of the object which it belongs to therefore you can pass data with the object that's calling it ( in this case myButton ).
The delegates:
function displayMessage(message, f)
{
f(message); // execute function "f" with variable "message"
}
function alerter(message)
{
alert(message);
}
function writer(message)
{
document.write(message);
}
Running the displayMessage function:
function runDelegate()
{
displayMessage("Hello World!", alerter); // alert message
displayMessage("Hello World!", writer); // write message to DOM
}
Example:
<input type="button" value="Click me" id="myButton">
<script>
var myButton = document.getElementById("myButton");
var test = "zipzambam";
myButton.onclick = function(eventObject) {
if (!eventObject) {
eventObject = window.event;
}
if (!eventObject.target) {
eventObject.target = eventObject.srcElement;
}
alert(eventObject.target);
alert(test);
};
(function(myMessage) {
alert(myMessage);
})("Hello");
</script>
What you have done is created a new anonymous function that takes a single parameter which then gets assigned to the local variable myMessage inside the function. Since no arguments are actually passed, and arguments which aren't passed a value become null, your function just does alert(null).
If you write it like
myButton.onclick = function() { alert(myMessage); };
It will work, but I don't know if that answers your questions.