source: main/trunk/model-interfaces-dev/heritage-nz/iframe/heritage-nz-dl_files/angular-strap.js@ 32796

Last change on this file since 32796 was 32796, checked in by davidb, 5 years ago

Initial set of files to provide look and feel of Heritage NZ site, plus SVN clickable map in an iframe

  • Property svn:executable set to *
File size: 37.3 KB
Line 
1/**
2 * AngularStrap - Twitter Bootstrap directives for AngularJS
3 * @version v0.7.5 - 2013-07-31
4 * @link http://mgcrea.github.com/angular-strap
5 * @author Olivier Louvignes <[email protected]>
6 * @license MIT License, http://www.opensource.org/licenses/MIT
7 */
8angular.module('$strap.config', []).value('$strapConfig', {});
9angular.module('$strap.filters', ['$strap.config']);
10angular.module('$strap.directives', ['$strap.config']);
11angular.module('$strap', [
12 '$strap.filters',
13 '$strap.directives',
14 '$strap.config'
15]);
16'use strict';
17angular.module('$strap.directives').directive('bsAlert', [
18 '$parse',
19 '$timeout',
20 '$compile',
21 function ($parse, $timeout, $compile) {
22 return {
23 restrict: 'A',
24 link: function postLink(scope, element, attrs) {
25 var getter = $parse(attrs.bsAlert), setter = getter.assign, value = getter(scope);
26 var closeAlert = function closeAlertFn(delay) {
27 $timeout(function () {
28 element.alert('close');
29 }, delay * 1);
30 };
31 if (!attrs.bsAlert) {
32 if (angular.isUndefined(attrs.closeButton) || attrs.closeButton !== '0' && attrs.closeButton !== 'false') {
33 element.prepend('<button type="button" class="close" data-dismiss="alert">&times;</button>');
34 }
35 if (attrs.closeAfter)
36 closeAlert(attrs.closeAfter);
37 } else {
38 scope.$watch(attrs.bsAlert, function (newValue, oldValue) {
39 value = newValue;
40 element.html((newValue.title ? '<strong>' + newValue.title + '</strong>&nbsp;' : '') + newValue.content || '');
41 if (!!newValue.closed) {
42 element.hide();
43 }
44 $compile(element.contents())(scope);
45 if (newValue.type || oldValue.type) {
46 oldValue.type && element.removeClass('alert-' + oldValue.type);
47 newValue.type && element.addClass('alert-' + newValue.type);
48 }
49 if (angular.isDefined(newValue.closeAfter))
50 closeAlert(newValue.closeAfter);
51 else if (attrs.closeAfter)
52 closeAlert(attrs.closeAfter);
53 if (angular.isUndefined(attrs.closeButton) || attrs.closeButton !== '0' && attrs.closeButton !== 'false') {
54 element.prepend('<button type="button" class="close" data-dismiss="alert">&times;</button>');
55 }
56 }, true);
57 }
58 element.addClass('alert').alert();
59 if (element.hasClass('fade')) {
60 element.removeClass('in');
61 setTimeout(function () {
62 element.addClass('in');
63 });
64 }
65 var parentArray = attrs.ngRepeat && attrs.ngRepeat.split(' in ').pop();
66 element.on('close', function (ev) {
67 var removeElement;
68 if (parentArray) {
69 ev.preventDefault();
70 element.removeClass('in');
71 removeElement = function () {
72 element.trigger('closed');
73 if (scope.$parent) {
74 scope.$parent.$apply(function () {
75 var path = parentArray.split('.');
76 var curr = scope.$parent;
77 for (var i = 0; i < path.length; ++i) {
78 if (curr) {
79 curr = curr[path[i]];
80 }
81 }
82 if (curr) {
83 curr.splice(scope.$index, 1);
84 }
85 });
86 }
87 };
88 $.support.transition && element.hasClass('fade') ? element.on($.support.transition.end, removeElement) : removeElement();
89 } else if (value) {
90 ev.preventDefault();
91 element.removeClass('in');
92 removeElement = function () {
93 element.trigger('closed');
94 scope.$apply(function () {
95 value.closed = true;
96 });
97 };
98 $.support.transition && element.hasClass('fade') ? element.on($.support.transition.end, removeElement) : removeElement();
99 } else {
100 }
101 });
102 }
103 };
104 }
105]);
106'use strict';
107angular.module('$strap.directives').directive('bsButton', [
108 '$parse',
109 '$timeout',
110 function ($parse, $timeout) {
111 return {
112 restrict: 'A',
113 require: '?ngModel',
114 link: function postLink(scope, element, attrs, controller) {
115 if (controller) {
116 if (!element.parent('[data-toggle="buttons-checkbox"], [data-toggle="buttons-radio"]').length) {
117 element.attr('data-toggle', 'button');
118 }
119 var startValue = !!scope.$eval(attrs.ngModel);
120 if (startValue) {
121 element.addClass('active');
122 }
123 scope.$watch(attrs.ngModel, function (newValue, oldValue) {
124 var bNew = !!newValue, bOld = !!oldValue;
125 if (bNew !== bOld) {
126 $.fn.button.Constructor.prototype.toggle.call(button);
127 } else if (bNew && !startValue) {
128 element.addClass('active');
129 }
130 });
131 }
132 if (!element.hasClass('btn')) {
133 element.on('click.button.data-api', function (ev) {
134 element.button('toggle');
135 });
136 }
137 element.button();
138 var button = element.data('button');
139 button.toggle = function () {
140 if (!controller) {
141 return $.fn.button.Constructor.prototype.toggle.call(this);
142 }
143 var $parent = element.parent('[data-toggle="buttons-radio"]');
144 if ($parent.length) {
145 element.siblings('[ng-model]').each(function (k, v) {
146 $parse($(v).attr('ng-model')).assign(scope, false);
147 });
148 scope.$digest();
149 if (!controller.$modelValue) {
150 controller.$setViewValue(!controller.$modelValue);
151 scope.$digest();
152 }
153 } else {
154 scope.$apply(function () {
155 controller.$setViewValue(!controller.$modelValue);
156 });
157 }
158 };
159 }
160 };
161 }
162]).directive('bsButtonsCheckbox', [
163 '$parse',
164 function ($parse) {
165 return {
166 restrict: 'A',
167 require: '?ngModel',
168 compile: function compile(tElement, tAttrs, transclude) {
169 tElement.attr('data-toggle', 'buttons-checkbox').find('a, button').each(function (k, v) {
170 $(v).attr('bs-button', '');
171 });
172 }
173 };
174 }
175]).directive('bsButtonsRadio', [
176 '$timeout',
177 function ($timeout) {
178 return {
179 restrict: 'A',
180 require: '?ngModel',
181 compile: function compile(tElement, tAttrs, transclude) {
182 tElement.attr('data-toggle', 'buttons-radio');
183 if (!tAttrs.ngModel) {
184 tElement.find('a, button').each(function (k, v) {
185 $(v).attr('bs-button', '');
186 });
187 }
188 return function postLink(scope, iElement, iAttrs, controller) {
189 if (controller) {
190 $timeout(function () {
191 iElement.find('[value]').button().filter('[value="' + controller.$viewValue + '"]').addClass('active');
192 });
193 iElement.on('click.button.data-api', function (ev) {
194 scope.$apply(function () {
195 controller.$setViewValue($(ev.target).closest('button').attr('value'));
196 });
197 });
198 scope.$watch(iAttrs.ngModel, function (newValue, oldValue) {
199 if (newValue !== oldValue) {
200 var $btn = iElement.find('[value="' + scope.$eval(iAttrs.ngModel) + '"]');
201 if ($btn.length) {
202 $btn.button('toggle');
203 }
204 }
205 });
206 }
207 };
208 }
209 };
210 }
211]);
212'use strict';
213angular.module('$strap.directives').directive('bsButtonSelect', [
214 '$parse',
215 '$timeout',
216 function ($parse, $timeout) {
217 return {
218 restrict: 'A',
219 require: '?ngModel',
220 link: function postLink(scope, element, attrs, ctrl) {
221 var getter = $parse(attrs.bsButtonSelect), setter = getter.assign;
222 if (ctrl) {
223 element.text(scope.$eval(attrs.ngModel));
224 scope.$watch(attrs.ngModel, function (newValue, oldValue) {
225 element.text(newValue);
226 });
227 }
228 var values, value, index, newValue;
229 element.bind('click', function (ev) {
230 values = getter(scope);
231 value = ctrl ? scope.$eval(attrs.ngModel) : element.text();
232 index = values.indexOf(value);
233 newValue = index > values.length - 2 ? values[0] : values[index + 1];
234 scope.$apply(function () {
235 element.text(newValue);
236 if (ctrl) {
237 ctrl.$setViewValue(newValue);
238 }
239 });
240 });
241 }
242 };
243 }
244]);
245'use strict';
246angular.module('$strap.directives').directive('bsDatepicker', [
247 '$timeout',
248 '$strapConfig',
249 function ($timeout, $strapConfig) {
250 var isAppleTouch = /(iP(a|o)d|iPhone)/g.test(navigator.userAgent);
251 var regexpMap = function regexpMapFn(language) {
252 language = language || 'en';
253 return {
254 '/': '[\\/]',
255 '-': '[-]',
256 '.': '[.]',
257 ' ': '[\\s]',
258 'dd': '(?:(?:[0-2]?[0-9]{1})|(?:[3][01]{1}))',
259 'd': '(?:(?:[0-2]?[0-9]{1})|(?:[3][01]{1}))',
260 'mm': '(?:[0]?[1-9]|[1][012])',
261 'm': '(?:[0]?[1-9]|[1][012])',
262 'DD': '(?:' + $.fn.datepicker.dates[language].days.join('|') + ')',
263 'D': '(?:' + $.fn.datepicker.dates[language].daysShort.join('|') + ')',
264 'MM': '(?:' + $.fn.datepicker.dates[language].months.join('|') + ')',
265 'M': '(?:' + $.fn.datepicker.dates[language].monthsShort.join('|') + ')',
266 'yyyy': '(?:(?:[1]{1}[0-9]{1}[0-9]{1}[0-9]{1})|(?:[2]{1}[0-9]{3}))(?![[0-9]])',
267 'yy': '(?:(?:[0-9]{1}[0-9]{1}))(?![[0-9]])'
268 };
269 };
270 var regexpForDateFormat = function regexpForDateFormatFn(format, language) {
271 var re = format, map = regexpMap(language), i;
272 i = 0;
273 angular.forEach(map, function (v, k) {
274 re = re.split(k).join('${' + i + '}');
275 i++;
276 });
277 i = 0;
278 angular.forEach(map, function (v, k) {
279 re = re.split('${' + i + '}').join(v);
280 i++;
281 });
282 return new RegExp('^' + re + '$', ['i']);
283 };
284 return {
285 restrict: 'A',
286 require: '?ngModel',
287 link: function postLink(scope, element, attrs, controller) {
288 var options = angular.extend({ autoclose: true }, $strapConfig.datepicker || {}), type = attrs.dateType || options.type || 'date';
289 angular.forEach([
290 'format',
291 'weekStart',
292 'calendarWeeks',
293 'startDate',
294 'endDate',
295 'daysOfWeekDisabled',
296 'autoclose',
297 'startView',
298 'minViewMode',
299 'todayBtn',
300 'todayHighlight',
301 'keyboardNavigation',
302 'language',
303 'forceParse'
304 ], function (key) {
305 if (angular.isDefined(attrs[key]))
306 options[key] = attrs[key];
307 });
308 var language = options.language || 'en', readFormat = attrs.dateFormat || options.format || $.fn.datepicker.dates[language] && $.fn.datepicker.dates[language].format || 'mm/dd/yyyy', format = isAppleTouch ? 'yyyy-mm-dd' : readFormat, dateFormatRegexp = regexpForDateFormat(format, language);
309 if (controller) {
310 controller.$formatters.unshift(function (modelValue) {
311 return type === 'date' && angular.isString(modelValue) && modelValue ? $.fn.datepicker.DPGlobal.parseDate(modelValue, $.fn.datepicker.DPGlobal.parseFormat(readFormat), language) : modelValue;
312 });
313 controller.$parsers.unshift(function (viewValue) {
314 if (!viewValue) {
315 controller.$setValidity('date', true);
316 return null;
317 } else if (type === 'date' && angular.isDate(viewValue)) {
318 controller.$setValidity('date', true);
319 return viewValue;
320 } else if (angular.isString(viewValue) && dateFormatRegexp.test(viewValue)) {
321 controller.$setValidity('date', true);
322 if (isAppleTouch)
323 return new Date(viewValue);
324 return type === 'string' ? viewValue : $.fn.datepicker.DPGlobal.parseDate(viewValue, $.fn.datepicker.DPGlobal.parseFormat(format), language);
325 } else {
326 controller.$setValidity('date', false);
327 return undefined;
328 }
329 });
330 controller.$render = function ngModelRender() {
331 if (isAppleTouch) {
332 var date = controller.$viewValue ? $.fn.datepicker.DPGlobal.formatDate(controller.$viewValue, $.fn.datepicker.DPGlobal.parseFormat(format), language) : '';
333 element.val(date);
334 return date;
335 }
336 if (!controller.$viewValue)
337 element.val('');
338 return element.datepicker('update', controller.$viewValue);
339 };
340 }
341 if (isAppleTouch) {
342 element.prop('type', 'date').css('-webkit-appearance', 'textfield');
343 } else {
344 if (controller) {
345 element.on('changeDate', function (ev) {
346 scope.$apply(function () {
347 controller.$setViewValue(type === 'string' ? element.val() : ev.date);
348 });
349 });
350 }
351 element.datepicker(angular.extend(options, {
352 format: format,
353 language: language
354 }));
355 scope.$on('$destroy', function () {
356 var datepicker = element.data('datepicker');
357 if (datepicker) {
358 datepicker.picker.remove();
359 element.data('datepicker', null);
360 }
361 });
362 attrs.$observe('startDate', function (value) {
363 element.datepicker('setStartDate', value);
364 });
365 attrs.$observe('endDate', function (value) {
366 element.datepicker('setEndDate', value);
367 });
368 }
369 var component = element.siblings('[data-toggle="datepicker"]');
370 if (component.length) {
371 component.on('click', function () {
372 if (!element.prop('disabled')) {
373 element.trigger('focus');
374 }
375 });
376 }
377 }
378 };
379 }
380]);
381'use strict';
382angular.module('$strap.directives').directive('bsDropdown', [
383 '$parse',
384 '$compile',
385 '$timeout',
386 function ($parse, $compile, $timeout) {
387 var buildTemplate = function (items, ul) {
388 if (!ul)
389 ul = [
390 '<ul class="dropdown-menu" role="menu" aria-labelledby="drop1">',
391 '</ul>'
392 ];
393 angular.forEach(items, function (item, index) {
394 if (item.divider)
395 return ul.splice(index + 1, 0, '<li class="divider"></li>');
396 var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' + '<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? '" ng-click="' + item.click + '"' : '') + (item.target ? '" target="' + item.target + '"' : '') + (item.method ? '" data-method="' + item.method + '"' : '') + '>' + (item.text || '') + '</a>';
397 if (item.submenu && item.submenu.length)
398 li += buildTemplate(item.submenu).join('\n');
399 li += '</li>';
400 ul.splice(index + 1, 0, li);
401 });
402 return ul;
403 };
404 return {
405 restrict: 'EA',
406 scope: true,
407 link: function postLink(scope, iElement, iAttrs) {
408 var getter = $parse(iAttrs.bsDropdown), items = getter(scope);
409 $timeout(function () {
410 if (!angular.isArray(items)) {
411 }
412 var dropdown = angular.element(buildTemplate(items).join(''));
413 dropdown.insertAfter(iElement);
414 $compile(iElement.next('ul.dropdown-menu'))(scope);
415 });
416 iElement.addClass('dropdown-toggle').attr('data-toggle', 'dropdown');
417 }
418 };
419 }
420]);
421'use strict';
422angular.module('$strap.directives').factory('$modal', [
423 '$rootScope',
424 '$compile',
425 '$http',
426 '$timeout',
427 '$q',
428 '$templateCache',
429 '$strapConfig',
430 function ($rootScope, $compile, $http, $timeout, $q, $templateCache, $strapConfig) {
431 var ModalFactory = function ModalFactoryFn(config) {
432 function Modal(config) {
433 var options = angular.extend({ show: true }, $strapConfig.modal, config), scope = options.scope ? options.scope : $rootScope.$new(), templateUrl = options.template;
434 return $q.when($templateCache.get(templateUrl) || $http.get(templateUrl, { cache: true }).then(function (res) {
435 return res.data;
436 })).then(function onSuccess(template) {
437 var id = templateUrl.replace('.html', '').replace(/[\/|\.|:]/g, '-') + '-' + scope.$id;
438 var $modal = $('<div class="modal hide" tabindex="-1"></div>').attr('id', id).addClass('fade').html(template);
439 if (options.modalClass)
440 $modal.addClass(options.modalClass);
441 $('body').append($modal);
442 $timeout(function () {
443 $compile($modal)(scope);
444 });
445 scope.$modal = function (name) {
446 $modal.modal(name);
447 };
448 angular.forEach([
449 'show',
450 'hide'
451 ], function (name) {
452 scope[name] = function () {
453 $modal.modal(name);
454 };
455 });
456 scope.dismiss = scope.hide;
457 angular.forEach([
458 'show',
459 'shown',
460 'hide',
461 'hidden'
462 ], function (name) {
463 $modal.on(name, function (ev) {
464 scope.$emit('modal-' + name, ev);
465 });
466 });
467 $modal.on('shown', function (ev) {
468 $('input[autofocus], textarea[autofocus]', $modal).first().trigger('focus');
469 });
470 $modal.on('hidden', function (ev) {
471 if (!options.persist)
472 scope.$destroy();
473 });
474 scope.$on('$destroy', function () {
475 $modal.remove();
476 });
477 $modal.modal(options);
478 return $modal;
479 });
480 }
481 return new Modal(config);
482 };
483 return ModalFactory;
484 }
485]).directive('bsModal', [
486 '$q',
487 '$modal',
488 function ($q, $modal) {
489 return {
490 restrict: 'A',
491 scope: true,
492 link: function postLink(scope, iElement, iAttrs, controller) {
493 var options = {
494 template: scope.$eval(iAttrs.bsModal),
495 persist: true,
496 show: false,
497 scope: scope
498 };
499 angular.forEach([
500 'modalClass',
501 'backdrop',
502 'keyboard'
503 ], function (key) {
504 if (angular.isDefined(iAttrs[key]))
505 options[key] = iAttrs[key];
506 });
507 $q.when($modal(options)).then(function onSuccess(modal) {
508 iElement.attr('data-target', '#' + modal.attr('id')).attr('data-toggle', 'modal');
509 });
510 }
511 };
512 }
513]);
514'use strict';
515angular.module('$strap.directives').directive('bsNavbar', [
516 '$location',
517 function ($location) {
518 return {
519 restrict: 'A',
520 link: function postLink(scope, element, attrs, controller) {
521 scope.$watch(function () {
522 return $location.path();
523 }, function (newValue, oldValue) {
524 $('li[data-match-route]', element).each(function (k, li) {
525 var $li = angular.element(li), pattern = $li.attr('data-match-route'), regexp = new RegExp('^' + pattern + '$', ['i']);
526 if (regexp.test(newValue)) {
527 $li.addClass('active').find('.collapse.in').collapse('hide');
528 } else {
529 $li.removeClass('active');
530 }
531 });
532 });
533 }
534 };
535 }
536]);
537'use strict';
538angular.module('$strap.directives').directive('bsPopover', [
539 '$parse',
540 '$compile',
541 '$http',
542 '$timeout',
543 '$q',
544 '$templateCache',
545 function ($parse, $compile, $http, $timeout, $q, $templateCache) {
546 $('body').on('keyup', function (ev) {
547 if (ev.keyCode === 27) {
548 $('.popover.in').each(function () {
549 $(this).popover('hide');
550 });
551 }
552 });
553 return {
554 restrict: 'A',
555 scope: true,
556 link: function postLink(scope, element, attr, ctrl) {
557 var getter = $parse(attr.bsPopover), setter = getter.assign, value = getter(scope), options = {};
558 if (angular.isObject(value)) {
559 options = value;
560 }
561 $q.when(options.content || $templateCache.get(value) || $http.get(value, { cache: true })).then(function onSuccess(template) {
562 if (angular.isObject(template)) {
563 template = template.data;
564 }
565 if (!!attr.unique) {
566 element.on('show', function (ev) {
567 $('.popover.in').each(function () {
568 var $this = $(this), popover = $this.data('popover');
569 if (popover && !popover.$element.is(element)) {
570 $this.popover('hide');
571 }
572 });
573 });
574 }
575 if (!!attr.hide) {
576 scope.$watch(attr.hide, function (newValue, oldValue) {
577 if (!!newValue) {
578 popover.hide();
579 } else if (newValue !== oldValue) {
580 popover.show();
581 }
582 });
583 }
584 if (!!attr.show) {
585 scope.$watch(attr.show, function (newValue, oldValue) {
586 if (!!newValue) {
587 $timeout(function () {
588 popover.show();
589 });
590 } else if (newValue !== oldValue) {
591 popover.hide();
592 }
593 });
594 }
595 element.popover(angular.extend({}, options, {
596 content: template,
597 html: true
598 }));
599 var popover = element.data('popover');
600 popover.hasContent = function () {
601 return this.getTitle() || template;
602 };
603 popover.getPosition = function () {
604 var r = $.fn.popover.Constructor.prototype.getPosition.apply(this, arguments);
605 $compile(this.$tip)(scope);
606 scope.$digest();
607 this.$tip.data('popover', this);
608 return r;
609 };
610 scope.$popover = function (name) {
611 popover(name);
612 };
613 angular.forEach([
614 'show',
615 'hide'
616 ], function (name) {
617 scope[name] = function () {
618 popover[name]();
619 };
620 });
621 scope.dismiss = scope.hide;
622 angular.forEach([
623 'show',
624 'shown',
625 'hide',
626 'hidden'
627 ], function (name) {
628 element.on(name, function (ev) {
629 scope.$emit('popover-' + name, ev);
630 });
631 });
632 });
633 }
634 };
635 }
636]);
637'use strict';
638angular.module('$strap.directives').directive('bsSelect', [
639 '$timeout',
640 function ($timeout) {
641 var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/;
642 return {
643 restrict: 'A',
644 require: '?ngModel',
645 link: function postLink(scope, element, attrs, controller) {
646 var options = scope.$eval(attrs.bsSelect) || {};
647 $timeout(function () {
648 element.selectpicker(options);
649 element.next().removeClass('ng-scope');
650 });
651 if (controller) {
652 scope.$watch(attrs.ngModel, function (newValue, oldValue) {
653 if (!angular.equals(newValue, oldValue)) {
654 element.selectpicker('refresh');
655 }
656 });
657 }
658 }
659 };
660 }
661]);
662'use strict';
663angular.module('$strap.directives').directive('bsTabs', [
664 '$parse',
665 '$compile',
666 '$timeout',
667 function ($parse, $compile, $timeout) {
668 var template = '<div class="tabs">' + '<ul class="nav nav-tabs">' + '<li ng-repeat="pane in panes" ng-class="{active:pane.active}">' + '<a data-target="#{{pane.id}}" data-index="{{$index}}" data-toggle="tab">{{pane.title}}</a>' + '</li>' + '</ul>' + '<div class="tab-content" ng-transclude>' + '</div>';
669 return {
670 restrict: 'A',
671 require: '?ngModel',
672 priority: 0,
673 scope: true,
674 template: template,
675 replace: true,
676 transclude: true,
677 compile: function compile(tElement, tAttrs, transclude) {
678 return function postLink(scope, iElement, iAttrs, controller) {
679 var getter = $parse(iAttrs.bsTabs), setter = getter.assign, value = getter(scope);
680 scope.panes = [];
681 var $tabs = iElement.find('ul.nav-tabs');
682 var $panes = iElement.find('div.tab-content');
683 var activeTab = 0, id, title, active;
684 $timeout(function () {
685 $panes.find('[data-title], [data-tab]').each(function (index) {
686 var $this = angular.element(this);
687 id = 'tab-' + scope.$id + '-' + index;
688 title = $this.data('title') || $this.data('tab');
689 active = !active && $this.hasClass('active');
690 $this.attr('id', id).addClass('tab-pane');
691 if (iAttrs.fade)
692 $this.addClass('fade');
693 scope.panes.push({
694 id: id,
695 title: title,
696 content: this.innerHTML,
697 active: active
698 });
699 });
700 if (scope.panes.length && !active) {
701 $panes.find('.tab-pane:first-child').addClass('active' + (iAttrs.fade ? ' in' : ''));
702 scope.panes[0].active = true;
703 }
704 });
705 if (controller) {
706 iElement.on('show', function (ev) {
707 var $target = $(ev.target);
708 scope.$apply(function () {
709 controller.$setViewValue($target.data('index'));
710 });
711 });
712 scope.$watch(iAttrs.ngModel, function (newValue, oldValue) {
713 if (angular.isUndefined(newValue))
714 return;
715 activeTab = newValue;
716 setTimeout(function () {
717 var $next = $($tabs[0].querySelectorAll('li')[newValue * 1]);
718 if (!$next.hasClass('active')) {
719 $next.children('a').tab('show');
720 }
721 });
722 });
723 }
724 };
725 }
726 };
727 }
728]);
729'use strict';
730angular.module('$strap.directives').directive('bsTimepicker', [
731 '$timeout',
732 '$strapConfig',
733 function ($timeout, $strapConfig) {
734 var TIME_REGEXP = '((?:(?:[0-1][0-9])|(?:[2][0-3])|(?:[0-9])):(?:[0-5][0-9])(?::[0-5][0-9])?(?:\\s?(?:am|AM|pm|PM))?)';
735 return {
736 restrict: 'A',
737 require: '?ngModel',
738 link: function postLink(scope, element, attrs, controller) {
739 if (controller) {
740 element.on('changeTime.timepicker', function (ev) {
741 $timeout(function () {
742 controller.$setViewValue(element.val());
743 });
744 });
745 var timeRegExp = new RegExp('^' + TIME_REGEXP + '$', ['i']);
746 controller.$parsers.unshift(function (viewValue) {
747 if (!viewValue || timeRegExp.test(viewValue)) {
748 controller.$setValidity('time', true);
749 return viewValue;
750 } else {
751 controller.$setValidity('time', false);
752 return;
753 }
754 });
755 }
756 element.attr('data-toggle', 'timepicker');
757 element.parent().addClass('bootstrap-timepicker');
758 element.timepicker($strapConfig.timepicker || {});
759 var timepicker = element.data('timepicker');
760 var component = element.siblings('[data-toggle="timepicker"]');
761 if (component.length) {
762 component.on('click', $.proxy(timepicker.showWidget, timepicker));
763 }
764 }
765 };
766 }
767]);
768'use strict';
769angular.module('$strap.directives').directive('bsTooltip', [
770 '$parse',
771 '$compile',
772 function ($parse, $compile) {
773 return {
774 restrict: 'A',
775 scope: true,
776 link: function postLink(scope, element, attrs, ctrl) {
777 var getter = $parse(attrs.bsTooltip), setter = getter.assign, value = getter(scope);
778 scope.$watch(attrs.bsTooltip, function (newValue, oldValue) {
779 if (newValue !== oldValue) {
780 value = newValue;
781 }
782 });
783 if (!!attrs.unique) {
784 element.on('show', function (ev) {
785 $('.tooltip.in').each(function () {
786 var $this = $(this), tooltip = $this.data('tooltip');
787 if (tooltip && !tooltip.$element.is(element)) {
788 $this.tooltip('hide');
789 }
790 });
791 });
792 }
793 element.tooltip({
794 title: function () {
795 return angular.isFunction(value) ? value.apply(null, arguments) : value;
796 },
797 html: true
798 });
799 var tooltip = element.data('tooltip');
800 tooltip.show = function () {
801 var r = $.fn.tooltip.Constructor.prototype.show.apply(this, arguments);
802 this.tip().data('tooltip', this);
803 return r;
804 };
805 scope._tooltip = function (event) {
806 element.tooltip(event);
807 };
808 scope.hide = function () {
809 element.tooltip('hide');
810 };
811 scope.show = function () {
812 element.tooltip('show');
813 };
814 scope.dismiss = scope.hide;
815 }
816 };
817 }
818]);
819'use strict';
820angular.module('$strap.directives').directive('bsTypeahead', [
821 '$parse',
822 function ($parse) {
823 return {
824 restrict: 'A',
825 require: '?ngModel',
826 link: function postLink(scope, element, attrs, controller) {
827 var getter = $parse(attrs.bsTypeahead), setter = getter.assign, value = getter(scope);
828 scope.$watch(attrs.bsTypeahead, function (newValue, oldValue) {
829 if (newValue !== oldValue) {
830 value = newValue;
831 }
832 });
833 element.attr('data-provide', 'typeahead');
834 element.typeahead({
835 source: function (query) {
836 return angular.isFunction(value) ? value.apply(null, arguments) : value;
837 },
838 minLength: attrs.minLength || 1,
839 items: attrs.items,
840 updater: function (value) {
841 if (controller) {
842 scope.$apply(function () {
843 controller.$setViewValue(value);
844 });
845 }
846 scope.$emit('typeahead-updated', value);
847 return value;
848 }
849 });
850 var typeahead = element.data('typeahead');
851 typeahead.lookup = function (ev) {
852 var items;
853 this.query = this.$element.val() || '';
854 if (this.query.length < this.options.minLength) {
855 return this.shown ? this.hide() : this;
856 }
857 items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source;
858 return items ? this.process(items) : this;
859 };
860 if (!!attrs.matchAll) {
861 typeahead.matcher = function (item) {
862 return true;
863 };
864 }
865 if (attrs.minLength === '0') {
866 setTimeout(function () {
867 element.on('focus', function () {
868 element.val().length === 0 && setTimeout(element.typeahead.bind(element, 'lookup'), 200);
869 });
870 });
871 }
872 }
873 };
874 }
875]);
Note: See TracBrowser for help on using the repository browser.