maction.js 7.0 KB

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