JavaScript Chrome extension using variables and functions from different JS files - javascript

I have 5 content_script.js (1-5) and each contains its own function inside each of these content scripts. However, I ran into an issue where I need to use a variable or function from another content script, it throws me an error saying variable/function undefined. So I have to redeclare the variable again in the same script to be able to use it.
Is there a way to pass variables and functions from one content script to another? In this case I want to use the setSelectedValue() function and objSelect variable.
content_script:
function clickUpdate() {
var updateArray = document.getElementsByClassName("updateButton");
var saveArray = document.getElementsByClassName("saveButton");
var updateArraySelector = document.querySelectorAll(".updateButton");
[].slice.call(updateArray).forEach(function(item) {
if (saveArray.length == 0)
setSelectedValue(objSelect, "P"); //it doesnt recognize this function from my other content_script
console.log("object select is: " + objSelect); //it also doesnt recongize this variable
});
console.log("this is the update array legnth: " + updateArray.length);
console.log("this is the save array legnth: " + saveArray.length);
console.log("this is the update array selector: " + updateArraySelector);
}
clickUpdate();
content_script1:
var objSelect = document.querySelectorAll('.engpf')
//Set selected
setSelectedValue(objSelect, "P");
function setSelectedValue(selectObj, valueToSet) {
for (var i=0; i<selectObj.length; i++) {
for(var j=0; j<selectObj[i].options.length; j++){
if (selectObj[i].options[j].value == valueToSet) {
selectObj[i].options[j].selected = true;
}
}
}
}

Related

How to call JS-Functions only on HTML pages where they are being used and not on all of them?

I am creating a demo-website for a fictional company.
The most of it is written in Javascript but I have a problem that all my functions are getting called on every HTML-page, even if they are not getting used.
Example: I have a Contact page where only one function should be called, but right now all functions are being called. Those for my Booking page and so on.
I am trying to use window.addEventListener together with window.location.pathname without result.
function start() {
// variable for pathname. split in to substrings by '/'
var pathArray = window.location.pathname.split('/');
// check the last substring of the array for determening which script to
run
if(pathArray[pathArray.length-1] == "contact.html")
{
browserDetect();
}
else if(pathArray[pathArray.length-1] == "ourfleet.html")
{
showFirstFleetImg();
showFleetImg();
}
else if(pathArray[pathArray.length-1] == "employees.html")
{
showFirstStaffImg();
showStaffImg();
}
}
window.addEventListener("load", start, false);
One of the functions
function showFleetImg(arrayno) {
var fleethtml = "";
var caption = document.getElementById("planename");
for(var i = 0; i < fleetarray.length; i++) {
fleethtml = fleethtml + "<a href = '#' onclick = 'showFleetImg(" + i +
"); return false; '><img src='" + fleetarray[i] + "' /></a>";
}
fleetimage.src = fleetarray[arrayno];
caption.innerHTML = planename[arrayno];
document.getElementById("fleetthumbs").innerHTML= fleethtml;
}
function showFirstFleetImg(imgnum) {
showFleetImg(0);
}
window.addEventListener("load", showFirstFleetImg, false);
What more do I add, or how do I structure this right so function X is only called in HTML file Y?
It looks like you are looking for something like ES Modules. There is a lot of information here http://exploringjs.com/es6/ch_modules.html, but the gist is they encapsulation javascript code so that functions aren't executed right away.
If you rewrite your javascript file to something like
// foo.js
export function showFleetImg(arrayno) {
var fleethtml = "";
var caption = document.getElementById("planename");
for(var i = 0; i < fleetarray.length; i++) {
fleethtml = fleethtml + "<a href = '#' onclick = 'showFleetImg(" + i +
"); return false; '><img src='" + fleetarray[i] + "' /></a>";
}
fleetimage.src = fleetarray[arrayno];
caption.innerHTML = planename[arrayno];
document.getElementById("fleetthumbs").innerHTML= fleethtml;
}
export function showFirstFleetImg(imgnum) {
showFleetImg(0);
}
and then your other js file will look like
import {showFleetImg, showFirstFleetImg} from './foo.js'
function start() {
// variable for pathname. split in to substrings by '/'
var pathArray = window.location.pathname.split('/');
// check the last substring of the array for determening which script to
run
if(pathArray[pathArray.length-1] == "contact.html")
{
browserDetect();
}
else if(pathArray[pathArray.length-1] == "ourfleet.html")
{
showFirstFleetImg();
showFleetImg();
}
else if(pathArray[pathArray.length-1] == "employees.html")
{
showFirstStaffImg();
showStaffImg();
}
}
There is nothing in the code you've posted to suggest each function should first every time.
However, there are many better ways to do what you're trying to do.
Use separate JS files and call into each page only those that need to be executed
If you prefer to use one JS file like currently, don't conditionalise based on pathname; what if your filename changes? You'd have to update your JS each time.
As regards the latter point, it would make more sense to act on the presence (or lack thereof) of a data attribute on the body identifying which page is currently showing.
HTML
<body data-page='contact'>
JS
switch (document.body.getAttribute('data-page')) {
case 'contact': /* do something */ break;
case 'fleet': /* do something else */ break;
//etc...
}
Note also the use of switch() rather than duplicative if/else if statements.
[Edit - or have a look at Modules as per #user1816294's answer]

Insert Logging In Functions ASP.NET

I have an .ascx containing javascript and div elements.
I want insert a log statement inside a function for troubleshooting.
May I know how can I achieve it?
Below is my code snippet:
function SaveGroupCheck() {
var isValid = true;
var haveError = false;
var schedule = document.getElementById("<%=ddlExecutionSchedule.ClientID%>").value;
//INSERT LOGGING HERE - Value of 'schedule'//
if (schedule == "Weekly")
{
var xday = document.getElementById("<%=chkSelectDay.ClientID%>");
var checkbox = xday.getElementsByTagName("input");
var counter = 0;
for (var i = 0; i < checkbox.length; i++) {
if (checkbox[i].checked) {
counter++;
}
}
//INSERT LOGGING HERE - Value of 'counter'//
if (counter < 1) {
$("#chkSelectDay").addClass('errorbox');
$("#divSelectDay").addClass('has-error has-feedback');
$("#lblSelectDay").addClass('has-error has-feedback');
haveError = true;
}
else {
$("#chkSelectDay").removeClass('errorbox');
$("#divSelectDay").removeClass('has-error has-feedback');
$("#lblSelectDay").removeClass('has-error has-feedback');
}
}
//INSERT LOGGING HERE - Value of 'haveError'//
Below is a log which I attempted but failed. I will use a try-catch if the error info needs to be provided.
var logFileName = ConfigurationManager.AppSettings["logpath"] + "Debug_" + DateTime.Now.ToString("ddMMyyyy_hhmmss") + ".log";
var itemPerPage = document.getElementById("<%=txtItemsPerPage.ClientID%>").value;
Log(DateTime.Now.ToString("ddMMyyyy_hhmmss") + " - itemPerPage = " + itemPerPage);
*logpath configured in app.config.
Thank you for your time.
To log any javascript variables you can use :
console.log("Hello I'm the variable value");
and open chrome console to see the value.
If you want to send variable value to server you must go to ajax call by calling server method for logging.
I hope that I understood your question.

javascript keeping a var within inner functions

I am making a website based dashboard. one of the functionalities is showing the locations of all customers. when i'm placing these on the map i can't seem to get the pop-up right.
function getCoordinates(locationList) {
for (var i = 0; i < locationList.length; i++) {
if (locationList[i].city != null) {
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(
function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(locationList[i].customerName);
}
);
}
}
}
When I use this code the pop-up will only contain the last customer's name in every pop-up.does someone know how to make sure that the attributes of the correct user are used?
That's a closure problem, to fix it you have to move your $http call to a new function like this.
function httpCall(locationList,i){
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(
function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(locationList[i].customerName);
}
);
}
After for loop i is always locationList.length - 1. Try to add IIFE with local i. For example you can solve the problem with replacing for loop with locationList.forEach
This is Infamous Loop Problem. Since you are just defining the function and not actually executing it when the for loop ends all the functions will have the same values for index i.
Solution: Is to assign the value to a variable and use this variable inside you success callback.
for (var i = 0; i < locationList.length; i++) {
if (locationList[i].city != null) {
var currLocation = locationList[i]; // assign the data to a variable
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(
function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(currLocation.customerName); // use the variable instead of the indexed lookup
}
);
}
}
Let me know if this helps.
It's a scope problem. Your i is updated and later, when you will click on the popup, it will read the last value of i.
You should put your conditional in the for a function which take in parameter the i :
function getCoordinates(locationList) {
for (var i = 0; i < locationList.length; i++) {
conditionalGet(i);
}
function conditionalGet(i) {
if (locationList[i].city != null) {
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(locationList[i].customerName);
});
}
}
}

Local variables giving global trouble

I'm a JS super n00b.
I asked about an aspect of this problem in this post (Puzzling behavior from IF ( ) statement) on IF statements but it looks like the actual issue is related to the scope of a variable I've created. It seems that after declaring (what I think is) a global variable, other functions in the code cannot access the variable.
I'm doing JS project/program that prompts a user to input a word and the program reverses the word input.
In the previous post (PP) a user correctly determined that I was getting the 'false' console message (see code) no matter what the length of the word input because I was assigning value the variable when the page loads but not reading it again when the user clicks the button on the page.
If the variable 'word' is local I'm only able to get a 'false' console message and when the variable 'word' is global I'm only able to get a 'ReferenceError.'
Any ideas anyone has are greatly appreciated.
See JS code below:
var word = document.getElementById('wordChoice').value;
var lttrs = [];
function flipFail () {
alert("Please enter a word of at least two characters.");
console.log(false);
var inputErrArr = ['has-error', 'has-feedback'];
var inputErrFdbk = ['glyphicon', 'glyphicon-remove'];
wordChoice.style.backgroundColor = "#FFDBAA";
for (var i = 0; i < inputErrArr.length; i ++) {
addClass(wordInput, inputErrArr[i]);
}
for (var i = 0; i < inputErrFdbk.length; i ++) {
addClass(glyph, inputErrFdbk[i]);
}
document.getElementById('wordChoice').value = " ";
} // END flipFail()
function flipSuccess (){
for (var i = 0; i < word.length; i ++) {
lttrs.push(word.charAt(i));
}
lttrs.reverse();
var reversedWord = lttrs.join('')
alert("Your reversed word is: " + reversedWord);
console.log(true);
document.getElementById("flip").innerHTML = "Flip Again!";
document.getElementById('wordChoice').value = " ";
} // EN flipSuccess ()
function flipChk () {
if (word.length < 2) {
flipFail ();
} else {
flipSuccess ();
}
}
See fully implemented code here: http://supsean.com/supsean/flipr/flipr.html
You need to set word in flipChk(). You're setting it when the page is first loaded, before the user has entered anything into the form, not when the user clicks on the Flip button.
Then, instead of using a global variable, pass it as an argument to the function. In general, avoid using global variables unless you really have to.
function flipChk () {
var word = document.getElementById('wordChoice').value;
if (word.length < 2) {
flipFail ();
} else {
flipSuccess (word);
}
}
function flipSuccess (word){
var lttrs = [];
for (var i = 0; i < word.length; i ++) {
lttrs.push(word.charAt(i));
}
lttrs.reverse();
var reversedWord = lttrs.join('')
alert("Your reversed word is: " + reversedWord);
console.log(true);
document.getElementById("flip").innerHTML = "Flip Again!";
document.getElementById('wordChoice').value = " ";
} // EN flipSuccess ()

How To Loop through result.invocationResult.resultSet in IBM worklight

Everything works except the display function . In this display function i am trying to access the field Name from the resultSet but it is not working.
function succ(result)
{
alert("connected");
var a = result.invocationResult.resultSet[1].Name;
$("#fetcharr").val(a);
alert("connectedlll");
display(result.invocationResult.resultSet);
alert("the end");
}
Display function is:
function display(items)
{
alert("heelo");
for(var j in items )
{
var a = j.Name;
alert(a);
}
}
Why the need for two functions here?
Anyway, to loop through the resultSet you can use a for loop like so:
function succ(result) {
for (var i = 0; i < result.invocationResult.resultSet.length; i++) {
display(result.invocationResult.resultSet[i]);
// do something with the current result, for example:
$("#someIdInTheHTML").append("<p>Name: " + result[i].name + "</p>");
};
}
You will want to search through the "worklight-adapters" tag, as this has been asked many times in various forms.

Categories

Resources