// Controller for the montage view /* jshint -W041 */ /* jslint browser: true*/ /* global cordova,StatusBar,angular,console,ionic,Packery, Draggabilly, imagesLoaded, ConnectSDK, moment */ angular.module('zmApp.controllers') .controller('zmApp.MontageCtrl', ['$scope', '$rootScope', 'NVRDataModel', 'message', '$ionicSideMenuDelegate', '$timeout', '$interval', '$ionicModal', '$ionicLoading', '$http', '$state', '$ionicPopup', '$stateParams', '$ionicHistory', '$ionicScrollDelegate', '$ionicPlatform', 'zm', '$ionicPopover', '$controller', 'imageLoadingDataShare', '$window', '$localstorage', '$translate', 'SecuredPopups', function($scope, $rootScope, NVRDataModel, message, $ionicSideMenuDelegate, $timeout, $interval, $ionicModal, $ionicLoading, $http, $state, $ionicPopup, $stateParams, $ionicHistory, $ionicScrollDelegate, $ionicPlatform, zm, $ionicPopover, $controller, imageLoadingDataShare, $window, $localstorage, $translate, SecuredPopups) { //--------------------------------------------------------------------- // Controller main //--------------------------------------------------------------------- var intervalHandleMontage; // image re-load handler var intervalHandleAlarmStatus; // status of each alarm state var intervalHandleMontageCycle; var gridcontainer; var pckry, draggie; var draggies; var loginData; var timestamp; var sizeInProgress; var modalIntervalHandle; var ld; var refreshSec; //-------------------------------------------------------------------------------------- // Handles bandwidth change, if required // //-------------------------------------------------------------------------------------- $rootScope.$on("bandwidth-change", function(e, data) { // not called for offline, I'm only interested in BW switches NVRDataModel.debug("Got network change:" + data); var ds; if (data == 'lowbw') { ds = $translate.instant('kLowBWDisplay'); } else { ds = $translate.instant('kHighBWDisplay'); } NVRDataModel.displayBanner('net', [ds]); var ld = NVRDataModel.getLogin(); refreshSec = (NVRDataModel.getBandwidth() == 'lowbw') ? ld.refreshSecLowBW : ld.refreshSec; $interval.cancel(intervalHandleMontage); $interval.cancel(intervalHandleMontageCycle); intervalHandleMontage = $interval(function() { loadNotifications(); }.bind(this), refreshSec * 1000); intervalHandleMontageCycle = $interval(function() { cycleMontageProfiles(); }.bind(this), NVRDataModel.getLogin().cycleMontageInterval* 1000); if (NVRDataModel.getBandwidth() == 'lowbw') { NVRDataModel.debug("Enabling low bandwidth parameters"); $scope.LoginData.montageQuality = zm.montageQualityLowBW; $scope.LoginData.singleImageQuality = zm.eventSingleImageQualityLowBW; $scope.LoginData.montageHistoryQuality = zm.montageQualityLowBW; } }); // -------------------------------------------------------- // Handling of back button in case modal is open should // close the modal // -------------------------------------------------------- $ionicPlatform.registerBackButtonAction(function(e) { e.preventDefault(); if ($scope.modal != undefined && $scope.modal.isShown()) { // switch off awake, as liveview is finished NVRDataModel.debug("Modal is open, closing it"); NVRDataModel.setAwake(false); $scope.isModalActive = false; cleanupOnClose(); } else { NVRDataModel.debug("Modal is closed, so toggling or exiting"); if (!$ionicSideMenuDelegate.isOpenLeft()) { $ionicSideMenuDelegate.toggleLeft(); } else { navigator.app.exitApp(); } } }, 1000); /*$scope.toggleHide = function(mon) { if (mon.Monitor.listDisplay == 'noshow') mon.Monitor.listDisplay = 'show'; else mon.Monitor.listDisplay = 'noshow'; };*/ // called by afterEnter to load Packery function initPackery() { $ionicLoading.show( { template: $translate.instant('kArrangingImages'), noBackdrop: true, duration: zm.loadingTimeout }); var progressCalled = false; draggies = []; var layouttype = true; var ld = NVRDataModel.getLogin(); var positionsStr = ld.packeryPositions; var positions = {}; if (positionsStr == '' || positionsStr == undefined) { NVRDataModel.log("Did NOT find a packery layout"); layouttype = true; } else { //console.log ("POSITION STR IS " + positionsStr); positions = JSON.parse(positionsStr); NVRDataModel.log("found a packery layout"); layouttype = false; } var cnt = 0; $scope.MontageMonitors.forEach(function(elem) { if ((elem.Monitor.Enabled != '0') && (elem.Monitor.Function != 'None') ) cnt++; }); NVRDataModel.log("Monitors that are active and not DOM hidden: " + cnt + " while grid has " + positions.length); if (cnt > NVRDataModel.getLogin().maxMontage) { cnt = NVRDataModel.getLogin().maxMontage; NVRDataModel.log("restricting monitor count to " + cnt + " due to max-montage setting"); } if (cnt != positions.length) { NVRDataModel.log("Whoops!! Monitors have changed. I'm resetting layouts, sorry!"); layouttype = true; positions = {}; } var elem = angular.element(document.getElementById("mygrid")); //console.log ("**** mygrid is " + JSON.stringify(elem)); pckry = new Packery('.grid', { itemSelector: '.grid-item', percentPosition: true, columnWidth: '.grid-sizer', gutter: 0, initLayout: layouttype, shiftPercentResize: true }); imagesLoaded(elem).on('progress', function(instance, img) { var result = img.isLoaded ? 'loaded' : 'broken'; NVRDataModel.debug('~~loaded image is ' + result + ' for ' + img.img.src); // lay out every image if a pre-arranged position has not been found $timeout(function() { if (layouttype) pckry.layout(); }, 100); progressCalled = true; // if (layouttype) $timeout (function(){layout(pckry);},100); }); imagesLoaded(elem).on('always', function() { //console.log ("******** ALL IMAGES LOADED"); // $scope.$digest(); NVRDataModel.debug("All images loaded"); $scope.areImagesLoading = false; $ionicLoading.hide(); if (!progressCalled) { NVRDataModel.log("*** PROGRESS WAS NOT CALLED"); // pckry.reloadItems(); } $timeout(function() { pckry.getItemElements().forEach(function(itemElem) { draggie = new Draggabilly(itemElem); pckry.bindDraggabillyEvents(draggie); draggies.push(draggie); draggie.disable(); draggie.unbindHandles(); }); pckry.on('dragItemPositioned', itemDragged); if (!isEmpty(positions)) { NVRDataModel.log("Arranging as per packery grid"); for (var i = 0; i < $scope.MontageMonitors.length; i++) { for (var j = 0; j < positions.length; j++) { if ($scope.MontageMonitors[i].Monitor.Id == positions[j].attr) { if (isNaN(positions[j].size)) positions[j].size=20; $scope.MontageMonitors[i].Monitor.gridScale = positions[j].size; $scope.MontageMonitors[i].Monitor.listDisplay = positions[j].display; NVRDataModel.debug("Setting monitor ID: " + $scope.MontageMonitors[i].Monitor.Id + " to size: " + positions[j].size + " and display:" + positions[j].display); } //console.log ("Index:"+positions[j].attr+ " with size: " + positions[j].size); } } NVRDataModel.debug("All images loaded, doing image layout"); } $timeout(function() { //NVRDataModel.log("Force calling resize"); ///pckry.reloadItems(); ///positions is defined only if layouttype was false console.log (">>> Positions is "+ JSON.stringify(positions)); if (!layouttype) pckry.initShiftLayout(positions, "data-item-id"); // now do a jiggle $timeout(function() { NVRDataModel.debug("doing the jiggle and dance..."); pckry.resize(true); }, 300); }, 100); //pckry.onresize(); }, 20); }); function itemDragged(item) { NVRDataModel.debug("drag complete"); $timeout (function(){pckry.shiftLayout();},20); pckry.once ('layoutComplete', function() { var positions = pckry.getShiftPositions('data-item-id'); //console.log ("POSITIONS MAP " + JSON.stringify(positions)); var ld = NVRDataModel.getLogin(); ld.packeryPositions = JSON.stringify(positions); console.log ("Saving " + ld.packeryPositions); // console.log ("FULL OBJECT "+ JSON.stringify(ld)); ld.currentMontageProfile = ""; $scope.currentProfileName = $translate.instant ('kMontage'); NVRDataModel.setLogin(ld); NVRDataModel.debug("saved new positions"); }); //pckry.getItemElements().forEach(function (itemElem) { //console.log (itemElem.attributes['data-item-id'].value+" size "+itemElem.attributes['data-item-size'].value ); // }); } } function isEmpty(obj) { for (var prop in obj) { return false; } return true; } //----------------------------------------------------------------------- // color for monitor state in montage //----------------------------------------------------------------------- $scope.stateColor = function() { //console.log ("***MONSTATUS**"+$scope.monStatus+"**"); var attr = ""; switch ($scope.monStatus) { case "": attr = "color:rgba(0, 0, 0, 0)"; break; case "idle": attr = "color:rgba(0, 0, 0, 0)"; break; case "pre-alarm": attr = "color:#e67e22"; break; case "alarmed": attr = "color:#D91E18"; break; case "alert": attr = "color:#e67e22"; break; case "record": attr = "color:#26A65B"; break; } return attr; }; function findNext (key,obj) { var keys = Object.keys(obj); return keys[(keys.indexOf(key) + 1) % keys.length]; /* var size = Object.keys(obj).length; var i; for (i=0; i