(function() { 'use strict'; angular.module('view.file', [ 'view.file.tpls', 'cb.x2js', 'com.2fdevs.videogular', 'com.2fdevs.videogular.plugins.controls', 'hljs', 'ngJsonExplorer', 'ngSanitize', 'RecursionHelper' ]); }()); (function () { 'use strict'; angular.module('view.file') .controller('FriendlyJsonCtrl', FriendlyJsonCtrl); FriendlyJsonCtrl.$inject = ['$scope', '$sce', '$templateCache', '$http']; function FriendlyJsonCtrl($scope, $sce, $templateCache, $http) { var ctrl = this; ctrl.trustUri = function(uri) { $sce.trustAsResourceUrl(uri); }; ctrl.load = function(uri) { var json = $templateCache.get(uri); if (!json) { $http.get(uri, { cache: $templateCache, transformResponse: function(data, headersGetter) { // Return the raw string, so $http doesn't parse it // if it's json. return data; } }).then(function (response) { $scope.loading = false; $scope.json = JSON.parse(response.data); }); } else if (angular.isArray(json)) { $scope.loading = false; $scope.json = JSON.parse(json[1]); } else { json.then(function(response) { $scope.json = JSON.parse(response.data); }); } }; } }()); /** * @ngdoc directive * @memberOf 'view.file' * @name friendly-json * @description * Angular directive for rendering nested JSON structures in a user-friendly way. * * @attr {String} json Optional. JSON contents to be rendered. Do not use together with uri. * @attr {String} template Optional. Url of HTML template to use for this directive. * @attr {String} uri Optional. Url of JSON file to be rendered. Url must be trusted upfront. * * @example * * * or * * */ (function () { 'use strict'; angular.module('view.file') .directive('friendlyJson', friendlyJsonDirective) .filter('isObject', function() { return function(val) { return angular.isObject(val); }; }) .filter('isArray', function() { return function(val) { return angular.isArray(val); }; }) .filter('isFunction', function() { return function(val) { return angular.isFunction(val); }; }); friendlyJsonDirective.$inject = ['RecursionHelper']; function friendlyJsonDirective(RecursionHelper) { return { restrict: 'E', controller: 'FriendlyJsonCtrl', controllerAs: 'ctrl', scope: { uri: '=?', json: '=?' }, templateUrl: template, compile: function(element) { // Use the compile function from the RecursionHelper, // And return the linking function(s) which it returns return RecursionHelper.compile(element, function ($scope, $elem, $attrs, ctrl) { $scope.loading = true; $scope.$watch('uri', function(newUri) { if (newUri) { ctrl.load(newUri); } }); }); } }; function template(element, attrs) { var url; if (attrs.template) { url = attrs.template; } else { url = '/view-file-ng/friendly-json.html'; } return url; } } }()); (function () { 'use strict'; angular.module('view.file') .controller('FriendlyXmlCtrl', FriendlyXmlCtrl); FriendlyXmlCtrl.$inject = ['$scope', '$sce', '$templateCache', '$http', 'x2js']; function FriendlyXmlCtrl($scope, $sce, $templateCache, $http, x2js) { var ctrl = this; ctrl.trustUri = function(uri) { $sce.trustAsResourceUrl(uri); }; ctrl.load = function(uri) { var xml = $templateCache.get(uri); if (!xml) { $http.get(uri, { cache: $templateCache, transformResponse: function(data, headersGetter) { // Return the raw string, so $http doesn't parse it // if it's json. return data; } }).then(function (response) { $scope.loading = false; ctrl.parse(response.data); }); } else if (angular.isArray(xml)){ $scope.loading = false; ctrl.parse(xml[1]); } else { xml.then(function(response) { $scope.loading = false; ctrl.parse(response.data); }); } }; ctrl.parse = function(xml) { /* jshint camelcase: false */ /* jscs: disable requireCamelCaseOrUpperCaseIdentifiers*/ $scope.json = x2js.xml_str2json(xml); /* jscs: enable requireCamelCaseOrUpperCaseIdentifiers*/ /* jshint camelcase: true */ }; } }()); /** * @ngdoc directive * @memberOf 'view.file' * @name friendly-xml * @description * Angular directive for rendering nested JSON structures in a user-friendly way. * * @attr {String} template Optional. Url of HTML template to use for this directive. * @attr {String} uri Optional. Url of XML file to be rendered. Url must be trusted upfront. * @attr {String} xml Optional. XML contents to be rendered. Do not use together with uri. * * @example * * * or * * */ (function () { 'use strict'; angular.module('view.file') .directive('friendlyXml', friendlyXmlDirective); friendlyXmlDirective.$inject = ['RecursionHelper']; function friendlyXmlDirective(RecursionHelper) { return { restrict: 'E', controller: 'FriendlyXmlCtrl', controllerAs: 'ctrl', scope: { uri: '=?', xml: '=?' }, templateUrl: template, compile: function(element) { // Use the compile function from the RecursionHelper, // And return the linking function(s) which it returns return RecursionHelper.compile(element, function ($scope, $elem, $attrs, ctrl) { $scope.loading = true; $scope.$watch('uri', function(newUri) { if (newUri) { ctrl.load(newUri); } }); $scope.$watch('xml', function(newXML) { if (newXML) { ctrl.parse(newXML); } }); }); } }; function template(element, attrs) { var url; if (attrs.template) { url = attrs.template; } else { url = '/view-file-ng/friendly-json.html'; } return url; } } }()); /** * @ngdoc directive * @memberOf 'view.file' * @name include-safe * @description * Angular attribute directive for including sanitized HTML from url. * * @attr {String} include-safe Required. Url of HTML file to be inserted. * * @example *
Loading..
*/ (function () { 'use strict'; angular.module('view.file') .directive('includeSafe', includeSafeDirective); includeSafeDirective.$inject = ['$http', '$sanitize']; function includeSafeDirective($http, $sanitize) { // directive factory creates a link function return function(scope, element, attrs) { scope.$watch( function(scope) { // watch the 'compile' expression for changes return scope.$eval(attrs.includeSafe); }, function(value) { $http.get(value).then(function(response) { var html = response.data; // when the 'compile' expression changes // assign it into the current DOM element.html($sanitize(html)); }); } ); }; } }()); /** * @ngdoc service * @memberOf 'view.file' * @name ModalService * @param {service} $uibModal angular-bootstrap modal service * @description * Angular helper service displaying, and handling modal overlays. Wraps around $uibModal. */ (function () { 'use strict'; angular.module('view.file') .service('ModalService', ['$uibModal', ModalService]); function ModalService($modal) { var service = { show: showModal }; return service; /** * Show a modal for given template, title, and data. * @memberof ModalService * @param {String} template Required. Url of modal template. * @param {String} title Optional. Title for modal overlay. * @param {Object} ctrl Optional. Object with data and callbacks for use on modal. For instance link to parent Ctrl. * @param {function} validate Optional. Callback function to validate input before closing modal. Expected to return an Array of Strings. * @param {Object} modalOptions Optional. Additional modal options. * @returns {Promise} result Promise for updated ctrl if ok was selected, or null if cancel. */ function showModal(template, title, ctrl, validate, modalOptions) { return $modal.open( angular.extend({ templateUrl: template+'', controller: ['$scope', '$uibModalInstance', 'title', 'ctrl', 'validate', function ($scope, $modalInstance, title, ctrl, validate) { $scope.title = title; $scope.ctrl = ctrl; $scope.alerts = []; $scope.ok = function () { if (validate) { $scope.alerts = validate($scope); } if ($scope.alerts.length === 0) { $modalInstance.close($scope.ctrl); } }; $scope.cancel = function () { $modalInstance.dismiss('cancel'); }; }], size: 'lg', resolve: { title: function () { return title; }, ctrl: function () { return ctrl; }, validate: function () { return validate || function($s) { var errors = []; if ($s.form) { angular.forEach($s.form.$error, function(err, key) { angular.forEach(err, function(e, index) { errors.push(key + ': ' + (e.$name || index)); }); }); } return errors; }; } } }, modalOptions) ).result; } } }()); (function () { 'use strict'; angular.module('view.file') .controller('ViewFileCtrl', ViewFileCtrl); ViewFileCtrl.$inject = ['$scope', '$sce', '$templateCache', '$http', 'ModalService']; function ViewFileCtrl($scope, $sce, $templateCache, $http, modal) { var ctrl = this; ctrl.trustUri = function(uri) { $sce.trustAsResourceUrl(uri); }; ctrl.loadHljs = function(uri) { $scope.loading = !$templateCache.get(uri); if ($scope.loading) { $http.get(uri, { cache: $templateCache, transformResponse: function(data, headersGetter) { // Return the raw string, so $http doesn't parse it // if it's json. return data; } }).then(function (result) { $scope.loading = false; $scope.hljsUri = uri; }); } else { $scope.hljsUri = uri; } }; ctrl.showModal = function() { if ($scope.allowModal) { modal.show('/view-file-ng/show-file.modal.html', null, $scope); } }; ctrl.toggleCode = function() { $scope.showCode = !$scope.showCode; }; } }()); /** * @ngdoc directive * @memberOf 'view.file' * @name view-file * @description * Angular directive for viewing files. Leverages a.o. highlightjs, json-explorer, sanitize, videogular, x2js. * * @attr {String} data Optional. Data of file to be viewed. Do not use together with uri. * @attr {String} uri Optional. Url of file to be viewed. * @attr {String} content-type Required. Mime-type of file to be viewed. * @attr {Boolean} allow-modal Optional. Allow opening of file in modal overlay. Default: true. * @attr {Boolean} controls Optional. Show controls on left. Default: true if download-uri or allow-modal. * @attr {String} download-uri Optional. Url of file for download purpose. Default: null. * @attr {String} file-name Optional. Filename for display. Default: uri portion after last /. * @attr {Boolean} show-code Optional. Show raw code initially for JSON, HTML, Text, and XML. Default: false. * @attr {String} template Optional. Url of HTML template to use for this directive. * @attr {Boolean} trust-uri Optional. Apply trustAsResourceUrl on uri (not recommended). Default: false. * * @example * * * * or * * * */ (function () { 'use strict'; angular.module('view.file') .directive('viewFile', viewFileDirective); function viewFileDirective() { function isTrue(b, def) { if (b !== undefined) { return b === true || b === 'true'; } else { return def; } } function getFileType(contentType) { var type = 'other'; if (/\/[x]?html/.test(contentType)) { type = 'html'; } else if (/[\+\/]json$/.test(contentType)) { type = 'json'; } else if (/[\+\/]xml$/.test(contentType)) { type = 'xml'; } else if (/^(audio|image|text|video|xml)\//.test(contentType)) { type = contentType.split('/')[0]; } else if (/^application\//.test(contentType)) { // TODO } return type; } return { restrict: 'E', controller: 'ViewFileCtrl', controllerAs: 'ctrl', scope: { data: '=?', uri: '=?', contentType: '=', _allowModal: '@allowModal', _controls: '@controls', downloadUri: '=?', fileName: '=?', _showCode: '@showCode', _trustUri: '@trustUri' }, templateUrl: template, link: function ($scope, $elem, $attrs, ctrl) { $scope.allowModal = isTrue($scope._allowModal, true); $scope.controls = isTrue($scope._controls, $scope.allowModal || !!$scope.downloadUri); $scope.showCode = isTrue($scope._showCode, false); $scope.trustUri = isTrue($scope._trustUri, false); if ($attrs.uri) { $scope.loading = true; $scope.$watch('uri', function(newUri) { if (newUri) { $scope.fileName = $scope.fileName || newUri.split('/').pop(); $scope.fileType = getFileType($scope.contentType); if ($scope.trustUri) { ctrl.trustUri(newUri); } if ($scope.fileType === 'xml') { ctrl.loadHljs(newUri); } else { $scope.loading = false; } } }); } else { $scope.loading = false; $scope.fileType = getFileType($scope.contentType); } } }; function template(element, attrs) { var url; if (attrs.template) { url = attrs.template; } else { url = '/view-file-ng/view-file.html'; } return url; } } }()); /** * @ngdoc directive * @memberOf 'view.file' * @name view-object * @description * Angular directive for including HTML object tag dynamically. * * @attr {String} data Required. Url of file to be viewed. Url must be trusted upfront. * @attr {String} type Optional. Mime-type of file to be viewed. * @attr {String} height Optional. Height value to be applied to object tag. * @attr {String} width Optional. Width value to be applied to object tag. * * @example * */ (function () { 'use strict'; angular.module('view.file') .directive('viewObject', ['$compile', function($compile) { return { restrict: 'E', link: function(scope, element, attrs) { // prepare object tag attributes var data = ' data="' + scope.$eval(attrs.data) + '"'; var type = attrs.type ? (' type="' + scope.$eval(attrs.type) + '"') : ''; var height = attrs.height ? (' height="' + scope.$eval(attrs.height) + '"') : ''; var width = attrs.width ? (' width="' + scope.$eval(attrs.width) + '"') : ''; // tried transclude before, but that didn't seem to work.. var innerHtml = element.html(); element.html('' + innerHtml + ''); $compile(element.contents())(scope); } }; }]); }()); (function(module) { try { module = angular.module('view.file.tpls'); } catch (e) { module = angular.module('view.file.tpls', []); } module.run(['$templateCache', function($templateCache) { $templateCache.put('/view-file-ng/friendly-json.html', '
\n' + ' \n' + '
{{ key.startsWith(\'__\') ? key.replace(\'__\', \'\') : key }}
\n' + ' \n' + '
{{ val !== \'\' ? val : \' \' }}
\n' + ' \n' + ' \n' + ' \n' + '
{{ val.join(\', \') }}
\n' + ' \n' + '
 
\n' + ' \n' + '
\n' + ' \n' + ' \n' + '
\n' + ' \n' + '
\n' + ' \n' + ' {{ v !== \'\' ? v : \' \' }}\n' + ' \n' + '
\n' + '
\n' + '
\n' + '
\n' + ''); }]); })(); (function(module) { try { module = angular.module('view.file.tpls'); } catch (e) { module = angular.module('view.file.tpls', []); } module.run(['$templateCache', function($templateCache) { $templateCache.put('/view-file-ng/show-file.modal.html', '
\n' + ' \n' + ' \n' + ' \n' + '
'); }]); })(); (function(module) { try { module = angular.module('view.file.tpls'); } catch (e) { module = angular.module('view.file.tpls', []); } module.run(['$templateCache', function($templateCache) { $templateCache.put('/view-file-ng/view-file.html', '
\n' + '
\n' + '
\n' + ' \n' + '\n' + ' \n' + '\n' + '
\n' + ' \n' + '
\n' + '
\n' + '\n' + '
\n' + '
\n' + ' Loading... \n' + '
\n' + '\n' + '
\n' + ' \n' + '
\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{ currentTime | date:\'mm:ss\' }}\n' + ' \n' + ' \n' + ' \n' + ' {{ timeLeft | date:\'mm:ss\' }}\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + '
\n' + '
\n' + ' Data view not supported for audio and video\n' + '
\n' + '\n' + ' \n' + '
\n' + '
\n' + '
\n' + '
\n' + '
\n' + '
\n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + '\n' + ' \n' + '
\n' + ' \n' + '
\n' + '
\n' + ' Data view not supported for images\n' + '
\n' + '\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + '\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + ' \n' + '
\n' + '
\n' + '\n' + ' \n' + ' \n' + ' Download\n' + '
Alert: cannnot display this file!
\n' + '
\n' + '
\n' + ' Data view not supported for binaries\n' + '
\n' + '
\n' + '
\n' + '\n' + '
\n' + '
'); }]); })();