Header.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* Top toolbar area with buttons and title
  2. ----------------------------------------------------------------------------------------------------------------------*/
  3. // TODO: rename all header-related things to "toolbar"
  4. function Header(calendar, options) {
  5. var t = this;
  6. // exports
  7. t.render = render;
  8. t.removeElement = removeElement;
  9. t.updateTitle = updateTitle;
  10. t.activateButton = activateButton;
  11. t.deactivateButton = deactivateButton;
  12. t.disableButton = disableButton;
  13. t.enableButton = enableButton;
  14. t.getViewsWithButtons = getViewsWithButtons;
  15. // locals
  16. var el = $();
  17. var viewsWithButtons = [];
  18. var tm;
  19. function render() {
  20. var sections = options.header;
  21. tm = options.theme ? 'ui' : 'fc';
  22. if (sections) {
  23. el = $("<div class='fc-toolbar'/>")
  24. .append(renderSection('left'))
  25. .append(renderSection('right'))
  26. .append(renderSection('center'))
  27. .append('<div class="fc-clear"/>');
  28. return el;
  29. }
  30. }
  31. function removeElement() {
  32. el.remove();
  33. el = $();
  34. }
  35. function renderSection(position) {
  36. var sectionEl = $('<div class="fc-' + position + '"/>');
  37. var buttonStr = options.header[position];
  38. if (buttonStr) {
  39. $.each(buttonStr.split(' '), function(i) {
  40. var groupChildren = $();
  41. var isOnlyButtons = true;
  42. var groupEl;
  43. $.each(this.split(','), function(j, buttonName) {
  44. var customButtonProps;
  45. var viewSpec;
  46. var buttonClick;
  47. var overrideText; // text explicitly set by calendar's constructor options. overcomes icons
  48. var defaultText;
  49. var themeIcon;
  50. var normalIcon;
  51. var innerHtml;
  52. var classes;
  53. var button; // the element
  54. if (buttonName == 'title') {
  55. groupChildren = groupChildren.add($('<h2>&nbsp;</h2>')); // we always want it to take up height
  56. isOnlyButtons = false;
  57. }
  58. else {
  59. if ((customButtonProps = (calendar.options.customButtons || {})[buttonName])) {
  60. buttonClick = function(ev) {
  61. if (customButtonProps.click) {
  62. customButtonProps.click.call(button[0], ev);
  63. }
  64. };
  65. overrideText = ''; // icons will override text
  66. defaultText = customButtonProps.text;
  67. }
  68. else if ((viewSpec = calendar.getViewSpec(buttonName))) {
  69. buttonClick = function() {
  70. calendar.changeView(buttonName);
  71. };
  72. viewsWithButtons.push(buttonName);
  73. overrideText = viewSpec.buttonTextOverride;
  74. defaultText = viewSpec.buttonTextDefault;
  75. }
  76. else if (calendar[buttonName]) { // a calendar method
  77. buttonClick = function() {
  78. calendar[buttonName]();
  79. };
  80. overrideText = (calendar.overrides.buttonText || {})[buttonName];
  81. defaultText = options.buttonText[buttonName]; // everything else is considered default
  82. }
  83. if (buttonClick) {
  84. themeIcon =
  85. customButtonProps ?
  86. customButtonProps.themeIcon :
  87. options.themeButtonIcons[buttonName];
  88. normalIcon =
  89. customButtonProps ?
  90. customButtonProps.icon :
  91. options.buttonIcons[buttonName];
  92. if (overrideText) {
  93. innerHtml = htmlEscape(overrideText);
  94. }
  95. else if (themeIcon && options.theme) {
  96. innerHtml = "<span class='ui-icon ui-icon-" + themeIcon + "'></span>";
  97. }
  98. else if (normalIcon && !options.theme) {
  99. innerHtml = "<span class='fc-icon fc-icon-" + normalIcon + "'></span>";
  100. }
  101. else {
  102. innerHtml = htmlEscape(defaultText);
  103. }
  104. classes = [
  105. 'fc-' + buttonName + '-button',
  106. tm + '-button',
  107. tm + '-state-default'
  108. ];
  109. button = $( // type="button" so that it doesn't submit a form
  110. '<button type="button" class="' + classes.join(' ') + '">' +
  111. innerHtml +
  112. '</button>'
  113. )
  114. .click(function(ev) {
  115. // don't process clicks for disabled buttons
  116. if (!button.hasClass(tm + '-state-disabled')) {
  117. buttonClick(ev);
  118. // after the click action, if the button becomes the "active" tab, or disabled,
  119. // it should never have a hover class, so remove it now.
  120. if (
  121. button.hasClass(tm + '-state-active') ||
  122. button.hasClass(tm + '-state-disabled')
  123. ) {
  124. button.removeClass(tm + '-state-hover');
  125. }
  126. }
  127. })
  128. .mousedown(function() {
  129. // the *down* effect (mouse pressed in).
  130. // only on buttons that are not the "active" tab, or disabled
  131. button
  132. .not('.' + tm + '-state-active')
  133. .not('.' + tm + '-state-disabled')
  134. .addClass(tm + '-state-down');
  135. })
  136. .mouseup(function() {
  137. // undo the *down* effect
  138. button.removeClass(tm + '-state-down');
  139. })
  140. .hover(
  141. function() {
  142. // the *hover* effect.
  143. // only on buttons that are not the "active" tab, or disabled
  144. button
  145. .not('.' + tm + '-state-active')
  146. .not('.' + tm + '-state-disabled')
  147. .addClass(tm + '-state-hover');
  148. },
  149. function() {
  150. // undo the *hover* effect
  151. button
  152. .removeClass(tm + '-state-hover')
  153. .removeClass(tm + '-state-down'); // if mouseleave happens before mouseup
  154. }
  155. );
  156. groupChildren = groupChildren.add(button);
  157. }
  158. }
  159. });
  160. if (isOnlyButtons) {
  161. groupChildren
  162. .first().addClass(tm + '-corner-left').end()
  163. .last().addClass(tm + '-corner-right').end();
  164. }
  165. if (groupChildren.length > 1) {
  166. groupEl = $('<div/>');
  167. if (isOnlyButtons) {
  168. groupEl.addClass('fc-button-group');
  169. }
  170. groupEl.append(groupChildren);
  171. sectionEl.append(groupEl);
  172. }
  173. else {
  174. sectionEl.append(groupChildren); // 1 or 0 children
  175. }
  176. });
  177. }
  178. return sectionEl;
  179. }
  180. function updateTitle(text) {
  181. el.find('h2').text(text);
  182. }
  183. function activateButton(buttonName) {
  184. el.find('.fc-' + buttonName + '-button')
  185. .addClass(tm + '-state-active');
  186. }
  187. function deactivateButton(buttonName) {
  188. el.find('.fc-' + buttonName + '-button')
  189. .removeClass(tm + '-state-active');
  190. }
  191. function disableButton(buttonName) {
  192. el.find('.fc-' + buttonName + '-button')
  193. .attr('disabled', 'disabled')
  194. .addClass(tm + '-state-disabled');
  195. }
  196. function enableButton(buttonName) {
  197. el.find('.fc-' + buttonName + '-button')
  198. .removeAttr('disabled')
  199. .removeClass(tm + '-state-disabled');
  200. }
  201. function getViewsWithButtons() {
  202. return viewsWithButtons;
  203. }
  204. }