summaryrefslogtreecommitdiff
path: root/www
diff options
context:
space:
mode:
authorPliable Pixels <pliablepixels@gmail.com>2017-12-08 20:16:51 -0500
committerPliable Pixels <pliablepixels@gmail.com>2017-12-08 20:16:51 -0500
commit21856d3106726668616fdf4b96e9a7b02ce69d42 (patch)
tree845d5355b46033152c15f0d8a9d31e1cf040b55c /www
parentbba28ae5040046886bcb35b38da4c1ac2af2002b (diff)
image fade in, placeholders, doubled image size during fetch for resolution, w/h tweaks #91
Diffstat (limited to 'www')
-rw-r--r--www/external/ng-image-appear.min.js1
-rw-r--r--www/external/origjs/ng-image-appear.js361
-rw-r--r--www/index.html5
-rwxr-xr-xwww/js/DataModel.js2
-rw-r--r--www/js/EventCtrl.js77
-rwxr-xr-xwww/js/app.js4
-rw-r--r--www/templates/events.html15
-rw-r--r--www/templates/image-modal.html10
8 files changed, 462 insertions, 13 deletions
diff --git a/www/external/ng-image-appear.min.js b/www/external/ng-image-appear.min.js
new file mode 100644
index 00000000..ccbc902a
--- /dev/null
+++ b/www/external/ng-image-appear.min.js
@@ -0,0 +1 @@
+!function(){"use strict";var A=angular.module("ngImageAppear",[]),e="#f0f0f0";A.run(function(){var A,e=document.head;if(void 0===A){A=document.createElement("style");A.appendChild(document.createTextNode("@animation .ngImageAppearLoader {width: 40px; height: 40px; position: absolute; left: calc((100% - 40px) / 2); top: calc((100% - 40px) / 2);} .ngImageAppearPlaceholder {position: relative; display: inline-block; background-size: cover; background-repeat: no-repeat; background-position: center center; background-color: #f0f0f0;}")),e.insertBefore(A,e.firstChild)}}),A.directive("ngImageAppear",["$timeout",function(A){return{restrict:"A",link:function(M,t,i){function o(A,e,M){void 0!==g&&""!==g&&(x+=g),(S=document.createElement("div")).setAttribute("style",x),S.className=w,void 0!==r&&""!==r&&(S.className+=" "+r),N?(k=Math.round(100*A/e),k+="%",S.style.width=k):(k=Math.round(A),k+="px",S.style.width=k);for(var t in M)S.style[t]=M[t];if(Q.style.width="100%",Q.style.padding=Q.style.margin=0,Q.replaceWith(S),S.appendChild(Q),!D){S.offsetWidth>=70?function(){function A(){z=document.createElement("img");for(var A in m)z[A]=m[A];z.style.margin=z.style.padding=z.style.border=z.style.borderRadius=0,z.style.boxShadow=z.style.float="none",z.style.transform=z.style.outline="",S.appendChild(z),O=!0}if(l){var e=l.split(".").pop();"gif"===(e=e.substring(0,3))?A():console.warn("The custom loader image should have a proper gif extension. Read full documentation here - https://github.com/ArunMichaelDsouza/ng-image-appear")}else A()}():E=!0}void 0!==j&&""!==j&&(f=y+" "+j+" "+p)}function a(A,e){var M=window.getComputedStyle(A),t=parseFloat(M.paddingLeft)+parseFloat(M.paddingRight);return"wrapper"===e?A.offsetWidth-t:A.offsetWidth}function u(){!function(){if(!E&&!D&&O){var A=t[0].nextSibling;A&&A.parentNode.removeChild(A)}}(),function(){var A=setInterval(function(){if(void 0!==S){clearInterval(A),S.style.backgroundColor=S.style.position=Q.style.width=Q.style.padding=Q.style.margin=Q.style.border=Q.style.borderRadius=Q.style.boxShadow=Q.style.float=Q.style.transform=Q.style.outline="";var e=t[0].parentNode;e.parentNode.replaceChild(t[0],e)}},1)}(),A(function(){t.css({transition:" all "+C+" "+p,opacity:1,animation:y?f:""})},100)}function n(){u(),t.unbind("load")}function s(){t.css({opacity:0}),function(){Q=t[0],T=Q.parentNode;var A=setInterval(function(){if(0!==Q.offsetWidth&&0!==Q.clientHeight){clearInterval(A);var e={padding:window.getComputedStyle(Q).padding,margin:window.getComputedStyle(Q).margin,borderRadius:window.getComputedStyle(Q).borderRadius,border:window.getComputedStyle(Q).border,boxShadow:window.getComputedStyle(Q).boxShadow,float:window.getComputedStyle(Q).float,transform:window.getComputedStyle(Q).transform,outline:window.getComputedStyle(Q).outline},M=a(T,"wrapper");o(a(t[0],"image"),M,e)}},1)}(),t[0].complete?u():t.bind("load",n)}var w="ngImageAppearPlaceholder",C=i.transitionDuration,D=t[0].hasAttribute("no-loader"),L=i.placeholder,r=i.placeholderClass,g=i.placeholderStyle,d=i.bgColor,l=i.loaderImg,I=i.loaderClass,c=i.loaderStyle,j=i.animationDuration,y=i.animation,N=t[0].hasAttribute("responsive"),p=i.easing,m={className:"ngImageAppearLoader"};void 0!==I&&(m.className+=" "+I),void 0!==c&&""!==c&&(m.style=c),C=C||"0.7s",d=d||e,j=j||"0.7s",p=p||"ease-in-out",m.src=l||"data:image/gif;base64,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";var Q,T,S,z,k,f,x="background-color: "+d+"; ",E=!1,O=!1;void 0!==L&&(x+=""===L?"background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iNDIuNjVweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgNDIuNjUgMzIiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQyLjY1IDMyIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxnPg0KCQk8cGF0aCBmaWxsPSIjRDNEM0QzIiBkPSJNMCwwaDQyLjYzN2MwLjAyNCwwLjM1NCwwLjAwNCwwLjcxLDAuMDExLDEuMDY2YzAsMTAuMzEzLDAsMjAuNjI0LDAsMzAuOTM0SDBWMHogTTE1Ljg0OSwxMS41MDINCgkJCWMwLDIuOTYzLTAuMDAyLDUuOTI3LDAuMDAxLDguODkxYzMuNjQ0LDAuMDAzLDcuMjksMC4wMDMsMTAuOTM2LDBjMC4wMDItMi45NjQsMC4wMDItNS45MjcsMC04Ljg5MQ0KCQkJQzIzLjE0MSwxMS40OTgsMTkuNDk1LDExLjQ5OCwxNS44NDksMTEuNTAyeiIvPg0KCTwvZz4NCgk8Zz4NCgkJPHBhdGggZmlsbD0iI0QzRDNEMyIgZD0iTTE2LjUzNywxMi4xODZjMy4xODgsMCw2LjM3NSwwLDkuNTY0LDBjMC4wMDEsMi41MDksMC4wMDEsNS4wMTQtMC4wMDIsNy41MjENCgkJCWMtMy4xODgsMC4wMDMtNi4zNzUsMC4wMDMtOS41NjMsMEMxNi41MzMsMTcuMTk5LDE2LjUzMywxNC42OTQsMTYuNTM3LDEyLjE4NnogTTE3LjIxNSwxMi44N2MwLDIuMDUyLTAuMDAyLDQuMTAzLDAuMDAyLDYuMTU1DQoJCQljMC40NTcsMCwwLjkxNSwwLjAwMywxLjM3My0wLjAwNGMwLjQxLTAuNDA5LDAuODIxLTAuODIxLDEuMjMyLTEuMjMyYzAuMDU2LTAuMDU0LDAuMTA2LTAuMTIxLDAuMTgzLTAuMTQ3DQoJCQljMC42NjUtMC4yMjYsMS4zMzUtMC40NDEsMi0wLjY3MmMwLjIyNi0wLjY4MSwwLjQ1MS0xLjM2MSwwLjY3OS0yLjA0MmMwLjE3OSwwLjM1MiwwLjM1NCwwLjcwNywwLjUzMSwxLjA2MQ0KCQkJYzAuMDY2LDAuMTM1LDAuMTQzLDAuMjY2LDAuMTg4LDAuNDA4YzAuMjA3LDAuNjI2LDAuNDE3LDEuMjUxLDAuNjI1LDEuODc4YzAuMDIxLDAuMDc4LDAuMDg3LDAuMTM0LDAuMTQ1LDAuMTkNCgkJCWMwLjE5LDAuMTg1LDAuMzcxLDAuMzc3LDAuNTY1LDAuNTZjMC4yMjgsMCwwLjQ1MywwLjAwMiwwLjY4MywwYzAuMDAyLTIuMDUyLDAuMDAyLTQuMTAzLDAtNi4xNTUNCgkJCUMyMi42ODYsMTIuODY4LDE5Ljk1LDEyLjg2OCwxNy4yMTUsMTIuODd6Ii8+DQoJPC9nPg0KCTxwYXRoIGZpbGw9IiNEM0QzRDMiIGQ9Ik0xOS4zNzcsMTMuNTgyYzAuNDctMC4xMiwwLjk5NywwLjE0OSwxLjE3NSwwLjU5OWMwLjIwMywwLjQ1NSwwLjAxLDEuMDM2LTAuNDI0LDEuMjc5DQoJCWMtMC40MTgsMC4yNjEtMS4wMTYsMC4xNTEtMS4zMTYtMC4yMzljLTAuMzA0LTAuMzY1LTAuMjk4LTAuOTM5LDAuMDEyLTEuMjk5QzE4Ljk2NSwxMy43NTMsMTkuMTYzLDEzLjYzMiwxOS4zNzcsMTMuNTgyeiIvPg0KPC9nPg0KPC9zdmc+DQo=); ":"background-image: url("+L+"); "),M.$watch(function(){return t[0].getAttribute("src")},function(A,e){A&&A!==e&&s()}),s()}}}])}();
diff --git a/www/external/origjs/ng-image-appear.js b/www/external/origjs/ng-image-appear.js
new file mode 100644
index 00000000..e20a65e0
--- /dev/null
+++ b/www/external/origjs/ng-image-appear.js
@@ -0,0 +1,361 @@
+/*
+ ng-image-appear v1.11.5
+ Copyright (c) 2016 Arun Michael Dsouza (amdsouza92@gmail.com)
+ Licence: MIT
+ Demo on CodePen - http://codepen.io/amdsouza92/full/aNQeWW/
+*/
+
+(function() {
+ 'use strict';
+
+ // Declaring ngImageAppear module
+ var ngImageAppear = angular.module('ngImageAppear', []);
+
+ // Default background color for image wrapper
+ var defaultBackgroundColor = '#f0f0f0';
+
+ // ngImageAppear initialization code
+ ngImageAppear.run(function() {
+
+ // Creating default stylesheet for elements
+ var defaultStylesheet,
+ head = document.head;
+
+ // Checking if default stylesheet already exists in DOM
+ if(defaultStylesheet === undefined) {
+ defaultStylesheet = document.createElement('style');
+
+ // Default CSS stylesheet
+ // Styles for elements + animations
+ var css = '@animation .ngImageAppearLoader {width: 40px; height: 40px; position: absolute; left: calc((100% - 40px) / 2); top: calc((100% - 40px) / 2);} .ngImageAppearPlaceholder {position: relative; display: inline-block; background-size: cover; background-repeat: no-repeat; background-position: center center; background-color: '+defaultBackgroundColor+';}';
+
+ // Adding CSS text to default stylesheet
+ defaultStylesheet.appendChild(document.createTextNode(css));
+
+ // Prepend default stylesheet to head
+ head.insertBefore(defaultStylesheet, head.firstChild);
+ }
+ });
+
+ // ngImageAppear directive
+ ngImageAppear.directive('ngImageAppear',['$timeout', function($timeout) {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs) {
+
+ // Set default CSS classes for elements
+ var defaultLoaderClass = 'ngImageAppearLoader',
+ defaultPlaceholderClass = 'ngImageAppearPlaceholder';
+
+ // Fetching element attributes
+ var transitionDurationAttr = attrs.transitionDuration, // Set transition duration
+ noLoaderAttr = element[0].hasAttribute('no-loader'), // Check if loader is to be hidden
+ placeholderAttr = attrs.placeholder, // Check if default placeholder image is to be shown
+ placeholderClassAttr = attrs.placeholderClass, // Set CSS class for placeholder (image wrapper)
+ placeholderStyleAttr = attrs.placeholderStyle, // Set CSS styles for placeholder (image wrapper)
+ bgColorAttr = attrs.bgColor, // Set loader wrapper background color
+ loaderImgAttr = attrs.loaderImg, // Set custom loader image
+ loaderClassAttr = attrs.loaderClass, // Set CSS class for loader element
+ loaderStyleAttr = attrs.loaderStyle, // Set custom styles for loader element
+ animationDurationAttr = attrs.animationDuration, // Set animation duration
+ animationAttr = attrs.animation, // Set animation type
+ isResponsiveAttr = element[0].hasAttribute('responsive'), // Check if image is to be set responsive or not
+ easingAttr = attrs.easing; // Set easing for transition/animation
+
+ // Setting default loader attributes
+ var loaderSrc = 'data:image/gif;base64,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',
+ defaultPlaceholder = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iNDIuNjVweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgNDIuNjUgMzIiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQyLjY1IDMyIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxnPg0KCQk8cGF0aCBmaWxsPSIjRDNEM0QzIiBkPSJNMCwwaDQyLjYzN2MwLjAyNCwwLjM1NCwwLjAwNCwwLjcxLDAuMDExLDEuMDY2YzAsMTAuMzEzLDAsMjAuNjI0LDAsMzAuOTM0SDBWMHogTTE1Ljg0OSwxMS41MDINCgkJCWMwLDIuOTYzLTAuMDAyLDUuOTI3LDAuMDAxLDguODkxYzMuNjQ0LDAuMDAzLDcuMjksMC4wMDMsMTAuOTM2LDBjMC4wMDItMi45NjQsMC4wMDItNS45MjcsMC04Ljg5MQ0KCQkJQzIzLjE0MSwxMS40OTgsMTkuNDk1LDExLjQ5OCwxNS44NDksMTEuNTAyeiIvPg0KCTwvZz4NCgk8Zz4NCgkJPHBhdGggZmlsbD0iI0QzRDNEMyIgZD0iTTE2LjUzNywxMi4xODZjMy4xODgsMCw2LjM3NSwwLDkuNTY0LDBjMC4wMDEsMi41MDksMC4wMDEsNS4wMTQtMC4wMDIsNy41MjENCgkJCWMtMy4xODgsMC4wMDMtNi4zNzUsMC4wMDMtOS41NjMsMEMxNi41MzMsMTcuMTk5LDE2LjUzMywxNC42OTQsMTYuNTM3LDEyLjE4NnogTTE3LjIxNSwxMi44N2MwLDIuMDUyLTAuMDAyLDQuMTAzLDAuMDAyLDYuMTU1DQoJCQljMC40NTcsMCwwLjkxNSwwLjAwMywxLjM3My0wLjAwNGMwLjQxLTAuNDA5LDAuODIxLTAuODIxLDEuMjMyLTEuMjMyYzAuMDU2LTAuMDU0LDAuMTA2LTAuMTIxLDAuMTgzLTAuMTQ3DQoJCQljMC42NjUtMC4yMjYsMS4zMzUtMC40NDEsMi0wLjY3MmMwLjIyNi0wLjY4MSwwLjQ1MS0xLjM2MSwwLjY3OS0yLjA0MmMwLjE3OSwwLjM1MiwwLjM1NCwwLjcwNywwLjUzMSwxLjA2MQ0KCQkJYzAuMDY2LDAuMTM1LDAuMTQzLDAuMjY2LDAuMTg4LDAuNDA4YzAuMjA3LDAuNjI2LDAuNDE3LDEuMjUxLDAuNjI1LDEuODc4YzAuMDIxLDAuMDc4LDAuMDg3LDAuMTM0LDAuMTQ1LDAuMTkNCgkJCWMwLjE5LDAuMTg1LDAuMzcxLDAuMzc3LDAuNTY1LDAuNTZjMC4yMjgsMCwwLjQ1MywwLjAwMiwwLjY4MywwYzAuMDAyLTIuMDUyLDAuMDAyLTQuMTAzLDAtNi4xNTUNCgkJCUMyMi42ODYsMTIuODY4LDE5Ljk1LDEyLjg2OCwxNy4yMTUsMTIuODd6Ii8+DQoJPC9nPg0KCTxwYXRoIGZpbGw9IiNEM0QzRDMiIGQ9Ik0xOS4zNzcsMTMuNTgyYzAuNDctMC4xMiwwLjk5NywwLjE0OSwxLjE3NSwwLjU5OWMwLjIwMywwLjQ1NSwwLjAxLDEuMDM2LTAuNDI0LDEuMjc5DQoJCWMtMC40MTgsMC4yNjEtMS4wMTYsMC4xNTEtMS4zMTYtMC4yMzljLTAuMzA0LTAuMzY1LTAuMjk4LTAuOTM5LDAuMDEyLTEuMjk5QzE4Ljk2NSwxMy43NTMsMTkuMTYzLDEzLjYzMiwxOS4zNzcsMTMuNTgyeiIvPg0KPC9nPg0KPC9zdmc+DQo=',
+ loaderObject = {
+ 'className': defaultLoaderClass
+ };
+
+ // Attach CSS class to loader element if attribute is present
+ if(loaderClassAttr !== undefined) {
+ loaderObject.className += ' '+loaderClassAttr;
+ }
+
+ // Set custom styles for loader element if attribute is present
+ if(loaderStyleAttr !== undefined && loaderStyleAttr !== '') {
+ loaderObject.style = loaderStyleAttr;
+ }
+
+ // Setting values for element attributes
+ transitionDurationAttr = !transitionDurationAttr ? 0.7+'s' : transitionDurationAttr; // Set transition duration, default - 700ms
+ bgColorAttr = !bgColorAttr ? defaultBackgroundColor : bgColorAttr, // Set default bg color for loader wrapper
+ animationDurationAttr = !animationDurationAttr ? 0.7+'s' : animationDurationAttr; // Set transition duration, default - 700ms
+ easingAttr = !easingAttr ? 'ease-in-out' : easingAttr; // Set easing for transition, default - ease-in-out
+
+ // Set custom loader image if present
+ loaderObject.src = loaderImgAttr ? loaderImgAttr : loaderSrc;
+
+ // DOM manipulation element variable declarations
+ var imgElement,
+ parentElement,
+ imgWrapper,
+ loaderElement,
+ wrapperStyles = 'background-color: '+bgColorAttr+'; ',
+ setImageElementWidth,
+ isSmall = false,
+ hasShownLoader = false,
+ animationText;
+
+ // Add placeholder image if attribute is present
+ if(placeholderAttr !== undefined) {
+ if(placeholderAttr === '') {
+ // Set default placeholder
+ wrapperStyles += 'background-image: url('+defaultPlaceholder+'); ';
+ }
+ else {
+ // Set custom placeholder
+ wrapperStyles += 'background-image: url('+placeholderAttr+'); ';
+ }
+ }
+
+ // Function to render loader
+ function renderLoader() {
+
+ // Show loader in DOM
+ function showLoader() {
+ loaderElement = document.createElement('img');
+
+ // Adding loader object properties to loader element
+ for(var key in loaderObject) {
+ loaderElement[key] = loaderObject[key];
+ }
+
+ // Set loader element's visual styles to null
+ loaderElement.style.margin = loaderElement.style.padding = loaderElement.style.border = loaderElement.style.borderRadius = 0;
+ loaderElement.style.boxShadow = loaderElement.style.float = 'none';
+ loaderElement.style.transform = loaderElement.style.outline = '';
+
+ // Add loader to DOM
+ imgWrapper.appendChild(loaderElement);
+ hasShownLoader = true;
+ }
+
+ // Check custom loader image extension
+ if(loaderImgAttr) {
+
+ // Get filetype of image
+ var fileType = loaderImgAttr.split('.').pop();
+ fileType = fileType.substring(0,3);
+
+ // Show loader if gif file is present
+ if(fileType === 'gif') {
+ showLoader();
+ }
+ // Else throw warning in console
+ else {
+ console.warn('The custom loader image should have a proper gif extension. Read full documentation here - https://github.com/ArunMichaelDsouza/ng-image-appear');
+ }
+ }
+ else {
+ showLoader();
+ }
+ }
+
+ // Function to remove loader element from DOM
+ function removeLoader() {
+
+ // Check for loader visibility flags
+ if(!isSmall && !noLoaderAttr && hasShownLoader) {
+ var elementLoader = element[0].nextSibling; // Get loader of current element
+ if(elementLoader) {
+ elementLoader.parentNode.removeChild(elementLoader); // Remove rendered loader from DOM
+ }
+ }
+ }
+
+ // Function to remove wrapper element from DOM
+ function removeImgWrapper() {
+
+ // Interval to check that image wrapper has been rendered in DOM
+ var intervalRemove = setInterval(function() {
+ if(imgWrapper !== undefined) {
+ clearInterval(intervalRemove);
+
+ // Reset img wrapper CSS
+ imgWrapper.style.backgroundColor = imgWrapper.style.position = imgElement.style.width = imgElement.style.padding = imgElement.style.margin = imgElement.style.border = imgElement.style.borderRadius = imgElement.style.boxShadow = imgElement.style.float = imgElement.style.transform = imgElement.style.outline = '';
+
+ var wrapper = element[0].parentNode,
+ wrapperParent = wrapper.parentNode;
+ wrapperParent.replaceChild(element[0], wrapper); // Replace wrapper with actual image element
+ }
+ }, 1);
+ }
+
+ // Function to render image wrapper in DOM
+ function renderImageWrapper(imgElementWidth, parentElementWidth, imgElementStyles) {
+
+ // Append placeholder styles to image wrapper if attribute is present
+ if(placeholderStyleAttr !== undefined && placeholderStyleAttr !== '') {
+ wrapperStyles += placeholderStyleAttr;
+ }
+
+ imgWrapper = document.createElement('div'); // Create wrapper element for image
+ imgWrapper.setAttribute('style', wrapperStyles); // Set default CSS for wrapper element
+ imgWrapper.className = defaultPlaceholderClass; // Attach default CSS placeholder class to image wrapper
+
+ // Append placeholder custom class if attribute is present
+ if(placeholderClassAttr !== undefined && placeholderClassAttr !== '') {
+ imgWrapper.className += ' '+placeholderClassAttr;
+ }
+
+ // Set default CSS width + unit for img element
+ if(isResponsiveAttr) {
+ // Set image element width in %
+ setImageElementWidth = Math.round((imgElementWidth * 100) / parentElementWidth);
+ setImageElementWidth+= '%';
+
+ // Set wrapper width to width of image element
+ imgWrapper.style.width = setImageElementWidth;
+ }
+ else {
+ // Set image element width in px
+ setImageElementWidth = Math.round(imgElementWidth);
+ setImageElementWidth+= 'px';
+
+ // Set wrapper width to width of image element
+ imgWrapper.style.width = setImageElementWidth;
+ }
+
+ // Add image element styles to wrapper element
+ for(var property in imgElementStyles) {
+ imgWrapper.style[property] = imgElementStyles[property];
+ }
+
+ imgElement.style.width = '100%'; // Span image element to 100% width of wrapper
+ imgElement.style.padding = imgElement.style.margin = 0; // Set image element's margin/padding to 0
+
+ //PP
+ //parentElement.replaceChild(imgWrapper, imgElement); // Replace actual image element with wrapper element
+ imgElement.replaceWith(imgWrapper);
+ imgWrapper.appendChild(imgElement); // Append actual image element to wrapper element
+ // This will wrap the image element into a parent div tag used for showing the loader
+
+ // Show loader if 'no-loader' attribute is not present
+ if(!noLoaderAttr) {
+ var imgWrapperWidth = imgWrapper.offsetWidth;
+
+ // Show loader if wrapper width is more than 70px
+ imgWrapperWidth >= 70 ? renderLoader() : isSmall = true;
+ }
+
+ // Create animation sequence if attribute is present
+ if(animationDurationAttr !== undefined && animationDurationAttr !== '') {
+ animationText = animationAttr+' '+animationDurationAttr+' '+easingAttr;
+ }
+ }
+
+ // Function to get element's content width (without horizontal padding)
+ function getElementContentWidth(element, type) {
+ var styles = window.getComputedStyle(element), // Get computed styles of element
+ padding = parseFloat(styles.paddingLeft) + parseFloat(styles.paddingRight); // Get horizontal padding of element
+
+ // Return content width
+ if(type === 'wrapper') {
+ return element.offsetWidth - padding;
+ }
+ else {
+ return element.offsetWidth;
+ }
+ }
+
+ // Function to create image wrapper element
+ function generateImageWrapper() {
+ imgElement = element[0], // Get image element
+ parentElement = imgElement.parentNode; // Get parent of image element
+
+ // Fire interval for checking image's width/height until calculated by DOM
+ var interval = setInterval(function() {
+
+ // If image element's width and height have been calculated by DOM then clear interval
+ if(imgElement.offsetWidth !== 0 && imgElement.clientHeight !== 0) {
+ clearInterval(interval);
+
+ // Get image element's visual styles and set it to wrapper element when rendered in DOM
+ var imgElementStyles = {
+ padding: window.getComputedStyle(imgElement).padding,
+ margin: window.getComputedStyle(imgElement).margin,
+ borderRadius: window.getComputedStyle(imgElement).borderRadius,
+ border: window.getComputedStyle(imgElement).border,
+ boxShadow: window.getComputedStyle(imgElement).boxShadow,
+ float: window.getComputedStyle(imgElement).float,
+ transform: window.getComputedStyle(imgElement).transform,
+ outline: window.getComputedStyle(imgElement).outline
+ };
+
+ // Set content width for parent, image elements
+ var parentElementWidth = getElementContentWidth(parentElement, 'wrapper'),
+ imgElementWidth = getElementContentWidth(element[0], 'image');
+
+ // Render image wrapper
+ renderImageWrapper(imgElementWidth, parentElementWidth, imgElementStyles);
+ }
+ }, 1);
+ }
+
+ // Function to load image into DOM
+ function loadImage() {
+ removeLoader(); // Remove loader element once image is loaded
+
+ removeImgWrapper(); // Remove image wrapper from DOM
+
+ // Make element appear with transition/animation
+ $timeout(function() {
+ element.css({
+ 'transition': ' all '+ transitionDurationAttr +' '+ easingAttr, // Set element transition
+ 'opacity': 1, // Show image element in view
+ 'animation': animationAttr ? animationText : '' // Set element animation
+ });
+ }, 100); // Timeout to clear stack and rebuild DOM
+ }
+
+ // Function to initiate actual image load
+ function onImageLoad() {
+ loadImage();
+ element.unbind('load');
+ }
+
+ // Function to initialise directive
+ function initialize() {
+
+ // Hide image element from view
+ element.css({
+ 'opacity': 0
+ });
+
+ // Create image wrapper for loader
+ generateImageWrapper();
+
+ // Check if image element has already been completely downloaded
+ if(element[0].complete) {
+ loadImage();
+ }
+ else {
+ // Else detect image load event
+ element.bind('load', onImageLoad);
+ }
+ }
+
+ // Function to get image element's source
+ function getImageSrc() {
+ return element[0].getAttribute('src');
+ }
+
+ // Attach a watcher to image element's source
+ scope.$watch(getImageSrc, function(newSrcValue, oldSrcValue) {
+
+ // Check if the image element's source has actually changed
+ if(newSrcValue && newSrcValue !== oldSrcValue) {
+ initialize(); // Re-initialise directive
+ }
+
+ });
+
+ // Initialise directive
+ initialize();
+ }
+ };
+ }]);
+})();
diff --git a/www/index.html b/www/index.html
index 604f6e9e..cf7728bf 100644
--- a/www/index.html
+++ b/www/index.html
@@ -85,7 +85,10 @@
<script src="external/polyfill.min.js"></script>
<script src="external/gifwriter.min.js"></script>
<script src="external/NeuQuant.min.js"></script>
- <script src="external/angular.dcb-img-fallback.min.js"></script>
+ <script src="external/angular.dcb-img-fallback.min.js"></script>
+ <script src="external/ng-image-appear.min.js"></script>
+
+
diff --git a/www/js/DataModel.js b/www/js/DataModel.js
index 4fd3a791..1b83ce48 100755
--- a/www/js/DataModel.js
+++ b/www/js/DataModel.js
@@ -2028,7 +2028,7 @@ angular.module('zmApp.controllers')
}
}
- return "(Unknown)";
+ return undefined;
},
getImageMode: function (id) {
diff --git a/www/js/EventCtrl.js b/www/js/EventCtrl.js
index 3468d988..73c6c77d 100644
--- a/www/js/EventCtrl.js
+++ b/www/js/EventCtrl.js
@@ -155,7 +155,7 @@ angular.module('zmApp.controllers')
if (NVRDataModel.getLogin().enableThumbs) {
NVRDataModel.debug ("--> thumbnail means increasing row size");
eventsListScrubHeight=370;
- eventsListDetailsHeight=300;
+ eventsListDetailsHeight=330;
}
@@ -380,6 +380,7 @@ angular.module('zmApp.controllers')
// console.log ("WE GOT EVENTS="+JSON.stringify(data));
var myevents = data;
+
NVRDataModel.debug("EventCtrl: success, got " + myevents.length + " events");
var loginData = NVRDataModel.getLogin();
for (var i = 0; i < myevents.length; i++)
@@ -418,6 +419,46 @@ angular.module('zmApp.controllers')
myevents[i].Event.BasePath = computeBasePath(myevents[i]);
myevents[i].Event.relativePath = computeRelativePath(myevents[i]);
+ // get thumbW/H
+
+ var tempMon = NVRDataModel.getMonitorObject(myevents[i].Event.MonitorId);
+ if (tempMon != undefined) {
+
+ var ratio;
+ var mw = parseInt(tempMon.Monitor.Width);
+ var mh = parseInt(tempMon.Monitor.Height);
+ var mo = Math.abs(parseInt(tempMon.Monitor.Orientation));
+
+ // scale by X if width > height
+ if (mw > mh ) {
+ ratio = mw / zm.thumbWidth;
+ myevents[i].Event.thumbWidth = 200;
+ myevents[i].Event.thumbHeight = Math.round(mh/ratio);
+ }
+ else {
+
+ ratio = mh / zm.thumbWidth;
+ myevents[i].Event.thumbHeight = 200;
+ myevents[i].Event.thumbWidth = Math.round(mw/ratio);
+
+ }
+
+ if (mo == 90) {
+ var t = myevents[i].Event.thumbHeight;
+ myevents[i].Event.thumbWidth = myevents[i].Event.thumbHeight;
+ myevents[i].Event.thumbHeight = t;
+
+
+ } // swap
+
+ console.log ("--------->" +"MW:"+myevents[i].Event.thumbWidth+ " MH:"+ myevents[i].Event.thumbHeight + " for Monitor:" + myevents[i].Event.MonitorName);
+
+
+
+
+
+ }
+
// in multiserver BasePath is login url for frames
// http://login.url/index.php?view=frame&eid=19696772&fid=21
@@ -2919,6 +2960,40 @@ angular.module('zmApp.controllers')
myevents[i].Event.relativePath = computeRelativePath(myevents[i]);
myevents[i].Event.height = eventsListDetailsHeight;
+ // get thumbW/H
+
+ var tempMon = NVRDataModel.getMonitorObject(myevents[i].Event.MonitorId);
+ if (tempMon != undefined) {
+
+ var ratio;
+ var mw = parseInt(tempMon.Monitor.Width);
+ var mh = parseInt(tempMon.Monitor.Height);
+ var mo = Math.abs(parseInt(tempMon.Monitor.Orientation));
+
+ // scale by X if width > height
+ if (mw > mh ) {
+ ratio = mw / zm.thumbWidth;
+ myevents[i].Event.thumbWidth = 200;
+ myevents[i].Event.thumbHeight = Math.round(mh/ratio);
+ }
+ else {
+
+ ratio = mh / zm.thumbWidth;
+ myevents[i].Event.thumbHeight = 200;
+ myevents[i].Event.thumbWidth = Math.round(mw/ratio);
+
+ }
+
+ if (mo == 90) {
+ var t = myevents[i].Event.thumbHeight;
+ myevents[i].Event.thumbWidth = myevents[i].Event.thumbHeight;
+ myevents[i].Event.thumbHeight = t;
+
+
+ } // swap
+ }
+
+
if (myevents[i].Event.imageMode == 'path')
//if (1)
myevents[i].Event.videoPath = myevents[i].Event.baseURL + "/events/" + myevents[i].Event.relativePath + myevents[i].Event.DefaultVideo;
diff --git a/www/js/app.js b/www/js/app.js
index 15c6aeab..a4fafc9e 100755
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -29,6 +29,7 @@ angular.module('zmApp', [
'jett.ionic.scroll.sista',
'uk.ac.soton.ecs.videogular.plugins.cuepoints',
'dcbImgFallback',
+ 'ngImageAppear'
])
@@ -102,7 +103,8 @@ angular.module('zmApp', [
maxGifWidth: 800.0,
quantSample: 15,
hashSecret: 'unused at the moment',
- forceMontageReloadDelay: 3600 // 1 hr
+ forceMontageReloadDelay: 3600, // 1 hr,
+ thumbWidth:200
})
diff --git a/www/templates/events.html b/www/templates/events.html
index 8157d0f6..999c8c88 100644
--- a/www/templates/events.html
+++ b/www/templates/events.html
@@ -25,7 +25,7 @@
<!-- lets make sure the events list is not empty as collection repeat needs height -->
<div ng-if="!eventsBeingLoaded">
<ion-list show-delete="eventList.showDelete">
- <ion-item collection-repeat="event in events| filter:search.text | eventListFilter
+ <ion-item force-refresh-images="true" collection-repeat="event in events| filter:search.text | eventListFilter
" item-height="event.Event.height" id="item-{{$index}}" on-swipe-left="checkSwipe($index);">
<span style="float:left;margin-top:-18px;background-color:#96281B;color:#fff;font-size:11px;opacity:0.7;border-radius: 0px 0px 5px 5px;">&nbsp;&nbsp;&nbsp;<i class="ion-calendar"></i>&nbsp;&nbsp;{{prettifyTime(event.Event.StartTime)}}&nbsp;{{tzAbbr}}&nbsp;</span>&nbsp;&nbsp;
<span style="float:left;margin-top:-18px;background-color:#fff;color:#888;font-size:11px;opacity:1;">&nbsp;&nbsp;<i class="ion-arrow-right-b"></i>&nbsp;{{event.Event.humanizeTime}} <span ng-if="!event.Event.EndTime">(<span translate="kRecordingProgress"></span>)</span>
@@ -64,7 +64,7 @@
<div class="col">
<div class="item-text-wrap">
- <b><i ng-if="event.Event.Archived=='1'" class="ion-ios-flag" style="color:red">&nbsp;</i>{{event.Event.MonitorName}}</b> ({{event.Event.Id}}) &nbsp;
+ <b><i ng-if="event.Event.Archived=='1'" class="ion-ios-flag" style="color:red">&nbsp;</i>{{event.Event.MonitorName}}</b> <span ng-if"!loginData.enableThumbs || !event.Event.MaxScore">({{event.Event.Id}})</span> &nbsp;
<button ng-if="gifshotSupported && loginData.enableGIFMP4 " class="button button-small button-clear icon gif-icon" ng-click="permissionsDownload(event)">
</button>
@@ -72,7 +72,7 @@
<a ng-if="(event.Event.DefaultVideo!='' && event.Event.DefaultVideo!==undefined) && $root.platformOS=='desktop' && loginData.enableGIFMP4 " class="button button-clear button-small icon mp4-icon" href="{{event.Event.videoPath}}" download="{{event.Event.Id}}-video.mp4" ng-click="mp4warning()"></a>
- <button ng-if="event.Event.DefaultVideo!='' && event.Event.DefaultVideo!=undefined && $root.platformOS!='desktop' && loginData.enableGIFMP4 " class="button button-small button-clear icon mp4-icon" ng-click="downloadFileToDevice(event.Event.videoPath, event.Event.Id)">
+ <button ng-if="event.Event.DefaultVideo!='' && event.Event.DefaultVideo!=undefined && $root.platformOS!='desktop' && lpoginData.enableGIFMP4 " class="button button-small button-clear icon mp4-icon" ng-click="downloadFileToDevice(event.Event.videoPath, event.Event.Id)">
</button>
</div>
@@ -80,15 +80,18 @@
<i class="ion-images"></i> {{event.Event.Frames}} &nbsp;
<i class="ion-ios-bell-outline"></i> {{event.Event.AlarmFrames}} &nbsp;
- <i class="ion-arrow-graph-up-right"></i> {{event.Event.TotScore}}
+ <!--<i class="ion-arrow-graph-up-right"></i> {{event.Event.TotScore}}-->
</div>
- <div ng-if="loginData.enableThumbs" class = "col col-left">
+ <div ng-if="loginData.enableThumbs && event.Event.MaxScore" class = "col col-left">
<!-- thumbnail -->
- <img style="max-width:150px; max-height:200px;" ng-src="{{event.Event.baseURL}}/index.php?view=image&fid={{event.Event.MaxScoreFrameId}}" on-tap="showThumbnail(event.Event.baseURL,event.Event.MaxScoreFrameId)" />
+ <!-- ng-image-appear transition-duration="0.5s" animation="fillIn" bg-color="#50a4e2" -->
+ <img ng-image-appear transition-duration="0.3s" animation="fillIn" bg-color="#50a4e2" width="{{event.Event.thumbWidth}}px" height="{{event.Event.thumbHeight}}px" ng-src="{{event.Event.baseURL}}/index.php?view=image&fid={{event.Event.MaxScoreFrameId}}&width={{event.Event.thumbWidth*2}}&height={{event.Event.thumbHeight*2}}" on-tap="showThumbnail(event.Event.baseURL,event.Event.MaxScoreFrameId)" />
+ <!--<p>{{event.Event.thumbWidth}}px*{{event.Event.thumbHeight}}px</p>-->
+
</div>
</div>
diff --git a/www/templates/image-modal.html b/www/templates/image-modal.html
index 2ed126c6..7195bae7 100644
--- a/www/templates/image-modal.html
+++ b/www/templates/image-modal.html
@@ -1,5 +1,9 @@
<ion-modal-view cache-view="false" style="background-color:#444444">
-<ion-content>
- <img on-double-tap="closeModal();" src="{{thumbnailLarge}}" style="display:block; width:100%"/>
-</ion-content>
+ <ion-content>
+ <ion-scroll direction="xy" scrollbar-x="false" scrollbar-y="false" overflow-scroll="false" zooming="true">
+ <img on-double-tap="closeModal();" src="{{thumbnailLarge}}" style="display:block; width:100%" />
+
+ </ion-scroll>
+
+ </ion-content>
</ion-modal-view>