I am using lightGallery for a website and I wanted to add a "load more" button to the gallery page, mostly for faster loading on mobile phones. I found various methods and tried them. Most of them don't work and/or doesn't suit my need for loading the elements on request.
One of them was with AngularJS:
var DemoApp = angular.module("DemoApp", []);
DemoApp.controller("DemoController",
function DemoController($scope) {
$scope.quantity = 0;
$scope.temp = [];
$scope.loadMore = function () {
for (i = $scope.quantity; i <= $scope.quantity + 1; i++) {
$scope.temp.push($scope.images[i]);
}
$scope.quantity = i;
}
$scope.images = [{
"src": "https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13244856_238092939903469_3778800896503555327_n.jpg?oh=e539748b060ba0cb43852314e2fdef0b&oe=57F01511"
}, {
"src": "https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13263891_238096316569798_4073904852035872297_n.jpg?oh=91a76b3515ac628706b912fdd3e9a346&oe=585C3DD1"
}, {
"src": "https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13260007_238096336569796_6324932140560503740_n.jpg?oh=1795ba25c4604dced3cdcc91b9729cc7&oe=5820EE5A"
}, {
"src": "https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/12871473_238096353236461_8115646425269026926_n.jpg?oh=b8958326d24a1a649e6a40adf29b062b&oe=582BFD38"
}, {
"src": "https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13256520_238096376569792_9057528716929719317_n.jpg?oh=a6bc66f75992c88260ae35bd4dbc9ff1&oe=5856F934"
}, {
"src": "https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13254297_238096389903124_1429633590050411734_n.jpg?oh=5e8c94a0b6a77dea110704a5727e0ee5&oe=5819B551"
}, {
"src": "https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13267713_238096416569788_8740461856631991826_n.jpg?oh=739e3268996e498f65867b314265250b&oe=585E4C93"
}];
$scope.loadMore();
});
And this is my HTML mark up:
<div class="col-xs-12">
<div ng-app="DemoApp" ng-controller="DemoController">
<div id="fotoalbum" class="col-thumb-wrap">
<div class="col-thumb" ng-repeat="image in temp" data-src="{{image.src}}">
<a href="{{image.src}}">
<i class="thumb" style="background-image: url({{image.src}});"></i>
</a>
</div>
</div>
<button class="btn btn-default" ng-click="loadMore()">Ik wil meer</button>
</div>
</div>
The "load more" button it self worked, however it broke the lightGallery itself.
Example: http://cytex.nl/projects/jk-installaties/album2.php
Then I found the solution for making lightGallery work with AngularJS in this StackOverflow question
I tried to combine the two but it still doesn't work. Now lightGallery gets fired up OK, but the "load more" button doesn't do anything!
Example: http://cytex.nl/projects/jk-installaties/album1.php
var DemoApp = angular.module('DemoApp', []);
DemoApp.controller('DemoController',
function DemoController($scope, $sce) {
$scope.total = 0;
$scope.temp = [];
$scope.loadMore = function () {
for (x = $scope.total; x <= $scope.total + 1; x++) {
$scope.temp.push($scope.photos[x]);
}
$scope.total = x;
}
$scope.photos = [{
fullres: 'https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13244856_238092939903469_3778800896503555327_n.jpg?oh=e539748b060ba0cb43852314e2fdef0b&oe=57F01511'
}, {
fullres: 'https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13263891_238096316569798_4073904852035872297_n.jpg?oh=91a76b3515ac628706b912fdd3e9a346&oe=585C3DD1'
}, {
fullres: 'https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13260007_238096336569796_6324932140560503740_n.jpg?oh=1795ba25c4604dced3cdcc91b9729cc7&oe=5820EE5A'
}, {
fullres: 'https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/12871473_238096353236461_8115646425269026926_n.jpg?oh=b8958326d24a1a649e6a40adf29b062b&oe=582BFD38'
}, {
fullres: 'https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13256520_238096376569792_9057528716929719317_n.jpg?oh=a6bc66f75992c88260ae35bd4dbc9ff1&oe=5856F934'
}, {
fullres: 'https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13254297_238096389903124_1429633590050411734_n.jpg?oh=5e8c94a0b6a77dea110704a5727e0ee5&oe=5819B551'
},{
fullres: 'https://scontent-ams3-1.xx.fbcdn.net/v/t1.0-9/13267713_238096416569788_8740461856631991826_n.jpg?oh=739e3268996e498f65867b314265250b&oe=585E4C93'
}];
$scope.loadMore();
for (var i = 0; i < $scope.photos.length; i++) {
$scope.photos[i].fullres = $sce.trustAsResourceUrl($scope.photos[i].fullres);
}
})
.directive('lightgallery', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
if (scope.$last) {
element.parent().lightGallery({
showThumbByDefault: false
});
}
}
};
});
I am very new to AngularJS,so I'm sorry if this is a really stupid question. Could you guys help to identify the problem and maybe pointers on how to tackle this?
Append this fragment of your code to the last row of loadMore function:
for (var i = 0; i < $scope.photos.length; i++) {
$scope.photos[i].fullres = $sce.trustAsResourceUrl($scope.photos[i].fullres);
}
This part should be run each time you add an item to the array, It means this should be run each time the function loadMore triggers.
Hope this will be helpfull. Regards.
For others who ran into this issue:
The answer of Ramin Esfahani is of course correct. But you also have to destroy the lightGallery data ever time the "Load More" button is clicked. This is in done in the directive part. Of course change the "#fotoalbum" to your own ID or class. This is the code:
.directive('lightgallery', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
if (scope.$last) {
element.parent().lightGallery({
showThumbByDefault: false
});
$('#LoadMore').on('click', function(){
$('#fotoalbum').data('lightGallery').destroy('true');
$('#fotoalbum').lightGallery({
showThumbByDefault: false
});
});
}
}
};
})
Related
I have an angular directive loading a svg map (using amchart) where I add thousands of svg circles. In the end everything works but my browser seems in pain and I would need to (1) optimize my loading and (2) display a loading symbol that could last till the map can actually display for real.
Today I use this kind of directive attribute to know when my directive is loaded :
directive('initialisation',['$rootScope',function($rootScope) {
return {
restrict: 'A',
link: function($scope) {
var to;
var listener = $scope.$watch(function() {
clearTimeout(to);
to = setTimeout(function () {
listener();
$rootScope.$broadcast('initialised');
}, 50);
});
}
};
Well this is not good to me as my loading symbol (angular-material) freezes, and then disappear to leaves an empty browser for a few seconds, before the map can render. For information I use ng-hide on the loading div and ng-show on the map div, and this is the way I apply it :
$scope.$on('initialised', function() {
$scope.$apply(function(){
$scope.mapLoaded = true;
});
})
Do you know a way to solve my (1) and (2) issue ? Or should I look for another js library to do this?
Thank you
PS : here is my map directive (images is an array with 20k entry at the moment) :
directive('amChartsLanguage', function() {
return {
restrict: 'E',
replace:true,
template: '<div id="mapLanguage" style="height: 1000px; margin: 0 auto"> </div>',
link: function(scope, element, attrs) {
var chart = false;
var initChart = function() {
if (chart) chart.destroy();
var images = [];
var legendData = [];
for(var i=0 ; i < scope.languageZeppelin.length ; i ++ ) {
images.push( {
"type": "circle",
"width": 7,
"height": 7,
"color": scope.languageZeppelin[i].color,
"longitude": scope.languageZeppelin[i].lon,
"latitude": scope.languageZeppelin[i].lat
} );
}
var legend = new AmCharts.AmLegend();
legend.width="10%";
legend.height="300";
legend.equalWidths = false;
legend.backgroundAlpha = 0.5;
legend.backgroundColor = "#FFFFFF";
legend.borderColor = "#ffffff";
legend.borderAlpha = 1;
legend.verticalGap = 10;
legend.top = 150;
legend.left = 70;
legend.position = "left";
legend.maxColumns = 1;
legend.data = scope.legend;
// build map
chart = AmCharts.makeChart( "mapLanguage", {
"type": "map",
"areasSettings": {
"unlistedAreasColor": "#15A892",
"autoZoom": true,
"selectedColor": "#FFCC00",
"color": "#909090"
},
"dataProvider": {
"map": "worldLow",
"getAreasFromMap": true,
"images": images,
"zoomLevel": 1,
"zoomLongitude": 6,
"zoomLatitude": 11
},
"export": {
"enabled": false
}
} );
chart.addLegend(legend);
chart.validateNow(legend);
};
initChart();
}
}
})
we have angular with a lot more data on the page. with poor design og architechture. loading ofcoarse too long but after that performance is great. we use d3
I'm trying to draw a morris chart in an angular directive that is within an ng-repeat block. It is weird, because it draws, almost? I can see it's there and the mouseovers work, but the graph itself is only a thin line at the top. Does anybody have any ideas?
Here's the html:
<div id="page-wrapper" ng-repeat="d in dealerGroup.Dealerships__r" ng-if="expandedDealer == d.Id">
<div class="panel-heading">Area Chart Example</div>
<div class="panel-body">
<area-chart dealership="d" chartData="d.SalesChartData"></area-chart>
</div>
</div>
And here's the directive
angular.module('areaChart', ['ui.bootstrap']).directive('areaChart', function($window) {
var directive = {};
// directive.templateUrl = directivePath + '/charts/area-chart.html';
directive.restrict = 'EA';
directive.scope = {
dealership: "=",
chartdata: "="
};
directive.controller = function($scope) {
$scope.ykeys = function() {
var ykeys = [];
angular.forEach($scope.chartdata, function(d,k) {
angular.forEach(d, function(value,key) {
if(key != 'period') { ykeys.push(key); }
})
});
return ykeys;
}
}
directive.link = function($scope,element,attrs) {
Morris.Area({
element: element,
xkey: 'period',
ykeys: $scope.ykeys(),
labels: $scope.ykeys(),
hideHover: 'auto',
pointSize: 2,
data: $scope.chartdata
});
}
return directive;
});
And here's what happens:
Additionally, resizing makes the whole thing blow up with javascript errors everywhere. But i'll worry that separately
Hi Friends here i have done the code for change text of button, like if i press the button the text of the button will change. But i need the text of the button to be change one more time,
eg: initially "Button1" -->(click)-->"Button2" -->(click)-->"Button3".
I need button3 also.
please reffer:http://jsfiddle.net/Ljrpd/17/
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
$scope.toggle = true;
$scope.$watch('toggle', function(){
$scope.toggleText = $scope.toggle ? 'Button1' : 'Button2';
})
})
Some one help me out in this issue.
Thanks
You don't need toggle variable, you can store selected index as suggested by Peter. I would also add check for last selection:
app.controller('AppController', function ($scope) {
$scope.buttonIndex = 0;
$scope.buttonNames = ['Button 1', 'Button 2', 'Button 3', 'Last Button']
$scope.changeText = function() {
if ($scope.buttonIndex === $scope.buttonNames.length - 1) {
$scope.buttonIndex = 0;
} else {
$scope.buttonIndex += 1;
}
};
});
JS Fiddle
Try my modification:
http://jsfiddle.net/Ljrpd/18/
<button ng-click="toggle = !toggle">{{buttonNames[buttonIndex]}}</button>
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
$scope.toggle = true;
$scope.buttonIndex = 0;
$scope.buttonNames = ['first', 'second', 'third']
$scope.$watch('toggle', function(){
$scope.buttonIndex += 1;
})
})
And here's a version without a watch:
http://jsfiddle.net/russf6s9/1/
<button ng-click="incrementButton()">{{buttonNames[buttonIndex]}}</button>
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
$scope.buttonIndex = 0;
$scope.incrementButton = function() {
$scope.buttonIndex += 1;
}
$scope.buttonNames = ['first', 'second', 'third']
})
Use a directive:
app.directive('changeText', function(){
return {
restrict: "A",
scope: {
changeText: "="
},
link: function(scope, element, attr) {
scope.index = 0;
element.html(scope.changeText[0]);
element.on('click', function(){
scope.index = (scope.index + 1) % scope.changeText.length;
element.html(scope.changeText[scope.index]);
})
}
};
})
Then in your html:
<body ng-controller="MainCtrl as ctrl">
<button change-text="ctrl.textValues"></button>
</body>
Plnkr
Script:
.controller('myctrl', function ($scope) {
$scope.btntext='button_1';
$scope.changetext = function () {
$scope.btntext = ($scope.btntext=='button_1')?'button_2':($scope.btntext=='button_2')?'button_3':'button_1';
}
});
Markup:
<input type="button" ng-click="changetext()" ng-value="btntext"/>
View in Plunker
I'm trying to show two section of my html page with same json data, i don't want to wrap both in same controller as it is positioned in different areas. I have implemented that concept successfully by using local json data in "angular service" see the demo
<div ng-app="testApp">
<div ng-controller="nameCtrl">
Add New
Remove First
<ul id="first" class="navigation">
<li ng-repeat="myname in mynames">{{myname.name}}</li>
</ul>
</div>
<div>
Lot of things in between
</div>
<ul id="second" class="popup" ng-controller="nameCtrl">
<li ng-repeat="myname in mynames">{{myname.name}}</li>
</ul>
JS
var testApp = angular.module('testApp', []);
testApp.service('nameService', function($http) {
var me = this;
me.mynames = [
{
"name": "Funny1"
},
{
"name": "Funny2"
},
{
"name": "Funny3"
},
{
"name": "Funny4"
}
];
//How to do
/*this.getNavTools = function(){
return $http.get('http://localhost/data/name.json').then(function(result) {
me.mynames = result.mynames;
return result.data;
});
};*/
this.addName = function() {
me.mynames.push({
"name": "New Name"
});
};
this.removeName = function() {
me.mynames.pop();
};
});
testApp.controller('nameCtrl', function ($scope, nameService) {
$scope.mynames = nameService.mynames;
$scope.$watch(
function(){ return nameService },
function(newVal) {
$scope.mynames = newVal.mynames;
}
)
$scope.addName = function() {
nameService.addName();
}
$scope.removeName = function() {
nameService.removeName();
}
});
jsfiddle
Next thing i want to do is to make a http request to json file and load my two section with data, and if i add or remove it should reflect in both areas.
Any pointers or exisisitng demo will be much helpful.
Thanks
The reason why only one ngRepeat is updating is because they are bound to two different arrays.
How could it happen? It's because that you have called getNavTools() twice, and in each call, you have replaced mynames with a new array! Eventually, the addName() and removeName() are working on the last assigned array of mynames, so you're seeing the problem.
I have the fix for you:
testApp.service('nameService', function($http) {
var me = this;
me.mynames = []; // me.mynames should not be replaced by new result
this.getNavTools = function(){
return $http.post('/echo/json/', { data: data }).then(function(result) {
var myname_json = JSON.parse(result.config.data.data.json);
angular.copy(myname_json, me.mynames); // update mynames, not replace it
return me.mynames;
});
};
this.addName = function() {
me.mynames.push({
"name": "New Name"
});
};
this.removeName = function() {
me.mynames.pop();
};
});
testApp.controller('nameCtrl', function ($scope, nameService) {
// $scope.mynames = nameService.mynames; // remove, not needed
nameService.getNavTools().then(function() {
$scope.mynames = nameService.mynames;
});
/* Remove, not needed
$scope.$watch(
function(){ return nameService },
function(newVal) {
$scope.mynames = newVal.mynames;
}
);
*/
$scope.addName = function() {
nameService.addName();
};
$scope.removeName = function() {
nameService.removeName();
};
});
http://jsfiddle.net/z6fEf/9/
What you can do is to put the data in a parent scope (maybe in $rootScope) it will trigger the both views ,And you don't need to $watch here..
$rootScope.mynames = nameService.mynames;
See the jsFiddle
I'm trying to set a variable, selected.child, on the $scope so that I can use it elsewhere. I'm still new to scopes in Angular, but not sure why I can't set something on the scope from within the directive. I can call scope functions.
I have a JSfiddle for it and code is posted below.
Thanks for the help in advance.
The HTML:
<div ng-controller="DashCtrl">
<h3>{{selected.child}}<h3>
<div ng-repeat="child in children" select={{child}}>
{{child.username}}
</div>
</div>
The javascript:
var dash = angular.module('dash', []);
dash.directive('select', function () {
return {
restrict: "A",
scope: false,
link: function (scope, element, attrs) {
element.bind('click', function () {
scope.selected.child = jQuery.parseJSON(attrs.select); //Neither this
scope.setSelected(jQuery.parseJSON(attrs.select)); //Nor this is working
if (attrs.select != scope.selected) {
other_elements = angular.element(document.querySelectorAll('[select]'));
for (var i = 0; i < other_elements.length; i++) {
elm = jQuery(other_elements[i]);
elm.css('background', 'none');
}
element.css('background', '#F3E2A9');
}
});
}
};
});
dash.controller('DashCtrl', function ($scope) {
$scope.setSelected = function (child) {
$scope.selected.child = child;
};
$scope.children = [{
"age_group": "6-8",
"username": "my_child"
}, {
"age_group": "8-10",
"username": "another_child"
}];
$scope.selected = {
child: "none"
};
});
You are missing a call to $apply
Just modify your code as below
scope.selected.child = jQuery.parseJSON(attrs.select); //Neither this
//scope.setSelected(jQuery.parseJSON(attrs.select)); //Nor this is working
scope.$apply();