maction.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
  2. /* vim: set ts=2 et sw=2 tw=80: */
  3. /*************************************************************
  4. *
  5. * MathJax/jax/output/HTML-CSS/autoload/maction.js
  6. *
  7. * Implements the HTML-CSS output for <maction> elements.
  8. *
  9. * ---------------------------------------------------------------------
  10. *
  11. * Copyright (c) 2010-2013 The MathJax Consortium
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License");
  14. * you may not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS,
  21. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. */
  25. MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () {
  26. var VERSION = "2.2";
  27. var MML = MathJax.ElementJax.mml,
  28. HTMLCSS = MathJax.OutputJax["HTML-CSS"];
  29. var currentTip, hover, clear;
  30. //
  31. // Add configuration for tooltips
  32. //
  33. var CONFIG = HTMLCSS.config.tooltip = MathJax.Hub.Insert({
  34. delayPost: 600, delayClear: 600,
  35. offsetX: 10, offsetY: 5
  36. },HTMLCSS.config.tooltip||{});
  37. MML.maction.Augment({
  38. HTMLtooltip: HTMLCSS.addElement(document.body,"div",{id:"MathJax_Tooltip"}),
  39. toHTML: function (span,HW,D) {
  40. var selected = this.selected();
  41. if (selected.type == "null") {
  42. span = this.HTMLcreateSpan(span);
  43. span.bbox = this.HTMLzeroBBox();
  44. return span;
  45. }
  46. span = this.HTMLhandleSize(this.HTMLcreateSpan(span)); span.bbox = null;
  47. var box = selected.toHTML(span);
  48. if (D != null) {HTMLCSS.Remeasured(selected.HTMLstretchV(span,HW,D),span)}
  49. else if (HW != null) {
  50. HTMLCSS.Remeasured(selected.HTMLstretchH(span,HW),span)
  51. } else {HTMLCSS.Measured(box,span)}
  52. this.HTMLhandleHitBox(span);
  53. this.HTMLhandleSpace(span);
  54. this.HTMLhandleColor(span);
  55. return span;
  56. },
  57. HTMLhandleHitBox: function (span,postfix) {
  58. var frame;
  59. if (HTMLCSS.msieHitBoxBug) {
  60. // margin-left doesn't work on inline-block elements in IE, so put it in a SPAN
  61. var box = HTMLCSS.addElement(span,"span",{isMathJax:true});
  62. frame = HTMLCSS.createFrame(box,span.bbox.h,span.bbox.d,span.bbox.w,0,"none");
  63. span.insertBefore(box,span.firstChild); // move below the content
  64. box.style.marginRight = HTMLCSS.Em(-span.bbox.w);
  65. if (HTMLCSS.msieInlineBlockAlignBug)
  66. {frame.style.verticalAlign = HTMLCSS.Em(HTMLCSS.getHD(span).d-span.bbox.d)}
  67. } else {
  68. frame = HTMLCSS.createFrame(span,span.bbox.h,span.bbox.d,span.bbox.w,0,"none");
  69. span.insertBefore(frame,span.firstChild); // move below the content
  70. frame.style.marginRight = HTMLCSS.Em(-span.bbox.w);
  71. }
  72. frame.className = "MathJax_HitBox";
  73. frame.id = "MathJax-HitBox-" + this.spanID + (postfix||"") + HTMLCSS.idPostfix;
  74. var type = this.Get("actiontype");
  75. if (this.HTMLaction[type]) {this.HTMLaction[type].call(this,span,frame,this.Get("selection"))}
  76. },
  77. HTMLstretchH: MML.mbase.HTMLstretchH,
  78. HTMLstretchV: MML.mbase.HTMLstretchV,
  79. //
  80. // Implementations for the various actions
  81. //
  82. HTMLaction: {
  83. toggle: function (span,frame,selection) {
  84. this.selection = selection;
  85. frame.onclick = span.childNodes[1].onclick = MathJax.Callback(["HTMLclick",this]);
  86. frame.style.cursor = span.childNodes[1].style.cursor="pointer";
  87. },
  88. statusline: function (span,frame,selection) {
  89. frame.onmouseover = span.childNodes[1].onmouseover = MathJax.Callback(["HTMLsetStatus",this]);
  90. frame.onmouseout = span.childNodes[1].onmouseout = MathJax.Callback(["HTMLclearStatus",this]);
  91. frame.onmouseover.autoReset = frame.onmouseout.autoReset = true;
  92. },
  93. tooltip: function(span,frame,selection) {
  94. if (this.data[1] && this.data[1].isToken) {
  95. frame.title = frame.alt = span.childNodes[1].title =
  96. span.childNodes[1].alt = this.data[1].data.join("");
  97. } else {
  98. frame.onmouseover = span.childNodes[1].onmouseover = MathJax.Callback(["HTMLtooltipOver",this]);
  99. frame.onmouseout = span.childNodes[1].onmouseout = MathJax.Callback(["HTMLtooltipOut",this]);
  100. frame.onmouseover.autoReset = frame.onmouseout.autoReset = true;
  101. }
  102. }
  103. },
  104. //
  105. // Handle a click on the maction element
  106. // (remove the original rendering and rerender)
  107. //
  108. HTMLclick: function (event) {
  109. this.selection++;
  110. if (this.selection > this.data.length) {this.selection = 1}
  111. var math = this; while (math.type !== "math") {math = math.inherit}
  112. var jax = MathJax.Hub.getJaxFor(math.inputID), hover = !!jax.hover;
  113. jax.Update();
  114. if (hover) {
  115. var span = document.getElementById(jax.inputID+"-Span");
  116. MathJax.Extension.MathEvents.Hover.Hover(jax,span);
  117. }
  118. return MathJax.Extension.MathEvents.Event.False(event);
  119. },
  120. //
  121. // Set/Clear the window status message
  122. //
  123. HTMLsetStatus: function (event) {
  124. // FIXME: Do something better with non-token elements
  125. this.messageID = MathJax.Message.Set
  126. ((this.data[1] && this.data[1].isToken) ?
  127. this.data[1].data.join("") : this.data[1].toString());
  128. },
  129. HTMLclearStatus: function (event) {
  130. if (this.messageID) {MathJax.Message.Clear(this.messageID,0)}
  131. delete this.messageID;
  132. },
  133. //
  134. // Handle tooltips
  135. //
  136. HTMLtooltipOver: function (event) {
  137. if (!event) {event = window.event}
  138. if (clear) {clearTimeout(clear); clear = null}
  139. if (hover) {clearTimeout(hover)}
  140. var x = event.pageX; var y = event.pageY;
  141. if (x == null) {
  142. x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  143. y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
  144. }
  145. var callback = MathJax.Callback(["HTMLtooltipPost",this,x+CONFIG.offsetX,y+CONFIG.offsetY])
  146. hover = setTimeout(callback,CONFIG.delayPost);
  147. },
  148. HTMLtooltipOut: function (event) {
  149. if (hover) {clearTimeout(hover); hover = null}
  150. if (clear) {clearTimeout(clear)}
  151. var callback = MathJax.Callback(["HTMLtooltipClear",this,80]);
  152. clear = setTimeout(callback,CONFIG.delayClear);
  153. },
  154. HTMLtooltipPost: function (x,y) {
  155. hover = null; if (clear) {clearTimeout(clear); clear = null}
  156. var tip = this.HTMLtooltip;
  157. tip.style.display = "block"; tip.style.opacity = "";
  158. tip.style.filter = HTMLCSS.config.styles["#MathJax_Tooltip"].filter;
  159. if (this === currentTip) return;
  160. tip.style.left = x+"px"; tip.style.top = y+"px";
  161. tip.innerHTML = '<span class="MathJax"><nobr></nobr></span>';
  162. //
  163. // get em sizes (taken from HTMLCSS.preTranslate)
  164. //
  165. var emex = tip.insertBefore(HTMLCSS.EmExSpan.cloneNode(true),tip.firstChild);
  166. var ex = emex.firstChild.offsetHeight/60,
  167. em = emex.lastChild.firstChild.offsetHeight/60;
  168. HTMLCSS.em = HTMLCSS.outerEm = MML.mbase.prototype.em = em;
  169. var scale = Math.floor(Math.max(HTMLCSS.config.minScaleAdjust/100,(ex/HTMLCSS.TeX.x_height)/em) * HTMLCSS.config.scale);
  170. tip.firstChild.style.fontSize = scale+"%";
  171. emex.parentNode.removeChild(emex);
  172. var stack = HTMLCSS.createStack(tip.firstChild.firstChild);
  173. var box = HTMLCSS.createBox(stack);
  174. try {HTMLCSS.Measured(this.data[1].toHTML(box),box)} catch(err) {
  175. if (!err.restart) {throw err}
  176. tip.style.display = "none";
  177. MathJax.Callback.After(["HTMLtooltipPost",this,x,y],err.restart);
  178. return;
  179. }
  180. HTMLCSS.placeBox(box,0,0);
  181. HTMLCSS.createRule(tip.firstChild.firstChild,box.bbox.h,box.bbox.d,0);
  182. currentTip = this;
  183. },
  184. HTMLtooltipClear: function (n) {
  185. var tip = this.HTMLtooltip;
  186. if (n <= 0) {
  187. tip.style.display = "none";
  188. tip.style.opacity = tip.style.filter = "";
  189. clear = null;
  190. } else {
  191. tip.style.opacity = n/100;
  192. tip.style.filter = "alpha(opacity="+n+")";
  193. clear = setTimeout(MathJax.Callback(["HTMLtooltipClear",this,n-20]),50);
  194. }
  195. }
  196. });
  197. //
  198. // Do browser-specific setup
  199. //
  200. MathJax.Hub.Browser.Select({
  201. MSIE: function (browser) {
  202. HTMLCSS.msieHitBoxBug = true;
  203. }
  204. });
  205. MathJax.Hub.Startup.signal.Post("HTML-CSS maction Ready");
  206. MathJax.Ajax.loadComplete(HTMLCSS.autoloadDir+"/maction.js");
  207. });