<!DOCTYPE html>
<html ng-app="angularjs-starter">
  
  <head lang="en">
    <meta charset="utf-8">
    <title>Custom Plunker</title>
    <link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.common.min.css" rel="stylesheet">
    <link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="style.css">
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
    <script src="//code.angularjs.org/1.1.4/angular.js"></script>
    <script src="http://cdn.kendostatic.com/2013.1.319/js/kendo.all.min.js"></script>
    <script>
      document.write('<base href="' + document.location + '" />');
    </script>
    <script src="http://demos.kendoui.com/content/shared/js/people.js"></script>
    <script src="app.js"></script>
    <!-- the cleanup one -->
    <script src="angular-kendo.js"></script>
  </head>
  
  <body ng-controller="MainCtrl">
    <h4>With only filtering</h4>
    <p>If you put a filter on a column, you can see that the columns has a filter applied because the filetr icon is highlighted.</p>
    <div kendo-grid data-pageable="true" data-height="250px" data-column-menu="false" data-filterable="true" data-sortable="true" kendo-source="dataSource" data-columns="{{columns}}" data-selectable="row"></div>

    
    <h4>With column menu on</h4>
    <p>If you put a filter on a column, There's no way to quickly see that a filter is applied and on which column.</p>
    <div kendo-grid data-pageable="true" data-height="250px" data-column-menu="true" data-filterable="true" data-sortable="true" kendo-source="dataSource" data-columns="{{columns}}" data-selectable="row"></div>
    
  </body>

</html>
var app = angular.module('angularjs-starter', ['kendo']);

app.controller('MainCtrl', function($scope) {
  $scope.dataSource = new kendo.data.DataSource({
        data: createRandomData(50),
        schema: {
            model: {
                fields: {
                    City: { type: "string" },
                    Title: { type: "string" },
                    BirthDate: { type: "date" },
                    Age: { type: "number" }
                }
            }
        },
        pageSize: 15
    });
  
  $scope.selection = function(e) {
    console.log(e);
    var grid = e.sender;
    var selectedRows = grid.select();
    $scope.selectedItem = [];
    for (var i = 0; i < selectedRows.length; i++) {
      $scope.selectedItem =grid.dataItem(selectedRows[i]);
    }
  };
  
  $scope.columns = [
        { field: 'City', title: 'City' },
        { field: 'Title', title: 'Title' },
        { field: 'Age', title: 'Age' }
    ];
        
});
/* CSS goes here */
(function(angular, $, kendo) {
  
  // Use strict mode because it's totally hip.
  'use strict';
  
  // Create directives and services modules.
  var directives = angular.module('kendo.directives', []);
  var services = angular.module('kendo.services', []);

  // Create a new kendo module and pass in the directives and services
  var main = angular.module('kendo', ['kendo.directives', 'kendo.services']);

  // Iterate over the kendo.ui and kendo.dataviz.ui namespace objects to get the Kendo UI widgets adding
  // them to the 'widgets' array. 
  var widgets = [];

  angular.forEach([kendo.ui, kendo.dataviz && kendo.dataviz.ui], function(namespace) {
    angular.forEach(namespace, function(value, key) {
      // add all widgets
      if( key.match(/^[A-Z]/) ){
        widgets.push("kendo" + key);
      }
    });
  });

  // Set up a value service containing the names of available Kendo UI Widgets.
  services.value('kendoWidgets', widgets);

  // Loop through the array of widget names and dynamically create a directive for each one.
  angular.forEach( widgets, function(kendoWidget) {
      directives.directive(kendoWidget, [ '$parse', '$timeout', function($parse, $timeout) {
          return {
            // Parse the directive for attributes, elements and classes.
            restrict: 'ACE',
            transclude: true,
            require: ['?ngModel', kendoWidget],
            controller: [ '$scope', '$attrs', '$element', '$transclude', function($scope, $attrs, $element, $transclude) {
              // Make the element's contents available to the kendo widget to allow creating some widgets from existing elements.
              $transclude(function(clone){
                $element.append(clone);
              });

              // TODO: add functions to allow other directives to register option decorators
            }],
            link: function(scope, element, attrs, ctrls) {
              // Widgets may be bound to the ng-model.
              var ngModel = ctrls[0],
                  widget;

              // Bind kendo widget to element only once interpolation on attributes is done.
              $timeout( function() {

                // create the kendo widget and bind it to the element.
                widget = createWidget(scope, element, attrs, ctrls[1]);

                // if kendo-refresh attribute is provided, rebind the kendo widget when 
                // the watched value changes
                if( attrs.kendoRefresh ) {
                    // watch for changes on the expression passed in the kendo-refresh attribute
                    scope.$watch(attrs.kendoRefresh, function(newValue, oldValue) {
                        if(newValue !== oldValue) {
                            // create the kendo widget and bind it to the element.
                            widget = createWidget(scope, element, attrs, ctrls[1]);
                        }
                    }, true); // watch for object equality. Use native or simple values.
                }

                // Cleanup after ourselves
                scope.$on( '$destroy', function() {
                  widget.destroy();
                });

                // if ngModel is on the element, we setup bi-directional data binding
                if (ngModel) {
                  if( !widget.value ) {
                    throw new Error('ng-model used but ' + kendoWidget + ' does not define a value accessor');
                  }
                  // Angular will invoke $render when the view needs to be updated with the view value.
                  ngModel.$render = function() {
                    // Update the widget with the view value.
                    widget.value(ngModel.$viewValue);
                  };
                  
                  // In order to be able to update the angular scope objects, we need to know when the change event is fired for a Kendo UI Widget.
                  widget.bind("change", function(e) {
                    scope.$apply(function() {
                      // Set the value on the scope to the widget value. 
                      ngModel.$setViewValue(widget.value());
                    });
                  });
                }
              });           
            }
          };

          // Create the kendo widget with gathered options
          function createWidget(scope, element, attrs, controller) {
                // Create the options object
                var options = gatherOptions(scope, element, attrs, controller);
                
                // Bind the kendo widget to the element and return a reference to the widget.
                return element[kendoWidget](options).data(kendoWidget);
          }

          // Gather the options from defaults and from attributes
          function gatherOptions(scope, element, attrs, controller) {
            // TODO: add kendoDefaults value service and use it to get a base options object?
            // var options = kendoDefaults[kendoWidget];

            var dataSource;
            // make a deep clone of the options object passed to the directive, if any.
            var options = angular.copy(scope.$eval(attrs[kendoWidget])) || {};

            // Mixin the data that's set on the element in the options
            angular.forEach( element.data(), function(value, key) {
              // Only add data items that were put as attributes since some items put by angular and kendo
              // may have circular references and Kendo's deepCopyOne doesn't like that.
              // Also make sure not to add the widget object kendo puts in the data.
              if( !!attrs[key] && key !== kendoWidget ) {
                if( angular.isObject(value) ) {
                  // Because this may be invoked on refresh (kendo-refresh) and that kendo may 
                  // have modified the object put in the element's data,
                  // we are parsing the attribute value to get the inital value of the object
                  // and not the potentially modified one. 
                  options[key] = JSON.parse(attrs[key]);
                } else {
                  // Natives are immutable so we can just put them in.
                  options[key] = value;
                }
              }
            });

            // If no dataSource was provided, 
            if( !options.dataSource ) {
              // Check if one was set in the element's data or in its ancestors.
              dataSource = element.inheritedData('$kendoDataSource');
              if( dataSource ) {
                options.dataSource = dataSource;
              }
            }

            // Add on-* event handlers to options.
            addEventHandlers(options, scope, attrs);

            // TODO: invoke controller.decorateOptions to allow other directives (or directive extensions)
            //       to modify the options before they get bound. This would provide an extention point for directives
            //       that require special processing like compiling nodes generated by kendo so that angular data binding
            //       can happen in kendo widget templates for example.
            //controller.decorateOptions(options);

            return options;

          }

          // Create an event handler function for each on-* attribute on the element and add to dest.
          function addEventHandlers(dest, scope, attrs) {
            var memo,
                eventHandlers = reduce(attrs, function(memo, attValue, att) {
              var match = att.match(/^on(.+)/), eventName, fn;
              if( match ) {
                // Lowercase the first letter to match the event name kendo expects.
                eventName = match[1].charAt(0).toLowerCase() + match[1].slice(1);
                // Parse the expression.
                fn = $parse(attValue);
                // Add a kendo event listener to the memo.
                memo[eventName] = function(e) {
                  // Make sure this gets invoked in the angularjs lifecycle.
                  scope.$apply(function() {
                    // Invoke the parsed expression with a kendoEvent local that the expression can use.
                    fn(scope, {kendoEvent: e});
                  });
                };
              }
              return memo;
            }, {});

            // mix the eventHandlers in the options object
            angular.extend(dest, eventHandlers);
          }

      }] );
  });


  // ## The kendoSource directive allows setting the Kendo UI DataSource of a widget directly from the HTML.
  directives.directive('kendoSource', [function() {
    return {
      // This is an attribute directive
      restrict: 'A',
      controller: ['$scope', '$attrs', '$element', function($scope, $attrs, $element) {
        // Set $kendoDataSource in the element's data. 3rd parties can define their own dataSource creation
        // directive and provide this data on the element.
        $element.data('$kendoDataSource', toDataSource($scope.$eval($attrs.kendoSource)));

        // Keep the element's data up-to-date with changes.
        $scope.$watch($attrs.kendoSource, function(newDS, oldDS) {
          if( newDS !== oldDS ) {
            $element.data('$kendoDataSource', toDataSource(newDS));
          }
        });
      }]
        
    };

    // Transforms the object into a Kendo UI DataSource.
    function toDataSource(ds) {
      // TODO: if ds is a $resource, wrap it in a kendo dataSource using an injected service
      return kendo.data.DataSource.create(ds);
    }

  }]);

  // Simplistic reduce function
  function reduce(obj, cb, memo) {
    angular.forEach(obj, function(value, key) {
      memo = cb.call(value, memo, value, key);
    });
    return memo;
  }

})(angular, jQuery, kendo);