EVAL dangerous How to replace it - javascript

I have the following code for a pop-up window (client request). It uses eval which I understand is dangerous. Is there a way to re-write the script below so it does not use (eval)?
/* exported popup_default , popup_help , popup_sitemap , popup_footerlinks */
var matchClass = ['popup_default', 'popup_sitemap', 'popup_footerlinks', 'popup_help'];
var newwindow = ''
var popup_default = 'width=800,height=640,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=250,top=200';
var popup_help = 'width=700,height=650,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=100,top=100';
var popup_sitemap = 'width=1000,height=600,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=100,top=100';
var popup_footerlinks = 'width=800,height=500,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=250,top=200';
function pop_ups() {
"use strict";
var x = 0;
var popClass;
while (x < matchClass.length) {
popClass = "'." + matchClass[x] + "'";
$(eval(popClass)).click(function() {
var popurl = $(this).attr('href');
var popupSpecs = $(this).attr('class');
var popupName = Math.floor(Math.random() * 10000001);
newwindow = window.open(popurl, popupName, eval(popupSpecs));
return false;
});
x++;
}
}
$(function() {
"use strict";
pop_ups();
});

You'll want to use
"use strict";
function makePopup(className, specs) {
$('.'+className).click(function(e) {
e.preventDefault();
var popupName = Math.floor(Math.random()*10000001);
window.open(this.href, popupName, specs);
});
}
var popups = {
popup_default: 'width=800,height=640,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=250,top=200',
popup_help: 'width=700,height=650,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=100,top=100',
popup_sitemap: 'width=1000,height=600,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=100,top=100',
popup_footerlinks: 'width=800,height=500,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=250,top=200'
};
$(function() {
for (var key in popups)
makePopup(key, popups[key]);
});
Instead of the first eval, just use string concatenation. Instead of the second eval, use an object to look up a property name.

Thanks #Bergi
I updated that last part of the script because it threw an error: "The body of a for in should be wrapped in an if statement"
$(function() {
"use strict";
for (var key in popups) {
if(popups.hasOwnProperty(key))
{
makePopup(key, popups[key]);
}
}
});
Thanks again for the help

Related

jquery .fadeOut() is not a function error

I'm working on swapping out some content in a simple div using the code below.
var slides = [
[],
[],
[],
[]
];
slides[0]['title'] = "Content One";
slides[0]['body'] = "Here is a little bit of useful information for you to read.";
slides[0]['link-text'] = "READ MORE...";
slides[0]['URL'] = "/go/somewhere";
slides[1]['title'] = "Content Two";
slides[1]['body'] = "This is different information for you to read.";
slides[1]['link-text'] = "READ THIS INSTEAD...";
slides[1]['URL'] = "/go/elsewhere";
var overlayTitle;
var overlayBody;
var overlayLink;
var i = 0;
var overlayInterval = setInterval(overlaySlider(), 600);
function overlaySlider() {
if (i == 1) {
i = 0;
} else {
i++;
}
overlayTitle = slides[i]['title'];
overlayBody = slides[i]['body'];
overlayLink = '' + slides[i]['link-text'] + '';
$("#hvoTitle").fadeOut()(400, function() {
$(this).html(overlayTitle).fadeIn();
});
$("#hvoBody").fadeOut()(400, function() {
$(this).html(overlayBody).fadeIn();
});
$("#hvoLink").fadeOut()(400, function() {
$(this).html(overlayLink).fadeIn();
});
}
Everything works until I get to the first .fadeOut, then I get an error that .fadeOut is not a function. I believe it should be in the version of the library I am using. (full, not slim).
Here is a fiddle I am trying to get working:
https://jsfiddle.net/529to1w5/41/
Problem
fadeOut()(
Solution
fadeout(
Simple syntax error, glad to help.

Phantomjs update values of var?

I have the below phantomjs program where the website contains a drop down list ddlLevel3
var page = require('webpage').create();
page.onConsoleMessage = function(str) {
console.log(str);
}
var z=0;
var z_l=0;
var op1='#ddlDivision'
var op2='#ddlLevel1'
var op3='#ddlLevel2'
var op4='#ddlLevel3'
function selectOption(selector, optionIndex) {
page.evaluate(function(selector, optionIndex){
var op4='#ddlLevel3'
var sel = document.querySelector(selector);
var sel4 = document.querySelector(op4);
sel.selectedIndex = optionIndex;
var event = document.createEvent("UIEvents"); // See update below
event.initUIEvent("change", true, false);
sel.dispatchEvent(event);
this.dispatchEvent(event);
z_l=sel4.length;
console.log("len: "sel4.length+" "+z_l);
}, selector, optionIndex);
}
page.open(...{
function loop4 () {
selectOption(op4,z);
window.setTimeout(function () {
go();
z++;
if (z < z_l) {
loop4();
}
}, 3000);
}
loop4();
});
I am trying to run loop4(). But the value of z_l is not changing from '0'.
In line console.log("len: "sel4.length+" "+z_l); Here values is proper.
But its not reflected back in loop4() in if (z < z_l), and remains 0 always.
What am I doing wrong?
I I wanted to get the value of z_l updated.I just need to use page.evaluate and assign it to z_l as below. Just made these changes in loop4().
function loop4 () {
var z_l = page.evaluate(function() {
var op4='#ddlLevel3'
return document.querySelector(op4)
});
selectOption(op4,z);
.
.
.
}

Jquery: $.each() returns value then ends

I have jQuery code to resize several Iframes based on the container they are in. When I did this without the .each() operator All of the iframes used the same div to base their size off of. With .each() the operator runs as evidenced by an alert but does not continue down the function.
Codepen: https://codepen.io/bjackson2016/pen/oLQopy?editors=0010
$(document).ready(function(){
function resize() {
var elements = $('.resize');
var eachElement = $.makeArray(elements);
alert(eachElement);
$.each(eachElement, function(index, value) {
alert(index + " " + value);
var multi = value.data('wfactor');
alert(multi);
var ratio = value.data('ratio');
alert(ratio);
var minX = value.data('minw');
alert(minX);
var minY = value.data('minh');
alert(minY);
var ruler = value.siblings('.widthTest');
alert(ruler);
var pWidth = ruler.width();
alert(pWidth);
var adjWidth = pWidth * multi;
alert(adjWidth);
var eHeight = (Math.round(ratio * adjWidth));
alert(eHeight);
var unadjHeight = Math.round(ratio * pWidth);
alert(unadjHeight);
var eWidth = (Math.round(adjWidth));
alert(eWidth);
if (eHeight < minY) {
$(this).height(minY);
alert('changed height');
} else {
value.height(eHeight);
alert('normal height');
}
if (eWidth < minX) {
value.css('width', pWidth).css('height', unadjHeight);
alert('changed width');
} else {
value.width(eWidth);
alert('kept width');
}
});
}
resize();
$(window).resize(function() {
resize();
});
});
The problem is that there is no value.data().
data() is a jQuery function, and iterating with $.each unwraps the elements, so you're trying to call data() on a native DOM node
$.each(eachElement, function(index, value) {
// value is not a jQuery object here, you'd have to do
var elem = $(value); // where you wrap it again.
});
Try instead
$(document).ready(function() {
$(window).on('resize', resize).trigger('resize');
function resize() {
$('.resize').each(function(index, element) {
var elem = $(element);
var multi = elem.data('wfactor'),
ratio = elem.data('ratio'),
... etc
});
}
});

Using each() method to animate typing of code

I am trying to use JQuery's each() method to animate typing on multiple blocks of code, but I keep getting this error:
Uncaught TypeError: Cannot call method 'createDocumentFragment' of undefined
Check out some example code in this Fiddle...
And for your convenience, the JS is listed below:
$('.typeanimator').each(function(index) {
console.log(index);
var codeBlock = $(this).text();
var done;
var blockLength = codeBlock.length;
var charCounter = 0;
$(this).text('|');
(function typeAnimator() {
var typingSimulator = Math.round(Math.random() * (200));
done = setTimeout(function() {
console.log("Le print.");
charCounter++;
var typeSection = codeBlock.substring(0, charCounter);
$(this).text(typeSection + '|');
typeAnimator();
if (charCounter == blockLength) {
$(this).text($(this).text().slice(0, -1));
clearTimeout(done);
}
}, typingSimulator);
}());
});
The problem is in the use of $(this) inside the typeAnimator function. You are actually want to refer the this from the parent function but instead you are getting a totally different this. So, use a temporary variable to store the $(this)
$('.typeanimator').each(function(index) {
...
var self = $(this);
self.text('|');
(function typeAnimator() {
var typingSimulator = Math.round(Math.random() * (200));
done = setTimeout(function() {
...
self.text(typeSection + '|');
typeAnimator();
if (charCounter == blockLength) {
self.text(self.text().slice(0, -1));
clearTimeout(done);
}
}, typingSimulator);
}());
});
Updated fiddle
$('.typeanimator').each(function(index, current) {
console.log(index);
var codeBlock = $(current).text();
var done;
var blockLength = codeBlock.length;
var charCounter = 0;
$(current).text('|');
(function typeAnimator(context) {
var typingSimulator = Math.round(Math.random() * (200));
done = setTimeout(function() {
console.log("Le print.");
charCounter++;
var typeSection = codeBlock.substring(0, charCounter);
$(context).text(typeSection + '|');
typeAnimator(context);
if (charCounter == blockLength) {
$(context).text($(context).text().slice(0, -1));
clearTimeout(done);
}
}, typingSimulator);
}(current));
});
This should work, always remember that javascript is really picky about the context when using 'this'. As well .each() has nifty parameter of current item :) Gl, and good code.

Titanium : Attach objects/variables with a view

I am creating some views in a loop iterating over list of objects. Now I want to register event with each view, which does something on the current object of the list.
for (var vs = 1; vs < 4; vs++) {
iMovie = moviesList[vs];
if (!iMovie) {
break;
}
var loopView = Ti.UI.createView({
....
});
loopView.addEventListener("click", function(e) {
var mv = iMovie;
Ti.API.info("Movie: " + mv);
if (mv) {
// do something
}
});
}
This code is not working, the log which is printed is : Movie: undefined.
So my question is how I can use the loop variable in the event listener?
Try the following code
var loopView - [];
var iMovie;
for (var vs = 1; vs < 4; vs++) {
iMovie = moviesList[vs];
if (!iMovie) {
break;
}
loopView[vs] = Ti.UI.createView({
_iMovie : iMovie
});
loopView[vs].addEventListener("click", function(e) {
var mv = e.source._iMovie;
Ti.API.info("Movie: " + mv);
if (mv) {
// do something
}
});
}
Well, first I'll start that what you are doing in the code above could potentially cause a memory leak since you are holding a reference to the iMovie variable.
what you should try doing is:
var mv = e.source;
this will return the source object that fired the click event.

Categories

Resources