<!DOCTYPE html>
<html>

<head>
  <script>
    console.clear()
  </script>

  <script>document.write('<base href="' + document.location + '" />');</script>

  <script data-require="jquery@2.2.0" data-semver="2.2.0" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.0/angular-ui-router.js"></script>
  <script src="//cdn.kendostatic.com/2013.1.319/js/kendo.all.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-messages.js"></script>
  <script src="angular.kendo.js"></script>
  

  <!--any version above ui-bootstrap-tpls-0.11.2.min.js, and the menu will not drop down when clicked -->
  <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.min.js"></script>
  
  
  <!--<script src="respond.js"></script>-->

  <script src="script.js"></script>
  <script src="textArea.js"></script>
  <script src="dataPusher.js"></script>
  <script src="textService.js"></script>
  
  <link data-require="bootstrap-css@3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />

  <link href="//cdn.kendostatic.com/2013.1.319/styles/kendo.common.min.css" rel="stylesheet" />
  <link href="//cdn.kendostatic.com/2013.1.319/styles/kendo.default.min.css" rel="stylesheet" />

  <link rel="stylesheet" href="style.css" />

</head>

<body ng-app="app">
  <div ng-controller="mainCtrl">

    <div class="urlBar">http://nohost.com{{url()}}</div>

    <div class="container">
      
      <div class="navbar">

        <div class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active">
              <a href="#">Link<span class="sr-only">(current)</span>
            </a>
            </li>
            <li>
              <a href="#">Link</a>
            </li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown">Examples<span class="caret"></span></a>
              <ul class="dropdown-menu">
                <li>
                  <a href="#/home" ng-class="selectedTabClass('home')">Home</a>
                </li>
                <li>
                  <a href="#/grid" ng-class="selectedTabClass('grid')">Grid</a>
                </li>
                <li>
                  <a href="#/textarea" ng-class="selectedTabClass('textarea')">Text Area</a>
                </li>
                <li>
                  <a href="#/ngmessages" ng-class="selectedTabClass('ngmessages')">ngMessages</a>
                </li>
                
                <li role="separator" class="divider"></li>
                <li>
                  <a href="#">Separated link</a>
                </li>
                <li role="separator" class="divider"></li>
                <li>
                  <a href="#">One more separated link</a>
                </li>
              </ul>
            </li>
          </ul>
          <form class="navbar-form navbar-left">
            <div class="form-group">
              <input type="text" class="form-control" placeholder="Search" />
            </div>
            <button type="submit" class="btn btn-default">Submit</button>
          </form>
          <ul class="nav navbar-nav navbar-right">
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Account<span class="caret"></span>
            </a>
              <ul class="dropdown-menu">
                <li>
                  <a href="#" ng-click="doLogout()">Logout</a>
                </li>
                <li>
                  <a href="#">Preferences</a>
                </li>
              </ul>
            </li>
          </ul>
        </div>
      </div>
    </div>
    <!-- /.navbar-collapse -->
    <div class="section">
      <h4>{{myIndex}}° F {{updateNotification}}</h4>
    </div>
    <div ui-view=""></div>
  </div>



</body>

</html>
//Example of 'push' service.
//uses deffered which allows 'notify' updates to the controller in addition to data push.
//in this case, we use simple incrementing index to represent data, and setTimeout simulates
//asyncronous polling operation such as api call

var app = angular.module('app', ['ui.bootstrap','ui.router','kendo.directives','ngMessages']); 

app.controller("mainCtrl", function ($scope, dataPusher, $state, $location) {
  console.log('INIT MAIN');
  $scope.url = function() { return $location.url(); }
  
  console.log($state);
  
  $scope.myIndex = 0;

  var updateTemp = function(theNextEvent) {
      //promise resolution invokes 
      theNextEvent.then(
        function(results) {
          $scope.myIndex = results.temp;
          $scope.updateNotification = '';
          updateTemp(results.nextEvent);
        },
        function(error) {
          alert('an error has occured: ' + error);
          updateTemp(dataPusher.watch());
        },
        function(update) {
          $scope.updateNotification = 'updating...';
        });
  }
  updateTemp(dataPusher.watch());
  
  $state.go('root.home');
  
  $scope.doLogout = function() {
    alert('here we would log out');
  }
  
    $scope.tab = function() {
    var tab = $state.current.name;
    var tabs = $state.current.name.split('.');
    return tabs[tabs.length - 1];
  }
  $scope.isTab = function(tabName) {
    return tabName == $scope.tab();
  }
  $scope.selectedTabClass = function(tabName) {
    return (tabName == $scope.tab()) ? 'selectedTab' : 'notSelectedTab';
  }  
});

//root abstract ==============================
app.config(function($stateProvider) {
    $stateProvider.state({
      name:'root',
      templateUrl:'root.html',
      controller:'rootCtrl',
      abstract:true
  })
}).controller('rootCtrl',function($scope, $location, $state) {
  console.log("In Root Controller");
});

//home =======================================
app.config(function($stateProvider) {
  $stateProvider.state({
      name:'root.home',
      url:'/home',
      templateUrl:'home.html',
      controller:'homeCtrl',
  })
})
.controller('homeCtrl', function($scope) {
  console.log('in home controller');
});

//Grid =========================================
app.config(function($stateProvider) {
  $stateProvider.state({
      name:'root.grid',
      url:'/grid',
      templateUrl:'grid.html',
      controller:'gridCtrl',
  })
})
.controller('gridCtrl', function($scope) {
  console.log('in grid controller');
    $scope.products = new kendo.data.DataSource({
    transport: {
      read: "products.json"
    },
    pageSize: 3
  });

  $scope.clickMe = function(i) {
      $scope.productId = i;
      $scope.modal.center().open();
    };
});



//ngMessages =========================================
app.config(function($stateProvider) {
  $stateProvider.state({
      name:'root.ngmessages',
      url:'/ngmessages',
      templateUrl:'ngMessages.html',
      controller:'ngMessagesCtrl',
  })
})
.controller('ngMessagesCtrl', function($scope) {
  console.log('in ngMessages controller');
});

/* Styles go here */

.section { padding:10px; }

.urlBar {
  color:blue;
  font-family:ariel;
  font-size:14px;
  border:solid 1px black;
  padding:3px;
  margin:5px 5px 10px 5px;
}

.navTab {
  color:gray;
}

.mymodal {
  font-size:.8em;
}

.navBar {
  border-left:solid 1px black;
}
.navBar a {
  text-decoration:none;
  border-bottom:solid 1px black;
  margin:-2px;
  padding:3px;
  border-right:solid 1px gray;
  border-top:solid 1px gray;
}

li.dropdown a.selectedTab {
  color:blue;
  font-weight:bold;
  background-color:#d8d8d8;
}
'use strict';

// declare all the module
angular.module('kendo.directives', []);
angular.module('kendo.directives', [], function($provide){

  // 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]/) && key !== 'Widget' ){
        widgets.push("kendo" + key);
      }
    });
  });

  $provide.value('kendoWidgets', widgets);

});

angular.module('kendo.directives').provider('kendoDecorator', [ function() {
  var provider = this, DECORATORS = '$kendoOptionsDecorators';

  var globalOptionsDecorators = {};

  // add an options decorator to be applied on all specified widget, not specific instances
  provider.addGlobalOptionsDecorator = function(widgetName, decorator) {
    if( angular.isString(widgetName) && angular.isFunction(decorator) ) {
      globalOptionsDecorators[widgetName] = globalOptionsDecorators[widgetName] || [];
      globalOptionsDecorators[widgetName].push(decorator);
      return function() {
          globalOptionsDecorators[widgetName].splice(globalOptionsDecorators[widgetName].indexOf(decorator), 1);
        };
    }
    throw new Error('Illegal Arguments');
  };

  // get the global list of options decorators for a specified widget. Useful for ordering
  provider.getGlobalOptionsDecorator = function(widgetName) {
    return globalOptionsDecorators[widgetName] || [];
  };

  provider.$get = [function() {

    // returns the decorators associated to the specified element
    function getOptionsDecorators(element) {
      var decorators = element.data(DECORATORS);
      if( !angular.isArray(decorators) ) {
        decorators = [];
        element.data(DECORATORS, decorators);
      }
      return decorators;
    }

    function invokeDecorators(element, decorators, opts) {
      for( var i = 0; i < decorators.length; i++ ) {
        decorators[i](element, opts);
      }
    }

    // invokes the provided element's decorators and global operators on the provided options object.
    function decorateOptions(element, widgetName, opts) {
      var i, decorators = provider.getGlobalOptionsDecorator(widgetName);
      invokeDecorators(element, decorators, opts);

      // get decorators for element
      decorators = element.data(DECORATORS) || [];
      invokeDecorators(element, decorators, opts);
    }

    function addOptionsDecorator(element, decorator) {
      if( angular.isFunction(decorator) ) {
        var decorators = getOptionsDecorators(element);
        decorators.push(decorator);
        return function() {
          decorators.splice(decorators.indexOf(decorator), 1);
        };
      }
    }

    return {
        getOptionsDecorator: getOptionsDecorators,
        addOptionsDecorator: addOptionsDecorator,
        decorateOptions: decorateOptions
      };
  }];

}]);

angular.module('kendo.directives').factory('widgetFactory', ['$parse', '$log', 'kendoDecorator', function($parse, $log, kendoDecorator) {

  // k-* attributes that should not be $parsed or $evaluated by gatherOptions
  var ignoredAttributes = {
    kDataSource: true,
    kOptions: true,
    kRebind: true
  };

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

    // make a deep clone of the options object provided by the k-options attribute, if any.
    var options = angular.element.extend(true, {}, scope.$eval(attrs.kOptions));

    // regexp for matching regular options attributes and event handler attributes
    // The first matching group will be defined only when the attribute starts by k-on- for event handlers.
    // The second matching group will contain the option name.
    var attrRE = /k(On)?([A-Z].*)/;
    // Mixin the data from the element's k-* attributes in the options
    angular.forEach(attrs, function(attValue, attName) {
      // ignore attributes that do not map to widget configuration options
      if( ignoredAttributes[attName] ) {
        return;
      }

      var match = attName.match(attrRE), optionName, fn;

      if( match ) {
        // Lowercase the first letter to match the option name kendo expects.
        optionName = match[2].charAt(0).toLowerCase() + match[2].slice(1);

        if( match[1] ) {
          // This is an event handler attribute (k-on-*)
          // Parse the expression so that it get evaluated later.
          fn = $parse(attValue);
          // Add a kendo event listener to the options.
          options[optionName] = 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});
            });
          };
        } else {
          // Evaluate the angular expression and put its result in the widget's options object.
          // Here we make a copy because the kendo widgets make changes to the objects passed in the options
          // and kendo-refresh would not be able to refresh with the initial values otherwise.
          options[optionName] = angular.copy(scope.$eval(attValue));
          if( options[optionName] === undefined && attValue.match(/^\w*$/) ) {
            // if the user put a single word as the attribute value and the expression evaluates to undefined,
            // he may have wanted to use a string literal.
            $log.warn(kendoWidget + '\'s ' + attName + ' attribute resolved to undefined. Maybe you meant to use a string literal like: \'' + attValue + '\'?');
          }
        }
      }
    });

    // The kDataSource directive sets the $kendoDataSource data on the element it is put on.
    // A datasource set in this way takes precedence over the one that could have been provided in options object passed
    // in the directive's attribute and that is used as the initial options object.
    options.dataSource = element.inheritedData('$kendoDataSource') || options.dataSource;

    // decorate options, if any decorators have been registered on this element or any global ones are registered for
    // the kendo widget
    kendoDecorator.decorateOptions(element, kendoWidget, options);

    return options;

  };

  // Create the kendo widget with gathered options
  var create = function(scope, element, attrs, kendoWidget) {

    // Create the options object
    var options = gatherOptions(scope, element, attrs, kendoWidget);

    // Bind the kendo widget to the element and return a reference to the widget.
    return element[kendoWidget](options).data(kendoWidget);
  };

  return {
    create: create
  };

}]);

angular.module('kendo.directives').factory('directiveFactory', ['widgetFactory', '$timeout', '$parse',
  function(widgetFactory, $timeout, $parse) {

    function exposeWidget(widget, scope, attrs, kendoWidget) {
      if( attrs[kendoWidget] ) {
        // expose the widget object
        var set = $parse(attrs[kendoWidget]).assign;
        if( set ) {
          // set the value of the expression to the kendo widget object to expose its api
          set(scope, widget);
        } else {
          throw new Error( kendoWidget + ' attribute used but expression in it is not assignable: ' + attrs[kendoWidget]);
        }
      }
    }

    var create = function(kendoWidget) {

      return {
        // Parse the directive for attributes and classes
        restrict: 'ACE',
        transclude: true,
        require: '?ngModel',
        scope: false,
        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);
          });

        }],

        link: function(scope, element, attrs, ngModel) {

          var widget;

          // Bind kendo widget to element only once interpolation on attributes is done.
          // Using a $timeout with no delay simply makes sure the function will be executed next in the event queue
          // after the current $digest cycle is finished. Other directives on the same element (select for example)
          // will have been processed, and interpolation will have happened on the attributes.
          $timeout( function() {

            // create the kendo widget and bind it to the element.
            widget = widgetFactory.create(scope, element, attrs, kendoWidget);
            exposeWidget(widget, scope, attrs, kendoWidget);

            // if k-rebind attribute is provided, rebind the kendo widget when
            // the watched value changes
            if( attrs.kRebind ) {
              // watch for changes on the expression passed in the k-rebind attribute
              scope.$watch(attrs.kRebind, function(newValue, oldValue) {
                if(newValue !== oldValue) {
                  // create the kendo widget and bind it to the element.
                  widget = widgetFactory.create(scope, element, attrs, kendoWidget);
                  exposeWidget(widget, scope, attrs, kendoWidget);
                }
              }, 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());
                });
              });
            }
          });
        }
      };
    };

    return {
      create: create
    };
  }
]);
(function(angular) {

  var widgets = angular.injector(['kendo.directives']).get('kendoWidgets');

  // loop through all the widgets and create a directive
  angular.forEach(widgets, function(widget) {
    angular.module('kendo.directives').directive(widget, ['directiveFactory',
      function(directiveFactory) {
        return directiveFactory.create(widget);
      }
    ]);
  });

}(angular));


// ## The kendoSource directive allows setting the Kendo UI DataSource of a widget directly from the HTML.
angular.module('kendo.directives').directive('kDataSource', [function() {

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

  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.kDataSource)));

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

}]);
angular.module('kendo.directives').directive('kendoGrid', ['$compile', 'kendoDecorator', '$parse', function($compile, kendoDecorator, $parse) {

  function dataBoundHandler(scope, element, rowDataVar) {
    var grid = element.data('kendoGrid');
    var rows = grid.tbody.children('tr');

    // Here we mimic ng-repeat in that we create a scope for each row that we can then destroy in dataBinding event.
    // Creating a scope for each row ensures you don't leak scopes when the
    // kendo widget regenerates the dom on pagination for example.
    rows.each(function(index, row) {
      var rowScope = scope.$new();
      // provide index of the row using the same $index var as ngRepeat
      rowScope.$index = index;
      // provide the data object for that row in the scope
      rowScope[rowDataVar] = grid.dataItem(row);

      // compile the row. You can now use angular templates in that row.
      $compile(row)(rowScope);
    });
  }

  function dataBindingHandler(element) {
    // find all the rows that we compiled in dataBound handler
    var rows = element.data('kendoGrid').tbody.children('tr.ng-scope');

    // here we need to destroy the scopes that we created in dataBound handler to make sure no scopes are leaked.
    rows.each(function(index, rowElement) {
        var rowScope = angular.element(rowElement).scope();
        // destroy the scope
        rowScope.$destroy();
    });
  }

  function createCompileRowsDecorator(scope, rowDataVar) {
    return function(element, options) {
      // keep a reference on the original event callbacks
      var origDataBinding = options.dataBinding;
      var origDataBound = options.dataBound;

      // The kendoGrid invokes this handler after it has created row elements for the data.
      options.dataBound = function() {
        dataBoundHandler(scope, element, rowDataVar);

        // invoke the original dataBound handler, if any
        if(angular.isFunction(origDataBound)) {
          origDataBound();
        }
      };

      // The kendoGrid invokes this handler before it creates new rows in the dom
      options.dataBinding = function() {
        dataBindingHandler(element);
        // invoke the original dataBinding handler, if any
        if(angular.isFunction(origDataBinding)) {
          origDataBinding();
        }
      };

    };
  }

  function createChangeDecorator(scope, changeExpFn) {
    return function(element, options) {
      options.change = function(e) {
        var cell, multiple, locals = { kendoEvent: e }, elems, items, columns, colIdx;
        if( angular.isString(options.selectable) ) {
          cell = options.selectable.indexOf('cell') !== -1;
          multiple = options.selectable.indexOf('multiple') !== -1;
        }

        elems = locals.selected = this.select();
        items = locals.data = [];
        columns = locals.columns = [];

        for (var i = 0; i < elems.length; i++) {
          var dataItem = this.dataItem(cell ? elems[i].parentNode : elems[i]);
          if( cell ) {
            if (angular.element.inArray(dataItem, items) < 0) {
              items.push(dataItem);
            }
            colIdx = angular.element(elems[i]).index();
            if (angular.element.inArray(colIdx, columns) < 0 ) {
              columns.push(colIdx);
            }
          } else {
            items.push(dataItem);
          }
        }

        if( !multiple ) {
          locals.data = items[0];
          locals.selected = elems[0];
        }

        // 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.
          changeExpFn(scope, locals);
        });
      };
    };
  }

  return {
    restrict: 'ACE',
    link: function(scope, element, attrs) {
      kendoDecorator.addOptionsDecorator(element, createCompileRowsDecorator(scope, 'dataItem'));

      // if k-on-change was defined, expose the selected rows/cells and not just the kendo event
      if( attrs.kOnChange ) {
        kendoDecorator.addOptionsDecorator(element, createChangeDecorator(scope, $parse(attrs.kOnChange)));
      }

    }
  };

}]);
[  
   {  
      "ProductID":1,
      "ProductName":"Chai",
      "Supplier":{  
         "SupplierID":1,
         "SupplierName":"Exotic Liquids"
      },
      "Category":{  
         "CategoryID":1,
         "CategoryName":"Beverages"
      },
      "UnitPrice":18.0,
      "UnitsInStock":39,
      "Discontinued":false
   },
   {  
      "ProductID":2,
      "ProductName":"Chang",
      "Supplier":{  
         "SupplierID":1,
         "SupplierName":"Exotic Liquids"
      },
      "Category":{  
         "CategoryID":1,
         "CategoryName":"Beverages"
      },
      "UnitPrice":19.0,
      "UnitsInStock":17,
      "Discontinued":false
   },
   {  
      "ProductID":3,
      "ProductName":"Aniseed Syrup",
      "Supplier":{  
         "SupplierID":1,
         "SupplierName":"Exotic Liquids"
      },
      "Category":{  
         "CategoryID":2,
         "CategoryName":"Condiments"
      },
      "UnitPrice":10.0,
      "UnitsInStock":13,
      "Discontinued":false
   },
   {  
      "ProductID":4,
      "ProductName":"Chef Anton\u0027s Cajun Seasoning",
      "Supplier":{  
         "SupplierID":2,
         "SupplierName":"New Orleans Cajun Delights"
      },
      "Category":{  
         "CategoryID":2,
         "CategoryName":"Condiments"
      },
      "UnitPrice":22.0,
      "UnitsInStock":53,
      "Discontinued":false
   },
   {  
      "ProductID":5,
      "ProductName":"Chef Anton\u0027s Gumbo Mix",
      "Supplier":{  
         "SupplierID":2,
         "SupplierName":"New Orleans Cajun Delights"
      },
      "Category":{  
         "CategoryID":2,
         "CategoryName":"Condiments"
      },
      "UnitPrice":21.35,
      "UnitsInStock":0,
      "Discontinued":true
   },
   {  
      "ProductID":6,
      "ProductName":"Grandma\u0027s Boysenberry Spread",
      "Supplier":{  
         "SupplierID":3,
         "SupplierName":"Grandma Kelly\u0027s Homestead"
      },
      "Category":{  
         "CategoryID":2,
         "CategoryName":"Condiments"
      },
      "UnitPrice":25.0,
      "UnitsInStock":120,
      "Discontinued":false
   },
   {  
      "ProductID":7,
      "ProductName":"Uncle Bob\u0027s Organic Dried Pears",
      "Supplier":{  
         "SupplierID":3,
         "SupplierName":"Grandma Kelly\u0027s Homestead"
      },
      "Category":{  
         "CategoryID":7,
         "CategoryName":"Produce"
      },
      "UnitPrice":30.0,
      "UnitsInStock":15,
      "Discontinued":false
   },
   {  
      "ProductID":8,
      "ProductName":"Northwoods Cranberry Sauce",
      "Supplier":{  
         "SupplierID":3,
         "SupplierName":"Grandma Kelly\u0027s Homestead"
      },
      "Category":{  
         "CategoryID":2,
         "CategoryName":"Condiments"
      },
      "UnitPrice":40.0,
      "UnitsInStock":6,
      "Discontinued":false
   },
   {  
      "ProductID":9,
      "ProductName":"Mishi Kobe Niku",
      "Supplier":{  
         "SupplierID":4,
         "SupplierName":"Tokyo Traders"
      },
      "Category":{  
         "CategoryID":6,
         "CategoryName":"Meat/Poultry"
      },
      "UnitPrice":97.0,
      "UnitsInStock":29,
      "Discontinued":true
   },
   {  
      "ProductID":10,
      "ProductName":"Ikura",
      "Supplier":{  
         "SupplierID":4,
         "SupplierName":"Tokyo Traders"
      },
      "Category":{  
         "CategoryID":8,
         "CategoryName":"Seafood"
      },
      "UnitPrice":31.0,
      "UnitsInStock":31,
      "Discontinued":false
   },
   {  
      "ProductID":11,
      "ProductName":"Queso Cabrales",
      "Supplier":{  
         "SupplierID":5,
         "SupplierName":"Cooperativa de Quesos \u0027Las Cabras\u0027"
      },
      "Category":{  
         "CategoryID":4,
         "CategoryName":"Dairy Products"
      },
      "UnitPrice":21.0,
      "UnitsInStock":22,
      "Discontinued":false
   },
   {  
      "ProductID":12,
      "ProductName":"Queso Manchego La Pastora",
      "Supplier":{  
         "SupplierID":5,
         "SupplierName":"Cooperativa de Quesos \u0027Las Cabras\u0027"
      },
      "Category":{  
         "CategoryID":4,
         "CategoryName":"Dairy Products"
      },
      "UnitPrice":38.0,
      "UnitsInStock":86,
      "Discontinued":false
   },
   {  
      "ProductID":13,
      "ProductName":"Konbu",
      "Supplier":{  
         "SupplierID":6,
         "SupplierName":"Mayumi\u0027s"
      },
      "Category":{  
         "CategoryID":8,
         "CategoryName":"Seafood"
      },
      "UnitPrice":6.0,
      "UnitsInStock":24,
      "Discontinued":false
   },
   {  
      "ProductID":14,
      "ProductName":"Tofu",
      "Supplier":{  
         "SupplierID":6,
         "SupplierName":"Mayumi\u0027s"
      },
      "Category":{  
         "CategoryID":7,
         "CategoryName":"Produce"
      },
      "UnitPrice":23.25,
      "UnitsInStock":35,
      "Discontinued":false
   },
   {  
      "ProductID":15,
      "ProductName":"Genen Shouyu",
      "Supplier":{  
         "SupplierID":6,
         "SupplierName":"Mayumi\u0027s"
      },
      "Category":{  
         "CategoryID":2,
         "CategoryName":"Condiments"
      },
      "UnitPrice":15.5,
      "UnitsInStock":39,
      "Discontinued":false
   },
   {  
      "ProductID":16,
      "ProductName":"Pavlova",
      "Supplier":{  
         "SupplierID":7,
         "SupplierName":"Pavlova, Ltd."
      },
      "Category":{  
         "CategoryID":3,
         "CategoryName":"Confections"
      },
      "UnitPrice":17.45,
      "UnitsInStock":29,
      "Discontinued":false
   },
   {  
      "ProductID":17,
      "ProductName":"Alice Mutton",
      "Supplier":{  
         "SupplierID":7,
         "SupplierName":"Pavlova, Ltd."
      },
      "Category":{  
         "CategoryID":6,
         "CategoryName":"Meat/Poultry"
      },
      "UnitPrice":39.0,
      "UnitsInStock":0,
      "Discontinued":true
   },
   {  
      "ProductID":18,
      "ProductName":"Carnarvon Tigers",
      "Supplier":{  
         "SupplierID":7,
         "SupplierName":"Pavlova, Ltd."
      },
      "Category":{  
         "CategoryID":8,
         "CategoryName":"Seafood"
      },
      "UnitPrice":62.5,
      "UnitsInStock":42,
      "Discontinued":false
   },
   {  
      "ProductID":19,
      "ProductName":"Teatime Chocolate Biscuits",
      "Supplier":{  
         "SupplierID":8,
         "SupplierName":"Specialty Biscuits, Ltd."
      },
      "Category":{  
         "CategoryID":3,
         "CategoryName":"Confections"
      },
      "UnitPrice":9.2,
      "UnitsInStock":25,
      "Discontinued":false
   },
   {  
      "ProductID":20,
      "ProductName":"Sir Rodney\u0027s Marmalade",
      "Supplier":{  
         "SupplierID":8,
         "SupplierName":"Specialty Biscuits, Ltd."
      },
      "Category":{  
         "CategoryID":3,
         "CategoryName":"Confections"
      },
      "UnitPrice":81.0,
      "UnitsInStock":40,
      "Discontinued":false
   }
]
//mocked api polling service.
//uses setTimeout to mock async api call

angular.module('app')
.service('dataPusher', function($q) {
  var index = 0;
  var temps = [70, 71, 72, 73, 75, 78, 80, 79, 75, 72];
  var nextInterval = 0;
  var initialized = false;

  var watch = function() {
    var deferred = $q.defer();

    setTimeout(function() {
      deferred.notify('');

      setTimeout(function() {
        nextInterval = Math.round(Math.random() * 5) + 5;
        index++;
        deferred.resolve({
          temp: temps[index % temps.length],
          nextEvent: watch()
        });
                        
      }, 1200);
    }, nextInterval * 1000);

    return deferred.promise;

  }
  return {
    watch: watch
  }
});
  <h1>AngularJS + kendo</h1>
  <div id="mygrid" kendo-grid k-data-source="products" k-pageable='{ "refresh": true, "pageSizes": true }' k-columns='[
                      { "field": "ProductName", "title": "Name"}, 
                      { "field": "Supplier.SupplierName", "title": "Supplier"}, 
                      { "field": "Category.CategoryName", "title": "Category" },
                      { "template": "<button class=\"k-button\" ng-click=\"clickMe(#=ProductID#)\">Delete this item</button>", "title": "..." }
                  ]' k-sortable="true" k-groupable="true" k-filterable="true">
  </div>

  <div kendo-window="modal" k-title="'Title'" k-visible="false" k-modal="true">
    Product Id clicked: {{ productId }}
  </div>
<h2>Kendo UI + Angular Example Project</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor dignissim nibh a commodo. Vestibulum aliquam nibh tortor, ac placerat libero condimentum in. Aenean quis nunc sollicitudin, fringilla ipsum sit amet, venenatis ligula. Maecenas nec neque arcu. Nullam pretium nisl a sem aliquet, non molestie lectus ultricies. Sed eget enim sit amet justo blandit dignissim id et erat. Phasellus faucibus, turpis et euismod scelerisque, tellus leo imperdiet lacus, molestie ornare erat mi at erat. Mauris ultricies lorem non nisi consectetur, at volutpat ante dictum. Nunc tempor sollicitudin urna, et dapibus neque interdum ac. Nam consequat lacus non purus ultricies, eget viverra lorem sagittis. Nullam vestibulum metus dolor, dictum malesuada quam faucibus at. Vestibulum iaculis erat et elit dignissim, at pretium diam sollicitudin. Curabitur quis felis vitae risus semper lacinia et sit amet risus. Donec tortor est, accumsan vitae volutpat id, imperdiet posuere dui. Aenean dapibus laoreet dui, eget elementum sapien ultricies at.</p>
<div>

  <div ui-view style='padding-left:25px'></div>
  
</div>
<div style='padding:10px'>

    <textarea kendo-editor
              ng-model='theText'
              k-tools="[
                  'bold',
                  'italic',
                  'undeline',
                  {
                    name: 'foreColor',
                    palette: [ '#f00', '#0f0', '#00f' ]
                  }
              ]">
    </textarea>
        
    <br/><br/>
              
    <div>
      <button ng-click="showPopup()">Populate</button>
    </div>
              
    <div class='mymodal' kendo-window="textModal" k-title="'Pre Seelcted Text'" k-visible="false" k-modal="true" k-width="400">
      <form id='theForm'>
        <h4>Select Text Please</h4>
        <div ng-repeat='text in texts'>
          <input type='radio' name="texts" id="{{text.id}}" ng-model='vm.selectedText' value="{{text.id}}"/><label for="{{text.id}}">{{text.text}}</label>
        </div>
        <br/>
        <input type='button' ng-click='select()' value='select'/>
        <input type='button' ng-click='close()' value='close'/>
      </form>
    </div>         
    
</div>
angular.module('app')
.service('textService',function() {
  return {
    getSelections: function() {
      var texts = [
        {id:0, text:"Quisque vel imperdiet orci."},
        {id:1, text:"metus arcu viverra ante, quis faucibus ex justo vel nisi."},
        {id:2, text:"Maecenas ultricies quam vel lectus convallis"},
      ];
      return texts;
    }
  }
});
<div>
  
  <br/><br/>
  
  <form name="myForm">
  <label>
    Enter text:
    <input type="email" ng-model="field" name="myField" required maxlength="15" />
  </label>
  <div ng-messages="myForm.myField.$error" role="alert">
    <div ng-message="required">Please enter a value for this field.</div>
    <div ng-message="email">This field must be a valid email address.</div>
    <div ng-message="maxlength">This field can be at most 15 characters long.</div>
  </div>
  <input type='submit' ng-click='submit()' ng-disabled='!myForm.$valid'/>
  
</form>

<br/><br/>
  <div idle-countdown="countdown" ng-init="countdown=5" class="modal-body">
   <progressbar max="5" value="5" animate="false" class="progress-striped active">You'll be logged out in {{countdown}} second(s).</progressbar>
  </div>
  
</div>
(function() {
    var app = angular.module('app');

    //TextArea =======================================
    app.config(function($stateProvider) {
        $stateProvider.state({
          name: 'root.textarea',
          url: '/textarea',
          templateUrl: 'textArea.html',
          controller: 'textAreaCtrl',
          resolve: {
            textList: function(textService) {
              return textService.getSelections();
            }
          }
        })
      })
      .controller('textAreaCtrl', function($scope, textService, textList) {
        $scope.texts = textList;
        $scope.vm = {};
        $scope.showPopup = function() {
          $scope.textModal.center().open();
        }
        $scope.select = function() {
          console.log($scope);
          $scope.theText = $scope.vm.selectedText ? textList[$scope.vm.selectedText].text : '';
          $scope.textModal.close();
        }
        $scope.close = function() {
          $scope.textModal.close();
        }
      })
  })();