Related
I'm new to angular and find myself stuck. I am trying to pass data from a factory to a controller and it returns undefined no matter what I have tried. Can anyone help? Ultimately I will need to access the Time and Output variables in the controller to pass into a chart.
Code:
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
$http.get(waveData[beach])
.success(function(data) {
console.log('yay it works');
return data;
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
//console.log(Time);
//console.log(Output);
});
}
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
var currentBeach = $state.current.title.toLowerCase();
$scope.waveData = waveService.getWaveData(currentBeach);
console.log($scope.waveData);
Tried to update based on refactored code provided in example 2 below, but $scope.waveData is now returning empty array. I am providing updated (and more complete) code:
Chart.js:
var WaveChart = angular.module('WaveChart', ["highcharts-ng"]);
var waveData = {
waimea: "assets/wave-waimea.json",
pauwela: "assets/wave-pauwela.json",
hanalei: "assets/wave-hanalei.json"
}
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
return $http.get(waveData[beach])
.then(function(data) {
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
return { time: Time, output: Output };
});
}
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
var currentBeach = $state.current.title.toLowerCase();
waveService.getWaveData(currentBeach)
.then(function(waveData){
$scope.waveData = waveData;
console.log($scope.waveData);
$scope.chartConfig = {
title: {
text: 'Wave Height Observations'
},
subtitle: {
text: 'according to the PacIOOS'
},
options: {
chart: {
type: 'spline'
},
plotOptions: {
spline: {
lineWidth: 2,
states: {
hover: {
lineWidth: 3
}
},
marker: {
enabled: false
}
},
area: {
fillColor: {
linearGradient: { x1: 0, y1: 0},
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
marker: {
enabled: true
},
lineWidth: 1,
states: {
hover: {
lineWidth: 2
}
},
threshold: null
}
}
},
xAxis: {
name: "Time",
categories: waveData.time
},
yAxis: {
title: {
text: 'Wave Height'
},
labels: {
formatter: function () {
return this.value;
}
}
},
tooltip: {
crosshairs: true,
shared: true
},
plotOptions: {
spline: {
marker: {
radius: 4,
lineColor: '#666666',
lineWidth: 1
}
}
},
series: [{
name: 'Wave Height',
marker: {
symbol: 'square'
},
data: waveData.output
}]
}
});
});
wave-waimea.json
[
{"Time":"00:09", "Output":4.40},
{"Time":"00:39", "Output":4.63},
{"Time":"01:09", "Output":4.72},
{"Time":"01:39", "Output":4.69},
{"Time":"02:09", "Output":4.20},
{"Time":"02:39", "Output":4.92},
{"Time":"03:09", "Output":4.89},
{"Time":"03:39", "Output":4.89},
{"Time":"04:09", "Output":5.18},
{"Time":"04:39", "Output":5.18},
{"Time":"05:09", "Output":5.41},
{"Time":"05:39", "Output":5.71},
{"Time":"06:09", "Output":5.91},
{"Time":"06:39", "Output":5.68},
{"Time":"07:09", "Output":6.33},
{"Time":"07:39", "Output":6.53},
{"Time":"08:09", "Output":6.23},
{"Time":"08:39", "Output":6.63},
{"Time":"09:09", "Output":7.58},
{"Time":"09:39", "Output":6.43},
{"Time":"10:09", "Output":6.86},
{"Time":"10:39", "Output":6.89},
{"Time":"11:09", "Output":7.25},
{"Time":"11:39", "Output":7.35},
{"Time":"12:09", "Output":7.12},
{"Time":"12:39", "Output":7.15},
{"Time":"13:09", "Output":6.73},
{"Time":"13:39", "Output":6.89},
{"Time":"14:09", "Output":6.63},
{"Time":"14:39", "Output":7.48}
]
This is a textbook use case of promises. Please see angular docs for details of working with promises in angularjs.
In this case, you have two options and I would recommend the second one as you do have a bit of post-processing after the http response comes through. (I've included the first one mainly to illustrate the most basic way to get an asynchronous $http response back to a controller)
1 - Return the $http promise itself and handle the response in the controller:
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
return $http.get(waveData[beach]);
};
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
waveService.getWaveData(currentBeach)
.success(function(data) {
console.log('yay it works');
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
//console.log(Time);
//console.log(Output);
$scope.waveData = {
time: Time,
output: Output
};
});
});
2 - create a new promise and resolve it from the $http.success callback
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
// return then $http.get promise
return $http.get(waveData[beach])
.then(function(data) {
console.log('yay it works');
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
//console.log(Time);
//console.log(Output);
// return value here is what the $http.get promise will resolve
return { time: Time, output: Output };
});
}
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
var currentBeach = $state.current.title.toLowerCase();
// use .then callback to wait for the promise to be resolved
waveService.getWaveData(currentBeach)
.then(function(waveData){
$scope.waveData = waveData;
console.log($scope.waveData);
});
EDIT:
Just noticed you can optimize your result processing by combining the two loops over data into one:
var Time = [];
var Output = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
Output.push(data[i].Output);
}
When I navagate away from a page in my angular site the error console fills up (occurs 108 times) with the error:
Error: d[h].apply is not a function
jf/this.$get</n.prototype.$broadcast#http://localhost:9885/Scripts/angular.min.js:137:355
jf/this.$get</n.prototype.$destroy#http://localhost:9885/Scripts/angular.min.js:133:254
ye</<.link/<#http://localhost:9885/Scripts/angular.min.js:252:477
jf/this.$get</n.prototype.$digest#http://localhost:9885/Scripts/angular.min.js:132:257
jf/this.$get</n.prototype.$apply#http://localhost:9885/Scripts/angular.min.js:135:267
Kc[c]</<.compile/</<#http://localhost:9885/Scripts/angular.min.js:252:124
n.event.dispatch#http://localhost:9885/Scripts/jquery-bundle.js:3:6414
n.event.add/r.handle#http://localhost:9885/Scripts/jquery-bundle.js:3:3224
It only occurs on this one page but I have no $watches or $broadcast events on it. Could someone help me by suggesting where I should look to find the trigger for this error?
I appreciate not having the code makes this difficult but I am keen to have some suggestions on what things cause errors like this and/or the best way to debug it.
UPDATE
app.controller('ticketController', ['$scope', '$state', 'Page', 'globals', 'localStorageService', 'Ticket', 'User', 'ticketData', 'ELearning', 'dialogs', 'Notification', 'Payment','Note', 'DTOptionsBuilder', 'DTColumnDefBuilder', 'History', 'Correspondance',function ($scope, $state, Page, globals, localStorageService, Ticket, User, ticketData, ELearning, dialogs, Notification, Payment,Note, DTOptionsBuilder, DTColumnDefBuilder, History, Correspondance) {
if (globals.debug) { console.log('Ticket controller loaded'); }
$scope.globals = globals;
Page.setTitle(ticketData.forename + ' ' + ticketData.surname);
$scope.authData = localStorageService.get('authorizationData');
$scope.ticket = ticketData;
$scope.user = User.admindata({ id: ticketData.ticketGUID });
$scope.person = {};
$scope.reOpenTicket = {
isOpen: false,
previousChanges: [],
newCriticalDate: moment(new Date($scope.ticket.criticalDate)).add(1, 'M').format('DD MMM YYYY'),
minCriticalDate: moment(new Date($scope.ticket.criticalDate)).add(-1, 'd').format('DD MMM YYYY'),
maxCriticalDate: moment(new Date($scope.ticket.criticalDate)).add(1, 'M').add(1, 'd').format('DD MMM YYYY'),
minErrorDate: moment(new Date($scope.ticket.criticalDate)).format('DD MMM YYYY'),
maxErrorDate: moment(new Date($scope.ticket.criticalDate)).add(1, 'M').format('DD MMM YYYY'),
reason: '',
form: {},
saving: false,
saveError: ''
};
$scope.notes = {
data: [],
newNote: '',
loading: false,
loadError: ''
};
$scope.payments = {
data: [],
loading: true,
dtOptions: {},
dtColumnDefs: {},
ticketGUID: ''
};
$scope.learning = {
data: [],
loading: true,
ticketGUID: '',
dtOptions: {},
dtColumnDefs: {}
};
$scope.history = {
data: [],
loading: true,
loadError: ''
};
$scope.letters = {
data: [],
loading: true,
laddaResendLetter: false,
laddaCancelLetter: false
};
$scope.dob = {
minDate: moment(new Date()).add(-90, 'y').format(),
maxDate: moment(new Date()).add(-10, 'y').format()
};
$scope.titles = ['Mr', 'Miss', 'Mrs', 'Ms', 'Dr', 'Rev'];
$scope.savePersonTab = function (validity) {
if (validity) {
$scope.ticket.dateOfBirth = $scope.dob.chosenDate;
Ticket.personTabSave({ 'id': $scope.ticket.ticketGUID }, $scope.ticket, function (success) {
Notification.success('Record updated successfully');
Ticket.getAdmin({ id: success.ticketGUID });
$scope.person.form.$setPristine();
$scope.getHistory();
}, function (error) {
});
} else {
console.log('skip Save');
}
};
//#region Tickets
$scope.reopenTicket = function () {
$scope.reOpenTicket.isOpen = true;
$scope.reOpenTicket.previousChanges = Ticket.getCriticalDateChanges({ id: $scope.ticket.ticketGUID });
// Reset
$scope.reOpenTicket.saveError = '';
$scope.reOpenTicket.reason = '';
};
$scope.saveReopen = function (validity) {
if (validity) {
$scope.reOpenTicket.saving = true;
var data = {
ChangeTo: $scope.reOpenTicket.newCriticalDate,
ChangeReason: $scope.reOpenTicket.reason
};
Ticket.reOpenTicket({ id: $scope.ticket.ticketGUID }, data, function (response) {
$scope.reOpenTicket.saving = false;
if (response.isSuccessful) {
$scope.getNotes();
$scope.getHistory();
$scope.ticket = Ticket.getAdmin({ id: $scope.ticket.ticketGUID });
$scope.reOpenTicket.isOpen = false;
} else {
$scope.reOpenTicket.saveError = response.errorMessage;
}
});
}
};
$scope.closeNewCriticalDate = function () {
$scope.reOpenTicket.isOpen = false;
};
$scope.confirmTCs = function () {
var opts = {
'keyboard': true,
'size': 'lg' //small or large modal size
};
// Checks
if ($scope.person.form.$dirty) {
dialogs.notify('Cannot Confirm!', 'Unsaved changes to personal details detected.', opts);
return;
}
// email address is complete
if (!$scope.ticket.eMailAddress) {
dialogs.notify('Cannot confirm!', 'An Email address must be entered and saved before confirming Terms and Conditions.', opts);
return;
} else {
if ($scope.ticket.status != 'AwaitingPayment' && $scope.ticket.status != 'Referred') {
dialogs.notify('Cannot confirm!', 'Ticket status must be Awaiting Payment or Referred before confirming Terms and Conditions. The current ticket status is ' + $scope.ticket.status, opts);
return;
}
}
var dlg = dialogs.confirm('Confirm terms and conditions', 'Please confirm that this delegate has read and agreed to the Terms and Conditions and also the details and offence relate to them.', opts);
dlg.result.then(function (btn) {
Ticket.confirmation({ 'id': $scope.ticket.ticketGUID }, $scope.ticket, function (success) {
Notification.success('Record updated successfully');
$scope.ticket = success;
$scope.getHistory();
}, function (error) {
});
});
};
$scope.lockTicket = function () {
Ticket.lock({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been locked');
}, function (error) {
console.log(error);
});
};
$scope.unlockTicket = function () {
Ticket.unlock({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been unlocked');
}, function (error) {
console.log(error);
});
};
$scope.cancelTicket = function () {
Ticket.cancelTicket({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been cancelled');
}, function (error) {
console.log(error);
});
};
$scope.restoreTicket = function () {
Ticket.restoreTicket({ id: $scope.ticket.ticketGUID }, function (success) {
$scope.ticket = success;
$scope.getHistory();
Notification.success('Ticket has been restored');
}, function (error) {
console.log(error);
});
};
//#endregion
//#region Payments
$scope.markAsPaid = function () {
var opts = {
'keyboard': true,
'size': 'lg' //small or large modal size
};
var dlg = dialogs.confirm('Mark as paid', 'Please confirm that you would like to manually mark this delegate as having paid.', opts);
dlg.result.then(function (btn) {
Payment.markAsPaid({ 'id': $scope.ticket.ticketGUID }, $scope.ticket, function (success) {
Notification.success('Record updated successfully');
$scope.ticket = Ticket.getAdmin({ id: success.ticketGUID });
}, function (error) {
console.info(error);
});
});
};
$scope.payments.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withDOM('tr');
$scope.payments.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef(0),
DTColumnDefBuilder.newColumnDef(1).withOption('width', '180'),
DTColumnDefBuilder.newColumnDef(2),
DTColumnDefBuilder.newColumnDef(3),
DTColumnDefBuilder.newColumnDef(4)
];
$scope.getPaymentData = function () {
$scope.payments.loading = true;
Payment.query({ id: $scope.ticket.ticketGUID }, function (result) {
$scope.payments.loading = false;
$scope.payments.data = result;
});
};
//#endregion
//#region Notes
$scope.addNote = function () {
Note.add({ id: $scope.ticket.ticketGUID }, '"' + $scope.notes.newNote + '"', function (successResponse) {
$scope.notes.data.push(successResponse);
$scope.notes.newNote = '';
Notification.success('Note added');
}, function (err) {
console.log(err);
});
};
$scope.getNotes = function () {
$scope.notes.loading = true;
$scope.notes.data = Note.query({ id: $scope.ticket.ticketGUID }, function (successResponse) {
$scope.notes.loading = false;
$scope.notes.loadError = '';
}, function (error) {
$scope.notes.loading = false;
$scope.notes.loadError = error.data;
});
};
//#endregion
//#region ELearning
$scope.learning.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withDOM('tr');
$scope.learning.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef(0),
DTColumnDefBuilder.newColumnDef(1),
DTColumnDefBuilder.newColumnDef(2),
DTColumnDefBuilder.newColumnDef(3).notSortable()
];
$scope.getLearningData = function () {
$scope.learning.loading = true;
ELearning.query({ id: $scope.ticket.ticketGUID }, function (result) {
$scope.learning.loading = false;
$scope.learning.data = result;
});
};
$scope.markAsCompleted = function () {
ELearning.MarkAsCompleted({ id: $scope.ticket.ticketGUID }, function (successResponse) {
$scope.ticket = successResponse;
$scope.getHistory();
$scope.getLearningData();
Notification.success('Ticket has been marked as completed');
});
};
$scope.getLearningHistory = function (learningData) {
var dlg = dialogs.create('app/elearning/ResultDialog.html', 'learningDialogController', { data: learningData.onlineLearningResultId }, 'lg');
};
//#endregion
//#region History
$scope.getHistory = function () {
$scope.history.loading = true;
History.query({ id: $scope.ticket.ticketGUID }, function (successResponse) {
$scope.history.data = successResponse;
$scope.history.loading = false;
$scope.history.loadError = '';
}, function (error) {
$scope.history.loading = false;
$scope.history.loadError = error.data;
});
};
$scope.animateElementIn = function ($el) {
$el.removeClass('hidden');
$el.addClass('bounce-in');
};
// optional: not mandatory (uses angular-scroll-animate)
$scope.animateElementOut = function ($el) {
$el.addClass('hidden');
$el.removeClass('bounce-in');
};
//#endregion
//#region Correspondance
$scope.getCorrespondanceData = function () {
$scope.letters.loading = true;
Correspondance.query({ id: $scope.ticket.ticketGUID }, function (result) {
$scope.letters.loading = false;
$scope.letters.data = result;
});
};
$scope.resendLetter = function (letter) {
$scope.letters.laddaResendLetter = true;
Correspondance.resend({ id: letter.correspondanceID }, function (result) {
Notification.success('New ' + result.correspondanceType.toLowerCase() + ' ' + result.deliveryMethod.toLowerCase() + ' has been requested');
$scope.getCorrespondanceData();
$scope.letters.laddaResendLetter = false;
}, function (error) {
$scope.letters.laddaResendLetter = false;
});
};
$scope.cancelLetter = function (letter) {
$scope.letters.laddaCancelLetter = true;
Correspondance.cancelLetterRequest({ id: letter.correspondanceID }, function (result) {
Notification.success(result.correspondanceType.toLowerCase() + ' ' + result.deliveryMethod.toLowerCase() + ' has been cancelled');
$scope.getCorrespondanceData();
$scope.letters.laddaCancelLetter = false;
}, function (error) {
$scope.letters.laddaCancelLetter = false;
});
};
//#endregion
$scope.getPaymentData();
$scope.getNotes();
$scope.getLearningData();
$scope.getHistory();
$scope.getCorrespondanceData();}]);
Found the problem to be a third party module (angular-timeline) for animating the history
I am using flot chart Angularjs directive to draw a stacked bar chart. When I make a async call to an end point to fetch data for chart, it is unable show up. I suspect it needs to redraw. There is a draw() function which looks like re draws flot chart. Please help me re-draw my flot chart in Angularjs.
<flot dataset="tasksRunData" options="tasksRunChartOptions" class="center-block" width="100%" height="400px" id="reportTasksRunRange.id"></flot>
angular.module('myApp').controller('Step2Controller', function($scope, $location, $interval, dialogs, $modal, $transition, ReportingService) {
...
$scope.tasksRunData = mainArray;
$scope.tasksRunChartOptions = {
legend: {
show: true,
margin: 2
},
xaxis: {
ticks: yaxisArray,
alignTicksWithAxis: "right"
},
grid: {
labelMargin: 10,
hoverable: true,
borderWidth: 0
},
series: {
stack: true
},
colors: colorCodesArray,
tooltip: true
};
...
$scope.redrawTasksRunDataHistoByChart();
...
$scope.redrawTasksRunDataHistoByChart = function() {
$scope.tasksRunData.draw(); //TypeError: undefined is not a function
alert("AAAA");
}
});
Update
ReportService.getTasksRunDateHistoByType().then(function(result) {
$scope.renderTasksRunDateHistoByType(result);
});
$scope.renderTasksRunDateHistoByType = function(jsonInput) {
console.log(json[RUN_AGG_BY_DATE_HISTO].aggregations[TASK_TYPE_AGG].buckets);
var yaxis = [];
var buckets = json[RUN_AGG_BY_DATE_HISTO].aggregations[TASK_TYPE_AGG].buckets;
var log = [];
var mainArray = [];
var colorCodes = ["#5C832F","#7B52AB","#263248","#AB1A25","#FF8598","#AB1A25","#FEB41C","#193441","#193441","#BEEB9F","#E3DB9A","#917A56"],
idx = 0;
angular.forEach(buckets, function(value, key) {
this.push(key + ': ' + value +", "+value["key"]);
var dataArray = [], index = 0;
console.log(JSON.stringify(value[RUN_OVER_TIME_KEY]["buckets"]));
angular.forEach(value[RUN_OVER_TIME_KEY]["buckets"], function(value, key) {
var dataArr = [];
dataArr.push('['+index+', '+value["doc_count"]+']');
dataArray.push(dataArr);
yaxis.push(JSON.parse('['+index+', "'+$scope.translate(value["key"])+'", "'+value["key"]+'"]'));
index++;
}, log);
var barObject = '"bars": {"show": "true", "barWidth":0.8, "fillColor": "'+colorCodes[idx]+'", "order": 1, "align": "center"}';
var object = '{ "data": ['+dataArray+'], "label": "'+value["key"]+'", '+barObject+'}';
mainArray.push(JSON.parse(object));
idx++;
}, log);
console.log(yaxis);
$scope.tasksRunData = mainArray;
$scope.tasksRunChartOptions = {
legend: {
show: true,
margin: 2
},
xaxis: {
//ticks:[[0,'Oct 4'],[1,'Oct 5'],[2,'Oct 6'],[3,'Oct 7'],[4,'Oct 8'],[5,'Oct 9']],
ticks: yaxis,
alignTicksWithAxis: "right"
},
grid: {
labelMargin: 10,
hoverable: true,
borderWidth: 0
},
series: {
stack: true
},
colors: colorCodes,
tooltip: true
};
};
angularjs service
angular.module('myApp')
.service('ReportService', function ReportService($http, $q) {
var getTasksRunDateHistoByType = function() {
var deferred = $q.defer();
$http({
method: 'POST',
url: "http://localhost:4040/reports/taskRun",
data: '{ "client_user_info": { "client_id": "MU03"}}'
}).
success(function(result, status, headers, config) {
deferred.resolve(result);
}).
error(function(result, status, headers, config) {
console.log("Error");
});
return deferred.promise;
};
return {
getTasksRunDateHistoByType: getTasksRunDateHistoByType
};
});
Looking at the source code to the directive, it'll redraw automatically when $scope.dataset changes.
$scope.redrawChart = function() {
var tmp = [];
for (var i = 0; i < 10; i++){
tmp.push([i,Math.random() * 10]);
}
$scope.dataset = [{ data: tmp }];
};
Here's an example.
EDITS FOR UPDATES
I'm having a hard time following your code, but in the end, you'll end up in the $scope.renderTasksRunDateHistoByType with data in the variable jsonInput. You then store some variable mainArray (which doesn't exist as far as I can tell) into other $scope level variables. I never see you assign data back to $scope.dataset. This is what the flot directive is watching to trigger a redraw. It's just that simple.
$scope.renderTasksRunDateHistoByType = function(jsonInput) {
$scope.dataset = [{
data: jsonInput
}];
//console.log(jsonInput);
//$scope.tasksRunData = mainArray;
//$scope.tasksRunChartOptions
//getting data here once response is received from server
};
See updates here.
I'm learning AngularJS and I want to create a custom service and directive to show window view which I can close, minimize, maximize, drag and resize. I wrote something but I am not sure if this is correct, especially, when I use ng-view while changing route I had to add
scope.$on('$routeChangeStart', function (next, current) {
});
to my code and ngRoute to the dependecies list to see the view, but I didn't add anything to respond to it and I am not sure how this works.
I wanted also add possibility to close window on esc but when I added this functionality closing window with animation stop working.
Could someone take a look at the code and tell me what is wrong or missed or explain something?
(function (window, angular) {
'use strict';
var module = angular.module('bbWindow', []);
module.provider('bbWindow', function () {
var defaults = this.defaults = {
id: null,
controller: null,
scope: null,
windowTitle: null,
windowContent: null,
className: 'bbwindow-theme-default',
position: 'top', // position of the window: 'top', 'center', 'bottom'
size: 'medium', // size of the window: 'small', 'medium', 'large'
showButtons: true,
showCloseButton: true,
showMinimizeButton: true,
showMaximizeButton: true,
showBackdrop: false,
closeByBackdropClick: false,
closeByEscape: true,
onClose: null,
praventClosing: false,
animation: 'am-fade-and-scale', // use animations from angular-motion, eg. am-slide-top, am-fade-and-scale, am-flip-x
backdropAnimation: 'am-fade',
template: 'common/bbwindow/bbwindow.tpl.html',
plainTemplate: false,
contentTemplate: null,
plainContentTemplate: false,
draggable: true,
dragOpacity: 0.35,
resizable: true,
resizeMinHeight: 150,
resizeMinWidth: 330
};
var openedWindows = [],
globalId = 0,
zIndex = 1000,
minimizedWindowPositions = [],
topId = 0,
defers = []; // used to resolve when window is closed
this.$get = ['$rootScope',
'$document',
'$compile',
'$q',
'$templateCache',
'$http',
'$timeout',
'$sce',
'$animate',
'$route',
'$log',
function ($rootScope, $document, $compile, $q, $templateCache, $http, $timeout, $sce, $animate, $route, $log) {
var body = $document.find('body');
// private methods
function onKeyUp(event) {
event.stopPropagation();
if (event.keyCode === 27) {
if (topId) {
bbwindow.close(topId);
}
}
}
function fetchTemplate(template, plain) {
if (plain) {
return $q.when(template);
}
return $q.when($templateCache.get(template) || $http.get(template))
.then(function (res) {
if (angular.isObject(res)) {
$templateCache.put(template, res.data);
return res.data;
}
return res;
});
}
// find elements in element or document for specified selectors
function findElement(selectors, element) {
return angular.element((element || document).querySelectorAll(selectors));
}
// get height of the screen
function getDocHeight() {
var D = document;
return Math.max(
D.body.scrollHeight, D.documentElement.scrollHeight,
D.body.offsetHeight, D.documentElement.offsetHeight,
D.body.clientHeight, D.documentElement.clientHeight
);
}
function getElementPositionObject(element) {
return {
width: element.css('width'),
height: element.css('height'),
top: element.css('top'),
left: element.css('left'),
margin: element.css('margin')
};
}
// find the minimized window position in the array and remove it
function removeMinimizedWindowPosition(windowElement) {
var left = parseInt(windowElement.css('left')),
top = parseInt(windowElement.css('top')),
i,
position = -1;
for (i = 0; i < minimizedWindowPositions.length; i++) {
if (minimizedWindowPositions[i][0] == left && minimizedWindowPositions[i][1] == top) {
position = i;
break;
}
}
if (position > -1) {
minimizedWindowPositions.splice(position, 1);
}
}
// public object returned from service
var bbwindow = {
open: function (config) {
var self = this,
options = angular.copy(defaults);
config = config || {};
angular.extend(options, config);
globalId += 1;
var id = options.id || 'bbwindow' + globalId;
topId = id;
var defer = $q.defer();
defers[id] = defer;
var scope = options.scope && angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
// Support scope as string options
angular.forEach(['windowTitle', 'windowContent'], function (key) {
if (options[key]) {
scope[key] = $sce.trustAsHtml(options[key]);
}
});
scope.showButtons = options.showButtons;
scope.showCloseButton = options.showCloseButton;
scope.showMinimizeButton = options.showMinimizeButton;
scope.showMaximizeButton = options.showMaximizeButton;
scope.close = function () {
scope.$$postDigest(function () {
if (!options.preventClosing) {
bbwindow.close(id);
}
if (options.onClose && $.isFunction(options.onClose)) {
options.onClose();
}
});
};
scope.maximize = function () {
scope.$$postDigest(function () {
bbwindow.maximize(id);
});
};
scope.minimize = function () {
scope.$$postDigest(function () {
bbwindow.minimize(id);
});
};
scope.$on('$routeChangeStart', function (next, current) {
});
// featch main window template
var templatePromise = fetchTemplate(options.template, options.plainTemplate);
// check if the user provided template for content and fetch it
if (options.contentTemplate) {
templatePromise = templatePromise.then(function (template) {
var templateElement = angular.element(template);
if (templateElement) {
// fetch content template
return fetchTemplate(options.contentTemplate, options.plainContentTemplate).then(function (contentTemplate) {
var contentElement = findElement('[data-ng-bind="windowContent"]', templateElement[0]);
if (contentElement) {
contentElement.removeAttr('data-ng-bind').html(contentTemplate);
return templateElement[0].outerHTML;
}
});
}
});
}
templatePromise.then(function (template) {
if (template) {
var windowElement = $compile(template)(scope);
scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
windowElement.attr('id', id);
if (options.controller && angular.isString(options.controller)) {
windowElement.attr('data-ng-controller', options.controller);
}
// set default theme class
windowElement.addClass(options.className);
// set initial positioning
windowElement.addClass(options.position);
// set initial size of the window
windowElement.addClass(options.size);
// add drag option if enabled
if (options.draggable) {
$(windowElement).draggable({
addClasses: false,
cancel: "input,textarea,button,select,option,.bbwindow-content,.bbwindow-header-buttons",
opacity: options.dragOpacity
});
// jquery draggable plugin sets position to relative and then there is
// problem while resizing element, so change position to absolute
$(windowElement).css('position', 'absolute');
} else {
// if the window won't be draggable, then find h4 element in the header
// and change cursor from move to normal
$(windowElement).find('.bbwindow-header h4').css('cursor', 'default');
}
// add resize option if enabled
if (options.resizable) {
$(windowElement).resizable({
handles: "all",
minHeight: options.resizeMinHeight,
minWidth: options.resizeMinWidth
});
if (options.position == 'center') {
$(windowElement).css('transform', 'inherit');
}
}
if (options.closeByEscape) {
//body.off('keyup');
//windowElement.on('keyup', onKeyUp);
}
if (options.animation) {
windowElement.addClass(options.animation);
}
windowElement.on('mousedown', function () {
topId = id;
windowElement.css('z-index', zIndex++);
});
$animate.enter(windowElement, body, null, function () {
});
}
});
return {
id: id,
closePromise: defer.promise,
close: function() {
bbwindow.close(id);
}
};
},
confirm: function(config) {
var defer = $q.defer();
var options = {
closeByBackdropClick: false,
closeByEscape: false
};
angular.extend(options, config);
options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
options.scope.confirm = function(value) {
defer.resolve(value);
window.close();
};
var window = bbwindow.open(options);
window.closePromise.then(function () {
defer.reject();
});
return defer.promise;
},
close: function (id) {
var windowElement = angular.element(document.getElementById(id));
if (windowElement) {
var isMinimized = windowElement.scope().isMinimized || false;
if (isMinimized) {
removeMinimizedWindowPosition(windowElement);
}
if (defers[id]) {
defers[id].resolve({
id: id,
window: windowElement
});
delete defers[id];
}
windowElement.scope().$destroy();
$animate.leave(windowElement, function () {
});
}
},
maximize: function (id) {
var windowElement = angular.element(document.getElementById(id));
if (windowElement) {
var isMinimized = windowElement.scope().isMinimized || false;
if (isMinimized) {
return;
}
var bodyWidth = $('body').width(),
bodyHeight = getDocHeight(),
elementWidth = parseInt(windowElement.css('width')),
elementHeight = parseInt(windowElement.css('height'));
if (windowElement.scope().lastPosition && elementWidth == bodyWidth && elementHeight == bodyHeight) {
var lastPosition = windowElement.scope().lastPosition;
$(windowElement).animate({
position: 'absolute',
width: lastPosition.width,
height: lastPosition.height,
top: lastPosition.top,
left: lastPosition.left,
margin: lastPosition.margin
}, 200);
windowElement.scope().lastPosition = null;
} else {
windowElement.scope().lastPosition = getElementPositionObject(windowElement);
$(windowElement).animate({
position: 'fixed',
width: '100%',
height: '100%',
top: '0',
left: '0',
margin: '0'
}, 200);
}
}
},
minimize: function (id) {
var windowElement = angular.element(document.getElementById(id));
if (windowElement) {
var bodyWidth = $('body').width(),
bodyHeight = getDocHeight(),
isMinimized = windowElement.scope().isMinimized || false;
if (isMinimized) {
var lastPosition = windowElement.scope().lastPositionForMinimizedElement;
removeMinimizedWindowPosition(windowElement);
$(windowElement).animate({
width: lastPosition.width,
height: lastPosition.height,
top: lastPosition.top,
left: lastPosition.left,
margin: lastPosition.margin
}, 200);
windowElement.scope().isMinimized = false;
windowElement.scope().lastPositionForMinimizedElement = null;
$(windowElement).draggable('enable');
$(windowElement).resizable('enable');
} else {
windowElement.scope().lastPositionForMinimizedElement = getElementPositionObject(windowElement);
var headerHeight = $(windowElement).find('.bbwindow-header').css('height');
var top = bodyHeight - parseInt(headerHeight);
var width = 200;
var left = 0;
var i = 0;
var found = false;
// find position for minimized window
do {
i++;
if (minimizedWindowPositions.length == 0) {
found = true;
break;
}
var positions = minimizedWindowPositions.filter(function (pos) {
return pos[0] == left && pos[1] == top;
});
if (positions.length > 0) {
left = i * width;
if (left + width >= bodyWidth) {
i = 0;
left = 0;
top -= parseInt(headerHeight);
}
} else {
found = true;
}
} while (!found);
minimizedWindowPositions.push([left, top]);
$(windowElement).animate({
height: headerHeight,
left: left + 'px',
top: top + 'px',
margin: '0',
width: width + 'px'
}, 200);
windowElement.scope().isMinimized = true;
$(windowElement).draggable('disable');
$(windowElement).resizable('disable');
}
}
}
};
return bbwindow;
}];
});
module.directive('bbWindowMain', ['$sce', 'bbWindow', function ($sce, bbWindow) {
return {
restrict: 'E',
scope: true,
link: function (scope, element, attr, transclusion) {
var options = {scope: scope};
angular.forEach(['id', 'className', 'position', 'size', 'animation', 'template', 'contentTemplate'], function (key) {
if (angular.isDefined(attr[key])) {
options[key] = attr[key];
}
});
angular.forEach(['windowTitle', 'windowContent'], function (key) {
attr[key] && attr.$observe(key, function (newValue, oldValue) {
scope[key] = $sce.trustAsHtml(newValue);
});
});
bbWindow.open(options);
}
};
}]);
})(window, window.angular);
I had created the directive file like this:
angular.module('myApp')
.directive('rGraph', function() {
return {
link: function ( scope, element, attrs ) {
var width = Math.max($("#graph-container").innerWidth(), 400);
var height = Math.max(width, 550);
var rgraph = new $jit.RGraph({
injectInto: 'graphcontainer',
width: width,
height: height,
background: {
CanvasStyles: {
strokeStyle: '#555'
}
},
Navigation: {
enable: true,
panning: true,
zooming: 10
},
Node: {
color: '#ddeeff',
overridable: true
},
Edge: {
color: '#C17878',
lineWidth: 1.0
},
onCreateLabel: function(domElement, node){
domElement.innerHTML = node.name;
domElement.onclick = function(){
rgraph.onClick(node.id, {
onComplete: function() {
Log.write("done");
}
});
};
},
onPlaceLabel: function(domElement, node){
style = domElement.style;
style.display = '';
style.cursor = 'pointer';
if (node._depth <= 1) {
style.fontSize = "0.8em";
style.color = "#ccc";
} else if(node._depth == 2){
style.fontSize = "0.7em";
style.color = "#494949";
} else {
style.display = 'none';
}
var left = parseInt(style.left);
var w = domElement.offsetWidth;
style.left = (left - w / 2) + 'px';
},
onBeforePlotNode: function(node){
if (node.data.type == 'group') {
node.setData('type', 'square');
} else if (node.data.type == 'judge') {
node.setData('type', 'star');
node.setData('dim', '8');
}
}
});
//Here I need to set the data
rgraph.loadJSON();
rgraph.refresh();
// Completing animations on every change was too much
// TODO come up with better way to watch for changes
rgraph.graph.eachNode(function(n) {
var pos = n.getPos();
pos.setc(-200, -200);
});
rgraph.compute('end');
rgraph.fx.animate({
modes:['polar'],
duration: 2000
});
}
};
});
And my controller is like this:
angular.module('myApp').controller('AnalysisCtrl', ['$scope', '$http', '$q', 'SearchService', function($scope, $http, $q, SearchService) {
$scope.graph_data = {
'id': 'judge_id',
'name': judge.name,
'type': 'judge',
'children': filters
}
My view is where I ma calling directive is like this:
<div id="graphcontainer" r-graph="graph_data"></div>
Now i need to add the data get from controller i.e data of $scope.graph_data into to the rgraph.loadJSON(); of directives.So how to do that.
Thanks
Sabbu