maction.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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/SVG/autoload/maction.js
  6. *
  7. * Implements the SVG output for <maction> elements.
  8. *
  9. * ---------------------------------------------------------------------
  10. *
  11. * Copyright (c) 2011-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("SVG Jax Ready",function () {
  26. var VERSION = "2.2";
  27. var MML = MathJax.ElementJax.mml,
  28. SVG = MathJax.OutputJax["SVG"];
  29. var currentTip, hover, clear;
  30. //
  31. // Add configuration for tooltips
  32. //
  33. var CONFIG = SVG.config.tooltip = MathJax.Hub.Insert({
  34. delayPost: 600, delayClear: 600,
  35. offsetX: 10, offsetY: 5
  36. },SVG.config.tooltip||{});
  37. MML.maction.Augment({
  38. SVGtooltip: MathJax.HTML.addElement(document.body,"div",{id:"MathJax_SVG_Tooltip"}),
  39. toSVG: function (HW,D) {
  40. this.SVGgetStyles();
  41. var svg = this.SVG();
  42. var selected = this.selected();
  43. if (selected.type == "null") {this.SVGsaveData(svg);return svg;}
  44. svg.Add(this.SVGdataStretched(this.Get("selection")-1,HW,D));
  45. this.SVGhandleHitBox(svg);
  46. this.SVGhandleSpace(svg);
  47. this.SVGhandleColor(svg);
  48. this.SVGsaveData(svg);
  49. return svg;
  50. },
  51. SVGhandleHitBox: function (svg) {
  52. var frame = SVG.addElement(svg.element,"rect",
  53. {width:svg.w, height:svg.h+svg.d, y:-svg.d, fill:"none", "pointer-events":"all"});
  54. var type = this.Get("actiontype");
  55. if (this.SVGaction[type]) {this.SVGaction[type].call(this,svg,frame,this.Get("selection"))}
  56. },
  57. SVGstretchH: MML.mbase.prototype.SVGstretchH,
  58. SVGstretchV: MML.mbase.prototype.SVGstretchV,
  59. //
  60. // Implementations for the various actions
  61. //
  62. SVGaction: {
  63. toggle: function (svg,frame,selection) {
  64. this.selection = selection;
  65. SVG.Element(frame,{cursor:"pointer"});
  66. frame.onclick = MathJax.Callback(["SVGclick",this]);
  67. },
  68. statusline: function (svg,frame,selection) {
  69. frame.onmouseover = MathJax.Callback(["SVGsetStatus",this]),
  70. frame.onmouseout = MathJax.Callback(["SVGclearStatus",this]);
  71. frame.onmouseover.autoReset = frame.onmouseout.autoReset = true;
  72. },
  73. tooltip: function(svg,frame,selection) {
  74. frame.onmouseover = MathJax.Callback(["SVGtooltipOver",this]),
  75. frame.onmouseout = MathJax.Callback(["SVGtooltipOut",this]);
  76. frame.onmouseover.autoReset = frame.onmouseout.autoReset = true;
  77. }
  78. },
  79. //
  80. // Handle a click on the maction element
  81. // (remove the original rendering and rerender)
  82. //
  83. SVGclick: function (event) {
  84. this.selection++;
  85. if (this.selection > this.data.length) {this.selection = 1}
  86. var math = this; while (math.type !== "math") {math = math.inherit}
  87. var jax = MathJax.Hub.getJaxFor(math.inputID); //, hover = !!jax.hover;
  88. jax.Update();
  89. /*
  90. * if (hover) {
  91. * var span = document.getElementById(jax.inputID+"-Span");
  92. * MathJax.Extension.MathEvents.Hover.Hover(jax,span);
  93. * }
  94. */
  95. return MathJax.Extension.MathEvents.Event.False(event);
  96. },
  97. //
  98. // Set/Clear the window status message
  99. //
  100. SVGsetStatus: function (event) {
  101. // FIXME: Do something better with non-token elements
  102. this.messageID = MathJax.Message.Set
  103. ((this.data[1] && this.data[1].isToken) ?
  104. this.data[1].data.join("") : this.data[1].toString());
  105. },
  106. SVGclearStatus: function (event) {
  107. if (this.messageID) {MathJax.Message.Clear(this.messageID,0)}
  108. delete this.messageID;
  109. },
  110. //
  111. // Handle tooltips
  112. //
  113. SVGtooltipOver: function (event) {
  114. if (!event) {event = window.event}
  115. if (clear) {clearTimeout(clear); clear = null}
  116. if (hover) {clearTimeout(hover)}
  117. var x = event.pageX; var y = event.pageY;
  118. if (x == null) {
  119. x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  120. y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
  121. }
  122. var callback = MathJax.Callback(["SVGtooltipPost",this,x+CONFIG.offsetX,y+CONFIG.offsetY])
  123. hover = setTimeout(callback,CONFIG.delayPost);
  124. },
  125. SVGtooltipOut: function (event) {
  126. if (hover) {clearTimeout(hover); hover = null}
  127. if (clear) {clearTimeout(clear)}
  128. var callback = MathJax.Callback(["SVGtooltipClear",this,80]);
  129. clear = setTimeout(callback,CONFIG.delayClear);
  130. },
  131. SVGtooltipPost: function (x,y) {
  132. hover = null; if (clear) {clearTimeout(clear); clear = null}
  133. //
  134. // Get the tip div and show it at the right location, then clear its contents
  135. //
  136. var tip = this.SVGtooltip;
  137. tip.style.display = "block"; tip.style.opacity = "";
  138. if (this === currentTip) return;
  139. tip.style.left = x+"px"; tip.style.top = y+"px";
  140. tip.innerHTML = ''; var span = MathJax.HTML.addElement(tip,"span");
  141. //
  142. // Get the sizes from the jax (FIXME: should calculate again?)
  143. //
  144. var math = this; while (math.type !== "math") {math = math.inherit}
  145. var jax = MathJax.Hub.getJaxFor(math.inputID);
  146. this.em = MML.mbase.prototype.em = jax.SVG.em; this.ex = jax.SVG.ex;
  147. this.linebreakWidth = jax.SVG.lineWidth * 1000; this.cwidth = jax.SVG.cwidth;
  148. //
  149. // Make a new math element and temporarily move the tooltip to it
  150. // Display the math containing the tip, but check for errors
  151. // Then put the tip back into the maction element
  152. //
  153. var mml = this.data[1];
  154. math = MML.math(mml);
  155. try {math.toSVG(span,tip)} catch(err) {
  156. this.SetData(1,mml); tip.style.display = "none";
  157. if (!err.restart) {throw err}
  158. MathJax.Callback.After(["SVGtooltipPost",this,x,y],err.restart);
  159. return;
  160. }
  161. this.SetData(1,mml);
  162. currentTip = this;
  163. },
  164. SVGtooltipClear: function (n) {
  165. var tip = this.SVGtooltip;
  166. if (n <= 0) {
  167. tip.style.display = "none";
  168. tip.style.opacity = "";
  169. clear = null;
  170. } else {
  171. tip.style.opacity = n/100;
  172. clear = setTimeout(MathJax.Callback(["SVGtooltipClear",this,n-20]),50);
  173. }
  174. }
  175. });
  176. MathJax.Hub.Startup.signal.Post("SVG maction Ready");
  177. MathJax.Ajax.loadComplete(SVG.autoloadDir+"/maction.js");
  178. });