Wrap JQuery in Angular directive

I am trying to add the jquery codepen below to angular directive, but I am new to directives and cannot get it to work ...

http://codepen.io/mnpenner/pen/mFokd

I added the code from above to the directive in the jsfiddle ...

http://jsfiddle.net/HB7LU/13968/

myApp.directive('clock', function(){
   return {
   restrict: 'E',
   link: function (scope, el, atts ){
};
});

<div>
  <clock id="input"></clock>
</div>

      

Can anyone please help?

+3


source to share


1 answer


The code below will work, but as suggested by Wawy it would be better in angular mode.

angular.module('exampleApp', [])
.directive('clock', function(){
  // Insert your jQuery code here, before the return, rather than in the link function
  // $.widget('wx.timepicker', {...};
  return {
    // You can use E(element) here, but clock is a very generic name, can generate conflict in the future.
    restrict: 'A',
    link: function (scope, el, atts ){
      // If jQuery was loaded before AngularJS, el will be a jQuery instance  
      // see https://docs.angularjs.org/api/ng/function/angular.element
      // So, you can call your jQuery plugin here.
      el.timepicker();
    }
  };
});

      



$.widget('wx.timepicker', {
  _create: function() {
    this.timepicker = $('<div class="timepicker"><div class="clock"><div class="unit hour bubble">Hr</div><div class="unit minute bubble">Min</div><div class="face"><div class="time-bubbles"></div><div class="minute hand"></div><div class="hour hand"></div></div><div class="meridiem am bubble">AM</div><div class="meridiem pm bubble">PM</div></div><div class="done">Done</div></div>').hide().insertAfter(this.element);
    this.hour = 0;
    this.minute = 0;
    this.meridiem = 0; // 0=am, 1=pm
    this.display = 0; // 0=none, 1=hours, 2=minutes
    this.isOpen = false;
    var self = this;
    
    this.element.prop('autocomplete',false);
    if(self._parseInput()) {
      self._refreshAll();
    }
    this.timepicker.find('.unit.minute').on('click', function() {
      self._buildMinutes();
    });
    this.timepicker.find('.unit.hour').on('click', function() {
      self._buildHours();
    });
    this.timepicker.on('click', '.time.hour', function() {
      self.hour = $(this).data('value');
      self._buildMinutes();
      self._refreshAll();
    });
    this.timepicker.on('click', '.time.minute', function() {
      self.minute = $(this).data('value');
      self._refreshAll();
    });
    this.element.on('focus click', function() {
      self._open();
    });
    this.timepicker.on('mousedown', function(e) {
      return false;
    });
    this.element.on('blur', function(e) {
      self._parseInput();
      self._refreshInput();
      self._close();
    });
    this.element.on('input', function() {
      if(self._parseInput()) {
        self._refreshClock();
      }
    });
    this.timepicker.find('.done').on('click', function() {
      self.element.focus();
      self._close();
    });
    this.timepicker.find('.meridiem.am').on('click', function() {
      self.meridiem = 0;
      self._refreshAll();
    });
    this.timepicker.find('.meridiem.pm').on('click', function() {
      self.meridiem = 1;
      self._refreshAll();
    });
  },
  
  _open: function() {
    if(!this.isOpen) {
      var offset = this.element.offset();
      this.timepicker.css({
        'left':offset.left+'px',
        'top':(offset.top+this.element.outerHeight())+'px'
      }).show();
      this.isOpen = true;
      this._buildHours();
    }
  },
  
  _close: function() {
    if(this.isOpen) {
      this.timepicker.hide();
      this.isOpen = false;
    }
  },
  
  _refreshAll: function() {
    this._refreshInput();
    this._refreshClock();
  },
  
  _refreshInput: function() {
    var hour = this.hour === 0 ? 12 : this.hour;
    var minute = this.minute < 10 ? '0'+this.minute : this.minute;
    this.element.val(hour+':'+minute+(this.meridiem?'pm':'am'));
  },
  
  _refreshClock: function() {
    var self = this;
    if(this.meridiem) {
      this.timepicker.find('.meridiem.am').removeClass('selected');
      this.timepicker.find('.meridiem.pm').addClass('selected');
    } else {
      this.timepicker.find('.meridiem.pm').removeClass('selected');
      this.timepicker.find('.meridiem.am').addClass('selected');
    }
    this.timepicker.find('.time.selected').removeClass('selected');
    if(this.display === 1) {
      this.timepicker.find('.time.hour').filter(function() {
        return $(this).data('value') === self.hour;
      }).addClass('selected');
    } else {
      this.timepicker.find('.time.minute').filter(function() {
        return $(this).data('value') === self.minute;
      }).addClass('selected');
    }
    this.timepicker.find('.hand.hour').css('transform', 'rotate(' + (this.hour / 12 * 360) + 'deg)');
    this.timepicker.find('.hand.minute').css('transform', 'rotate(' + (this.minute / 60 * 360) + 'deg)');
  },
  
  _parseInput: function() {
    var time = $.trim(this.element.val());
    var match;
    var valid = false;
    this.hour = 0;
    this.minute = 0;
    this.meridiem = 0;
    if(time.length > 0 && (match = /^(\d{1,2})(?::?(\d{2}))?(?: ?([ap])\.?(?:m\.?)?)?$/i.exec(time))) {
      valid = true;
      this.hour = parseInt(match[1]);
      this.minute = match[2] ? parseInt(match[2]) : 0;
      if(match[3] && match[3].toLowerCase() === 'p') {
        this.meridiem = 1;
      }
    }
    if(this.minute >= 60) {
      this.hour += Math.floor(this.minute/60);
      this.minute = this.minute % 60;
    }
    if(this.hour >= 12) {
      this.meridiem = 1;
      this.hour = this.hour % 12;
    }
    return valid;
  },
  
  _buildHours: function() {
    if(this.display === 1) return;
    this.display = 1;
    var r = this.timepicker.find('.face').width() / 2;
    var j = r - 22;
    var bubbles = [];
    for(var hour = 0; hour < 12; ++hour) {
      var x = j * Math.sin(Math.PI * 2 * (hour / 12));
      var y = j * Math.cos(Math.PI * 2 * (hour / 12));
      var bubble = $('<div>', {'class': 'time hour bubble'})
      .text(hour == 0 ? 12 : hour)
      .css({
        marginLeft: (x + r - 15) + 'px',
        marginTop: (-y + r - 15) + 'px'
      })
      .data('value', hour);
      if(this.hour === hour) bubble.addClass('selected');
      bubbles.push(bubble);
    }
    this.timepicker.find('.time-bubbles').html(bubbles);
    this.timepicker.find('.minute.hand').removeClass('selected');
    this.timepicker.find('.minute.unit').removeClass('selected');
    this.timepicker.find('.hour.hand').addClass('selected').appendTo(this.timepicker.find('.face'));
    this.timepicker.find('.hour.unit').addClass('selected');
  },
  
  _buildMinutes: function() {
    if(this.display === 2) return;
    this.display = 2;
    var r = this.timepicker.find('.face').width() / 2;
    var j = r - 22;
    var bubbles = [];
    for(var min = 0; min < 60; min += 5) {
      var str = min < 10 ? '0' + min : String(min);
      var x = j * Math.sin(Math.PI * 2 * (min / 60));
      var y = j * Math.cos(Math.PI * 2 * (min / 60));
      var bubble = $('<div>', {'class': 'time minute bubble'})
      .text(str)
      .css({
        marginLeft: (x + r - 15) + 'px',
        marginTop: (-y + r - 15) + 'px'
      })
      .data('value', min);
      if(this.minute === min) bubble.addClass('selected');
      bubbles.push(bubble);
    }
    this.timepicker.find('.time-bubbles').html(bubbles);
    this.timepicker.find('.hour.hand').removeClass('selected');
    this.timepicker.find('.hour.unit').removeClass('selected');
    this.timepicker.find('.minute.hand').addClass('selected').appendTo(this.timepicker.find('.face'));
    this.timepicker.find('.minute.unit').addClass('selected');
  }
});


angular.module('exampleApp', [])
.directive('clock', function(){
  return {
    restrict: 'A',
    link: function (scope, el, atts ){
      el.timepicker();
    }
  };
});
      

.timepicker {
  background-color: #F2F2F2;
  position: absolute;
  color: #8C8C8C;
  border: 1px solid #B5B5B5;
  -webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.33);
  -moz-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.33);
  box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.33);
  z-index: 2147483647;
}
.timepicker .clock {
  width: 200px;
  height: 200px;
  position: relative;
  padding: 5px;
}
.timepicker .done {
  cursor: pointer;
  text-align: center;
  text-wrap: nowrap;
  line-height: 34px;
  font-size: 14px;
  display: block;
  border-top: 1px solid #DEDEDE;
}
.timepicker .done:hover {
  background-color: #DEDEDE;
  color: #848484;
}
.timepicker .meridiem {
  position: absolute;
  bottom: 5px;
  width: 32px;
  height: 32px;
  background-color: white;
  line-height: 32px;
  font-size: 14px;
  text-align: center;
  border-radius: 50%;
  cursor: pointer;
}
.timepicker .meridiem.selected {
  background-color: #D6F0F9;
  color: #6D828C;
}
.timepicker .meridiem.am {
  left: 5px;
}
.timepicker .meridiem.pm {
  right: 5px;
}
.timepicker .bubble {
  position: absolute;
  width: 32px;
  height: 32px;
  line-height: 32px;
  font-size: 14px;
  text-align: center;
  border-radius: 50%;
  cursor: pointer;
}
.timepicker .bubble:hover {
  background-color: #D6F0F9;
  color: #6D828C;
}
.timepicker .bubble.selected {
  color: #D6F0F9;
  background-color: #33b4e4;
}
.timepicker .unit {
  top: 5px;
  background-color: white;
}
.timepicker .unit.hour {
  left: 5px;
}
.timepicker .unit.minute {
  right: 5px;
}
.timepicker .face {
  width: 100%;
  height: 100%;
  background-color: white;
  border: none;
  border-radius: 50%;
  position: relative;
}
.timepicker .face:after {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  background-color: #33B4E4;
  border-radius: 50%;
  content: "";
  display: block;
}
.timepicker .hand {
  width: 0;
  height: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform-origin: 50% 100%;
  -moz-transform-origin: 50% 100%;
  -ms-transform-origin: 50% 100%;
  transform-origin: 50% 100%;
  pointer-events: none;
  background-color: #8C8C8C;
}
.timepicker .hand.minute {
  margin: -30% 0 0 -1px;
  padding: 30% 1px 0;
  border-radius: 1px 1px 0 0;
}
.timepicker .hand.hour {
  margin: -23% 0 0 -2px;
  padding: 23% 2px 0;
  border-radius: 2px 2px 0 0;
}
.timepicker .hand.selected {
  background-color: #33B4E4;
}
.timepicker .time {
  background-color: #F2F2F2;
}
body {
  margin: 10px;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="exampleApp">
  <input id="input" clock />
</div>
      

Run code


It's important to make sure jQuery is loaded before Angular in order to override jQLite (Angular's built-in shaded version of jQuery).

+3


source







All Articles