How can I prevent my javascript from polling websites too fast? - javascript

I made this website quite a while ago for the purpose of grabbing random puu.sh images and displaying them. Also a warning, the content this site shows is user generated, and I can not guarantee it is SFW.
https://dl.dropboxusercontent.com/s/dlb1uke5udz8kwy/index.html
I just started looking at it again, and it appears it has some serious bugs with the systems it uses to gather content. How can I change my javascript so that it doesn't spam out puu.sh, and make it refuse connections?
Here is the code:
var currentThumb = 0;
function getImgUrl()
{
var text = (Math.round(Math.random() * 9)).toString();
//var text = '3T';
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for(var i=0; i < 4; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return 'http://puu.sh/' + text;
}
function open_in_new_tab(url)
{
var win=window.open(url, '_blank');
win.focus();
}
function getImages()
{
//var width = window.innerWidth;
var images = 10;
for(var i = 0;i < images;i++)
{
var url = getImgUrl();
document.getElementById('thumbs').innerHTML += '<img class="thumb" id="thumb' + i + '" src=' + url + '>';
if(i == 0)
{
document.getElementById('fullimage').innerHTML = '<img id="big" src=' + url + '>';
$('#thumb' + currentThumb).css('border','2px solid white');
}
}
}
function refreshImages()
{
var images = 10;
for(var i = 0;i < images;i++)
{
var url = getImgUrl();
$('#thumb' + i).attr('src',url);
}
$('img').css('border','');
$('#thumb' + currentThumb).css('border','2px solid white');
}
function resize()
{
var width = $(window).width();
var height = $(window).height();
$('#fullimage img').css('max-width',width);
$('#fullimage img').css('max-height',height - 87);
}
function setBig()
{
$('#big').attr('src',($('#thumb' + currentThumb).attr('src')));
$('img').css('border','');
$('#thumb' + currentThumb).css('border','2px solid white');
resize();
}
getImages();
$('img').error(function() {
$(this).attr('src',getImgUrl());
setBig();
});
$('#thumbs img').click(function() {
$('#fullimage').html('<img id="big" src=' + $(this).attr('src') + '>');
currentThumb = parseInt($(this).attr("id").match(/\d+/));
$('img').css('border','');
$(this).css('border','2px solid white');
resize();
});
$('#fullimage').click(function() {
open_in_new_tab($('#fullimage img').attr('src'));
});
$(window).resize(function() {
resize();
});
$(document).ready(function() {
resize();
});
The problem most likely lies in
$('img').error(function() {
$(this).attr('src',getImgUrl());
setBig();
});

Your main problem seems to be that you are spamming the servers when you hit a 404 because of the error handler. Try something like
$('img').error(function() {
var _this = this;
setTimeout(function () {
$(_this).attr('src',getImgUrl());
setBig();
}, 500); // Whatever timeout is good not to spam
});

Untested, but try this new getImages() function (replace the old one)
function getImages(images)
{
if (!images) {
document.getElementById('fullimage').innerHTML = '<img id="big" src=' + url + '>';
$('#thumb' + currentThumb).css('border','2px solid white');
images = 1;
}
document.getElementById('thumbs').innerHTML += '<img class="thumb" id="thumb' + i + '" src=' + url + '>';
images++;
if (images < 10) {
setTimeout(function() { getImages(images); }, 25);
}
}
It will be called 9 times, but the first time it should do what you were doing at i = 0 and 1; It will be fired every 25ms regardless of whether images have loaded yet or not. Increase that number (25) to slow it down.

Related

Append div with interval in Jquery

Hi I need help regarding appending div while using 2 types of speed interval via 2 loops
Here is my sample code
<script type="text/javascript">
$(document).ready(function() {
for (var i = 0; i <= 300; i++) {
$(".wrapper").append("<div class='item' id='" + i + "'>" + i + "</div>");
if (i==300)
{
//I need this for loop to slow down my
//interval so div will display slower compared to the first 300
for (var i = 300; i <= 500; i++) {
$(".wrapper").append("<div class='item' id='" + i + "'>" + i + "</div>");
};
}
};
});
var step = 0;
function hideItemFunc() {
var interval = setInterval(function() {
$("#" + step).animate({
opacity: 1
}, 50);
step += 1;
}, 50);
}
</script>
I've done it using two interval()... But one function.
And use some variables to control iterations and delays (or speed).
Look how it slows when it reaches 300.
$(document).ready(function(){
var intervalSpeed = 20 // in milliseconds
var ratio_1=1; // 1 is 100% of the above delay
var ratio_2=10;
var animateSpeed=300; // in milliseconds
var i=0;
function twoSpeedInterval(){
// Append.
$(".wrapper").prepend("<div class='item' id='" + i + "'>" + i + "</div>");
// Animate.
$("#" + i).animate({opacity: 1},animateSpeed);
// Condition to slow or stop.
if (i==300){
clearInterval(interval_1); // Stop the 1st interval.
// Start 2nd interval.
interval_2 = setInterval(twoSpeedInterval,intervalSpeed*ratio_2);
animateSpeed = animateSpeed*ratio_2;
}
if (i==500){
clearInterval(interval_2); // Stop the 2nd interval.
}
i++;
}
// Start 1st interval.
var interval_1 = setInterval(twoSpeedInterval,intervalSpeed*ratio_1);
var interval_2;
});
.item{
opacity:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper"></div>
Just having a bit fun with it, I used jQuery .queue() for this and made i a global variable.
var i = 0;
$(document).ready(function() {
for (i = 0; i <= 300; i++) {
$(".wrapper").append("<div class='item' id='" + i + "'>" + i + "</div>");
}
for (j = 300; j <= 500; j++) {
$(".wrapper").delay(1000).queue(function(next) {
$(this).append("<div class='item' id='" + i + "'>" + i + "</div>");
i++;
next();
});
}
});
var step = 0;
function hideItemFunc() {
var interval = setInterval(function() {
$("#" + step).animate({
opacity: 1
}, 50);
step += 1;
}, 50);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="wrapper"></div>
As commented before,
You will have to use recursion with timer to add delay in loops.
You can check this JSFiddle as a sample or use following snippet to debug:
Note: Please note the difference in the delay for every value where count%3 === 0.
var count = 0;
function animate(delay) {
setTimeout(function() {
var div = $('<div class="tile" style="display: none">'+count+'</div>');
$('.content').append(div)
div.fadeIn()
if (++count < 10) {
animate(count % 3 === 0 ? 3000 : 1000)
}
}, delay || 1000)
}
animate();
.tile {
height: 40px;
margin: 5px;
border: 2px solid #ddd;
border-radius: 4px;
background: #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="content"></div>

Facebook Graph API get original picture size not working

Need some help to get a normal or larger image from posts using the Facebook Graph API, at the moment it only gives a 130 x 130 px image in the object.
function fbFetch() {
var access_token = "";
var url = "https://graph.facebook.com/?ids=intel&fields=posts.limit(5){message,created_time,picture.type(normal)}&access_token=' + access_token;
$.getJSON(url, function(response) {
var messages = [];
Object.getOwnPropertyNames(response).forEach(function(page, idx, array) {
response[page].posts.data.forEach(function(post, idx, array) {
messages.push(post);
});
});
function compare(a, b) {
if (a.created_time < b.created_time)
return -1;
if (a.created_time > b.created_time)
return 1;
return 0;
}
var html = "<ul>";
$.each(messages.sort(compare), function(i, fb) {
if (typeof fb.picture != "undefined") {
html += "<li>" + fb.message + "</br>" + '<img SRC="' + fb.picture + '">' + "</br>" + fb.created_time + "</li></br>";
} else {
html += "<li>" + fb.message + "</br>" + fb.created_time + "</li></br>";
}
});
html += "</ul>";
$('.facebookfeed').html(html);
});
}
fbFetch();
<div class="facebookfeed"></div>
Fiddle here: http://jsfiddle.net/6fhq3dat/17/
use full_picture instead of picture
var url = "https://graph.facebook.com/?ids=intel&fields=posts.limit(3){message,created_time,full_picture}&access_token=" + access_token;
demo

Create alert in Google Alert using PhantomJS

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);
}

Fetching data in chunks

I have a carousel which I have built, which gets a list of products from my API and then each product is created as a slide in a carousel. This is all working perfectly.
When the current slide becomes active I download all of the images for that slide and populate the slide. This data also comes from the API.
What I want to do is have a speedier way to do this. At the moment I am loading these one at a time as they become "active". Ideally I want to be able to load 5 in straight away. So that the start of the array (0) is in the center of the loading array. Then when a user navigates left or right through the carousel I want to call in the next one forward or back.
So far my code is working so that when a slide is active it will have all images loaded, the code I have used for this is here:
module.carousel = (function(){
"use strict";
var exports = {};
exports.details = {};
exports.init = function (options) {
var defaultOptions = {
speed: 1500,
next: {},
back: {},
target: {}
};
if(options == null) options = {};
options = $.extend(defaultOptions, options);
exports.details.targetLength = options.target.children('li').length - 1;
exports.details.position = 0;
exports.details.products = options.target.children('li');
options.target.children('li:nth-child(' + (exports.details.position + 1) + ')').addClass('active');
exports.details.position += 1;
getMedia();
function removeActive() {
options.target.children('li.active').removeClass('active');
}
function addActive() {
options.target.children('li:nth-child(' + (exports.details.position) + ')').addClass('active');
}
function nextItem() {
if(exports.details.position >= exports.details.targetLength + 1) {
exports.details.position = 1;
} else {
exports.details.position += 1;
}
removeActive();
addActive();
getMedia();
}
function getMedia() {
var id = options.target.children('li.active').attr('data-id');
$.ajax({
url: "/beta/api/v1/watches/id/" + id + "/media",
dataType: "json",
async: false,
success: function(data) {
var mediaItems = "";
for(var x = 0, tot = data.length; x < tot; x++) {
mediaItems += "<div class='box'><img src='" + data[x] + "' class='intro-image'></div>";
}
$('#' + id + '_media').html(mediaItems);
}
});
}
function previousItem() {
if(exports.details.position === 1) {
exports.details.position = exports.details.targetLength + 1;
} else {
exports.details.position -= 1;
}
removeActive();
addActive();
getMedia();
}
$('html, body').on('swipeleft', function(event) {
event.stopPropagation();
nextItem();
});
$('html, body').on('swiperight', function(event) {
event.stopPropagation();
previousItem();
});
};
return exports;
}());
That is how my carousel works, and this is how I start it :
$(document).ready(function() {
$.getJSON("/beta/api/v1/watches", function(data) {
var productArray = [];
for(var i = 0, tot = data.length; i < tot; i++){
var productItem = "";
if(i === 0) {
productItem += "<li data-id='" + data[i].id + "' class='product active'>";
} else {
productItem += "<li data-id='" + data[i].id + "' class='product'>";
}
productItem += "<div class='product-header'><h3>"
+ data[i].name + "</h3><h3>" + data[i].case_finish
+ "</h3><h3>" + data[i].id + "</h3><h3>£" + data[i].price + "</h3></div>";
var product = data[i];
productItem += "<div id='" + data[i].id + "_media'></div>";
productItem += "</li>";
productArray.push(productItem);
}
$('#carousel').html(productArray);
$(document).on('swipeleft swiperight', function(event) {
event.stopImmediatePropagation();
});
module.carousel.init({
target: $('#carousel'),
next: $('#next'),
back: $('#back')
});
});
});

JS - Clicking on thumbnail will display the right image

In javascript only, no librairies, I am trying to create a carousel.
I have 2 items:
One div for the main image and the caption (the images and captions are loaded dynamically one by one after a setTimeOut)
Another one with a list of thumbnails. I'd like to upon clicking on a thumbnail display the right image and caption.
Here is the html:
<div class="slide">
<h2 id="description" class="title">La Slide #0</h2>
<img id="largeImg" class="car" src="images/0.jpg" width="658" height="267" alt="" />
</div>
<ul id="thumbs">
</ul>
and here are my functions:
// Function to display the images and the captions switching from one to the other
function slideshowAuto() {
document.querySelector('div.slide').id = 'slide-' + i;
var caption = document.getElementById("description");
caption.innerHTML = data.slides[i].slide_name;
var img= document.getElementById("largeImg");
img.src = data.slides[i].image_src;
if (i < totalSlides) {
i++;
} else {
i = 0;
}
setTimeout("slideshowAuto()",3000);
}
// Function to display the images and the captions swaping from one to the other
function swapSlide() {
document.querySelector('div.slide').id = 'slide-' + i; // add an id on the current slide
var caption = document.getElementById("description");
caption.innerHTML = data.slides[i].slide_name;
var img = document.getElementById("largeImg");
img.src = data.slides[i].image_src;
if (i < totalSlides) {
i++;
} else {
i = 0;
}
setTimeout("swapSlide()",50);
}
// Function to display all the thumbnails
function displayAllThumbs() {
thumbs = document.getElementById('thumbs');
html = '';
for( i=0 ; i < totalSlides; i++) {
html += '<li><a onclick="swapSlide(slide-' + i + ')"><img src="' + data.slides[i].thumbnail_src + '" alt="' + data.slides[i].slide_name + '" title="' + data.slides[i].slide_name + '" /></a></li>';
}
thumbs.innerHTML = html;
}
My troubles:
The slide content display the last variables instead of the first one.
The clic on the thumbnails don't swap the "slide" content.
Here is a link of where I'm at...
Anyone can help me with that?
First,you used the global i which is changed to 7 by function preload and rechanged by function displayAllThumbs,So you got trouble 1.
Scond,you click function is swapSlide(slide-' + i + '),the parameter is a variable that doesn't exsits,also your swapSlide doesn't accept parameter.
Change to this will solve your problem:
function preload(images) {
if (document.images) {
var imageArray = data.slides[i].image_src;
var imageObjs = [];
var imageObj = new Image();
for(var j=0; j <= totalSlides - 1;j ++) {
imageObj.src = imageArray[j];
imageObjs.push(imageObj);
}
}
}
// Function to display the images and the captions switching from one to the other
function slideshowAuto() {
setSlide(i);
if (i < totalSlides) {
i++;
} else {
i = 0;
}
//document.getElementById('slide').style.webkitTransition = 'opacity 1s';
setTimeout("slideshowAuto()",3000);
}
// Function to display the images and the captions swaping from one to the other
function swapSlide(index) {
i=index; //change the current i
setSlide(index);
}
// Function to display all the thumbnails
function displayAllThumbs() {
thumbs = document.getElementById('thumbs');
html = '';
for( var k=0 ; k < totalSlides; k++) {
html += '<li><a onclick="swapSlide(' + k + ')"><img src="' + data.slides[k].thumbnail_src + '" alt="' + data.slides[k].slide_name + '" title="' + data.slides[k].slide_name + '" /></a></li>';
}
thumbs.innerHTML = html;
}
function setSlide(index){
document.querySelector('div.slide').id = 'slide-' +index; // add an id on the current slide
var caption = document.getElementById("description");
caption.innerHTML = data.slides[index].slide_name;
var img = document.getElementById("largeImg");
img.src = data.slides[index].image_src;
}
And can i get accepted?
I add a new function to avoid the repeat.

Categories