I have some JavaScript that currently looks for _target and anchors to target.
I wish to change it to look for a array [_target_index] however I cant seem to get this to work every time I try I get errors.
When I console.log my array I get my expected array output.
Can someone help me addend y code to accept the array rather than just _target ?
What I tried
_scrollTopPixels = (anchorElementArray [_target_index]).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
console error
Uncaught TypeError: anchorElementArray[_target_index].offset is not a function
My full code
_pdpNavigationScrollTo = function () {
_pdpLink.on('click', function (e) {
e.preventDefault();
var _fixedNavHeight, _target, _target_index, _scrollTopPixels;
if (!INFORMA.global.device.isDesktop) {
_target = $(this).data('target');
_target_index = $(this).data('target-index');
$('#pdp-sections').slideUp();
_pdpNavigationHeight = $('#pdp-navigation .nav-pdp-nondesktop').outerHeight();
if (!_pdpFixed)
_pdpSectionsHeight = $('#pdp-sections').height();
else
_pdpSectionsHeight = 0;
_fixedNavHeight = _navHeightMobile;
var anchorElementArray = $("[id='" + _target + "']");
console.log(anchorElementArray[_target_index]);
if (anchorElementArray.length >= [_target_index]) {
//_scrollTopPixels = $("#" + _target).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
_scrollTopPixels = (anchorElementArray [_target_index]).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
} else {
_scrollTopPixels = $("#" + _target).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
}
$('html, body').stop().animate({
scrollTop: _scrollTopPixels
}, 1000);
} else {
_target = $(this).data('target');
$('#pdp-navigation li').removeClass('selected');
$('#pdp-navigation li').addClass('select-options');
_pdpNavigationHeight = _pdpNavigation.height();
_fixedNavHeight = _navHeight;
_scrollTopPixels = $("#" + _target).offset().top - (_fixedNavHeight + _pdpNavigationHeight);
$('html, body').stop().animate({
scrollTop: _scrollTopPixels
}, 1000);
}
})
};
The jQuery method offset requires a jQuery object to access it, as such you need to change;
(anchorElementArray[_target_index]).offset().top
to
$(anchorElementArray[_target_index]).offset().top
Related
I've been trying to fix this for hours now and just can't get it to work. I'm retrieving the name of every activity in the database and for every row it recreates this script with the correct data.
<script>var count = 1;</script>
#foreach($data as $scriptdata)
<script>
eval("var id" + count + " = '{{$scriptdata->activiteit}}';");
eval("var clas" + count + " = '{{$scriptdata->activiteit}}';");
eval("var id" + count + " = id" + count .replace(/[^a-zA-Z]/g, '') + ";");
eval("var clas" + count + " = clas" + count .replace(/[^a-zA-Z]/g, '') + ";");
$("#" + id1).mouseenter(function(event) {
console.log("clicked.");
var target = $('.' + clas1);
if( target.length ) {
$('html, body').animate({
scrollTop: target.offset().top-120
}, 1000);
}
});
count++
</script>
#endforeach
the variables become dynamic without any trouble, I just can't get that .replace to do it's job.
anyone?:p
Either output the variables from the serverside code, use Objects with bracket notation, use common classes so there is no need to have individual selections, or make it so the variables are not in global scope.
Make it so the variable are not in global scope
(function() {
var id = '{{$scriptdata->activiteit}}';
var clas = '{{$scriptdata->activiteit}}';
$("#" + id).mouseenter(function(event) {
var target = $('.' + clas);
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top - 120
}, 1000);
}
});
}());
Now you do not have to worry about count.
If you go to Google Alert website while you are not login with your Google Account you would have a chance of creating an alert send to your Yahoo account for example.
I am going create an alert using PhantomJS. Then I would need to click on the CREATE ALERT button. I need to do that using JavaScript. But it seems that PhantomJS cannot click on this button!
I have even tried to click on this button through Google Console but I could not.
I have used three different ways for clicking on the button which nothing works. Can someone help me to click on the CREATE ALERT button?
javascript:if(!window.jQuery||confirm('Overwrite\x20current\x20version?\x20v'+jQuery.fn.jquery))(function(d,s){s=d.createElement('script');s.src='https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.js';(d.head||d.documentElement).appendChild(s)})(document);
var inputOne = document.getElementsByTagName('input')[0];
inputOne.value = "testAlert";
var inputTwo = document.getElementsByTagName('input')[1];
inputTwo.value = "test#yahoo.com";
var button = document.getElementById('create_alert');
//1.
//button.click();
//2.
//$(button).trigger('click');
//$(button).trigger('change');
//3.
var event = document.createEvent("MouseEvents");
event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
button.dispatchEvent(event);
And I am using following code in PhantomJS
phantom.injectJs("functions/jquery.js");
var page = require('webpage').create();
var load, contoroller;
var numOfActions = 1;
var clicked = false;
var initialURL = "https://www.google.com/alerts";
page.open(initialURL, function(status) {
load = true;
});
page.onLoadFinished = function(status)
{
clearInterval(contoroller);
if (clicked)
{
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}
else
{
contoroller = setInterval(function () {
if (load)
{
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
load = false;
enterQuery("test");
}
else
{
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
page.evaluate(function(){
var input = document.getElementsByTagName('input')[1];
input.value = "test#test.com";
})
click();
}
}, 5000);
}
}
function enterQuery(query)
{
page.injectJs("functions/jquery.js");
page.evaluate(function(query)
{
var box = document.getElementsByTagName('input')[0];
box.value = query;
//$(box).keypress();
}, query);
}
function click()
{
clicked = true;
clearInterval(contoroller);
var but = page.evaluate(function(){
var button = document.getElementById('create_alert');
//var event = document.createEvent("MouseEvents");
//event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
//button.dispatchEvent(event);
return button;
})
page.sendEvent('click', but);
window.setTimeout(function () {
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}, 5000);
}
It seems that I need to first hover the mouse on the button. When you hover the mouse you will see that the class attribute of the element changes. I have tried $(button).trigger('mouseover') but after that the class attribute did not change. How can I trigger mouseover on this element?
There are two problems with your code: typing and clicking.
When you set the value of an input field directly, none of the input event handlers are called. You could use the native page.sendEvent("keypress", keys) which types keys as if a user would type them, so all event handlers will be triggered. Since the function doesn't know where to type to, you need to focus on the element first:
page.evaluate(function(selector){
document.querySelector(selector).focus();
}, selector);
page.sendEvent("keypress", query);
You can solve the clicking also with page.sendEvent("click", posx, posy). Now the challenge becomes to find out the position of the elements on the page. This answer provides a jQuery way of solving this:
page.injectJs("jquery.min.js");
var rect = page.evaluate(function(selector) {
return $(selector)[0].getBoundingClientRect();
}, selector);
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);
This is your full script that works as expected:
var page = require('webpage').create();
var load, contoroller;
var numOfActions = 1;
var clicked = false;
var initialURL = "https://www.google.com/alerts";
page.open(initialURL, function(status) {
load = true;
});
page.onLoadFinished = function(status)
{
clearInterval(contoroller);
if (clicked)
{
console.log("1| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}
else
{
contoroller = setInterval(function () {
if (load)
{
console.log("2| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
load = false;
enter("input", "test"); // very first input
}
else
{
console.log("3| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
enter("input.email_input", "test#test.com");
setTimeout(function(){
click("#create_alert");
}, 500);
}
}, 5000);
}
}
function enter(selector, query)
{
page.evaluate(function(selector){
document.querySelector(selector).focus();
}, selector);
page.sendEvent("keypress", query);
}
function click(selector)
{
clicked = true;
clearInterval(contoroller);
page.injectJs("functions/jquery.js");
var rect = page.evaluate(function(selector) {
return $(selector)[0].getBoundingClientRect();
}, selector);
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);
window.setTimeout(function () {
console.log("4| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}, 5000);
}
this code works:
var myElement = document.getElementById("red");
setInterval(function() {
console.log("Left:" + myElement.offsetLeft + "px | Top:" + myElement.offsetTop + "px");
}, 1000);
This prints out the position(x, y) every second
But If I try and change it to using objects:
function Enemy(id){
this.id = getElementById(id);
this.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + this.id.offsetLeft + "px | Top:" + this.id.offsetTop + "px");
}, 1000);
}
}
$(document).ready(function(){
var enemy = new Enemy("red");
enemy.getCoordinates();
});
It prints out nothing - and I can't see where my mistake is.
In a setInterval or setTimeout (or any event handler like onclick) the this variable refers to the global object. In a browser that's window.
In modern browsers you can do this:
setInterval((function() {
console.log("Left:" + that.id.offsetLeft + "px");
}).bind(this), 1000); // <------- bind
Otherwise all other solutions are basically similar to your first piece of code.
Note that there is an implementation of bind() in pure js from Mozilla that can be ported to older browsers. Search for it on MDN.
The problem is that the value of "this" is changing within the setInterval. The fix is to change it to:
function Enemy(id){
this.id = document.getElementById(id);
var self = this;
this.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + self.id.offsetLeft + "px | Top:" + self.id.offsetTop + "px");
}, 1000);
}
}
function Enemy(id){
this.id = document.getElementById(id);
this.getCoordinates = function(){
var element = this.id;
setInterval(function() {
console.log("Left:" + element.offsetLeft + "px | Top:" + element.offsetTop + "px");
}, 1000);
}
}
$(document).ready(function(){
var enemy = new Enemy("red");
enemy.getCoordinates();
});
As slebetman said, the 'this' variable is not what you expected. Try saving it in a 'that' variable, which can be accessed in different scopes.
function Enemy(id){
var that = this; // reference to 'this' that can be used in other scopes
that.id = document.getElementById(id);
that.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + that.id.offsetLeft + "px | Top:" + that.id.offsetTop + "px");
}, 1000);
}
return that;
}
After replacign the location with new parameters, the page after loaded doesn't get the paramaters value, despite there are values in the parameters
the used code is :
function getURLParameter(name) {
return
decodeURI((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
}
$(document).ready(function () {
$(".sub").slideUp();
var div = getURLParameter("div");
var ddl = getURLParameter("ddl");
alert(div);
// alert("ManageTrainingNeeds.aspx?div=" + div + "&ddl=" + ddl);
// $("#" + div).slideDown();
// $("#ddlObjectiveGroup").val("'" + ddl + "'");
});
$(".btnAddSub").live("click", function () {
var diva = $(this).parent().parent().parent().parent().parent().parent().attr("id");
var ddl = $("#ddlObjectiveGroup option:selected").val();
window.location.replace("ManageTrainingNeeds.aspx?div=" + diva + "&ddl=" + ddl);
});
this alert(div); return undefined.. despite the div vairable in click event has a value
Try encoding the parameters and also canceling the default action in the click event:
function getURLParameter(name) {
return decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
}
$(document).ready(function () {
var div = getURLParameter('div');
var ddl = getURLParameter('ddl');
alert(div + ' ' + ddl);
});
$('.btnAddSub').live('click', function () {
var diva = encodeURIComponent($(this).parent().parent().parent().parent().parent().parent().attr('id'));
var ddl = encodeURIComponent($('#ddlObjectiveGroup').val());
window.location.replace('/ManageTrainingNeeds.aspx?div=' + diva + '&ddl=' + ddl);
return false;
});
Instead of fiddling with the URLs yourself, you could use a library for the job - such as URI.js. (sorry for the self-promo)
$(document).ready(function () {
var search = URI().search(true);
alert(search.div + ' ' + search.ddl);
});
$('.btnAddSub').live('click', function (e) {
var uri = URI('/ManageTrainingNeeds.aspx');
uri.search({
diva: $(this).parent().parent().parent().parent().parent().parent().attr('id'),
ddl: $('#ddlObjectiveGroup').val()
});
window.location.href = uri.toString();
e.preventDefault();
});
Current function:
function SetPopup() {
x$('body').setStyle('overflow', 'hidden');
x$('#divOne').setStyle('height', document.body.offsetHeight + 'px');
x$('#divOne').setStyle('width', 100 + '%');
x$('#divOne').setStyle('display', 'block');
}
What I would like to do is change this function such that 'divOne' would be read-in as a parameter like this:
function SetPopup(string x) {
x$('body').setStyle('overflow', 'hidden');
x$('#x').setStyle('height', document.body.offsetHeight + 'px');
x$('#x').setStyle('width', 100 + '%');
x$('#x').setStyle('display', 'block');
}
But obviously that doesnt work.
What would I need to do to include x where I have optimistically placed it in the bottom function?
Try this:
function SetPopup(elem) {
x$('body').setStyle('overflow', 'hidden');
x$('#' + elem).setStyle('height', document.body.offsetHeight + 'px');
x$('#' + elem).setStyle('width', 100 + '%');
x$('#' + elem).setStyle('display', 'block');
}
function SetPopup(x) {
x$('body').setStyle('overflow', 'hidden');
x$('#'+x).setStyle('height', document.body.offsetHeight + 'px');
x$('#'+x).setStyle('width', 100 + '%');
x$('#'+x).setStyle('display', 'block');
}