How were Chrome and other browsers able to initialize this JavaScript variable? - javascript

I'm working on a shopping cart that asks the user to check the box indicating they agree to the terms of service before they can "review order" and finally make the purchase.
I have to accomplish this with JavaScript by getting the element containing the "review order" and "continue shopping" buttons and changing the inner HTML to be what I need. I have to do it this way because the cart I am using does not give me full control over these elements in the cart source code.
Here is the code I originally came up with, which worked on Chrome, Edge, and other browsers, but not IE.
var x = document.getElementById('CHECKOUT_LINKS');
x.innerHTML = '<div class="checkoutLinksBottom"><input id="tosBox" type="checkbox" name="tosBox">I agree to the Terms of Service<br>Continue ShoppingReview Order</div>';
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#tosBox').addEventListener('change', changeHandler);
});
var checkbox = document.getElementById("tosBox");
checkbox.checked = true;
checkbox.checked = false;
function changeHandler() {
if (!tosBox.checked)
alert("You must agree to the Terms of Service");
}
function clicker() {
if (!tosBox.checked)
alert("You must agree to the Terms of Service");
else { // Go to review order page
}
}
As you can see the CHECKOUT_LINKS element's inner HTML is changed to what I need on the fly as the page loads. The primary point is to add the id="tosBox" element, then capture the click on id="reviewOrderButton" element and filter it though the simple JS functions changeHandler() and clicker().
In IE developer tools, the console reports 'tosBox' is undefined when I click on id="reviewOrderButton" element. This makes sense when looking at var checkbox = document.getElementById("tosBox"); the variable created is called checkbox, but the variable I try to use later is called tosBox. I simply changed checkbox to tosBox and then everything worked on IE as well.
What's shocking to me is that the original code worked on Chrome and Edge. How did it work? Should I expect it to work and IE is faulting?

Related

JavaScript - My checkbox (which is checked by default) doesn't run it's script on page load

I apologize if this is something really simple, but I'm relatively new to JavaScript. I've scoured the web to find a solution but haven't found anything!
So I'm building a sort of "settings" UI for a Google Chrome extension popup and I'm using checkboxes to enable/disable options. I want one of the checkboxes to be checked by default, so I have the checked attribute defined in its HTML like so;
<input type="checkbox" id="option1" style="margin-left: 20px;" checked>
<!-- ^ Right here ^ -->
<script src="script.js"></script>
I implemented a script here so that if the checkbox is checked, a certain script will be programmatically injected. If it isn't checked, it will inject a different script. Code:
document.getElementById("option1").addEventListener("click", toggleOption1);
function toggleOption1() {
var option1 = document.getElementById("option1");
// if option1 is checked, run first script
if (option1.checked === true) {
chrome.tabs.executeScript({
file: 'optionEnabled.js'
});
// otherwise, run script 2
} else {
chrome.tabs.executeScript({
file: 'optionDisabled.js'
});
}
}
Now, this has worked great for me so far, it does exactly what it intends to do except for one thing:
I want the code to be run automatically because, duh, the checkbox is checked by default. The code only recognizes when the box is unchecked or checked by the user.
Note: I am aware that this line of code
document.getElementById("option1").addEventListener("click", toggleOption1);
means that the function is run on click and I should just use onclick="toggleOption1()" instead, but because I am making a chrome extension, inline scripts are not allowed.
Note 2: I would appreciate it if the solution could avoid JQuery or other external libraries, but if nothing else is available, I guess it's okay!
Note 3: I would provide a JSFiddle, but I don't believe there's a way to implement the chrome extension environment.
Anyone out there know a way to fix this? I've been confuzzled for several days and I'd really like to fix this issue.
Thanks in advance!
call
toggleOption1();
after
document.getElementById("option1").addEventListener("click", toggleOption1);
EDIT
You should use something like DOMContentsLoaded event to make sure the Data Object Model is loaded
JavaScript
window.addEventListener('DOMContentLoaded', (event) => {
document.getElementById("option1").addEventListener("click", toggleOption1);
toggleOption1();
});
function toggleOption1() {
var option1 = document.getElementById("option1");
// if option1 is checked, run first script
if (option1.checked === true) {
console.log("checked");
// chrome.tabs.executeScript({
// file: 'optionEnabled.js'
// });
// otherwise, run script 2
} else {
console.log("not checked");
// chrome.tabs.executeScript({
// file: 'optionDisabled.js'
// });
}
}
Since you know by default that checkbox is checked then you can simply execute your code
chrome.tabs.executeScript
From the background script and not from the popup script.
Background script is loaded once the extension is loaded.
Background script has one instance for all tabs.
update:
It will do it only one time when the extension is loaded. So no problem for the user to play with the checkbox after that from thr popup

Advanced jQuery Popout Window

Several problems:
1) I am trying to make this script run more efficiently.
2) When the user clicks either pop out button it opens a windows and hides the element. (Currently I am using .detach() to remove the embedded video player because in Firefox .toggle() just hides the player but keeps the audio playing. Is there a better way to do this?
3) In theory by clicking the button again or closing the window manually it should un hide or .toggle() the element but does not for the video player due to detach().
4) If a user pops out the window manually closes it and then pops it out again to only close it once more the element does not .toggle() back.
See it in action here, http://www.mst3k.tv/.
$(document).ready(function() {
$('#lights').click(function(){$('#darkness').fadeToggle(500);});
$("#lights").toggle(function(){$("#lights").attr('id','lightsoff');},function(){$("#lightsoff").attr('id','lights');});
/**VIDEO**/
var videoWin;
$('#video-toggle').click(function(){
$('#video').fadeToggle(500);
$('#video').detach();
});
$('#video-toggle').click(function(){
if (videoWin && !videoWin.closed) {
videoWin.close();
return false;
}
videoWin = window.open(
$(this).attr('rel'),
'videoWin',
'width=600,height=480,toolbar=0,top=0,left=0,menubar=0,location=0,status=0,scrollbars=0,resizable=1');
return false;
}
);
var watchVideo = setInterval(function() {
if (videoWin.closed) {clearTimeout(watchVideo);$('#video').show(500)}
return false;
}, 1);
/**CHAT**/
var chatWin;
$('#chat-toggle').click(function(){
$('#chat').fadeToggle(500);
/*$('#chat').detach();*/
});
$('#chat-toggle').click(function(){
if (chatWin && !chatWin.closed) {
chatWin.close();
return false;
}
chatWin = window.open(
$(this).attr('rel'),
'chatWin',
'width=320,height=480,toolbar=0,top=0,left=601,menubar=0,location=0,status=0,scrollbars=0,resizable=1');
return false;
}
);
var watchChat = setInterval(function() {
if (chatWin.closed) {clearTimeout(watchChat);$('#chat').show(500)}
return false;
}, 1);
/*$("a.btn").fitText(1.2, { minFontSize: "6px", maxFontSize: "14px" });*/
});
It would be better if you created a jQuery plugin for your code so you can re-use it and avoid DRY. Here are a couple of options:
Plugin 1: jQuery popupWindow
Plugin 2: jQuery winPop
Also note that the closed property is not part of any W3C specification, however it might be supported across Browsers.
You could also write a JS function that could be reused. According to the w3cschools website the window.closed property is supported in most major browsers and you can check for it prior to triggering the event.
instead of
if(videoWin && !videoWin.closed)
you could use
if (typeof videoWin!='undefined'){ /* it has been created */}
elseif(typeof videoWin='undefined') { /*it's okay to open the new window*/}
Make sure you're not creating the variable if you're using this as a check though until the window open event has been fired. Since you're creating the var a couple of lines above your function declaration it will always return as defined.
You'll need to specify a target object in your function to have it throw multiple windows correctly... meaning you can't declare one var for multiple windows. Maybe a class would be better.
Something I thought was odd earlier but forgot to mention before FB posted my response prematurely was that you're adding your href in the rel attribute and specifying the href as a js:void(0) which is also non-standard. The rel attribute is for specifying the relationship between the link and the page... (eg. rel=nofollow). That might also be why it's not firing and misfiring some of the time as well, and the differences between browser response.

making a custom Confirm box in javascript

I want to make a custom made confirmation box in javascipt just like the built in confirm box. the built in confirm box does not allow the code to progress unless the user selects atleast one thing. Below is my code:
*****HTML start*****
<div class = "popUp confirm" style="z-index:40000;" id="confirmBlock">
<div id = "confirmLabel" >Confirm Message</div>
<div style ="border:0px solid red;height:44.56px;">
<input id="Confirm" type="button" value="Confirm" onclick = "confirmAction(1)" />
<input id = "CancelConfirm" type="button" value="Cancel" onclick = "confirmAction(0)" />
</div>
</div>
*****HTML end*****
*****Javascript start*****
var confirmresult = "-1";
function confirmationLoop()
{
alert("If this alert is preesnt it works, seems like the built in alert provides some sort of pause for other parts of code to continue to work");
if(confirmresult == "-1")
confirmationLoop();
return;
}
function confirmAction(val)
{
confirmresult = val;
}
function checkuuu()
{
confirmresult = "1";
}
function confirmMessage(message)
{
document.getElementById("confirmLabel").innerHTML= message;
//var check = setTimeout(function(){confirmAction(1)},5000);
confirmationLoop();
/*
while(1) //using while almost does not allow any other part to run at all hence tried recursion
{
if(confirmresult != "-1")
break;
}
*/
document.getElementById("confirmLabel").innerHTML= "Confirm Message";
var returnVal = confirmresult;
confirmresult = -1;
return returnVal;
}
*****Javascript end*****
*****Sample code start*****
So this i what i expect below:
function example
{
var check = confirmMessage(message);
//the next part of code should not execute untill i press confirm or cancel, using settimeout or settimeinterval is asynchronous and the code flow continues. i want the effect something like alert and confirm built in boxes
}
*****Sample code end*****
I used loop but it keeps the thread completely occupied and does not give me a chance to press any button, which was quite obvious
However recursion gives u the freedom to perform other activities. The problem even though the value of confirmResult will become 1 upon pressing confirm button, which i check through alert. the recursive loop i.e. confirmation loop does not seem read it as 1. it still continues as -1. If i put a alert in that confirmation loop the value wil be read as 1. Can anyone help me to achieve what i started out to??????
P.s.=> sorry for such a huge question!!!
You can't use any sort of loop - as you've found it'll just cause the browser to lock up.
What you need to do is to emulate a "modal" dialog box.
This is usually done by having your dialog box appear on top of another "overlay" element which importantly covers every other element, and prevents any user interaction with them.
It's also pretty hard to implement a confirm function that'll return a value - the window.confirm method can only do that because it's synchronous - it blocks all other JS processing while the dialog is displayed.
The easiest approach is to instead supply a callback function that'll get called once the user has selected the desired value.

Return value from custom alert [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to create TRULY modal alerts/confirms in Javascript?
TL;DR: I've overridden the default alert() function with a custom HTML based one. I want the new dialogue to still block execution, and get the buttons within my dialogue to return true or false from the call to alert() to use in logic (and continue execution).
I'm trying to implement a custom alert box, which replaces the default browser alert with a nicely themed box with the same (or similar) functionality.
I've read this question, and I'm using the solution given in this answer (to the same question). What I want to do now is get my overridden alert to return a true or false value for use in if() statements, depending on whether OK or Cancel was clicked:
if(alert('Confirm?') {
// Do stuff
}
However, due to having custom HTML instead of a normal alert I can't do this for two reasons:
I can't return a value from the buttons in the replacement dialogue (click events bound with $.on()) because I have no idea how to.
I can't block program flow with this alert, as far as I know.
I've bound $.on() events to the Cancel and OK buttons in the replacement dialogue which hide the box. These work fine, but the problem I have now is returning a value when a button is clicked, so that execution will halt until an action is taken by the user.
HTML:
<div class="alert background"></div>
<div class="alert box">
<div class="message"></div>
<hr>
<div class="buttons">
<input type="button" name="cancel" value="Cancel">
<input type="button" name="confirm" value="OK">
</div>
</div>
Current JavaScript: (pretty much a carbon copy of the answer in my linked question)
(function () {
nalert = window.alert;
Type = {
native: 'native',
custom: 'custom'
};
})();
(function (proxy) {
proxy.alert = function () {
var message = (!arguments[0]) ? 'null' : arguments[0];
var type = (!arguments[1]) ? '' : arguments[1];
if (type && type == 'native') {
nalert(message);
} else {
// Custom alert box code
console.log(message);
}
};
})(this);
Ideally, I want to be able to put something like this in the // Custom alert box code part:
$('.alert.box input[name="confirm"]').on('click', function() {
// Hide dialogue box - I can do this already
// *** Return `true` or other truthy value from
// alert for use in `if()` statements
});
So that when the OK or Cancel button is clicked, it removes the custom alert box and returns a true or false value from the call to alert(). I can already remove the alert with $.fadeOut() and $.remove(), that's easy. What isn't is knowing how to get the button click events to get alert() (overridden) to return something.
I've tried to be as clear as I can, but I may have missed something out. Please let me know if I have.
The example below shows an approach to creating a custom alert and handling the outcome of the user selection
/*
message = String describing the alert
successCallBack = callback function for when the user selects yes
*/
function exampleAlert(message, successCallback)
{
/*Alert box object*/
var alertBox = document.createElement("div");
/*Alert message*/
var msg = document.createElement("div");
msg.innerHTML = message;
/*Yes and no buttons
The buttons in this example have been defined as div containers to accentuate the customisability expected by the thread starter*/
var btnYes = document.createElement("div");
btnYes.innerHTML= "Yes";
/*Both yes and no buttons should destroy the alert box by default, however the yes button will additionally call the successCallback function*/
btnYes.onclick = function(){ $(this.parentNode).remove();successCallback();}
var btnNo = document.createElement("div");
btnNo.innerHTML= "No"
btnNo.onclick = function(){ $(this.parentNode).remove();}
/*Append alert box to the current document body*/
$(alertBox).append(msg, btnYes, btnNo).appendTo("body");
}
function test()
{
alert("Example alert is working, don't use this test as a replacement test - horrible recursion!")
}
exampleAlert("shoe", test)
This is fairly basic and doesn't allow for additional data to be supplied to the callback function and for that reason is not ideal for production however jQuery's .bind() and similar methods allow for data to be associated with the callback method
It's worth commenting that while the above demonstrates a full implementation of the problem, there are in fact only two lines that actually matter.
btnYes.onclick...
btnNo.onclick...
Since we're achieving the desired result by binding onclick events for true and false respectively, everything else is there to paint the picture.
With that in mind it is possible to effectively turn any container object with at least one sibling into an alert box for eaxmple:
<!-- Example html -->
<div id='a'>
<ul>
<ul>
<li>Something</li>
<li>Something Else</li>
<li id='yesIdentifier'>Something not necessarily suggesting a trigger?</li>
</ul>
</ul>
</div>
As long as your yes / no (if no exists) options destroy the appropriate container a converting a container into an alert box can be handled in a couple of lines of code.
$('#yesIdentifier', '#a').click(
function(){ someCallback(); $(this).closest('#a').remove()});
Neither of the above are exemplary models for implementation but should provide some ideas on how to go about the task.
Finally... do you really need to replace the native alert method? That is, either you're writing the alert calls, in which case you'd know to use your custom method, or you're overwriting default behaviour that you can't guarantee the other developers will be aware of.
Overall recommendation:
I feel the best approach to this would be to create a jQuery plugin which creates the custom alerts on the fly and track callbacks, results and what not within the plugin.
SOliver.
Why don't you just use a confirm box like so.
var c = confirm('Confirm?');
if(c)
{
// Yes clicked
}
else
{
// No clicked
}
Or you could use jQuery UI's dialog confirmation box.
http://jqueryui.com/demos/dialog/#modal-confirmation

Adding checkbox settings to a Safari extension

I wrote this extension that basically changes the look of a website using CSS and JS. But now I want to add some checkbox settings to the extension so users can toggle features of the website.
I tried reading the documentation, and searched all over the web. Even tried to look for demo extensions that I could reverse engineer, but to no avail.
Let's say I want to add a "Check Box", title it "sidebar" and given it a "key" value of "tg_sidebar". Can someone explain how I would add an event listener for this, and then trigger some jquery code?
[I think this StackOverflow query [http://stackoverflow.com/questions/3032945/safari-extension-how-to-respond-to-settings-changes] makes things clear, but it still doesn't explain much.]
Here's one thing that worked.
function numberChanged(event)
{
if(event.key == "tg_sidebar")
alert("Number has changed!");
}
safari.extension.settings.addEventListener("change",numberChanged,false);
[Screenshot of the Extension Settings window: http://dznr.org/56wi]
Now whenever I toggle the setting, I get an error. But replacing that alert function with say adding or removing a CSS class doesn't work.
I also tried using the code by the answerer below, but that doesn't do anything. Would have been perfect to be able to look at the code of some extension…
One more thing, in case it wasn't clear, is that the setting should make the change permanent. That is, when the setting is ticked, it should do that action every time the page loads.
Assuming you have it setup in your extensions.
It's pretty simple. Every time your function is called in your global.html call this:
var type = safari.extension.settings.yourSettingsCall;
example:
var type;
function performCommand(event)
{
if (event.command === "start-event") {
type = safari.extension.settings.tg_sidebar;
}
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("type", type);
}
then your inject.js add these:
safari.self.addEventListener("message", handleMessage, false);
and
function handleMessage(event){
if (event.name === "type") {
//run code
}
}

Categories

Resources