GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Code Duplication    Length = 404-404 lines in 2 locations

third-party/angularjs-modules-plugins/UI-Bootstrap/ui-bootstrap-tpls-1.3.2.js 1 location

@@ 2570-2973 (lines=404) @@
2567
})
2568
2569
.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
2570
function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
2571
  var cache = {},
2572
    isHtml5DateInput = false;
2573
  var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
2574
    datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
2575
    ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [],
2576
    timezone;
2577
2578
  this.init = function(_ngModel_) {
2579
    ngModel = _ngModel_;
2580
    ngModelOptions = _ngModel_.$options;
2581
    closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
2582
      $scope.$parent.$eval($attrs.closeOnDateSelection) :
2583
      datepickerPopupConfig.closeOnDateSelection;
2584
    appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
2585
      $scope.$parent.$eval($attrs.datepickerAppendToBody) :
2586
      datepickerPopupConfig.appendToBody;
2587
    onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
2588
      $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
2589
    datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
2590
      $attrs.datepickerPopupTemplateUrl :
2591
      datepickerPopupConfig.datepickerPopupTemplateUrl;
2592
    datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
2593
      $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
2594
    altInputFormats = angular.isDefined($attrs.altInputFormats) ?
2595
      $scope.$parent.$eval($attrs.altInputFormats) :
2596
      datepickerPopupConfig.altInputFormats;
2597
2598
    $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
2599
      $scope.$parent.$eval($attrs.showButtonBar) :
2600
      datepickerPopupConfig.showButtonBar;
2601
2602
    if (datepickerPopupConfig.html5Types[$attrs.type]) {
2603
      dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
2604
      isHtml5DateInput = true;
2605
    } else {
2606
      dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
2607
      $attrs.$observe('uibDatepickerPopup', function(value, oldValue) {
2608
        var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
2609
        // Invalidate the $modelValue to ensure that formatters re-run
2610
        // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
2611
        if (newDateFormat !== dateFormat) {
2612
          dateFormat = newDateFormat;
2613
          ngModel.$modelValue = null;
2614
2615
          if (!dateFormat) {
2616
            throw new Error('uibDatepickerPopup must have a date format specified.');
2617
          }
2618
        }
2619
      });
2620
    }
2621
2622
    if (!dateFormat) {
2623
      throw new Error('uibDatepickerPopup must have a date format specified.');
2624
    }
2625
2626
    if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
2627
      throw new Error('HTML5 date input types do not support custom formats.');
2628
    }
2629
2630
    // popup element used to display calendar
2631
    popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
2632
    if (ngModelOptions) {
2633
      timezone = ngModelOptions.timezone;
2634
      $scope.ngModelOptions = angular.copy(ngModelOptions);
2635
      $scope.ngModelOptions.timezone = null;
2636
      if ($scope.ngModelOptions.updateOnDefault === true) {
2637
        $scope.ngModelOptions.updateOn = $scope.ngModelOptions.updateOn ?
2638
          $scope.ngModelOptions.updateOn + ' default' : 'default';
2639
      }
2640
2641
      popupEl.attr('ng-model-options', 'ngModelOptions');
2642
    } else {
2643
      timezone = null;
2644
    }
2645
2646
    popupEl.attr({
2647
      'ng-model': 'date',
2648
      'ng-change': 'dateSelection(date)',
2649
      'template-url': datepickerPopupTemplateUrl
2650
    });
2651
2652
    // datepicker element
2653
    datepickerEl = angular.element(popupEl.children()[0]);
2654
    datepickerEl.attr('template-url', datepickerTemplateUrl);
2655
2656
    if (!$scope.datepickerOptions) {
2657
      $scope.datepickerOptions = {};
2658
    }
2659
2660
    if (isHtml5DateInput) {
2661
      if ($attrs.type === 'month') {
2662
        $scope.datepickerOptions.datepickerMode = 'month';
2663
        $scope.datepickerOptions.minMode = 'month';
2664
      }
2665
    }
2666
2667
    datepickerEl.attr('datepicker-options', 'datepickerOptions');
2668
2669
    if (!isHtml5DateInput) {
2670
      // Internal API to maintain the correct ng-invalid-[key] class
2671
      ngModel.$$parserName = 'date';
2672
      ngModel.$validators.date = validator;
2673
      ngModel.$parsers.unshift(parseDate);
2674
      ngModel.$formatters.push(function(value) {
2675
        if (ngModel.$isEmpty(value)) {
2676
          $scope.date = value;
2677
          return value;
2678
        }
2679
2680
        $scope.date = dateParser.fromTimezone(value, timezone);
2681
2682
        if (angular.isNumber($scope.date)) {
2683
          $scope.date = new Date($scope.date);
2684
        }
2685
2686
        return dateParser.filter($scope.date, dateFormat);
2687
      });
2688
    } else {
2689
      ngModel.$formatters.push(function(value) {
2690
        $scope.date = dateParser.fromTimezone(value, timezone);
2691
        return value;
2692
      });
2693
    }
2694
2695
    // Detect changes in the view from the text box
2696
    ngModel.$viewChangeListeners.push(function() {
2697
      $scope.date = parseDateString(ngModel.$viewValue);
2698
    });
2699
2700
    $element.on('keydown', inputKeydownBind);
2701
2702
    $popup = $compile(popupEl)($scope);
2703
    // Prevent jQuery cache memory leak (template is now redundant after linking)
2704
    popupEl.remove();
2705
2706
    if (appendToBody) {
2707
      $document.find('body').append($popup);
2708
    } else {
2709
      $element.after($popup);
2710
    }
2711
2712
    $scope.$on('$destroy', function() {
2713
      if ($scope.isOpen === true) {
2714
        if (!$rootScope.$$phase) {
2715
          $scope.$apply(function() {
2716
            $scope.isOpen = false;
2717
          });
2718
        }
2719
      }
2720
2721
      $popup.remove();
2722
      $element.off('keydown', inputKeydownBind);
2723
      $document.off('click', documentClickBind);
2724
      if (scrollParentEl) {
2725
        scrollParentEl.off('scroll', positionPopup);
2726
      }
2727
      angular.element($window).off('resize', positionPopup);
2728
2729
      //Clear all watch listeners on destroy
2730
      while (watchListeners.length) {
2731
        watchListeners.shift()();
2732
      }
2733
    });
2734
  };
2735
2736
  $scope.getText = function(key) {
2737
    return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
2738
  };
2739
2740
  $scope.isDisabled = function(date) {
2741
    if (date === 'today') {
2742
      date = dateParser.fromTimezone(new Date(), timezone);
2743
    }
2744
2745
    var dates = {};
2746
    angular.forEach(['minDate', 'maxDate'], function(key) {
2747
      if (!$scope.datepickerOptions[key]) {
2748
        dates[key] = null;
2749
      } else if (angular.isDate($scope.datepickerOptions[key])) {
2750
        dates[key] = dateParser.fromTimezone(new Date($scope.datepickerOptions[key]), timezone);
2751
      } else {
2752
        if ($datepickerPopupLiteralWarning) {
2753
          $log.warn('Literal date support has been deprecated, please switch to date object usage');
2754
        }
2755
2756
        dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
2757
      }
2758
    });
2759
2760
    return $scope.datepickerOptions &&
2761
      dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
2762
      dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
2763
  };
2764
2765
  $scope.compare = function(date1, date2) {
2766
    return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
2767
  };
2768
2769
  // Inner change
2770
  $scope.dateSelection = function(dt) {
2771
    if (angular.isDefined(dt)) {
2772
      $scope.date = dt;
2773
    }
2774
    var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
2775
    $element.val(date);
2776
    ngModel.$setViewValue(date);
2777
2778
    if (closeOnDateSelection) {
2779
      $scope.isOpen = false;
2780
      $element[0].focus();
2781
    }
2782
  };
2783
2784
  $scope.keydown = function(evt) {
2785
    if (evt.which === 27) {
2786
      evt.stopPropagation();
2787
      $scope.isOpen = false;
2788
      $element[0].focus();
2789
    }
2790
  };
2791
2792
  $scope.select = function(date, evt) {
2793
    evt.stopPropagation();
2794
2795
    if (date === 'today') {
2796
      var today = new Date();
2797
      if (angular.isDate($scope.date)) {
2798
        date = new Date($scope.date);
2799
        date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
2800
      } else {
2801
        date = new Date(today.setHours(0, 0, 0, 0));
2802
      }
2803
    }
2804
    $scope.dateSelection(date);
2805
  };
2806
2807
  $scope.close = function(evt) {
2808
    evt.stopPropagation();
2809
2810
    $scope.isOpen = false;
2811
    $element[0].focus();
2812
  };
2813
2814
  $scope.disabled = angular.isDefined($attrs.disabled) || false;
2815
  if ($attrs.ngDisabled) {
2816
    watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {
2817
      $scope.disabled = disabled;
2818
    }));
2819
  }
2820
2821
  $scope.$watch('isOpen', function(value) {
2822
    if (value) {
2823
      if (!$scope.disabled) {
2824
        $timeout(function() {
2825
          positionPopup();
2826
2827
          if (onOpenFocus) {
2828
            $scope.$broadcast('uib:datepicker.focus');
2829
          }
2830
2831
          $document.on('click', documentClickBind);
2832
2833
          var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
2834
          if (appendToBody || $position.parsePlacement(placement)[2]) {
2835
            scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
2836
            if (scrollParentEl) {
2837
              scrollParentEl.on('scroll', positionPopup);
2838
            }
2839
          } else {
2840
            scrollParentEl = null;
2841
          }
2842
2843
          angular.element($window).on('resize', positionPopup);
2844
        }, 0, false);
2845
      } else {
2846
        $scope.isOpen = false;
2847
      }
2848
    } else {
2849
      $document.off('click', documentClickBind);
2850
      if (scrollParentEl) {
2851
        scrollParentEl.off('scroll', positionPopup);
2852
      }
2853
      angular.element($window).off('resize', positionPopup);
2854
    }
2855
  });
2856
2857
  function cameltoDash(string) {
2858
    return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
2859
  }
2860
2861
  function parseDateString(viewValue) {
2862
    var date = dateParser.parse(viewValue, dateFormat, $scope.date);
2863
    if (isNaN(date)) {
2864
      for (var i = 0; i < altInputFormats.length; i++) {
2865
        date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
2866
        if (!isNaN(date)) {
2867
          return date;
2868
        }
2869
      }
2870
    }
2871
    return date;
2872
  }
2873
2874
  function parseDate(viewValue) {
2875
    if (angular.isNumber(viewValue)) {
2876
      // presumably timestamp to date object
2877
      viewValue = new Date(viewValue);
2878
    }
2879
2880
    if (!viewValue) {
2881
      return null;
2882
    }
2883
2884
    if (angular.isDate(viewValue) && !isNaN(viewValue)) {
2885
      return viewValue;
2886
    }
2887
2888
    if (angular.isString(viewValue)) {
2889
      var date = parseDateString(viewValue);
2890
      if (!isNaN(date)) {
2891
        return dateParser.toTimezone(date, timezone);
2892
      }
2893
    }
2894
2895
    return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined;
2896
  }
2897
2898
  function validator(modelValue, viewValue) {
2899
    var value = modelValue || viewValue;
2900
2901
    if (!$attrs.ngRequired && !value) {
2902
      return true;
2903
    }
2904
2905
    if (angular.isNumber(value)) {
2906
      value = new Date(value);
2907
    }
2908
2909
    if (!value) {
2910
      return true;
2911
    }
2912
2913
    if (angular.isDate(value) && !isNaN(value)) {
2914
      return true;
2915
    }
2916
2917
    if (angular.isString(value)) {
2918
      return !isNaN(parseDateString(viewValue));
2919
    }
2920
2921
    return false;
2922
  }
2923
2924
  function documentClickBind(event) {
2925
    if (!$scope.isOpen && $scope.disabled) {
2926
      return;
2927
    }
2928
2929
    var popup = $popup[0];
2930
    var dpContainsTarget = $element[0].contains(event.target);
2931
    // The popup node may not be an element node
2932
    // In some browsers (IE) only element nodes have the 'contains' function
2933
    var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
2934
    if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
2935
      $scope.$apply(function() {
2936
        $scope.isOpen = false;
2937
      });
2938
    }
2939
  }
2940
2941
  function inputKeydownBind(evt) {
2942
    if (evt.which === 27 && $scope.isOpen) {
2943
      evt.preventDefault();
2944
      evt.stopPropagation();
2945
      $scope.$apply(function() {
2946
        $scope.isOpen = false;
2947
      });
2948
      $element[0].focus();
2949
    } else if (evt.which === 40 && !$scope.isOpen) {
2950
      evt.preventDefault();
2951
      evt.stopPropagation();
2952
      $scope.$apply(function() {
2953
        $scope.isOpen = true;
2954
      });
2955
    }
2956
  }
2957
2958
  function positionPopup() {
2959
    if ($scope.isOpen) {
2960
      var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
2961
      var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
2962
      var position = $position.positionElements($element, dpElement, placement, appendToBody);
2963
      dpElement.css({top: position.top + 'px', left: position.left + 'px'});
2964
      if (dpElement.hasClass('uib-position-measure')) {
2965
        dpElement.removeClass('uib-position-measure');
2966
      }
2967
    }
2968
  }
2969
2970
  $scope.$on('uib:datepicker.mode', function() {
2971
    $timeout(positionPopup, 0, false);
2972
  });
2973
}])
2974
2975
.directive('uibDatepickerPopup', function() {
2976
  return {

third-party/angularjs-modules-plugins/UI-Bootstrap/ui-bootstrap-1.3.2.js 1 location

@@ 2569-2972 (lines=404) @@
2566
})
2567
2568
.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
2569
function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
2570
  var cache = {},
2571
    isHtml5DateInput = false;
2572
  var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
2573
    datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
2574
    ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [],
2575
    timezone;
2576
2577
  this.init = function(_ngModel_) {
2578
    ngModel = _ngModel_;
2579
    ngModelOptions = _ngModel_.$options;
2580
    closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
2581
      $scope.$parent.$eval($attrs.closeOnDateSelection) :
2582
      datepickerPopupConfig.closeOnDateSelection;
2583
    appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
2584
      $scope.$parent.$eval($attrs.datepickerAppendToBody) :
2585
      datepickerPopupConfig.appendToBody;
2586
    onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
2587
      $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
2588
    datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
2589
      $attrs.datepickerPopupTemplateUrl :
2590
      datepickerPopupConfig.datepickerPopupTemplateUrl;
2591
    datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
2592
      $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
2593
    altInputFormats = angular.isDefined($attrs.altInputFormats) ?
2594
      $scope.$parent.$eval($attrs.altInputFormats) :
2595
      datepickerPopupConfig.altInputFormats;
2596
2597
    $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
2598
      $scope.$parent.$eval($attrs.showButtonBar) :
2599
      datepickerPopupConfig.showButtonBar;
2600
2601
    if (datepickerPopupConfig.html5Types[$attrs.type]) {
2602
      dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
2603
      isHtml5DateInput = true;
2604
    } else {
2605
      dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
2606
      $attrs.$observe('uibDatepickerPopup', function(value, oldValue) {
2607
        var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
2608
        // Invalidate the $modelValue to ensure that formatters re-run
2609
        // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
2610
        if (newDateFormat !== dateFormat) {
2611
          dateFormat = newDateFormat;
2612
          ngModel.$modelValue = null;
2613
2614
          if (!dateFormat) {
2615
            throw new Error('uibDatepickerPopup must have a date format specified.');
2616
          }
2617
        }
2618
      });
2619
    }
2620
2621
    if (!dateFormat) {
2622
      throw new Error('uibDatepickerPopup must have a date format specified.');
2623
    }
2624
2625
    if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
2626
      throw new Error('HTML5 date input types do not support custom formats.');
2627
    }
2628
2629
    // popup element used to display calendar
2630
    popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
2631
    if (ngModelOptions) {
2632
      timezone = ngModelOptions.timezone;
2633
      $scope.ngModelOptions = angular.copy(ngModelOptions);
2634
      $scope.ngModelOptions.timezone = null;
2635
      if ($scope.ngModelOptions.updateOnDefault === true) {
2636
        $scope.ngModelOptions.updateOn = $scope.ngModelOptions.updateOn ?
2637
          $scope.ngModelOptions.updateOn + ' default' : 'default';
2638
      }
2639
2640
      popupEl.attr('ng-model-options', 'ngModelOptions');
2641
    } else {
2642
      timezone = null;
2643
    }
2644
2645
    popupEl.attr({
2646
      'ng-model': 'date',
2647
      'ng-change': 'dateSelection(date)',
2648
      'template-url': datepickerPopupTemplateUrl
2649
    });
2650
2651
    // datepicker element
2652
    datepickerEl = angular.element(popupEl.children()[0]);
2653
    datepickerEl.attr('template-url', datepickerTemplateUrl);
2654
2655
    if (!$scope.datepickerOptions) {
2656
      $scope.datepickerOptions = {};
2657
    }
2658
2659
    if (isHtml5DateInput) {
2660
      if ($attrs.type === 'month') {
2661
        $scope.datepickerOptions.datepickerMode = 'month';
2662
        $scope.datepickerOptions.minMode = 'month';
2663
      }
2664
    }
2665
2666
    datepickerEl.attr('datepicker-options', 'datepickerOptions');
2667
2668
    if (!isHtml5DateInput) {
2669
      // Internal API to maintain the correct ng-invalid-[key] class
2670
      ngModel.$$parserName = 'date';
2671
      ngModel.$validators.date = validator;
2672
      ngModel.$parsers.unshift(parseDate);
2673
      ngModel.$formatters.push(function(value) {
2674
        if (ngModel.$isEmpty(value)) {
2675
          $scope.date = value;
2676
          return value;
2677
        }
2678
2679
        $scope.date = dateParser.fromTimezone(value, timezone);
2680
2681
        if (angular.isNumber($scope.date)) {
2682
          $scope.date = new Date($scope.date);
2683
        }
2684
2685
        return dateParser.filter($scope.date, dateFormat);
2686
      });
2687
    } else {
2688
      ngModel.$formatters.push(function(value) {
2689
        $scope.date = dateParser.fromTimezone(value, timezone);
2690
        return value;
2691
      });
2692
    }
2693
2694
    // Detect changes in the view from the text box
2695
    ngModel.$viewChangeListeners.push(function() {
2696
      $scope.date = parseDateString(ngModel.$viewValue);
2697
    });
2698
2699
    $element.on('keydown', inputKeydownBind);
2700
2701
    $popup = $compile(popupEl)($scope);
2702
    // Prevent jQuery cache memory leak (template is now redundant after linking)
2703
    popupEl.remove();
2704
2705
    if (appendToBody) {
2706
      $document.find('body').append($popup);
2707
    } else {
2708
      $element.after($popup);
2709
    }
2710
2711
    $scope.$on('$destroy', function() {
2712
      if ($scope.isOpen === true) {
2713
        if (!$rootScope.$$phase) {
2714
          $scope.$apply(function() {
2715
            $scope.isOpen = false;
2716
          });
2717
        }
2718
      }
2719
2720
      $popup.remove();
2721
      $element.off('keydown', inputKeydownBind);
2722
      $document.off('click', documentClickBind);
2723
      if (scrollParentEl) {
2724
        scrollParentEl.off('scroll', positionPopup);
2725
      }
2726
      angular.element($window).off('resize', positionPopup);
2727
2728
      //Clear all watch listeners on destroy
2729
      while (watchListeners.length) {
2730
        watchListeners.shift()();
2731
      }
2732
    });
2733
  };
2734
2735
  $scope.getText = function(key) {
2736
    return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
2737
  };
2738
2739
  $scope.isDisabled = function(date) {
2740
    if (date === 'today') {
2741
      date = dateParser.fromTimezone(new Date(), timezone);
2742
    }
2743
2744
    var dates = {};
2745
    angular.forEach(['minDate', 'maxDate'], function(key) {
2746
      if (!$scope.datepickerOptions[key]) {
2747
        dates[key] = null;
2748
      } else if (angular.isDate($scope.datepickerOptions[key])) {
2749
        dates[key] = dateParser.fromTimezone(new Date($scope.datepickerOptions[key]), timezone);
2750
      } else {
2751
        if ($datepickerPopupLiteralWarning) {
2752
          $log.warn('Literal date support has been deprecated, please switch to date object usage');
2753
        }
2754
2755
        dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
2756
      }
2757
    });
2758
2759
    return $scope.datepickerOptions &&
2760
      dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
2761
      dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
2762
  };
2763
2764
  $scope.compare = function(date1, date2) {
2765
    return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
2766
  };
2767
2768
  // Inner change
2769
  $scope.dateSelection = function(dt) {
2770
    if (angular.isDefined(dt)) {
2771
      $scope.date = dt;
2772
    }
2773
    var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
2774
    $element.val(date);
2775
    ngModel.$setViewValue(date);
2776
2777
    if (closeOnDateSelection) {
2778
      $scope.isOpen = false;
2779
      $element[0].focus();
2780
    }
2781
  };
2782
2783
  $scope.keydown = function(evt) {
2784
    if (evt.which === 27) {
2785
      evt.stopPropagation();
2786
      $scope.isOpen = false;
2787
      $element[0].focus();
2788
    }
2789
  };
2790
2791
  $scope.select = function(date, evt) {
2792
    evt.stopPropagation();
2793
2794
    if (date === 'today') {
2795
      var today = new Date();
2796
      if (angular.isDate($scope.date)) {
2797
        date = new Date($scope.date);
2798
        date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
2799
      } else {
2800
        date = new Date(today.setHours(0, 0, 0, 0));
2801
      }
2802
    }
2803
    $scope.dateSelection(date);
2804
  };
2805
2806
  $scope.close = function(evt) {
2807
    evt.stopPropagation();
2808
2809
    $scope.isOpen = false;
2810
    $element[0].focus();
2811
  };
2812
2813
  $scope.disabled = angular.isDefined($attrs.disabled) || false;
2814
  if ($attrs.ngDisabled) {
2815
    watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {
2816
      $scope.disabled = disabled;
2817
    }));
2818
  }
2819
2820
  $scope.$watch('isOpen', function(value) {
2821
    if (value) {
2822
      if (!$scope.disabled) {
2823
        $timeout(function() {
2824
          positionPopup();
2825
2826
          if (onOpenFocus) {
2827
            $scope.$broadcast('uib:datepicker.focus');
2828
          }
2829
2830
          $document.on('click', documentClickBind);
2831
2832
          var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
2833
          if (appendToBody || $position.parsePlacement(placement)[2]) {
2834
            scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
2835
            if (scrollParentEl) {
2836
              scrollParentEl.on('scroll', positionPopup);
2837
            }
2838
          } else {
2839
            scrollParentEl = null;
2840
          }
2841
2842
          angular.element($window).on('resize', positionPopup);
2843
        }, 0, false);
2844
      } else {
2845
        $scope.isOpen = false;
2846
      }
2847
    } else {
2848
      $document.off('click', documentClickBind);
2849
      if (scrollParentEl) {
2850
        scrollParentEl.off('scroll', positionPopup);
2851
      }
2852
      angular.element($window).off('resize', positionPopup);
2853
    }
2854
  });
2855
2856
  function cameltoDash(string) {
2857
    return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
2858
  }
2859
2860
  function parseDateString(viewValue) {
2861
    var date = dateParser.parse(viewValue, dateFormat, $scope.date);
2862
    if (isNaN(date)) {
2863
      for (var i = 0; i < altInputFormats.length; i++) {
2864
        date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
2865
        if (!isNaN(date)) {
2866
          return date;
2867
        }
2868
      }
2869
    }
2870
    return date;
2871
  }
2872
2873
  function parseDate(viewValue) {
2874
    if (angular.isNumber(viewValue)) {
2875
      // presumably timestamp to date object
2876
      viewValue = new Date(viewValue);
2877
    }
2878
2879
    if (!viewValue) {
2880
      return null;
2881
    }
2882
2883
    if (angular.isDate(viewValue) && !isNaN(viewValue)) {
2884
      return viewValue;
2885
    }
2886
2887
    if (angular.isString(viewValue)) {
2888
      var date = parseDateString(viewValue);
2889
      if (!isNaN(date)) {
2890
        return dateParser.toTimezone(date, timezone);
2891
      }
2892
    }
2893
2894
    return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined;
2895
  }
2896
2897
  function validator(modelValue, viewValue) {
2898
    var value = modelValue || viewValue;
2899
2900
    if (!$attrs.ngRequired && !value) {
2901
      return true;
2902
    }
2903
2904
    if (angular.isNumber(value)) {
2905
      value = new Date(value);
2906
    }
2907
2908
    if (!value) {
2909
      return true;
2910
    }
2911
2912
    if (angular.isDate(value) && !isNaN(value)) {
2913
      return true;
2914
    }
2915
2916
    if (angular.isString(value)) {
2917
      return !isNaN(parseDateString(viewValue));
2918
    }
2919
2920
    return false;
2921
  }
2922
2923
  function documentClickBind(event) {
2924
    if (!$scope.isOpen && $scope.disabled) {
2925
      return;
2926
    }
2927
2928
    var popup = $popup[0];
2929
    var dpContainsTarget = $element[0].contains(event.target);
2930
    // The popup node may not be an element node
2931
    // In some browsers (IE) only element nodes have the 'contains' function
2932
    var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
2933
    if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
2934
      $scope.$apply(function() {
2935
        $scope.isOpen = false;
2936
      });
2937
    }
2938
  }
2939
2940
  function inputKeydownBind(evt) {
2941
    if (evt.which === 27 && $scope.isOpen) {
2942
      evt.preventDefault();
2943
      evt.stopPropagation();
2944
      $scope.$apply(function() {
2945
        $scope.isOpen = false;
2946
      });
2947
      $element[0].focus();
2948
    } else if (evt.which === 40 && !$scope.isOpen) {
2949
      evt.preventDefault();
2950
      evt.stopPropagation();
2951
      $scope.$apply(function() {
2952
        $scope.isOpen = true;
2953
      });
2954
    }
2955
  }
2956
2957
  function positionPopup() {
2958
    if ($scope.isOpen) {
2959
      var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
2960
      var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
2961
      var position = $position.positionElements($element, dpElement, placement, appendToBody);
2962
      dpElement.css({top: position.top + 'px', left: position.left + 'px'});
2963
      if (dpElement.hasClass('uib-position-measure')) {
2964
        dpElement.removeClass('uib-position-measure');
2965
      }
2966
    }
2967
  }
2968
2969
  $scope.$on('uib:datepicker.mode', function() {
2970
    $timeout(positionPopup, 0, false);
2971
  });
2972
}])
2973
2974
.directive('uibDatepickerPopup', function() {
2975
  return {