Why is my custom signature pad directive not showing canvas? (without jQuery) - angularjs

Hi I'm working on a signature pad for angularjs without importing jquery, i'm just using elements of jquery lite that angular uses. I have hit a wall and I have no idea how to get past it. Here's my code:
var sig = angular.module('signature', []);
sig.directive("signatureDirective", function () {
return {
template: '<canvas id="canvas" width="500" height="100" style="border: 1px solid #ccc;"></canvas>',
restrict: 'E',
link: function (scope, element, attrs) {
var canvas = $(element);
var context = canvas.getContext("2d");
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
canvas.on("mousedown", mouseDown, false);
canvas.on("mousemove", mouseXY, false);
document.body.on("mouseup", mouseUp, false);
canvas.on("touchstart", mouseDown, false);
canvas.on("touchmove", mouseXY, true);
canvas.on("touchend", mouseUp, false);
canvas.on('touchmove', function (e) {
pen.x = e.pageX;
pen.y = e.pageY;
});
canvas.on('touchstart', function (e) {
context.fillRect(pen.x, pen.y, 1, 1);
});
canvas.on('mousemove', function (e) {
pen.x = e.pageX;
pen.y = e.pageY;
});
canvas.on('mousedown', function (e) {
context.fillRect(pen.x, pen.y, 1, 1);
});
context.getImageData();
document.body.on("touchcancel", mouseUp, false);
function draw() {
context.clearRect(0, 0, 500, 100);
context.strokeStyle = "#000000";
context.lineJoin = "miter";
context.lineWidth = 2;
for (var i = 0; i < clickX.length; i++) {
context.beginPath();
if (clickDrag[i] && i) {
context.moveTo(clickX[i - 1], clickY[i - 1]);
} else {
context.moveTo(clickX[i] - 1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.stroke();
context.closePath();
}
}
function mouseDown(e) {
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
draw();
}
function addClick(x, y, dragging) {
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function mouseUp() {
paint = false;
}
function mouseXY(e) {
if (paint) {
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
draw();
}
}
}
};
});
I append it as an element but it doesnt show and javascript doesn't throw any exceptions. Can anyone help?

I found a great answer for you on stackoverflow, a canvas drawing directive with live example.
example: http://plnkr.co/aG4paH

HTML:
<div class="col-md-8" cg-signature>
<div class="sig sigWrapper">
<div class="typed"></div>
<canvas class="pad" width="197" height="52"></canvas>
<input type="hidden" name="output" class="output">
<a class="clearButton" href="#">Clear</a>
</div>
</div>
JavaScript:
angular.module('YourModuleName')
.directive('directiveName', function() {
var directive = {};
directive.restrict = 'A';
directive.link = function($scope, $ele, $attrs){
$ele.addClass('sigPad')
$ele.ready(function() {
$ele.signaturePad({drawOnly:true});
});
};
return directive;
});

Related

AngularJS - update ng-repeat list in DOM instantly to allow animation

I have a list to which I can add languages. When a language is added, there is an animation for maximum eye candy sexyness. The animation is triggered by a state change in ng-show="lang.visible" in the HTML. I have to first add the language to the language array, and THEN change the visible state to true for the animation to show.
The problem is, when I add the language to the array, it takes around 700 ms for the DOM to get updated, and then I change the state of visible. Those 700 ms make the page feel slow.
$scope.addTourDescLang = function(newLang) {
newLang.visible = false;
$scope.newClient.tours.languages.push(newLang);
$timeout(function() {
newLang.visible = true;
}, 700 );
};
Here's the animation code:
<script>
app.animation('.slide-toggle', ['$animateCss', function($animateCss) {
var lastId = 0;
var _cache = {};
function getId(el) {
var id = el[0].getAttribute("data-slide-toggle");
if (!id) {
id = ++lastId;
el[0].setAttribute("data-slide-toggle", id);
}
return id;
}
function getState(id) {
var state = _cache[id];
if (!state) {
state = {};
_cache[id] = state;
}
return state;
}
function generateRunner(closing, state, animator, element, doneFn) {
return function() {
state.animating = true;
state.animator = animator;
state.doneFn = doneFn;
animator.start().finally(function() {
if (closing && state.doneFn === doneFn) {
element[0].style.height = '';
}
element[0].style.height = 'auto';
state.animating = false;
state.animator = undefined;
state.doneFn();
});
}
}
return {
addClass: function(element, className, doneFn) {
if (className == 'ng-hide') {
var state = getState(getId(element));
var height = (state.animating && state.height) ?
state.height : element[0].offsetHeight;
var animator = $animateCss(element, {
from: {height: height + 'px'},
to: {height: '0px'}
});
if (animator) {
if (state.animating) {
state.doneFn =
generateRunner(true,
state,
animator,
element,
doneFn);
return state.animator.end();
}
else {
state.height = height;
return generateRunner(true,
state,
animator,
element,
doneFn)();
}
}
}
doneFn();
},
removeClass: function(element, className, doneFn) {
if (className == 'ng-hide') {
var state = getState(getId(element));
var height = (state.animating && state.height) ?
state.height : element[0].offsetHeight;
var animator = $animateCss(element, {
from: {height: '0px'},
to: {height: height + 'px'}
});
if (animator) {
if (state.animating) {
state.doneFn = generateRunner(false,
state,
animator,
element,
doneFn);
return state.animator.end();
}
else {
state.height = height;
return generateRunner(false,
state,
animator,
element,
doneFn)();
}
}
}
doneFn();
}
};
}]);
(function() {
var app = angular.module('app', ['ngAnimate']);
app.animation('.slide-toggle', ['$animateCss', function($animateCss) {
return {
addClass: function(element, className, doneFn) {
if (className == 'ng-hide') {
var animator = $animateCss(element, {
to: {height: '0px'}
});
if (animator) {
return animator.start().finally(function() {
element[0].style.height = '';
doneFn();
});
}
}
doneFn();
},
removeClass: function(element, className, doneFn) {
if (className == 'ng-hide') {
var height = element[0].offsetHeight;
var animator = $animateCss(element, {
from: {height: '0px'},
to: {height: height + 'px'}
});
if (animator) {
return animator.start().finally(doneFn);
}
}
doneFn();
}
};
}]);
})();
</script>
The CSS:
.slide-toggle {
overflow: hidden;
transition: all 0.25s;
}
The HTML:
<table class="table-list">
<tbody ng-repeat="langAdded in newClient.tours.languages">
<tr>
<td>
<div ng-show="langAdded.added" class="table-list-content slide-toggle">
<div>
<img ng-src="/images/icons/flags/flag-{{ langAdded.code }}-30x20.png" style="vertical-align: middle; margin: 0 10px 0 20px;">
{{ langAdded.title }}
</div>
</div>
</td>
<td>
<div ng-show="langAdded.added" class="slide-toggle">
<md-button class="md-icon-button remove-icon-button" ng-click="removeTourDescLang(langAdded)" aria-label="Remove">
<md-icon md-svg-icon="/images/icons/svg/cross-close.svg"></md-icon>
</md-button>
</div>
</td>
</tr>
</tbody>
</table>
How can this be done in a better way?
How can I update DOM instantly, and then directly after changing the visible state to true?

Trying to create D3 + AngularJS Bar Chart

I would like to create a D3 Bar chart with angularjs. This is my directive, and currently I am having a couple of problems.
The chart is not appended to the directives div, but to html tag
Chart is appended multiple times, even though when watch is called, we only log one append
When loggin d3.select(jqElm[0]), it outputs the directives element
What am I doing wrong?
(function (angular, d3) {
'use strict';
var isDef = angular.isDefined,
aExtend = angular.extend,
aCopy = angular.copy,
isArray = angular.isArray,
isObject = angular.isObject,
aElement = angular.element,
isEqual = angular.equals;
angular.module('Widgets.Module')
.factory('ConstructorD3Bar', Constructor)
.directive('tmD3Bar', Directive);
Constructor.$inject = [
'Common'
];
Directive.$inject = [
'Common',
'ConstructorD3Bar'
];
function Constructor(Common) {
var cgenerator = Common.Generator;
function D3Bar(attrs) {
this._setProps(attrs);
}
D3Bar.prototype = {
_setProps: function (p) {
p = p || {};
this.id = isDef(p.id) ? p.id : cgenerator.id;
this.theme = isDef(p.theme) ? p.theme : 'D3Bar';
this.message = isDef(p.message) ? p.message : 'D3Bar';
this.data = isDef(p.data) ? p.data : [];
this.format = isDef(p.format) ? p.format : null;
this.tsv = isDef(p.tsv) ? p.tsv : null;
this.csv = isDef(p.csv) ? p.csv : null;
this.margin = isDef(p.margin) ? p.margin : { top: 0, bottom: 0, left: 0, right: 0};
this.boxWidth = isDef(p.boxWidth) ? p.boxWidth : Common.$window.innerWidth;
this.boxHeight = isDef(p.boxHeight) ? p.boxHeight : Common.$window.innerHeight;
this.width = isDef(p.width) ? p.width : Common.$window.innerWidth;
this.height = isDef(p.height) ? p.height : Common.$window.innerHeight;
this.init();
},
init: function () {
var that = this;
if (that.tsv !== null) {
d3.tsv(that.tsv, function (err, data) {
if (isDef(err) && err && err.status) {
switch (err.status) {
case 404:
return;
}
}
that.data = data;
});
}
},
toString: function () {
return this;
}
};
return {
create: function (props) {
return new D3Bar(props);
}
};
}
function Directive(
Common,
ConstructorD3Bar
) {
var directive = {
templateUrl: 'widgets/d3-charts/bar/bar.tpl.html',
controller: ctrl,
compile: compile,
scope: {
attrs: '=?'
},
replace: true,
restrict: 'AC'
};
return directive;
function compile(tElement, tAttrs) {
return {
pre: function (scope, jqElm, attr) {
scope.initWidget = function () {
if (!isDef(scope.attrs) || scope.attrs === null) {
scope.attrs = ConstructorD3Bar.create({});
}
var margin = scope.attrs.margin,
width = scope.attrs.boxWidth - margin.left - margin.right,
height = scope.attrs.boxHeight - margin.top - margin.bottom;
scope.attrs.width = width;
scope.attrs.height = height;
var formatPercent = d3.format('.0%');
scope.attrs.x = d3.scale
.ordinal()
.rangeRoundBands([0, width], 0.1, 1);
scope.attrs.y = d3.scale
.linear()
.range([height, 0]);
scope.attrs.xAxis = d3.svg
.axis()
.scale(scope.attrs.x)
.orient('bottom');
scope.attrs.yAxis = d3.svg
.axis()
.scale(scope.attrs.y)
.orient('left')
.tickFormat(formatPercent);
};
},
post: function (scope, jqElm, attr) {
scope.$on('$destroy', function () { });
scope.$watch(
function () {
return scope.attrs.data;
},
function (nValue, oValue) {
if (!nValue) {
return;
}
if (nValue.length === 0) {
return;
}
var data = nValue;
scope.attrs.svg = d3.select(jqElm[0])
.data(data)
.enter()
.append('svg')
.attr('width', scope.attrs.width + scope.attrs.margin.left + scope.attrs.margin.right)
.attr('height', scope.attrs.height + scope.attrs.margin.top + scope.attrs.margin.bottom)
.append('g')
.attr('transform', 'translate(' + scope.attrs.margin.left + ',' + scope.attrs.margin.top + ')');
data.forEach(function (d) {
d.frequency = +d.frequency;
});
scope.attrs.x.domain(data.map(function (d) {
return d.letter;
}));
scope.attrs.y.domain([0, d3.max(data, function (d) {
return d.frequency;
})]);
scope.attrs.svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + scope.attrs.height + ')')
.call(scope.attrs.xAxis);
scope.attrs.svg.append('g')
.attr('class', 'y axis')
.call(scope.attrs.yAxis)
.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Frequency');
scope.attrs.svg.selectAll('.bar')
.data(data)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function (d) {
return scope.attrs.x(d.letter);
})
.attr('width', scope.attrs.x.rangeBand())
.attr('y', function (d) {
return scope.attrs.y(d.frequency);
})
.attr('height', function (d) {
return scope.attrs.height - scope.attrs.y(d.frequency);
});
}
);
}
};
}
function ctrl($scope, $element, $attrs) {
var vm = $scope;
if (!isDef(vm.attrs) || vm.attrs === null) {
vm.attrs = ConstructorD3Bar.create({ });
}
var attrs = vm.attrs;
}
}
})(window.angular, window.d3);
<div id="{{ attrs.id }}" class="D3Bar" ng-class="attrs.theme" ng-init="initWidget()">
</div>
Remove .data().enter in .select
scope.attrs.svg = d3.select(jqElm[0])
.append('svg')
.attr('width', scope.attrs.width + scope.attrs.margin.left + scope.attrs.margin.right)
.attr('height', scope.attrs.height + scope.attrs.margin.top + scope.attrs.margin.bottom)
.append('g')
.attr('transform', 'translate(' + scope.attrs.margin.left + ',' + scope.attrs.margin.top + ')');

Converting CSS Sticky Plugin Into Angular Directive

I am trying to use this Sticky CSS plugin with an Angular Directive. I tried wrapping this code into a Directive but no luck yet getting it to work.
Here is the CodePen of the plugin without Angular - http://codepen.io/chrissp26/pen/gBrdo
and this is what I have so far.
Any help or guidance would be greatly appreciated.
app.directive('sticky', function() {
return function stickyTitles(stickies) {
this.load = function() {
stickies.each(function(){
var thisSticky = jQuery(this).wrap('<div class="followWrap" />');
thisSticky.parent().height(thisSticky.outerHeight());
jQuery.data(thisSticky[0], 'pos', thisSticky.offset().top);
});
}
this.scroll = function() {
stickies.each(function(i){
var thisSticky = jQuery(this),
nextSticky = stickies.eq(i+1),
prevSticky = stickies.eq(i-1),
pos = jQuery.data(thisSticky[0], 'pos');
if (pos <= jQuery(window).scrollTop()) {
thisSticky.addClass("fixed");
if (nextSticky.length > 0 && thisSticky.offset().top >= jQuery.data(nextSticky[0], 'pos') - thisSticky.outerHeight()) {
thisSticky.addClass("absolute").css("top", jQuery.data(nextSticky[0], 'pos') - thisSticky.outerHeight());
}
} else {
thisSticky.removeClass("fixed");
if (prevSticky.length > 0 && jQuery(window).scrollTop() <= jQuery.data(thisSticky[0], 'pos') - prevSticky.outerHeight()) {
prevSticky.removeClass("absolute").removeAttr("style");
}
}
});
}
}
return function(){
var newStickies = new stickyTitles(jQuery(".followMeBar"));
newStickies.load();
jQuery(window).on("scroll", function() {
newStickies.scroll();
});
};
});
try this:
<sticky>
<div class="followMeBar">a</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">b</div>
</sticky>
directive:
app.directive('sticky', function() {
var stickyTitles = function (stickies) {
this.load = function() {
stickies.each(function() {
var thisSticky = jQuery(this).wrap('<div class="followWrap" />');
thisSticky.parent().height(thisSticky.outerHeight());
jQuery.data(thisSticky[0], 'pos', thisSticky.offset().top);
});
}
this.scroll = function() {
stickies.each(function(i) {
var thisSticky = jQuery(this),
nextSticky = stickies.eq(i + 1),
prevSticky = stickies.eq(i - 1),
pos = jQuery.data(thisSticky[0], 'pos');
if (pos <= jQuery(window).scrollTop()) {
thisSticky.addClass("fixed");
if (nextSticky.length > 0 && thisSticky.offset().top >= jQuery.data(nextSticky[0], 'pos') - thisSticky.outerHeight()) {
thisSticky.addClass("absolute").css("top", jQuery.data(nextSticky[0], 'pos') - thisSticky.outerHeight());
}
} else {
thisSticky.removeClass("fixed");
if (prevSticky.length > 0 && jQuery(window).scrollTop() <= jQuery.data(thisSticky[0], 'pos') - prevSticky.outerHeight()) {
prevSticky.removeClass("absolute").removeAttr("style");
}
}
});
}
}
return {
restrict: 'E',
link: function(scope, element, attrs) {
var newStickies = new stickyTitles($(element).find(".followMeBar"));
newStickies.load();
jQuery(window).on("scroll", function() {
newStickies.scroll();
});
}
};
http://plnkr.co/edit/13w5e7n0ReWoaO8513K5?p=preview

How to do the Logic behind the next button in angularjs wizard

I have a customers.create.html partial bound to the WizardController.
Then I have 3 customers.create1,2,3.html partial files bound to WizardController1,2,3
Each WizardController1,2 or 3 has an isValid() function. This function determines wether the user can proceed to the next step.
The next button at the bottom of the pasted html should be disabed if ALL ? isValid() functions are false...
Thats my question but the same time that seems not correct to me.
I guess I am not doing the Wizard correctly...
Can someone please guide me how I should proceed with the architecture that the bottom next button is disabled when the current step isValid function returns false, please.
How can I make a connection from the WizardController to any of the WizardController1,2 or 3 ?
Is Firing an event like broadcast a good direction?
<div class="btn-group">
<button class="btn" ng-class="{'btn-primary':isCurrentStep(0)}" ng-click="setCurrentStep(0)">One</button>
<button class="btn" ng-class="{'btn-primary':isCurrentStep(1)}" ng-click="setCurrentStep(1)">Two</button>
<button class="btn" ng-class="{'btn-primary':isCurrentStep(2)}" ng-click="setCurrentStep(2)">Three</button>
</div>
<div ng-switch="getCurrentStep()" ng-animate="'slide'" class="slide-frame">
<div ng-switch-when="one">
<div ng-controller="WizardController1" ng-include src="'../views/customers.create1.html'"></div>
</div>
<div ng-switch-when="two">
<div ng-controller="WizardController2" ng-include src="'../views/customers.create2.html'"></div>
</div>
<div ng-switch-when="three">
<div ng-controller="WizardController3" ng-include src="'../views/customers.create3.html'"></div>
</div>
</div>
<a class="btn" ng-click="handlePrevious()" ng-show="!isFirstStep()">Back</a>
<a class="btn btn-primary" ng-disabled="" ng-click="handleNext(dismiss)">{{getNextLabel()}}</a>
'use strict';
angular.module('myApp').controller('WizardController', function($scope) {
$scope.steps = ['one', 'two', 'three'];
$scope.step = 0;
$scope.wizard = { tacos: 2 };
$scope.isFirstStep = function() {
return $scope.step === 0;
};
$scope.isLastStep = function() {
return $scope.step === ($scope.steps.length - 1);
};
$scope.isCurrentStep = function(step) {
return $scope.step === step;
};
$scope.setCurrentStep = function(step) {
$scope.step = step;
};
$scope.getCurrentStep = function() {
return $scope.steps[$scope.step];
};
$scope.getNextLabel = function() {
return ($scope.isLastStep()) ? 'Submit' : 'Next';
};
$scope.handlePrevious = function() {
$scope.step -= ($scope.isFirstStep()) ? 0 : 1;
};
$scope.handleNext = function(dismiss) {
if($scope.isLastStep()) {
dismiss();
} else {
$scope.step += 1;
}
};
});
durandalJS wizard sample code which could be used to rewrite a wizard for angularJS:
define(['durandal/activator', 'viewmodels/step1', 'viewmodels/step2', 'knockout', 'plugins/dialog', 'durandal/app', 'services/dataservice'],
function (activator, Step1, Step2, ko, dialog, app, service) {
var ctor = function (viewMode, schoolyearId) {
debugger;
if (viewMode === 'edit') {
service.editSchoolyear(schoolyearId);
}
else if (viewMode === 'create') {
service.createSchoolyear();
}
var self = this;
var steps = [new Step1(), new Step2()];
var step = ko.observable(0); // Start with first step
self.activeStep = activator.create();
var stepsLength = steps.length;
this.hasPrevious = ko.computed(function () {
return step() > 0;
});
self.caption = ko.observable();
this.activeStep(steps[step()]);
this.hasNext = ko.computed(function () {
if ((step() === stepsLength - 1) && self.activeStep().isValid()) {
// save
self.caption('save');
return true;
} else if ((step() < stepsLength - 1) && self.activeStep().isValid()) {
self.caption('next');
return true;
}
});
this.isLastStep = function() {
return step() === stepsLength - 1;
}
this.next = function() {
if (this.isLastStep()) {
$.when(service.createTimeTable())
.done(function () {
app.trigger('savedTimeTable', { isSuccess: true });
})
.fail(function () {
app.trigger('savedTimeTable', { isSuccess: false });
});
}
else if (step() < stepsLength) {
step(step() + 1);
self.activeStep(steps[step()]);
}
}
this.previous = function() {
if (step() > 0) {
step(step() - 1);
self.activeStep(steps[step()]);
}
}
}
return ctor;
});

What is the easiest way to delay loading of images in Angular

I have an app that allows paginating through a large text dataset via the keyboard's right/left arrow keys. The data that is displayed, also contains images.
I would like to delay the loading of these images for 1-2 seconds while the user is paginating through the data quickly.
As soon as the user stops at a certain page, all images should be "lazily" loaded.
I tried to adapt this fiddle to my app without success (see below). http://jsfiddle.net/boneskull/UfrhH/3/
my controller code
$scope.delay_images = function() {
$timeout(function() {
return true;
}, 2000);
};
view code
<tbody>
<tr>
<td style='text-align:left;padding-right:40px; height:250px;width:{{100 / panel.size}}%' ng-repeat="event in data| slice:panel.offset:panel.offset+panel.size">
<h4>{{event._source.Price}} {{event._source.Currency}}</h4>
<img ng-show="delay_images" ng-animate="{show: 'show'}" style='height:100px' ng-src="/img/{{event._source.image_paths}}"/><br /><h6>{{event._source.Title}}</h6>
<button ng-click="build_search(event._source)" ng-show='event._source.ClusterID' type="button" class="btn btn-primary">More like this</button>
</td>
</tr>
</tbody>
I am fairly new to angular.js so any tips that can guide me into the right direction are greatly appreciated.
Thanks!
UPDATE
This is a partially working code based on the accepted answer. BTW, it also implements a delay for the keydownevent.
Right now the code uses ng-show to hide and show images. I realized that this approach is problematic because it triggers a lot of image resource requests in the background while the user is paging.
So the best would be to combine the current solution somehow with the second solution replacing the src= attribute.
How would I go about that? I am catching the keydownevent from a surrounding div, so I have no direct handle to the images. Is there a way to access a class of elements with angular js? Just like with a jquery selector?
var lastFire = 0;
$scope.changeIndex = function($event) {
if($event.keyCode == 37 || $event.keyCode == 39){
var cFire = new Date();
// cancel old timeout
if ($scope.panel.timeoutId) {
$timeout.cancel($scope.panel.timeoutId);
}
// $event.keyCode...
if ((cFire - lastFire) / 1000 > 0.3){
// hide images to start with
$scope.panel.imagesVisible = false;
if ($event.keyCode == 37 && $scope.panel.offset > 0){
$scope.panel.offset = $scope.panel.offset - 10;
//$scope.get_data();
lastFire = cFire;
$scope.panel.timeoutId = $timeout(function() {
$scope.panel.imagesVisible = true;
$scope.panel.timeoutId = undefined;
}, 1000);
}
if ($event.keyCode == 39 && $scope.panel.offset < $scope.data.length - 10){
$scope.panel.offset = $scope.panel.offset + 10;
//$scope.get_data();
lastFire = cFire;
$scope.panel.timeoutId = $timeout(function() {
$scope.panel.imagesVisible = true;
$scope.panel.timeoutId = undefined;
}, 1000);
}
}
else{
$scope.panel.timeoutId = $timeout(function() {
$scope.panel.imagesVisible = true;
$scope.panel.timeoutId = undefined;
}, 1000);
}
}
};
I'd make a custom directive. This is off the top of my head, untested, but something like this should work:
myApp.directive('ngSlowSrc', function($timeout){
return{
restrict: 'A',
link: function(scope, element, attrs){
$timeout(function() {
element.src = attrs.ngSlowSrc;
}, 2000);
}
}
});
now just make your image calls like this: <img ng-slow-src="myimage.jpg" >
The way this works is it just waits 2 seconds to set the src of your image.
I think the simplest thing would be to handle it when you are paging. Let's say this is the function you call to page:
$scope.changeOffset = function(offset) {
$scope.panel.offset = offset;
// cancel old timeout
if ($scope.panel.timeoutId) {
$timeout.cancel($scope.panel.timeoutId);
}
// hide images to start with
$scope.panel.imagesVisible = false;
$scope.panel.timeoutId = $timeout(function() {
$scope.panel.imagesVisible = true;
$scope.panel.timeoutId = undefined;
}, 2000);
});
Then all images on the page can use the flag:
<img ng-show="panel.imagesVisible" ...
Working solution...
used the element method from angular which wraps jquery.
Also included the apply method in between the timeouts to make the ui experience smoother.
Thanks for your input guys.
var lastFire = 0;
$scope.changeIndex = function($event) {
if($event.keyCode == 37 || $event.keyCode == 39){
var cFire = new Date();
// cancel old timeout
if ($scope.panel.timeoutId) {
$timeout.cancel($scope.panel.timeoutId);
}
// $event.keyCode...
if ((cFire - lastFire) / 1000 > 0.5){
if ($event.keyCode == 37 && $scope.panel.offset > 0){
$scope.panel.offset = $scope.panel.offset - 10;
//$scope.get_data();
lastFire = cFire;
$scope.panel.timeoutId = $timeout(function() {
$scope.$apply(function () {
angular.forEach(angular.element('.productImage'), function(value, key){
var elem = angular.element(value);
elem.attr('src',elem.attr('ng-slow-src'));
});
$scope.panel.timeoutId = undefined;
});
}, 1000);
}
if ($event.keyCode == 39 && $scope.panel.offset < $scope.data.length - 10){
$scope.panel.offset = $scope.panel.offset + 10;
//$scope.get_data();
lastFire = cFire;
$scope.panel.timeoutId = $timeout(function() {
$scope.$apply(function () {
angular.forEach(angular.element('.productImage'), function(value, key){
var elem = angular.element(value);
elem.attr('src',elem.attr('ng-slow-src'));
});
$scope.panel.timeoutId = undefined;
});
}, 1000);
}
}
else{
$scope.panel.timeoutId = $timeout(function() {
$scope.$apply(function () {
angular.forEach(angular.element('.productImage'), function(value, key){
var elem = angular.element(value);
elem.attr('src',elem.attr('ng-slow-src'));
});
$scope.panel.timeoutId = undefined;
});
}, 1000);
}
}
};

Resources