(function () { 'use strict'; var app = angular.module('app'); //directive to handle the registration process app.directive('register', ['common', 'config', 'auth', 'validation', 'datacontext', 'myUsersDataContext', '$window', 'fullScreenLoaderContext', 'paymentsDataContext', '$routeParams', 'OrganisationAdminService', '$location', function (common, config, authService, validation, datacontext, myUsersDataContext, $window, fsl, paymentsDataContext, $routeParams, OrganisationAdminService, $location) { return { restrict: 'E', // transclude: true, templateUrl: "app/register/registerdirective.html", scope: { emailDomains: '@', organisationId: '@', brandOrganisationId: '@' }, link: function ($scope, element, $attrs) { if (!$scope.emailDomains) $scope.emailDomains = ''; $scope.registrationInProgress = false; NProgress.done(); $scope.registerFailed = false; $scope.confirmed = false; $scope.redirectUrl = config.sysUrl; $scope.showUserExists = false; $scope.showOrgExists = false; $scope.user = { iAmRobot: false }; $scope.showPlans = $routeParams.payment; var ind = false; $scope.individual = ind; if ($location.search().hasOwnProperty('registration')) { var myvalue = $location.search()['registration']; // 'myvalue' now stores '33' if (myvalue == "individual") { ind = true; } $scope.individual = ind; } $scope.selectedCurrency = { code: 'usd', name: 'USD', symbol: '' } $scope.selectedUsers = 50; $scope.allAccountOptions = [ { planId: "myshowcaseAcademicUSD2", planName: "Academic / Charity", planDescription: "Myshowcase Non Profit", planCost: 300.0, planCurrency: "usd", planFrequency: "year", minQuantity: 50, maxQuantity: 500, }, { planId: "myshowcaseProfitUSD2", planName: "Government / For-profit", planDescription: "Myshowcase For Profit", planCost: 450.0, planCurrency: "usd", planFrequency: "year", minQuantity: 50, maxQuantity: 500, }, { planId: "myshowcaseAcademicEUR2", planName: "Academic / Charity", planDescription: "Myshowcase Non Profit", planCost: 300.0, planCurrency: "eur", planFrequency: "year", minQuantity: 50, maxQuantity: 500, }, { planId: "myshowcaseProfitEUR2", planName: "Government / For-profit", planDescription: "Myshowcase For Profit", planCost: 450.0, planCurrency: "eur", planFrequency: "year", minQuantity: 50, maxQuantity: 500, }, { planId: "myshowcaseProfitGBP", planName: "Government / For-profit", planDescription: "Myshowcase For Profit", planCost: 350.0, planCurrency: "gbp", planFrequency: "year", minQuantity: 50, maxQuantity: 500, }, { planId: "myshowcaseAcademicGBP", planName: "Academic / Charity", planDescription: "Myshowcase Non Profit", planCost: 250.0, planCurrency: "gbp", planFrequency: "year", minQuantity: 50, maxQuantity: 500, }, { planId: "myshowcaseFree", planName: "Free", planDescription: "Myshowcase Free", planCost: 0.0, planCurrency: "gbp", planFrequency: "month", minQuantity: 0, maxQuantity: 5, } ]; $scope.currencyOptions = [ { code: 'gbp', name: 'GBP', symbol: '' }, { code: 'usd', name: 'USD', symbol: '' }, { code: 'eur', name: 'EUR', symbol: '' } ]; var euCountriesCodes = ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'UK']; function isCountryEU(countryCode) { if (countryCode == 'UK') return false; //we can ignore UK for now as this is treated a bit differently since we don't current need VAT registration numbers and such if (euCountriesCodes.indexOf(countryCode) !== -1) return true; else return false; } function getSelectedCurrency(countryCode, isEU) { // we can limit the amount of currencies if the user is in one of the countries we know the currnecy for (e.g uk us or an eu country). // we can then disable the selector on the modal with this value preset. if (countryCode == 'GB') { $scope.currencyOptions = [$scope.originalCurrencyOptions[0]]; } else if (isEU) { $scope.currencyOptions = [$scope.originalCurrencyOptions[2]]; } else { $scope.currencyOptions = [$scope.originalCurrencyOptions[1]]; } return $scope.currencyOptions[0]; } $scope.countryChanged = function () { $scope.setCurrency(); $scope.euVATRequired = isCountryEU($scope.selectedCurrency.code); $scope.currencyChanged(); } $scope.setCurrency = function () { if ($scope.user.countryCode == 'GB') { $scope.selectedCurrency = $scope.currencyOptions[0]; } else if (isCountryEU($scope.user.countryCode)) { $scope.selectedCurrency = $scope.currencyOptions[2]; } else { $scope.selectedCurrency = $scope.currencyOptions[1]; } $scope.currencyChanged(); } $scope.currencyChanged = function () { if ($scope.selectedCurrency) { var accountType; if ($scope.user.accountType == '1') { accountType = 'Academic / Charity' } if ($scope.user.accountType == '0') { accountType = "Government / For-profit"; } $scope.accountOptions = $scope.allAccountOptions.filter(function (item) { return item.planCurrency === $scope.selectedCurrency.code; }); $scope.selectedAccount = $scope.accountOptions.filter(function (item) { return item.planName === accountType; }); console.log($scope.selectedAccount); $scope.checkCost(); if ($scope.selectedCurrency.code === 'usd') { $scope.noVat = true; } else { $scope.noVat = false; } } } $scope.checkCost = function () { if ($scope.selectedAccount) { if ($scope.selectedAccount.length > 0) { var currentUsers = $scope.selectedUsers; $scope.currentCost = (currentUsers * ($scope.selectedAccount[0].planCost * 1.0 / 100)) * 100; if ($scope.currentCost < 100) { $scope.belowMinimum = true; $scope.currentCost = 100; } else { $scope.belowMinimum = false; } } } } if ($scope.emailDomains) $scope.splitEmailDomains = $scope.emailDomains.split(","); $scope.validation = validation.userValidationConfig(); //get the relevant validation logic $scope.doesUsernameExist = function (username) { datacontext.isUsernameAvailable(username).then(function (data) { $scope.showUserExists = data === "false"; }); } $scope.doesEmailExist = function (email) { $scope.emailExists = false; //HTML encode the username so that e.g. '+' is handled correctly var email = encodeURIComponent(email); datacontext.isEmailAvailable(email).then(function (data) { //Decode the email back again email = decodeURIComponent(email); if (data === true) { $scope.emailExists = true; } else { $scope.emailExists = false; } }); } $scope.doesSubDomainExist = function (subDomain) { OrganisationAdminService.doesSubDomainExist(subDomain).then(function (data) { if (data == "Exists") { $scope.showSubDomainExists = true; } else { $scope.showSubDomainExists = false; } }); } $scope.clearOrgError = function () { $scope.showOrgExists = false; //myUsersDataContext.getOrganisations().then(function (data) { // for (var i in data) { // if (data[i].name === orgName) { // $scope.showOrgExists = true; // return true; // } // } // $scope.showOrgExists = false; //}); }; //is the email domain the user is trying to register with valid (e.g. a mmu user cannot register without an mmu address) $scope.isValidEmailDomain = function (email) { if (!$scope.emailDomains || $scope.emailDomains.length === 0) return true; if (!email) return true; if (email.indexOf("@") === -1) return true; if (email) { for (var i = 0; i < $scope.splitEmailDomains.length; i++) { if (email.indexOf($scope.splitEmailDomains[i]) !== -1) return true; } } return false; } $scope.register = function () { //robots tend to complete all form fields - this is a hidden field hence no real user would complete it hence if its complete it must be a robot //this is a good way to do this without impacting users, unlike captcha if ($scope.user.iAmRobot) return; if ($scope.organisationId) $scope.user.organisation = $scope.organisationId; $scope.user.appCode = config.appCode; $scope.user.newOrganisation = true; $scope.registerFailed = false; fsl.show('Registering'); if (config.appCode == 'MSA') { authService.register($scope.user, $scope.showPlans, $scope.selectedAccount[0], $scope.selectedUsers, $scope.currentCost).then(function () { }).catch(function (data, status) { //problem with registration so tell user if (data.data.errorCode === "0" || data.data.errorCode === "2") { if (data.data.errorCode === "0") { $scope.showUserExists = true; } if (data.data.errorCode === "2") { $scope.showOrgExists = true; } } else $scope.registerFailed = true; fsl.hide(); }); } if (config.appCode == 'OB') { console.log($scope); authService.registerOpenBadges($scope.user, $scope.individual, $scope.brandOrganisationId).then(function () { }).catch(function (data, status) { //problem with registration so tell user if (data.data.errorCode === "0" || data.data.errorCode === "2") { if (data.data.errorCode === "0") { $scope.showUserExists = true; } if (data.data.errorCode === "2") { $scope.showOrgExists = true; } } else $scope.registerFailed = true; fsl.hide(); }); } if (config.appCode == 'CUPPA') { authService.registerCuppa($scope.user, false).then(function () { }).catch(function (data, status) { //problem with registration so tell user if (data.data.errorCode === "0" || data.data.errorCode === "2") { if (data.data.errorCode === "0") { $scope.showUserExists = true; } if (data.data.errorCode === "2") { $scope.showOrgExists = true; } } else $scope.registerFailed = true; fsl.hide(); }); } } //paymentsDataContext.getPlans().then(function (data) { // $scope.allAccountOptions = data; //}); } }; }]); app.directive('httpPrefix', function () { return { restrict: 'A', require: 'ngModel', link: function (scope, element, attrs, controller) { function ensureHttpPrefix(value) { // Need to add prefix if we don't have http:// prefix already AND we don't have part of it if (value && !/^(https?):\/\//i.test(value) && 'http://'.indexOf(value) !== 0 && 'https://'.indexOf(value) !== 0) { controller.$setViewValue('http://' + value); controller.$render(); return 'http://' + value; } else return value; } controller.$formatters.push(ensureHttpPrefix); controller.$parsers.splice(0, 0, ensureHttpPrefix); } }; }); app.directive('httpsPrefix', function () { return { restrict: 'A', require: 'ngModel', link: function (scope, element, attrs, controller) { function ensureHttpPrefix(value) { // Need to add prefix if we don't have http:// prefix already AND we don't have part of it if (value && !/^(https?):\/\//i.test(value) && 'http://'.indexOf(value) !== 0 && 'https://'.indexOf(value) !== 0) { controller.$setViewValue('https://' + value); controller.$render(); return 'https://' + value; } else return value; } controller.$formatters.push(ensureHttpPrefix); controller.$parsers.splice(0, 0, ensureHttpPrefix); } }; }); app.directive('isolateForm', [function () { return { restrict: 'A', require: '?form', link: function (scope, elm, attrs, ctrl) { if (!ctrl) { return; } // Do a copy of the controller var ctrlCopy = {}; angular.copy(ctrl, ctrlCopy); // Get the parent of the form var parent = elm.parent().controller('form'); // Remove parent link to the controller parent.$removeControl(ctrl); // Replace form controller with a "isolated form" var isolatedFormCtrl = { $setValidity: function (validationToken, isValid, control) { ctrlCopy.$setValidity(validationToken, isValid, control); parent.$setValidity(validationToken, true, ctrl); }, $setDirty: function () { elm.removeClass('ng-pristine').addClass('ng-dirty'); ctrl.$dirty = true; ctrl.$pristine = false; }, }; angular.extend(ctrl, isolatedFormCtrl); } }; }]); //directive to display and handle social logins app.directive('socialLoginRegister', ['$sce', '$location', '$window', 'config', function ($sce, $location, $window, config) { return { restrict: 'E', transclude: true, templateUrl: "app/register/socialloginregister.html", scope: { register: "@" }, link: function ($scope, element, $attrs) { //define the social logins $scope.loginbuttons = [ { LoginUrl: $sce.trustAsResourceUrl(config.realm + 'Account/ExternalLogin' + '?provider=Facebook&ReturnUrl=' + config.applicationId + '&state=' + $scope.state), CssClass: "facebook", Icon: "facebook", Name: "Facebook" }, { LoginUrl: $sce.trustAsResourceUrl(config.realm + 'Account/ExternalLogin' + '?provider=Google&ReturnUrl=' + config.applicationId + '&state=' + $scope.state), CssClass: "google", Icon: "google", Name: "Google" } ]; //redirect the user to the social login $scope.redirect = function (button) { $window.location.href = button.LoginUrl; } } }; }]); app.directive('userSummaryReport', ['config', '$modal', function (config, $modal) { return { templateUrl: "app/reporting/usersummary.html", scope: { currentFrameworkId: "=", userSummary: "=", truncatedLabels: "=", chartType: "=", summaryOptions: "=", showItems: "=" }, link: function ($scope, element, $attrs) { // Modal to preview user $scope.previewUser = function (userSummary, chartType, truncatedLabels, currentFrameworkId) { $modal.open({ templateUrl: "app/reporting/usersummarymodal.html", controller: previewUserController, size: 'lg', backdrop: 'static', resolve: { userSummary: function () { return userSummary; }, chartType: function () { return chartType; }, truncatedLabels: function () { return truncatedLabels; }, currentFrameworkId: function () { return currentFrameworkId; } } }); } // Controller for previewing badge template var previewUserController = function (common, $scope, $modalInstance, userSummary, chartType, truncatedLabels, currentFrameworkId) { $scope.userSummary = userSummary; $scope.chartType = chartType; $scope.truncatedLabels = truncatedLabels; $scope.currentFrameworkId = currentFrameworkId $scope.summaryOptions = { //pointDot: false, //pointLabelFontSize: 20, scale: { reverse: false, ticks: { beginAtZero: true, fontSize: 0 }, }, }; // close the modal $scope.cancel = function () { $modalInstance.dismiss('cancel'); }; } } }; }]); // Help Search Directive app.directive('helpsearch', ['helpCentreSearch', 'config', function (helpCentreSearch, config) { return { restrict: 'EA', scope: { helpquery: '@' }, templateUrl: 'app/help/helpsearch.html', link: function ($scope, element, $attrs) { $scope.videoName = 'Adding stuff to Myshowcase.me'; $scope.settingsUrl = helpCentreSearch.settings.umbracoUrl; $scope.settingsUserType = helpCentreSearch.settings.userType; $scope.settingsArticleId = helpCentreSearch.settings.articleId; $scope.settingsProduct = config.productName; $scope.settingsVersion = config.productVersion; $scope.settingsShowResults = helpCentreSearch.settings.showResults; var timeTaken; $scope.search = function (query) { var d = new Date(); $scope.timeSearchTookStart = d.getTime(); helpCentreSearch.search(query, timeTaken).then(function (results, timeTaken) { $scope.results = results; $scope.currentArticle = $scope.results[0]; $scope.selectedIndex = 0; $scope.currentQuery = query; if (query.userType === 'form-collection') $scope.currentQuery = 'Forms'; if (query.userType === 'org-collection') $scope.currentQuery = 'Organisations'; if (query.userType === 'group-collection') $scope.currentQuery = 'Groups'; if (query.userType === 'reporting-collection') $scope.currentQuery = 'Reporting'; $scope.isBodyOpen = false; $scope.setResult = function (index) { $scope.currentArticle = $scope.results[index]; $scope.selectedIndex = index; } var d = new Date(); $scope.timeSearchTookEnd = d.getTime(); $scope.timeSearchTookEnd = $scope.timeSearchTookEnd - $scope.timeSearchTookStart }); }; $scope.resetResults = function (results) { $scope.results = null; }; $scope.changeSettings = function () { helpCentreSearch.settings.umbracoUrl = $scope.settingsUrl; helpCentreSearch.settings.userType = $scope.settingsUserType; helpCentreSearch.settings.articleId = $scope.settingsArticleId; helpCentreSearch.settings.product = product; helpCentreSearch.settings.version = version; helpCentreSearch.settings.showResults = $scope.settingsShowResults; } } }; }]); app.directive('hoverPopover', function ($compile, $templateCache, $timeout, $rootScope) { return { restrict: 'A', link: function (scope, element, attrs) { scope.template = attrs.template; scope.getTemplate = function (contentType) { return $templateCache.get(scope.template); }; $rootScope.insidePopover = false; scope.content = scope.getTemplate(); scope.content = $compile(scope.content)(scope); var removed = false; $(element).popover({ content: scope.content, title: null, container: 'body', placement: 'right', trigger: 'manual', html: true }); $(element).bind('mouseenter', function (e) { scope.content = scope.getTemplate(); scope.content = $compile(scope.content)(scope); $(element).popover({ content: scope.content, title: null, container: 'body', placement: 'right', trigger: 'manual', html: true }); $(element).popover('show'); scope.attachEvents(element); }); $(element).bind('mouseleave', function (e) { $timeout(function () { if (!$rootScope.insidePopover) { $('.popover').remove(); removed = true; $templateCache.remove(scope.content) } }, 1); }); }, controller: function ($scope, $element) { $scope.attachEvents = function (element) { $('.popover').on('mouseenter', function () { $rootScope.insidePopover = true; }); $('.popover').on('mouseleave', function () { $rootScope.insidePopover = false; $('.popover').remove(); }); } } }; }); app.directive('onlyAlphabets', function () { return { restrict: 'A', require: '?ngModel', link: function (scope, element, attrs, ngModel) { if (!ngModel) { return; } ngModel.$parsers.unshift(function (inputValue) { var alphabets = inputValue.split('').filter(function (s) { return (isALetter(s)); }).join(''); ngModel.$viewValue = alphabets; ngModel.$render(); return alphabets; }); } }; function isALetter(charVal) { if (charVal.toUpperCase() != charVal.toLowerCase()) { return true; } else { return false; } } }); //directive to display a users avatar app.directive('userAvatarDisplay', ['$sce', function ($sc) { return { restrict: 'E', transclude: true, templateUrl: "app/templates/avatar.html", scope: { size: "=", url: "=", online: "=", center: '=', userId: '=', disableLink: '=', }, link: function (scope, element, $attrs) { } }; }]); app.directive('restrictField', function () { return { restrict: 'AE', scope: { restrictField: '=' }, link: function (scope) { // this will match spaces, tabs, line feeds etc // you can change this regex as you want var regex = /\s/g; scope.$watch('restrictField', function (newValue, oldValue) { if (newValue != oldValue && regex.test(newValue)) { scope.restrictField = newValue.replace(regex, ''); } }); } }; }); app.directive('restrictSpecialCharacters', function () { function link(scope, elem, attrs, ngModel) { ngModel.$parsers.push(function (viewValue) { var reg = /^[a-zA-Z0-9+-]*$/; if (viewValue.match(reg)) { return viewValue; } var transformedValue = ngModel.$modelValue; ngModel.$setViewValue(transformedValue); ngModel.$render(); return transformedValue; }); } return { restrict: 'A', require: 'ngModel', link: link }; }); app.directive('removeTags', function () { return { restrict: 'AE', scope: { removeTags: '=' }, link: function (scope) { if (scope.removeTags == null) scope.removeTags = ''; scope.$watch('removeTags', function (newValue, oldValue) { scope.removeTags = String(scope.removeTags).replace(//gm, ''); }); } }; }); app.directive('mapTooltip', function () { return { restrict: 'A', link: function (scope, element, attrs) { $(element).hover(function () { // on mouseenter $(element).tooltip('show'); }, function () { // on mouseleave $(element).tooltip('hide'); }); } }; }); app.filter('Filesize', function () { return function (size) { if (isNaN(size)) size = 0; if (size < 1024) return size + ' Bytes'; size /= 1024; if (size < 1024) return size.toFixed(2) + ' Kb'; size /= 1024; if (size < 1024) return size.toFixed(2) + ' Mb'; size /= 1024; if (size < 1024) return size.toFixed(2) + ' Gb'; size /= 1024; return size.toFixed(2) + ' Tb'; }; }); app.directive("dropzone", function () { return { restrict: "A", scope: { addFiles: '=' }, link: function (scope, elem) { elem.bind('drop', function (evt) { evt.stopPropagation(); evt.preventDefault(); var files = evt.originalEvent.dataTransfer.files; scope.addFiles(files); }); elem.bind('dragenter', function (e) { e.stopPropagation(); e.preventDefault(); elem.addClass('dragover'); }); elem.bind('dragleave', function (e) { e.stopPropagation(); e.preventDefault(); elem.removeClass('dragover'); }); } } }); app.directive('numericbinding', function () { return { restrict: 'A', require: 'ngModel', scope: { model: '=ngModel', }, link: function (scope, element, attrs, ngModelCtrl) { if (scope.model && typeof scope.model == 'string') { scope.model = parseInt(scope.model); } } }; }); app.directive('noNewLines', function () { return { restrict: 'A', require: 'ngModel', link: function (scope, element, attributes, ngModelController) { var model = attributes.ngModel; var regex = new RegExp("^[^\n\r]*$"); // $parsers handle input from the element where the // ng-model directive is set ngModelController.$parsers.unshift(function (value) { if (!value) return value; var modelValue = ngModelController.$modelValue; var isValid = regex.test(value); ngModelController.$setValidity('Does not match pattern', isValid); var transformedInput = value.replace(/[\n\r]/g, ''); if (transformedInput !== value) { ngModelController.$setViewValue(transformedInput); ngModelController.$render(); } return transformedInput; }); // $formatters handle when the model is changed and // the element needs to be updated ngModelController.$formatters.unshift(function (value) { if (!value) return value; var isValid = regex.test(value); ngModelController.$setValidity('Does not match pattern', isValid); return value; }); element.on('keypress', function (e) { var char = String.fromCharCode(e.which); var text = angular.element(e.srcElement).val(); if (!regex.test(char) || !regex.test(text)) { event.preventDefault(); } }); } }; }); app.directive('noExclamationMark', function () { return { require: 'ngModel', restrict: 'A', link: function (scope, element, attrs, modelCtrl) { modelCtrl.$parsers.push(function (inputValue) { if (inputValue == null) return '' var cleanInputValue = inputValue.replace(/\!/g, '') if (cleanInputValue != inputValue) { modelCtrl.$setViewValue(cleanInputValue); modelCtrl.$render(); } return cleanInputValue; }); } } }); app.directive('dirDisqus', ['$window', function ($window) { return { restrict: 'E', scope: { config: '=' }, template: '
', link: function (scope) { scope.$watch('config', configChanged, true); function configChanged() { // Ensure that the disqus_identifier and disqus_url are both set, otherwise we will run in to identifier conflicts when using URLs with "#" in them // see http://help.disqus.com/customer/portal/articles/662547-why-are-the-same-comments-showing-up-on-multiple-pages- if (!scope.config.disqus_shortname || !scope.config.disqus_identifier || !scope.config.disqus_url) { return; } $window.disqus_shortname = scope.config.disqus_shortname; $window.disqus_identifier = scope.config.disqus_identifier; $window.disqus_url = scope.config.disqus_url; $window.disqus_title = scope.config.disqus_title; $window.disqus_category_id = scope.config.disqus_category_id; $window.disqus_disable_mobile = scope.config.disqus_disable_mobile; $window.disqus_config = function () { this.language = scope.config.disqus_config_language; this.page.remote_auth_s3 = scope.config.disqus_remote_auth_s3; this.page.api_key = scope.config.disqus_api_key; if (scope.config.disqus_on_ready) { this.callbacks.onReady = [function () { scope.config.disqus_on_ready(); }]; } }; // Get the remote Disqus script and insert it into the DOM, but only if it not already loaded (as that will cause warnings) if (!$window.DISQUS) { var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; dsq.src = '//' + scope.config.disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); } else { $window.DISQUS.reset({ reload: true, config: function () { this.page.identifier = scope.config.disqus_identifier; this.page.url = scope.config.disqus_url; this.page.title = scope.config.disqus_title; this.language = scope.config.disqus_config_language; this.page.remote_auth_s3 = scope.config.disqus_remote_auth_s3; this.page.api_key = scope.config.disqus_api_key; } }); } } } }; }]); app.directive('colorContrast', function () { var DARK = '000000'; var LIGHT = 'FFFFFF'; function getContrastYIQ(hexcolor) { var isOk = /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(hexcolor); if (!isOk) { return DARK; } var r = parseInt(hexcolor.substr(0, 2), 16); var g = parseInt(hexcolor.substr(2, 2), 16); var b = parseInt(hexcolor.substr(4, 2), 16); var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; return (yiq >= 128) ? DARK : LIGHT; }; function stripNumberSign(color) { if (color[0] === "#") { color = color.substring(1, color.length); } return color; }; return { restrict: 'A', link: function postLink(scope, element, attrs) { attrs.$observe('colorContrast', function (color) { if (color) { color = stripNumberSign(color); //element.css("background-color", "#" + color); element.css("color", "#" + getContrastYIQ(color)); } }); } }; }); app.directive('popoverClose', function ($timeout) { return { scope: { excludeClass: '@' }, link: function (scope, element, attrs) { element.on('click', function (event) { console.log(event) if (angular.element(".popover").hasClass('in')) angular.element(".popover").remove(); }); } }; }); app.directive('mySrc', function () { return { restrict: 'A', scope: { mySrc: '@' }, link: function (scope, iElement, iAttrs) { scope.$watch('mySrc', function () { var iFrame = iElement; if (!(iFrame && iFrame.length > 0)) { iFrame = $(''); iElement.append(iFrame); } iFrame.attr("src", scope.mySrc); }); } }; }); app.directive('ngIframe', ['$compile', function ($compile) { return { restrict: 'E', template: ` `, scope: { iframeTemplate: '=', iframeContext: '=' }, link: function ($scope, $element, $attrs) { let setScope = () => { angular.forEach($scope.iframeContext, (value, key) => { $scope[key] = value; }); setContextWatchers(); }; let render = () => { $compile($element .find('iframe').contents() .find('body').html($scope.iframeTemplate) .contents() )($scope); }; let setContextWatchers = () => { angular.forEach($scope.iframeContext, (value, key) => { $scope.$watch( ($scope) => { return $scope.iframeContext[key]; }, () => { $scope[key] = $scope.iframeContext[key]; }); }); }; $scope.$watch('iframeTemplate', () => { setScope(); render('template'); }); } } } ]); })();