(function () { 'use strict'; var app = angular.module('flexibleTemplate'); var templatePath = modulesSharedResourcesUrl + 'Modules/FlexibleTemplate/Views/'; app.directive('onFinishRender', function ($timeout) { return { restrict: 'A', link: function (scope, element, attr) { if (scope.$last === true) { $timeout(function () { scope.$emit('ngRepeatFinished'); }); } } } }); app.directive("sizeWatcher", ['$timeout', function ($timeout) { return { scope: { sizeWatcherHeight: '=', sizeWatcherWidth: '=', }, link: function( scope, elem, attrs ){ function checkSize(){ scope.sizeWatcherHeight = elem.prop('offsetHeight'); scope.sizeWatcherWidth = elem.prop('clientWidth'); $timeout( checkSize, 1000 ); } checkSize(); } }; }]); //a directive that renders a flexible template app.directive('flexibleTemplate', ['flexibleTemplateDataContext', '$window', 'user', function (dataContext, $window, user) { return { restrict: 'E', scope: { maxCols: '=', margin: '=', disabled: '=', items: '=', showcaseId: '=', backgroundColour: '=', headerTextColour: '=', highlightColour: '=', backgroundUrl: '=', backgroundPattern: '=', backgroundBlur: '=', includeAvatar: '=', themeHeader: '=', themeMode: '=', avatarUrl: '=', hasChanged:'=', userId:'=' }, templateUrl: templatePath + 'flexibletemplaterenderer.html?version=160718', link: link }; function link(scope, $rootScope, elem, attrs) { scope.leftAlign = 'text-align:left'; scope.bold = 'font-weight:bold'; scope.normal = 'font-weight:normal'; scope.underline = 'text-decoration:underline'; scope.underline = 'font-style:italic;'; scope.centerAlign = 'text-align:center'; scope.rightAlign = 'text-align:right'; scope.displayNone = 'display:none !important'; scope.display = 'display:block !important'; scope.textSizes = [ { size: '8px' }, { size: '9px' }, { size: '10px' }, { size: '12px' }, { size: '14px' }, { size: '16px' }, { size: '18px' }, { size: '20px' }, { size: '22px' }, { size: '24px' }, { size: '26px' }, { size: '28px' }, { size: '32px' }, { size: '36px' }, { size: '42px' }, { size: '50px' }, { size: '60px' }, { size: '72px' } ]; scope.availableFonts = [ { font: 'Amatic SC' }, { font: 'Courier New' }, { font: 'Impact' }, { font: 'Lobster' }, { font: 'Onyx' }, { font: 'Open Sans' }, { font: 'Open Sans Condensed' }, { font: 'Pacifico' }, { font: 'Roboto' }, { font: 'Roboto Condensed' }, { font: 'Roboto Slab' }, { font: 'Rockwell' }, { font: 'Shadows Into Light' }, { font: 'Source Sans Pro' }, { font: 'Stencil' }, { font: 'Times New Roman' }, { font: 'Trebuchet MS' }, { font: 'Verdana' }, ]; scope.borderRadius = [ { radius: '0px' }, { radius: '1px' }, { radius: '2px' }, { radius: '3px' }, { radius: '4px' }, { radius: '5px' }, { radius: '8px' }, { radius: '12px' }, { radius: '20px' }, { radius: '500px' }, { radius: '1000px' } ]; scope.borderWidth = [ { radius: '0px' }, { radius: '1px' }, { radius: '2px' }, { radius: '3px' }, { radius: '4px' }, { radius: '5px' }, { radius: '8px' }, { radius: '12px' }, { radius: '20px' }, ]; scope.stylesSet = false; scope.$watch("userId", function (userId){ user.getUploadBucketSasForUser(userId).then(function (sas) { scope.sasToken = sas; }); }); scope.$watch('items', function (items, oldvalue) { if (items) { dataContext.getPreviewShowcase(scope.showcaseId).then(function (theShowcase) { // Detect if a new item hase been added var newItemCount = 0; var newItemPos = 0; for (var i = 0, il = theShowcase.items.length; i < il; i++) { if (theShowcase.items[i].type == 'image' ) { theShowcase.items[i].bluredUrl = theShowcase.items[i].url; theShowcase.items[i].bluredUrl = theShowcase.items[i].bluredUrl.replace('upload', 'upload/e_blur:5000/'); } if (theShowcase.items[i].showcaseItemDisplayProperties.showDate == 'False') { theShowcase.items[i].showcaseItemDisplayProperties.showDate = false; } else { theShowcase.items[i].showcaseItemDisplayProperties.showDate = true; } if (theShowcase.items[i].showcaseItemDisplayProperties.sizeY === '0' && theShowcase.items[i].showcaseItemDisplayProperties.sizeX === '0') { newItemCount = newItemCount + 1; newItemPos = newItemPos + 1; if (newItemCount > 0) theShowcase.items[i].showcaseItemDisplayProperties.row = 300; newItemCount = 0; if (newItemPos % 2 === 0) { theShowcase.items[i].showcaseItemDisplayProperties.col = 7; } else { theShowcase.items[i].showcaseItemDisplayProperties.col = 1; } theShowcase.items[i].showcaseItemDisplayProperties.sizeX = 6; theShowcase.items[i].showcaseItemDisplayProperties.sizeY = 6; } } for (i in theShowcase.items) { if (theShowcase.items[i].type == 'badgecollection') { if (theShowcase.items[i].jsonData.length < 3) { theShowcase.items[i].doesNotExist = true; } var parsed = JSON.parse(theShowcase.items[i].jsonData); if (!parsed.public && theShowcase.items[i].jsonData.length > 3) { theShowcase.items[i].isPrivate = true; } theShowcase.items[i].displayOptions = parsed.advancedCollectionDisplay; theShowcase.items[i].collectionName = parsed.name; //vm.data.items[i].mybadgesCollectionId = parsed.id; theShowcase.items[i].collectionDescription = parsed.description; theShowcase.items[i].backpackCollectionItems = parsed.backpackCollectionItems; } if (theShowcase.items[i].type === "Myprogress assessment") { theShowcase.items[i].jsonResponse = parseResponse(theShowcase.items[i].jsonResponse); } } scope.showcase = theShowcase; scope.showcase.themeHeader = scope.showcase.themeHeader; scope.avatarUrl = scope.avatarUrl; setDisplayPropertiesInitial(scope.showcase, scope.items); scope.setStyleDisplayProperties('', '', scope.items, 'reset'); scope.setStyleDisplayProperties(theShowcase.items[0].itemId, '', scope.items, '') }); scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) { var serializedPos; // launch gridster if (scope.themeMode === 'noMargin') scope.margin = 0; var gridster = $(".gridster ul").gridster({ widget_base_dimensions: [82, 45], widget_margins: [scope.margin, scope.margin], autogrow_cols: false, max_cols: scope.maxCols, min_cols: scope.maxCols, serialize_params: function ($w, wgd) { return { id: $($w).attr('id'), col: wgd.col, row: wgd.row, size_x: wgd.size_x, size_y: wgd.size_y }; }, resize: { enabled: true, stop: function (e, ui, $widget) { serializedPos = gridster.serialize(); setDisplayProperties(scope.items, serializedPos); scope.hasChanged = true; scope.blockStyleMenu = false; scope.globalStyleMenu = false; if (!scope.$$phase) scope.$apply(); } }, draggable: { stop: function (e, ui, $widget) { serializedPos = gridster.serialize(); setDisplayProperties(scope.items, serializedPos); scope.hasChanged = true; scope.blockStyleMenu = false; scope.globalStyleMenu = false; if (!scope.$$phase) scope.$apply(); } } }).data('gridster'); // Get all item's current positions var serializedPosInitial = gridster.serialize(); setPosPropertiesInitial(scope.items, serializedPosInitial); }); } }); // Returns either white or black depending on the color provided scope.invertColor = function (hexcolor) { return (parseInt(hexcolor, 16) > 0xffffff / 2) ? 'black' : 'white'; } //Set header template scope.setHeaderType = function () { scope.hasChanged = true; scope.showcase.themeHeader = scope.themeHeader; } // Set theme mode scope.setThemeMode = function (fontStyle) { scope.hasChanged = true; scope.showcase.themeMode = fontStyle; scope.themeMode = fontStyle; } scope.updateAvatar = function () { scope.hasChanged = true; scope.includeAvatar = scope.showcase.includeAvatar; } scope.setCustomStyle = function (itemId, styleValue, url, hasChanged) { scope.hasChanged = hasChanged; var url = 'background-image:url(' + url + ')' +';'; for (var i = 0, il = scope.showcase.items.length; i'); element.replaceWith(template(scope)); } } }; }]); app.directive('colorPicker', function () { return { restrict: 'E', templateUrl: 'colorPicker.html' }; }); app.directive('colorPickerGlobal', function () { return { restrict: 'E', templateUrl: 'colorPickerGlobal.html' }; }); // Include the custom styles using a directive app.directive('flexibleTemplateStyles', function () { return { restrict: 'E', templateUrl: '/viewshowcase/css/flexible-template-styles.css?' }; }); app.filter('unsafe', function ($sce) { return function (val) { return $sce.trustAsHtml(val); }; }); // Include the custom styles using a directive app.directive('showcaseStyles', function () { return { restrict: 'E', templateUrl: 'styles.html' }; }); // Include the showcase header using a directive app.directive('showcaseHeaderCenter', function () { return { restrict: 'E', templateUrl: 'headerCenter.html' }; }); app.directive('showcaseHeader', function () { return { restrict: 'E', templateUrl: 'header.html' }; }); app.directive('showcaseHeaderClean', function () { return { restrict: 'E', templateUrl: 'headerClean.html' }; }); app.directive('showcaseHeaderSideBar', function () { return { restrict: 'E', templateUrl: 'header-side-bar.html' }; }); // Include the author information using a directive app.directive('showcaseAuthor', function () { return { restrict: 'E', templateUrl: 'author.html' }; }); // Include the item type templates // Headings app.directive('showcaseItemHeading', function () { return { restrict: 'E', templateUrl: 'heading.html' }; }); // Showcase text blocks app.directive('showcaseItemShowcasetext', function () { return { restrict: 'E', templateUrl: 'text.html' }; }); // embed app.directive('showcaseItemEmbed', function () { return { restrict: 'E', templateUrl: 'embed.html' }; }); //prezi app.directive('showcaseItemPrezi', function () { return { restrict: 'E', templateUrl: 'embedprezi.html' }; }); //Evernote app.directive('showcaseItemEvernote', function () { return { restrict: 'E', templateUrl: 'evernote.html' }; }); // Rich text / HTML block app.directive('showcaseItemStatus', function () { return { restrict: 'E', templateUrl: 'status.html' }; }); // Uploaded file app.directive('showcaseItemFile', function () { return { restrict: 'E', templateUrl: 'file.html' }; }); // Uploaded image app.directive('showcaseItemImage', function () { return { restrict: 'E', templateUrl: 'image.html' }; }); // Uploaded video app.directive('showcaseItemVideo', function () { return { restrict: 'E', templateUrl: 'video.html', link: function (scope, elm, attr) { scope.cloudinaryVideoBaseUrl = cloudinaryVideoBaseUrl; } }; }); // Uploaded badge app.directive('showcaseItemBadge', function () { return { restrict: 'E', templateUrl: 'badge.html' }; }); app.directive('showcaseItemForm', function () { return { restrict: 'E', templateUrl: 'form.html' }; }); // Added badge collection app.directive('showcaseItemBadgeCollection', function () { return { restrict: 'E', templateUrl: 'badge-collection.html' }; }); app.directive('formStyles', function () { return { restrict: 'E', templateUrl: '/modules/MyFormsCompleted/views/styles.html' }; }); // Uploaded weblink app.directive('showcaseItemWeblink', ['flexibleTemplateConfig', function (config) { return { restrict: 'E', templateUrl: 'weblink.html', link: link }; function link(scope, element, attrs) { scope.baseWebLinkImageUrl = config.baseWebLinkImageUrl; } }]); // MyProgress Assessment items app.directive('showcaseItemAssessment', function () { return { restrict: 'E', templateUrl: 'assessment2.html', scope: { myShowcaseItem: '=item', accessToken: '=' }, link: function ($scope, element, attrs) { $scope.getLetter = function (index) { if (0 <= index && index <= 25) { return String.fromCharCode(65 + index); } else if (26 <= index <= 51) { return String.fromCharCode(71 + index); } else { return ''; } } $scope.getAssessmentItemResultFromCustomText = function (customText) { var assessmentItemIdentifier = $scope.getAssessmentItemIdentifier(customText); if (assessmentItemIdentifier.length > 0) { var result = $scope.getAssessmentItemResult(assessmentItemIdentifier); return result; } return null; } $scope.getAssessmentItemResult = function (assessmentItemIdentifier) { var resultArray = $scope.myShowcaseItem.jsonResponse.Result.itemResults.filter(function (assessmentItemResult) { return assessmentItemResult.identifier === assessmentItemIdentifier; }) if (resultArray.length > 0) { return resultArray[0]; } else { return null; } } $scope.getAssessmentItemIdentifier = function (customText) { var identifierString = 'identifier:'; if (customText && customText.length > 0 && customText.indexOf(identifierString) > -1) { var startIndex = customText.indexOf(identifierString) + identifierString.length; return customText.substring(startIndex); } return ''; } $scope.isAssessmentItemHidden = function (customText) { if (customText && customText.length > 0) { for (var i = 0; i < $scope.myShowcaseItem.jsonResponse.HiddenAssessmentItemIdentifiers.length; i++) { if (customText.includes($scope.myShowcaseItem.jsonResponse.HiddenAssessmentItemIdentifiers[i])) { return true; } } } return false; } } }; }); app.directive('myprogressAssessmentItem', function ($http) { return { restrict: 'E', templateUrl: 'assessmentResponseItem.html', scope: { myShowcaseItem: '=', assessmentItem: '=', itemResult: '=', accessToken: '=' }, link: function ($scope, element, attrs) { $scope.getSelectedInteractionOptions = function (assessmentItemResult, responseIdentifier) { if (assessmentItemResult) { var responseValues = assessmentItemResult.responseValues.filter(function (responseValue) { return responseValue.identifier === responseIdentifier; }) if (responseValues.length > 0) { return responseValues[0].values; } else { return null; } } else { return null; } } $scope.getSingleResponseValue = function (assessmentItemResult, responseIdentifier) { if (assessmentItemResult && responseIdentifier) { var responseValues = assessmentItemResult.responseValues.filter(function (responseValue) { return responseValue.identifier === responseIdentifier; }) if (responseValues && responseValues.length > 0) { var responseValueArray = responseValues[0].values; if (responseValueArray && responseValueArray.length > 0) { return responseValueArray[0]; } else { return null; } } else { return null; } } else { return null; } } $scope.isInCorrectValues = function (responseValue, correctValues, correctValue, correctDate, correctTime, dateFormat) { return responseValue && responseValue.length && (correctValues && correctValues.length > 0 && correctValues.includes(responseValue)) || (correctValue && correctValue.length > 0 && correctValue == responseValue) || (correctDate && correctDate.length > 0 && $scope.compareDateStrings(correctDate, responseValue, dateFormat)) || (correctTime && correctTime.length > 0 && $scope.compareTimeStrings(correctTime, responseValue)); } $scope.compareTimeStrings = function (time1, time2) { var t1 = time1.split(':'); var t2 = time2.split(':'); var h1 = parseInt(t1[0]); var h2 = parseInt(t2[0]); var m1 = parseInt(t1[1]); var m2 = parseInt(t2[1]); return (h1 == h2 && m1 == m2); } $scope.compareDateStrings = function (correctDate, responseDate, dateFormat) { var dateCorrect = new Date(correctDate); var dayCorrect = dateCorrect.getDate(); var monthCorrect = (dateCorrect.getMonth() + 1).toString(); if (monthCorrect.length == 1) { monthCorrect = '0' + monthCorrect; } var yearCorrect = dateCorrect.getFullYear().toString(); var stringCorrect = ''; if (dateFormat == 'DATE') { stringCorrect = dayCorrect + '/' + monthCorrect + '/' + yearCorrect; } else { var hoursCorrect = dateCorrect.getHours().toString(); var minutesCorrect = dateCorrect.getMinutes().toString(); if (hoursCorrect.length == 1) { hoursCorrect = '0' + hoursCorrect; } if (minutesCorrect.length == '1') { minutesCorrect = '0' + minutesCorrect; } stringCorrect = dayCorrect + '/' + monthCorrect + '/' + yearCorrect + ' ' + hoursCorrect + ':' + minutesCorrect; } return stringCorrect == responseDate } } }; }); app.directive('myprogressInteractionChoice', function () { return { restrict: 'E', templateUrl: 'assessmentResponseChoice.html', scope: { simpleChoice: '=', selectedValues: '=', correctValues: '=' }, link: function ($scope, element, attrs) { $scope.isSelected = function () { return $scope.selectedValues && $scope.selectedValues.length > 0 && $scope.selectedValues.includes($scope.simpleChoice.Identifier); } $scope.isCorrect = function () { return $scope.correctValues && $scope.correctValues.length > 0 && $scope.correctValues.includes($scope.simpleChoice.Identifier); } $scope.isIncorrect = function () { //value is incorrect only if there are defined correct values return $scope.correctValues && $scope.correctValues.length > 0 && !$scope.correctValues.includes($scope.simpleChoice.Identifier); } } }; }); app.directive('myProgressInteractionGrid', function () { return { restrict: 'E', templateUrl: 'assessmentResponseGrid.html', scope: { sourceItems: '=', targetItems: '=', selectedValues: '=' }, link: function ($scope, element, attrs) { $scope.isSelected = function (sourceId, targetId) { return $scope.selectedValues && $scope.selectedValues.length > 0 && $scope.selectedValues.includes(sourceId + ' ' + targetId); } } } }); app.directive('myProgressInteractionFile', ['$http', '$timeout', function ($http, $timeout) { return { restrict: 'E', templateUrl: 'assessmentResponseFile.html', scope: { myShowcaseItemId: '=', streamedResourceData: '=', responseString: '=', accessToken: '=' }, link: function ($scope, element, attrs) { function fileNameFromResponse() { if ($scope.responseString && $scope.responseString.indexOf(',') > 0) { return $scope.responseString.substring($scope.responseString.indexOf(',') + 1) } else { return ''; } } function fileGuidFromResponse() { if ($scope.responseString && $scope.responseString.indexOf(',') > 0) { return $scope.responseString.substring(0, $scope.responseString.indexOf(',')) } else { return ''; } } $scope.fileName = fileNameFromResponse(); $scope.fileGuid = fileGuidFromResponse(); //&userid=9F33C4E1-7A70-47B4-9C1C-A46A40B67D8D function fileDownloadUrl() { if ($scope.fileGuid && $scope.fileGuid.length > 0 && $scope.fileName && $scope.fileName.length > 0) { return '/api/myitem/' + $scope.myShowcaseItemId + '/zipcontents?name=' + $scope.fileGuid + '&originalName=' + $scope.fileName; } return ''; } function resourceIsImage() { if ($scope.streamedResourceData) { var isImage = false; for (var i = 0; i < $scope.streamedResourceData.length; i++) { if ($scope.streamedResourceData[i].ResourceId == $scope.fileGuid) { isImage = ($scope.streamedResourceData[i].Type.toLowerCase().indexOf('image') >= 0); break; } } return isImage; } } function getResourceType() { if ($scope.streamedResourceData) { var rType = ''; for (var i = 0; i < $scope.streamedResourceData.length; i++) { if ($scope.streamedResourceData[i].ResourceId == $scope.fileGuid) { rType = $scope.streamedResourceData[i].Type; break; } } return rType; } } $scope.fileUrl = fileDownloadUrl(); $scope.isImage = resourceIsImage(); $scope.resourceType = getResourceType(); //$scope.downloadFile = function (event) { // //var maxSizeForBase64 = 1048576; //1024 * 1024 // if ($scope.responseString) { // var anchor = angular.element(''); //angular.element(event.currentTarget); // //only get data again if base64Url hasn't been generated // if (!$scope.base64Url || $scope.base64Url.length == 0) { // var request = $http({ // method: "get", // url: $scope.fileUrl, // headers: { // Authorization: 'Bearer ' + $scope.accessToken // }, // responseType: 'arraybuffer' // }); // return (request.then(function (response) { // var str = response.data; // var windowUrl = window.URL || window.webkitURL; // if (typeof windowUrl.createObjectURL === 'function') { // var blob = new Blob([response.data], { type: $scope.resourceType }); // var url = window.URL.createObjectURL(blob); // //anchor.prop('href', url); // //anchor.prop('download', $scope.fileName); // anchor.attr({ // href: url, // download: $scope.fileName, // }); // anchor.get(0).click(); // windowUrl.revokeObjectURL(url); // } // else { // //use base64 encoding when less than set limit or file API is not available // anchor.attr({ // href: $scope.base64Url, // download: $scope.fileName, // }); // anchor.get(0).click(); // } // }, $scope.handleError)); // } // else { // //anchor.attr({ // // href: $scope.base64Url, // // download: $scope.fileName, // //}); // anchor.prop('href', $scope.base64Url); // anchor.prop('download', $scope.fileName); // //$timeout(function () { // anchor.get(0).click(); // //}, 0, false); // } // } //} function getResourceAsBase64Url() { var maxSizeForBase64 = 3000050; //4Gb max data url for IE - 50 bytes for metadata var url = $scope.fileUrl; var request = $http({ method: "get", url: url, headers: { Authorization: 'Bearer ' + $scope.accessToken }, responseType: 'arraybuffer' }); return (request.then(function (response) { var arrayBuffer = response.data; if (arrayBuffer) { var u8 = new Uint8Array(arrayBuffer); if (u8.length <= maxSizeForBase64) { var len = u8.byteLength; var binary = ''; for (var i = 0; i < len; i++) { binary += String.fromCharCode(u8[i]); } var b64encoded = window.btoa(binary); var mimetype = $scope.resourceType; return "data:" + mimetype + ";base64," + b64encoded; } else { return ''; } } else { return ''; } }, $scope.handleError)); } $scope.handleError = function (response) { console.log(response); } $scope.handleSuccess = function (response) { return (response.data); } function downloadFileUrl() { //var maxSizeForBase64 = 1048576; //1024 * 1024 //use dataurl if it exists - only get data again if base64Url hasn't been generated //if (!$scope.base64Url || $scope.base64Url.length == 0) { var request = $http({ method: "get", url: $scope.fileUrl, headers: { Authorization: 'Bearer ' + $scope.accessToken }, responseType: 'arraybuffer' }); return (request.then(function (response) { var str = response.data; var windowUrl = window.URL || window.webkitURL; if (typeof windowUrl.createObjectURL === 'function') { var blob = new Blob([str], { type: $scope.resourceType }); var url = windowUrl.createObjectURL(blob); return url; } else { return ''; } }, $scope.handleError)); //} //else { // return new Promise(function(resolve, reject) { // return resolve($scope.base64Url); // //return reject('error'); // }) //} } //getResourceAsBase64Url().then(function (response) { // $scope.base64Url = response; // downloadFileUrl().then(function (response) { // $scope.downloadFileLocation = response; // }) //}) downloadFileUrl().then(function (response) { $scope.downloadFileLocation = response; }) $scope.useIEDownload = window.navigator.msSaveOrOpenBlob; $scope.doIEDownload = function () { var request = $http({ method: "get", url: $scope.fileUrl, headers: { Authorization: 'Bearer ' + $scope.accessToken }, responseType: 'arraybuffer' }); return (request.then(function (response) { var str = response.data; var windowUrl = window.URL || window.webkitURL; if (typeof windowUrl.createObjectURL === 'function') { var blob = new Blob([str], { type: $scope.resourceType }); window.navigator.msSaveOrOpenBlob(blob, $scope.fileName); } else { return ''; } }, $scope.handleError)); } } } }]); app.filter('dateOrTime', function () { return function (input, responseType) { if (input && responseType === "date") { var parts = input.split(" "); if (parts.length > 0) { return parts[0]; } else { return input; } } else if (input && responseType === "time") { var parts = input.split(" "); if (parts.length > 1) { return parts[1]; } else { return input; } } else { //default is to handle as for responseType === "datetime", i.e. return unmodified return input; } } }); app.directive('colorContrast', function () { var DARK = '000000'; var LIGHT = 'FFFFFF'; function getContrastYIQ(hexcolor) { hexcolor = hexcolor.trim(); 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)); } }); } }; }); })();