diff options
| author | Pliable Pixels <pliablepixels@users.noreply.github.com> | 2016-10-03 14:14:55 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-10-03 14:14:55 -0400 |
| commit | e69b00e63f06bcccafc713a46fc31847d598d419 (patch) | |
| tree | 94582a32a960488c2b3b0bc26577bc1c44e0d91a | |
| parent | a1a8d2e24f638ffe5bcf7229fcc84271aa145282 (diff) | |
| parent | 8a8b1d9766735becc351643697ea9f495767ab6a (diff) | |
Merge pull request #340 from pliablepixels/shrinking-header
initial experiments
Former-commit-id: 5194ee61e6690f8ddbdbba3e9dd14a116c9bd929
32 files changed, 3449 insertions, 57 deletions
diff --git a/.jscodehints b/.jscodehints new file mode 100644 index 00000000..b6a3d3f5 --- /dev/null +++ b/.jscodehints @@ -0,0 +1 @@ +{ "excluded-directories" : ["merges", "platforms", "www/lib", "node_modules"] } @@ -1 +1,2 @@ /*jshint devel:false */ + diff --git a/build_android.sh b/build_android.sh index b9daded9..43182a9a 100755 --- a/build_android.sh +++ b/build_android.sh @@ -91,6 +91,9 @@ if [ "$BUILD_MODE" = "native" ] || [ "$BUILD_MODE" = "all" ]; then ~/Library/Android/sdk/build-tools/22.0.1/zipalign -v 4 android-release-unsigned.apk zmNinja.apk rm -f android-release-unsigned.apk cd .. + ./checkperms.sh release_files/zmNinja.apk + echo "*** Phone State Check:" + ./checkperms.sh release_files/zmNinja.apk | grep PHONE_STATE fi @@ -15,6 +15,7 @@ <preference name="CrosswalkAnimatable" value="true" /> <preference name="webviewbounce" value="false" /> <preference name="UIWebViewBounce" value="false" /> + <preference name="StatusBarBackgroundColor" value="#2980b9" /> <preference name="DisallowOverscroll" value="true" /> <preference name="BackupWebStorage" value="none" /> <preference name="AutoHideSplashScreen" value="false" /> @@ -24,7 +25,7 @@ <preference name="SplashScreenDelay" value="300" /> <preference name="SplashMaintainAspectRatio" value="true" /> <preference name="FadeSplashScreen" value="false" /> - <preference name="BackgroundColor" value="0xff555555" /> + <preference name="BackgroundColor" value="#444444" /> <feature name="StatusBar"> <param name="ios-package" onload="true" value="CDVStatusBar" /> </feature> diff --git a/package.json b/package.json index 448df406..08a00eea 100644 --- a/package.json +++ b/package.json @@ -67,11 +67,11 @@ "locator": "https://github.com/jcjee/email-composer", "id": "com.jcjee.plugins.emailcomposer" }, - "cordova-plugin-compat", { "locator": "https://github.com/pliablepixels/cordova-plugin-media", - "id": "cordova-plugin-media" + "id": "org.apache.cordova.media" }, + "cordova-plugin-compat", { "locator": "https://github.com/litehelpers/Cordova-sqlite-storage.git", "id": "cordova-sqlite-storage" @@ -80,11 +80,19 @@ "cordova-plugin-android-permissions", "cordova-plugin-network-information", "cordova-plugin-statusbar", + "cordova-plugin-settings-hook", + { + "locator": "https://github.com/phonegap/phonegap-mobile-accessibility.git", + "id": "phonegap-plugin-mobile-accessibility" + }, + { + "locator": "https://github.com/apache/cordova-plugin-device.git", + "id": "cordova-plugin-device" + }, { "locator": "https://github.com/hypery2k/cordova-certificate-plugin", "id": "cordova-plugin-certificates" - }, - "cordova-plugin-settings-hook" + } ], "cordovaPlatforms": [ {}, diff --git a/plugins/fetch.json b/plugins/fetch.json index 27ba9870..8fcf245c 100644 --- a/plugins/fetch.json +++ b/plugins/fetch.json @@ -134,30 +134,11 @@ "is_top_level": true, "variables": {} }, - "org.apache.cordova.media": { - "source": { - "type": "git", - "url": "https://github.com/pliablepixels/cordova-plugin-media", - "subdir": ".", - "ref": "playback-only" - }, - "is_top_level": true, - "variables": {} - }, "cordova-plugin-compat": { "source": { "type": "registry", "id": "cordova-plugin-compat" }, - "is_top_level": false, - "variables": {} - }, - "cordova-plugin-media": { - "source": { - "type": "git", - "url": "https://github.com/pliablepixels/cordova-plugin-media", - "subdir": "." - }, "is_top_level": true, "variables": {} }, @@ -228,6 +209,15 @@ "is_top_level": false, "variables": {} }, + "cordova-plugin-media": { + "source": { + "type": "git", + "url": "https://github.com/pliablepixels/cordova-plugin-media", + "subdir": "." + }, + "is_top_level": true, + "variables": {} + }, "cordova-plugin-certificates": { "source": { "type": "git", diff --git a/www/css/style.css b/www/css/style.css index 33e6f972..cc61aee5 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -99,12 +99,12 @@ Credit: https://css-tricks.com/snippets/css/a-guide-to-flexbox/ opacity: 80%; } .header-event-id { - background: #9b59b6; - color: #cccccc; - border-color: #9b59b6; - border-style: solid; - border-width: 1px; - opacity: 80%; + background:rgba(52, 152, 219,0.2); + color: #FFF; + bottom: 0; + left: 0; + right: 0; + opacity: 1; } .header-paused { background: #ba3e3e; @@ -912,4 +912,5 @@ body { } .white-button-text { color: #fff !important; -}
\ No newline at end of file +} + diff --git a/www/external/ionic.headerShrink.js b/www/external/ionic.headerShrink.js new file mode 100644 index 00000000..70f9a1d2 --- /dev/null +++ b/www/external/ionic.headerShrink.js @@ -0,0 +1,73 @@ +angular.module('ionic.ion.headerShrink', []) + + .directive('headerShrink', function ($document) { + var fadeAmt; + + var shrink = function (header, content, amt, max) { + amt = Math.min(max, amt); + fadeAmt = 1 - amt / max; + ionic.requestAnimationFrame(function () { + header.style[ionic.CSS.TRANSFORM] = 'translate3d(0, -' + amt + 'px, 0)'; + for (var i = 0, j = header.children.length; i < j; i++) { + header.children[i].style.opacity = fadeAmt; + } + }); + }; + + return { + restrict: 'A', + link: function ($scope, $element, $attr) { + var starty = $scope.$eval($attr.headerShrink) || 0; + var shrinkAmt; + + var amt; + + var y = 0; + var prevY = 0; + var scrollDelay = 0.4; + + var fadeAmt; + + var headers = $document[0].body.querySelectorAll('.bar-header'); + var headerHeight = headers[0].offsetHeight; + + function onScroll(e) { + var scrollTop = e.detail.scrollTop; + + if (scrollTop >= 0) { + y = Math.min(headerHeight / scrollDelay, Math.max(0, y + scrollTop - prevY)); + } else { + y = 0; + } + //console.log(scrollTop); + + ionic.requestAnimationFrame(function () { + fadeAmt = 1 - (y / headerHeight); + for (var k = 0, l = headers.length; k < l; k++) { + headers[k].style[ionic.CSS.TRANSFORM] = 'translate3d(0, ' + -y + 'px, 0)'; + headers[k].style.opacity = fadeAmt; + } + }); + + prevY = scrollTop; + } + + $element.bind('scroll', onScroll); + } + } +}) + +angular.module('app', ['ionic', 'ionic.ion.headerShrink']) + .config(function ($stateProvider, $urlRouterProvider) { + + // Define our views + $stateProvider.state('home', { + url: "/home", + templateUrl: 'views/home.html' + // If you wanted some AngularJS controller behaviour... + // controller: "HomeCtrl as ctrl" + }); + + // Default view to show + $urlRouterProvider.otherwise('/home'); +}); diff --git a/www/external/ionic.scroll.sista.js b/www/external/ionic.scroll.sista.js new file mode 100644 index 00000000..598c7ca7 --- /dev/null +++ b/www/external/ionic.scroll.sista.js @@ -0,0 +1,318 @@ +/* global angular,ionic */ +(function (angular, ionic) { + 'use strict'; + + angular.module('jett.ionic.scroll.sista', ['ionic']) + .directive('scrollSista', ['$document', '$timeout', '$rootScope', '$ionicScrollDelegate', '$ionicPlatform',function($document, $timeout, $rootScope, $ionicScrollDelegate, $ionicPlatform) { + var TRANSITION_DELAY = 400; + var defaultDelay = TRANSITION_DELAY * 2; + var defaultDuration = TRANSITION_DELAY + 'ms'; + var scaleHeaderElements = ionic.Platform.isAndroid() ? false : true; + + function getParentWithAttr (e, attrName, attrValue, depth) { + var attr; + + depth = depth || 10; + while (e.parentNode && depth--) { + attr = e.parentNode.getAttribute(attrName); + if (attr && attr === attrValue) { + return e.parentNode; + } + e = e.parentNode; + } + return null; + } + + return { + restrict: 'A', + link: function($scope, $element, $attr) { + var isNavBarTransitioning = true; + var body = $document[0].body; + var scrollDelegate = $attr.delegateHandle ? $ionicScrollDelegate.$getByHandle($attr.delegateHandle) : $ionicScrollDelegate; + var scrollView = scrollDelegate.getScrollView(); + var isIos = false; + + //coordinates + var y, prevY, prevScrollTop; + //headers + var cachedHeader, activeHeader, headerHeight, contentTop; + //subheader + var subHeader, subHeaderHeight; + //tabs + var tabs, tabsHeight, hasTabsTop = false, hasTabsBottom = false; + + //y position that will indicate where specific elements should start and end their transition. + var headerStart = 0; + var tabsStart = 0; + var subheaderStart = 0; + var defaultEnd, headerEnd, tabsEnd, subheaderEnd; + + /** + * translates an element along the y axis by the supplied value. if duration is passed in, + * a transition duration is set + * @param element + * @param y + * @param duration + */ + function translateY (element, y, duration) { + if (duration && !element.style[ionic.CSS.TRANSITION_DURATION]) { + element.style[ionic.CSS.TRANSITION_DURATION] = duration; + $timeout(function () { + element.style[ionic.CSS.TRANSITION_DURATION] = ''; + }, defaultDelay, false); + } + element.style[ionic.CSS.TRANSFORM] = 'translate3d(0, ' + (-y) + 'px, 0)'; + } + + /** + * Initializes y and scroll variables + */ + function initCoordinates () { + y = 0; + prevY = 0; + prevScrollTop = 0; + } + + /** + * Initializes headers, tabs, and subheaders, and determines how they will transition on scroll + */ + function init () { + var activeView; + + cachedHeader = body.querySelector('[nav-bar="cached"] .bar-header'); + activeHeader = body.querySelector('[nav-bar="active"] .bar-header'); + + if (!activeHeader) { + return; + } + + // credit - adapted 20px PR from https://github.com/driftyco/ionic-ion-header-shrink/pull/10 + + headerHeight = activeHeader.offsetHeight; + $ionicPlatform.ready(function() { + if($ionicPlatform.is('ios')) { + isIos = true; + headerHeight -= 20; // account 20px for the ios status bar + } + }); + contentTop = headerHeight; + + //since some people can have nested tabs, get the last tabs + tabs = body.querySelectorAll('.tabs'); + tabs = tabs[tabs.length - 1]; + if (tabs) { + tabsHeight = tabs.offsetHeight; + if (tabs.parentNode.classList.contains('tabs-top')) { + hasTabsTop = true; + contentTop += tabsHeight; + } else if (tabs.parentNode.classList.contains('tabs-bottom')) { + hasTabsBottom = true; + } + } + + //subheader + //since subheader is going to be nested in the active view, get the closest active view from $element and + activeView = getParentWithAttr($element[0], 'nav-view', 'active'); + subHeader = activeView && activeView.querySelector('.bar-subheader'); + if (subHeader) { + subHeaderHeight = subHeader.offsetHeight; + contentTop += subHeaderHeight; + } + + //set default end for header/tabs elements to scroll out of the scroll view and set elements end to default + defaultEnd = contentTop * 2; + headerEnd = tabsEnd = subheaderEnd = defaultEnd; + + //if tabs or subheader aren't available, set height to 0 + tabsHeight = tabsHeight || 0; + subHeaderHeight = subHeaderHeight || 0; + + switch($attr.scrollSista) { + case 'header': + subheaderEnd = headerHeight; + tabsEnd = hasTabsTop ? headerHeight : 0; + break; + case 'header-tabs': + headerStart = hasTabsTop ? tabsHeight : 0; + subheaderEnd = hasTabsTop ? headerHeight + tabsHeight : headerHeight; + break; + case 'tabs-subheader': + headerEnd = 0; + headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight; + tabsStart = hasTabsTop ? subHeaderHeight : 0; + break; + case 'tabs': + headerEnd = 0; + subheaderEnd = hasTabsTop ? tabsHeight : 0; + break; + case 'subheader': + headerEnd = 0; + tabsEnd = 0; + break; + case 'header-subheader': + tabsEnd = hasTabsTop ? headerHeight : 0; + break; + case 'subheader-header': + headerStart = subHeaderHeight; + tabsStart = hasTabsTop ? subHeaderHeight : 0; + tabsEnd = hasTabsTop ? headerHeight : 0; + break; + //defaults to header-tabs-subheader + default: + headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight; + tabsStart = hasTabsTop ? subHeaderHeight : 0; + } + } + + /** + * Translates active and cached headers, and animates active children + * @param y + * @param duration + */ + function translateHeaders (y, duration) { + var fadeAmt = Math.max(0, 1 - (y / headerHeight)); + + //translate active header + if (activeHeader) { + translateY(activeHeader, y, duration); + angular.forEach(activeHeader.children, function (child) { + child.style.opacity = fadeAmt; + if (scaleHeaderElements) { + child.style[ionic.CSS.TRANSFORM] = 'scale(' + fadeAmt + ',' + fadeAmt + ')'; + } + }); + } + + //translate cached header + if (cachedHeader) { + translateY(cachedHeader, y, duration); + } + } + + /** + * Translates header, tabs, subheader elements and resets content top and/or bottom + * When the active view leaves, we need sync functionality to reset headers and clear + * @param y + * @param duration + */ + function translateElementsSync (y, duration) { + var contentStyle = $element[0].style; + var headerY = y > headerStart ? y - headerStart : 0; + var tabsY, subheaderY; + + //subheader + if (subHeader) { + subheaderY = y > subheaderStart ? y - subheaderStart : 0; + translateY(subHeader, Math.min(subheaderEnd, subheaderY), duration); + } + + //tabs + if (tabs) { + tabsY = Math.min(tabsEnd, y > tabsStart ? y - tabsStart : 0); + + if (hasTabsBottom) { + tabsY = -tabsY; + contentStyle.bottom = Math.max(0, tabsHeight - y) + 'px'; + } + translateY(tabs, tabsY, duration); + } + + //headers + translateHeaders(Math.min(headerEnd, headerY), duration); + + //readjust top of ion-content + contentStyle.top = Math.max(0, contentTop - y) + 'px'; + } + + /** + * Translates header, tabs, subheader elements and resets content top and/or bottom + * Wraps translate functionality in an animation frame request + * @param y + * @param duration + */ + function translateElements (y, duration) { + ionic.requestAnimationFrame(function() { + translateElementsSync(y, duration); + }); + } + + //Need to reinitialize the values on refreshComplete or things will get out of wack + $scope.$on('scroll.refreshComplete', function () { + initCoordinates(); + }); + + /** + * Before the active view leaves, reset elements, and reset the scroll container + */ + $scope.$parent.$on('$ionicView.beforeLeave', function () { + isNavBarTransitioning = true; + translateElementsSync(0); + activeHeader = null; + cachedHeader = null; + }); + + /** + * Scroll to the top when entering to reset then scrollView scrollTop. (prevents jumping) + */ + $scope.$parent.$on('$ionicView.beforeEnter', function () { + if (scrollView) { + scrollView.scrollTo(0, 0); + } + }); + + /** + * Ionic sets the active/cached nav-bar AFTER the afterEnter event is called, so we need to set a small + * timeout to let the nav-bar logic run. + */ + $scope.$parent.$on('$ionicView.afterEnter', function () { + initCoordinates(); + + $timeout(function () { + init(); + isNavBarTransitioning = false; + }, 20, false); + }); + + /** + * Called onScroll. computes coordinates based on scroll position and translates accordingly + */ + $element.bind('scroll', function (e) { + if (isNavBarTransitioning) { + return; + } + //support for jQuery event as well + e = e.originalEvent || e; + + var duration = 0; + var scrollTop = e.detail?e.detail.scrollTop:e.target.scrollTop; + + y = scrollTop >= 0 ? Math.min(defaultEnd, Math.max(0, y + scrollTop - prevScrollTop)) : 0; + if (isIos && y >headerHeight) + { + y = headerHeight; + } + + + //if we are at the bottom, animate the header/tabs back in + if (scrollView.getScrollMax().top - scrollTop <= contentTop) { + // console.log ("MAX TOP="+scrollView.getScrollMax().top+" SCROLL TOP:"+scrollTop+" CONTOP="+contentTop); + // y = 0; + // duration = defaultDuration; + } + + prevScrollTop = scrollTop; + + //if previous and current y are the same, no need to continue + if (prevY === y) { + return; + } + prevY = y; + + translateElements(y, duration); + }); + + } + } + }]); + +})(angular, ionic); diff --git a/www/external/packery.pkgd.js b/www/external/packery.pkgd.js index a85a10f4..66c3b21f 100644 --- a/www/external/packery.pkgd.js +++ b/www/external/packery.pkgd.js @@ -2758,6 +2758,20 @@ Packery.prototype.getShiftPositions = function( attrName ) { }); }; +// get JSON-friendly data for items positions +Packery.prototype.EHgetShiftPositions = function( attrName ) { + attrName = attrName || 'id'; + var _this = this; + return this.items.map( function( item ) { + return { + attr: item.element.getAttribute( attrName ), + size: item.element.getAttribute ("eh-data-item-size"), + display: item.element.getAttribute ("eh-data-item-listdisplay"), + x: item.rect.x / _this.packer.width, + y: item.rect.y / _this.packer.height + } + }); +}; Packery.prototype.initShiftLayout = function( positions, attr ) { if ( !positions ) { // if no initial positions, run packery layout diff --git a/www/index.html b/www/index.html index 66f2c178..6b7ffa55 100644 --- a/www/index.html +++ b/www/index.html @@ -104,7 +104,7 @@ <script src="js/EventServer.js"></script> <script src="js/EventServerSettingsCtrl.js"></script> <script src="js/FirstUseCtrl.js"></script> - <script src="js/MontageHistoryCtrl.js"></script> + <script src="js/MontageHistoryCtrl2.js"></script> <script src="js/NewsCtrl.js"></script> <script src="js/TimelineModalCtrl.js"></script> <script src="js/WizardCtrl.js"></script> @@ -144,10 +144,13 @@ <script src="external/ionic.content.banner.js"></script> <script src="external/FileSaver.min.js"></script> <script src="external/canvas-toBlob.js"></script> + <script src="external/imagesloaded.pkgd.js"></script> <script src="external/packery.pkgd.js"></script> <script src="external/draggabilly.pkgd.js"></script> + + <script src="external/ionic.scroll.sista.js"></script> <!-- <script src="external/imagesloaded.pkgd.js"></script>--> @@ -185,7 +188,7 @@ </ion-side-menu-content> <ion-side-menu> - <ion-header-bar class="bar bar-header bar-dark"> + <ion-header-bar class="bar bar-header bar-stable"> <h1 class="title">{{'kMenuOptions'|translate}}</h1> </ion-header-bar> diff --git a/www/js/DataModel.js b/www/js/DataModel.js index 16b33431..65c5835d 100644 --- a/www/js/DataModel.js +++ b/www/js/DataModel.js @@ -105,6 +105,7 @@ angular.module('zmApp.controllers') 'enableBlog': true, 'use24hr': false, 'packeryPositions': '', + 'EHpackeryPositions': '', 'packerySizes': '', 'timelineModalGraphType': 'all', 'resumeDelay': 0, @@ -666,6 +667,13 @@ angular.module('zmApp.controllers') loginData.packeryPositions = ""; } + + + if (typeof loginData.EHpackeryPositions == 'undefined') { + debug("EHpackeryPositions does not exist. Setting to empty"); + loginData.EHpackeryPositions = ""; + + } if (typeof loginData.packerySizes == 'undefined') { diff --git a/www/js/EventServer.js b/www/js/EventServer.js index 04a3d72a..8ea63531 100644 --- a/www/js/EventServer.js +++ b/www/js/EventServer.js @@ -10,16 +10,14 @@ //-------------------------------------------------------------------------- angular.module('zmApp.controllers') - .factory('EventServer', ['NVRDataModel', '$rootScope', '$websocket', '$ionicPopup', '$timeout', '$q', 'zm', '$ionicPlatform', '$cordovaMedia', '$translate', function (NVRDataModel, $rootScope, $websocket, $ionicPopup, $timeout, $q, zm, $ionicPlatform, $cordovaMedia, $translate) { - + var lastEventServerCheck = Date.now(); var ws; var localNotificationId = 0; - - + var firstError = true; //-------------------------------------------------------------------------- @@ -62,6 +60,9 @@ angular.module('zmApp.controllers') // Called once at app start. Does a lazy definition of websockets open //-------------------------------------------------------------------------- function init() { + + + $rootScope.isAlarm = 0; $rootScope.alarmCount = "0"; @@ -94,7 +95,7 @@ angular.module('zmApp.controllers') ws = $websocket.$new({ url: loginData.eventServer, reconnect: true, - reconnectInterval: 5000, + reconnectInterval: 60000, lazy: true }); @@ -103,6 +104,24 @@ angular.module('zmApp.controllers') // Transmit auth information to server ws.$on('$open', openHandshake); + NVRDataModel.debug ("Setting up websocket error handler" ); + ws.$on('$error', function (e){ + + // we don't need this check as I changed reconnect interval to 60s + //if ((Date.now() - lastEventServerCheck > 30000.0) || firstError) + if (1) + { + NVRDataModel.debug ("Websocket Errorhandler called"); + $timeout( function(){ + NVRDataModel.displayBanner('error',['Event Server connection error']); + },3000); // leave 3 seconds for transitions + firstError = false; + lastEventServerCheck = Date.now(); + } + //console.log ("VALUE TIME " + lastEventServerCheck); + //console.log ("NOW TIME " + Date.now()); + }); + ws.$on('$close', function () { NVRDataModel.log("Websocket closed"); diff --git a/www/js/MontageHistoryCtrl2.js b/www/js/MontageHistoryCtrl2.js new file mode 100644 index 00000000..d9107a0f --- /dev/null +++ b/www/js/MontageHistoryCtrl2.js @@ -0,0 +1,1708 @@ +// Controller for the montage view +/* jshint -W041 */ +/* jslint browser: true*/ +/* global cordova,StatusBar,angular,console,ionic,Masonry,moment,Packery, Draggabilly, imagesLoaded */ + + +// FIXME: This is a copy of montageCtrl - needs a lot of code cleanup + +angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$scope', '$rootScope', 'NVRDataModel', 'message', '$ionicSideMenuDelegate', '$timeout', '$interval', '$ionicModal', '$ionicLoading', '$http', '$state', '$ionicPopup', '$stateParams', '$ionicHistory', '$ionicScrollDelegate', '$ionicPlatform', 'zm', '$ionicPopover', '$controller', 'imageLoadingDataShare', '$window', '$translate', function ($scope, $rootScope, NVRDataModel, message, $ionicSideMenuDelegate, $timeout, $interval, $ionicModal, $ionicLoading, $http, $state, $ionicPopup, $stateParams, $ionicHistory, $ionicScrollDelegate, $ionicPlatform, zm, $ionicPopover, $controller, imageLoadingDataShare, $window, $translate) { + + + + + //-------------------------------------------------------------------------------------- + // Handles bandwidth change, if required + // + //-------------------------------------------------------------------------------------- + + $rootScope.$on("bandwidth-change", function (e, data) { + // nothing to do for now + // eventUrl will use lower BW in next query cycle + }); + + + + //-------------------------------------- + // formats events dates in a nice way + //--------------------------------------- + + $scope.prettifyDateTimeFirst = function (str) { + return moment(str).format(NVRDataModel.getTimeFormat() + '/MMM Do'); + + }; + $scope.prettifyDate = function (str) { + return moment(str).format('MMM Do, YYYY ' + NVRDataModel.getTimeFormat()); + }; + + function prettifyDate(str) { + return moment(str).format('MMM Do'); + } + + $scope.prettifyTime = function (str) { + + return moment(str).format('h:mm a'); + }; + + + $scope.prettify = function (str) { + return moment(str).format(NVRDataModel.getTimeFormat() + ' on MMMM Do YYYY'); + }; + + + + + function orientationChanged() { + NVRDataModel.debug("Detected orientation change, redoing packery resize"); + $timeout(function () { + pckry.onresize(); + }); + } + + $scope.toggleSizeButtons = function () { + + $scope.showSizeButtons = !$scope.showSizeButtons; + + NVRDataModel.debug("toggling size buttons:" + $scope.showSizeButtons); + if ($scope.showSizeButtons) $ionicScrollDelegate.$getByHandle("montage-delegate").scrollTop(); + }; + + //-------------------------------------- + // pause/unpause nph-zms + //--------------------------------------- + $scope.togglePause = function (mid) { + //console.log ("TOGGLE PAUSE " + mid); + var m = -1; + for (var i = 0; i < $scope.MontageMonitors.length; i++) { + + if ($scope.MontageMonitors[i].Monitor.Id == mid) { + m = i; + break; + } + } + if (m != -1) { + $scope.MontageMonitors[m].Monitor.isPaused = !$scope.MontageMonitors[m].Monitor.isPaused; + + var cmd = $scope.MontageMonitors[m].Monitor.isPaused ? 1 : 2; + + NVRDataModel.debug("Sending CMD:" + cmd + " for monitor " + $scope.MontageMonitors[m].Monitor.Name); + controlEventStream(cmd, "", $scope.MontageMonitors[m].Monitor.connKey, -1); + } + }; + + + $scope.humanizeTime = function (str) { + return moment(str).fromNow(); + + }; + + //-------------------------------------- + // Called when ion-footer collapses + // note that on init it is also called + //--------------------------------------- + + $scope.footerExpand = function () { + // console.log ("**************** EXPAND CALLED ***************"); + $ionicSideMenuDelegate.canDragContent(false); + }; + + $scope.footerCollapse = function () { + + + footerCollapse(); + + + }; + + + /* Note this is also called when the view is first loaded */ + function footerCollapse() { + // console.log ("**************** COLLAPSE CALLED ***************"); + if (readyToRun == false) { + NVRDataModel.debug("fake call to footerCollapse - ignoring"); + return; + } + + + + $scope.dragBorder = ""; + $scope.isDragabillyOn = false; + $ionicSideMenuDelegate.canDragContent(true); + + NVRDataModel.stopNetwork("MontageHistory-footerCollapse"); + var ld = NVRDataModel.getLogin(); + + $scope.sliderVal.realRate = $scope.sliderVal.rate * 100; + //NVRDataModel.debug ("Playback rate is:" + $scope.sliderVal.realRate); + + var TimeObjectFrom = moment($scope.datetimeValueFrom.value).format("YYYY-MM-DD HH:mm"); + var TimeObjectTo = moment($scope.datetimeValueTo.value).format('YYYY-MM-DD HH:mm'); + + // console.log ("TIME START: " + TimeObjectFrom + " " + TimeObjectTo); + //console.log ("TIME START: " + TimeObjectFrom + " " + TimeObjectTo); + + + var apiurl; + + // release all active streams + for (var i = 0; i < $scope.MontageMonitors.length; i++) { + $scope.MontageMonitors[i].Monitor.selectStyle = ""; + // generate new connKeys if timeline changes + if ($scope.MontageMonitors[i].Monitor.eventUrl != 'img/noevent.png') { + NVRDataModel.log("footerCollapse: Calling kill with " + $scope.MontageMonitors[i].Monitor.connKey + " because url is " + $scope.MontageMonitors[i].Monitor.eventUrl); + var tmpCK = angular.copy($scope.MontageMonitors[i].Monitor.connKey); + timedControlEventStream(2500, 17, "", tmpCK, -1); + $scope.MontageMonitors[i].Monitor.eventUrl = "img/noevent.png"; + $scope.MontageMonitors[i].Monitor.connKey = (Math.floor((Math.random() * 999999) + 1)).toString(); + //console.log ("Generating connkey: " +$scope.MontageMonitors[i].Monitor.connKey); + } else { + //console.log ("footerCollapse: Skipped kill: connkey:"+$scope.MontageMonitors[i].Monitor.connKey + " function " + $scope.MontageMonitors[i].Monitor.Function + " listDisplay " + $scope.MontageMonitors[i].Monitor.lisDisplay + " enabled " + $scope.MontageMonitors[i].Monitor.Enabled + " eventURL " + $scope.MontageMonitors[i].Monitor.eventUrl); + } + + + + + } + // grab events that start on or before the time and end on or after the time + // this should only bring up events that span that time + apiurl = ld.apiurl + "/events/index/StartTime >=:" + TimeObjectFrom + "/EndTime <=:" + TimeObjectTo + ".json"; + + NVRDataModel.log("Event timeline API is " + apiurl); + + $http.get(apiurl) + .success(function (data) { + + var ld = NVRDataModel.getLogin(); + NVRDataModel.debug("Got " + data.events.length + "new history events..."); + var eid, mid, stime; + for (i = 0; i < data.events.length; i++) { + mid = data.events[i].Event.MonitorId; + eid = data.events[i].Event.Id; + stime = data.events[i].Event.StartTime; + + // only take the first one for each monitor + for (var j = 0; j < $scope.MontageMonitors.length; j++) { + $scope.MontageMonitors[j].Monitor.isPaused = false; + // that's the earliest match and play gapless from there + if ($scope.MontageMonitors[j].Monitor.Id == mid) { + + if ($scope.MontageMonitors[j].Monitor.eventUrl == 'img/noevent.png') { + + // console.log ("Old value of event url " + $scope.MontageMonitors[j].eventUrl); + //console.log ("ldurl is " + ld.streamingurl); + + var bw = NVRDataModel.getBandwidth() == "lowbw" ? zm.eventMontageQualityLowBW : ld.montageHistoryQuality; + $scope.MontageMonitors[j].Monitor.eventUrl = ld.streamingurl + "/nph-zms?source=event&mode=jpeg&event=" + eid + "&frame=1&replay=gapless&rate=" + $scope.sliderVal.realRate + "&connkey=" + $scope.MontageMonitors[j].Monitor.connKey + "&scale=" + bw + "&rand=" + $rootScope.rand; + //console.log ("Setting event URL to " +$scope.MontageMonitors[j].Monitor.eventUrl); + + // console.log ("SWITCHING TO " + $scope.MontageMonitors[j].eventUrl); + + + $scope.MontageMonitors[j].Monitor.eventUrlTime = stime; + } + } + } + } + + // make sure we do our best to get that duration for all monitors + // in the above call, is possible some did not make the cut in the first page + + NVRDataModel.log("Making sure all monitors have a fair chance..."); + for (i = 0; i < $scope.MontageMonitors.length; i++) { + if ($scope.MontageMonitors[i].Monitor.eventUrl == 'img/noevent.png') { + + + var indivGrab = ld.apiurl + "/events/index/MonitorId:" + $scope.MontageMonitors[i].Monitor.Id + "/StartTime >=:" + TimeObjectFrom + "/EndTime <=:" + TimeObjectTo + ".json"; + + NVRDataModel.debug("Monitor " + $scope.MontageMonitors[i].Monitor.Id + ":" + $scope.MontageMonitors[i].Monitor.Name + " does not have events, trying " + indivGrab); + + getExpandedEvents(i, indivGrab); + + } + } + console.log("REDOING PACKERY & DRAG"); + if (pckry !== undefined) + $timeout(function () { + + + draggies.forEach(function (drag) { + drag.destroy(); + }); + + draggies = []; + pckry.reloadItems(); + pckry.getItemElements().forEach(function (itemElem) { + draggie = new Draggabilly(itemElem); + pckry.bindDraggabillyEvents(draggie); + draggies.push(draggie); + draggie.disable(); + }); + + $timeout(function () { + console.log (">>>>> layouting"); + //pckry.onresize(); + pckry.layout(); + }, 100); + + }, 500); + + + }) + .error(function (data) { + NVRDataModel.debug("history ERROR:" + JSON.stringify(data)); + + }); + + + function getExpandedEvents(i, indivGrab) { + var ld = NVRDataModel.getLogin(); + // console.log ("EXPANDED EVENT " + i + " " + indivGrab); + $http.get(indivGrab) + .success(function (data) { + // console.log ("EXPANDED DATA FOR MONITOR " + i + JSON.stringify(data)); + if (data.events.length > 0) { + + if (!NVRDataModel.isBackground()) { + + var bw = NVRDataModel.getBandwidth() == "lowbw" ? zm.eventMontageQualityLowBW : ld.montageHistoryQuality; + + $scope.MontageMonitors[i].Monitor.eventUrl = ld.streamingurl + "/nph-zms?source=event&mode=jpeg&event=" + data.events[0].Event.Id + "&frame=1&replay=gapless&rate=" + $scope.sliderVal.realRate + "&connkey=" + $scope.MontageMonitors[i].Monitor.connKey + "&scale=" + bw + "&rand=" + $rootScope.rand; + + + + //console.log ("SWITCHING TO " + $scope.MontageMonitors[i].eventUrl); + + $scope.MontageMonitors[i].Monitor.eventUrlTime = data.events[0].Event.StartTime; + + NVRDataModel.log("Found expanded event " + data.events[0].Event.Id + " for monitor " + $scope.MontageMonitors[i].Monitor.Id); + } else { + // $scope.MontageMonitors[i].eventUrl="img/noevent.png"; + // $scope.MontageMonitors[i].eventUrlTime = ""; + // NVRDataModel.log ("Setting img src to null as data received in background"); + } + } + + }) + .error(function (data) {}); + } + } + + //--------------------------------------------------------- + // This is periodically called to get the current playing + // event by zms. I use this to display a timestamp + // Its a 2 step process - get event Id then go a Event + // API call to get time stamp. Sucks + //--------------------------------------------------------- + + function checkAllEvents() { + + //console.log ("Events are checked...."); + + for (var i = 0; i < $scope.MontageMonitors.length; i++) { + // don't check for monitors that are not shown + // because nph connkey won't exist and the response + // will fail + if ($scope.MontageMonitors[i].Monitor.eventUrl != "" && $scope.MontageMonitors[i].Monitor.eventUrl != 'img/noevent.png' && $scope.MontageMonitors[i].Monitor.connKey != '' && + $scope.MontageMonitors[i].Monitor.Function != 'None' && + $scope.MontageMonitors[i].Monitor.listDisplay != 'noshow' && + $scope.MontageMonitors[i].Monitor.Enabled != '0') { + NVRDataModel.debug("Checking event status for " + $scope.MontageMonitors[i].Monitor.Name + ":" + $scope.MontageMonitors[i].Monitor.eventUrl + ":" + $scope.MontageMonitors[i].Monitor.Function + ":" + $scope.MontageMonitors[i].Monitor.listDisplay); + controlEventStream('99', '', $scope.MontageMonitors[i].Monitor.connKey, i); + + } + } + } + + + $scope.dateChanged = function () { + // window.stop(); + // console.log (">>>>>>>>>>>>>>>>>>>>>>>>>>>>> BAD BAD"); + footerCollapse(); + }; + + + //-------------------------------------------------------------- + // Used to control zms for a connkey. If ndx is not -1, + // then it also calls an event API for the returned eid + // and stores its time in the montage monitors array + //-------------------------------------------------------------- + $scope.controlEventStream = function (cmd, disp, connkey, ndx) { + controlEventStream(cmd, disp, connkey, ndx); + }; + + function timedControlEventStream(mTime, cmd, disp, connkey, ndx) { + var mMtime = mTime || 2000; + NVRDataModel.debug("Deferring control " + cmd + " by " + mMtime); + $timeout(function () { + subControlStream(cmd, connkey); + + }, mMtime); + } + + function subControlStream(cmd, connkey) { + var loginData = NVRDataModel.getLogin(); + var myauthtoken = $rootScope.authSession.replace("&auth=", ""); + //&auth= + var req = $http({ + method: 'POST', + /*timeout: 15000,*/ + url: loginData.url + '/index.php', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + //'Accept': '*/*', + }, + transformRequest: function (obj) { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + + encodeURIComponent(obj[p])); + var foo = str.join("&"); + //console.log("****SUB RETURNING " + foo); + return foo; + }, + + data: { + view: "request", + request: "stream", + connkey: connkey, + command: cmd, + auth: myauthtoken, + // user: loginData.username, + // pass: loginData.password + } + }); + + req.success(function (resp) { + NVRDataModel.debug("subControl success:" + JSON.stringify(resp)); + }); + + + req.error(function (resp) { + NVRDataModel.debug("subControl error:" + JSON.stringify(resp)); + }); + } + + + function controlEventStream(cmd, disp, connkey, ndx) { + // console.log("Command value " + cmd); + + if (disp) { + $ionicLoading.hide(); + $ionicLoading.show({ + template: $translate.instant('kPleaseWait') + "...", + noBackdrop: true, + duration: zm.loadingTimeout, + }); + } + var loginData = NVRDataModel.getLogin(); + + /* + var CMD_NONE = 0; + var CMD_PAUSE = 1; + var CMD_PLAY = 2; + var CMD_STOP = 3; + var CMD_FASTFWD = 4; + var CMD_SLOWFWD = 5; + var CMD_SLOWREV = 6; + var CMD_FASTREV = 7; + var CMD_ZOOMIN = 8; + var CMD_ZOOMOUT = 9; + var CMD_PAN = 10; + var CMD_SCALE = 11; + var CMD_PREV = 12; + var CMD_NEXT = 13; + var CMD_SEEK = 14; + var CMD_QUERY = 99; + */ + + + + // You need to POST commands to control zms + // Note that I am url encoding the parameters into the URL + // If I leave it as JSON, it gets converted to OPTONS due + // to CORS behaviour and ZM/Apache don't seem to handle it + + //console.log("POST: " + loginData.url + '/index.php'); + + //console.log ("AUTH IS " + $rootScope.authSession); + + var myauthtoken = $rootScope.authSession.replace("&auth=", ""); + //&auth= + var req = $http({ + method: 'POST', + /*timeout: 15000,*/ + url: loginData.url + '/index.php', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + //'Accept': '*/*', + }, + transformRequest: function (obj) { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + + encodeURIComponent(obj[p])); + var foo = str.join("&"); + // console.log("****RETURNING " + foo); + return foo; + }, + + data: { + view: "request", + request: "stream", + connkey: connkey, + command: cmd, + auth: myauthtoken, + // user: loginData.username, + // pass: loginData.password + } + }); + req.success(function (resp) { + + // console.log("SUCCESS FOR: " + JSON.stringify(resp)); + + if (resp.result == "Ok" && ndx != -1) { + var ld = NVRDataModel.getLogin(); + var apiurl = ld.apiurl + "/events/" + resp.status.event + ".json"; + //console.log ("API " + apiurl); + $http.get(apiurl) + .success(function (data) { + var currentEventTime = moment(data.event.Event.StartTime); + var maxTime = moment($scope.datetimeValueTo.value); + //NVRDataModel.debug ("Monitor: " + $scope.MontageMonitors[ndx].Monitor.Id + " max time="+maxTime + "("+$scope.datetimeValueTo.value+")"+ " current="+currentEventTime + "("+data.event.Event.StartTime+")"); + if ($scope.MontageMonitors[ndx].Monitor.eventUrlTime != data.event.Event.StartTime && currentEventTime.diff(maxTime) <= 0) { + + var ld = NVRDataModel.getLogin(); + var element = angular.element(document.getElementById($scope.MontageMonitors[ndx].Monitor.Id + "-timeline")); + element.removeClass('animated flipInX'); + element.addClass('animated flipOutX'); + $timeout(function () { + element.removeClass('animated flipOutX'); + element.addClass('animated flipInX'); + $scope.MontageMonitors[ndx].Monitor.eventUrlTime = data.event.Event.StartTime; + + var bw = NVRDataModel.getBandwidth() == "lowbw" ? zm.eventMontageQualityLowBW : ld.montageHistoryQuality; + $scope.MontageMonitors[ndx].Monitor.eventUrl = ld.streamingurl + "/nph-zms?source=event&mode=jpeg&event=" + data.event.Event.Id + "&frame=1&replay=gapless&rate=" + $scope.sliderVal.realRate + "&connkey=" + $scope.MontageMonitors[ndx].Monitor.connKey + "&scale=" + bw + "&rand=" + $rootScope.rand; + }, 700); + + } else if (currentEventTime.diff(maxTime) > 0) { + NVRDataModel.debug(">>>>>>>>Monitor " + $scope.MontageMonitors[ndx].Monitor.Id + " event time of " + data.event.Event.StartTime + " exceeds " + $scope.datetimeValueTo.value + " stopping..."); + subControlStream(17, connkey); + + + } + + }) + .error(function (data) { + $scope.MontageMonitors[ndx].Monitor.eventUrlTime = "-"; + }); + + } + }); + + req.error(function (resp) { + //console.log("ERROR: " + JSON.stringify(resp)); + NVRDataModel.log("Error sending event command " + JSON.stringify(resp), "error"); + }); + } + + + $scope.closeReorderModal = function () { + //console.log("Close & Destroy Monitor Modal"); + // switch off awake, as liveview is finished + //NVRDataModel.setAwake(false); + $scope.modal.remove(); + + }; + + + $scope.isBackground = function () { + return NVRDataModel.isBackground(); + }; + + + //---------------------------------------------------------------- + // Alarm notification handling + //---------------------------------------------------------------- + $scope.handleAlarms = function () { + $rootScope.isAlarm = !$rootScope.isAlarm; + if (!$rootScope.isAlarm) { + $rootScope.alarmCount = "0"; + $ionicHistory.nextViewOptions({ + disableBack: true + }); + $state.go("events", { + "id": 0 + }, { + reload: true + }); + } + }; + + $scope.handleAlarmsWhileMinimized = function () { + $rootScope.isAlarm = !$rootScope.isAlarm; + + $scope.minimal = !$scope.minimal; + NVRDataModel.debug("MontageHistoryCtrl: switch minimal is " + $scope.minimal); + ionic.Platform.fullScreen($scope.minimal, !$scope.minimal); + $interval.cancel(intervalHandle); + $interval.cancel($rootScope.eventQueryInterval); + + if (!$rootScope.isAlarm) { + $rootScope.alarmCount = "0"; + $ionicHistory.nextViewOptions({ + disableBack: true + }); + $state.go("events", { + "id": 0 + }, { + reload: true + }); + } + }; + + + //------------------------------------------------------------- + // this is checked to make sure we are not pulling images + // when app is in background. This is a problem with Android, + // for example + //------------------------------------------------------------- + + $scope.isBackground = function () { + //console.log ("Is background called from Montage and returned " + + //NVRDataModel.isBackground()); + return NVRDataModel.isBackground(); + }; + + //------------------------------------------------------------- + // Called when user taps on the reorder button + //------------------------------------------------------------- + + $scope.reorderList = function () { + //console.log("REORDER"); + $scope.data.showDelete = false; + $scope.data.showReorder = !$scope.data.showReorder; + }; + + $scope.deleteList = function () { + //console.log("DELETE"); + $scope.data.showDelete = !$scope.data.showDelete; + $scope.data.showReorder = false; + }; + + $scope.reloadReorder = function () { + var refresh = NVRDataModel.getMonitors(1); + + refresh.then(function (data) { + $scope.monitors = data; + $scope.MontageMonitors = data; + oldMonitors = angular.copy($scope.monitors); + var i; + montageOrder = []; + for (i = 0; i < $scope.monitors.length; i++) { + montageOrder[i] = i; + hiddenOrder[i] = 0; + } + + loginData.montageOrder = montageOrder.toString(); + loginData.montageHiddenOrder = hiddenOrder.toString(); + NVRDataModel.setLogin(loginData); + //window.localStorage.setItem("montageOrder", montageOrder.toString()); + //window.localStorage.setItem("montageHiddenOrder", hiddenOrder.toString()); + NVRDataModel.log("Montage order saved on refresh: " + montageOrder.toString() + " and hidden order: " + hiddenOrder.toString()); + + }); + }; + + $scope.saveReorder = function () { + loginData.montageOrder = montageOrder.toString(); + loginData.montageHiddenOrder = hiddenOrder.toString(); + NVRDataModel.setLogin(loginData); + //window.localStorage.setItem("montageOrder", montageOrder.toString()); + // window.localStorage.setItem("montageHiddenOrder", + // hiddenOrder.toString()); + //console.log("Saved " + montageOrder.toString()); + NVRDataModel.log("User press OK. Saved Monitor Order as: " + + montageOrder.toString() + + " and hidden order as " + hiddenOrder.toString()); + $scope.modal.remove(); + }; + + $scope.cancelReorder = function () { + // user tapped cancel + var i, myhiddenorder; + if (loginData.montageOrder == '') { + //if (window.localStorage.getItem("montageOrder") == undefined) { + for (i = 0; i < $scope.MontageMonitors.length; i++) { + montageOrder[i] = i; + hiddenOrder[i] = 0; + } + //console.log("Order string is " + montageOrder.toString()); + NVRDataModel.log("User press Cancel. Reset Monitor Order to: " + montageOrder.toString()); + } else // montageOrder exists + { + var myorder = loginData.montageOrder; + + if (loginData.montageHiddenOrder == '') { + for (i = 0; i < $scope.MontageMonitors.length; i++) { + hiddenOrder[i] = 0; + } + } else { + myhiddenorder = loginData.montageHiddenOrder; + hiddenOrder = myhiddenorder.split(","); + } + + //console.log("Montage order is " + myorder + " and hidden order is " + myhiddenorder); + montageOrder = myorder.split(","); + + for (i = 0; i < montageOrder.length; i++) { + montageOrder[i] = parseInt(montageOrder[i]); + hiddenOrder[i] = parseInt(hiddenOrder[i]); + } + + $scope.MontageMonitors = oldMonitors; + NVRDataModel.log("User press Cancel. Restored Monitor Order as: " + montageOrder.toString() + " and hidden order as: " + hiddenOrder.toString()); + + } + $scope.modal.remove(); + }; + + $scope.toggleReorder = function () { + $scope.isReorder = !$scope.isReorder; + $scope.data = {}; + $scope.data.showDelete = false; + $scope.data.showReorder = false; + + var i; + oldMonitors = angular.copy($scope.monitors); + /*for (i=0; i<$scope.monitors.length; i++) + { + $scope.monitors[i].Monitor.listDisplay="show"; + }*/ + + ld = NVRDataModel.getLogin(); + if (ld.enableDebug) { + // Lets show the re-order list + for (i = 0; i < $scope.MontageMonitors.length; i++) { + NVRDataModel.debug("Montage reorder list: " + $scope.MontageMonitors[i].Monitor.Name + + ":listdisplay->" + $scope.MontageMonitors[i].Monitor.listDisplay); + + } + } + + $ionicModal.fromTemplateUrl('templates/reorder-modal.html', { + scope: $scope, + animation: 'slide-in-up' + }) + .then(function (modal) { + $scope.modal = modal; + $scope.modal.show(); + }); + + + + }; + + /* + $scope.onSwipeLeft = function ($index) { + $scope.showSizeButtons = true; + }; + + $scope.onSwipeRight = function ($index) { + $timeout(function () { + $scope.showSizeButtons = false; + }, 1000); + + };*/ + + //--------------------------------------------------------------------- + // This marks a monitor as hidden in montage view + //--------------------------------------------------------------------- + + $scope.deleteItem = function (index) { + var findindex = montageOrder.indexOf(index); + // $scope.monitors[index].Monitor.Function = 'None'; + if ($scope.MontageMonitors[index].Monitor.listDisplay == 'show') { + $scope.MontageMonitors[index].Monitor.listDisplay = 'noshow'; + hiddenOrder[findindex] = 1; + } else { + $scope.MontageMonitors[index].Monitor.listDisplay = 'show'; + // we need to find the index of Montage Order that contains index + // because remember, hiddenOrder does not change its orders as monitors + // move + + hiddenOrder[findindex] = 0; + } + //window.localStorage.setItem("montageOrder", montageOrder.toString()); + //console.log("DELETE: Order Array now is " + montageOrder.toString()); + //console.log("DELETE: Hidden Array now is " + hiddenOrder.toString()); + NVRDataModel.log("Marked monitor " + findindex + " as " + $scope.MontageMonitors[index].Monitor.listDisplay + " in montage"); + + }; + + //--------------------------------------------------------------------- + // When we re-arrange the montage, all the ordering index moves + // horrible horrible code + //--------------------------------------------------------------------- + + function reorderItem(item, from, to, reorderHidden) { + + NVRDataModel.debug("MontageHistoryCtrl: Reorder from " + from + " to " + to); + $scope.MontageMonitors.splice(from, 1); + $scope.MontageMonitors.splice(to, 0, item); + + // Now we need to re-arrange the montageOrder + // hiddenOrder remains the same + + var i, j; + for (i = 0; i < $scope.monitors.length; i++) { + for (j = 0; j < $scope.MontageMonitors.length; j++) { + if ($scope.monitors[i].Monitor.Id == $scope.MontageMonitors[j].Monitor.Id) { + montageOrder[i] = j; + break; + } + } + } + NVRDataModel.log("New Montage Order is: " + montageOrder.toString()); + + } + + + $scope.reorderItem = function (item, from, to) { + reorderItem(item, from, to, true); + }; + + + //--------------------------------------------------------------------- + // Triggered when you enter/exit full screen + //--------------------------------------------------------------------- + $scope.switchMinimal = function () { + $scope.minimal = !$scope.minimal; + NVRDataModel.debug("MontageHistoryCtrl: switch minimal is " + $scope.minimal); + //console.log("Hide Statusbar"); + ionic.Platform.fullScreen($scope.minimal, !$scope.minimal); + $interval.cancel(intervalHandle); //we will renew on reload + // We are reloading this view, so we don't want entry animations + $ionicHistory.nextViewOptions({ + disableAnimate: true, + disableBack: true + }); + $state.go("montage", { + minimal: $scope.minimal, + isRefresh: true + }); + }; + + + $scope.toggleSelectItem = function (ndx) { + + if ($scope.MontageMonitors[ndx].Monitor.selectStyle !== "undefined" && $scope.MontageMonitors[ndx].Monitor.selectStyle == "dragborder-selected") { + $scope.MontageMonitors[ndx].Monitor.selectStyle = ""; + } else { + $scope.MontageMonitors[ndx].Monitor.selectStyle = "dragborder-selected"; + } + //console.log ("Switched value to " + $scope.MontageMonitors[ndx].Monitor.selectStyle); + }; + //--------------------------------------------------------------------- + // Called when you enable/disable dragging + //--------------------------------------------------------------------- + + $scope.dragToggle = function () { + dragToggle(); + + + }; + + function dragToggle() { + var i; + $scope.isDragabillyOn = !$scope.isDragabillyOn; + + $ionicSideMenuDelegate.canDragContent($scope.isDragabillyOn ? false : true); + + //$timeout(function(){pckry.reloadItems();},10); + NVRDataModel.debug("setting dragabilly to " + $scope.isDragabillyOn); + if ($scope.isDragabillyOn) { + $scope.showSizeButtons = true; + + $scope.dragBorder = "dragborder"; + NVRDataModel.debug("Enabling drag for " + draggies.length + " items"); + for (i = 0; i < draggies.length; i++) { + draggies[i].enable(); + draggies[i].bindHandles(); + } + + // reflow and reload as some may be hidden + // $timeout(function(){pckry.reloadItems();$timeout(function(){pckry.layout();},300);},100); + } else { + $scope.dragBorder = ""; + NVRDataModel.debug("Disabling drag for " + draggies.length + " items"); + for (i = 0; i < draggies.length; i++) { + draggies[i].disable(); + draggies[i].unbindHandles(); + } + for (i = 0; i < $scope.MontageMonitors.length; i++) { + $scope.MontageMonitors[i].Monitor.selectStyle = ""; + } + // reflow and reload as some may be hidden + $timeout(function () { + $timeout(function () { + pckry.shiftLayout(); + /*var positions = pckry.getShiftPositions('data-item-id'); + //console.log ("POSITIONS MAP " + JSON.stringify(positions)); + var ld = NVRDataModel.getLogin(); + ld.packeryPositions = JSON.stringify(positions); + NVRDataModel.setLogin(ld);*/ + }, 300); + }, 100); + + } + } + //--------------------------------------------------------------------- + // Show/Hide PTZ control in monitor view + //--------------------------------------------------------------------- + $scope.togglePTZ = function () { + $scope.showPTZ = !$scope.showPTZ; + }; + + $scope.callback = function () { + // console.log("dragging"); + }; + + + $scope.onDropComplete = function (index, obj, event) { + //console.log("dragged"); + var otherObj = $scope.monitors[index]; + var otherIndex = $scope.monitors.indexOf(obj); + $scope.monitors[index] = obj; + $scope.monitors[otherIndex] = otherObj; + }; + + + + + //--------------------------------------------------------------------- + // changes order of montage display + //--------------------------------------------------------------------- + + $scope.toggleMontageDisplayOrder = function () { + $scope.packMontage = !$scope.packMontage; + loginData.packMontage = $scope.packMontage; + NVRDataModel.setLogin(loginData); + //console.log ("Switching orientation"); + }; + + + //--------------------------------------------------------------------- + // In Android, the app runs full steam while in background mode + // while in iOS it gets suspended unless you ask for specific resources + // So while this view, we DON'T want Android to keep sending 1 second + // refreshes to the server for images we are not seeing + //--------------------------------------------------------------------- + + function onPause() { + NVRDataModel.debug("MontageHistoryCtrl: onpause called"); + $interval.cancel($rootScope.eventQueryInterval); + $interval.cancel(intervalHandle); + + // $interval.cancel(modalIntervalHandle); + + // FIXME: Do I need to setAwake(false) here? + } + + + function onResume() { + + // FIXME: Do we need to resume timers? when you resume, you go to portal and then here + /* + if (!$scope.isModalActive) { + var ld = NVRDataModel.getLogin(); + + + NVRDataModel.debug("MontageHistoryCtrl: onresume called"); + NVRDataModel.log("Restarting eventQuery timer on resume"); + + console.log ("************** TIMER STARTED INSIDE RESUME ***************"); + + //$rootScope.rand = Math.floor((Math.random() * 100000) + 1); + $interval.cancel($rootScope.eventQueryInterval); + $rootScope.eventQueryInterval = $interval(function () { + checkAllEvents(); + // console.log ("Refreshing Image..."); + }.bind(this),zm.eventHistoryTimer); + } else // modal is active + { + // $rootScope.modalRand = Math.floor((Math.random() * 100000) + 1); + }*/ + + + + + } + + $scope.openMenu = function () { + $timeout(function () { + $rootScope.stateofSlide = $ionicSideMenuDelegate.isOpen(); + }, 500); + + $ionicSideMenuDelegate.toggleLeft(); + }; + + $scope.$on('$destroy', function () { + NVRDataModel.debug("Cancelling eventQueryInterval"); + $interval.cancel($rootScope.eventQueryInterval); + + + + + }); + + + $scope.$on('$ionicView.loaded', function () { + //console.log("**VIEW ** MontageHistoryCtrl Loaded"); + }); + + $scope.$on('$ionicView.enter', function () { + NVRDataModel.debug("**VIEW ** MontageHistory Ctrl Entered"); + var ld = NVRDataModel.getLogin(); + //console.log("Setting Awake to " + NVRDataModel.getKeepAwake()); + NVRDataModel.setAwake(NVRDataModel.getKeepAwake()); + + $interval.cancel($rootScope.eventQueryInterval); + //console.log ("****************** TIMER STARTED INSIDE ENTER"); + $rootScope.eventQueryInterval = $interval(function () { + checkAllEvents(); + // console.log ("Refreshing Image..."); + }.bind(this), zm.eventHistoryTimer); + + + + + + }); + + /*$scope.$on ('$ionicView.unloaded', function() { + console.log ("******** HISTORY UNLOADED KILLING WINDOW ************"); + window.stop(); + });*/ + + + $scope.$on('$ionicView.beforeEnter', function () { + + // NVRDataModel.log ("Before Enter History: initing connkeys"); + + + + + + }); + + $scope.$on('$ionicView.beforeLeave', function () { + //console.log("**VIEW ** Event History Ctrl Left, force removing modal"); + if ($scope.modal) $scope.modal.remove(); + + + NVRDataModel.log("BeforeLeave: Nullifying the streams..."); + + for (i = 0; i < $scope.MontageMonitors.length; i++) { + var element = document.getElementById("img-" + i); + /*if (element) + { + NVRDataModel.debug("BeforeLeave: Nullifying " + element.src); + element.src=""; + //element.removeAttribute('src'); + + //$scope.$apply(nullify(element)); + //element.src=""; + }*/ + + } + + + + NVRDataModel.log("Cancelling event query timer"); + $interval.cancel($rootScope.eventQueryInterval); + + NVRDataModel.log("MontageHistory:Stopping network pull..."); + // make sure this is applied in scope digest to stop network pull + // thats why we are doing it beforeLeave + + for (i = 0; i < $scope.MontageMonitors.length; i++) { + if ($scope.MontageMonitors[i].Monitor.connKey != '' && + $scope.MontageMonitors[i].Monitor.eventUrl != 'img/noevent.png' && + $scope.MontageMonitors[i].Monitor.Function != 'None' && + $scope.MontageMonitors[i].Monitor.lisDisplay != 'noshow' && + $scope.MontageMonitors[i].Monitor.Enabled != '0') { + NVRDataModel.log("Before leave: Calling kill with " + $scope.MontageMonitors[i].Monitor.connKey); + var tmpCK = angular.copy($scope.MontageMonitors[i].Monitor.connKey); + timedControlEventStream(2500, 17, "", tmpCK, -1); + } + } + + pckry.destroy(); + window.removeEventListener("resize", orientationChanged, false); + + NVRDataModel.log("Forcing a window.stop() here"); + NVRDataModel.stopNetwork("MontageHistory-beforeLeave"); + + + + + }); + + $scope.$on('$ionicView.unloaded', function () { + + }); + + + $scope.sliderChanged = function (dirn) { + console.log("SLIDER CHANGED"); + if ($scope.sliderChanging) { + // console.log ("too fast my friend"); + //$scope.slider.monsize = oldSliderVal; + // return; + } + + $scope.sliderChanging = true; + + var somethingReset = false; + + // this only changes items that are selected + for (var i = 0; i < $scope.MontageMonitors.length; i++) { + + var curVal = parseInt($scope.MontageMonitors[i].Monitor.gridScale); + curVal = curVal + (10 * dirn); + if (curVal < 10) curVal = 10; + if (curVal > 100) curVal = 100; + //console.log ("For Index: " + i + " From: " + $scope.MontageMonitors[i].Monitor.gridScale + " To: " + curVal); + + if ($scope.isDragabillyOn) { + // only do this for selected monitors + if ($scope.MontageMonitors[i].Monitor.selectStyle == "dragborder-selected") { + + $scope.MontageMonitors[i].Monitor.gridScale = curVal; + somethingReset = true; + } + } else { + $scope.MontageMonitors[i].Monitor.gridScale = curVal; + //somethingReset = true; + + } + + } + + // this changes all items if none were selected + if (!somethingReset && $scope.isDragabillyOn) // nothing was selected + { + for (i = 0; i < $scope.MontageMonitors.length; i++) { + var cv = parseInt($scope.MontageMonitors[i].Monitor.gridScale); + cv = cv + (10 * dirn); + if (cv < 10) cv = 10; + if (cv > 100) cv = 100; + $scope.MontageMonitors[i].Monitor.gridScale = cv; + } + } + + + //pckry.reloadItems(); + + pckry.once('layoutComplete', function () { + /* $timeout(function () { + var positions = pckry.EHgetShiftPositions('eh-data-item-id'); + //console.log ("POSITIONS MAP " + JSON.stringify(positions)); + var ld = NVRDataModel.getLogin(); + ld.EHpackeryPositions = JSON.stringify(positions); + NVRDataModel.setLogin(ld); + $ionicLoading.hide(); + $scope.sliderChanging = false; + }, zm.packeryTimer);*/ + }); + + + + if (!somethingReset) { + //console.log (">>>SOMETHING NOT RESET"); + $timeout(function () { + pckry.layout(); + }, zm.packeryTimer); + } else { + + //console.log (">>>SOMETHING RESET"); + $timeout(function () { + layout(pckry); + }, zm.packeryTimer); + } + + + + + }; + + function layout(pckry) { + pckry.shiftLayout(); + } + + + + $scope.resetSizes = function () { + var somethingReset = false; + for (var i = 0; i < $scope.MontageMonitors.length; i++) { + if ($scope.isDragabillyOn) { + if ($scope.MontageMonitors[i].Monitor.selectStyle == "dragborder-selected") { + $scope.MontageMonitors[i].Monitor.gridScale = "50"; + somethingReset = true; + } + } else { + $scope.MontageMonitors[i].Monitor.gridScale = "50"; + // somethingReset = true; + } + } + if (!somethingReset && $scope.isDragabillyOn) // nothing was selected + { + for (i = 0; i < $scope.MontageMonitors.length; i++) { + $scope.MontageMonitors[i].Monitor.gridScale = "50"; + } + } + + $timeout(function () { + pckry.reloadItems(); + + + $timeout(function () { + pckry.layout(); + }, zm.packeryTimer); // force here - no shiftlayout + + + }, 100); + + }; + + + //--------------------------------------------------------- + // This function readjusts montage size + // and stores current size to persistent memory + //--------------------------------------------------------- + + function processSliderChanged(val) { + if (sizeInProgress) return; + + sizeInProgress = true; + //console.log('Size has changed'); + NVRDataModel.setMontageSize(val); + //console.log("ZMData Montage is " + NVRDataModel.getMontageSize() + + // " and slider montage is " + $scope.slider.monsize); + // Now go ahead and reset sizes of entire monitor array + var monsizestring = ""; + var i; + for (i = 0; i < $scope.monitors.length; i++) { + + $scope.monitorSize[i] = parseInt(NVRDataModel.getMontageSize()); + //console.log("Resetting Monitor " + i + " size to " + $scope.monitorSize[i]); + $scope.scaleDirection[i] = 1; + monsizestring = monsizestring + $scope.monitorSize[i] + ':'; + } + monsizestring = monsizestring.slice(0, -1); // kill last : + //console.log("Setting monsize string:" + monsizestring); + loginData.montageArraySize = monsizestring; + NVRDataModel.setLogin(loginData); + //window.localStorage.setItem("montageArraySize", monsizestring); + sizeInProgress = false; + } + + function isEmpty(obj) { + for (var prop in obj) { + return false; + } + return true; + } + + // called by afterEnter to load Packery + function initPackery() { + + console.log(">>>>>>>>>>>>>>>>> HIT INIT"); + $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 == '') { + if (1) { + + NVRDataModel.log("Did NOT find a EHpackery layout"); + layouttype = true; + } else { + + //console.log ("POSITION STR IS " + positionsStr); + positions = JSON.parse(positionsStr); + NVRDataModel.log("found a EHpackery layout"); + console.log(positionsStr); + 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)); + + imagesLoaded(elem).on('progress', function (instance, img) { + + progressCalled = true; + + // if (layouttype) $timeout (function(){layout(pckry);},100); + }); + + imagesLoaded(elem).once('always', function () { + console.log("******** ALL IMAGES LOADED"); + NVRDataModel.debug("All images loaded"); + $scope.allImagesLoaded = true; + + $ionicLoading.hide(); + + pckry = new Packery('.grid', { + itemSelector: '.grid-item', + percentPosition: true, + columnWidth: '.grid-sizer', + gutter: 0, + initLayout: layouttype + + }); + if (!progressCalled) { + NVRDataModel.log("*** BUG PROGRESS WAS NOT CALLED"); + pckry.reloadItems(); + + } + + $timeout(function () { + var cnt = 0; + pckry.getItemElements().forEach(function (itemElem) { + + console.log("DRAG ADD " + cnt++); + 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) { + $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 () { + pckry.initShiftLayout(positions, 'eh-data-item-id'); + }, 0);*/ + } + $timeout(function () { + NVRDataModel.log("Force calling resize"); + pckry.layout(); + }, zm.packeryTimer); // don't ask + + + + }, zm.packeryTimer); + + }); + + function itemDragged(item) { + NVRDataModel.debug("drag complete"); + + //pckry.getItemElements().forEach(function (itemElem) { + + //console.log (itemElem.attributes['data-item-id'].value+" size "+itemElem.attributes['data-item-size'].value ); + // }); + + /* var positions = pckry.EHgetShiftPositions('eh-data-item-id'); + //console.log ("POSITIONS MAP " + JSON.stringify(positions)); + var ld = NVRDataModel.getLogin(); + ld.EHpackeryPositions = JSON.stringify(positions); + NVRDataModel.setLogin(ld);*/ + } + + + } + + + $scope.$on('$ionicView.afterEnter', function () { + // This rand is really used to reload the monitor image in img-src so it is not cached + // I am making sure the image in montage view is always fresh + // I don't think I am using this anymore FIXME: check and delete if needed + // $rootScope.rand = Math.floor((Math.random() * 100000) + 1); + + $timeout(function () { + initPackery(); + }, zm.packeryTimer); + }); + + $scope.reloadView = function () { + $rootScope.rand = Math.floor((Math.random() * 100000) + 1); + NVRDataModel.log("User action: image reload " + $rootScope.rand); + }; + + $scope.doRefresh = function () { + + + + //console.log("***Pull to Refresh, recomputing Rand"); + NVRDataModel.log("Reloading view for montage view, recomputing rand"); + $rootScope.rand = Math.floor((Math.random() * 100000) + 1); + $scope.monitors = []; + imageLoadingDataShare.set(0); + + var refresh = NVRDataModel.getMonitors(1); + + refresh.then(function (data) { + $scope.monitors = data; + $scope.$broadcast('scroll.refreshComplete'); + }); + }; + + //--------------------------------------------------------------------- + // Controller main + //--------------------------------------------------------------------- + + + + var intervalHandle; + $scope.isModalActive = false; + var modalIntervalHandle; + + window.addEventListener("resize", orientationChanged, false); + + document.addEventListener("pause", onPause, false); + document.addEventListener("resume", onResume, false); + + $scope.timeFormat = "yyyy-MM-dd " + NVRDataModel.getTimeFormat(); + $scope.displayDateTimeSliders = true; + $scope.showtimers = true; + $scope.loginData = NVRDataModel.getLogin(); + + var curYear = new Date().getFullYear(); + + var readyToRun = false; + var i; + + $scope.sliderVal = { + + rate: 1, + realRate: 100, + hideNoEvents: false, + enableGapless: true, + exactMatch: false, + showTimeline: true + + }; + + + + // default = start of day + var timeto = moment(); + var timefrom = moment().startOf('day'); + + $scope.sliderVal.rate = 1; + $scope.sliderVal.realRate = $scope.sliderVal.rate * 100; + + + + //var tdatetimeValueFrom = new Date(); + //tdatetimeValueFrom.setDate(tdatetimeValueFrom.getDate()-1); + + $scope.datetimeValueFrom = { + value: "" + }; + $scope.datetimeValueTo = { + value: "" + }; + + $scope.datetimeValueFrom.value = timefrom.toDate(); + $scope.datetimeValueTo.value = timeto.toDate(); + + $rootScope.eventQueryInterval = ""; + + + var commonCss = { + + background: { + "background-color": "silver" + }, + before: { + "background-color": "purple" + }, + default: { + "background-color": "white" + }, // default value: 1px + after: { + "background-color": "green" + }, // zone after default value + pointer: { + "background-color": "red" + }, // circle pointer + range: { + "background-color": "red" + } // use it if double value + }; + + + $scope.slider_modal_options_rate = { + from: 1, + to: 10, + realtime: true, + step: 1, + className: "mySliderClass", + //modelLabels:function(val) {return "";}, + smooth: false, + css: commonCss, + dimension: 'X' + + }; + + + + var isLongPressActive = false; + $scope.isReorder = false; + var intervalHandleMontage; // will hold image resize timer on long press + var montageIndex = 0; // will hold monitor ID to scale in timer + + var gridcontainer, pckry, draggie, draggies; + + $scope.monitorSize = []; // array with montage sizes per monitor + $scope.scaleDirection = []; // 1 = increase -1 = decrease + + $scope.slider = {}; + + //console.log ("************ HISTORY " + NVRDataModel.getMontageSize()); + $scope.slider.monsize = NVRDataModel.getMontageSize(); + $scope.revMonSize = 11 - parseInt($scope.slider.monsize); + + // The difference between old and original is this: + // old will have a copy of the last re-arranged monitor list + // while original will have a copy of the order returned by ZM + + var oldMonitors = []; // To keep old order if user cancels after sort; + + // Montage display order may be different so don't + // mangle monitors as it will affect other screens + // in Montage screen we will work with this local copy + //$scope.MontageMonitors = angular.copy ($scope.monitors); + + var montageOrder = []; // This array will keep the ordering in montage view + var hiddenOrder = []; // 1 = hide, 0 = don't hide + + var tempMonitors = message; + if (tempMonitors.length == 0) { + $rootScope.zmPopup = $ionicPopup.alert({ + title: $translate.instant('kNoMonitors'), + template: $translate.instant('kPleaseCheckCredentials') + }); + $ionicHistory.nextViewOptions({ + disableBack: true + }); + $state.go("login"); + return; + } + + // console.log ("TEMP MONITORS IS " + JSON.stringify(tempMonitors)); + var tempResponse = NVRDataModel.applyMontageMonitorPrefs(message, 0); + $scope.monitors = tempResponse[0]; + montageOrder = tempResponse[1]; + hiddenOrder = tempResponse[2]; + + NVRDataModel.log("Inside MontageHistoryCtrl:We found " + $scope.monitors.length + " monitors"); + + $scope.MontageMonitors = NVRDataModel.applyMontageMonitorPrefs(message, 1)[0]; + + var loginData = NVRDataModel.getLogin(); + + $scope.packMontage = loginData.packMontage; + + + // init monitors + NVRDataModel.debug(">>Initializing connkeys and images..."); + for (i = 0; i < $scope.MontageMonitors.length; i++) { + //$scope.MontageMonitors[i].Monitor.connKey=''; + + + + $scope.MontageMonitors[i].Monitor.connKey = (Math.floor((Math.random() * 999999) + 1)).toString(); + $scope.MontageMonitors[i].Monitor.eventUrl = 'img/noevent.png'; + $scope.MontageMonitors[i].Monitor.eventUrlTime = ""; + $scope.MontageMonitors[i].Monitor.isPaused = false; + $scope.MontageMonitors[i].Monitor.gridScale = "50"; + $scope.MontageMonitors[i].Monitor.selectStyle = ""; + $scope.MontageMonitors[i].Monitor.alarmState = 'color:rgba(0,0,0,0);'; + + } + readyToRun = true; + + + + // -------------------------------------------------------- + // Handling of back button in case modal is open should + // close the modal + // -------------------------------------------------------- + + $ionicPlatform.registerBackButtonAction(function (e) { + e.preventDefault(); + if ($scope.modal && $scope.modal.isShown()) { + // switch off awake, as liveview is finished + NVRDataModel.debug("Modal is open, closing it"); + NVRDataModel.setAwake(false); + $scope.modal.remove(); + $scope.isModalActive = false; + } else { + NVRDataModel.debug("Modal is closed, so toggling or exiting"); + if (!$ionicSideMenuDelegate.isOpenLeft()) { + $ionicSideMenuDelegate.toggleLeft(); + + } else { + navigator.app.exitApp(); + } + + } + + }, 1000); + + + + + $scope.showSizeButtons = false; + $ionicPopover.fromTemplateUrl('templates/help/montage-help.html', { + scope: $scope, + }).then(function (popover) { + $scope.popover = popover; + }); + + var timestamp = new Date().getUTCMilliseconds(); + $scope.minimal = $stateParams.minimal; + $scope.zmMarginTop = $scope.minimal ? 0 : 15; + //console.log ("********* MARGIN IS " + $scope.zmMarginTop); + + $scope.isRefresh = $stateParams.isRefresh; + var sizeInProgress = false; + $scope.imageStyle = true; + + $ionicSideMenuDelegate.canDragContent(true); + + + + // Do we have a saved montage array size? No? + // if (window.localStorage.getItem("montageArraySize") == undefined) { + if (loginData.montageArraySize == '0') { + + for (i = 0; i < $scope.monitors.length; i++) { + $scope.monitorSize.push(NVRDataModel.getMontageSize()); + $scope.scaleDirection.push(1); + } + } else // recover previous settings + { + var msize = loginData.montageArraySize; + //console.log("MontageArrayString is=>" + msize); + $scope.monitorSize = msize.split(":"); + var j; + + for (j = 0; j < $scope.monitorSize.length; j++) { + // convert to number other wise adding to it concatenates :-) + $scope.monitorSize[j] = parseInt($scope.monitorSize[j]); + $scope.scaleDirection.push(1); + //console.log("Montage size for monitor " + j + " is " + $scope.monitorSize[j]); + + } + + } + // $scope.monitorSize = monitorSize; + // $scope.scaleDirection = scaleDirection; + + $scope.LoginData = NVRDataModel.getLogin(); + $scope.monLimit = $scope.LoginData.maxMontage; + + if ($rootScope.platformOS != 'ios') { + NVRDataModel.log("Limiting montage to 5, thanks to Chrome's stupid connection limit"); + $scope.monLimit = 5; + } + + //console.log("********* Inside MontageHistoryCtrl, MAX LIMIT=" + $scope.monLimit); + + + $rootScope.authSession = "undefined"; + $ionicLoading.show({ + template: $translate.instant('kNegotiatingStreamAuth'), + animation: 'fade-in', + showBackdrop: true, + duration: zm.loadingTimeout, + maxWidth: 300, + showDelay: 0 + }); + + + var ld = NVRDataModel.getLogin(); + + //console.log ("MONITORS " + JSON.stringify($scope.monitors)); + $rootScope.validMonitorId = $scope.monitors[0].Monitor.Id; + NVRDataModel.getAuthKey($rootScope.validMonitorId) + .then(function (success) { + $ionicLoading.hide(); + //console.log(success); + $rootScope.authSession = success; + NVRDataModel.log("Stream authentication construction: " + + $rootScope.authSession); + + }, + function (error) { + + $ionicLoading.hide(); + NVRDataModel.debug("MontageHistoryCtrl: Error in authkey retrieval " + error); + //$rootScope.authSession=""; + NVRDataModel.log("MontageHistoryCtrl: Error returned Stream authentication construction. Retaining old value of: " + $rootScope.authSession); + }); + + + + + + + +}]);
\ No newline at end of file diff --git a/www/js/app.js b/www/js/app.js index 034a89c6..b543efaf 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -28,7 +28,8 @@ angular.module('zmApp', [ 'com.2fdevs.videogular.plugins.overlayplay', 'ionic-native-transitions', 'mgo-angular-wizard', - 'pascalprecht.translate' + 'pascalprecht.translate', + 'jett.ionic.scroll.sista' @@ -1265,7 +1266,10 @@ angular.module('zmApp', [ } if (window.StatusBar) { // org.apache.cordova.statusbar required + NVRDataModel.log("Updating statusbar"); StatusBar.styleDefault(); + //StatusBar.overlaysWebView(false); + StatusBar.backgroundColorByHexString("#2980b9"); } @@ -1762,7 +1766,7 @@ angular.module('zmApp', [ }, url: "/montage-history", - templateUrl: "templates/montage-history.html", + templateUrl: "templates/montage-history2.html", controller: 'zmApp.MontageHistoryCtrl', params: { minimal: false, diff --git a/www/lib/ionic-content-banner/.bower.json b/www/lib/ionic-content-banner/.bower.json new file mode 100644 index 00000000..b5f74569 --- /dev/null +++ b/www/lib/ionic-content-banner/.bower.json @@ -0,0 +1,10 @@ +{ + "name": "ionic-content-banner", + "_cacheHeaders": { + "Content-Type": "text/html; charset=utf-8" + }, + "main": "index", + "_source": "https://github.com/pliablepixels/ionic-content-banner", + "_target": "*", + "_originalSource": "https://github.com/pliablepixels/ionic-content-banner" +}
\ No newline at end of file diff --git a/www/lib/ionic-content-banner/index b/www/lib/ionic-content-banner/index new file mode 100644 index 00000000..7cd1a9cd --- /dev/null +++ b/www/lib/ionic-content-banner/index @@ -0,0 +1,994 @@ + + + + +<!DOCTYPE html> +<html lang="en" class=""> + <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#"> + <meta charset='utf-8'> + + + <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-4736542a9762352d9c02b0e277f6ccd6d3d8d4e5bf6bf9eba242c089a1d313cc.css" media="all" rel="stylesheet" /> + <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/github-32986c0e3d905f34959de0ab6880e1cb667dfeaa0d61a2b6c6d1c947c9c2cad7.css" media="all" rel="stylesheet" /> + + + <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/site-f6ce114ac3bc145f575863b4a6dbdf65e924bccb184fc4d4a4f5a09819b4173d.css" media="all" rel="stylesheet" /> + + + <link as="script" href="https://assets-cdn.github.com/assets/frameworks-411d610e4b2b1ffa3d063904534406d08c8351d9ba9b4b3f339bab35e86bb4f3.js" rel="preload" /> + + <link as="script" href="https://assets-cdn.github.com/assets/github-877cf6bfb710d9ccb14e4a6841ffe0fe6b52fec0f230b1f594ed779dc6ba0f94.js" rel="preload" /> + + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta http-equiv="Content-Language" content="en"> + <meta name="viewport" content="width=device-width"> + + <title>GitHub - pliablepixels/ionic-content-banner: An informational content banner for Ionic applications</title> + <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> + <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> + <link rel="apple-touch-icon" href="/apple-touch-icon.png"> + <link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png"> + <meta property="fb:app_id" content="1401488693436528"> + + <meta content="https://avatars0.githubusercontent.com/u/4116654?v=3&s=400" name="twitter:image:src" /><meta content="@github" name="twitter:site" /><meta content="summary" name="twitter:card" /><meta content="pliablepixels/ionic-content-banner" name="twitter:title" /><meta content="ionic-content-banner - An informational content banner for Ionic applications" name="twitter:description" /> + <meta content="https://avatars0.githubusercontent.com/u/4116654?v=3&s=400" property="og:image" /><meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="pliablepixels/ionic-content-banner" property="og:title" /><meta content="https://github.com/pliablepixels/ionic-content-banner" property="og:url" /><meta content="ionic-content-banner - An informational content banner for Ionic applications" property="og:description" /> + <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> + <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> + <link rel="assets" href="https://assets-cdn.github.com/"> + + <meta name="pjax-timeout" content="1000"> + + <meta name="request-id" content="32BE7664:1A6B0:92D092A:57EC009B" data-pjax-transient> + + <meta name="msapplication-TileImage" content="/windows-tile.png"> + <meta name="msapplication-TileColor" content="#ffffff"> + <meta name="selected-link" value="repo_source" data-pjax-transient> + + <meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU"> +<meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA"> + <meta name="google-analytics" content="UA-3769691-2"> + +<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="github" name="octolytics-app-id" /><meta content="32BE7664:1A6B0:92D092A:57EC009B" name="octolytics-dimension-request_id" /> +<meta content="/<user-name>/<repo-name>" data-pjax-transient="true" name="analytics-location" /> + + + + <meta class="js-ga-set" name="dimension1" content="Logged Out"> + + + + <meta name="hostname" content="github.com"> + <meta name="user-login" content=""> + + <meta name="expected-hostname" content="github.com"> + <meta name="js-proxy-site-detection-payload" content="YWU2OThlMzk2YjI4NjJkY2ZmNWVlNDRmMjE3NTA5ZTY1ZWFkNGU0NTA0Mzg2ZmQzNzRlYTI3YTg1OWVlMDFiZHx7InJlbW90ZV9hZGRyZXNzIjoiNTAuMTkwLjExOC4xMDAiLCJyZXF1ZXN0X2lkIjoiMzJCRTc2NjQ6MUE2QjA6OTJEMDkyQTo1N0VDMDA5QiIsInRpbWVzdGFtcCI6MTQ3NTA4NDQ0M30="> + + + <link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#4078c0"> + <link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico"> + + <meta name="html-safe-nonce" content="9cfac0674d88b04428da35525c95a48f9ba043e2"> + <meta content="c8b66cb37a2451ec561568d352d4ce24d539cf6a" name="form-nonce" /> + + <meta http-equiv="x-pjax-version" content="129b01be0c3118dfa772025e0c9dcf56"> + + + + <meta name="description" content="ionic-content-banner - An informational content banner for Ionic applications"> + <meta name="go-import" content="github.com/pliablepixels/ionic-content-banner git https://github.com/pliablepixels/ionic-content-banner.git"> + + <meta content="4116654" name="octolytics-dimension-user_id" /><meta content="pliablepixels" name="octolytics-dimension-user_login" /><meta content="67287661" name="octolytics-dimension-repository_id" /><meta content="pliablepixels/ionic-content-banner" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="true" name="octolytics-dimension-repository_is_fork" /><meta content="39717988" name="octolytics-dimension-repository_parent_id" /><meta content="djett41/ionic-content-banner" name="octolytics-dimension-repository_parent_nwo" /><meta content="39717988" name="octolytics-dimension-repository_network_root_id" /><meta content="djett41/ionic-content-banner" name="octolytics-dimension-repository_network_root_nwo" /> + <link href="https://github.com/pliablepixels/ionic-content-banner/commits/master.atom" rel="alternate" title="Recent Commits to ionic-content-banner:master" type="application/atom+xml"> + + + <link rel="canonical" href="https://github.com/pliablepixels/ionic-content-banner" data-pjax-transient> + </head> + + + <body class="logged-out env-production vis-public fork"> + <div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div> + <a href="#start-of-content" tabindex="1" class="accessibility-aid js-skip-to-content">Skip to content</a> + + + + + + + + <header class="site-header js-details-container" role="banner"> + <div class="container-responsive"> + <a class="header-logo-invertocat" href="https://github.com/" aria-label="Homepage" data-ga-click="(Logged out) Header, go to homepage, icon:logo-wordmark"> + <svg aria-hidden="true" class="octicon octicon-mark-github" height="32" version="1.1" viewBox="0 0 16 16" width="32"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg> + </a> + + <button class="btn-link float-right site-header-toggle js-details-target" type="button" aria-label="Toggle navigation"> + <svg aria-hidden="true" class="octicon octicon-three-bars" height="24" version="1.1" viewBox="0 0 12 16" width="18"><path d="M11.41 9H.59C0 9 0 8.59 0 8c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zm0-4H.59C0 5 0 4.59 0 4c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zM.59 11H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1H.59C0 13 0 12.59 0 12c0-.59 0-1 .59-1z"></path></svg> + </button> + + <div class="site-header-menu"> + <nav class="site-header-nav site-header-nav-main"> + <a href="/personal" class="js-selected-navigation-item nav-item nav-item-personal" data-ga-click="Header, click, Nav menu - item:personal" data-selected-links="/personal /personal"> + Personal +</a> <a href="/open-source" class="js-selected-navigation-item nav-item nav-item-opensource" data-ga-click="Header, click, Nav menu - item:opensource" data-selected-links="/open-source /open-source"> + Open source +</a> <a href="/business" class="js-selected-navigation-item nav-item nav-item-business" data-ga-click="Header, click, Nav menu - item:business" data-selected-links="/business /business/partners /business/features /business/customers /business"> + Business +</a> <a href="/explore" class="js-selected-navigation-item nav-item nav-item-explore" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship /explore"> + Explore +</a> </nav> + + <div class="site-header-actions"> + <a class="btn btn-primary site-header-actions-btn" href="/join?source=header-repo" data-ga-click="(Logged out) Header, clicked Sign up, text:sign-up">Sign up</a> + <a class="btn site-header-actions-btn mr-2" href="/login?return_to=%2Fpliablepixels%2Fionic-content-banner" data-ga-click="(Logged out) Header, clicked Sign in, text:sign-in">Sign in</a> + </div> + + <nav class="site-header-nav site-header-nav-secondary"> + <a class="nav-item" href="/pricing">Pricing</a> + <a class="nav-item" href="/blog">Blog</a> + <a class="nav-item" href="https://help.github.com">Support</a> + <a class="nav-item header-search-link" href="https://github.com/search">Search GitHub</a> + <div class="header-search scoped-search site-scoped-search js-site-search" role="search"> + <!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="/pliablepixels/ionic-content-banner/search" class="js-site-search-form" data-scoped-search-url="/pliablepixels/ionic-content-banner/search" data-unscoped-search-url="/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div> + <label class="form-control header-search-wrapper js-chromeless-input-container"> + <div class="header-search-scope">This repository</div> + <input type="text" + class="form-control header-search-input js-site-search-focus js-site-search-field is-clearable" + data-hotkey="s" + name="q" + placeholder="Search" + aria-label="Search this repository" + data-unscoped-placeholder="Search GitHub" + data-scoped-placeholder="Search" + autocapitalize="off"> + </label> +</form></div> + + </nav> + </div> + </div> +</header> + + + + <div id="start-of-content" class="accessibility-aid"></div> + + <div id="js-flash-container"> +</div> + + + <div role="main"> + <div itemscope itemtype="http://schema.org/SoftwareSourceCode"> + <div id="js-repo-pjax-container" data-pjax-container> + +<div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav"> + <div class="container repohead-details-container"> + + + +<ul class="pagehead-actions"> + + <li> + <a href="/login?return_to=%2Fpliablepixels%2Fionic-content-banner" + class="btn btn-sm btn-with-count tooltipped tooltipped-n" + aria-label="You must be signed in to watch a repository" rel="nofollow"> + <svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"></path></svg> + Watch + </a> + <a class="social-count" href="/pliablepixels/ionic-content-banner/watchers" + aria-label="1 user is watching this repository"> + 1 + </a> + + </li> + + <li> + <a href="/login?return_to=%2Fpliablepixels%2Fionic-content-banner" + class="btn btn-sm btn-with-count tooltipped tooltipped-n" + aria-label="You must be signed in to star a repository" rel="nofollow"> + <svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74z"></path></svg> + Star + </a> + + <a class="social-count js-social-count" href="/pliablepixels/ionic-content-banner/stargazers" + aria-label="0 users starred this repository"> + 0 + </a> + + </li> + + <li> + <a href="/login?return_to=%2Fpliablepixels%2Fionic-content-banner" + class="btn btn-sm btn-with-count tooltipped tooltipped-n" + aria-label="You must be signed in to fork a repository" rel="nofollow"> + <svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg> + Fork + </a> + + <a href="/pliablepixels/ionic-content-banner/network" class="social-count" + aria-label="23 users are forked this repository"> + 23 + </a> + </li> +</ul> + + <h1 class="public "> + <svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg> + <span class="author" itemprop="author"><a href="/pliablepixels" class="url fn" rel="author">pliablepixels</a></span><!-- +--><span class="path-divider">/</span><!-- +--><strong itemprop="name"><a href="/pliablepixels/ionic-content-banner" data-pjax="#js-repo-pjax-container">ionic-content-banner</a></strong> + + <span class="fork-flag"> + <span class="text">forked from <a href="/djett41/ionic-content-banner">djett41/ionic-content-banner</a></span> + </span> +</h1> + + </div> + <div class="container"> + +<nav class="reponav js-repo-nav js-sidenav-container-pjax" + itemscope + itemtype="http://schema.org/BreadcrumbList" + role="navigation" + data-pjax="#js-repo-pjax-container"> + + <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> + <a href="/pliablepixels/ionic-content-banner" aria-selected="true" class="js-selected-navigation-item selected reponav-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches /pliablepixels/ionic-content-banner" itemprop="url"> + <svg aria-hidden="true" class="octicon octicon-code" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"></path></svg> + <span itemprop="name">Code</span> + <meta itemprop="position" content="1"> +</a> </span> + + + <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> + <a href="/pliablepixels/ionic-content-banner/pulls" class="js-selected-navigation-item reponav-item" data-hotkey="g p" data-selected-links="repo_pulls /pliablepixels/ionic-content-banner/pulls" itemprop="url"> + <svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg> + <span itemprop="name">Pull requests</span> + <span class="counter">0</span> + <meta itemprop="position" content="3"> +</a> </span> + + <a href="/pliablepixels/ionic-content-banner/projects" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /pliablepixels/ionic-content-banner/projects"> + <svg class="octicon" aria-hidden="true" version="1.1" width="15" height="16" viewBox="0 0 15 16"> + <path d="M1 15h13V1H1v14zM15 1v14a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1h13a1 1 0 0 1 1 1zm-4.41 11h1.82c.59 0 .59-.41.59-1V3c0-.59 0-1-.59-1h-1.82C10 2 10 2.41 10 3v8c0 .59 0 1 .59 1zm-4-2h1.82C9 10 9 9.59 9 9V3c0-.59 0-1-.59-1H6.59C6 2 6 2.41 6 3v6c0 .59 0 1 .59 1zM2 13V3c0-.59 0-1 .59-1h1.82C5 2 5 2.41 5 3v10c0 .59 0 1-.59 1H2.59C2 14 2 13.59 2 13z"></path> + </svg> + Projects + <span class="counter">0</span> +</a> + + + <a href="/pliablepixels/ionic-content-banner/pulse" class="js-selected-navigation-item reponav-item" data-selected-links="pulse /pliablepixels/ionic-content-banner/pulse"> + <svg aria-hidden="true" class="octicon octicon-pulse" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M11.5 8L8.8 5.4 6.6 8.5 5.5 1.6 2.38 8H0v2h3.6l.9-1.8.9 5.4L9 8.5l1.6 1.5H14V8z"></path></svg> + Pulse +</a> + <a href="/pliablepixels/ionic-content-banner/graphs" class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors /pliablepixels/ionic-content-banner/graphs"> + <svg aria-hidden="true" class="octicon octicon-graph" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"></path></svg> + Graphs +</a> + +</nav> + + </div> +</div> + +<div class="container new-discussion-timeline experiment-repo-nav"> + <div class="repository-content"> + + +<div class="repository-meta js-details-container"> + <span class="repository-meta-content"> + <span itemprop="about"> An informational content banner for Ionic applications</span> + </span> + +</div> + + +<div class="overall-summary overall-summary-bottomless"> + <div class="stats-switcher-viewport js-stats-switcher-viewport"> + <div class="stats-switcher-wrapper"> + <ul class="numbers-summary"> + <li class="commits"> + <a data-pjax href="/pliablepixels/ionic-content-banner/commits/master"> + <svg aria-hidden="true" class="octicon octicon-history" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M8 13H6V6h5v2H8v5zM7 1C4.81 1 2.87 2.02 1.59 3.59L0 2v4h4L2.5 4.5C3.55 3.17 5.17 2.3 7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-.34.03-.67.09-1H.08C.03 7.33 0 7.66 0 8c0 3.86 3.14 7 7 7s7-3.14 7-7-3.14-7-7-7z"></path></svg> + <span class="num text-emphasized"> + 22 + </span> + commits + </a> + </li> + <li> + <a data-pjax href="/pliablepixels/ionic-content-banner/branches"> + <svg aria-hidden="true" class="octicon octicon-git-branch" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path d="M10 5c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v.3c-.02.52-.23.98-.63 1.38-.4.4-.86.61-1.38.63-.83.02-1.48.16-2 .45V4.72a1.993 1.993 0 0 0-1-3.72C.88 1 0 1.89 0 3a2 2 0 0 0 1 1.72v6.56c-.59.35-1 .99-1 1.72 0 1.11.89 2 2 2 1.11 0 2-.89 2-2 0-.53-.2-1-.53-1.36.09-.06.48-.41.59-.47.25-.11.56-.17.94-.17 1.05-.05 1.95-.45 2.75-1.25S8.95 7.77 9 6.73h-.02C9.59 6.37 10 5.73 10 5zM2 1.8c.66 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2C1.35 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2zm0 12.41c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm6-8c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg> + <span class="num text-emphasized"> + 1 + </span> + branch + </a> + </li> + + <li> + <a data-pjax href="/pliablepixels/ionic-content-banner/releases"> + <svg aria-hidden="true" class="octicon octicon-tag" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M7.73 1.73C7.26 1.26 6.62 1 5.96 1H3.5C2.13 1 1 2.13 1 3.5v2.47c0 .66.27 1.3.73 1.77l6.06 6.06c.39.39 1.02.39 1.41 0l4.59-4.59a.996.996 0 0 0 0-1.41L7.73 1.73zM2.38 7.09c-.31-.3-.47-.7-.47-1.13V3.5c0-.88.72-1.59 1.59-1.59h2.47c.42 0 .83.16 1.13.47l6.14 6.13-4.73 4.73-6.13-6.15zM3.01 3h2v2H3V3h.01z"></path></svg> + <span class="num text-emphasized"> + 2 + </span> + releases + </a> + </li> + + <li> + <include-fragment src="/pliablepixels/ionic-content-banner/contributors_size"> + <a href="/pliablepixels/ionic-content-banner/graphs/contributors"> + <svg aria-hidden="true" class="octicon octicon-organization" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M16 12.999c0 .439-.45 1-1 1H7.995c-.539 0-.994-.447-.995-.999H1c-.54 0-1-.561-1-1 0-2.634 3-4 3-4s.229-.409 0-1c-.841-.621-1.058-.59-1-3 .058-2.419 1.367-3 2.5-3s2.442.58 2.5 3c.058 2.41-.159 2.379-1 3-.229.59 0 1 0 1s1.549.711 2.42 2.088C9.196 9.369 10 8.999 10 8.999s.229-.409 0-1c-.841-.62-1.058-.59-1-3 .058-2.419 1.367-3 2.5-3s2.437.581 2.495 3c.059 2.41-.158 2.38-1 3-.229.59 0 1 0 1s3.005 1.366 3.005 4"></path></svg> + <span class="num text-emphasized"></span> + Fetching contributors + </a> +</include-fragment> </li> + </ul> + + <div class="repository-lang-stats"> + <ol class="repository-lang-stats-numbers"> + <li> + <a href="/pliablepixels/ionic-content-banner/search?l=javascript" data-ga-click="Repository, language stats search click, location:repo overview"> + <span class="color-block language-color" style="background-color:#f1e05a;"></span> + <span class="lang">JavaScript</span> + <span class="percent">86.5%</span> + </a> + </li> + <li> + <a href="/pliablepixels/ionic-content-banner/search?l=css" data-ga-click="Repository, language stats search click, location:repo overview"> + <span class="color-block language-color" style="background-color:#563d7c;"></span> + <span class="lang">CSS</span> + <span class="percent">9.6%</span> + </a> + </li> + <li> + <a href="/pliablepixels/ionic-content-banner/search?l=html" data-ga-click="Repository, language stats search click, location:repo overview"> + <span class="color-block language-color" style="background-color:#e44b23;"></span> + <span class="lang">HTML</span> + <span class="percent">3.9%</span> + </a> + </li> + </ol> + </div> + </div> + </div> +</div> + + <div class="repository-lang-stats-graph js-toggle-lang-stats" title="Click for language details" data-ga-click="Repository, language bar stats toggle, location:repo overview"> + <span class="language-color" aria-label="JavaScript 86.5%" style="width:86.5%; background-color:#f1e05a;" itemprop="keywords">JavaScript</span> + <span class="language-color" aria-label="CSS 9.6%" style="width:9.6%; background-color:#563d7c;" itemprop="keywords">CSS</span> + <span class="language-color" aria-label="HTML 3.9%" style="width:3.9%; background-color:#e44b23;" itemprop="keywords">HTML</span> + </div> + + +<div class="file-navigation in-mid-page"> + + <div class="select-menu get-repo-select-menu js-menu-container float-right select-menu-modal-right"> + <button class="btn btn-sm btn-primary select-menu-button js-menu-target" + title="Clone or download this repository" + type="button" aria-label="Clone or download this repository" tabindex="0" aria-haspopup="true"> + <span>Clone or download</span> + </button> + + <div class="select-menu-modal-holder dropdown-menu-content js-menu-content" aria-hidden="true"> + <div class="get-repo-modal dropdown-menu dropdown-menu-sw pb-0 js-toggler-container "> + <div class="clone-options https-clone-options"> + + <h4 class="mb-1"> + Clone with HTTPS + <a class="muted-link" href="https://help.github.com/articles/which-remote-url-should-i-use" target="_blank"> + <svg aria-hidden="true" class="octicon octicon-question" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M6 10h2v2H6v-2zm4-3.5C10 8.64 8 9 8 9H6c0-.55.45-1 1-1h.5c.28 0 .5-.22.5-.5v-1c0-.28-.22-.5-.5-.5h-1c-.28 0-.5.22-.5.5V7H4c0-1.5 1.5-3 3-3s3 1 3 2.5zM7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7z"></path></svg> + </a> + </h4> + <p class="mb-2 get-repo-decription-text"> + Use Git or checkout with SVN using the web URL. + </p> + + <div class="input-group js-zeroclipboard-container"> + <input type="text" class="form-control input-monospace input-sm js-zeroclipboard-target js-url-field" value="https://github.com/pliablepixels/ionic-content-banner.git" aria-label="Clone this repository at https://github.com/pliablepixels/ionic-content-banner.git" readonly> + <div class="input-group-button"> + <button aria-label="Copy to clipboard" class="js-zeroclipboard btn btn-sm zeroclipboard-button tooltipped tooltipped-s" data-copied-hint="Copied!" type="button"><svg aria-hidden="true" class="octicon octicon-clippy" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M2 13h4v1H2v-1zm5-6H2v1h5V7zm2 3V8l-3 3 3 3v-2h5v-2H9zM4.5 9H2v1h2.5V9zM2 12h2.5v-1H2v1zm9 1h1v2c-.02.28-.11.52-.3.7-.19.18-.42.28-.7.3H1c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h3c0-1.11.89-2 2-2 1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V6H1v9h10v-2zM2 5h8c0-.55-.45-1-1-1H8c-.55 0-1-.45-1-1s-.45-1-1-1-1 .45-1 1-.45 1-1 1H3c-.55 0-1 .45-1 1z"></path></svg></button> + </div> +</div> + + </div> + + + <div class="mt-2"> + +<a href="/pliablepixels/ionic-content-banner/archive/master.zip" + class="btn btn-outline get-repo-btn +" + rel="nofollow" + data-ga-click="Repository, download zip, location:repo overview"> + Download ZIP +</a> + + </div> + </div> + </div> +</div> + + + <div class="BtnGroup float-right"> + + <a href="/pliablepixels/ionic-content-banner/find/master" + class="btn btn-sm empty-icon float-right BtnGroup-item" + data-pjax + data-hotkey="t" + data-ga-click="Repository, find file, location:repo overview"> + Find file + </a> + </div> + + +<div class="select-menu branch-select-menu js-menu-container js-select-menu float-left"> + <button class="btn btn-sm select-menu-button js-menu-target css-truncate" data-hotkey="w" + + type="button" aria-label="Switch branches or tags" tabindex="0" aria-haspopup="true"> + <i>Branch:</i> + <span class="js-select-button css-truncate-target">master</span> + </button> + + <div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax aria-hidden="true"> + + <div class="select-menu-modal"> + <div class="select-menu-header"> + <svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg> + <span class="select-menu-title">Switch branches/tags</span> + </div> + + <div class="select-menu-filters"> + <div class="select-menu-text-filter"> + <input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="form-control js-filterable-field js-navigation-enable" placeholder="Filter branches/tags"> + </div> + <div class="select-menu-tabs"> + <ul> + <li class="select-menu-tab"> + <a href="#" data-tab-filter="branches" data-filter-placeholder="Filter branches/tags" class="js-select-menu-tab" role="tab">Branches</a> + </li> + <li class="select-menu-tab"> + <a href="#" data-tab-filter="tags" data-filter-placeholder="Find a tag…" class="js-select-menu-tab" role="tab">Tags</a> + </li> + </ul> + </div> + </div> + + <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches" role="menu"> + + <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring"> + + + <a class="select-menu-item js-navigation-item js-navigation-open selected" + href="/pliablepixels/ionic-content-banner/tree/master" + data-name="master" + data-skip-pjax="true" + rel="nofollow"> + <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg> + <span class="select-menu-item-text css-truncate-target js-select-menu-filter-text"> + master + </span> + </a> + </div> + + <div class="select-menu-no-results">Nothing to show</div> + </div> + + <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags"> + <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring"> + + + <a class="select-menu-item js-navigation-item js-navigation-open " + href="/pliablepixels/ionic-content-banner/tree/v1.0.1" + data-name="v1.0.1" + data-skip-pjax="true" + rel="nofollow"> + <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg> + <span class="select-menu-item-text css-truncate-target" title="v1.0.1"> + v1.0.1 + </span> + </a> + <a class="select-menu-item js-navigation-item js-navigation-open " + href="/pliablepixels/ionic-content-banner/tree/v1.0.0" + data-name="v1.0.0" + data-skip-pjax="true" + rel="nofollow"> + <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg> + <span class="select-menu-item-text css-truncate-target" title="v1.0.0"> + v1.0.0 + </span> + </a> + </div> + + <div class="select-menu-no-results">Nothing to show</div> + </div> + + </div> + </div> +</div> + + + <button type="button" class="btn btn-sm disabled tooltipped tooltipped-n new-pull-request-btn" aria-label="You must be signed in to create a pull request"> + New pull request + </button> + + <div class="breadcrumb"> + + </div> +</div> + + + + <div class="branch-infobar"> + <span class="float-right"> + <a class="muted-link" href="/pliablepixels/ionic-content-banner/pull/new/master"> + <svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg> + Pull request + </a> + <a class="muted-link" href="/pliablepixels/ionic-content-banner/compare"> + <svg aria-hidden="true" class="octicon octicon-diff" height="16" version="1.1" viewBox="0 0 13 16" width="13"><path d="M6 7h2v1H6v2H5V8H3V7h2V5h1v2zm-3 6h5v-1H3v1zM7.5 2L11 5.5V15c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h6.5zM10 6L7 3H1v12h9V6zM8.5 0H3v1h5l4 4v8h1V4.5L8.5 0z"></path></svg> + Compare + </a> + </span> + + This branch is 2 commits ahead of djett41:master. + </div> + +<include-fragment class="commit-tease commit-loader" src="/pliablepixels/ionic-content-banner/tree-commit/eed5b1cb107772d79beb6f34a65d01538f50c444"> + <div class="blank"> + <img alt="" class="loader" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32-EAF2F5.gif" width="16" /> + Fetching latest commit… + </div> + <div class="loader-error"> + Cannot retrieve the latest commit at this time. + </div> +</include-fragment> + +<include-fragment class="file-wrap" src="/pliablepixels/ionic-content-banner/file-list/master"> + + <a href="/pliablepixels/ionic-content-banner/tree/eed5b1cb107772d79beb6f34a65d01538f50c444" class="d-none js-permalink-shortcut" data-hotkey="y">Permalink</a> + + <table class="files js-navigation-container js-active-navigation-container" data-pjax> + + + <tbody> + <tr class="warning include-fragment-error"> + <td class="icon"><svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"></path></svg></td> + <td class="content" colspan="3">Failed to load latest commit information.</td> + </tr> + + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-directory" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/tree/master/.idea" class="js-navigation-open" id="95b55b1e3a304f4e340394a679893575-a571ab800a86117d8d1b59d80ae35964859488c6" title=".idea">.idea</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-directory" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/tree/master/demo" class="js-navigation-open" id="fe01ce2a7fbac8fafaed7c982a04e229-25035f3c73776ad1316b01e5139d5a3974932dc3" title="demo">demo</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-directory" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/tree/master/dist" class="js-navigation-open" id="2a6d07eef8b10b84129b42424ed99327-f27babf531e9e231ae9f1a501484ccf9797d21c7" title="dist">dist</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-directory" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/tree/master/js" class="js-navigation-open" id="32981a13284db7a021131df49e6cd203-2fe5044bad36cf4ead50a27d76e96437c8faebd5" title="js">js</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-directory" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/tree/master/scss" class="js-navigation-open" id="d711b55165b29776dc8996509be4c9f8-4888ef02353b7695c907007fddb639eaeda51b1f" title="scss">scss</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-directory" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/tree/master/test/unit" class="js-navigation-open" id="877fbbe2538d21acbd5acd35d57e8d66-3cd81fb8dd2f91478cca1235a281d577ad66a7dc" title="This path skips through empty directories"><span class="simplified-path">test/</span>unit</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-text" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/blob/master/.gitignore" class="js-navigation-open" id="a084b794bc0759e7a6b77810e01874f2-bb93d680af6f29ebef270576011c7adbf3804e25" title=".gitignore">.gitignore</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-text" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/blob/master/LICENSE" class="js-navigation-open" id="9879d6db96fd29134fc802214163b95a-e9b3c9751634f8a1a03f69736ebabe48a9e668b6" itemprop="license" title="LICENSE">LICENSE</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-text" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/blob/master/README.md" class="js-navigation-open" id="04c6e90faac2675aa89e2176d2eec7d8-19437ec3d7a4fe07769699f84ce4306c2ede69c5" title="README.md">README.md</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-text" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/blob/master/bower.json" class="js-navigation-open" id="0a08a7565aba4405282251491979bb6b-7e330544c40cfbb329807023c7189be961ca44bd" title="bower.json">bower.json</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-text" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/blob/master/gulpfile.js" class="js-navigation-open" id="b9e12334e9eafd8341a6107dd98510c9-5122394029974f6285b3a3cbbb8633a0ab582608" title="gulpfile.js">gulpfile.js</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-text" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/blob/master/karma.conf.js" class="js-navigation-open" id="a2a3b7b0c9c3b4b93b4aebf4e3ec3cfb-c202222a88def4e97a5755d3abbfb3e54b6a5692" title="karma.conf.js">karma.conf.js</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + <tr class="js-navigation-item"> + <td class="icon"> + <svg aria-hidden="true" class="octicon octicon-file-text" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M6 5H2V4h4v1zM2 8h7V7H2v1zm0 2h7V9H2v1zm0 2h7v-1H2v1zm10-7.5V14c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1V2c0-.55.45-1 1-1h7.5L12 4.5zM11 5L8 2H1v12h10V5z"></path></svg> + <img alt="" class="spinner" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16" /> + </td> + <td class="content"> + <span class="css-truncate css-truncate-target"><a href="/pliablepixels/ionic-content-banner/blob/master/package.json" class="js-navigation-open" id="b9cfc7f2cdf78a7f4b91a753d10865a2-36aa036a781c9721fa023b2e4eea183f24161391" title="package.json">package.json</a></span> + </td> + <td class="message"> + <span class="css-truncate css-truncate-target"> + </span> + </td> + <td class="age"> + <span class="css-truncate css-truncate-target"></span> + </td> + </tr> + </tbody> + </table> + +</include-fragment> + + + + <div id="readme" class="readme boxed-group clearfix announce instapaper_body md"> + <h3> + <svg aria-hidden="true" class="octicon octicon-book" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M3 5h4v1H3V5zm0 3h4V7H3v1zm0 2h4V9H3v1zm11-5h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm2-6v9c0 .55-.45 1-1 1H9.5l-1 1-1-1H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h5.5l1 1 1-1H15c.55 0 1 .45 1 1zm-8 .5L7.5 3H2v9h6V3.5zm7-.5H9.5l-.5.5V12h6V3z"></path></svg> + README.md + </h3> + + <article class="markdown-body entry-content" itemprop="text"><h1><a id="user-content-ionic-content-banner" class="anchor" href="#ionic-content-banner" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Ionic Content Banner</h1> + +<blockquote> +<p>A Facebook style info/error content banner for the Ionic Framework</p> +</blockquote> + +<h2><a id="user-content-table-of-contents" class="anchor" href="#table-of-contents" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Table of Contents</h2> + +<ul> +<li><a href="#demo">Demo</a></li> +<li><a href="#setup">Setup</a></li> +<li><a href="#usage">Usage</a></li> +<li><a href="#screenshots">Screenshots</a></li> +</ul> + +<h2><a id="user-content-demo" class="anchor" href="#demo" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h2> + +<ul> +<li>Download my sports news app <strong>SportScoop</strong> on iOS/Android to see it live!! <a href="http://www.sportscoopapp.com">Web Demo</a> | <a href="https://itunes.apple.com/us/app/sportscoop/id1035164619?mt=8">iOS</a> | <a href="https://play.google.com/store/apps/details?id=com.coseur.sportscoop">Android</a></li> +</ul> + +<p><a href="http://www.sportscoopapp.com"><img src="https://camo.githubusercontent.com/f3e6ef7364cc8ee2d69fd8f206916e42fa8f18d1/687474703a2f2f7777772e73706f727473636f6f706170702e636f6d2f6173736574732f73706f727473636f6f705f646f776e6c6f61642e706e67" alt="SportScoop" data-canonical-src="http://www.sportscoopapp.com/assets/sportscoop_download.png" style="max-width:100%;"></a></p> + +<ul> +<li>Watch the Demo video below</li> +</ul> + +<p><a href="http://www.youtube.com/watch?v=O_18dIEbZXM"><img src="https://camo.githubusercontent.com/070697e2e6ff38d6e5bf4dc86fbc0a4c3c7e7dac/687474703a2f2f696d672e796f75747562652e636f6d2f76692f4f5f3138644945625a584d2f302e6a7067" alt="Ionic Content Banner" data-canonical-src="http://img.youtube.com/vi/O_18dIEbZXM/0.jpg" style="max-width:100%;"></a></p> + +<ul> +<li>Download the Demo app on <a href="http://view.ionic.io/">Ionic View</a> with appId: <code>5445a4a4</code></li> +<li>Run the demo source code by cloning the ionic-content-banner repo, navigating to /demo and running the following</li> +</ul> + +<p>Run the following ommands:</p> + +<pre><code>npm install +bower install +gulp +</code></pre> + +<h2><a id="user-content-setup" class="anchor" href="#setup" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setup</h2> + +<h4><a id="user-content-install" class="anchor" href="#install" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install</h4> + +<p><code>bower install ionic-content-banner</code></p> + +<h4><a id="user-content-jscss-imports-indexhtml" class="anchor" href="#jscss-imports-indexhtml" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>JS/CSS Imports (index.html)</h4> + +<p>Include the following JavaScript/CSS file imports in your index.html. Remember to import the ionic libraries first! +The example below assumes your 3rd party bower dependencies are located in the default bower_components folder.</p> + +<pre><code><link rel="stylesheet" href="bower_components/ionic-content-banner/dist/ionic.content.banner.css"> +<script src="bower_components/ionic-content-banner/dist/ionic.content.banner.js"></script> +</code></pre> + +<h4><a id="user-content-angular-dependency-appjs" class="anchor" href="#angular-dependency-appjs" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Angular Dependency (app.js)</h4> + +<p>Add <code>jett.ionic.content.banner</code> as a module dependency of your app module.</p> + +<pre><code>angular.module('Demo', ['ionic', 'jett.ionic.content.banner']) + .config(function () {..}); +</code></pre> + +<h4><a id="user-content-sass-import-mainscss" class="anchor" href="#sass-import-mainscss" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>SASS Import (main.scss)</h4> + +<p>Include the <code>scss/ionic.content.banner.scss</code> file at the top of your <code>main.scss</code> file as shown below. Import any +custom Content Banner scss styles below the ionic and ionic.content.banner scss.</p> + +<pre><code>@import + "path_to_bower_components/ionic/scss/ionic", + "path_to_bower_components/ionic-content-banner/scss/ionic.content.banner"; +</code></pre> + +<h2><a id="user-content-usage" class="anchor" href="#usage" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Usage</h2> + +<h3><a id="user-content-ioniccontentbanner" class="anchor" href="#ioniccontentbanner" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>$ionicContentBanner</h3> + +<p>A service you can inject in your controller to show the Content Banner</p> + +<h4><a id="user-content-ioniccontentbannershow" class="anchor" href="#ioniccontentbannershow" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>$ionicContentBanner.show</h4> + +<p>Create and show a new Content Banner. A new isolated scope will be created for the Content Banner and the new + Content Banner will animate just under the top of the active views ion-content.</p> + +<p>@returns {function} <code>close</code> A function which, when called, closes the Content Banner. Make sure you use this to + clean up and remove the content banner!!</p> + +<p>@param {object} options The options for the content banner. Properties:</p> + +<ul> +<li><p><code>{string=}</code> <code>icon</code></p> + +<p>The icon used for the close button. defaults to <code>ion-ios-close-empty</code></p></li> +<li><p><code>{string=}</code> <code>transition</code></p> + +<p>The transition used to animate in the content banner. Supported options are <code>vertical</code> and <code>fade</code>; defaults to +<code>vertical</code>. The content banner will create a css class <code>content-banner-transition-{transitionVal}</code>, so you can add +a custom value and then a custom css class to match if you would like to create your own transition.</p></li> +<li><p><code>{string=}</code> <code>type</code></p> + +<p>The type of banner to show. Supported types are <code>info</code> and <code>error</code>; defaults to <code>info</code>. The content banner will +create a css class <code>content-banner-{typeVal}</code>, so you can add a custom type value and then a custom css class to +match if you would like to create your own type.</p></li> +<li><p><code>[String]</code> <code>text</code></p> + +<p>A string array that contains the text values to display on the banner. If the array contains more than one value, +the content banner will cycle through the values of the array at the supplied <code>interval</code> (see below).</p></li> +<li><p><code>{number=}</code> <code>interval</code></p> + +<p>Number of milliseconds between text value changes. Default value is 7000ms (7 seconds).</p></li> +<li><p><code>{number=}</code> <code>autoClose</code></p> + +<p>Number of milliseconds before the content banner automatically closes. This option is disabled by default. </p></li> +<li><p><code>{boolean=}</code> <code>cancelOnStateChange</code></p> + +<p>Whether to cancel the content banner when navigating to a new state. Default value is true.</p></li> +</ul> + +<h2><a id="user-content-screenshots" class="anchor" href="#screenshots" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Screenshots</h2> + +<p><a href="/pliablepixels/ionic-content-banner/blob/master/demo/resources/screenshots/ios1.png" target="_blank"><img src="/pliablepixels/ionic-content-banner/raw/master/demo/resources/screenshots/ios1.png" align="left" height="500" width="281" style="max-width:100%;"></a> +<a href="/pliablepixels/ionic-content-banner/blob/master/demo/resources/screenshots/ios2.png" target="_blank"><img src="/pliablepixels/ionic-content-banner/raw/master/demo/resources/screenshots/ios2.png" align="left" height="500" width="281" style="max-width:100%;"></a></p> + +<p><a href="/pliablepixels/ionic-content-banner/blob/master/demo/resources/screenshots/android1.png" target="_blank"><img src="/pliablepixels/ionic-content-banner/raw/master/demo/resources/screenshots/android1.png" align="left" height="500" width="281" style="max-width:100%;"></a> +<a href="/pliablepixels/ionic-content-banner/blob/master/demo/resources/screenshots/android2.png" target="_blank"><img src="/pliablepixels/ionic-content-banner/raw/master/demo/resources/screenshots/android2.png" align="left" height="500" width="281" style="max-width:100%;"></a></p> +</article> + </div> + + + </div> + <div class="modal-backdrop js-touch-events"></div> +</div> + + + </div> + </div> + + </div> + + <div class="container site-footer-container"> + <div class="site-footer" role="contentinfo"> + <ul class="site-footer-links float-right"> + <li><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact GitHub</a></li> + <li><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li> + <li><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li> + <li><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li> + <li><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li> + <li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li> + + </ul> + + <a href="https://github.com" aria-label="Homepage" class="site-footer-mark" title="GitHub"> + <svg aria-hidden="true" class="octicon octicon-mark-github" height="24" version="1.1" viewBox="0 0 16 16" width="24"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg> +</a> + <ul class="site-footer-links"> + <li>© 2016 <span title="0.12349s from github-fe-651e69d.cp1-iad.github.net">GitHub</span>, Inc.</li> + <li><a href="https://github.com/site/terms" data-ga-click="Footer, go to terms, text:terms">Terms</a></li> + <li><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li> + <li><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security">Security</a></li> + <li><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li> + <li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li> + </ul> + </div> +</div> + + + + + + <div id="ajax-error-message" class="ajax-error-message flash flash-error"> + <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"></path></svg> + <button type="button" class="flash-close js-flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> + <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg> + </button> + You can't perform that action at this time. + </div> + + + <script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/compat-e4d83aa5a60ed31324537822c58c689dbab3943acc78ca2c88fc482479865c7e.js"></script> + <script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/frameworks-411d610e4b2b1ffa3d063904534406d08c8351d9ba9b4b3f339bab35e86bb4f3.js"></script> + <script async="async" crossorigin="anonymous" src="https://assets-cdn.github.com/assets/github-877cf6bfb710d9ccb14e4a6841ffe0fe6b52fec0f230b1f594ed779dc6ba0f94.js"></script> + + + + + + + <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner d-none"> + <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"></path></svg> + <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span> + <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span> + </div> + <div class="facebox" id="facebox" style="display:none;"> + <div class="facebox-popup"> + <div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description"> + </div> + <button type="button" class="facebox-close js-facebox-close" aria-label="Close modal"> + <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg> + </button> + </div> +</div> + + </body> +</html> + diff --git a/www/templates/devoptions.html b/www/templates/devoptions.html index 98a9dcef..b206a559 100644 --- a/www/templates/devoptions.html +++ b/www/templates/devoptions.html @@ -11,7 +11,7 @@ </ion-nav-buttons> - <ion-content class="padding"> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll > <div class="list list-inset"> <span style="color:rgb(100,100,100)"> <i class="ion-android-settings" style="font-size:150%"></i> {{'kDeveloperOptionsFor'|translate}} {{loginData.serverName}} diff --git a/www/templates/events-date-time-filter.html b/www/templates/events-date-time-filter.html index 84e39ea2..af97ad60 100644 --- a/www/templates/events-date-time-filter.html +++ b/www/templates/events-date-time-filter.html @@ -2,7 +2,7 @@ - <ion-content> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll > <label class="item item-input"> <span class="input-label">{{'kFromDate'|translate}}:</span> <input type="date" ng-model="$root.fromDate" max={{today}}> diff --git a/www/templates/events.html b/www/templates/events.html index 485cdc0d..8ea421a3 100644 --- a/www/templates/events.html +++ b/www/templates/events.html @@ -1,5 +1,6 @@ <ion-view cache-view="false"> + <ion-nav-title>{{scrollPosition();}}</ion-nav-title> <ion-nav-buttons side="left"> <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"> @@ -27,10 +28,12 @@ </div> - - <ion-content ng-cloak on-tap="tapped();" delegate-handle="mainScroll" has-subheader="true" overflow-scroll="false" mouse-wheel-scroll> - - + + <!-- collection repeat forces js scrolling, thing to remember --> + + <ion-content scroll-sista ng-cloak on-tap="tapped();" delegate-handle="mainScroll" mouse-wheel-scroll> + <!-- needed for header-shrink so first item doesn't go below header--> + <!-- <div style="height: 64px;"></div>--> <!-- lets make sure the events list is not empty as collection repeat needs height --> <div ng-if="!eventsBeingLoaded"> diff --git a/www/templates/eventserversettings.html b/www/templates/eventserversettings.html index 6a3b7d90..e6ec4614 100644 --- a/www/templates/eventserversettings.html +++ b/www/templates/eventserversettings.html @@ -12,7 +12,7 @@ <button class="button button-clear" ng-click="saveItems()">{{'kSave'|translate}}</button> </ion-nav-buttons> - <ion-content padding="true"> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll > <div class="list list-inset"> {{'kEventServerConfig1' | translate }} diff --git a/www/templates/help.html b/www/templates/help.html index 169d1abe..fffdf2d1 100644 --- a/www/templates/help.html +++ b/www/templates/help.html @@ -1,4 +1,4 @@ -<ion-view view-title="Help"> +<ion-view cache-view="false" view-title="Help"> <ion-nav-buttons side="left"> <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button> @@ -8,7 +8,7 @@ </ion-nav-buttons> - <ion-content class="padding" overflow-scroll="false" ng-cloak> + <ion-content class="padding" scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll> <p><small>{{$root.appName}} v{{zmAppVersion}}</small></p> <div class="list"> diff --git a/www/templates/log.html b/www/templates/log.html index 7bbb022a..e53f00aa 100644 --- a/www/templates/log.html +++ b/www/templates/log.html @@ -22,7 +22,7 @@ </div> </ion-nav-buttons> - <ion-content class="padding"> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll> <b>{{$root.appName}} {{'kVersion'|translate}}: {{zmAppVersion}}</b><br/> <!-- don't indent here -- its a pre--> <pre>{{log.logString}}</pre> diff --git a/www/templates/login.html b/www/templates/login.html index 054aaf49..738c1c46 100644 --- a/www/templates/login.html +++ b/www/templates/login.html @@ -13,7 +13,7 @@ <button class="button button-clear" ng-click="saveItems()">Save</button> </ion-nav-buttons> - <ion-content padding="true"> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll > <div class="item item-input-inset"> {{'kServerName' | translate }}: diff --git a/www/templates/monitors.html b/www/templates/monitors.html index 6c23e6c7..a9168c09 100644 --- a/www/templates/monitors.html +++ b/www/templates/monitors.html @@ -1,4 +1,5 @@ <ion-view view-title="{{'kMonitors' | translate}}" cache-view="false"> + <ion-nav-buttons side="left"> <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"> </button> @@ -6,8 +7,9 @@ <button data-badge="{{$root.alarmCount}}" class="animated infinite tada button button-icon button-clear ion-ios-bell notification-badge" ng-click="handleAlarms();" ng-if="$root.isAlarm"></button> </ion-nav-buttons> + - <ion-content overflow-scroll="false"> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll > <ion-refresher pulling-text="Pull to reload Monitors..." spinner="bubbles" on-refresh="doRefresh()"> </ion-refresher> <div style="float:right;margin-top:3px;margin-right:8px;"> diff --git a/www/templates/montage-history.html b/www/templates/montage-history.html index f0e4a4a5..eb751105 100644 --- a/www/templates/montage-history.html +++ b/www/templates/montage-history.html @@ -21,7 +21,7 @@ </ion-nav-buttons> - <ion-content has-bouncing="false" style="background-color:#444444"> + <ion-content scroll-sista has-bouncing="false" style="background-color:#444444" delegate-handle="montage-delegate" overflow-scroll="false" mouse-wheel-scroll> diff --git a/www/templates/montage-history2.html b/www/templates/montage-history2.html new file mode 100644 index 00000000..69fb2bb6 --- /dev/null +++ b/www/templates/montage-history2.html @@ -0,0 +1,230 @@ +<ion-view view-title="{{'kEventMontage' | translate}}" cache-view="false" hide-nav-bar="{{minimal}}"> + <ion-nav-buttons side="left"> + <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button> + + <button class="button button-icon button-clear ion-arrow-move" ng-click="dragToggle();"> + </button> + + <button data-badge="{{$root.alarmCount}}" class="animated infinite tada button button-icon button-clear ion-ios-bell notification-badge" ng-click="handleAlarms();" ng-if="$root.isAlarm"></button> + </ion-nav-buttons> + + + + <ion-nav-buttons side="right"> + + <button class="button button-icon button-clear ion-loop" ng-click="resetSizes();"> + </button> + + <button class="button button-icon button-clear ion-plus-round" ng-click="sliderChanged(1);"> + </button> + + <button class="button button-icon button-clear ion-minus-round" ng-click="sliderChanged(-1);"> + </button> + + <button data-badge="{{$root.alarmCount}}" class="animated infinite tada button button-icon button-clear ion-ios-bell notification-badge" ng-click="handleAlarms();" ng-if="$root.isAlarm"></button> + + + + </ion-nav-buttons> + + <ion-content scroll-sista has-bouncing="false" style="background-color:#444444" delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll> + + + + <div class="timeline_text" ion-datetime-picker title="From" am-pm={{!loginData.use24hr}} ng-model="datetimeValueFrom.value" ng-change="dateChanged()"> + <b>{{'kFrom' | translate}} : </b>{{datetimeValueFrom.value | date: timeFormat}} + </div> + + <div class="timeline_text" ion-datetime-picker am-pm={{!loginData.use24hr}} ng-model="datetimeValueTo.value" ng-change="dateChanged()"> + <b>{{'kTo' | translate}}: </b>{{datetimeValueTo.value | date: timeFormat}} @ {{sliderVal.rate}}x + <div ng-if="$root.platformOS != 'ios'">({{'kChromeMax' | translate}})</div> + </div> + + + + + <div class="grid" id="mygrid"> + <div class="grid-sizer grid-item-10"></div> + + + + + <!-- <span ng-repeat="monitor in MontageMonitors|limitTo: monLimit" ng- --> + <span ng-repeat="monitor in MontageMonitors | onlyEnabled |limitTo: monLimit"> + + + + + <div ng-if="$root.authSession!='undefined'"> + <div ng-if = "monitor.Monitor.eventUrl == 'img/noevent.png' && !sliderVal.hideNoEvents"> + + <!-- make sure we don't use id here + -- or we lose the handle for cleanup forever!--> + <div class="grid-item grid-item-{{monitor.Monitor.gridScale}} " data-item-id="{{monitor.Monitor.Id}}" data-item-size="{{monitor.Monitor.gridScale}}" data-item-listdisplay="{{monitor.Monitor.listDisplay}}" > + <figure height="{{Monitor.monitor.height}}" width="{{Monitor.monitor.width}}" class="{{dragBorder}}" ng-show=" monitor.Monitor.listDisplay!='noshow'"> + + <img class="{{monitor.Monitor.selectStyle}}" image-spinner-src="{{monitor.Monitor.eventUrl}}" image-spinner-loader="lines" on-tap="!isDragabillyOn?noop():toggleSelectItem($index)" /> + + + <figcaption class="normal-figcaption" > + + <i class="ion-ios-videocam"></i> + {{monitor.Monitor.Name}} + + </figcaption> + + + + </figure> + </div> + </div> + + <div ng-if = "monitor.Monitor.eventUrl != 'img/noevent.png' && monitor.Monitor.connKey !=''"> + + <div class="grid-item grid-item-{{monitor.Monitor.gridScale}} " data-item-id="{{monitor.Monitor.Id}}" data-item-size="{{monitor.Monitor.gridScale}}" data-item-listdisplay="{{monitor.Monitor.listDisplay}}" > + <figure height="{{Monitor.monitor.height}}" width="{{Monitor.monitor.width}}" class="{{dragBorder}}" ng-show=" monitor.Monitor.listDisplay!='noshow'"> + + <img class="{{monitor.Monitor.selectStyle}}" image-spinner-src="{{monitor.Monitor.eventUrl}}{{$root.authSession}}" image-spinner-loader="lines" on-tap="!isDragabillyOn?togglePause(monitor.Monitor.Id):toggleSelectItem($index)" /> + + + <figcaption class="normal-figcaption" > + + <i class="ion-ios-videocam"></i> <span style="background-color:red;color:#fff" ng-if="monitor.Monitor.isPaused"> <i class="ion-pause"></i> </span> + {{monitor.Monitor.Name}} + + <div ng-if="sliderVal.showTimeline && $root.runMode!='lowbw'" style="white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:9px" + class="header-event-id" id="{{monitor.Monitor.Id}}-timeline"> + <i class="ion-clock"></i> + {{prettifyDateTimeFirst(monitor.Monitor.eventUrlTime)}} ({{humanizeTime(monitor.Monitor.eventUrlTime)}}) + </div> + + </figcaption> + + + + </figure> + </div> + + + + + + <!-- + <div ng-if="sliderVal.showTimeline && $root.runMode!='lowbw'" style=" position:absolute; bottom:15px; right:0%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;" + class="header-event-id" id="{{monitor.Monitor.Id}}-timeline"> + <i class="ion-clock"></i> + {{prettifyDate(monitor.Monitor.eventUrlTime)}} + </div> + --> + + + <!--<div ng-if="!monitor.isPaused" + style="position:absolute; bottom:35px; right:0%;white-space:nowrap;overflow:hidden;" class="header-event-id">paused + </div>--> + + + </div> + </div> <!-- valid auth session &!background --> + + <div ng-if="!$root.authSession=='undefined' || isBackground()"> + <img image-spinner-src="img/pausevideo.png" + /> + + </div> + </span> + </div> + + <ion-item ng-show="!MontageMonitors.length"> + {{'kNoMonitors' | translate }} + </ion-item> + + + + </ion-content> + + <div class="bwmode" ng-if="$root.runMode=='lowbw'"> + {{ 'kLowBWDisplay' | translate }} + </div> + + <div ng-show="minimal"> + <nav mfb-menu position="br" effect="zoomin" label="collapse" active-icon="ion-chevron-down" resting-icon="ion-chevron-up" toggling-method="click"> + + <button mfb-button icon="ion-arrow-expand" label="increase size" ng-click="changeSize(-1)"> + </button> + <button mfb-button icon="ion-arrow-shrink" label="decrease size" ng-click="changeSize(1)"> + </button> + <button mfb-button icon="ion-refresh" label="refresh" ng-click="reloadView();"> + </button> + <button mfb-button icon="ion-close" label="exit full screen" ng-click="switchMinimal()"> + </button> + </nav> + + <span class="modal-alarm-badge"> + <a data-badge="{{$root.alarmCount}}" class="animated infinite tada button icon ion-ios-bell notification-badge button-assertive" + ng-click="handleAlarmsWhileMinimized();" ng-if="$root.isAlarm"></a> + </span> + + </div> + + <ion-pull-up-footer class="zmPullup" on-expand="footerExpand()" on-minimize="footerCollapse()" on-collapse="footerCollapse()" initial-state="minimized" default-behavior="expand"> + <ion-pull-up-handle width="100" height="25" toggle="ion-chevron-up ion-chevron-down" style="border-radius: 25px 25px 0 0"> + <i class="icon ion-chevron-up"></i> + </ion-pull-up-handle> + <ion-pull-up-bar> + <h1 class="title" ion-pull-up-trigger>{{'kEventMontage' | translate}}</h1> + </ion-pull-up-bar> + <ion-pull-up-content scroll="true"> + + + <div class="list list-inset"> + + + <ion-toggle ng-model="sliderVal.hideNoEvents" ng-checked="{{sliderVal.hideNoEvents}}" toggle-class="toggle-dark"><span class="item-text-wrap">{{'kHideMonsWithoutEvents' | translate}}</span></ion-toggle> + + + + + <!--<div class="item item-divider" ion-datetime-picker ng-model="datetimeValueFrom.value"> + Tap to change: {{datetimeValueFrom.value| date: "yyyy-MMM-dd hh:mma"}} + </div>--> + + + + + + <div class="row"> + <div class="col col-75"> + <br/> + <div style="width:90%;color:black;"> + <input ng-model="sliderVal.rate" type="text" id="mySlider6" slider options="slider_modal_options_rate" /> + </div> + <br/> + </div> + <div class="col col-25" style="background-color:#AEA8D3;text-align:center"> + {{'kSpeed' | translate }} + </div> + </div> + + <div class="item item-divider">{{'kTimeline' | translate}}</div> + + <ion-item> + <div ion-datetime-picker title="From" am-pm={{!loginData.use24hr}} ng-model="datetimeValueFrom.value"> + <b>{{'kFrom' | translate }}: </b>{{datetimeValueFrom.value | date: timeFormat}} + </div> + </ion-item> + + <ion-item> + <div ion-datetime-picker am-pm={{!loginData.use24hr}} ng-model="datetimeValueTo.value"> + <b>{{'kTo' | translate}}: </b>{{datetimeValueTo.value | date: timeFormat}} + </div> + </ion-item> + + </div> + </ion-pull-up-content> + </ion-pull-up-footer> + + + + + +</ion-view>
\ No newline at end of file diff --git a/www/templates/montage.html b/www/templates/montage.html index f79db1ef..b442f998 100644 --- a/www/templates/montage.html +++ b/www/templates/montage.html @@ -33,7 +33,7 @@ </ion-nav-buttons> - <ion-content ng-cloak has-bouncing="false" style="background-color:#444444" delegate-handle="montage-delegate" > + <ion-content scroll-sista ng-cloak has-bouncing="false" style="background-color:#444444" delegate-handle="montage-delegate" overflow-scroll="false" > diff --git a/www/templates/news.html b/www/templates/news.html index 3edb2a16..f4a87e4f 100644 --- a/www/templates/news.html +++ b/www/templates/news.html @@ -8,7 +8,7 @@ </ion-nav-buttons> - <ion-content > + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll > <div class="list"> <span ng-repeat = "post in newsItems"> diff --git a/www/templates/state.html b/www/templates/state.html index 5763c284..bf0cda4a 100644 --- a/www/templates/state.html +++ b/www/templates/state.html @@ -4,7 +4,7 @@ <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button> <button data-badge="{{$root.alarmCount}}" class="animated infinite tada button button-icon button-clear ion-ios-bell notification-badge" ng-click="handleAlarms();" ng-if="$root.isAlarm"></button> </ion-nav-buttons> - <ion-content> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll> <ion-refresher pulling-text="{{'kPullToReload' | translate}}..." spinner="bubbles" on-refresh="doRefresh()"></ion-refresher> <ion-list> diff --git a/www/templates/timeline.html b/www/templates/timeline.html index 2f8e6481..e443e705 100644 --- a/www/templates/timeline.html +++ b/www/templates/timeline.html @@ -23,7 +23,7 @@ </ion-nav-buttons> <!--<ion-content data-tap-disabled="true">--> - <ion-content> + <ion-content scroll-sista delegate-handle="none" overflow-scroll="false" mouse-wheel-scroll> <div style="padding-left:15px; font-size:10px; color:grey"> {{prettify(fromDate)}} - {{prettify(toDate)}} ({{'kTimelineOnlyDisplaying1' | translate:translationData}}) diff --git a/www/templates/wizard.html b/www/templates/wizard.html index ca2daf6a..3d20c522 100644 --- a/www/templates/wizard.html +++ b/www/templates/wizard.html @@ -86,6 +86,7 @@ <wz-step wz-title="3" > + <br/><br/> <h4>{{'kWizResults' | translate}}</h4> <span ng-if="wizard.portalValidText" style="color:{{wizard.portalColor}};"><i ng-class="wizard.portalColor=='#16a085' ? 'ion-checkmark-circled':'ion-close-circled'"></i> {{wizard.portalValidText}}<br/></span> |
