Whole day I have been trying to get my script working on a specific website.
Basically I want this script to only run on specific domains.
Here is the code:
document.addEventListener("DOMContentLoaded", function(event) {
// URL variables
let fullURL = window.location.host;
let fullURL2 = window.location.host + window.location.pathname;
var timer = setInterval(deletor, 1);
alert(fullURL2);
alert(fullURL);
if (fullURL === "net.adjara.com") {
function deletor() {
timer;
var slider = document.querySelector("#slider-con");
var bannerTop = document.querySelector("#MainContent > div:nth-child(2)")
var bannerMiddle = document.querySelector("#MainContent > iframe");
var bannerRandom = document.querySelector("#MainContent > div:nth-child(3)");
if (slider) {
slider.parentNode.removeChild(slider);
}
if (bannerTop) {
bannerTop.parentNode.removeChild(bannerTop);
}
if (bannerMiddle) {
bannerMiddle.parentNode.removeChild(bannerMiddle);
}
if (bannerRandom) {
bannerRandom.parentNode.removeChild(bannerRandom);
}
console.log("worked!");
};
} else {
console.log("false!");
return false;
}
});
I do get "false" console logged when I go to other site than mentioned, but the script doesn't execute when the domain matches. I even added an alert to see what the value was of the variable and copy-pasted that.
When the function is defined inside the if, the variable will be hoisted, but it will not have a value
console.log(test)
if (new Date()){
function test() {}
}
so you are setting the interval with undefined.
Move the interval after you define the function.
Related
This is my code:
window.onload = function ()
{
var user = firebase.auth().currentUser
var login = document.getElementById("NavLogin");
if (user) {
login.innerHTML = "Account";
login.href = "AccountPage/AccountPage.html";
}
else {
login.innerHTML = "Login";
login.href = "AccountPage/LoginPage.html"
}
}
I have tried changing it to the onload of the body, but that didn't help either. I do not understand why it only works if called manually.
From your code I can see that you need to wait until #NavLogin element is loaded. If this element needs to be present in your page to run the rest of the code, then I would suggest you to use a pulling function like bellow:
function waitForElement(selector, cb) {
var tick = setInterval(function () {
var target = document.querySelector(selector);
if (null !== target) {
clearInterval(tick);
cb(target);
}
}, 200);
};
Then you can call the pulling function and pass your target element as the first parameter:
waitForElement("#NavLogin", function(login){
if (user) {
login.innerHTML = "Account";
login.href = "AccountPage/AccountPage.html";
}
else {
login.innerHTML = "Login";
login.href = "AccountPage/LoginPage.html"
}
})
If the target element is found, the callback function will be called and the target element will be passed as parameter to the callback function
I have a PHP page that loads two JS files at the end. In the first file I have this...
// global variables
var refineSearchStorage = {};
// function calls
window.addEventListener("load", function() {
refineSearchStorage.get();
});
refineSearchStorage = {
data : null, // empty storage
get : function() {
refineSearchStorage.data = localStorage.getItem("refineSearchStorage");
if(refineSearchStorage.data === null) {
refineSearchStorage.data = { refineKeywords: '' };
refineSearchStorage.save();
}
else {
refineSearchStorage.data = JSON.parse(refineSearchStorage.data);
}
},
add : function(x) {
refineSearchStorage.data.refineKeywords = x;
refineSearchStorage.save();
},
save : function() {
localStorage.setItem("refineSearchStorage", JSON.stringify(refineSearchStorage.data));
}
};
Inline javascript calls Function 1 from the middle of the page. It is created by PHP after a search result...
<script>
window.addEventListener('load', function () {
searchActions('{$keywords_human}');
});
</script>
Function 1 appears in the 2nd JS page and the result is Uncaught TypeError: Cannot set property 'refineKeywords' of null... instead of adding to the localStorage.
function searchActions(x) {
refineSearchStorage.add(x);
}
Function 2 below is called with the click of a button and adds to a localStorage variable without issue. It is also located on the 2nd JS page...
function keywordAdd(y) {
var existingParams = refineSearchStorage.data.refineKeywords;
var param = y.toLowerCase();
var newParams;
newParams = (existingParams + ' ' + param).trim();
refineSearchStorage.add(newParams);
}
Function 1 used to work, but I did something to break it when I split the functions on to different pages. What did I do?
It's because
window.addEventListener('load', function () {
searchActions('{$keywords_human}');
});
gets called before
window.addEventListener("load", function() {
refineSearchStorage.get();
});
That error means that your data attribute is null
(screenshot) See what I mean by that
convert add to
add : function(x) {
refineSearchStorage.data = refineSearchStorage.data || {}; // this might help
refineSearchStorage.data.refineKeywords = x;
refineSearchStorage.save();
},
I use the following function to dynamically load JavaScript:
function loadJS(file, c)
{
var jsEl = document.createElement("script");
jsEl.type = "application/javascript";
jsEl.src = file;
jsEl.async = false;
document.body.appendChild(jsEl);
if (c) { jsEl.addEventListener('load', function (e) { c(null, e); }, false); }
document.getElementsByTagName("head")[0].appendChild(jsEl);
}
Below is one of the functions contained within a dynamically added file:
function formelements_SELECT_add(x)
{
console.log("add");
alert("add");
var id = x[1];
var value = x[2];
var index = x[3];
var select = document.getElementById(id);
var option;
option = document.createElement("option");
option.text = value;
select.add(option, index);
}
I know the JavaScript file gets added correctly and the function gets executed because an option is added to the select element. Why does the alert and console.log not execute? If I click inspect, then there are no error messages.
EDIT
This is the code I use to call the function:
var typeAndElement = x[0][0] + "_" + x[0][1];
start = i + 1;
if (!window[typeAndElement])
{
loadJS("https://websemantica.org/scripts/" + x[0][0] + "/" + x[0][1] + ".js", continueManipulatingElements(typeAndElement, actions, x, start, total));
return;
}
else
{
fn = window[typeAndElement + "_" + x[0][2]];
if (typeof fn === 'function')
fn(x);
}
I didn't want to include it initially, because I already knew it was working and it will be unclear how it works considering it is using dynamic data.
Also, I have edited the loadJS function:
function loadJS(file, c)
{
var jsEl = document.createElement("script");
jsEl.type = "text/javascript";
jsEl.src = file;
jsEl.async = false;
if (c) { jsEl.addEventListener('load', function (e) { c(null, e); }, false); }
document.getElementsByTagName("head")[0].appendChild(jsEl);
}
The problem appears to be solved now.
Three things jump out:
You're appending the script to the page twice, once to document.body, and the other to document.getElementsByTagName("head")[0]. The second one will move the script from the first place to the second. You really only need to do one of those.
You're looking the load event after appending the element. If the script is in cache, you can miss the event. Hook it before appending the script to the DOM.
You're not doing anything in the quoted code to call the function that's defined by the script you're adding.
Other side notes:
No need to set type, the default is JavaScript.
No need to set async, all dynamically-inserted script elements are async (now, it wasn't always true).
As Jarosław Wlazło points out document.alert isn't a function; just alert is all you need. :-)
In addition: document has no alert method. It belongs to window, so you can call it like this alert('add');
I'm using the below CasperJS script to recursively parse the (multi-page) search results provided by google for the query site:https://www.launchgood.com/project/.
var links = [];
var casper = require('casper').create();
function getLinks() {
var currentLinks = document.querySelectorAll('h3.r a');
return Array.prototype.map.call(currentLinks, function(e) {
rawHref = e.getAttribute('href');
urlPattern = /.*(https?[:/]+[^&]+).*/g;
cleanHref = urlPattern.exec(rawHref);
return cleanHref[1];
});
Array.prototype.push.apply(links, currentLinks);
this.echo(' - ' + currentLinks.join('\n - '));
}
function parseAndContinue() {
links = this.evaluate(getLinks);
// now click 'Next'
if(this.exists('a.fl')) {
this.thenClick('a.fl');
this.then(parseAndContinue);
} else {
this.exit();
}
}
casper.start('http://google.com/ncr', function() {
// search from google form
this.fill('form[action="/search"]',
{ q: 'site:https://www.launchgood.com/project/' }, true);
});
casper.then(parseAndContinue);
casper.run();
This seems to continually search the 2nd page, over and over again in a never-ending loop -- instead of advancing to the next page.
What am I doing wrong?
Your looks fine apart from not printing anything. getLinks is a function that is evaluated in the page context. this refers to the global object, which is window, inside of the page context. You have no access to casper inside of the page context, because it is sandboxed and only primitive objects can be passed in or out. It has no access to variables defined outside of it (no access to links).
function getLinks() {
var currentLinks = document.querySelectorAll('h3.r a');
return Array.prototype.map.call(currentLinks, function(e) {
var rawHref = e.getAttribute('href');
var urlPattern = /.*(https?[:/]+[^&]+).*/g;
var cleanHref = urlPattern.exec(rawHref);
return cleanHref[1];
});
}
function parseAndContinue() {
var links = this.evaluate(getLinks);
console.log(JSON.stringify(links, undefined, 4));
// now click 'Next'
if(this.exists('a.fl')) {
this.thenClick('a.fl');
this.then(parseAndContinue);
} else {
this.exit();
}
}
Additionally, no code after the return statement will be executed.
Please be more careful and don't create global variables left and right.
How to write this JavaScript code without eval?
var typeOfString = eval("typeof " + that.modules[modName].varName);
if (typeOfString !== "undefined") {
doSomething();
}
The point is that the name of the var that I want to check for is in a string.
Maybe it is simple but I don't know how.
Edit: Thank you for the very interesting answers so far. I will follow your suggestions and integrate this into my code and do some testing and report. Could take a while.
Edit2: I had another look at the could and maybe itis better I show you a bigger picture. I am greatful for the experts to explain so beautiful, it is better with more code:
MYNAMESPACE.Loader = ( function() {
function C() {
this.modules = {};
this.required = {};
this.waitCount = 0;
this.appendUrl = '';
this.docHead = document.getElementsByTagName('head')[0];
}
function insert() {
var that = this;
//insert all script tags to the head now!
//loop over all modules:
for (var modName in this.required) {
if(this.required.hasOwnProperty(modName)){
if (this.required[modName] === 'required') {
this.required[modName] = 'loading';
this.waitCount = this.waitCount + 1;
this.insertModule(modName);
}
}
}
//now poll until everything is loaded or
//until timout
this.intervalId = 0;
var checkFunction = function() {
if (that.waitCount === 0) {
clearInterval(that.intervalId);
that.onSuccess();
return;
}
for (var modName in that.required) {
if(that.required.hasOwnProperty(modName)){
if (that.required[modName] === 'loading') {
var typeOfString = eval("typeof " + that.modules[modName].varName);
if (typeOfString !== "undefined") {
//module is loaded!
that.required[modName] = 'ok';
that.waitCount = that.waitCount - 1;
if (that.waitCount === 0) {
clearInterval(that.intervalId);
that.onSuccess();
return;
}
}
}
}
}
};
//execute the function twice a second to check if all is loaded:
this.intervalId = setInterval(checkFunction, 500);
//further execution will be in checkFunction,
//so nothing left to do here
}
C.prototype.insert = insert;
//there are more functions here...
return C;
}());
var myLoader = new MYNAMESPACE.Loader();
//some more lines here...
myLoader.insert();
Edit3:
I am planning to put this in the global namespace in variable MYNAMESPACE.loadCheck, for simplicity, so the result would be, combining from the different answers and comments:
if (MYNAMESPACE.loadCheck.modules[modName].varName in window) {
doSomething();
}
Of course I will have to update the Loader class where ever "varName" is mentioned.
in JS every variable is a property, if you have no idea whose property it is, it's a window property, so I suppose, in your case, this could work:
var typeOFString = typeof window[that.modules[modName].varName]
if (typeOFString !== "undefined") {
doSomething();
}
Since you are only testing for the existence of the item, you can use in rather than typeof.
So for global variables as per ZJR's answer, you can look for them on the window object:
if (that.modules[modName].varName in window) {
...
}
If you need to look for local variables there's no way to do that without eval. But this would be a sign of a serious misdesign further up the line.