123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- 'use strict';
- var directive = {};
- var service = { value: {} };
- var DEPENDENCIES = {
- 'angular.js': 'http://code.angularjs.org/' + angular.version.full + '/angular.min.js',
- 'angular-resource.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-resource.min.js',
- 'angular-route.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-route.min.js',
- 'angular-animate.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-animate.min.js',
- 'angular-sanitize.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-sanitize.min.js',
- 'angular-cookies.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-cookies.min.js'
- };
- function escape(text) {
- return text.
- replace(/\&/g, '&').
- replace(/\</g, '<').
- replace(/\>/g, '>').
- replace(/"/g, '"');
- }
- /**
- * http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie
- * http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript
- */
- function setHtmlIe8SafeWay(element, html) {
- var newElement = angular.element('<pre>' + html + '</pre>');
- element.empty();
- element.append(newElement.contents());
- return element;
- }
- directive.jsFiddle = function(getEmbeddedTemplate, escape, script) {
- return {
- terminal: true,
- link: function(scope, element, attr) {
- var name = '',
- stylesheet = '<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">\n',
- fields = {
- html: '',
- css: '',
- js: ''
- };
- angular.forEach(attr.jsFiddle.split(' '), function(file, index) {
- var fileType = file.split('.')[1];
- if (fileType == 'html') {
- if (index == 0) {
- fields[fileType] +=
- '<div ng-app' + (attr.module ? '="' + attr.module + '"' : '') + '>\n' +
- getEmbeddedTemplate(file, 2);
- } else {
- fields[fileType] += '\n\n\n <!-- CACHE FILE: ' + file + ' -->\n' +
- ' <script type="text/ng-template" id="' + file + '">\n' +
- getEmbeddedTemplate(file, 4) +
- ' </script>\n';
- }
- } else {
- fields[fileType] += getEmbeddedTemplate(file) + '\n';
- }
- });
- fields.html += '</div>\n';
- setHtmlIe8SafeWay(element,
- '<form class="jsfiddle" method="post" action="http://jsfiddle.net/api/post/library/pure/" target="_blank">' +
- hiddenField('title', 'AngularJS Example: ' + name) +
- hiddenField('css', '</style> <!-- Ugly Hack due to jsFiddle issue: http://goo.gl/BUfGZ --> \n' +
- stylesheet +
- script.angular +
- (attr.resource ? script.resource : '') +
- '<style>\n' +
- fields.css) +
- hiddenField('html', fields.html) +
- hiddenField('js', fields.js) +
- '<button class="btn btn-primary"><i class="icon-white icon-pencil"></i> Edit Me</button>' +
- '</form>');
- function hiddenField(name, value) {
- return '<input type="hidden" name="' + name + '" value="' + escape(value) + '">';
- }
- }
- }
- };
- directive.code = function() {
- return {restrict: 'E', terminal: true};
- };
- directive.prettyprint = ['reindentCode', function(reindentCode) {
- return {
- restrict: 'C',
- compile: function(element) {
- var html = element.html();
- //ensure that angular won't compile {{ curly }} values
- html = html.replace(/\{\{/g, '<span>{{</span>')
- .replace(/\}\}/g, '<span>}}</span>');
- if (window.RUNNING_IN_NG_TEST_RUNNER) {
- element.html(html);
- }
- else {
- element.html(window.prettyPrintOne(reindentCode(html), undefined, true));
- }
- }
- };
- }];
- directive.ngSetText = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
- return {
- restrict: 'CA',
- priority: 10,
- compile: function(element, attr) {
- setHtmlIe8SafeWay(element, escape(getEmbeddedTemplate(attr.ngSetText)));
- }
- }
- }]
- directive.ngHtmlWrap = ['reindentCode', 'templateMerge', function(reindentCode, templateMerge) {
- return {
- compile: function(element, attr) {
- var properties = {
- head: '',
- module: '',
- body: element.text()
- },
- html = "<!doctype html>\n<html ng-app{{module}}>\n <head>\n{{head:4}} </head>\n <body>\n{{body:4}} </body>\n</html>";
- angular.forEach((attr.ngHtmlWrap || '').split(' '), function(dep) {
- if (!dep) return;
- dep = DEPENDENCIES[dep] || dep;
- var ext = dep.split(/\./).pop();
- if (ext == 'css') {
- properties.head += '<link rel="stylesheet" href="' + dep + '" type="text/css">\n';
- } else if(ext == 'js') {
- properties.head += '<script src="' + dep + '"></script>\n';
- } else {
- properties.module = '="' + dep + '"';
- }
- });
- setHtmlIe8SafeWay(element, escape(templateMerge(html, properties)));
- }
- }
- }];
- directive.ngSetHtml = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
- return {
- restrict: 'CA',
- priority: 10,
- compile: function(element, attr) {
- setHtmlIe8SafeWay(element, getEmbeddedTemplate(attr.ngSetHtml));
- }
- }
- }];
- directive.ngEvalJavascript = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
- return {
- compile: function (element, attr) {
- var fileNames = attr.ngEvalJavascript.split(' ');
- angular.forEach(fileNames, function(fileName) {
- var script = getEmbeddedTemplate(fileName);
- try {
- if (window.execScript) { // IE
- window.execScript(script || '""'); // IE complains when evaling empty string
- } else {
- window.eval(script + '//@ sourceURL=' + fileName);
- }
- } catch (e) {
- if (window.console) {
- window.console.log(script, '\n', e);
- } else {
- window.alert(e);
- }
- }
- });
- }
- };
- }];
- directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location', '$sniffer', '$exceptionHandler',
- function($templateCache, $browser, docsRootScope, $location, $sniffer, $exceptionHandler) {
- return {
- terminal: true,
- link: function(scope, element, attrs) {
- var modules = ['ngAnimate'],
- embedRootScope,
- deregisterEmbedRootScope;
- modules.push(['$provide', function($provide) {
- $provide.value('$templateCache', $templateCache);
- $provide.value('$anchorScroll', angular.noop);
- $provide.value('$browser', $browser);
- $provide.value('$sniffer', $sniffer);
- $provide.provider('$location', function() {
- this.$get = ['$rootScope', function($rootScope) {
- docsRootScope.$on('$locationChangeSuccess', function(event, oldUrl, newUrl) {
- $rootScope.$broadcast('$locationChangeSuccess', oldUrl, newUrl);
- });
- return $location;
- }];
- this.html5Mode = angular.noop;
- this.hashPrefix = function () {
- return '';
- };
- });
- $provide.decorator('$rootScope', ['$delegate', function($delegate) {
- embedRootScope = $delegate;
- // Since we are teleporting the $animate service, which relies on the $$postDigestQueue
- // we need the embedded scope to use the same $$postDigestQueue as the outer scope
- function docsRootDigest() {
- var postDigestQueue = docsRootScope.$$postDigestQueue;
- while (postDigestQueue.length) {
- try {
- postDigestQueue.shift()();
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- }
- embedRootScope.$watch(function () {
- embedRootScope.$$postDigest(docsRootDigest);
- })
- deregisterEmbedRootScope = docsRootScope.$watch(function embedRootScopeDigestWatch() {
- embedRootScope.$digest();
- });
- return embedRootScope;
- }]);
- }]);
- if (attrs.ngEmbedApp) modules.push(attrs.ngEmbedApp);
- element.on('click', function(event) {
- if (event.target.attributes.getNamedItem('ng-click')) {
- event.preventDefault();
- }
- });
- element.bind('$destroy', function() {
- if (deregisterEmbedRootScope) {
- deregisterEmbedRootScope();
- }
- if (embedRootScope) {
- embedRootScope.$destroy();
- }
- });
- element.data('$injector', null);
- angular.bootstrap(element, modules);
- }
- };
- }];
- service.reindentCode = function() {
- return function (text, spaces) {
- if (!text) return text;
- var lines = text.split(/\r?\n/);
- var prefix = ' '.substr(0, spaces || 0);
- var i;
- // remove any leading blank lines
- while (lines.length && lines[0].match(/^\s*$/)) lines.shift();
- // remove any trailing blank lines
- while (lines.length && lines[lines.length - 1].match(/^\s*$/)) lines.pop();
- var minIndent = 999;
- for (i = 0; i < lines.length; i++) {
- var line = lines[0];
- var reindentCode = line.match(/^\s*/)[0];
- if (reindentCode !== line && reindentCode.length < minIndent) {
- minIndent = reindentCode.length;
- }
- }
- for (i = 0; i < lines.length; i++) {
- lines[i] = prefix + lines[i].substring(minIndent);
- }
- lines.push('');
- return lines.join('\n');
- }
- };
- service.templateMerge = ['reindentCode', function(indentCode) {
- return function(template, properties) {
- return template.replace(/\{\{(\w+)(?:\:(\d+))?\}\}/g, function(_, key, indent) {
- var value = properties[key];
- if (indent) {
- value = indentCode(value, indent);
- }
- return value == undefined ? '' : value;
- });
- };
- }];
- service.getEmbeddedTemplate = ['reindentCode', function(reindentCode) {
- return function (id) {
- var element = document.getElementById(id);
- if (!element) {
- return null;
- }
- return reindentCode(angular.element(element).html(), 0);
- }
- }];
- angular.module('bootstrapPrettify', []).directive(directive).factory(service);
|