<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
<title></title>
<link data-require="ionic@1.0.0" data-semver="1.0.0" rel="stylesheet" href="https://code.ionicframework.com/1.0.0/css/ionic.css" />
<link rel="stylesheet" href="style.css" />
<script data-require="ionic@1.0.0-beta.14" data-semver="1.0.0-beta.14" src="https://code.ionicframework.com/1.0.0/js/ionic.bundle.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<!--script src="cordova.js"></script-->
<script src="app.js"></script>
<script src="header_shrink.js"></script>
<script src="search_panel.js"></script>
</head>
<body ng-app="starter" ng-cloak ng-controller="AppController as vm">
<ion-pane>
<div header-shrink-group>
<ion-header-bar class="bar-positive">
<div class="buttons">
<button class="button button-icon ion-navicon"></button>
</div>
<h1 class="title" ng-cloak>Shrinkable Headers</h1>
</ion-header-bar>
<search-panel duration="0.4" dst-y="-210">
<div id="search-box" class="bar item-input-inset">
<div class="item-input-wrapper">
<i class="icon ion-ios7-search placeholder-icon"></i>
<input type="search" placeholder="Please input keyword" ng-model="vm.keyword">
<i class="icon ion-ios7-close-empty" ng-click="vm.clearKeyword()"></i>
</div>
</div>
<ion-checkbox ng-disabled="{{$parent.isDisabled}}" ng-repeat="item in vm.items" ng-model="item.checked" ng-checked="item.checked" ng-change="vm.change()">
{{item.text}}
</ion-checkbox>
<div class="padding">
<button class="button button-block button-positive" ng-click="vm.toggle()">
Go
</button>
<div ng-click="vm.toggle()" class="row”>
<div class="col" >Condition: {{vm.condStr}} {{vm.keyword}} ( here is search panel)</div>
</div>
</div>
</search-panel>
</div>
<ion-content header-shrink header-shrink-len="48" scroll-event-interval="5">
<div class="list card">
<div class="item">
<div style="height: 100px;"></div>
<p>tap above search panel, its position is back</p>
<div style="height: 100px;"></div>
</div>
<div class="item">
<div style="height: 100px;"></div>
<p>Once scrolling happen, search panel is hidden</p>
<div style="height: 100px;"></div>
</div>
<div class="item">
<div style="height: 100px;"></div>
<p>more scrolling, header is shrinking</p>
<div style="height: 100px;"></div>
</div>
</div>
</ion-content>
</ion-pane>
</body>
</html>
.bar-header {
height: 48px !important;
z-index: 3;
}
.bar-header > * {
margin-top: 1px !important;
}
.searchpanel-border {
background-color: #ffffff;
border: 2px solid #ddd;
box-shadow: 0 3px 2px -2px #777;
margin-top: 44px;
position: absolute;
width : 100%;
z-index: 2;
}
.searchpanel-border:before {
content: "";
position: absolute;
bottom: -11px;
left: 50%;
margin-left: -11px;
width: 0;
height: 0;
border-top: 11px solid #ddd;
border-left: 11px solid transparent;
border-right: 11px solid transparent;
}
.searchpanel-border:after {
content: "";
position: absolute;
bottom: -9px;
left: 50%;
margin-left: -11px;
width: 0;
height: 0;
border-top: 11px solid #fff;
border-left: 11px solid transparent;
border-right: 11px solid transparent;
}
ion-content {
z-index : -1;
}
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('starter', [
'ionic',
'starter.directive',
'starter.controller'
])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
});
angular.module('starter.controller',[])
.controller('AppController',AppController);
AppController.$inject = ['$scope','searchPanelDelegate'];
function AppController($scope,searchPanelDelegate){
var vm = this;
vm.keyword = '';
vm.clearKeyword = function() {
vm.keyword = '';
};
vm.toggle = function() {
searchPanelDelegate.togglePanel();
},
vm.items = [
{ text: 'option1', checked: false},
{ text: 'option2', checked: false},
];
vm.condStr = '';
vm.change = function() {
vm.condStr = '';
angular.forEach(vm.items,function(item){
console.log(item.text+','+item.checked);
if(item.checked)
vm.condStr += ' ,' + item.text;
});
};
}
shrinking header + custom ionic search panel
https://github.com/noritamago/ionic-custom-component-sample
// The MIT License (MIT)
// Copyright (c) 2014 Drifty
// https://github.com/driftyco/ionic-ion-header-shrink/blob/master/LICENSE
//
angular
.module('starter.directive', [])
.directive('headerShrinkGroup', headerShrinkGroup)
.directive('headerShrink', headerShrink);
headerShrink.$inject = ['$document','searchPanelDelegate'];
function headerShrinkGroup() {
return {
restrict : 'A',
template : '<div class="header-shrink-group" ng-transclude></div>',
transclude : true
};
}
function headerShrink($document, searchPanelDelegate) {
var fadeAmt;
var min;
var group = $document[0].body.querySelector('.header-shrink-group');
var shrink = function(header, content, amt, max) {
amt = Math.min(min, amt);
fadeAmt = 1 - amt / min;
ionic.requestAnimationFrame(function() {
if(group) {
group.style[ionic.CSS.TRANSFORM] = 'translate3d(0, -' + amt + 'px, 0)';
searchPanelDelegate.togglePanelIfOpen();
} else {
header.style[ionic.CSS.TRANSFORM] = 'translate3d(0, -' + amt + 'px, 0)';
}
for(var i = 0, j = header.children.length; i < j; i++) {
header.children[i].style.opacity = fadeAmt;
}
});
};
return {
restrict: 'A',
link: link
};
function link($scope, $element, $attr) {
var starty = $scope.$eval($attr.headerShrink) || 0;
var shrinkAmt;
min = $scope.$eval($attr.headerShrinkLen) || 24;
var header = $document[0].body.querySelector('.bar-header');
var headerHeight = header.offsetHeight;
$element.bind('scroll', function(e) {
var scrollTop = null;
if(e.detail){
scrollTop = e.detail.scrollTop;
}else if(e.target){
scrollTop = e.target.scrollTop;
}
if(scrollTop > starty){
// Start shrinking
shrinkAmt = headerHeight - Math.max(0, (starty + headerHeight) - scrollTop);
shrink(header, $element[0], shrinkAmt, headerHeight);
} else {
shrink(header, $element[0], 0, headerHeight);
}
});
}
}
angular
.module('starter.directive')
.constant('ionic',window.ionic)
.directive('searchPanel', searchPanel)
.factory('searchPanelDelegate',searchPanelDelegate);
searchPanel.$inject = ['ionic','$rootScope'];
function searchPanel(ionic, $rootScope) {
var SearchPanelView = ionic.views.View.inherit({
initialize : function(opts) {
opts = ionic.extend({},opts);
ionic.extend(this, opts);
this.el = opts.el;
this.el.style.display = 'block';
this.isOpen = true;
this.panelAnimDuration = opts.duration;
this.dstY = opts.dstY;
},
setY : function(y) {
this.el.style[ionic.CSS.TRANSFORM] = 'translate3d(0px,'+ y + 'px, 0)';
},
setTransform : function() {
this.el.style[ionic.CSS.TRANSITION] = '-webkit-transform '+this.panelAnimDuration+'s ease';
},
toggle : function() {
var self = this;
ionic.requestAnimationFrame(function(){
self.setTransform();
if(self.isOpen) {
self.setY(self.dstY);
self.isOpen = false;
} else {
self.setY(0);
self.isOpen = true;
}
});
},
toggleIfOpen : function() {
var self = this;
ionic.requestAnimationFrame(function(){
if(self.isOpen) {
self.toggle();
}
});
}
});
return {
restrict : 'E',
template: '<div class="searchpanel-border" ng-transclude></div>',
transclude : true,
link : function($scope, $element, $attr) {
var el = $element[0];
var searchPanelView = new SearchPanelView({
el: el,
duration : $attr['duration'] || 0.5,
dstY : $attr['dstY'] || -105
});
$rootScope.$on('searchPanel.toggle',function(){
searchPanelView.toggle();
});
$rootScope.$on('searchPanel.toggleIfOpen',function(){
searchPanelView.toggleIfOpen();
});
}
};
}
searchPanelDelegate.$inject = ['$rootScope'];
function searchPanelDelegate($rootScope){
return {
togglePanel : function() {
$rootScope.$emit('searchPanel.toggle');
},
togglePanelIfOpen : function() {
$rootScope.$emit('searchPanel.toggleIfOpen');
}
};
}