[
  {
    "path": ".gitignore",
    "content": "node_modules\nbower_components"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License\n\nCopyright (c) 2015 Devin Jett\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "#Ionic Scroll Sista\n>An Ionic plugin that will hide your header and tabs while scrolling a list to give users a little more room.  This plugin was inspired by [Ionic Header Shrink](https://github.com/driftyco/ionic-ion-header-shrink) however it doesn't seem that the repo is still maintained, not to mention it doesn't support the breaking changes from Ionic beta-14.\n\n## Table of Contents\n - [Demo](#demo)\n - [Setup](#setup)\n - [Usage](#usage)\n - [NOTES](#notes)\n - [Screenshots](#screenshots)\n\n## Demo\n\n- Download my sports news app **SportScoop** on iOS/Android to see it live!! [Web Demo](http://www.sportscoopapp.com) | [iOS](https://itunes.apple.com/us/app/sportscoop/id1035164619?mt=8) | [Android](https://play.google.com/store/apps/details?id=com.coseur.sportscoop)\n\n[![SportScoop](http://www.sportscoopapp.com/assets/sportscoop_download.png)](http://www.sportscoopapp.com)\n\n- Watch the Demo video below\n\n[![Ionic Scroll Sista](http://img.youtube.com/vi/x3Htocx4acc/0.jpg)](http://www.youtube.com/watch?v=x3Htocx4acc)\n\n- Download from [Ionic View](http://view.ionic.io/) with appId: `474d3495`\n\n\nView the demo application code at demo/ for an example on how to use the filterBar.  To run the demo\nclone the ionic-scroll-sista repo, then navigate to the demo/ directory and run the following\n\n    npm install\n    bower install\n    gulp\n    \n## Setup\n\n\n#### Install\n\n`bower install ionic-scroll-sista`\n\n#### JS Imports (index.html)\n\nInclude the following JavaScript file import in your index.html.  Remember to import the ionic libraries first!\nThe example below assumes your 3rd party bower dependencies are located in the default bower_components folder.\n\n    <script src=\"bower_components/ionic-scroll-sista/dist/ionic.scroll.sista.js\"></script>\n\n#### SASS FIX for Subheader placement\n\nWhen all three (header/top tabs/subheader) are defined in the same view, Ionic doesn't position the subheader under the\ntop tabs by default.  If you wish to show all three in order Header/Top Tabs/Subheader, then you can import the\nIonic Scroll Sista SASS or CSS as shown below\n\nSASS\n    @import\n        \"path_to_bower_components/ionic/scss/ionic\",\n        \"path_to_bower_components/ionic-content-banner/scss/ionic.scroll.sista\";\n\n#### Angular Dependency (app.js)\n\nAdd `jett.ionic.scroll.sista` as a module dependency of your app module.\n\n    angular.module('Demo', ['ionic', 'jett.ionic.scroll.sista'])\n      .config(function () {..});\n\n## Usage\n\nIonic Scroll Sista is an attribute level directive that you put in your ion-content to hide the header, tabs, and/or\nsubheader while scrolling.\n\nIonic Scroll Sista includes the following behavior.\n  - Headers, Tabs, and subheaders are all supported.  Configured values tell the directive WHAT to hide\n  - Only JS scrolling supported (haven't yet tested native scrolling)\n  - The header/tabs will hide while dragging/scrolling up, and show while dragging/scrolling down.\n  - iOS header/title/buttons will fade AND scale down like Instagram\n  - Android header/title/buttons will fade only\n  - Elements that are configured to hide will slide underneath their parent.\n  - tabs/header/subheader's are reset on pull to refresh or when the active view leaves or gets close to the bottom\n    of the scroll view.\n\n### Possible Values\n\n  - `scroll-sista=\"header-tabs-subheader\"` (Default.  Same as just `scroll-sista`)\n    - For top tabs, the subheader will slide under the tabs, the tabs will slide under the header, and then the\n      header will slide out of the view.  At this point all elements are out of the view\n    - For bottom tabs, the subheader will slide under the header while the tabs slide out of the view,\n      then the header will slide out of the view.  At this point all elements are out of the view.\n\n  - `scroll-sista=\"header-tabs\"`\n    - For top tabs, the tabs will first slide under the header, then the header will slide out of the view.\n    - For bottom tabs, the tabs and header will slide out of the scroll view at the same time.\n    - If there is a subheader, the subheader will slide to the very top of the screen\n\n  - `scroll-sista=\"header-subheader\"`\n    - For top tabs, the header will first slide out of the view, then the subheader will slide under the tabs\n    - For bottom tabs or no tabs, the header and subheader will slide out of the view together\n  \n  - `scroll-sista=\"subheader-header\"`\n    - For top tabs, the subheader will first slide under the tabs, then the header will slide out of the view\n    - For bottom tabs or no tabs, the header and subheader will slide out of the view together (like header-subheader)\n  \n  - `scroll-sista=\"tabs-subheader\"`\n    - For top tabs, the subheader will slide under the tabs, then the tabs will slide under the header.\n    - For bottom tabs, the tabs and subheader will slide out of the scroll view at the same time.\n    - The header will remain at the top of the screen\n\n  - `scroll-sista=\"tabs\"`\n    - For top tabs, the tabs will slide under the header.\n    - For bottom tabs, the tabs will slide out of the view.\n    - If a subheader is present WITH top tabs, the subheader will slide up with the tabs and now be right beneath\n      the header.  If tabs are bottom, the subheader will just stay put.\n    - The header won't move and will still be at the top of the screen.\n\n  - `scroll-sista=\"subheader\"`\n    - The subheader will always slide under it's parent whether that's a header or top tabs.\n    - If tabs are available and at the bottom, they will not move.\n\n  - `scroll-sista=\"header\"`\n    - The header only will slide out of the screen.\n    - Any elements beneath the header, whether a subheader or top tabs, or top tabs AND a subheader, will slide\n      to the very top of the screen\n\n## NOTES\n\n  1   When using subheaders, make sure you add ionic's `has-subheader` to your `ion-content` as described on the Ionic\n      docs. See the demo's `tab-dash.html` for more info\n\n      <div class=\"bar bar-subheader\">\n          <h2 class=\"title\">Sub Header</h2>\n      </div>\n\n      <ion-content scroll-sista class=\"has-subheader\" delegate-handle-\"myScrollDelegate\">\n        //your list and content\n      </ion-content>\n\n  2.  If you have more than one scrolling area, define the `delegate-handle` attribute on `ion-content` so that Scroll\n      Sista picks uses the correct scroll delegate.\n\n## Screenshots\n\n<img src=\"demo/resources/screenshots/ios1.png\" align=\"left\" height=\"500\" width=\"281\" >\n<img src=\"demo/resources/screenshots/ios2.png\" align=\"left\" height=\"500\" width=\"281\" >\n<img src=\"demo/resources/screenshots/ios3.png\" align=\"left\" height=\"500\" width=\"281\" >\n\n\n<img src=\"demo/resources/screenshots/android1.png\" align=\"left\" height=\"500\" width=\"281\" >\n<img src=\"demo/resources/screenshots/android2.png\" align=\"left\" height=\"500\" width=\"281\" >\n<img src=\"demo/resources/screenshots/android3.png\" align=\"left\" height=\"500\" width=\"281\" >\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"ionic-scroll-sista\",\n  \"version\": \"1.0.7\",\n  \"description\": \"An Ionic plugin that will push your headers and tabs away while scrolling to free up more space\",\n  \"author\": \"Devin Jett <djett41@gmail.com> (https://github.com/djett41)\",\n  \"main\": [\n    \"dist/ionic.scroll.sista.js\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/djett41/ionic-scroll-sista.git\"\n  },\n  \"ignore\": [\n    \"demo\",\n    \"js\",\n    \"test\",\n    \".gitignore\",\n    \"gulpfile.js\",\n    \"LICENSE\",\n    \"package.json\",\n    \"README.md\"\n  ],\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"ionic\": \"^1.0.0-rc.0\",\n    \"angular-mocks\": \"1.4.3\"\n  },\n  \"keywords\": [\n    \"mobile\",\n    \"html5\",\n    \"ionic\",\n    \"cordova\",\n    \"phonegap\",\n    \"scroll\",\n    \"header\",\n    \"shrink\",\n    \"tabs\",\n    \"angularjs\",\n    \"angular\"\n  ],\n  \"license\": \"MIT\",\n  \"private\": false\n}\n"
  },
  {
    "path": "demo/.gitignore",
    "content": "# Specifies intentionally untracked files to ignore when using Git\n# http://git-scm.com/docs/gitignore\n\nnode_modules/\nplatforms/\nplugins/\nbower_components/\n\n.tmp/\nwww/\n.sass-cache\n*.DS_Store\n*.log\n"
  },
  {
    "path": "demo/app/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width\">\n    <title></title>\n\n    <!-- inject:app-styles:css --><!-- endinject -->\n\n\n  </head>\n  <body ng-app=\"starter\">\n    <!--\n      The nav bar that will be updated as we navigate between views.\n    -->\n    <ion-nav-bar class=\"bar-positive\">\n      <ion-nav-back-button>\n      </ion-nav-back-button>\n    </ion-nav-bar>\n    <!--\n      The views will be rendered in the <ion-nav-view> directive below\n      Templates are in the /templates folder (but you could also\n      have templates inline in this html file if you'd like).\n    -->\n    <ion-nav-view></ion-nav-view>\n\n    <!-- inject:vendor:js --><!-- endinject -->\n    <!-- inject:app:js --><!-- endinject -->\n\n    <script src=\"cordova.js\"></script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "demo/app/scripts/app.js",
    "content": "'use strict';\n// Ionic Starter App\n\n// angular.module is a global place for creating, registering and retrieving Angular modules\n// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)\n// the 2nd parameter is an array of 'requires'\n// 'starter.services' is found in services.js\n// 'starter.controllers' is found in controllers.js\nangular.module('starter', [\n  'ionic',\n  'starter.controllers',\n  'starter.services',\n  'jett.ionic.content.banner',\n  'jett.ionic.filter.bar',\n  'jett.ionic.scroll.sista'\n])\n\n.run(function($ionicPlatform) {\n  $ionicPlatform.ready(function() {\n    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard\n    // for form inputs)\n    if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {\n      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);\n      cordova.plugins.Keyboard.disableScroll(true);\n\n    }\n    if (window.StatusBar) {\n      // org.apache.cordova.statusbar required\n      StatusBar.styleLightContent();\n    }\n  });\n})\n\n.config(function($stateProvider, $urlRouterProvider) {\n\n  // Ionic uses AngularUI Router which uses the concept of states\n  // Learn more here: https://github.com/angular-ui/ui-router\n  // Set up the various states which the app can be in.\n  // Each state's controller can be found in controllers.js\n  $stateProvider\n\n  // setup an abstract state for the tabs directive\n    .state('tab', {\n    url: '/tab',\n    abstract: true,\n    templateUrl: 'templates/tabs.html'\n  })\n\n  // Each tab has its own nav history stack:\n\n  .state('tab.dash', {\n    url: '/dash',\n    views: {\n      'tab-dash': {\n        templateUrl: 'templates/tab-dash.html',\n        controller: 'DashCtrl'\n      }\n    }\n  })\n\n  .state('tab.chats', {\n      url: '/chats',\n      views: {\n        'tab-chats': {\n          templateUrl: 'templates/tab-chats.html',\n          controller: 'ChatsCtrl'\n        }\n      }\n    })\n    .state('tab.chat-detail', {\n      url: '/chats/:chatId',\n      views: {\n        'tab-chats': {\n          templateUrl: 'templates/chat-detail.html',\n          controller: 'ChatDetailCtrl'\n        }\n      }\n    })\n\n  .state('tab.account', {\n    url: '/account',\n    views: {\n      'tab-account': {\n        templateUrl: 'templates/tab-account.html',\n        controller: 'AccountCtrl'\n      }\n    }\n  });\n\n  // if none of the above states are matched, use this as the fallback\n  $urlRouterProvider.otherwise('/tab/dash');\n\n});\n"
  },
  {
    "path": "demo/app/scripts/controllers.js",
    "content": "'use strict';\n\nangular.module('starter.controllers', [])\n\n.controller('DashCtrl', function($scope, $timeout, $ionicFilterBar, $ionicContentBanner) {\n    var filterBarInstance, contentBannerInstance;\n\n    function getItems () {\n      if (filterBarInstance) {\n        filterBarInstance();\n        filterBarInstance = null;\n      }\n\n      if (contentBannerInstance) {\n        contentBannerInstance();\n        contentBannerInstance = null;\n      }\n\n      var items = [];\n      for (var x = 1; x < 50; x++) {\n        items.push({text: 'This is item number ' + x + ' which is an ' + (x % 2 === 0 ? 'EVEN' : 'ODD') + ' number.'});\n      }\n      $scope.items = items;\n    }\n\n    getItems();\n\n    $scope.showFilterBar = function () {\n      filterBarInstance = $ionicFilterBar.show({\n        items: $scope.items,\n        update: function (filteredItems) {\n          $scope.items = filteredItems;\n        }\n      });\n    };\n\n    $scope.refreshItems = function () {\n      $timeout(function () {\n        getItems();\n        $scope.$broadcast('scroll.refreshComplete');\n      }, 1000);\n    };\n\n    $scope.showBanner = function () {\n      $ionicContentBanner.show({\n        text: ['System Unavailable', 'Please try again later']\n      });\n    };\n  })\n\n.controller('ChatsCtrl', function($scope, Chats) {\n  // With the new view caching in Ionic, Controllers are only called\n  // when they are recreated or on app start, instead of every page change.\n  // To listen for when this page is active (for example, to refresh data),\n  // listen for the $ionicView.enter event:\n  //\n  //$scope.$on('$ionicView.enter', function(e) {\n  //});\n\n  $scope.chats = Chats.all();\n  $scope.remove = function(chat) {\n    Chats.remove(chat);\n  };\n})\n\n.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {\n  $scope.chat = Chats.get($stateParams.chatId);\n})\n\n.controller('AccountCtrl', function($scope) {\n  $scope.settings = {\n    enableFriends: true\n  };\n});\n"
  },
  {
    "path": "demo/app/scripts/services.js",
    "content": "'use strict';\n\nangular.module('starter.services', [])\n\n.factory('Chats', function() {\n  // Might use a resource here that returns a JSON array\n\n  // Some fake testing data\n  var chats = [{\n    id: 0,\n    name: 'Ben Sparrow',\n    lastText: 'You on your way?',\n    face: 'https://pbs.twimg.com/profile_images/514549811765211136/9SgAuHeY.png'\n  }, {\n    id: 1,\n    name: 'Max Lynx',\n    lastText: 'Hey, it\\'s me',\n    face: 'https://avatars3.githubusercontent.com/u/11214?v=3&s=460'\n  }, {\n    id: 2,\n    name: 'Adam Bradleyson',\n    lastText: 'I should buy a boat',\n    face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'\n  }, {\n    id: 3,\n    name: 'Perry Governor',\n    lastText: 'Look at my mukluks!',\n    face: 'https://pbs.twimg.com/profile_images/598205061232103424/3j5HUXMY.png'\n  }, {\n    id: 4,\n    name: 'Mike Harrington',\n    lastText: 'This is wicked good ice cream.',\n    face: 'https://pbs.twimg.com/profile_images/578237281384841216/R3ae1n61.png'\n  }, {\n    id: 5,\n    name: 'Adam Bradleyson',\n    lastText: 'I should buy a boat',\n    face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'\n  }, {\n    id: 6,\n    name: 'Perry Governor',\n    lastText: 'Look at my mukluks!',\n    face: 'https://pbs.twimg.com/profile_images/598205061232103424/3j5HUXMY.png'\n  }, {\n    id: 7,\n    name: 'Mike Harrington',\n    lastText: 'This is wicked good ice cream.',\n    face: 'https://pbs.twimg.com/profile_images/578237281384841216/R3ae1n61.png'\n  }, {\n    id: 8,\n    name: 'Adam Bradleyson',\n    lastText: 'I should buy a boat',\n    face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'\n  }, {\n    id: 9,\n    name: 'Mike Harrington',\n    lastText: 'This is wicked good ice cream.',\n    face: 'https://pbs.twimg.com/profile_images/578237281384841216/R3ae1n61.png'\n  }, {\n    id: 10,\n    name: 'Ben Sparrow',\n    lastText: 'You on your way?',\n    face: 'https://pbs.twimg.com/profile_images/514549811765211136/9SgAuHeY.png'\n  }, {\n    id: 11,\n    name: 'Max Lynx',\n    lastText: 'Hey, it\\'s me',\n    face: 'https://avatars3.githubusercontent.com/u/11214?v=3&s=460'\n  }, {\n    id: 12,\n    name: 'Adam Bradleyson',\n    lastText: 'I should buy a boat',\n    face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'\n  }, {\n    id: 13,\n    name: 'Perry Governor',\n    lastText: 'Look at my mukluks!',\n    face: 'https://pbs.twimg.com/profile_images/598205061232103424/3j5HUXMY.png'\n  }, {\n    id: 14,\n    name: 'Mike Harrington',\n    lastText: 'This is wicked good ice cream.',\n    face: 'https://pbs.twimg.com/profile_images/578237281384841216/R3ae1n61.png'\n  }, {\n    id: 15,\n    name: 'Adam Bradleyson',\n    lastText: 'I should buy a boat',\n    face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'\n  }, {\n    id: 16,\n    name: 'Perry Governor',\n    lastText: 'Look at my mukluks!',\n    face: 'https://pbs.twimg.com/profile_images/598205061232103424/3j5HUXMY.png'\n  }, {\n    id: 17,\n    name: 'Mike Harrington',\n    lastText: 'This is wicked good ice cream.',\n    face: 'https://pbs.twimg.com/profile_images/578237281384841216/R3ae1n61.png'\n  }, {\n    id: 18,\n    name: 'Adam Bradleyson',\n    lastText: 'I should buy a boat',\n    face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'\n  }, {\n    id: 19,\n    name: 'Perry Governor',\n    lastText: 'Look at my mukluks!',\n    face: 'https://pbs.twimg.com/profile_images/598205061232103424/3j5HUXMY.png'\n  }, {\n    id: 20,\n    name: 'Mike Harrington',\n    lastText: 'This is wicked good ice cream.',\n    face: 'https://pbs.twimg.com/profile_images/578237281384841216/R3ae1n61.png'\n  }];\n\n  return {\n    all: function() {\n      return chats;\n    },\n    remove: function(chat) {\n      chats.splice(chats.indexOf(chat), 1);\n    },\n    get: function(chatId) {\n      for (var i = 0; i < chats.length; i++) {\n        if (chats[i].id === parseInt(chatId)) {\n          return chats[i];\n        }\n      }\n      return null;\n    }\n  };\n});\n"
  },
  {
    "path": "demo/app/styles/main.scss",
    "content": "/************************************\n *\n *  Main Styles to compile. Here only @imports!\n *\n ************************************/\n\n@import\n  \"../../bower_components/ionic/scss/ionic\",\n  \"../../bower_components/ionic-content-banner/scss/ionic.content.banner\",\n  \"../../bower_components/ionic-filter-bar/scss/ionic.filter.bar\",\n  \"../../../scss/ionic.scroll.sista\";"
  },
  {
    "path": "demo/app/templates/chat-detail.html",
    "content": "<!--\n  This template loads for the 'tab.friend-detail' state (app.js)\n  'friend' is a $scope variable created in the FriendsCtrl controller (controllers.js)\n  The FriendsCtrl pulls data from the Friends service (service.js)\n  The Friends service returns an array of friend data\n-->\n<ion-view view-title=\"{{chat.name}}\">\n  <ion-content class=\"padding\">\n    <img ng-src=\"{{chat.face}}\" style=\"width: 64px; height: 64px\">\n    <p>\n      {{chat.lastText}}\n    </p>\n  </ion-content>\n</ion-view>\n"
  },
  {
    "path": "demo/app/templates/tab-account.html",
    "content": "<ion-view view-title=\"Account\">\n  <ion-content>\n    <ion-list>\n    <ion-toggle  ng-model=\"settings.enableFriends\">\n        Enable Friends\n    </ion-toggle>\n    </ion-list>\n  </ion-content>\n</ion-view>\n"
  },
  {
    "path": "demo/app/templates/tab-chats.html",
    "content": "<ion-view view-title=\"Chats\">\n  <ion-content scroll-sista>\n    <ion-list>\n      <ion-item class=\"item-remove-animate item-avatar item-icon-right\" ng-repeat=\"chat in chats\" type=\"item-text-wrap\" href=\"#/tab/chats/{{chat.id}}\">\n        <img ng-src=\"{{chat.face}}\">\n        <h2>{{chat.name}}</h2>\n        <p>{{chat.lastText}}</p>\n        <i class=\"icon ion-chevron-right icon-accessory\"></i>\n\n        <ion-option-button class=\"button-assertive\" ng-click=\"remove(chat)\">\n          Delete\n        </ion-option-button>\n      </ion-item>\n    </ion-list>\n  </ion-content>\n</ion-view>\n"
  },
  {
    "path": "demo/app/templates/tab-dash.html",
    "content": "<ion-view view-title=\"Ionic Scroll Sista\">\n\n  <ion-nav-buttons side=\"primary\">\n    <button class=\"button button-clear\" ng-click=\"showBanner()\">\n      Banner\n    </button>\n  </ion-nav-buttons>\n  <ion-nav-buttons side=\"secondary\">\n    <button class=\"button button-icon icon ion-ios-search-strong\" ng-click=\"showFilterBar()\">\n    </button>\n  </ion-nav-buttons>\n\n  <div class=\"bar bar-subheader\">\n    <h2 class=\"title\">Sub Header</h2>\n  </div>\n\n  <ion-content scroll-sista class=\"has-subheader\">\n\n    <ion-refresher pulling-icon=\"ion-arrow-down-b\" on-refresh=\"refreshItems()\">\n    </ion-refresher>\n\n    <ion-list>\n      <ion-item collection-repeat=\"item in items\" >\n        <p>{{item.text}}</p>\n      </ion-item>\n    </ion-list>\n\n    <div ng-if=\"items !== undefined && !items.length\" class=\"no-results\">\n      <p>No Results</p>\n    </div>\n\n  </ion-content>\n</ion-view>\n"
  },
  {
    "path": "demo/app/templates/tabs.html",
    "content": "<!--\nCreate tabs with an icon and label, using the tabs-positive style.\nEach tab's child <ion-nav-view> directive will have its own\nnavigation history that also transitions its views in and out.\n-->\n<ion-tabs class=\"tabs-icon-top tabs-color-active-positive\">\n\n  <!-- Dashboard Tab -->\n  <ion-tab title=\"Status\" icon-off=\"ion-ios-pulse\" icon-on=\"ion-ios-pulse-strong\" href=\"#/tab/dash\">\n    <ion-nav-view name=\"tab-dash\"></ion-nav-view>\n  </ion-tab>\n\n  <!-- Chats Tab -->\n  <ion-tab title=\"Chats\" icon-off=\"ion-ios-chatboxes-outline\" icon-on=\"ion-ios-chatboxes\" href=\"#/tab/chats\">\n    <ion-nav-view name=\"tab-chats\"></ion-nav-view>\n  </ion-tab>\n\n  <!-- Account Tab -->\n  <ion-tab title=\"Account\" icon-off=\"ion-ios-gear-outline\" icon-on=\"ion-ios-gear\" href=\"#/tab/account\">\n    <ion-nav-view name=\"tab-account\"></ion-nav-view>\n  </ion-tab>\n\n\n</ion-tabs>\n"
  },
  {
    "path": "demo/bower.json",
    "content": "{\n  \"name\": \"demo\",\n  \"private\": \"true\",\n  \"devDependencies\": {},\n  \"dependencies\": {\n    \"ionic\": \"^1.0.0-rc.0\",\n    \"ionic-filter-bar\": \"1.0.5\",\n    \"ionic-content-banner\": \"1.0.1\"\n  }\n}\n"
  },
  {
    "path": "demo/config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<widget id=\"com.devinjett.scroll.sista\" version=\"0.0.1\" xmlns=\"http://www.w3.org/ns/widgets\" xmlns:cdv=\"http://cordova.apache.org/ns/1.0\">\n  <name>Ionic Scroll Sista</name>\n  <description>\n        A demo application for Ionic Scroll Sista\n    </description>\n  <author email=\"hi@ionicframework\" href=\"http://ionicframework.com/\">\n      Ionic Framework Team\n    </author>\n  <content src=\"index.html\"/>\n  <access origin=\"*\"/>\n  <preference name=\"webviewbounce\" value=\"false\"/>\n  <preference name=\"UIWebViewBounce\" value=\"false\"/>\n  <preference name=\"DisallowOverscroll\" value=\"true\"/>\n  <preference name=\"android-minSdkVersion\" value=\"16\"/>\n  <preference name=\"BackupWebStorage\" value=\"none\"/>\n  <preference name=\"SplashScreen\" value=\"screen\"/>\n  <preference name=\"SplashScreenDelay\" value=\"3000\"/>\n  <feature name=\"StatusBar\">\n    <param name=\"ios-package\" value=\"CDVStatusBar\" onload=\"true\"/>\n  </feature>\n  <platform name=\"ios\">\n    <icon src=\"resources/ios/icon/icon.png\" width=\"57\" height=\"57\"/>\n    <icon src=\"resources/ios/icon/icon@2x.png\" width=\"114\" height=\"114\"/>\n    <icon src=\"resources/ios/icon/icon-40.png\" width=\"40\" height=\"40\"/>\n    <icon src=\"resources/ios/icon/icon-40@2x.png\" width=\"80\" height=\"80\"/>\n    <icon src=\"resources/ios/icon/icon-50.png\" width=\"50\" height=\"50\"/>\n    <icon src=\"resources/ios/icon/icon-50@2x.png\" width=\"100\" height=\"100\"/>\n    <icon src=\"resources/ios/icon/icon-60.png\" width=\"60\" height=\"60\"/>\n    <icon src=\"resources/ios/icon/icon-60@2x.png\" width=\"120\" height=\"120\"/>\n    <icon src=\"resources/ios/icon/icon-60@3x.png\" width=\"180\" height=\"180\"/>\n    <icon src=\"resources/ios/icon/icon-72.png\" width=\"72\" height=\"72\"/>\n    <icon src=\"resources/ios/icon/icon-72@2x.png\" width=\"144\" height=\"144\"/>\n    <icon src=\"resources/ios/icon/icon-76.png\" width=\"76\" height=\"76\"/>\n    <icon src=\"resources/ios/icon/icon-76@2x.png\" width=\"152\" height=\"152\"/>\n    <icon src=\"resources/ios/icon/icon-small.png\" width=\"29\" height=\"29\"/>\n    <icon src=\"resources/ios/icon/icon-small@2x.png\" width=\"58\" height=\"58\"/>\n    <icon src=\"resources/ios/icon/icon-small@3x.png\" width=\"87\" height=\"87\"/>\n    <splash src=\"resources/ios/splash/Default-568h@2x~iphone.png\" height=\"1136\" width=\"640\"/>\n    <splash src=\"resources/ios/splash/Default-667h.png\" height=\"1334\" width=\"750\"/>\n    <splash src=\"resources/ios/splash/Default-736h.png\" height=\"2208\" width=\"1242\"/>\n    <splash src=\"resources/ios/splash/Default-Landscape-736h.png\" height=\"1242\" width=\"2208\"/>\n    <splash src=\"resources/ios/splash/Default-Landscape@2x~ipad.png\" height=\"1536\" width=\"2048\"/>\n    <splash src=\"resources/ios/splash/Default-Landscape~ipad.png\" height=\"768\" width=\"1024\"/>\n    <splash src=\"resources/ios/splash/Default-Portrait@2x~ipad.png\" height=\"2048\" width=\"1536\"/>\n    <splash src=\"resources/ios/splash/Default-Portrait~ipad.png\" height=\"1024\" width=\"768\"/>\n    <splash src=\"resources/ios/splash/Default@2x~iphone.png\" height=\"960\" width=\"640\"/>\n    <splash src=\"resources/ios/splash/Default~iphone.png\" height=\"480\" width=\"320\"/>\n  </platform>\n  <platform name=\"android\">\n    <icon src=\"resources/android/icon/drawable-ldpi-icon.png\" density=\"ldpi\"/>\n    <icon src=\"resources/android/icon/drawable-mdpi-icon.png\" density=\"mdpi\"/>\n    <icon src=\"resources/android/icon/drawable-hdpi-icon.png\" density=\"hdpi\"/>\n    <icon src=\"resources/android/icon/drawable-xhdpi-icon.png\" density=\"xhdpi\"/>\n    <icon src=\"resources/android/icon/drawable-xxhdpi-icon.png\" density=\"xxhdpi\"/>\n    <icon src=\"resources/android/icon/drawable-xxxhdpi-icon.png\" density=\"xxxhdpi\"/>\n    <splash src=\"resources/android/splash/drawable-land-ldpi-screen.png\" density=\"land-ldpi\"/>\n    <splash src=\"resources/android/splash/drawable-land-mdpi-screen.png\" density=\"land-mdpi\"/>\n    <splash src=\"resources/android/splash/drawable-land-hdpi-screen.png\" density=\"land-hdpi\"/>\n    <splash src=\"resources/android/splash/drawable-land-xhdpi-screen.png\" density=\"land-xhdpi\"/>\n    <splash src=\"resources/android/splash/drawable-land-xxhdpi-screen.png\" density=\"land-xxhdpi\"/>\n    <splash src=\"resources/android/splash/drawable-land-xxxhdpi-screen.png\" density=\"land-xxxhdpi\"/>\n    <splash src=\"resources/android/splash/drawable-port-ldpi-screen.png\" density=\"port-ldpi\"/>\n    <splash src=\"resources/android/splash/drawable-port-mdpi-screen.png\" density=\"port-mdpi\"/>\n    <splash src=\"resources/android/splash/drawable-port-hdpi-screen.png\" density=\"port-hdpi\"/>\n    <splash src=\"resources/android/splash/drawable-port-xhdpi-screen.png\" density=\"port-xhdpi\"/>\n    <splash src=\"resources/android/splash/drawable-port-xxhdpi-screen.png\" density=\"port-xxhdpi\"/>\n    <splash src=\"resources/android/splash/drawable-port-xxxhdpi-screen.png\" density=\"port-xxxhdpi\"/>\n  </platform>\n</widget>"
  },
  {
    "path": "demo/gulpfile.js",
    "content": "'use strict';\n\nvar appName = 'starter';\n\nvar gulp = require('gulp');\nvar plugins = require('gulp-load-plugins')();\nvar del = require('del');\nvar beep = require('beepbeep');\nvar express = require('express');\nvar path = require('path');\nvar open = require('open');\nvar stylish = require('jshint-stylish');\nvar streamqueue = require('streamqueue');\nvar runSequence = require('run-sequence');\nvar ripple = require('ripple-emulator');\nvar minifyCss = require('gulp-minify-css');\nvar sass = require('gulp-sass');\n\n/**\n * Parse arguments\n */\nvar args = require('yargs')\n  .alias('e', 'emulate')\n  .alias('b', 'build')\n  .alias('r', 'run')\n  // remove all debug messages (console.logs, alerts etc) from release build\n  .alias('release', 'strip-debug')\n  .default('build', false)\n  .default('port', 9000)\n  .default('strip-debug', false)\n  .argv;\n\nvar build = !!(args.build || args.emulate || args.run);\nvar emulate = args.emulate;\nvar run = args.run;\nvar port = args.port;\nvar stripDebug = !!args.stripDebug;\nvar targetDir = path.resolve('www');\n\n// if we just use emualate or run without specifying platform, we assume iOS\n// in this case the value returned from yargs would just be true\nif (emulate === true) {\n  emulate = 'ios';\n}\nif (run === true) {\n  run = 'ios';\n}\n\n// global error handler\nvar errorHandler = function(error) {\n  if (build) {\n    throw error;\n  } else {\n    beep(2, 170);\n    plugins.util.log(error);\n  }\n};\n\n\n// clean target dir\ngulp.task('clean', function(done) {\n  del([targetDir], done);\n});\n\n// precompile .scss\ngulp.task('styles', function() {\n  return gulp.src('app/styles/main.scss')\n    .pipe(sass({ errLogToConsole: true }))\n    .pipe(minifyCss({ keepSpecialComments: 0 }))\n    .pipe(gulp.dest(path.join(targetDir, 'styles')))\n    .on('error', errorHandler);\n});\n\n\n// build templatecache, copy scripts.\n// if build: concat, minsafe, uglify and versionize\ngulp.task('scripts', function() {\n  var dest = path.join(targetDir, 'scripts');\n\n  var minifyConfig = {\n    collapseWhitespace: true,\n    collapseBooleanAttributes: true,\n    removeAttributeQuotes: true,\n    removeComments: true\n  };\n\n  // prepare angular template cache from html templates\n  // (remember to change appName var to desired module name)\n  var templateStream = gulp\n    .src('**/*.html', { cwd: 'app/templates'})\n    .pipe(plugins.angularTemplatecache('templates.js', {\n      root: 'templates/',\n      module: appName,\n      htmlmin: build && minifyConfig\n    }));\n\n  var scriptStream = gulp\n    .src(['templates.js', 'app.js', '**/*.js'], { cwd: 'app/scripts' })\n\n    .pipe(plugins.if(!build, plugins.changed(dest)));\n\n  return streamqueue({ objectMode: true }, scriptStream, templateStream)\n    .pipe(plugins.if(build, plugins.ngAnnotate()))\n    .pipe(plugins.if(stripDebug, plugins.stripDebug()))\n    .pipe(plugins.if(build, plugins.concat('app.js')))\n    .pipe(plugins.if(build, plugins.uglify()))\n    .pipe(plugins.if(build && !emulate, plugins.rev()))\n\n    .pipe(gulp.dest(dest))\n\n    .on('error', errorHandler);\n});\n\n// copy fonts\ngulp.task('fonts', function() {\n  return gulp\n    .src(['app/fonts/*.*', 'bower_components/ionic/release/fonts/*.*'])\n\n    .pipe(gulp.dest(path.join(targetDir, 'fonts')))\n\n    .on('error', errorHandler);\n});\n\n\n// copy templates\ngulp.task('templates', function() {\n  return gulp.src('app/templates/**/*.*')\n    .pipe(gulp.dest(path.join(targetDir, 'templates')))\n\n    .on('error', errorHandler);\n});\n\n// generate iconfont\ngulp.task('iconfont', function(){\n  return gulp.src('app/icons/*.svg', {\n    buffer: false\n  })\n    .pipe(plugins.iconfontCss({\n      fontName: 'ownIconFont',\n      path: 'app/icons/own-icons-template.css',\n      targetPath: '../styles/own-icons.css',\n      fontPath: '../fonts/'\n    }))\n    .pipe(plugins.iconfont({\n      fontName: 'ownIconFont'\n    }))\n    .pipe(gulp.dest(path.join(targetDir, 'fonts')))\n    .on('error', errorHandler);\n});\n\n// copy images\ngulp.task('images', function() {\n  return gulp.src('app/images/**/*.*')\n    .pipe(gulp.dest(path.join(targetDir, 'images')))\n\n    .on('error', errorHandler);\n});\n\n\n// lint js sources based on .jshintrc ruleset\ngulp.task('jsHint', function(done) {\n  return gulp\n    .src('app/scripts/**/*.js')\n    .pipe(plugins.jshint())\n    .pipe(plugins.jshint.reporter(stylish))\n\n    .on('error', errorHandler);\n  done();\n});\n\n// concatenate and minify vendor sources\ngulp.task('vendor', function() {\n  var vendorFiles = require('./vendor.json');\n\n  return gulp.src(vendorFiles)\n    .pipe(plugins.concat('vendor.js'))\n    .pipe(plugins.if(build, plugins.uglify()))\n    .pipe(plugins.if(build, plugins.rev()))\n\n    .pipe(gulp.dest(targetDir))\n\n    .on('error', errorHandler);\n});\n\n\n// inject the files in index.html\ngulp.task('index', ['jsHint', 'scripts'], function() {\n\n  // build has a '-versionnumber' suffix\n  var cssNaming = 'styles/main*';\n\n  // injects 'src' into index.html at position 'tag'\n  var _inject = function(src, tag) {\n    return plugins.inject(src, {\n      starttag: '<!-- inject:' + tag + ':{{ext}} -->',\n      read: false,\n      addRootSlash: false\n    });\n  };\n\n  // get all our javascript sources\n  // in development mode, it's better to add each file seperately.\n  // it makes debugging easier.\n  var _getAllScriptSources = function() {\n    var scriptStream = gulp.src(['scripts/app.js', 'scripts/**/*.js'], { cwd: targetDir });\n    return streamqueue({ objectMode: true }, scriptStream);\n  };\n\n  return gulp.src('app/index.html')\n    // inject css\n    .pipe(_inject(gulp.src(cssNaming, { cwd: targetDir }), 'app-styles'))\n    // inject vendor.js\n    .pipe(_inject(gulp.src('vendor*.js', { cwd: targetDir }), 'vendor'))\n    // inject app.js (build) or all js files indivually (dev)\n    .pipe(plugins.if(build,\n      _inject(gulp.src('scripts/app*.js', { cwd: targetDir }), 'app'),\n      _inject(_getAllScriptSources(), 'app')\n    ))\n\n    .pipe(gulp.dest(targetDir))\n    .on('error', errorHandler);\n});\n\ngulp.task('serve', plugins.shell.task([\n  'ionic serve --lab'\n]));\n\n// ionic emulate wrapper\ngulp.task('ionic:emulate', plugins.shell.task([\n  'ionic emulate ' + emulate + ' --livereload --consolelogs'\n]));\n\n// ionic run wrapper\ngulp.task('ionic:run', plugins.shell.task([\n  'ionic run ' + run\n]));\n\n// ionic resources wrapper\ngulp.task('icon', plugins.shell.task([\n  'ionic resources --icon'\n]));\ngulp.task('splash', plugins.shell.task([\n  'ionic resources --splash'\n]));\ngulp.task('resources', plugins.shell.task([\n  'ionic resources'\n]));\n\n// select emulator device\ngulp.task('select', plugins.shell.task([\n  './helpers/emulateios'\n]));\n\n// ripple emulator\ngulp.task('ripple', ['scripts', 'styles', 'watchers'], function() {\n\n  var options = {\n    keepAlive: false,\n    open: true,\n    port: 4400\n  };\n\n  // Start the ripple server\n  ripple.emulate.start(options);\n\n  open('http://localhost:' + options.port + '?enableripple=true');\n});\n\n\n// start watchers\ngulp.task('watchers', function() {\n  plugins.livereload.listen();\n  gulp.watch('app/styles/**/*.scss', ['styles']);\n  gulp.watch('app/fonts/**', ['fonts']);\n  gulp.watch('app/icons/**', ['iconfont']);\n  gulp.watch('app/images/**', ['images']);\n  gulp.watch('app/scripts/**/*.js', ['index']);\n  gulp.watch('../dist/*.js', ['vendor']);\n  gulp.watch('./vendor.json', ['vendor']);\n  gulp.watch('app/templates/**/*.html', ['index']);\n  gulp.watch('app/index.html', ['index']);\n  gulp.watch(targetDir + '/**')\n    .on('change', plugins.livereload.changed)\n    .on('error', errorHandler);\n});\n\n// no-op = empty function\ngulp.task('noop', function() {});\n\n// our main sequence, with some conditional jobs depending on params\ngulp.task('default', function(done) {\n  runSequence(\n    'clean',\n    'iconfont',\n    [\n      'fonts',\n      'templates',\n      'styles',\n      'images',\n      'vendor'\n    ],\n    'index',\n    build ? 'noop' : 'watchers',\n    build ? 'noop' : 'serve',\n    emulate ? ['ionic:emulate', 'watchers'] : 'noop',\n    run ? 'ionic:run' : 'noop',\n    done);\n});\n"
  },
  {
    "path": "demo/hooks/README.md",
    "content": "<!--\n#\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n#  KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n#\n-->\n# Cordova Hooks\n\nThis directory may contain scripts used to customize cordova commands. This\ndirectory used to exist at `.cordova/hooks`, but has now been moved to the\nproject root. Any scripts you add to these directories will be executed before\nand after the commands corresponding to the directory name. Useful for\nintegrating your own build systems or integrating with version control systems.\n\n__Remember__: Make your scripts executable.\n\n## Hook Directories\nThe following subdirectories will be used for hooks:\n\n    after_build/\n    after_compile/\n    after_docs/\n    after_emulate/\n    after_platform_add/\n    after_platform_rm/\n    after_platform_ls/\n    after_plugin_add/\n    after_plugin_ls/\n    after_plugin_rm/\n    after_plugin_search/\n    after_prepare/\n    after_run/\n    after_serve/\n    before_build/\n    before_compile/\n    before_docs/\n    before_emulate/\n    before_platform_add/\n    before_platform_rm/\n    before_platform_ls/\n    before_plugin_add/\n    before_plugin_ls/\n    before_plugin_rm/\n    before_plugin_search/\n    before_prepare/\n    before_run/\n    before_serve/\n    pre_package/ <-- Windows 8 and Windows Phone only.\n\n## Script Interface\n\nAll scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:\n\n* CORDOVA_VERSION - The version of the Cordova-CLI.\n* CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).\n* CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)\n* CORDOVA_HOOK - Path to the hook that is being executed.\n* CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)\n\nIf a script returns a non-zero exit code, then the parent cordova command will be aborted.\n\n\n## Writing hooks\n\nWe highly recommend writting your hooks using Node.js so that they are\ncross-platform. Some good examples are shown here:\n\n[http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)\n\n"
  },
  {
    "path": "demo/hooks/after_prepare/010_add_platform_class.js",
    "content": "#!/usr/bin/env node\n\n// Add Platform Class\n// v1.0\n// Automatically adds the platform class to the body tag\n// after the `prepare` command. By placing the platform CSS classes\n// directly in the HTML built for the platform, it speeds up\n// rendering the correct layout/style for the specific platform\n// instead of waiting for the JS to figure out the correct classes.\n\nvar fs = require('fs');\nvar path = require('path');\n\nvar rootdir = process.argv[2];\n\nfunction addPlatformBodyTag(indexPath, platform) {\n  // add the platform class to the body tag\n  try {\n    var platformClass = 'platform-' + platform;\n    var cordovaClass = 'platform-cordova platform-webview';\n\n    var html = fs.readFileSync(indexPath, 'utf8');\n\n    var bodyTag = findBodyTag(html);\n    if(!bodyTag) return; // no opening body tag, something's wrong\n\n    if(bodyTag.indexOf(platformClass) > -1) return; // already added\n\n    var newBodyTag = bodyTag;\n\n    var classAttr = findClassAttr(bodyTag);\n    if(classAttr) {\n      // body tag has existing class attribute, add the classname\n      var endingQuote = classAttr.substring(classAttr.length-1);\n      var newClassAttr = classAttr.substring(0, classAttr.length-1);\n      newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;\n      newBodyTag = bodyTag.replace(classAttr, newClassAttr);\n\n    } else {\n      // add class attribute to the body tag\n      newBodyTag = bodyTag.replace('>', ' class=\"' + platformClass + ' ' + cordovaClass + '\">');\n    }\n\n    html = html.replace(bodyTag, newBodyTag);\n\n    fs.writeFileSync(indexPath, html, 'utf8');\n\n    process.stdout.write('add to body class: ' + platformClass + '\\n');\n  } catch(e) {\n    process.stdout.write(e);\n  }\n}\n\nfunction findBodyTag(html) {\n  // get the body tag\n  try{\n    return html.match(/<body(?=[\\s>])(.*?)>/gi)[0];\n  }catch(e){}\n}\n\nfunction findClassAttr(bodyTag) {\n  // get the body tag's class attribute\n  try{\n    return bodyTag.match(/ class=[\"|'](.*?)[\"|']/gi)[0];\n  }catch(e){}\n}\n\nif (rootdir) {\n\n  // go through each of the platform directories that have been prepared\n  var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);\n\n  for(var x=0; x<platforms.length; x++) {\n    // open up the index.html file at the www root\n    try {\n      var platform = platforms[x].trim().toLowerCase();\n      var indexPath;\n\n      if(platform == 'android') {\n        indexPath = path.join('platforms', platform, 'assets', 'www', 'index.html');\n      } else {\n        indexPath = path.join('platforms', platform, 'www', 'index.html');\n      }\n\n      if(fs.existsSync(indexPath)) {\n        addPlatformBodyTag(indexPath, platform);\n      }\n\n    } catch(e) {\n      process.stdout.write(e);\n    }\n  }\n\n}\n"
  },
  {
    "path": "demo/ionic.project",
    "content": "{\n  \"name\": \"Ionic Scroll Sista\",\n  \"app_id\": \"474d3495\"\n}"
  },
  {
    "path": "demo/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"author\": \"Devin Jett <djett41@gmail.com>\",\n  \"description\": \"ionic-scroll-sista: A Demo for Ionic Scroll Sista\",\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"beepbeep\": \"^1.2.0\",\n    \"bower\": \"^1.3.3\",\n    \"connect-livereload\": \"^0.5.2\",\n    \"del\": \"^1.1.1\",\n    \"express\": \"^4.11.1\",\n    \"glob\": \"^4.3.5\",\n    \"gulp\": \"^3.8.10\",\n    \"gulp-angular-templatecache\": \"^1.5.0\",\n    \"gulp-autoprefixer\": \"^2.1.0\",\n    \"gulp-changed\": \"^1.1.1\",\n    \"gulp-concat\": \"^2.4.3\",\n    \"gulp-iconfont\": \"^1.0.0\",\n    \"gulp-iconfont-css\": \"0.0.9\",\n    \"gulp-if\": \"^1.2.5\",\n    \"gulp-inject\": \"^1.1.1\",\n    \"gulp-jshint\": \"^1.9.0\",\n    \"gulp-livereload\": \"^3.7.0\",\n    \"gulp-load-plugins\": \"^0.8.0\",\n    \"gulp-minify-css\": \"^0.3.0\",\n    \"gulp-ng-annotate\": \"^0.5.0\",\n    \"gulp-rev\": \"^3.0.0\",\n    \"gulp-ruby-sass\": \"^1.0.0-alpha.3\",\n    \"gulp-sass\": \"^1.3.3\",\n    \"gulp-shell\": \"^0.2.11\",\n    \"gulp-strip-css-comments\": \"^1.1.0\",\n    \"gulp-strip-debug\": \"^1.0.2\",\n    \"gulp-uglify\": \"^1.1.0\",\n    \"gulp-util\": \"^2.2.14\",\n    \"jshint-stylish\": \"^1.0.0\",\n    \"open\": \"0.0.5\",\n    \"ripple-emulator\": \"^0.9.28\",\n    \"run-sequence\": \"^1.0.2\",\n    \"shelljs\": \"^0.3.0\",\n    \"streamqueue\": \"^0.1.1\",\n    \"yargs\": \"^1.3.3\"\n  },\n  \"scripts\": {\n    \"gulp\": \"./node_modules/.bin/gulp\"\n  },\n  \"cordovaPlugins\": [\n    \"com.ionic.keyboard\",\n    \"cordova-plugin-whitelist\",\n    \"cordova-plugin-statusbar\"\n  ],\n  \"cordovaPlatforms\": [\n    \"android\",\n    \"ios\"\n  ]\n}\n"
  },
  {
    "path": "demo/vendor.json",
    "content": "[\n    \"bower_components/angular/angular.js\",\n    \"bower_components/angular-animate/angular-animate.js\",\n    \"bower_components/angular-sanitize/angular-sanitize.js\",\n    \"bower_components/angular-ui-router/release/angular-ui-router.js\",\n    \"bower_components/ionic/release/js/ionic.js\",\n    \"bower_components/ionic/release/js/ionic-angular.js\",\n    \"bower_components/ionic-filter-bar/dist/ionic.filter.bar.js\",\n    \"bower_components/ionic-content-banner/dist/ionic.content.banner.js\",\n    \"../dist/ionic.scroll.sista.js\"\n]\n"
  },
  {
    "path": "dist/ionic.scroll.sista.js",
    "content": "/* global angular,ionic */\n(function (angular, ionic) {\n  'use strict';\n\n  angular.module('jett.ionic.scroll.sista', ['ionic'])\n    .directive('scrollSista', ['$document', '$timeout', '$rootScope', '$ionicScrollDelegate', function($document, $timeout, $rootScope, $ionicScrollDelegate) {\n      var TRANSITION_DELAY = 400;\n      var defaultDelay = TRANSITION_DELAY * 2;\n      var defaultDuration = TRANSITION_DELAY + 'ms';\n      var scaleHeaderElements = ionic.Platform.isAndroid() ? false : true;\n\n      function getParentWithAttr (e, attrName, attrValue, depth) {\n        var attr;\n\n        depth = depth || 10;\n        while (e.parentNode && depth--) {\n          attr = e.parentNode.getAttribute(attrName);\n          if (attr && attr === attrValue) {\n            return e.parentNode;\n          }\n          e = e.parentNode;\n        }\n        return null;\n      }\n\n      return {\n        restrict: 'A',\n        link: function($scope, $element, $attr) {\n          var isNavBarTransitioning = true;\n          var body = $document[0].body;\n          var scrollDelegate = $attr.delegateHandle ? $ionicScrollDelegate.$getByHandle($attr.delegateHandle) : $ionicScrollDelegate;\n          var scrollView = scrollDelegate.getScrollView();\n\n          //coordinates\n          var y, prevY, prevScrollTop;\n          //headers\n          var cachedHeader, activeHeader, headerHeight, contentTop;\n          //subheader\n          var subHeader, subHeaderHeight;\n          //tabs\n          var tabs, tabsHeight, hasTabsTop = false, hasTabsBottom = false;\n\n          //y position that will indicate where specific elements should start and end their transition.\n          var headerStart = 0;\n          var tabsStart = 0;\n          var subheaderStart = 0;\n          var defaultEnd, headerEnd, tabsEnd, subheaderEnd;\n\n          /**\n           * translates an element along the y axis by the supplied value.  if duration is passed in,\n           * a transition duration is set\n           * @param element\n           * @param y\n           * @param duration\n           */\n          function translateY (element, y, duration) {\n            if (duration && !element.style[ionic.CSS.TRANSITION_DURATION]) {\n              element.style[ionic.CSS.TRANSITION_DURATION] = duration;\n              $timeout(function () {\n                element.style[ionic.CSS.TRANSITION_DURATION] = '';\n              }, defaultDelay, false);\n            }\n            element.style[ionic.CSS.TRANSFORM] = 'translate3d(0, ' + (-y) + 'px, 0)';\n          }\n\n          /**\n           * Initializes y and scroll variables\n           */\n          function initCoordinates () {\n            y = 0;\n            prevY = 0;\n            prevScrollTop = 0;\n          }\n\n          /**\n           * Initializes headers, tabs, and subheaders, and determines how they will transition on scroll\n           */\n          function init () {\n            var activeView;\n\n            cachedHeader = body.querySelector('[nav-bar=\"cached\"] .bar-header');\n            activeHeader = body.querySelector('[nav-bar=\"active\"] .bar-header');\n\n            if (!activeHeader) {\n              return;\n            }\n\n            headerHeight = activeHeader.offsetHeight;\n            contentTop = headerHeight;\n\n            //since some people can have nested tabs, get the last tabs\n            tabs = body.querySelectorAll('.tabs');\n            tabs = tabs[tabs.length - 1];\n            if (tabs) {\n              tabsHeight = tabs.offsetHeight;\n              if (tabs.parentNode.classList.contains('tabs-top')) {\n                hasTabsTop = true;\n                contentTop += tabsHeight;\n              } else if (tabs.parentNode.classList.contains('tabs-bottom')) {\n                hasTabsBottom = true;\n              }\n            }\n\n            //subheader\n            //since subheader is going to be nested in the active view, get the closest active view from $element and\n            activeView = getParentWithAttr($element[0], 'nav-view', 'active');\n            subHeader = activeView && activeView.querySelector('.bar-subheader');\n            if (subHeader) {\n              subHeaderHeight = subHeader.offsetHeight;\n              contentTop += subHeaderHeight;\n            }\n\n            //set default end for header/tabs elements to scroll out of the scroll view and set elements end to default\n            defaultEnd = contentTop * 2;\n            headerEnd = tabsEnd = subheaderEnd = defaultEnd;\n\n            //if tabs or subheader aren't available, set height to 0\n            tabsHeight = tabsHeight || 0;\n            subHeaderHeight = subHeaderHeight || 0;\n\n            switch($attr.scrollSista) {\n              case 'header':\n                subheaderEnd =  headerHeight;\n                tabsEnd = hasTabsTop ? headerHeight : 0;\n                break;\n              case 'header-tabs':\n                headerStart = hasTabsTop ? tabsHeight : 0;\n                subheaderEnd = hasTabsTop ? headerHeight + tabsHeight : headerHeight;\n                break;\n              case 'tabs-subheader':\n                headerEnd = 0;\n                headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight;\n                tabsStart = hasTabsTop ? subHeaderHeight : 0;\n                break;\n              case 'tabs':\n                headerEnd = 0;\n                subheaderEnd =  hasTabsTop ? tabsHeight : 0;\n                break;\n              case 'subheader':\n                headerEnd = 0;\n                tabsEnd = 0;\n                break;\n              case 'header-subheader':\n                tabsEnd = hasTabsTop ? headerHeight : 0;\n                break;\n              case 'subheader-header':\n                headerStart = subHeaderHeight;\n                tabsStart = hasTabsTop ? subHeaderHeight : 0;\n                tabsEnd = hasTabsTop ? headerHeight : 0;\n                break;\n              //defaults to header-tabs-subheader\n              default:\n                headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight;\n                tabsStart = hasTabsTop ? subHeaderHeight : 0;\n            }\n          }\n\n          /**\n           * Translates active and cached headers, and animates active children\n           * @param y\n           * @param duration\n           */\n          function translateHeaders (y, duration) {\n            var fadeAmt = Math.max(0, 1 - (y / headerHeight));\n\n            //translate active header\n            if (activeHeader) {\n              translateY(activeHeader, y, duration);\n              angular.forEach(activeHeader.children, function (child) {\n                child.style.opacity = fadeAmt;\n                if (scaleHeaderElements) {\n                  child.style[ionic.CSS.TRANSFORM] = 'scale(' + fadeAmt + ',' + fadeAmt + ')';\n                }\n              });\n            }\n\n            //translate cached header\n            if (cachedHeader) {\n              translateY(cachedHeader, y, duration);\n            }\n          }\n\n          /**\n           * Translates header, tabs, subheader elements and resets content top and/or bottom\n           * When the active view leaves, we need sync functionality to reset headers and clear\n           * @param y\n           * @param duration\n           */\n          function translateElementsSync (y, duration) {\n            var contentStyle = $element[0].style;\n            var headerY = y > headerStart ? y - headerStart : 0;\n            var tabsY, subheaderY;\n\n            //subheader\n            if (subHeader) {\n              subheaderY =  y > subheaderStart ? y - subheaderStart : 0;\n              translateY(subHeader, Math.min(subheaderEnd, subheaderY), duration);\n            }\n\n            //tabs\n            if (tabs) {\n              tabsY = Math.min(tabsEnd, y > tabsStart ? y - tabsStart : 0);\n\n              if (hasTabsBottom) {\n                tabsY = -tabsY;\n                contentStyle.bottom = Math.max(0, tabsHeight - y) + 'px';\n              }\n              translateY(tabs, tabsY, duration);\n            }\n\n            //headers\n            translateHeaders(Math.min(headerEnd, headerY), duration);\n\n            //readjust top of ion-content\n            contentStyle.top = Math.max(0, contentTop - y) + 'px';\n          }\n\n          /**\n           * Translates header, tabs, subheader elements and resets content top and/or bottom\n           * Wraps translate functionality in an animation frame request\n           * @param y\n           * @param duration\n           */\n          function translateElements (y, duration) {\n            ionic.requestAnimationFrame(function() {\n              translateElementsSync(y, duration);\n            });\n          }\n\n          //Need to reinitialize the values on refreshComplete or things will get out of wack\n          $scope.$on('scroll.refreshComplete', function () {\n            initCoordinates();\n          });\n\n          /**\n           * Before the active view leaves, reset elements, and reset the scroll container\n           */\n          $scope.$parent.$on('$ionicView.beforeLeave', function () {\n            isNavBarTransitioning = true;\n            translateElementsSync(0);\n            activeHeader = null;\n            cachedHeader = null;\n          });\n\n          /**\n           * Scroll to the top when entering to reset then scrollView scrollTop. (prevents jumping)\n           */\n          $scope.$parent.$on('$ionicView.beforeEnter', function () {\n            if (scrollView) {\n              scrollView.scrollTo(0, 0);\n            }\n          });\n\n          /**\n           * Ionic sets the active/cached nav-bar AFTER the afterEnter event is called, so we need to set a small\n           * timeout to let the nav-bar logic run.\n           */\n          $scope.$parent.$on('$ionicView.afterEnter', function () {\n            initCoordinates();\n\n            $timeout(function () {\n              init();\n              isNavBarTransitioning = false;\n            }, 20, false);\n          });\n\n          /**\n           * Called onScroll.  computes coordinates based on scroll position and translates accordingly\n           */\n          $element.bind('scroll', function (e) {\n            if (isNavBarTransitioning) {\n              return;\n            }\n            //support for jQuery event as well\n            e = e.originalEvent || e;\n\n            var duration = 0;\n            var scrollTop = e.detail.scrollTop;\n\n            y = scrollTop >= 0 ? Math.min(defaultEnd, Math.max(0, y + scrollTop - prevScrollTop)) : 0;\n\n            //if we are at the bottom, animate the header/tabs back in\n            if (scrollView.getScrollMax().top - scrollTop <= contentTop) {\n              y = 0;\n              duration = defaultDuration;\n            }\n\n            prevScrollTop = scrollTop;\n\n            //if previous and current y are the same, no need to continue\n            if (prevY === y) {\n              return;\n            }\n            prevY = y;\n\n            translateElements(y, duration);\n          });\n\n        }\n      }\n    }]);\n\n})(angular, ionic);\n"
  },
  {
    "path": "gulpfile.js",
    "content": "var gulp = require('gulp');\nvar gutil = require('gulp-util');\nvar bower = require('bower');\nvar concat = require('gulp-concat');\nvar sass = require('gulp-sass');\nvar minifyCss = require('gulp-minify-css');\nvar rename = require('gulp-rename');\nvar sh = require('shelljs');\nvar karma = require('karma').server;\nvar uglify = require('gulp-uglify');\nvar ngAnnotate = require('gulp-ng-annotate');\n\nvar karmaConf = require('./karma.conf.js');\nvar paths = {\n  sass: ['./scss/**/*.scss'],\n  js: ['js/**/*.js'],\n  dist: './dist'\n};\n\ngulp.task('default', ['karma']);\ngulp.task('dist', ['scripts']);\n\ngulp.task('scripts', function() {\n  return gulp.src(['js/ionic.scroll.sista.js'])\n    .pipe(concat('ionic.scroll.sista.js'))\n    .pipe(ngAnnotate({single_quotes: true}))\n    .pipe(gulp.dest(paths.dist))\n    .pipe(uglify())\n    .pipe(rename({ extname: '.min.js' }))\n    .pipe(gulp.dest(paths.dist));\n});\n\n\ngulp.task('sass', function(done) {\n  gulp.src('./scss/ionic.scroll.sista.scss')\n    /*\n     Since this is a plugin, we dont want to include ionic scss in dist.  Don't think there is a way to compile scss\n     using ionic vars/mixins without including it in the compiled file.\n     For now we need to manually add @import \"../bower_components/ionic/scss/ionic\"; to the scss file,\n     run this gulp task, remove ionic css in css file (inlcuding minified version), then remove the import in scss\n     */\n    .pipe(sass({ errLogToConsole: true }))\n    .pipe(gulp.dest(paths.dist))\n    .pipe(minifyCss({ keepSpecialComments: 0 }))\n    .pipe(rename({ extname: '.min.css' }))\n    .pipe(gulp.dest(paths.dist))\n    .on('end', done);\n});\n\ngulp.task('watch', function() {\n  gulp.watch(paths.sass, ['sass']);\n});\n\ngulp.task('karma', function(done) {\n  karmaConf.singleRun = true;\n  karma.start(karmaConf, done);\n});\n\ngulp.task('karma-watch', function(done) {\n  karmaConf.singleRun = false;\n  karma.start(karmaConf, done);\n});\n\ngulp.task('install', ['git-check'], function() {\n  return bower.commands.install()\n    .on('log', function(data) {\n      gutil.log('bower', gutil.colors.cyan(data.id), data.message);\n    });\n});\n\ngulp.task('git-check', function(done) {\n  if (!sh.which('git')) {\n    console.log(\n      '  ' + gutil.colors.red('Git is not installed.'),\n      '\\n  Git, the version control system, is required to download Ionic.',\n      '\\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',\n      '\\n  Once git is installed, run \\'' + gutil.colors.cyan('gulp install') + '\\' again.'\n    );\n    process.exit(1);\n  }\n  done();\n});\n"
  },
  {
    "path": "js/ionic.scroll.sista.js",
    "content": "/* global angular,ionic */\n(function (angular, ionic) {\n  'use strict';\n\n  angular.module('jett.ionic.scroll.sista', ['ionic'])\n    .directive('scrollSista', function($document, $timeout, $rootScope, $ionicScrollDelegate) {\n      var TRANSITION_DELAY = 400;\n      var defaultDelay = TRANSITION_DELAY * 2;\n      var defaultDuration = TRANSITION_DELAY + 'ms';\n      var scaleHeaderElements = ionic.Platform.isAndroid() ? false : true;\n\n      function getParentWithAttr (e, attrName, attrValue, depth) {\n        var attr;\n\n        depth = depth || 10;\n        while (e.parentNode && depth--) {\n          attr = e.parentNode.getAttribute(attrName);\n          if (attr && attr === attrValue) {\n            return e.parentNode;\n          }\n          e = e.parentNode;\n        }\n        return null;\n      }\n\n      return {\n        restrict: 'A',\n        link: function($scope, $element, $attr) {\n          var isNavBarTransitioning = true;\n          var body = $document[0].body;\n          var scrollDelegate = $attr.delegateHandle ? $ionicScrollDelegate.$getByHandle($attr.delegateHandle) : $ionicScrollDelegate;\n          var scrollView = scrollDelegate.getScrollView();\n\n          //coordinates\n          var y, prevY, prevScrollTop;\n          //headers\n          var cachedHeader, activeHeader, headerHeight, contentTop;\n          //subheader\n          var subHeader, subHeaderHeight;\n          //tabs\n          var tabs, tabsHeight, hasTabsTop = false, hasTabsBottom = false;\n\n          //y position that will indicate where specific elements should start and end their transition.\n          var headerStart = 0;\n          var tabsStart = 0;\n          var subheaderStart = 0;\n          var defaultEnd, headerEnd, tabsEnd, subheaderEnd;\n\n          /**\n           * translates an element along the y axis by the supplied value.  if duration is passed in,\n           * a transition duration is set\n           * @param element\n           * @param y\n           * @param duration\n           */\n          function translateY (element, y, duration) {\n            if (duration && !element.style[ionic.CSS.TRANSITION_DURATION]) {\n              element.style[ionic.CSS.TRANSITION_DURATION] = duration;\n              $timeout(function () {\n                element.style[ionic.CSS.TRANSITION_DURATION] = '';\n              }, defaultDelay, false);\n            }\n            element.style[ionic.CSS.TRANSFORM] = 'translate3d(0, ' + (-y) + 'px, 0)';\n          }\n\n          /**\n           * Initializes y and scroll variables\n           */\n          function initCoordinates () {\n            y = 0;\n            prevY = 0;\n            prevScrollTop = 0;\n          }\n\n          /**\n           * Initializes headers, tabs, and subheaders, and determines how they will transition on scroll\n           */\n          function init () {\n            var activeView;\n\n            cachedHeader = body.querySelector('[nav-bar=\"cached\"] .bar-header');\n            activeHeader = body.querySelector('[nav-bar=\"active\"] .bar-header');\n\n            if (!activeHeader) {\n              return;\n            }\n\n            headerHeight = activeHeader.offsetHeight;\n            contentTop = headerHeight;\n\n            //since some people can have nested tabs, get the last tabs\n            tabs = body.querySelectorAll('.tabs');\n            tabs = tabs[tabs.length - 1];\n            if (tabs) {\n              tabsHeight = tabs.offsetHeight;\n              if (tabs.parentNode.classList.contains('tabs-top')) {\n                hasTabsTop = true;\n                contentTop += tabsHeight;\n              } else if (tabs.parentNode.classList.contains('tabs-bottom')) {\n                hasTabsBottom = true;\n              }\n            }\n\n            //subheader\n            //since subheader is going to be nested in the active view, get the closest active view from $element and\n            activeView = getParentWithAttr($element[0], 'nav-view', 'active');\n            subHeader = activeView && activeView.querySelector('.bar-subheader');\n            if (subHeader) {\n              subHeaderHeight = subHeader.offsetHeight;\n              contentTop += subHeaderHeight;\n            }\n\n            //set default end for header/tabs elements to scroll out of the scroll view and set elements end to default\n            defaultEnd = contentTop * 2;\n            headerEnd = tabsEnd = subheaderEnd = defaultEnd;\n\n            //if tabs or subheader aren't available, set height to 0\n            tabsHeight = tabsHeight || 0;\n            subHeaderHeight = subHeaderHeight || 0;\n\n            switch($attr.scrollSista) {\n              case 'header':\n                subheaderEnd =  headerHeight;\n                tabsEnd = hasTabsTop ? headerHeight : 0;\n                break;\n              case 'header-tabs':\n                headerStart = hasTabsTop ? tabsHeight : 0;\n                subheaderEnd = hasTabsTop ? headerHeight + tabsHeight : headerHeight;\n                break;\n              case 'tabs-subheader':\n                headerEnd = 0;\n                headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight;\n                tabsStart = hasTabsTop ? subHeaderHeight : 0;\n                break;\n              case 'tabs':\n                headerEnd = 0;\n                subheaderEnd =  hasTabsTop ? tabsHeight : 0;\n                break;\n              case 'subheader':\n                headerEnd = 0;\n                tabsEnd = 0;\n                break;\n              case 'header-subheader':\n                tabsEnd = hasTabsTop ? headerHeight : 0;\n                break;\n              case 'subheader-header':\n                headerStart = subHeaderHeight;\n                tabsStart = hasTabsTop ? subHeaderHeight : 0;\n                tabsEnd = hasTabsTop ? headerHeight : 0;\n                break;\n              //defaults to header-tabs-subheader\n              default:\n                headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight;\n                tabsStart = hasTabsTop ? subHeaderHeight : 0;\n            }\n          }\n\n          /**\n           * Translates active and cached headers, and animates active children\n           * @param y\n           * @param duration\n           */\n          function translateHeaders (y, duration) {\n            var fadeAmt = Math.max(0, 1 - (y / headerHeight));\n\n            //translate active header\n            if (activeHeader) {\n              translateY(activeHeader, y, duration);\n              angular.forEach(activeHeader.children, function (child) {\n                child.style.opacity = fadeAmt;\n                if (scaleHeaderElements) {\n                  child.style[ionic.CSS.TRANSFORM] = 'scale(' + fadeAmt + ',' + fadeAmt + ')';\n                }\n              });\n            }\n\n            //translate cached header\n            if (cachedHeader) {\n              translateY(cachedHeader, y, duration);\n            }\n          }\n\n          /**\n           * Translates header, tabs, subheader elements and resets content top and/or bottom\n           * When the active view leaves, we need sync functionality to reset headers and clear\n           * @param y\n           * @param duration\n           */\n          function translateElementsSync (y, duration) {\n            var contentStyle = $element[0].style;\n            var headerY = y > headerStart ? y - headerStart : 0;\n            var tabsY, subheaderY;\n\n            //subheader\n            if (subHeader) {\n              subheaderY =  y > subheaderStart ? y - subheaderStart : 0;\n              translateY(subHeader, Math.min(subheaderEnd, subheaderY), duration);\n            }\n\n            //tabs\n            if (tabs) {\n              tabsY = Math.min(tabsEnd, y > tabsStart ? y - tabsStart : 0);\n\n              if (hasTabsBottom) {\n                tabsY = -tabsY;\n                contentStyle.bottom = Math.max(0, tabsHeight - y) + 'px';\n              }\n              translateY(tabs, tabsY, duration);\n            }\n\n            //headers\n            translateHeaders(Math.min(headerEnd, headerY), duration);\n\n            //readjust top of ion-content\n            contentStyle.top = Math.max(0, contentTop - y) + 'px';\n          }\n\n          /**\n           * Translates header, tabs, subheader elements and resets content top and/or bottom\n           * Wraps translate functionality in an animation frame request\n           * @param y\n           * @param duration\n           */\n          function translateElements (y, duration) {\n            ionic.requestAnimationFrame(function() {\n              translateElementsSync(y, duration);\n            });\n          }\n\n          //Need to reinitialize the values on refreshComplete or things will get out of wack\n          $scope.$on('scroll.refreshComplete', function () {\n            initCoordinates();\n          });\n\n          /**\n           * Before the active view leaves, reset elements, and reset the scroll container\n           */\n          $scope.$parent.$on('$ionicView.beforeLeave', function () {\n            isNavBarTransitioning = true;\n            translateElementsSync(0);\n            activeHeader = null;\n            cachedHeader = null;\n          });\n\n          /**\n           * Scroll to the top when entering to reset then scrollView scrollTop. (prevents jumping)\n           */\n          $scope.$parent.$on('$ionicView.beforeEnter', function () {\n            if (scrollView) {\n              scrollView.scrollTo(0, 0);\n            }\n          });\n\n          /**\n           * Ionic sets the active/cached nav-bar AFTER the afterEnter event is called, so we need to set a small\n           * timeout to let the nav-bar logic run.\n           */\n          $scope.$parent.$on('$ionicView.afterEnter', function () {\n            initCoordinates();\n\n            $timeout(function () {\n              init();\n              isNavBarTransitioning = false;\n            }, 20, false);\n          });\n\n          /**\n           * Called onScroll.  computes coordinates based on scroll position and translates accordingly\n           */\n          $element.bind('scroll', function (e) {\n            if (isNavBarTransitioning) {\n              return;\n            }\n            //support for jQuery events\n            e = e.originalEvent || e;\n\n            var duration = 0;\n            var scrollTop = e.detail.scrollTop;\n\n            y = scrollTop >= 0 ? Math.min(defaultEnd, Math.max(0, y + scrollTop - prevScrollTop)) : 0;\n\n            //if we are at the bottom, animate the header/tabs back in\n            if (scrollView.getScrollMax().top - scrollTop <= contentTop) {\n              y = 0;\n              duration = defaultDuration;\n            }\n\n            prevScrollTop = scrollTop;\n\n            //if previous and current y are the same, no need to continue\n            if (prevY === y) {\n              return;\n            }\n            prevY = y;\n\n            translateElements(y, duration);\n          });\n\n        }\n      }\n    });\n\n})(angular, ionic);\n"
  },
  {
    "path": "karma.conf.js",
    "content": "module.exports = {\n  files: [\n    'bower_components/angular/angular.js',\n    'bower_components/angular-animate/angular-animate.js',\n    'bower_components/angular-sanitize/angular-sanitize.js',\n    'bower_components/angular-ui-router/release/angular-ui-router.js',\n    'bower_components/ionic/release/js/ionic.js',\n    'bower_components/ionic/release/js/ionic-angular.js',\n    'bower_components/angular-mocks/angular-mocks.js',\n    'js/ionic.scroll.sista.js'\n  ],\n\n  frameworks: ['jasmine'],\n  reporters: ['progress'],\n  port: 9876,\n  colors: true,\n  // possible values: 'OFF', 'ERROR', 'WARN', 'INFO', 'DEBUG'\n  logLevel: 'INFO',\n  autoWatch: true,\n  captureTimeout: 60000,\n  singleRun: false,\n\n  // Start these browsers, currently available:\n  // - Chrome\n  // - ChromeCanary\n  // - Firefox\n  // - Opera (has to be installed with `npm install karma-opera-launcher`)\n  // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)\n  // - PhantomJS\n  // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)\n  browsers: ['PhantomJS']\n};"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"ionic-scroll-sista\",\n  \"version\": \"1.0.6\",\n  \"description\": \"An Ionic plugin that will push your headers and tabs away while scrolling to free up more space\",\n  \"author\": \"Devin Jett <djett41@gmail.com> (https://github.com/djett41)\",\n  \"main\": \"./dist/ionic.scroll.sista.js\",\n  \"engines\": {\n    \"node\": \"*\"\n  },\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/djett41/ionic-scroll-sista.git\"\n  },\n  \"devDependencies\": {\n    \"gulp\": \"^3.5.6\",\n    \"gulp-sass\": \"^1.3.3\",\n    \"gulp-concat\": \"^2.2.0\",\n    \"gulp-minify-css\": \"^0.3.0\",\n    \"gulp-rename\": \"^1.2.0\",\n    \"bower\": \"^1.3.3\",\n    \"gulp-ng-annotate\": \"1.1.0\",\n    \"gulp-uglify\": \"^0.2.1\",\n    \"gulp-util\": \"^2.2.14\",\n    \"shelljs\": \"^0.3.0\",\n    \"karma\": \"^0.12.23\",\n    \"karma-chrome-launcher\": \"^0.1.4\",\n    \"karma-jasmine\": \"~0.1.5\",\n    \"karma-phantomjs-launcher\": \"~0.1.2\"\n  }\n}\n"
  },
  {
    "path": "scss/ionic.scroll.sista.scss",
    "content": "//Scroll Sista\n\n//places subheader underneath top tabs.  Don't forget to import ionic scss before this file!\n.tabs-top .bar-subheader {\n  top: $bar-height + $tabs-height;\n}\n.platform-ios.platform-cordova {\n  // iOS has a status bar which sits on top of the header.\n  // Bump down everything to make room for it. However, if\n  // if its in Cordova, and set to fullscreen, then disregard the bump.\n  &:not(.fullscreen) {\n    .tabs-top .bar-subheader {\n      top: $bar-height + $tabs-height + $ios-statusbar-height;\n    }\n  }\n}"
  }
]