PageSourceSearch

https://angularjs.org/js/homepage.js

js angularjs.org collected 2026-10-01 07:32:31 UTC 16,303 bytes, 490 lines download raw bytes

1angular.module('homepage', ['ngAnimate', 'ui.bootstrap', 'download-data'])
2
3  .config(function($provide, $locationProvider) {
4    var pulseElements = $(),
5        pulseColor = {r:0xE6, g:0xF0, b: 0xFF},
6        baseColor = {r:0x99, g:0xc2, b: 0xFF},
7        pulseDuration = 1000,
8        pulseDelay = 15000;
9
10    function hex(number) {
11      return ('0' + Number(number).toString(16)).slice(-2);
12    }
13
14    jQuery.fn.pulse = function () {
15      pulseElements = pulseElements.add(this);
16    };
17    var lastPulse;
18
19    function tick() {
20      var duration = new Date().getTime() - lastPulse,
21          index = duration * Math.PI / pulseDuration ,
22          level = Math.pow(Math.sin(index), 10),
23          color = {
24            r: Math.round(pulseColor.r * level + baseColor.r * (1 - level)),
25            g: Math.round(pulseColor.g * level + baseColor.g * (1 - level)),
26            b: Math.round(pulseColor.b * level + baseColor.b * (1 - level))
27          },
28          style = '#' + hex(color.r) + hex(color.g) + hex(color.b);
29
30      pulseElements.css('backgroundColor', style);
31      if (duration > pulseDuration) {
32        setTimeout(function() {
33          lastPulse = new Date().getTime();
34          tick();
35        }, pulseDelay);
36      } else {
37        setTimeout(tick, 50);
38      }
39    }
40
41    $provide.value('startPulse', function() {
42       setTimeout(function() {
43         lastPulse = new Date().getTime();
44         tick();
45       }, 2000);
46    });
47
48    $locationProvider.html5Mode(true);
49    $locationProvider.hashPrefix('!');
50  })
51
52  .value('indent', function(text, spaces) {
53    if (!text) return text;
54    var lines = text.split(/\r?\n/);
55    var prefix = '      '.substr(0, spaces || 0);
56    var i;
57
58    // remove any leading blank lines
59    while (lines.length && lines[0].match(/^\s*$/)) lines.shift();
60    // remove any trailing blank lines
61    while (lines.length && lines[lines.length - 1].match(/^\s*$/)) lines.pop();
62    var minIndent = 999;
63    for (i = 0; i < lines.length; i++) {
64      var line = lines[0];
65      var indent = line.match(/^\s*/)[0];
66      if (indent !== line && indent.length < minIndent) {
67        minIndent = indent.length;
68      }
69    }
70
71    for (i = 0; i < lines.length; i++) {
72      lines[i] = prefix + lines[i].substring(minIndent);
73    }
74    lines.push('');
75    return lines.join('\n');
76  })
77
78  .value('escape', function(text) {
79    return text.replace(/\&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
80  })
81
82  .factory('script', function() {
83
84    return {
85      angular: '<script src="https://ajax.googleapis.com/ajax/libs/angularjs/' + angular.version.full + '/angular.min.js"></script>\n',
86      resource: '<script src="https://ajax.googleapis.com/ajax/libs/angularjs/' + angular.version.full + '/angular-resource.min.js"></script>\n',
87      route: '<script src="https://ajax.googleapis.com/ajax/libs/angularjs/' + angular.version.full + '/angular-route.min.js"></script>\n',
88      firebase: '<script src="https://cdn.firebase.com/js/client/2.0.4/firebase.js"></script>\n    <script src="https://cdn.firebase.com/libs/angularfire/0.9.0/angularfire.min.js"></script>\n'
89    };
90  })
91
92  .factory('fetchCode', function(indent) {
93    return function get(id, spaces) {
94      return indent(angular.element(document.getElementById(id)).html(), spaces);
95    };
96  })
97
98  .factory('formPostData', ['$document', function($document) {
99    return function(url, newWindow, fields) {
100      /**
101       * If the form posts to target="_blank", pop-up blockers can cause it not to work.
102       * If a user choses to bypass pop-up blocker one time and click the link, they will arrive at
103       * a new default plnkr, not a plnkr with the desired template.  Given this undesired behavior,
104       * some may still want to open the plnk in a new window by opting-in via ctrl+click.  The
105       * newWindow param allows for this possibility.
106       */
107      var target = newWindow ? '_blank' : '_self';
108      var form = angular.element('<form style="display: none;" method="post" action="' + url + '" target="' + target + '"></form>');
109      angular.forEach(fields, function(value, name) {
110        var input = angular.element('<input type="hidden" name="' +  name + '">');
111        input.attr('value', value);
112        form.append(input);
113      });
114      $document.find('body').append(form);
115      form[0].submit();
116      form.remove();
117    };
118  }])
119
120  .factory('templateBuilder', function(script) {
121    var COPYRIGHT = 'Copyright ' + (new Date()).getFullYear() + ' Google Inc. All Rights Reserved.\n'
122     + 'Use of this source code is governed by an MIT-style license that\n'
123     + 'can be found in the LICENSE file at https://angular.io/license';
124    var COPYRIGHT_JS_CSS = '\n\n/*\n' + COPYRIGHT + '\n*/';
125    var COPYRIGHT_HTML = '\n\n<!-- \n' + COPYRIGHT + '\n-->';
126
127    return {
128      createLocalDependencies: function(files) {
129        var head = [];
130
131        angular.forEach(files.split(' '), function(file, index) {
132          var filename = file.split(':')[0],
133              fileType = filename.split(/\./)[1];
134
135          if (index === 0) return;
136          if (fileType == 'js') {
137            head.push('    <script src="' + filename + '"></script>\n');
138          } else if (fileType == 'css') {
139            head.push('    <link rel="stylesheet" href="' + filename + '">\n');
140          }
141        });
142
143        return head;
144      },
145      getIndexTemplate: function(deps) {
146        return '<!doctype html>\n' +
147            '<html ng-app__MODULE__>\n' +
148            '  <head>\n' +
149            '    ' + script.angular +
150           (deps.resource ? ('    ' + script.resource.replace('></', '>\n    </')) : '') +
151           (deps.route ? ('    ' + script.route.replace('></', '>\n   </')) : '') +
152           (deps.firebase ? ('    ' + script.firebase) : '') +
153            '__HEAD__' +
154            '  </head>\n' +
155            '  <body>\n' +
156            '__BODY__' +
157            '  </body>\n' +
158            '</html>';
159      },
160      getCopyright: function(filename) {
161        switch (filename.substr(filename.lastIndexOf('.'))) {
162          case '.html':
163            return COPYRIGHT_HTML;
164          case '.js':
165          case '.css':
166            return COPYRIGHT_JS_CSS;
167          case '.md':
168            return COPYRIGHT;
169        }
170        return '';
171      }
172    };
173  })
174
175  .directive('code', function() {
176    return {restrict: 'E', terminal: true};
177  })
178
179  .directive('appRun', function(fetchCode, $templateCache, $browser) {
180    return {
181      terminal: true,
182      link: function(scope, element, attrs) {
183        var modules = [];
184
185        modules.push(function($provide, $locationProvider) {
186          $provide.value('$templateCache', {
187            get: function(key) {
188              var value = $templateCache.get(key);
189              if (value) {
190                value = value.replace(/\#\//mg, '/');
191              }
192              return value;
193            },
194            put: function(key, value) {
195              // noop, we don't need the cache for anything in examples
196              return value;
197            }
198          });
199          $provide.value('$anchorScroll', angular.noop);
200          $provide.value('$browser', $browser);
201          $locationProvider.html5Mode(true);
202          $locationProvider.hashPrefix('!');
203        });
204        if (attrs.module) {
205          modules.push(attrs.module);
206        }
207
208        element.html(fetchCode(attrs.appRun));
209        element.bind('click', function(event) {
210          if (event.target.attributes.getNamedItem('ng-click')) {
211            event.preventDefault();
212          }
213        });
214        element.data('$injector', null);
215        angular.bootstrap(element, modules);
216      }
217    };
218  })
219
220  .directive('appSource', function(fetchCode, escape, $compile, $timeout, templateBuilder, $sce) {
221    return {
222      terminal: true,
223      scope: {},
224      link: function(scope, element, attrs) {
225        var tabs = [],
226            annotation = attrs.annotate && angular.fromJson(fetchCode(attrs.annotate)) || {};
227
228        element.css('clear', 'both');
229
230        angular.forEach(attrs.appSource.split(' '), function(filename, index) {
231          var content;
232
233          if (index === 0) {
234            var head = templateBuilder.createLocalDependencies(attrs.appSource);
235
236            content = templateBuilder.getIndexTemplate(attrs);
237            content = content.
238              replace('__MODULE__', attrs.module ? '="' + attrs.module + '"' : '').
239              replace('__HEAD__', head.join('')).
240              replace('__BODY__', fetchCode(filename, 4));
241          } else {
242            content = fetchCode(filename);
243          }
244
245          // hack around incorrect tokenization
246          content = content.replace('.done-true', 'doneTrue');
247          content = prettyPrintOne(escape(content), undefined, true);
248          // hack around incorrect tokenization
249          content = content.replace('doneTrue', '.done-true');
250
251          var popovers = {},
252              counter = 0;
253
254          angular.forEach(annotation[filename], function(text, key) {
255            counter++;
256
257            text = text.replace('{{', '&#123;&#123;').replace('}}', '&#125;&#125;');
258
259            var regexp = new RegExp('(\\W|^)(' + key.replace(/([\W\-])/g, '\\$1') + ')(\\W|$)');
260
261            scope['popover' + index + counter] = $sce.trustAsHtml(text);
262
263            content = content.replace(regexp, function(_, before, token, after) {
264              token = '__' + counter + '__';
265              popovers[token] =
266                '<span ' +
267                    'class="nocode code-annotation" ' +
268                    'popover-append-to-body="true" ' +
269                    'popover-trigger="mouseenter" ' +
270                    'popover-title="' + escape(key) + '" ' +
271                    'uib-popover-html="popover' + index + counter + '">' +
272                  '<code>' + escape(key) + '</code>' +
273                '</span>';
274              return before + token + after;
275            });
276          });
277
278          angular.forEach(popovers, function(text, token) {
279            content = content.replace(token, text);
280          });
281
282          tabs.push(
283            '<uib-tab heading="' + (index ? filename : 'index.html')  + '">\n' +
284            '  <pre class="prettyprint linenums nocode"><code>' + content +'</code></pre>\n' +
285            '</uib-tab>\n'
286          );
287        });
288
289        element.html(
290          '<uib-tabset>' +
291            tabs.join('') +
292          '</uib-tabset>');
293
294        // Compile up the HTML to get the directives to kick-in
295        $compile(element.children())(scope);
296        $timeout(function() {
297          var annotationElements = element.find('span[uib-popover-html]');
298          $compile(annotationElements)(scope);
299        }, 0);
300      }
301    };
302  })
303
304  .directive('plnkr', function(fetchCode, formPostData, script, templateBuilder) {
305    return {
306      template: '<button ng-click="plnkr.open($event)" class="btn btn-primary">' +
307                '<i class="icon-white icon-pencil"></i> ' +
308                'Edit Me' +
309              '</button>',
310      scope: {},
311      bindToController: {
312        'files': '@plnkr',
313        'module': '@?module',
314        'resource': '@?',
315        'route': '@?',
316        'firebase': '@?',
317      },
318      controllerAs: 'plnkr',
319      controller: function() {
320
321        this.$onInit = function() {
322          var ctrl = this;
323
324          var name = '',
325            bootstrapStylesheet = 'https://netdna.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css',
326            plnkrFiles = [];
327
328          angular.forEach(ctrl.files.split(' '), function(filename, index) {
329            var content;
330
331            if (index === 0) {
332              var head = templateBuilder.createLocalDependencies(ctrl.files);
333
334              head.push('    <link rel="stylesheet" href="' + bootstrapStylesheet + '">\n');
335              content = templateBuilder.getIndexTemplate({resource: ctrl.resource, route: ctrl.route, firebase: ctrl.firebase});
336              content = content.
337                replace('__MODULE__', ctrl.module ? '="' + ctrl.module + '"' : '').
338                replace('__HEAD__', head.join('')).
339                replace('__BODY__', fetchCode(filename, 4));
340            } else {
341              content = fetchCode(filename);
342            }
343
344            content += templateBuilder.getCopyright(filename);
345
346            plnkrFiles.push({
347              name: index === 0 ? 'index.html' : filename, // plnkr expects an index.html
348              content: content
349            });
350          });
351
352          ctrl.open = function(clickEvent) {
353
354            var newWindow = clickEvent.ctrlKey || clickEvent.metaKey;
355
356            var postData = {
357              'tags[0]': "angularjs",
358              'tags[1]': "example",
359              'private': true
360            };
361
362            angular.forEach(plnkrFiles, function(file) {
363              postData['files[' + file.name + ']'] = file.content;
364            });
365
366            postData.description = 'AngularJS Example: ' + name;
367
368            formPostData('https://plnkr.co/edit/?p=preview', newWindow, postData);
369          };
370        };
371      }
372    };
373  })
374
375  .directive('hint', function() {
376    return {
377      template:
378        '<em>Hint:</em> ' +
379          'hover over ' +
380          '<code ' +
381              'class="nocode code-annotation" ' +
382              'popover-append-to-body="true" ' +
383              'popover-trigger="mouseenter" ' +
384              'popover-title="Hover" ' +
385              'uib-popover="Place your mouse over highlighted areas in the code for explanations.">' +
386            'me' +
387          '</code>.'
388    };
389  })
390
391  .controller('AppController', function($scope, $uibModal, BRANCHES) {
392    $scope.BRANCHES = BRANCHES;
393
394    $scope.showDownloadModal = function() {
395      $uibModal.open({
396        templateUrl: 'partials/download-modal.html',
397        windowClass: 'download-modal'
398      });
399    };
400
401    $scope.showVideo = function(videoUrl) {
402      $uibModal.open({
403        templateUrl: 'partials/video-modal.html',
404        windowClass: 'video-modal',
405        controller: 'VideoController',
406        resolve: {
407          videoUrl: function() { return videoUrl; }
408        }
409      });
410    };
411
412  })
413
414  .controller('DownloadController', function($scope, $sce, BRANCHES, BUILDS, DOWNLOAD_INFO) {
415
416    function getRelativeUrl(branch, build) {
417      switch (build.name) {
418        case 'Minified':
419          return branch.version + '/angular.min.js';
420        case 'Uncompressed':
421          return branch.version + '/angular.js';
422        case 'Zip':
423          return branch.version + '/angular-' + branch.version + '.zip';
424      }
425    }
426
427    $scope.BRANCHES = BRANCHES;
428    $scope.BUILDS = BUILDS;
429    $scope.DOWNLOAD_INFO_TRUSTED = {
430      branchesInfo: $sce.trustAsHtml(DOWNLOAD_INFO.branchesInfo),
431      buildsInfo: $sce.trustAsHtml(DOWNLOAD_INFO.buildsInfo),
432      bowerInfo: $sce.trustAsHtml(DOWNLOAD_INFO.bowerInfo),
433      cdnInfo: $sce.trustAsHtml(DOWNLOAD_INFO.cdnInfo)
434    };
435
436    $scope.currentBranch = $scope.BRANCHES[0];
437    $scope.currentBuild = $scope.BUILDS[0];
438
439    $scope.setBranch = function(branch) {
440      $scope.currentBranch = branch;
441    };
442
443    $scope.setBuild = function(build) {
444      $scope.currentBuild = build;
445    };
446
447    var BASE_CDN_URL = 'https://ajax.googleapis.com/ajax/libs/angularjs/';
448    $scope.cdnUrl = function() {
449      if ($scope.currentBuild.name !== 'Zip') {
450        return BASE_CDN_URL + getRelativeUrl($scope.currentBranch, $scope.currentBuild);
451      }
452    };
453
454
455    var BASE_CODE_ANGULAR_URL = 'https://code.angularjs.org/';
456    $scope.downloadLink = function() {
457      return $scope.cdnUrl() || BASE_CODE_ANGULAR_URL + getRelativeUrl($scope.currentBranch, $scope.currentBuild);
458    };
459
460
461  })
462
463.controller('VideoController', function($scope, $timeout, $sce, videoUrl) {
464
465  // HACK: Trick YouTube to play HD by showing big and then resizing after 2500ms.
466
467  $scope.video = {
468    width: 1280,
469    height: 720,
470    allowfullscreen: true,
471    src: $sce.trustAsResourceUrl(videoUrl)
472  };
473
474  $timeout(function() {
475    $scope.video.width = 970;
476    $scope.video.height = 556;
477  }, 2500);
478
479})
480
481.run(function($rootScope, startPulse){
482  $rootScope.version = angular.version;
483
484  //   $('[rel=popover]').
485  //     popover().
486  //     pulse();
487  //   startPulse();
488  // });
489
490});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.