Skip to content

Instantly share code, notes, and snippets.

@TheDarkCode
Created February 8, 2016 04:53
Show Gist options
  • Save TheDarkCode/c2d3a74150efadf4ba7c to your computer and use it in GitHub Desktop.
Save TheDarkCode/c2d3a74150efadf4ba7c to your computer and use it in GitHub Desktop.
YwJmQZ
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>Tabbed Slide box</title>
<!-- ionic css -->
<link href="http://code.ionicframework.com/1.0.0-rc.4/css/ionic.css" rel="stylesheet">
<!-- your app's css -->
<link href="tabSlideBox.css" rel="stylesheet">
<!-- ionic/angularjs scripts -->
<script src="http://code.ionicframework.com/1.0.0-rc.4/js/ionic.bundle.min.js"></script>
<script src="tabSlideBox.js"></script>
</head>
<body ng-app="slidebox" animation="slide-left-right-ios7">
<ion-nav-bar class="nav-title-slide-ios7 bar-positive">
<ion-nav-back-button class="button-icon ion-arrow-left-c">
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view ng-controller="IndexCtrl"></ion-nav-view>
<script id="index.html" type="text/ng-template">
<ion-view title="ion-ios-tab-view">
<ion-content scroll="false">
<tab-slide-box>
<div class="tsb-icons">
<div class="tsb-ic-wrp">
<ion-scroll direction="x" class="tsb-hscroll">
<a href="javascript:;" class="{{tab.icon}}" ng-repeat="tab in tabs" on-finish-render="test()">{{tab.text}}</a>
</ion-scroll>
</div>
</div>
<ion-slide-box show-pager="false" on-slide-changed="slideHasChanged($index)">
<ion-slide>
<h3>Home content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Games content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Mail content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Car content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Profile content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Favourites content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Chats content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Settings content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide>
<h3>Photos content</h3>
<div style="height: 100%; background:rgba(255,255,255,0.2);">
</div>
</ion-slide>
<ion-slide><h3>End</h3></ion-slide>
<ion-slide></ion-slide>
</ion-slide-box>
</tab-slide-box>
</ion-content>
</ion-view>
</script>
</body>
</html>
/*
* SimplePubSub from https://github.com/mbenford/ngTagsInput/blob/master/src/util.js
* */
'use strict';
function SimplePubSub() {
var events = {};
return {
on: function(names, handler) {
names.split(' ').forEach(function(name) {
if (!events[name]) {
events[name] = [];
}
events[name].push(handler);
});
return this;
},
trigger: function(name, args) {
angular.forEach(events[name], function(handler) {
handler.call(null, args);
});
return this;
}
};
};
angular.module('tabSlideBox', [])
.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
});
}
}
}
})
.directive('tabSlideBox', [ '$timeout', '$window', '$ionicSlideBoxDelegate', '$ionicScrollDelegate',
function($timeout, $window, $ionicSlideBoxDelegate, $ionicScrollDelegate) {
'use strict';
return {
restrict : 'A, E, C',
link : function(scope, element, attrs, ngModel) {
var ta = element[0], $ta = element;
$ta.addClass("tabbed-slidebox");
if(attrs.tabsPosition === "bottom"){
$ta.addClass("btm");
}
//Handle multiple slide/scroll boxes
var handle = ta.querySelector('.slider').getAttribute('delegate-handle');
var ionicSlideBoxDelegate = $ionicSlideBoxDelegate;
if(handle){
ionicSlideBoxDelegate = ionicSlideBoxDelegate.$getByHandle(handle);
}
var ionicScrollDelegate = $ionicScrollDelegate;
if(handle){
ionicScrollDelegate = ionicScrollDelegate.$getByHandle(handle);
}
function renderScrollableTabs(){
var iconsDiv = angular.element(ta.querySelector(".tsb-icons")), icons = iconsDiv.find("a"), wrap = iconsDiv[0].querySelector(".tsb-ic-wrp"), totalTabs = icons.length;
var scrollDiv = wrap.querySelector(".scroll");
angular.forEach(icons, function(value, key){
var a = angular.element(value);
a.on('click', function(){
ionicSlideBoxDelegate.slide(key);
});
if(a.attr('icon-off')) {
a.attr("class", a.attr('icon-off'));
}
});
var initialIndex = attrs.tab;
//Initializing the middle tab
if(typeof attrs.tab === 'undefined' || (totalTabs <= initialIndex) || initialIndex < 0){
initialIndex = Math.floor(icons.length/2);
}
//If initial element is 0, set position of the tab to 0th tab
if(initialIndex == 0){
setPosition(0);
}
$timeout(function() {
ionicSlideBoxDelegate.slide(initialIndex);
}, 0);
}
function setPosition(index){
var iconsDiv = angular.element(ta.querySelector(".tsb-icons")), icons = iconsDiv.find("a"), wrap = iconsDiv[0].querySelector(".tsb-ic-wrp"), totalTabs = icons.length;
var scrollDiv = wrap.querySelector(".scroll");
var middle = iconsDiv[0].offsetWidth/2;
var curEl = angular.element(icons[index]);
var prvEl = angular.element(iconsDiv[0].querySelector(".active"));
if(curEl && curEl.length){
var curElWidth = curEl[0].offsetWidth, curElLeft = curEl[0].offsetLeft;
if(prvEl.attr('icon-off')) {
prvEl.attr("class", prvEl.attr('icon-off'));
}else{
prvEl.removeClass("active");
}
if(curEl.attr('icon-on')) {
curEl.attr("class", curEl.attr('icon-on'));
}
curEl.addClass("active");
var leftStr = (middle - (curElLeft) - curElWidth/2 + 5);
//If tabs are not scrollable
if(!scrollDiv){
var leftStr = (middle - (curElLeft) - curElWidth/2 + 5) + "px";
wrap.style.webkitTransform = "translate3d("+leftStr+",0,0)" ;
}else{
//If scrollable tabs
var wrapWidth = wrap.offsetWidth;
var currentX = Math.abs(getX(scrollDiv.style.webkitTransform));
var leftOffset = 100;
var elementOffset = 40;
//If tabs are reaching right end or left end
if(((currentX + wrapWidth) < (curElLeft + curElWidth + elementOffset)) || (currentX > (curElLeft - leftOffset))){
if(leftStr > 0){
leftStr = 0;
}
//Use this scrollTo, so when scrolling tab manually will not flicker
ionicScrollDelegate.scrollTo(Math.abs(leftStr), 0, true);
}
}
}
};
function getX(matrix) {
matrix = matrix.replace("translate3d(","");
matrix = matrix.replace("translate(","");
return (parseInt(matrix));
}
var events = scope.events;
events.on('slideChange', function(data){
setPosition(data.index);
});
events.on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
renderScrollableTabs();
});
renderScrollableTabs();
},
controller : function($scope, $attrs, $element) {
$scope.events = new SimplePubSub();
$scope.slideHasChanged = function(index){
$scope.events.trigger("slideChange", {"index" : index});
$timeout(function(){if($scope.onSlideMove) $scope.onSlideMove({"index" : eval(index)});},100);
};
$scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
$scope.events.trigger("ngRepeatFinished", {"event" : ngRepeatFinishedEvent});
});
}
};
}
]);
var app = angular.module('slidebox', ['ionic', 'tabSlideBox'])
.run(['$q', '$http', '$rootScope', '$location', '$window', '$timeout',
function($q, $http, $rootScope, $location, $window, $timeout){
$rootScope.$on("$locationChangeStart", function(event, next, current){
$rootScope.error = null;
console.log("Route change!!!", $location.path());
var path = $location.path();
console.log("App Loaded!!!");
});
}
]);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state('index', {
url : '/',
templateUrl : 'index.html',
controller : 'IndexCtrl'
});
$urlRouterProvider.otherwise("/");
});
app.controller("IndexCtrl", ['$rootScope', "$scope", "$stateParams", "$q", "$location", "$window", '$timeout',
function($rootScope, $scope, $stateParams, $q, $location, $window, $timeout){
$scope.tabs = [
{"text" : "Home"},
{"text" : "Games"},
{"text" : "Mail"},
{"text" : "Car"},
{"text" : "Profile"},
{"text" : "Favourites"},
{"text" : "Chats"},
{"text" : "Settings"},
{"text" : "Photos"}
];
$scope.onSlideMove = function(data){
//alert("You have selected " + data.index + " tab");
};
}
]);
.slider {
background: #3b679e; /* Old browsers */
background: -moz-linear-gradient(-45deg, #3b679e 0%, #2b88d9 35%, #7db9e8 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(-45deg, #3b679e 0%,#2b88d9 35%,#7db9e8 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(135deg, #3b679e 0%,#2b88d9 35%,#7db9e8 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3b679e', endColorstr='#7db9e8',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
top: 0;
position: absolute;
}
.tsb-icons {
display: absolute;
z-index: 1000;
top: calc(100vh - 65px);
}
.tabbed-slidebox .slider {
padding: 0;
margin-top: 0;
height: 100%;
}
.tabbed-slidebox.btm .slider {
margin-bottom: -50px;
}
.tabbed-slidebox .slider-slides {
width: 100%;
margin-top: 0;
max-height: calc(100vh - 65px) !important;
}
.tabbed-slidebox .slider-slide {
padding-top: 10px;
color: #000;
background-color: #fff;
text-align: center;
font-weight: 300;
/* blue bg *
background-color: rgba(55,150,250,0.70); */
background-color: rgba(0,0,0,0.1);
margin-left: 10px;
margin-top:10px;
border-radius: 15px;
}
.tabbed-slidebox .tsb-icons {
text-align: center;
margin: 0;
margin-top: -20px;
margin-bottom: -20px;
position: relative;
background-color:rgba(255,255,255,1);
}
.tabbed-slidebox .tsb-ic-wrp {
display: flex;
position: relative;
-webkit-transition: -webkit-transform 0.3s; /* For Safari 3.1 to 6.0 */
-webkit-transform:translate3d(0,0,0);
}
.tabbed-slidebox .tsb-icons a {
display: inline-block;
width: 54px;
font-size: 2.5em;
color: rgba(0, 0, 0, 0.3);
-webkit-transform:translate3d(0,8px,0);
}
.tabbed-slidebox .tsb-icons a.active {
color: rgba(0, 0, 0, 1);
font-size: 3.5em;
-webkit-transform:translate3d(0,0,0);
}
.tabbed-slidebox .tabbed-slidebox {
position: relative;
height: 100%;
overflow: hidden;
}
.tabbed-slidebox .tsb-icons:after {
width: 0;
height: 0;
border-style: solid;
border-width: 0 1.4em 1.4em 1.4em;
border-color: transparent transparent #0398dc transparent;
position: absolute;
content: "";
display: block;
bottom: -12px;
left: 50%;
margin-left: -14px;
}
.tsb-hscroll.scroll-view{
white-space: nowrap;
margin:0 auto;
}
.tsb-hscroll.scroll-view .scroll-bar{
visibility:hidden;
}
.tsb-hscroll.scroll-view .scroll.onscroll{
-webkit-transition: -webkit-transform 0.3s; /* For Safari 3.1 to 6.0 */
}
.tabbed-slidebox .tsb-icons .scroll a{
width:auto;
font-size: 1.5em;
line-height: 1.5em;
text-decoration: none;
margin: 0 15px;
border-bottom: 3px solid transparent;
}
.tabbed-slidebox .tsb-icons .scroll a.active {
font-size: 1.8em;
border-bottom: 3px solid #ccc;
}
.slider-slide h3{
color:#fff;
margin-top:10px;
}
.scroll{
height:100%;
}
.tabbed-slidebox .tsb-icons:after{
display:none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment