commit 2367f0e92bafdc48e706625da058167ac41559e2
parent 5b421d32d1124d83d7b0b53e6665714f54f80d55
Author: Davide P. Cervone <dpvc@union.edu>
Date: Fri, 19 Aug 2011 09:19:22 -0400
Preliminary 'discoverable' math implementation. INCOMPLETE: DO NOT USE YET. Only in HTML-CSS mode, and still need to refactor to move event code to common file. Does support mobile devices through tap event. Does not include packed or combined versions yet.
Diffstat:
4 files changed, 164 insertions(+), 17 deletions(-)
diff --git a/unpacked/MathJax.js b/unpacked/MathJax.js
@@ -30,7 +30,7 @@ if (!window.MathJax) {window.MathJax= {}}
if (!MathJax.Hub) { // skip if already loaded
MathJax.version = "1.1a";
-MathJax.fileversion = "1.1.10";
+MathJax.fileversion = "1.1.11";
/**********************************************************/
@@ -1025,6 +1025,7 @@ MathJax.fileversion = "1.1.10";
if (AJAX.loadingMathMenu) {return False(event)}
var jax = BASE.OutputJax[math.jaxID];
if (!event) {event = window.event}
+ event.isContextMenu = (type === "ContextMenu");
return jax.HandleEvent(event,type,math);
},
//
@@ -1054,21 +1055,28 @@ MathJax.fileversion = "1.1.10";
//
// Load the contextual menu code, if needed, and post the menu
//
- ContextMenu: function (event,math) {
+ ContextMenu: function (event,jax) {
+ if (jax.hover) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove); delete jax.hover.remove}
+ jax.hover.nofade = true;
+ }
var MENU = BASE.Menu;
if (MENU) {
- MENU.jax = BASE.Hub.getJaxFor(math.nextSibling);
- MENU.menu.items[1].menu.items[1].name =
+ MENU.jax = jax;
+ MENU.menu.Find("Format").menu.items[1].name =
(MENU.jax.inputJax.id === "MathML" ? "Original" : MENU.jax.inputJax.id);
return MENU.menu.Post(event);
} else {
if (!AJAX.loadingMathMenu) {
AJAX.loadingMathMenu = true;
- var ev = {pageX:event.pageX, pageY:event.pageY, clientX:event.clientX, clientY:event.clientY};
+ var ev = {
+ pageX:event.pageX, pageY:event.pageY,
+ clientX:event.clientX, clientY:event.clientY
+ };
CALLBACK.Queue(
AJAX.Require("[MathJax]/extensions/MathMenu.js"),
function () {delete AJAX.loadingMathMenu; if (!BASE.Menu) {BASE.Menu = {}}},
- ["ContextMenu",this,ev,math] // call this function again
+ ["ContextMenu",this,ev,jax] // call this function again
);
}
return this.False(event);
@@ -1329,6 +1337,8 @@ MathJax.Hub = {
ALT: false, // require Alt or Option?
CMD: false, // require CMD?
Shift: false, // require Shift?
+ hover: 500, // length of time mouse must be still to count as hover
+ discoverable: true, // make math menu discoverable on hover?
zscale: "200%", // the scaling factor for MathZoom
renderer: "", // set when Jax are loaded
font: "Auto", // what font HTML-CSS should use
diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js
@@ -176,9 +176,9 @@
if (MENU.isMobile) {
HTML.addElement(menu,"img",{
src: MathJax.Ajax.fileURL(MathJax.OutputJax.imageDir+"/CloseX-31.png"),
- width: 31, height: 31,
+ width: 31, height: 31, menu: parent,
style: {position:"absolute", top:"-15px", left:"-15px"},
- ontouchstart: MENU.Close, ontouchend: this.False, menu: parent
+ ontouchstart: MENU.Close, ontouchend: this.False, onmousedown: MENU.Close
});
}
this.posted = true;
@@ -193,7 +193,7 @@
if (x + menu.offsetWidth > document.body.offsetWidth - this.margin)
{x = document.body.offsetWidth - menu.offsetWidth - this.margin}
if (MENU.isMobile) {x = Math.max(5,x-Math.floor(menu.offsetWidth/2)); y -= 20}
- MENU.skipUp = true;
+ MENU.skipUp = event.isContextMenu;
} else {
var side = "left", mw = parent.offsetWidth;
x = (MENU.isMobile ? 30 : mw - 2); y = 0;
@@ -227,6 +227,10 @@
div.parentNode.removeChild(div);
if (this.msieBackgroundBug) {detachEvent("onresize",MENU.Resize)}
}
+ if (MENU.jax.hover) {
+ delete MENU.jax.hover.nofade;
+ MENU.jax.outputJax.UnHover(MENU.jax);
+ }
},
False: FALSE,
@@ -265,10 +269,11 @@
Touchstart: function (event) {return MENU.Event(event,this,"Touchstart")},
Touchend: function (event) {return MENU.Event(event,this,"Touchend")},
Event: function (event,menu,type,force) {
- if (MENU.isMobile && type === "Mouseover" && !force) {return FALSE(event)}
+ if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)}
if (MENU.skipUp) {
if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)}
- if (type.match(/Touchstart/)) {delete MENU.skipUp}
+ if (type === "Touchstart" ||
+ (type === "Mousedown" && !MENU.skipMousedown)) {delete MENU.skipUp}
}
if (!event) {event = window.event}
var item = menu.menuItem;
@@ -759,9 +764,13 @@
delete CONFIG.styles["#MathJax_About"].filter;
delete CONFIG.styles[".MathJax_Menu"].filter;
}
+ },
+ Firefox: function (browser) {
+ MENU.skipMouseover = browser.isMobile && browser.versionAtLeast("6.0");
+ MENU.skipMousedown = browser.isMobile;
}
});
- MENU.isMobile = MathJax.Hub.Browser.isMobile;
+ MENU.isMobile = MathJax.Hub.Browser.isMobile;
MENU.noContextMenu = MathJax.Hub.Browser.noContextMenu;
/*************************************************************/
diff --git a/unpacked/jax/output/HTML-CSS/config.js b/unpacked/jax/output/HTML-CSS/config.js
@@ -24,7 +24,7 @@
MathJax.OutputJax["HTML-CSS"] = MathJax.OutputJax({
id: "HTML-CSS",
- version: "1.1.8",
+ version: "1.1.9",
directory: MathJax.OutputJax.directory + "/HTML-CSS",
extensionDir: MathJax.OutputJax.extensionDir + "/HTML-CSS",
autoloadDir: MathJax.OutputJax.directory + "/HTML-CSS/autoload",
diff --git a/unpacked/jax/output/HTML-CSS/jax.js b/unpacked/jax/output/HTML-CSS/jax.js
@@ -248,6 +248,27 @@
".MathJax .MathJax_HitBox": {
cursor: "text"
},
+
+ ".MathJax_Hover_Frame": {
+ "border-radius": ".25em", // Opera 10.5 and IE9
+ "-webkit-border-radius": ".25em", // Safari and Chrome
+ "-moz-border-radius": ".25em", // Firefox
+ "-khtml-border-radius": ".25em", // Konqueror
+
+ "box-shadow": "0px 0px 15px #83A", // Opera 10.5 and IE9
+ "-webkit-box-shadow": "0px 0px 15px #83A", // Safari and Chrome
+ "-moz-box-shadow": "0px 0px 15px #83A", // Forefox 3.5
+ "-khtml-box-shadow": "0px 0px 15px #83A", // Konqueror
+
+ border: ".1em solid #A6D ! important",
+ display: "inline-block", position:"absolute"
+ },
+ ".MathJax_Hover_Arrow": {
+ position:"absolute",
+ top:"-5px", right:"-9px",
+ width:"15px", height:"11px",
+ cursor:"pointer"
+ },
"#MathJax_Tooltip": {
position: "absolute", left: 0, top: 0,
@@ -425,8 +446,8 @@
if (this.config.showMathMenu && (this.settings.context === "MathJax" || force)) {
if (this.safariContextMenuBug) {setTimeout("window.getSelection().empty()",0)}
if (this.msieEventBug) {event = window.event}
- if (math.parentNode.className === "MathJax_Display") {math = math.parentNode}
- return EVENT.ContextMenu(event,math);
+ this.ClearHoverTimer();
+ return EVENT.ContextMenu(event,this.getJaxFromMath(math));
}
},
Mousedown: function (event,math) {
@@ -440,6 +461,105 @@
return this.ContextMenu(event,math,true);
}
},
+ Mouseover: function (event,math) {
+ var from = event.fromElement || event.relatedTarget,
+ to = event.toElement || event.target;
+ if (from && to && from.isMathJax != to.isMathJax) {
+ var jax = this.getJaxFromMath(math);
+ if (jax.hover) {this.ReHover(jax)} else {this.HoverTimer(jax,math)}
+ return EVENT.False(event);
+ }
+ },
+ Mouseout: function (event,math) {
+ var from = event.fromElement || event.relatedTarget,
+ to = event.toElement || event.target;
+ if (from && to && from.isMathJax != to.isMathJax) {
+ var jax = this.getJaxFromMath(math);
+ if (jax.hover) {this.UnHover(jax)} else {this.ClearHoverTimer()}
+ return EVENT.False(event);
+ }
+ },
+ Mousemove: function (event,math) {
+ var jax = this.getJaxFromMath(math); if (jax.hover) return;
+ if (this.lastX == event.clientX && this.lastY == event.clientY) return;
+ this.lastX = event.clientX; this.lastY = event.clientY;
+ this.HoverTimer(jax,math);
+ return EVENT.False(event);
+ },
+
+ HoverTimer: function (jax,math) {
+ this.ClearHoverTimer();
+ this.hoverTimer = setTimeout(MathJax.Callback(["Hover",this,jax,math]),this.settings.hover);
+ },
+ ClearHoverTimer: function () {
+ if (this.hoverTimer) {clearTimeout(this.hoverTimer); delete this.hoverTimer}
+ },
+
+ Hover: function (jax,math) {
+ // check for MathZoom hover
+ jax.hover = {opacity:0};
+ var span = jax.root.HTMLspanElement(), bbox = span.bbox;
+ var dx = .25, dy = .33, dd = .1; // frame size
+ if (this.msieBorderWidthBug) {dd = 0}
+ jax.hover.id = "MathJax-Hover-"+jax.inputID.replace(/.*-(\d+)$/,"$1");
+ var frame = HTMLCSS.Element("span",{
+ id:jax.hover.id, isMathJax: true,
+ style:{display:"inline-block", "z-index":1, width:0, height:0, position:"relative"}
+ },[["span",{
+ className:"MathJax_Hover_Frame", isMathJax: true,
+ style:{
+ display:"inline-block", position:"absolute",
+ top:HTMLCSS.Em(-bbox.h-dy-dd), left:HTMLCSS.Em(-dx-dd),
+ width:HTMLCSS.Em(bbox.w+2*dx), height:HTMLCSS.Em(bbox.h+bbox.d+2*dy),
+ opacity:0, filter:"alpha(opacity=0)"
+ }},[[
+ "img",{
+ className: "MathJax_Hover_Arrow", isMathJax: true, math: math,
+ src: AJAX.fileURL(MathJax.OutputJax.imageDir+"/MenuArrow-15.png"),
+ onclick: this.HoverMenu
+ }
+ ]]
+ ]]
+ );
+ span.parentNode.insertBefore(frame,span); span.style.position = "relative";
+ this.ReHover(jax,.2);
+ },
+ ReHover: function (jax) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ jax.hover.remove = setTimeout(MathJax.Callback(["UnHover",this,jax]),15*1000);
+ this.HoverFadeTimer(jax,.2);
+ },
+ UnHover: function (jax) {
+ if (!jax.hover.nofade) {this.HoverFadeTimer(jax,-.05,400)}
+ },
+ HoverFade: function (jax) {
+ delete jax.hover.timer;
+ jax.hover.opacity = Math.max(0,Math.min(1,jax.hover.opacity + jax.hover.inc));
+ jax.hover.opacity = Math.floor(1000*jax.hover.opacity)/1000;
+ var span = document.getElementById(jax.hover.id);
+ span.firstChild.style.opacity = jax.hover.opacity;
+ span.firstChild.style.filter = "alpha(opacity="+Math.floor(100*jax.hover.opacity)+")";
+ if (jax.hover.opacity === 1) {return}
+ if (jax.hover.opacity) {this.HoverFadeTimer(jax,jax.hover.inc); return}
+ var frame = document.getElementById(jax.hover.id);
+ frame.parentNode.removeChild(frame);
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ delete jax.hover;
+ },
+ HoverFadeTimer: function (jax,inc,delay) {
+ jax.hover.inc = inc;
+ if (!jax.hover.timer) {
+ jax.hover.timer = setTimeout(MathJax.Callback(["HoverFade",this,jax]),(delay||50));
+ }
+ },
+ HoverMenu: function (event) {
+ if (!event) {event = window.event}
+ HTMLCSS.ContextMenu(event,this.math,true);
+ },
+ getJaxFromMath: function (math) {
+ if (math.parentNode.className === "MathJax_Display") {math = math.parentNode}
+ return HUB.getJaxFor(math.nextSibling);
+ },
initImg: function (span) {},
initHTML: function (math,span) {},
@@ -1284,7 +1404,7 @@
span.style.cssText = this.style;
if (span.style.fontSize) {this.mathsize = span.style.fontSize; span.style.fontSize = ""}
}
- this.spanID = HTMLCSS.GetID();
+ if (!this.spanID) {this.spanID = HTMLCSS.GetID()}
span.id = (this.id || "MathJax-Span-"+this.spanID) + HTMLCSS.idPostfix;
span.bbox = {w:0, h:0, d:0, lw:0, lr:0};
if (this.href) {span.parentNode.bbox = span.bbox}
@@ -2103,7 +2223,8 @@
}
}
return span;
- }
+ },
+ HTMLspanElement: MML.mbase.prototype.HTMLspanElement
});
MML.TeXAtom.Augment({
@@ -2141,6 +2262,13 @@
});
HUB.Register.StartupHook("End Config",function () {
+
+ if (MathJax.Hub.Browser.isMobile) {
+ var arrow = HTMLCSS.config.styles[".MathJax_Hover_Arrow"];
+ arrow.width = "25px"; arrow.height = "18px";
+ arrow.top = "-11px"; arrow.right = "-15px";
+ }
+
//
// Handle browser-specific setup
//