Lazyload and Masonry on mobile - masonry

I have a code working pretty well on desktop, but my images on mobiles take too long to load and sometimes isn't loading at all... any help?
code
.js
(function(a) {
var b = a(".grid").masonry({
itemSelector: ".grid-item",
columnWidth: 306,
fitWidth: !0,
transitionDuration: 0
});
b.imagesLoaded().progress(function() {
b.masonry("layout");
a(".loading").hide();
a(".grid").show();
});
a(document).ready(function() {
a("img.imgload").lazyload({
threshold: 430,
failure_limit: 10
});
});
})(jQuery);
.html
<div class="loading"></div>
<div class="grid">
<div class="grid-item"><img class="imgload" src="/img/dummy.jpg" data-original="blablabla" width="300" height="420">
</div>
</div>
.css
.loading {position: fixed;left: 0;top: 0;width: 100%;height: 100%;z-index: 9999;background: url(/img/modal-loader.gif) center no-repeat #fff }

I have found the issue:
a(document).ready(function() {

Related

Angularjs Material md-datepicker within Formly template will not open calendar pane

I'm trying to create a Formly template using md-datepicker. Unfortunately, when I click on the md-datepicker control within my form the calendar panel does not open.
controller code:
{
className: 'col-xs-6',
key: 'dateCreated',
type: 'materialdatepicker',
templateOptions: {
label: 'Created'
},
expressionProperties: {
'templateOptions.disabled': function () {
return !vm.options.editMode;
},
'templateOptions.required': function () {
return vm.options.editMode;
}
}
}
template:
<script type="text/ng-template" id="materialdatepicker.html">
<div layout="column">
<div flex="100">
<p class="input-group" style="display: block; margin: 0px;">
<md-datepicker id="{{::id}}" name="{{::id}}" ng-model="model[options.key]"></md-datepicker>
</p>
<div class="formlyMessages" ng-messages="fc.$error" ng-if="fc.$touched">
<div class="formlyMessage" ng-message="{{::name}}" ng-repeat="(name, message) in ::options.validation.messages">
{{message(fc.$viewValue, fc.$modelValue, this)}}
</div>
</div>
</div>
</div>
</script>
formly config:
formlyConfigProvider.setType({
name: 'materialdatepicker',
templateUrl: 'materialdatepicker.html',
wrapper: ['bootstrapLabel', 'bootstrapHasError'],
defaultOptions: {
ngModelAttrs: ngModelAttrs
},
controller: ['$scope', function ($scope) {
$scope.materialdatepicker = {};
}]
});
I can't seem to figure out how to get the calendar panel to open. I'm not getting any errors in the console and the control does get populated with my initial value.
Any ideas?
What I forgot to mention in my original post was that this form is contained within a modal window ($uibModal). As such, the calendar pane was popping up behind my modal window.
The solution found here worked for me: Angular Material DatePicker Calendar Shows Behind Angular Modal
You need to tell your calendar pane to open with a high z-index so it renders above the modal. Place this style sheet code into your modal html:
<style>
.md-datepicker-calendar-pane {
z-index: 1200;
}
</style>

How to apply masonry to items appended by ajax call

I have a picture grid and in the Mobile View (320 X 480), there is a "Load More" button. The container div is as follows:
<div id="divMoments" class="grid" data-masonry='{ "itemSelector": ".grid-item"}'>
<div class="grid-item">
<div class="gridContainer">
<img src="ImageURL" />
<p>OwnerName</p>
</div>
</div>
</div>
On the button click, it triggers an ajax call. The received result is a html string of many such grid items:
"<div class=\"grid-item\">imagex<div>
<div class=\"grid-item\">imagey<div>
..."
After appending the string to the container, I have the jQuery code to reload masonry, but all the images are overlapped. When I check the html, the masonry css is applied to all the items.
function GetNextSet() {
jQuery.ajax({
url: "/api/sitecore/Moment/GetNextSet",
type: "POST",
context: this,
success: function (data) {
ShowNextResultSet(data);
}
});
}
function ShowNextResultSet(data) {
var $content = jQuery(data.ResultSet);
jQuery("#divMoments").append($content).masonry('appended', $content);
jQuery("#divMoments").masonry('reloadItems');
jQuery("#divMoments").masonry();
}
using masonry v4.1.1
Re-applying masonry after a delay worked for me.
function ShowNextResultSet(data) {
var $content = jQuery(data.ResultSet);
jQuery("#divMoments").append($content).masonry('appended', $content);
setTimeout(function () {
jQuery("#divMoments").masonry('reloadItems');
jQuery("#divMoments").masonry();
}, 100);
}

kentico youtube webpart used within slick.js

I have a repeater that out puts panels for a slide show plugin, slick.js. So far, things are working as planned.
The user, when creating the custom page, enters in copy, then either and image, video from the media library, or a link to you tube.
What i'm trying to do is write the JS function that will fire when the user clicks play on the youtube video.
The webpart injects the youtube video via the iFrame method.
Here's my transformation:
<section class="slide">
<div class="copy">
<%# Eval("SlideContent") %>
</div>
<asp:PlaceHolder runat='server' id='slideImage' visible='<%# IfEmpty( Eval("SlideImage"), false, true ) %>'>
<div class="img">
<img class="img-responsive" src="<%# Eval(" SlideImage ") %>" alt="<%# Eval(" SlideContent ") %>">
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='slideVideo' visible='<%# IfEmpty( Eval("SlideVideo"), false, true ) %>'>
<div class='videoHolder html5'>
<video id='video' class='html5Video' controls>
<source src='<%# Eval("SlideVideo") %>'>
</video>
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='youTubeVideo' visible='<%# IfEmpty( Eval("YouTubeVideo"), false, true ) %>'>
<%# Register Src="~/CMSWebParts/Media/YouTubeVideo.ascx" TagName="YoutubeVideo" TagPrefix="webPart" %>
<div class='videoHolder yt'>
<webPart:YoutubeVideo runat="server" id="YouTubeVideoWebpart" CssClass="ytVideo" VideoURL='<%# ResolveMacros(Eval("YouTubeVideo").ToString())%>' FullScreen='true' />
</div>
</asp:PlaceHolder>
</section>
And here is my JS (this also includes the code to pause videos if the slider changes)
$(function () {
'use strict';
var $slider = $('.slider'),
$slickJS = '/kffIntranet/ui/bower_components/slick-carousel/slick/slick.min.js';
// we check for a slider on the page
if ($slider.length !== 0) {
// if there is a slider, we load the slick.js plugin
$.getScript($slickJS, function () {
// init the slider
$slider.slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
slidesToScroll: 1,
fade: false,
lazyLoad: 'ondemand',
adaptiveHeight: true,
autoplay: true,
autoplaySpeed: 5000,
responsive: [{
breakpoint: 1024,
settings: {}
}, {
breakpoint: 600,
settings: {}
}, {
breakpoint: 480,
settings: {
arrows: false
}
}
// You can unslick at a given breakpoint now by adding:
// settings: "unslick"
// instead of a settings object
]
});
});
//
// video control. If a slide has video, we need to pause
//bind our event here, it gets the current slide and pauses the video before each slide changes.
$slider.on('beforeChange', function (event, slick) {
var currentSlide, player, command, videoType;
//find the current slide element and decide which player API we need to use.
currentSlide = $(slick.$slider).find('.slick-current');
//determine which type of slide this by looking for the video holder than getting the video type class
if (currentSlide.find('.videoHolder').length) {
videoType = $('.videoHolder', currentSlide).attr('class').split(' ')[1];
//get the iframe inside this slide.
player = currentSlide.find('iframe').get(0);
}
// pause videos
if (videoType === 'yt') {
command = {
'event': 'command',
'func': 'pauseVideo'
};
player.contentWindow.postMessage(JSON.stringify(command), '*');
} else if (videoType === 'html5') {
document.getElementById('video').pause();
}
});
// pause slider if a video is playing
// html 5 video click
$('.html5Video').on('click', function () {
var $video = $(this).get(0);
// control pause play state of video
if ($video.paused) {
$video.play();
} else {
$video.pause();
}
// call slide pause function
pauseSlide();
});
// youtube play
$('.ytVideo iframe').on('click', function () {
// call slide pause function
pauseSlide();
});
}
// puse slider function
function pauseSlide() {
$slider.slick('slickPause');
console.log('pause');
}
});
So i've created a function pauseSlide that will pause the slider, but i'm struggling with capturing the youtube play click.
Check this answer out. It suggests using the YouTube iframe API.
<!DOCTYPE html> <html> <head> <script src="https://www.youtube.com/iframe_api"></script> </head> <body> <div id='vidWrapper'> <!-- The <iframe> (and video player) will replace this <div> tag. --> <div id="ytplayer"></div> </div> <script> var player; function onYouTubeIframeAPIReady() { player = new YT.Player('ytplayer', { height: '390', width: '640', videoId: 'M7lc1UVf-VE', events: { 'onStateChange': function(event) { if (event.data == YT.PlayerState.PLAYING) { pauseAudio(); } } } }); } function pauseAudio() { ... } </script> </body> </html>
Ok, so i took a step back in this. The transformation now looks for a YouTube ID and then i have a jQuery plugin take over.
So the slider auto playes, and if a video (either youtube, or mp4) is started, the slider stops. Also, if either of the slider direction arrows, or one of the pips are clicked, the video will pause.
I still need to refactor and add some logic, but it's working.
Here's the updated transformation:
<section class="slide">
<div class="copy">
<%# Eval("SlideContent") %>
</div>
<asp:PlaceHolder runat='server' id='slideImage' visible='<%# IfEmpty( Eval("SlideImage"), false, true ) %>'>
<div class="img">
<img class="img-responsive" src="<%# Eval(" SlideImage ") %>" alt="<%# Eval(" SlideContent ") %>">
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='slideVideo' visible='<%# IfEmpty( Eval("SlideVideo"), false, true ) %>'>
<div class='videoHolder html5'>
<video id='video' class='html5Video' controls>
<source src='<%# Eval("SlideVideo") %>'>
</video>
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='youTubeVideoID' visible='<%# IfEmpty( Eval("YouTubeVideoID"), false, true ) %>'>
<div class='videoHolder yt' data-vID='<%# Eval("YouTubeVideoID") %>'>
<div class="vh"></div>
</div>
</asp:PlaceHolder>
</section>
my video.js file
$(function () {
'use strict';
var vHolder = $('.videoHolder'),
vtPlugin = '/kffIntranet/ui/scripts/plugins/tubePlayer/jQuery.tubeplayer.min.js',
vID;
// check for a youtube video, and if there is one, load the youtube pluging
if ($('.yt').length) {
// load plugin
$.getScript(vtPlugin, function () {
// once plugin is loaded, loop through each YT and call the plugin
$('.yt').each(function (i, v) {
var $this = $(this);
vID = $this.attr('data-vid');
$('.vh', $this).tubeplayer({
initialVideo: vID,
onPlayerPlaying: function () {
$('.slider').slick('slickPause');
}
});
});
});
} else if ($('.html5').length) {
$('.html5 .html5video').bind('pause', function () {
$('.slider').slick('slickPause');
});
}
});
and my slider js file
$(function () {
'use strict';
var $slider = $('.slider'),
$slickJS = '/kffIntranet/ui/bower_components/slick-carousel/slick/slick.min.js',
videoType;
// we check for a slider on the page
if ($slider.length !== 0) {
// if there is a slider, we load the slick.js plugin
$.getScript($slickJS, function () {
// init the slider
$slider.slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
slidesToScroll: 1,
fade: false,
lazyLoad: 'ondemand',
adaptiveHeight: true,
autoplay: true,
autoplaySpeed: 5000,
responsive: [{
breakpoint: 1024,
settings: {}
}, {
breakpoint: 600,
settings: {}
}, {
breakpoint: 480,
settings: {
arrows: false
}
}
// You can unslick at a given breakpoint now by adding:
// settings: "unslick"
// instead of a settings object
]
});
});
// on slide change
$slider.on('beforeChange', function (event, slick) {
var currentSlide;
//find the current slide element and decide which player API we need to use.
currentSlide = $(slick.$slider).find('.slick-current');
//determine which type of slide this by looking for the video holder than getting the video type class
if (currentSlide.find('.videoHolder').length) {
videoType = $('.videoHolder', currentSlide).attr('class').split(' ')[1];
}
// pause videos
if (videoType === 'html5') {
document.getElementById('video').pause();
} else if (videoType === 'yt') {
$('.vh', currentSlide).tubeplayer('pause');
}
});
}
});

How to implement dynamic flex value with Angular Material

I'm trying to build a div with uncertain number of child divs, I want the child div have flex="100" when there is only one of them, which takes the entire row. If there are more than one child divs (even if there are three or four child elements), they should all have exactly flex="50", which will take half of the row.
Any idea how could I do that?
Thanks in advance.
Another way is <div flex="{{::flexSize}}"></div> and in controller define and modify flexSize e.g $scope.flexSize = 50;
Thanks for the help from #William S, I shouldn't work with flex box for a static size layout.
So I work with ng-class to solve my problem.
HTML:
<div flex layout-fill layout="column" layout-wrap>
<div ng-repeat="function in functions" ng-class="test" class="card-container">
<md-card>
contents
</md-card>
</div>
</div>
My CSS is like the following:
.test1 {
width: 100%;
}
.test2 {
width: 50%;
}
The initial value of $scope.test is 'test1',by changing the value from 'test1' to 'test2', the width of children divs will be set to 50%.
Defining "flex" inside an element will always try to take up the most amount of space that the parent allows, without supplying any parameters to flex. This needs to be accompanied by layout="row/column", so flex expands in the right direction.
Is this what you're looking for?
http://codepen.io/qvazzler/pen/LVJZpR
Note that eventually, the items will start growing outside the parent size. You can solve this in several ways, but I believe this is outside the scope of the question.
HTML
<div ng-app="MyApp" ng-controller="AppCtrl as ctrl">
<h2>Static height list with Flex</h2>
<md-button class="thebutton" ng-click="addItem()">Add Item</md-button>
<div class="page" layout="row">
<md-list layout-fill layout="column">
<md-list-item flex layout="column" class="listitem" ng-repeat="item in items" ng-click="logme('Unrelated action')">
<md-item-content layout="column" md-ink-ripple flex>
<div class="inset">
{{item.title}}
</div>
</md-item-content>
</md-list-item>
</md-list>
</div>
</div>
CSS
.page {
height: 300px; /* Or whatever */
}
.thebutton {
background-color: gray;
}
.listitem {
/*height: 100px;*/
flex;
background-color: pink;
}
JS
angular.module('MyApp', ['ngMaterial'])
.controller('AppCtrl', function($scope) {
$scope.items = [{
title: 'Item One',
active: true
} ];
$scope.addItem = function() {
newitem = {
title: 'Another item',
active: false
};
$scope.items.push(newitem);
}
$scope.toggle = function(item) {
item.active = !item.active;
console.log("bool toggled");
}
$scope.logme = function(text) {
alert(text);
console.log(text);
}
});
Use below :
scope.flexSize = countryService.market === 'FR'? 40: 50;
<div flex="{{::flexSize}}">

dojo layout tutorial for version 1.7 doesn't work for 1.7.2

This is sortof a continuation to dojo1.7 layout acting screwy.
So I made some working widgets and tested them out, i then tried altering my work using the tutorial at http://dojotoolkit.org/documentation/tutorials/1.7/dijit_layout/ to make the layout nice. After failing at that in many interesting ways (thus my last question) I started on a new path. My plan is now to implement the layout tutorial example and then stick in my widgets. For some reason even following the tutorial wont work... everything loads then disappears and I'm left with a blank browser window.
Any ideas?
It just struck me that it could be browser compatibility issues, I'm working on Firefox 13.0.1. As far as I know Dojo is supposed to be compatible with this...
anyway, have some code:
HTML:
<body class="claro">
<div
id="appLayout" class="demoLayout"
data-dojo-type="dijit.layout.BorderContainer"
data-dojo-props="design: 'headline'">
<div
class="centerPanel"
data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="region: 'center'">
<div>
<h4>Group 1 Content</h4>
<p>stuff</p>
</div>
<div>
<h4>Group 2 Content</h4>
</div>
<div>
<h4>Group 3 Content</h4>
</div>
</div>
<div
class="edgePanel"
data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="region: 'top'">
Header content (top)
</div>
<div
id="leftCol" class="edgePanel"
data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="region: 'left', splitter: true">
Sidebar content (left)
</div>
</div>
</body>
Dojo Configuration:
var dojoConfig = {
baseUrl: "${request.static_url('mega:static/js')}", //this is in a mako template
tlmSiblingOfDojo: false,
packages: [
{ name: "dojo", location: "libs/dojo" },
{ name: "dijit", location: "libs/dijit" },
{ name: "dojox", location: "libs/dojox" },
],
parseOnLoad: true,
has: {
"dojo-firebug": true,
"dojo-debug-messages": true
},
async: true
};
other js stuff:
require(["dijit/layout/BorderContainer", "dijit/layout/TabContainer",
"dijit/layout/ContentPane", "dojo/parser"]);
css:
html, body {
height: 100%;
margin: 0;
overflow: hidden;
padding: 0;
}
#appLayout {
height: 100%;
}
#leftCol {
width: 14em;
}
I would suggest viewing the 'complete demo' on the tutorial page and then use firebug to compare your code to the example. Often they'll leave out an additional 'demo.css' file or something else that you actually need to stitch everything together.

Resources