infinte scroll + imagesloaded + masonry on tumblr API loaded via ajax within shopify - shopify

I've been trying to make this work for a while but haven't made any progress. Not sure if I'm missing something or if it just won't work within this setup.
In short: client has a shopify site, and wants to load in images from tumblr in an infinite scroll.
I'm using the standards from DeSandro: Infinite Scroll, Masonry, ImagesLoaded, and basing the combination on this pen.
I have the tumblr feed loading in fine via tumblr API, and displayed in a masonry grid, but can't get the infinite scroll to work.
Will InfiniteScroll not work because the content is loaded in via ajax, and isn't actually on the page yet when InfiniteScroll tries to load it in? Any insight would be appreciated!
$(document).ready(function() {
// Main content container
var $container = $('#tblr_container');
$.ajax({
url: 'https://api.tumblr.com/v2/blog/xxxxxxx.tumblr.com/posts?api_key=xxxxxxx&limit={{ pagesize }}&offset={{ offset }}&callback=?',
dataType:'json',
success: function(data) {
$.each(data.response.posts, function(index,item) {
if (this['type'] === 'photo') {
var src = item.photos[0].alt_sizes[0].url;
$("#tblr_container").append('<div class="item masonry__item ' + index + '"><li><img src = "'+src+'"></li></div>');
}
});
// init Masonry
var $grid = $('#tblr_container').masonry({
itemSelector: 'none', // select none at first
columnWidth: '.grid-sizer',
gutter: 5,
percentPosition: true,
stagger: 30,
// nicer reveal transition
visibleStyle: { transform: 'translateY(0)', opacity: 1 },
hiddenStyle: { transform: 'translateY(100px)', opacity: 0 },
});
// get Masonry instance
var msnry = $grid.data('masonry');
// initial items reveal
$grid.imagesLoaded( function() {
$grid.removeClass('are-images-unloaded');
$grid.masonry( 'option', { itemSelector: '.item' });
var $items = $grid.find('.item');
$grid.masonry( 'appended', $items );
});
// init Infinte Scroll
$grid.infiniteScroll({
path: '.pagination__next',
append: '.item',
outlayer: msnry,
hideNav: '#pagination',
status: '.page-load-status',
});
}
});
Here's the link: https://negativeunderwear.com/pages/for-women
And, the link to page 2: https://negativeunderwear.com/pages/for-women?page=2&cache=false - this is .pagination__next
(FYI before clicking, it's a women's underwear site.)
Thanks!

Related

CasperJS can not trigger twitter infinite scroll

I am trying to get some information from twitter using CasperJS. And I'm stuck with infinite scroll. The thing is that even using jquery to scroll the page down nothings seems to work. Neither scrolling, neither triggering the exact event on window (smth like uiNearTheBottom) doesn't seem to help.
Interesting thing - all of these attempts work when injecting JS code via js console in FF & Chrome.
Here's the example code :
casper.thenEvaluate(function(){
$(window).trigger('uiNearTheBottom');
});
or
casper.thenEvaluate(function(){
document.body.scrollTop = document.body.scrollHeight;
});
If casper.scrollToBottom() fails you or casper.scroll_to_bottom(), then the one below will serve you:
this.page.scrollPosition = { top: this.page.scrollPosition["top"] +
document.body.scrollHeight, left: 0 };
A working example:
casper.start(url, function () {
this.wait(10000, function () {
this.page.scrollPosition = { top: this.page.scrollPosition["top"] + document.body.scrollHeight, left: 0 };
if (this.visible("div.load-more")) {
this.echo("I am here");
}
})});
It uses the underlying PhantomJS scroll found here
CasperJs is based on PhantomJS and as per below discussion no window object exist for the headless browser.
You can check the discussion here
On Twitter you can use:
casper.scrollToBottom();
casper.wait(1000, function () {
casper.capture("loadedContent.png");
});
But if you include jQuery... , the above code won't work!
var casper = require('casper').create({
clientScripts: [
'jquery-1.11.0.min.js'
]
});
The script injection blocks Twitter's infinite scroll from loading content. On BoingBoing.net, CasperJS scrollToBottom() works with jQuery without blocking. It really depends on the site.
However, you can inject jQuery after the content has loaded.
casper.scrollToBottom();
casper.wait(1000, function () {
casper.capture("loadedContent.png");
// Inject client-side jQuery library
casper.options.clientScripts.push("jquery.js");
// And use like so...
var height = casper.evaluate(function () {
return $(document).height();
});
});
I have adopted this from a previous answer
var iterations = 5; //amount of pages to go through
var timeToWait = 2000; //time to wait in milliseconds
var last;
var list = [];
for (i = 0; i <= iterations; i++) {
list.push(i);
}
//evaluate this in the browser context and pass the timer back to casperjs
casper.thenEvaluate(function(iters, waitTime) {
window.x = 0;
var intervalID = setInterval(function() {
console.log("Using setInternal " + window.x);
window.scrollTo(0, document.body.scrollHeight);
if (++window.x === iters) {
window.clearInterval(intervalID);
}
}, waitTime);
}, iterations, timeToWait);
casper.each(list, function(self, i) {
self.wait(timeToWait, function() {
last = i;
this.echo('Using this.wait ' + i);
});
});
casper.waitFor(function() {
return (last === list[list.length - 1] && iterations === this.getGlobal('x'));
}, function() {
this.echo('All done.')
});
Essentially what happens is I enter the page context, scroll to the bottom, and then wait 2 seconds for the content to load. Obviously I would have liked to use repeated applications of casper.scrollToBottom() or something more sophisticated, but the loading time wasn't allowing me to make this happen.

ArcGis javascript api 3.5 how to set visibility of a feature layer

i am using ArcGis javascript api 3.5 and my code is
map = new esri.Map("mapDiv", {
basemap: "streets",
center: [-112.07102547942392, 46.75909704205151],
zoom: 12,
slider: false,
infoWindow: infoWindow
});
var featureLayer = new esri.layers.FeatureLayer("http:/abc/arcgis/rest/services/MTARNG/MapServer/1", {
mode: esri.layers.FeatureLayer.MODE_SNAPSHOT,
infoTemplate: templateFuze,
outFields: ["*"]
});
var featureLayer1 = new esri.layers.FeatureLayer("http://abc/arcgis/rest/services/MTARNG/MapServer/0", {
mode: esri.layers.FeatureLayer.MODE_SNAPSHOT,
infoTemplate: templateParcel,
outFields: ["*"]
});
var featureLayer2 = new esri.layers.FeatureLayer("http://abc/arcgis/rest/services/MTARNG/MapServer/2", {
mode: esri.layers.FeatureLayer.MODE_SNAPSHOT,
infoTemplate: templateGrid,
outFields: ["*"]
});
Ext.create('Ext.form.Panel', {
width: 400,
height: 600,
bodyPadding: 10,
renderTo: Ext.get('LayerDiv'),
items: [{
xtype: 'checkboxgroup',
columns: 1,
vertical: true,
items: layerInfo,
listeners: {
change: {
fn: function (checkbox, checked) {
for (var i = 0; i < checkbox.items.items.length; i++) {
if (checkbox.items.items[i].checked) {
//visible true checkbox.items.items[0].boxLabel
}
else {
//visible false
}
}
}
}
}
}]
});
});
So i am trying to set the visibilty of the layer but i am not able to do. after that how to refresh the map ?
I got some function but it is working e.g.- visibleAtMapScale = false,
defaultVisibility = false and for refreshing i got only map.resize=true;
What else i can try to achive this functionality.
You can change the visibility of an layer using the hide() and show() functions - FeatureLayer inherits them from GraphicsLayuer (Which inherits them from Layer). So in your example, given featureLayer is a global variable it should be in scope when the event fires so you could just do:
featureLayer.hide();
and
featureLayer.show();
You don't need to refresh the map, it will happen automatically.
Simon
When creating a new FeatureLayer, you can specify the default visibility using the optional parameters. The default is true.
var featureLayer = new esri.layers.FeatureLayer("http:/.../MapServer/1",
{visible:false}
});
To set the visibility of the existing layer, you can use the setVisibility() method.
featureLayer.setVisibility(false);
If you want to enable intellisense support in Visual Studio you can download and reference the code assist plugin from the Esri website. There is a help page about it here with links to the various versions supported and how to use it from VS.
If you just want to get the VS2012 version for v3.5 of the JS API it is here and to reference it:
If working in an HTML file, add a script tag to add a reference to the code assist
<script type='text/javascript' src='path_to_vsdoc.js'></script>
If working in a JavaScript file, add a reference directive to the VSDoc file:
/// <reference path="~/Scripts/esri-jsapi-vsdoc.js" />

Google Maps KML Layer won't Zoom

I have an embedded Google Map using API V3 but I cannot get it default Zoom to anything other than 1.
My JS in the head is:
var map1;
var src1 = 'https://latitude.google.com/latitude/apps/badge/api?user=8963899225283336226&type=kml';
function initialize1() {
map1 = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 7,
mapTypeId: google.maps.MapTypeId.TERRAIN
});
loadKmlLayer1(src1, map1);
}
google.maps.event.addDomListener(window, 'load', initialize1);
function loadKmlLayer1(src1, map1) {
var kmlLayer1 = new google.maps.KmlLayer(src1, {
suppressInfoWindows: false,
clickable: true,
preserveViewport: false,
map: map1
});
}
The HTML is just the map-canvas div, nothing else. Looking at some of the threads on here it look like its something to do with detecting the viewport and resetting the bounds.
I found a thread that suggested adding something like:
google.maps.event.addListener(kmlLayer1, 'defaultviewport_changed', function() {
var bounds = kmlLayer1.getDefaultViewport();
map.setCenter(bounds.getCenter());
})
but it made no difference. I'm by no means a JS expert and whilst I mostly understand what is going on in most of the code above, I'm not advanced enough to improvise or even understand where it should be placed.
Thanks Molle.
I enhanced to this and it works:
google.maps.event.addListener(kmlLayer, 'status_changed', function () {
console.log('kml loaded:');
google.maps.event.addListenerOnce(map, 'zoom_changed', function () {
console.log('zoom_changed:');
map.setZoom(7);
map.setCenter(new google.maps.LatLng(0, 0));
});
});
The API will set the viewport to contain all KML-features, what will override the zoom-settings.
Reset the zoom once the zoom has changed(as it does when the KML-Layer has been loaded)
google.maps.event.addListenerOnce(map1, 'zoom_changed', function() {
this.setZoom(7);
})

3.5 Wordpress media uploader manual implementation

I'm having problems to understand how to implement new WP media uploader into my theme options page. Is there a documentation on how to do this or some explanation what-so-ever? I have seen couple of samples of how to do this but none of them has any good explanation about their code. Is there list of options how to customize media uploader frame? I mean wouldn't it be good if you can do something like this (See // Create the media frame.):
// Uploading files
var file_frame;
jQuery('.upload_image_button').live('click', function() {
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frames.file_frame = wp.media({
title: 'My frame title',
button: {
text: 'My button text',
},
id: 'logo-frame',
multiple: false,
editing_sidebar: false, // Just added for example
default_tab: 'upload', // Just added for example
tabs: 'upload, library', // Just added for example
returned_image_size: 'thumbnail' // Just added for example
});
// When an image is selected, run a callback.
file_frame.on( 'select', function() {
var attachment;
// We set multiple to false so only get one image from the uploader
attachment = file_frame.state().get('selection').first().toJSON();
// Do something with attachment.id and/or attachment.url here
});
// Finally, open the modal
file_frame.open();
return false
});
For WP 3.5, you can use the new media uploader. I'll be brief in the hopes that you know what you're doing. The idea is to call the wp_enqueue_script (this only works on WP >= 3.5 btw). Once the script is called, you can manipulate the javascript object. You'll have to do some inspecting to see your full set of options.
First you have to enqueue the script:
add_action( 'wp_enqueue_scripts', 'front_upload_enqueues' );
function front_upload_enqueues() {
wp_register_script('uploads',
// path to upload script
get_template_directory_uri().'/lib/js/media-upload.js'
);
wp_enqueue_script('uploads');
if ( function_exists('wp_enqueue_media') ) {
// this enqueues all the media upload stuff
wp_enqueue_media();
}
}
Then you have to add the javascript (jQuery in my case):
jQuery(document).ready(function($){
var frame;
/*
* Upload button click event, which builds the choose-from-library frame.
*
*/
$('.form-table').on('click', '.member-upload-field .btn-upload', function( event ) {
var $el = $(this);
event.preventDefault();
// Create the media frame.
frame = wp.media.frames.customHeader = wp.media({
title: $el.data('choose'),
library: { // remove these to show all
type: 'image', // specific mime
author: userSettings.uid // specific user-posted attachment
},
button: {
text: $el.data('update'), // button text
close: true // whether click closes
}
});
// When an image is selected, run a callback.
frame.on( 'select', function() {
// Grab the selected attachment.
var attachment = frame.state().get('selection').first(),
link = $el.data('updateLink');
$el.prev('input').val( attachment.attributes.id );
$el.parent().prev().find('img').attr('src', attachment.attributes.url );
});
frame.open();
});
});

Dojo Tooltip only shows after first mousover event

I'm using dojo's event delegation to connect a Tooltip widget to dynamically generated dom nodes.
The Dojo site explains event delegation this way:
"The idea behind event delegation is that instead of attaching a
listener to an event on each individual node of interest, you attach a
single listener to a node at a higher level, which will check the
target of events it catches to see whether they bubbled from an actual
node of interest; if so, the handler's logic will be performed."
Following is my code implementation. It works beautifully ... EXCEPT, the tooltip only shows AFTER the first mouse over event. When I first mouseover the node, the event fires perfectly, but the tooltip doesn't render. It will only show the consequent mouseover events. On the first mouseover event, I can watch the Firebug console and see the xhr.get go to the database and get the correct data. If I comment out the tooltip and throw in a simple alert(), it works the first time.
Any suggestions on how to get the Tooltip to show on the first mouseover event? Thanks in advance!
<div class="col_section" id="my_groups">
<div class="col_section_label">My Groups</div>
<ul>
<?php
foreach($myGroups as $grp) {
echo '<li><a class="myGroupLink" id="grp'.$grp['grp_id'].'">'.$grp['name'].'</a></li>';
}
?>
</ul>
</div>
<script>
require(["dojo/on",
"dojo/dom",
"dijit/Tooltip",
"dojo/_base/xhr",
"ready!"], function(on, dom, Tooltip, xhr) {
// Get Group ToolTip
var myObject = {
id: "myObject",
onMouseover: function(evt){
var grp_id = this.id;
var content = '';
xhr.get({
url: "getGrpInfo.php",
handleAs: "json",
content: {
grp_id: grp_id,
content: "tooltip"
},
load: function(info) {
if(info == 0) {
content = '<div class="grpToolTip">';
content += ' Information about this group is confidential';
content += '</div>';
} else {
content = '<div class="grpToolTip">';
content += ' <img src="../ajax/getimg.php?id='+info.logo_id+'" />';
content += ' <div style="text-align:center">'+info.name+'</div>';
content += '</div>';
}
new Tooltip({
connectId: [grp_id],
label: content
});
},
error: function() {}
});
}
};
var div = dom.byId("my_groups");
on(div,".myGroupLink:mouseover",myObject.onMouseover);
});
</script>
Your Tooltip does not show on the first onmouseover because it does not exist at the moment the onmouseover event was fired.
dijit/Tooltip instances manage theirs mouse events themselves, so you do not have to manage onmouseover/onmouseout and you probably did so because you do not want to preload data or you want to load data every time the tooltip is about to show.
Beside dijit/Tooltip instances you can use Tooltip.show(innerHTML, aroundNode, position) and Tooltip.hide(aroundNode) to display tooltips, but in that case you will have to manage mouse events yourself, which is what you need, because from the UX perspective, you do not want to show single tooltip, you want to:
Show a tooltip indicating information is being loaded.
Then either:
display XHR loaded information if a user still hover over the node
cancel XHR and hide tooltip on mouseout
Here is working example: http://jsfiddle.net/phusick/3hmds/
require([
"dojo/dom",
"dojo/on",
"dojo/_base/xhr",
"dijit/Tooltip",
"dojo/domReady!"
], function(
dom,
on,
xhr,
Tooltip
) {
on(dom.byId("groups"), ".group-link:mouseover", function(e) {
var target = e.target;
Tooltip.show("Loading...", target);
var def = xhr.post({
url: "/echo/html/",
content: { html: target.textContent},
failOk: true,
load: function(data) {
Tooltip._masterTT.xhr = null;
Tooltip._masterTT.containerNode.innerHTML = data;
Tooltip._masterTT.domNode.width = "auto";
},
error: function(e) {
if (e.dojoType != "cancel") {
console.error(e);
}
}
});
Tooltip._masterTT.xhr = def;
});
on(dom.byId("groups"), ".group-link:mouseout", function(e) {
var target = e.target;
Tooltip.hide(target);
if (Tooltip._masterTT.xhr) {
Tooltip._masterTT.xhr.cancel();
}
});
});​
As usual, I was over-thinking the problem, focusing on event registration rather than on simply creating the tooltips when the page loads. So, it's really stupidly simple:
query for the nodes
iterate through them and create the tooltips pointing to each node.
var myGroupsList = query("a.myGroupLink"); // query nodes based on class
array.forEach(myGroupsList,function(entry,i){ // iterate through
var grp_id = entry.id;
var content = '';
xhr.get({ // get data via xhr.get
url: "getGrpInfo.php",
handleAs: "json",
content: {
grp_id: grp_id,
content: "tooltip"
},
load: function(info) {
if(info == 0) {
content = '<div class="grpToolTip">';
content += ' Information about this group is confidential';
content += '</div>';
} else {
content = '<div class="grpToolTip">';
content += ' <img src="../ajax/getimg.php?id='+info.logo_id+'" />';
content += ' <div style="text-align:center">'+info.name+'</div>';
content += '</div>';
}
new Tooltip({ // create tooltip
connectId: [entry.id],
label: content
});
},
error: function() {}
});
});