<!DOCTYPE html>
<html ng-app="calendarApp">
<head>
    <link rel="stylesheet" href="http://code.ionicframework.com/1.0.0-beta.6/css/ionic.css" />
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.0.2/fullcalendar.css" />
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.7.0/moment.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.0.2/fullcalendar.min.js"></script>
    <script src="http://code.ionicframework.com/1.0.0-beta.11/js/ionic.bundle.js"></script>
    <script src="uicalendar.js"></script>
    <script src="script.js"></script>
    <style>
    
    .fc-agenda .fc-agenda-axis{
    	width: 60px!important;
    	font-size: 125%!important;
    }
    .fc-event-time{padding-top: 3px;padding-bottom: 3px}
    .fc-agenda-slots td div, .fc-agenda-slots tr{
    	height: 50px!important
    }
    </style>
  </head>
  <body disable-tap>
  <ion-nav-view></ion-nav-view>
  <script id="home-content.html" type="text/ng-template">
    <ion-nav-view name="menuContent" animation="slide-right-left"></ion-nav-view>
  </script>
  <script id="calendar.html" type="text/ng-template">
    <ion-view >
    <ion-nav-bar>
     <h1 class="title"><b>Calendar Scroll Issue</b></h1>
    </ion-nav-bar>
    <ion-content scroll="true" has-bouncing="false" class="showScroll">
            <div class="row">
            	<div class="col col-100" >
              <div scroll="true"  ui-calendar="uiConfig" class="calendar target" ng-model="eventSource" id="dayCalendar" calendar="dayCalendar"></div>
              </div>
             </div>
     </ion-content>
    </ion-view>
  </script>
  </body>
</html>
var myApp = angular.module('calendarApp', ['ionic', 'ui.calendar']);
myApp.config(['$stateProvider', '$urlRouterProvider',
 function($stateProvider, $urlRouterProvider) {
  $stateProvider
   .state('home', {
    url: '/home',
    "abstract": true,
    templateUrl: 'home-content.html'
   })
   .state('home.calendar', {
    url: '/calendar',
    views: {
     'menuContent': {
      templateUrl: 'calendar.html',
      controller: 'CalendarController'
     }
    }
   });
  $urlRouterProvider.otherwise('/home/calendar');
 }
]);





myApp.controller('CalendarController', ['$scope',
 function($scope) {
  $scope.eventSource = [];
  $scope.onSelect = function(start, end) {
   console.log("Event select fired");
  };
  $scope.eventClick = function(event, allDay, jsEvent, view) {
   alert("Event clicked");
  };
  $scope.uiConfig = {
   defaultView: 'agendaDay',
   disableDragging: true,
   allDaySlot: false,
   selectable: true,
   unselectAuto: true,
   selectHelper: true,
   editable: false,
   maxTime: "21:00:00",
   minTime: "8:00:00",
   eventDurationEditable: false, // disabling will show resize
   columnFormat: {
    week: 'dd-MM-yyyy',
    day: 'D-MMM-YYYY'
   },
   height: 1550,
   maxTime: "21:00:00",
   minTime: "8:00:00",
   eventDurationEditable: false, // disabling will show resize
   columnFormat: {
    week: 'dd-MM-yyyy',
    day: 'D-MMM-YYYY'
   },
   titleFormat: {
    day: 'dd-MM-yyyy'
   },
   axisFormat: 'H:mm',
   weekends: true,
   header: {
    left: 'prev',
    center: '',
    right: 'next'
   },
   select: $scope.onSelect,
   eventClick: $scope.eventClick,
   events: [{
    "id": "8",
    "title": "Adam Scott",
    "start": "2014-08-20 10:30:00",
    "end": "2014-08-20 12:00:00",
    "allDay": false,
    "color": "#734187"
   }]
  };

 }
])

.directive('disableTap', function($timeout) {
 return {
   link: function() {

     $timeout(function() {
       var tab = document.getElementsByClassName('fc-widget-content');

       for (i = 0; i < tab.length; ++i) {
  tab[i].setAttribute('data-tap-disabled', 'true')
   console.log(tab[i]);
}
        },500);
   }
 };
});













/*
*  AngularJs Fullcalendar Wrapper for the JQuery FullCalendar
*  API @ http://arshaw.com/fullcalendar/
*
*  Angular Calendar Directive that takes in the [eventSources] nested array object as the ng-model and watches it deeply changes.
*       Can also take in multiple event urls as a source object(s) and feed the events per view.
*       The calendar will watch any eventSource array and update itself when a change is made.
*
*/

angular.module('ui.calendar', [])
  .constant('uiCalendarConfig', {})
  .controller('uiCalendarCtrl', ['$scope', '$timeout', function($scope, $timeout){

      var sourceSerialId = 1,
          eventSerialId = 1,
          sources = $scope.eventSources,
          extraEventSignature = $scope.calendarWatchEvent ? $scope.calendarWatchEvent : angular.noop,

          wrapFunctionWithScopeApply = function(functionToWrap){
              var wrapper;

              if (functionToWrap){
                  wrapper = function(){
                      // This happens outside of angular context so we need to wrap it in a timeout which has an implied apply.
                      // In this way the function will be safely executed on the next digest.

                      var args = arguments;
                      $timeout(function(){
                          functionToWrap.apply(this, args);
                      });
                  };
              }

              return wrapper;
          };

      this.eventsFingerprint = function(e) {
        if (!e.__uiCalId) {
          e.__uiCalId = eventSerialId++;
        }
        // This extracts all the information we need from the event. http://jsperf.com/angular-calendar-events-fingerprint/3
        return "" + e.__uiCalId + (e.id || '') + (e.title || '') + (e.url || '') + (+e.start || '') + (+e.end || '') +
          (e.allDay || '') + (e.className || '') + extraEventSignature(e) || '';
      };

      this.sourcesFingerprint = function(source) {
          return source.__id || (source.__id = sourceSerialId++);
      };

      this.allEvents = function() {
        // return sources.flatten(); but we don't have flatten
        var arraySources = [];
        for (var i = 0, srcLen = sources.length; i < srcLen; i++) {
          var source = sources[i];
          if (angular.isArray(source)) {
            // event source as array
            arraySources.push(source);
          } else if(angular.isObject(source) && angular.isArray(source.events)){
            // event source as object, ie extended form
            var extEvent = {};
            for(var key in source){
              if(key !== '_uiCalId' && key !== 'events'){
                 extEvent[key] = source[key];
              }
            }
            for(var eI = 0;eI < source.events.length;eI++){
              angular.extend(source.events[eI],extEvent);
            }
            arraySources.push(source.events);
          }
        }

        return Array.prototype.concat.apply([], arraySources);
      };

      // Track changes in array by assigning id tokens to each element and watching the scope for changes in those tokens
      // arguments:
      //  arraySource array of function that returns array of objects to watch
      //  tokenFn function(object) that returns the token for a given object
      this.changeWatcher = function(arraySource, tokenFn) {
        var self;
        var getTokens = function() {
          var array = angular.isFunction(arraySource) ? arraySource() : arraySource;
          var result = [], token, el;
          for (var i = 0, n = array.length; i < n; i++) {
            el = array[i];
            token = tokenFn(el);
            map[token] = el;
            result.push(token);
          }
          return result;
        };
        // returns elements in that are in a but not in b
        // subtractAsSets([4, 5, 6], [4, 5, 7]) => [6]
        var subtractAsSets = function(a, b) {
          var result = [], inB = {}, i, n;
          for (i = 0, n = b.length; i < n; i++) {
            inB[b[i]] = true;
          }
          for (i = 0, n = a.length; i < n; i++) {
            if (!inB[a[i]]) {
              result.push(a[i]);
            }
          }
          return result;
        };

        // Map objects to tokens and vice-versa
        var map = {};

        var applyChanges = function(newTokens, oldTokens) {
          var i, n, el, token;
          var replacedTokens = {};
          var removedTokens = subtractAsSets(oldTokens, newTokens);
          for (i = 0, n = removedTokens.length; i < n; i++) {
            var removedToken = removedTokens[i];
            el = map[removedToken];
            delete map[removedToken];
            var newToken = tokenFn(el);
            // if the element wasn't removed but simply got a new token, its old token will be different from the current one
            if (newToken === removedToken) {
              self.onRemoved(el);
            } else {
              replacedTokens[newToken] = removedToken;
              self.onChanged(el);
            }
          }

          var addedTokens = subtractAsSets(newTokens, oldTokens);
          for (i = 0, n = addedTokens.length; i < n; i++) {
            token = addedTokens[i];
            el = map[token];
            if (!replacedTokens[token]) {
              self.onAdded(el);
            }
          }
        };
        return self = {
          subscribe: function(scope, onChanged) {
            scope.$watch(getTokens, function(newTokens, oldTokens) {
              if (!onChanged || onChanged(newTokens, oldTokens) !== false) {
                applyChanges(newTokens, oldTokens);
              }
            }, true);
          },
          onAdded: angular.noop,
          onChanged: angular.noop,
          onRemoved: angular.noop
        };
      };

      this.getFullCalendarConfig = function(calendarSettings, uiCalendarConfig){
          var config = {};

          angular.extend(config, uiCalendarConfig);
          angular.extend(config, calendarSettings);
         
          angular.forEach(config, function(value,key){
            if (typeof value === 'function'){
              config[key] = wrapFunctionWithScopeApply(config[key]);
            }
          });

          return config;
      };
  }])
  .directive('uiCalendar', ['uiCalendarConfig', '$locale', function(uiCalendarConfig, $locale) {
    // Configure to use locale names by default
    var tValues = function(data) {
      // convert {0: "Jan", 1: "Feb", ...} to ["Jan", "Feb", ...]
      var r, k;
      r = [];
      for (k in data) {
        r[k] = data[k];
      }
      return r;
    };
    var dtf = $locale.DATETIME_FORMATS;
    uiCalendarConfig = angular.extend({
      monthNames: tValues(dtf.MONTH),
      monthNamesShort: tValues(dtf.SHORTMONTH),
      dayNames: tValues(dtf.DAY),
      dayNamesShort: tValues(dtf.SHORTDAY)
    }, uiCalendarConfig || {});

    return {
      restrict: 'A',
      scope: {eventSources:'=ngModel',calendarWatchEvent: '&'},
      controller: 'uiCalendarCtrl',
      link: function(scope, elm, attrs, controller) {

        var sources = scope.eventSources,
            sourcesChanged = false,
            eventSourcesWatcher = controller.changeWatcher(sources, controller.sourcesFingerprint),
            eventsWatcher = controller.changeWatcher(controller.allEvents, controller.eventsFingerprint),
            options = null;

        function getOptions(){
          var calendarSettings = attrs.uiCalendar ? scope.$parent.$eval(attrs.uiCalendar) : {},
              fullCalendarConfig;

          fullCalendarConfig = controller.getFullCalendarConfig(calendarSettings, uiCalendarConfig);

          options = { eventSources: sources };
          angular.extend(options, fullCalendarConfig);

          var options2 = {};
          for(var o in options){
            if(o !== 'eventSources'){
              options2[o] = options[o];
            }
          }
          return JSON.stringify(options2);
        }

        scope.destroy = function(){
          if(attrs.calendar) {
            scope.calendar = scope.$parent[attrs.calendar] =  elm.html('');
          } else {
            scope.calendar = elm.html('');
          }
        };

        scope.init = function(){
          scope.calendar.fullCalendar(options);
        };

        eventSourcesWatcher.onAdded = function(source) {
          scope.calendar.fullCalendar('addEventSource', source);
          sourcesChanged = true;
        };

        eventSourcesWatcher.onRemoved = function(source) {
          scope.calendar.fullCalendar('removeEventSource', source);
          sourcesChanged = true;
        };

        eventsWatcher.onAdded = function(event) {
          scope.calendar.fullCalendar('renderEvent', event);
        };

        eventsWatcher.onRemoved = function(event) {
          scope.calendar.fullCalendar('removeEvents', function(e) { return e === event; });
        };

        eventsWatcher.onChanged = function(event) {
          scope.calendar.fullCalendar('updateEvent', event);
        };

        eventSourcesWatcher.subscribe(scope);
        eventsWatcher.subscribe(scope, function(newTokens, oldTokens) {
          if (sourcesChanged === true) {
            sourcesChanged = false;
            // prevent incremental updates in this case
            return false;
          }
        });

        scope.$watch(getOptions, function(newO,oldO){
            scope.destroy();
            scope.init();
        });
      }
    };
}]);