angular-tabSlideBox.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * SimplePubSub from https://github.com/mbenford/ngTagsInput/blob/master/src/util.js
  3. * */
  4. 'use strict';
  5. function SimplePubSub() {
  6. var events = {};
  7. return {
  8. on: function (names, handler) {
  9. names.split(' ').forEach(function (name) {
  10. if (!events[name]) {
  11. events[name] = [];
  12. }
  13. events[name].push(handler);
  14. });
  15. return this;
  16. },
  17. trigger: function (name, args) {
  18. angular.forEach(events[name], function (handler) {
  19. handler.call(null, args);
  20. });
  21. return this;
  22. }
  23. };
  24. };
  25. angular.module('tabSlideBox', [])
  26. .directive('onFinishRender', function ($timeout) {
  27. return {
  28. restrict: 'A',
  29. link: function (scope, element, attr) {
  30. if (scope.$last === true) {
  31. $timeout(function () {
  32. scope.$emit('ngRepeatFinished');
  33. });
  34. }
  35. }
  36. }
  37. })
  38. .directive('tabSlideBox', ['$timeout', '$window', '$ionicSlideBoxDelegate', '$ionicScrollDelegate',
  39. function ($timeout, $window, $ionicSlideBoxDelegate, $ionicScrollDelegate) {
  40. 'use strict';
  41. return {
  42. restrict: 'A, E, C',
  43. link: function (scope, element, attrs, ngModel) {
  44. var ta = element[0], $ta = element;
  45. $ta.addClass("tabbed-slidebox");
  46. if (attrs.tabsPosition === "bottom") {
  47. $ta.addClass("btm");
  48. }
  49. //Handle multiple slide/scroll boxes
  50. var handle = ta.querySelector('.slider').getAttribute('delegate-handle');
  51. var ionicSlideBoxDelegate = $ionicSlideBoxDelegate;
  52. if (handle) {
  53. ionicSlideBoxDelegate = ionicSlideBoxDelegate.$getByHandle(handle);
  54. }
  55. var ionicScrollDelegate = $ionicScrollDelegate;
  56. if (handle) {
  57. ionicScrollDelegate = ionicScrollDelegate.$getByHandle(handle);
  58. }
  59. function renderScrollableTabs() {
  60. var iconsDiv = angular.element(ta.querySelector(".tsb-icons")), icons = iconsDiv.find("a"), wrap = iconsDiv[0].querySelector(".tsb-ic-wrp"), totalTabs = icons.length;
  61. var scrollDiv = wrap.querySelector(".scroll");
  62. angular.forEach(icons, function (value, key) {
  63. var a = angular.element(value);
  64. a.on('click', function () {
  65. ionicSlideBoxDelegate.slide(key);
  66. });
  67. if (a.attr('icon-off')) {
  68. a.attr("class", a.attr('icon-off'));
  69. }
  70. });
  71. var initialIndex = attrs.tab;
  72. //Initializing the middle tab
  73. if (typeof attrs.tab === 'undefined' || (totalTabs <= initialIndex) || initialIndex < 0) {
  74. initialIndex = Math.floor(icons.length / 2);
  75. }
  76. //If initial element is 0, set position of the tab to 0th tab
  77. if (initialIndex == 0) {
  78. setPosition(0);
  79. }
  80. $timeout(function () {
  81. ionicSlideBoxDelegate.slide(initialIndex);
  82. }, 0);
  83. }
  84. function setPosition(index) {
  85. var iconsDiv = angular.element(ta.querySelector(".tsb-icons")), icons = iconsDiv.find("a"), wrap = iconsDiv[0].querySelector(".tsb-ic-wrp"), totalTabs = icons.length;
  86. var scrollDiv = wrap.querySelector(".scroll");
  87. var middle = iconsDiv[0].offsetWidth / 2;
  88. var curEl = angular.element(icons[index]);
  89. var prvEl = angular.element(iconsDiv[0].querySelector(".active"));
  90. if (curEl && curEl.length) {
  91. var curElWidth = curEl[0].offsetWidth, curElLeft = curEl[0].offsetLeft;
  92. if (prvEl.attr('icon-off')) {
  93. prvEl.attr("class", prvEl.attr('icon-off'));
  94. } else {
  95. prvEl.removeClass("active");
  96. }
  97. if (curEl.attr('icon-on')) {
  98. curEl.attr("class", curEl.attr('icon-on'));
  99. }
  100. curEl.addClass("active");
  101. var leftStr = (middle - (curElLeft) - curElWidth / 2 + 5);
  102. //If tabs are not scrollable
  103. if (!scrollDiv) {
  104. var leftStr = (middle - (curElLeft) - curElWidth / 2 + 5) + "px";
  105. wrap.style.webkitTransform = "translate3d(" + leftStr + ",0,0)";
  106. } else {
  107. //If scrollable tabs
  108. var wrapWidth = wrap.offsetWidth;
  109. var currentX = Math.abs(getX(scrollDiv.style.webkitTransform));
  110. var leftOffset = 100;
  111. var elementOffset = 40;
  112. //If tabs are reaching right end or left end
  113. if (((currentX + wrapWidth) < (curElLeft + curElWidth + elementOffset)) || (currentX > (curElLeft - leftOffset))) {
  114. if (leftStr > 0) {
  115. leftStr = 0;
  116. }
  117. //Use this scrollTo, so when scrolling tab manually will not flicker
  118. ionicScrollDelegate.scrollTo(Math.abs(leftStr), 0, true);
  119. }
  120. }
  121. }
  122. };
  123. function getX(matrix) {
  124. matrix = matrix.replace("translate3d(", "");
  125. matrix = matrix.replace("translate(", "");
  126. return (parseInt(matrix));
  127. }
  128. var events = scope.events;
  129. events.on('slideChange', function (data) {
  130. setPosition(data.index);
  131. });
  132. events.on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
  133. renderScrollableTabs();
  134. });
  135. renderScrollableTabs();
  136. },
  137. controller: function ($scope, $attrs, $element) {
  138. $scope.events = new SimplePubSub();
  139. $scope.slideHasChanged = function (index) {
  140. $scope.events.trigger("slideChange", { "index": index });
  141. $timeout(function () { if ($scope.onSlideMove) $scope.onSlideMove({ "index": eval(index) }); }, 100);
  142. };
  143. $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
  144. $scope.events.trigger("ngRepeatFinished", { "event": ngRepeatFinishedEvent });
  145. });
  146. }
  147. };
  148. }
  149. ]);