diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js index af46cf9b0f6d2ea46a480630fba3b5444ec6da7c..5a058037662fb25f88b06294fa364a945d4f78e5 100644 --- a/www/js/services/utils-services.js +++ b/www/js/services/utils-services.js @@ -26,17 +26,17 @@ angular.module('cesium.utils.services', []) var loadingTextCache=null, CONST = { - MAX_HEIGHT: 400, - MAX_WIDTH: 400, - THUMB_MAX_HEIGHT: 100, - THUMB_MAX_WIDTH: 100 + MAX_HEIGHT: 480, + MAX_WIDTH: 640, + THUMB_MAX_HEIGHT: 200, + THUMB_MAX_WIDTH: 200 }, data = { smallscreen: screenmatch.bind('xs, sm', $rootScope) }, exports, raw = {} - ; + ; function alertError(err, subtitle) { if (!err) { @@ -45,45 +45,45 @@ angular.module('cesium.utils.services', []) return $q(function(resolve) { $translate([err, subtitle, 'ERROR.POPUP_TITLE', 'ERROR.UNKNOWN_ERROR', 'COMMON.BTN_OK']) - .then(function (translations) { - var message = err.message || translations[err]; - return $ionicPopup.show({ - template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', - title: translations['ERROR.POPUP_TITLE'], - subTitle: translations[subtitle], - buttons: [ - { - text: '<b>'+translations['COMMON.BTN_OK']+'</b>', - type: 'button-assertive', - onTap: function(e) { - resolve(e); + .then(function (translations) { + var message = err.message || translations[err]; + return $ionicPopup.show({ + template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', + title: translations['ERROR.POPUP_TITLE'], + subTitle: translations[subtitle], + buttons: [ + { + text: '<b>'+translations['COMMON.BTN_OK']+'</b>', + type: 'button-assertive', + onTap: function(e) { + resolve(e); + } } - } - ] + ] + }); }); - }); }); } function alertInfo(message, subtitle) { return $q(function(resolve) { $translate([message, subtitle, 'INFO.POPUP_TITLE', 'COMMON.BTN_OK']) - .then(function (translations) { - $ionicPopup.show({ - template: '<p>' + translations[message] + '</p>', - title: translations['INFO.POPUP_TITLE'], - subTitle: translations[subtitle], - buttons: [ - { - text: translations['COMMON.BTN_OK'], - type: 'button-positive', - onTap: function(e) { - resolve(e); + .then(function (translations) { + $ionicPopup.show({ + template: '<p>' + translations[message] + '</p>', + title: translations['INFO.POPUP_TITLE'], + subTitle: translations[subtitle], + buttons: [ + { + text: translations['COMMON.BTN_OK'], + type: 'button-positive', + onTap: function(e) { + resolve(e); + } } - } - ] + ] + }); }); - }); }); } @@ -243,41 +243,82 @@ angular.module('cesium.utils.services', []) function getSelectionText(){ var selectedText = ""; if (window.getSelection){ // all modern browsers and IE9+ - selectedText = $window.getSelection().toString(); + selectedText = $window.getSelection().toString(); } return selectedText; } function imageOnLoadResize(resolve, reject, thumbnail) { return function(event) { - var width = event.target.width; - var height = event.target.height; - var maxWidth = (thumbnail ? CONST.THUMB_MAX_WIDTH : CONST.MAX_WIDTH); - var maxHeight = (thumbnail ? CONST.THUMB_MAX_HEIGHT : CONST.MAX_HEIGHT); - - if (width > height) { - if (width > maxWidth) { - height *= maxWidth / width; - width = maxWidth; - } - } else { - if (height > maxHeight) { - width *= maxHeight / height; - height = maxHeight; - } + var width = event.target.width, + height = event.target.height, + maxWidth = (thumbnail ? CONST.THUMB_MAX_WIDTH : CONST.MAX_WIDTH), + maxHeight = (thumbnail ? CONST.THUMB_MAX_HEIGHT : CONST.MAX_HEIGHT) + ; + + var canvas = document.createElement("canvas"); + var ctx; + + // Thumbnail: resize and crop (to the expected size) + if (thumbnail) { + + // landscape + if (width > height) { + width *= maxHeight / height; + height = maxHeight; + } + + // portrait + else { + height *= maxWidth / width; + width = maxWidth; + } + canvas.width = maxWidth; + canvas.height = maxHeight; + ctx = canvas.getContext("2d"); + var xoffset = Math.trunc((maxWidth - width) / 2 + 0.5); + var yoffset = Math.trunc((maxHeight - height) / 2 + 0.5); + ctx.drawImage(event.target, + xoffset, // x1 + yoffset, // y1 + maxWidth + -2 * xoffset, // x2 + maxHeight + -2 * yoffset // y2 + ); + } + + // Resize, but keep the full image + else { + + // landscape + if (width > height) { + if (width > maxWidth) { + height *= maxWidth / width; + width = maxWidth; } - var canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; - var ctx = canvas.getContext("2d"); - ctx.drawImage(event.target, 0, 0, canvas.width, canvas.height); + } - var dataurl = canvas.toDataURL(); + // portrait + else { + if (height > maxHeight) { + width *= maxHeight / height; + height = maxHeight; + } + } - canvas.remove(); + canvas.width = width; + canvas.height = height; + ctx = canvas.getContext("2d"); - resolve(dataurl); - }; + // Resize the whole image + ctx.drawImage(event.target, 0, 0, canvas.width, canvas.height); + } + + var dataurl = canvas.toDataURL(); + + canvas.remove(); + + resolve(dataurl); + }; } function resizeImageFromFile(file, thumbnail) { @@ -387,34 +428,34 @@ angular.module('cesium.utils.services', []) angular.merge(popover.scope, options.bindings); $timeout(function() { // This is need for Firefox popover.show(event) - .then(function() { - var element; - // Auto select text - if (options.autoselect) { - element = document.querySelectorAll(options.autoselect)[0]; - if (element) { - if ($window.getSelection && !$window.getSelection().toString()) { - element.setSelectionRange(0, element.value.length); - element.focus(); - } - else { - element.focus(); + .then(function() { + var element; + // Auto select text + if (options.autoselect) { + element = document.querySelectorAll(options.autoselect)[0]; + if (element) { + if ($window.getSelection && !$window.getSelection().toString()) { + element.setSelectionRange(0, element.value.length); + element.focus(); + } + else { + element.focus(); + } } } - } - else { - // Auto focus on a element - if (options.autofocus) { - element = document.querySelectorAll(options.autofocus)[0]; - if (element) element.focus(); + else { + // Auto focus on a element + if (options.autofocus) { + element = document.querySelectorAll(options.autofocus)[0]; + if (element) element.focus(); + } } - } - popover.scope.$parent.$emit('popover.shown'); + popover.scope.$parent.$emit('popover.shown'); - // Callback 'afterShow' - if (options.afterShow) options.afterShow(popover); - }); + // Callback 'afterShow' + if (options.afterShow) options.afterShow(popover); + }); }); }; @@ -424,9 +465,9 @@ angular.module('cesium.utils.services', []) delete options.scope.popovers[options.templateUrl]; // Remove the popover popover.remove() - // Workaround for issue #244 - // See also https://github.com/driftyco/ionic-v1/issues/71 - // and https://github.com/driftyco/ionic/issues/9069 + // Workaround for issue #244 + // See also https://github.com/driftyco/ionic-v1/issues/71 + // and https://github.com/driftyco/ionic/issues/9069 .then(function() { var bodyEl = angular.element($window.document.querySelectorAll('body')[0]); bodyEl.removeClass('popover-open'); @@ -628,7 +669,7 @@ angular.module('cesium.utils.services', []) function motionDelegate(delegate, ionListClass) { var motionTimeout = isSmallScreen() ? 100 : 10; var defaultSelector = '.list.{0} .item, .list .{0} .item'.format(ionListClass, ionListClass); - return { + return { ionListClass: ionListClass, show: function(options) { options = options || {}; @@ -688,8 +729,8 @@ angular.module('cesium.utils.services', []) ripple: motionDelegate(ionicMaterialMotion.ripple, 'animate-ripple'), slideUp: motionDelegate(ionicMaterialMotion.slideUp, 'slide-up'), fadeIn: motionDelegate(function(options) { - toggleOn(options); - }, 'fade-in'), + toggleOn(options); + }, 'fade-in'), toggleOn: toggleOn, toggleOff: toggleOff }; @@ -743,10 +784,8 @@ angular.module('cesium.utils.services', []) }, timeout || 900); } - - csSettings.api.data.on.changed($rootScope, function(data) { - setEffects(data.uiEffects); + setEffects(data.uiEffects); }); exports = { diff --git a/www/plugins/es/js/controllers/common-controllers.js b/www/plugins/es/js/controllers/common-controllers.js index 330c40e0aa69c5ffb8e93fbb7b9cfdf2b650544e..5b4e5bde214ac36ccacbff5079bb8a24f5e5f841 100644 --- a/www/plugins/es/js/controllers/common-controllers.js +++ b/www/plugins/es/js/controllers/common-controllers.js @@ -51,19 +51,23 @@ function ESPicturesEditController($scope, UIUtils, $q, Device) { }; $scope.fileChanged = function(event) { + if (!event.target.files || !event.target.files.length) return; UIUtils.loading.show(); - return $q(function(resolve, reject) { - var file = event.target.files[0]; - UIUtils.image.resizeFile(file) - .then(function(imageData) { - $scope.pictures.push({ - src: imageData, - isnew: true // use to prevent visibility hidden (if animation) - }); - UIUtils.loading.hide(100); - resolve(); + var file = event.target.files[0]; + return UIUtils.image.resizeFile(file) + .then(function(imageData) { + $scope.pictures.push({ + src: imageData, + isnew: true // use to prevent visibility hidden (if animation) }); - }); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(100); + }) + .catch(function(err) { + console.error(err); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(); + }); }; $scope.removePicture = function(index){ @@ -141,7 +145,7 @@ function ESCategoryModalController($scope, UIUtils, $timeout, parameters) { -function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { +function ESCommentsController($scope, $filter, $state, $focus, $timeout, $anchorScroll, UIUtils) { 'ngInject'; $scope.loading = true; @@ -150,8 +154,12 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.comments = {}; $scope.$on('$recordView.enter', function(e, state) { + // First enter + if ($scope.loading) { + $scope.anchor = state && state.stateParams.anchor; + } // second call (when using cached view) - if (!$scope.loading && $scope.id) { + else if (!$scope.loading && $scope.id) { $scope.load($scope.id, {animate: false}); } }); @@ -159,15 +167,21 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.$on('$recordView.load', function(event, id, service) { $scope.id = id || $scope.id; $scope.service = service || $scope.service; - console.debug("[ES] [comment] Initialized service with: " + service.id); + console.debug("[ES] [comment] Will use {" + service.index + "} service"); if ($scope.id) { - $scope.load($scope.id); + $scope.load($scope.id) + .then(function() { + // Scroll to anchor + $scope.scrollToAnchor(); + }); } }); $scope.load = function(id, options) { options = options || {}; options.from = options.from || 0; + // If anchor has been defined, load all comments + options.size = options.size || ($scope.anchor && -1/*all*/); options.size = options.size || $scope.defaultCommentSize; options.animate = angular.isDefined(options.animate) ? options.animate : true; options.loadAvatarAllParent = angular.isDefined(options.loadAvatarAllParent) ? options.loadAvatarAllParent : true; @@ -202,6 +216,25 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { } }); + $scope.scrollToAnchor = function() { + if (!$scope.anchor) return; + var elemList = document.getElementsByName($scope.anchor); + // Waiting for the element + if (!elemList || !elemList.length) { + return $timeout($scope.scrollToAnchor, 500); + } + // If many, remove all anchor except the last one + for (var i = 0; i<elemList.length-1; i++) { + angular.element(elemList[i]).remove(); + } + // Scroll to the anchor + $anchorScroll($scope.anchor); + // Remove the anchor. This will the CSS class 'positive-100-bg' on the comment + $timeout(function () { + $scope.anchor = null; + }, 1500); + }; + $scope.showMore = function(){ var from = 0; var size = -1; @@ -355,8 +388,6 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) selector: '#social-' + $filter('formatSlug')(social.url), startVelocity: 10000 }); - - }; $scope.editSocialNetwork = function(index) { @@ -381,9 +412,9 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) function ESSocialsViewController($scope) { 'ngInject'; - $scope.openSocial = function($event, social) { - $event.stopPropagation(); - return $scope.openLink($event, social.url, { + $scope.openSocial = function(event, social) { + event.stopPropagation(); + return $scope.openLink(event, social.url, { type: social.type }); }; @@ -482,7 +513,6 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { .catch(function(err) { console.error(err); // Silent loadingCurrentPosition = false; - //$scope.form.geoPoint.$setValidity('required', false); }); } @@ -507,22 +537,24 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { }); }; - $scope.onCityChanged = function() { - if ($scope.loading) return; - if ($scope.form) { - $scope.form.$valid = undefined; - } - if ($scope.formPosition.enable) { - return $scope.tryToLocalize(); - } - }; + $scope.onCityChanged = function() { + if ($scope.loading) return; + if ($scope.formPosition.enable) { + if ($scope.formData.geoPoint) { + // Invalidate the position + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; + } + return $scope.tryToLocalize(); + } + }; $scope.onUseGeopointChanged = function() { if ($scope.loading) return; if (!$scope.formPosition.enable) { if ($scope.formData.geoPoint) { - $scope.formData.geoPoint = null; - //$scope.form.geoPoint.$setValidity('required', true); + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; $scope.dirty = true; } } @@ -696,7 +728,7 @@ function ESLookupPositionController($scope, $q, csConfig, esGeo, ModalUtils) { }; } -function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConfig, esGeo) { +function ESSearchPositionItemController($scope, $timeout, ModalUtils, csConfig, esGeo) { 'ngInject'; // The default country used for address localisation @@ -780,15 +812,20 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf $scope.showDropdown = function() { var text = $scope.search.location && $scope.search.location.trim(); if (!text || text.length < minLength) { - $scope.locations = undefined; - return $q.when(); // nothing to search + return $scope.hideDropdown(true/*force, if still loading*/); } + // Compute a request id, to apply response only if current request + var requestId = ($scope.requestId && $scope.requestId + 1) || 1; + $scope.requestId = requestId; + loadingPosition = true; // Execute the given query return esGeo.point.searchByAddress(text) .then(function(res) { + if ($scope.requestId != requestId) return; // Skip apply if not same request: + loadingPosition = false; $scope.locations = res||[]; $scope.license = res && res.length && res[0].license; @@ -800,6 +837,7 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf }; $scope.hideDropdown = function(force) { + // force, even if still loading if (force) { $scope.locations = undefined; $scope.selectLocationIndex = -1; diff --git a/www/plugins/map/js/controllers/user-controllers.js b/www/plugins/map/js/controllers/user-controllers.js index 9fff394e579b9fed2a53f95ccdf11c76feb01ac6..5b429c2e5ed9531fca8050bdfbaca42372a7a01d 100644 --- a/www/plugins/map/js/controllers/user-controllers.js +++ b/www/plugins/map/js/controllers/user-controllers.js @@ -9,7 +9,16 @@ angular.module('cesium.map.user.controllers', ['cesium.services', 'cesium.map.se PluginServiceProvider - .extendState('app.user_edit_profile', { + .extendState('app.edit_profile', { + points: { + 'after-position': { + templateUrl: 'plugins/map/templates/user/edit_profile_extend.html', + controller: 'MapEditProfileViewCtrl' + } + } + }) + + .extendState('app.edit_profile_by_id', { points: { 'after-position': { templateUrl: 'plugins/map/templates/user/edit_profile_extend.html',