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.

This commit is contained in:
Davide P. Cervone 2011-08-19 09:19:22 -04:00
parent 5b421d32d1
commit 2367f0e92b
4 changed files with 164 additions and 17 deletions

View File

@ -30,7 +30,7 @@ if (!window.MathJax) {window.MathJax= {}}
if (!MathJax.Hub) { // skip if already loaded if (!MathJax.Hub) { // skip if already loaded
MathJax.version = "1.1a"; 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)} if (AJAX.loadingMathMenu) {return False(event)}
var jax = BASE.OutputJax[math.jaxID]; var jax = BASE.OutputJax[math.jaxID];
if (!event) {event = window.event} if (!event) {event = window.event}
event.isContextMenu = (type === "ContextMenu");
return jax.HandleEvent(event,type,math); 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 // 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; var MENU = BASE.Menu;
if (MENU) { if (MENU) {
MENU.jax = BASE.Hub.getJaxFor(math.nextSibling); MENU.jax = jax;
MENU.menu.items[1].menu.items[1].name = MENU.menu.Find("Format").menu.items[1].name =
(MENU.jax.inputJax.id === "MathML" ? "Original" : MENU.jax.inputJax.id); (MENU.jax.inputJax.id === "MathML" ? "Original" : MENU.jax.inputJax.id);
return MENU.menu.Post(event); return MENU.menu.Post(event);
} else { } else {
if (!AJAX.loadingMathMenu) { if (!AJAX.loadingMathMenu) {
AJAX.loadingMathMenu = true; 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( CALLBACK.Queue(
AJAX.Require("[MathJax]/extensions/MathMenu.js"), AJAX.Require("[MathJax]/extensions/MathMenu.js"),
function () {delete AJAX.loadingMathMenu; if (!BASE.Menu) {BASE.Menu = {}}}, 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); return this.False(event);
@ -1329,6 +1337,8 @@ MathJax.Hub = {
ALT: false, // require Alt or Option? ALT: false, // require Alt or Option?
CMD: false, // require CMD? CMD: false, // require CMD?
Shift: false, // require Shift? 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 zscale: "200%", // the scaling factor for MathZoom
renderer: "", // set when Jax are loaded renderer: "", // set when Jax are loaded
font: "Auto", // what font HTML-CSS should use font: "Auto", // what font HTML-CSS should use

View File

@ -176,9 +176,9 @@
if (MENU.isMobile) { if (MENU.isMobile) {
HTML.addElement(menu,"img",{ HTML.addElement(menu,"img",{
src: MathJax.Ajax.fileURL(MathJax.OutputJax.imageDir+"/CloseX-31.png"), 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"}, 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; this.posted = true;
@ -193,7 +193,7 @@
if (x + menu.offsetWidth > document.body.offsetWidth - this.margin) if (x + menu.offsetWidth > document.body.offsetWidth - this.margin)
{x = document.body.offsetWidth - menu.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} if (MENU.isMobile) {x = Math.max(5,x-Math.floor(menu.offsetWidth/2)); y -= 20}
MENU.skipUp = true; MENU.skipUp = event.isContextMenu;
} else { } else {
var side = "left", mw = parent.offsetWidth; var side = "left", mw = parent.offsetWidth;
x = (MENU.isMobile ? 30 : mw - 2); y = 0; x = (MENU.isMobile ? 30 : mw - 2); y = 0;
@ -227,6 +227,10 @@
div.parentNode.removeChild(div); div.parentNode.removeChild(div);
if (this.msieBackgroundBug) {detachEvent("onresize",MENU.Resize)} if (this.msieBackgroundBug) {detachEvent("onresize",MENU.Resize)}
} }
if (MENU.jax.hover) {
delete MENU.jax.hover.nofade;
MENU.jax.outputJax.UnHover(MENU.jax);
}
}, },
False: FALSE, False: FALSE,
@ -265,10 +269,11 @@
Touchstart: function (event) {return MENU.Event(event,this,"Touchstart")}, Touchstart: function (event) {return MENU.Event(event,this,"Touchstart")},
Touchend: function (event) {return MENU.Event(event,this,"Touchend")}, Touchend: function (event) {return MENU.Event(event,this,"Touchend")},
Event: function (event,menu,type,force) { 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 (MENU.skipUp) {
if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)} 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} if (!event) {event = window.event}
var item = menu.menuItem; var item = menu.menuItem;
@ -759,6 +764,10 @@
delete CONFIG.styles["#MathJax_About"].filter; delete CONFIG.styles["#MathJax_About"].filter;
delete CONFIG.styles[".MathJax_Menu"].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;

View File

@ -24,7 +24,7 @@
MathJax.OutputJax["HTML-CSS"] = MathJax.OutputJax({ MathJax.OutputJax["HTML-CSS"] = MathJax.OutputJax({
id: "HTML-CSS", id: "HTML-CSS",
version: "1.1.8", version: "1.1.9",
directory: MathJax.OutputJax.directory + "/HTML-CSS", directory: MathJax.OutputJax.directory + "/HTML-CSS",
extensionDir: MathJax.OutputJax.extensionDir + "/HTML-CSS", extensionDir: MathJax.OutputJax.extensionDir + "/HTML-CSS",
autoloadDir: MathJax.OutputJax.directory + "/HTML-CSS/autoload", autoloadDir: MathJax.OutputJax.directory + "/HTML-CSS/autoload",

View File

@ -249,6 +249,27 @@
cursor: "text" 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": { "#MathJax_Tooltip": {
position: "absolute", left: 0, top: 0, position: "absolute", left: 0, top: 0,
width: "auto", height: "auto", width: "auto", height: "auto",
@ -425,8 +446,8 @@
if (this.config.showMathMenu && (this.settings.context === "MathJax" || force)) { if (this.config.showMathMenu && (this.settings.context === "MathJax" || force)) {
if (this.safariContextMenuBug) {setTimeout("window.getSelection().empty()",0)} if (this.safariContextMenuBug) {setTimeout("window.getSelection().empty()",0)}
if (this.msieEventBug) {event = window.event} if (this.msieEventBug) {event = window.event}
if (math.parentNode.className === "MathJax_Display") {math = math.parentNode} this.ClearHoverTimer();
return EVENT.ContextMenu(event,math); return EVENT.ContextMenu(event,this.getJaxFromMath(math));
} }
}, },
Mousedown: function (event,math) { Mousedown: function (event,math) {
@ -440,6 +461,105 @@
return this.ContextMenu(event,math,true); 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) {}, initImg: function (span) {},
initHTML: function (math,span) {}, initHTML: function (math,span) {},
@ -1284,7 +1404,7 @@
span.style.cssText = this.style; span.style.cssText = this.style;
if (span.style.fontSize) {this.mathsize = span.style.fontSize; span.style.fontSize = ""} 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.id = (this.id || "MathJax-Span-"+this.spanID) + HTMLCSS.idPostfix;
span.bbox = {w:0, h:0, d:0, lw:0, lr:0}; span.bbox = {w:0, h:0, d:0, lw:0, lr:0};
if (this.href) {span.parentNode.bbox = span.bbox} if (this.href) {span.parentNode.bbox = span.bbox}
@ -2103,7 +2223,8 @@
} }
} }
return span; return span;
} },
HTMLspanElement: MML.mbase.prototype.HTMLspanElement
}); });
MML.TeXAtom.Augment({ MML.TeXAtom.Augment({
@ -2141,6 +2262,13 @@
}); });
HUB.Register.StartupHook("End Config",function () { 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 // Handle browser-specific setup
// //