Display MathJax dynamically only when there are delimiters - javascript

I have been tweaking with below sample code. The documentation for MathJax isn't very complete. Could someone more experience tell how I should modify the below code so that Tex is only parse when I have specified delimiters like $\alpha$. I would like to make it work like on math.stackexchange.
<html>
<head>
<title>MathJax Dynamic Math Test Page</title>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [["$","$"],["\\(","\\)"]]
}
});
</script>
<script type="text/javascript"
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML-full">
</script>
</head>
<body>
<script>
//
// Use a closure to hide the local variables from the
// global namespace
//
(function () {
var QUEUE = MathJax.Hub.queue; // shorthand for the queue
var math = null; // the element jax for the math output.
//
// Get the element jax when MathJax has produced it.
//
QUEUE.Push(function () {
math = MathJax.Hub.getAllJax("MathOutput")[0];
});
//
// The onchange event handler that typesets the
// math entered by the user
//
window.UpdateMath = function (TeX) {
QUEUE.Push(["Text",math,"\\displaystyle{"+TeX+"}"]);
}
})();
</script>
<textarea id="MathInput" size="50" onkeyup="UpdateMath(this.value)"></textarea>
<div id="MathOutput">
You typed: ${}$
</div>
</body>
</html>

The sample code you posted takes the contents of the MathInput and replaces the first MathJax element with the new "math" from the MathInput. What you want is to Typeset the MathInput and create new MathJax elements for the delimited text. I setup a jsFiddle example here:
http://jsfiddle.net/Zky72/2/
The main change is in the UpdateMath function:
window.UpdateMath = function (TeX) {
//set the MathOutput HTML
document.getElementById("MathOutput").innerHTML = TeX;
//reprocess the MathOutput Element
MathJax.Hub.Queue(["Typeset",MathJax.Hub,"MathOutput"]);
}

Related

Changing the inner HTML of a div to a variable collected from user

I have a site, which takes a html code block from the user, for the site time.is and then is supposed to show that later. The code is taken as a JavaScript Prompt and the stored in the local storage
let timeislink= prompt("Please enter the code as it is, with no spaces, or your clock might break");
localStorage.setItem("timeisperslink", timeislink);
And for adding it to the div, I take the local storage value, and store it in a variable and try to pass that under the .innerHTML function, but that doesn't seem to be working
function changetime(){
let timedivneed= document.getElementById('timeisdynmdiv')
let usetimeis= localStorage.getItem("timeisperslink")
timedivneed.innerHTML+= usetimeis;
}
Any help is appreciated
Edit:- #HTML of the page in which div has to be changed#
<!DOCTYPE html>
<html lang="en">
<body onload="myFunction()">
<h2 id="timewish" onload="changetime()"></h2>
<div id="timeisdynmdiv">
</div>
</body>
</html>
Have removed unwanted things
What I think is that your script block is not located anywhere in the HTML. For best results, add your script block after the <div>. So:
<!DOCTYPE html>
<html lang="en">
<body onload="myFunction()">
<h2 id="timewish" onload="changetime()"></h2>
<div id="timeisdynmdiv">
</div>
<script>
window.onload = function(){
let timeislink= prompt("Please enter the code as it is, with no spaces, or your clock might break");
localStorage.setItem("timeisperslink", timeislink);
}
function changetime(){
let timedivneed= document.getElementById('timeisdynmdiv')
let usetimeis= localStorage.getItem("timeisperslink")
timedivneed.innerHTML+= usetimeis;
}
</script>
</body>
</html>
Tell me if this doesn't work for you and I'll try to fix it.
Use window load event and put your logic to get localStorage data.
// Test mock to set data in localstorage
document.onreadystatechange = function(e) {
if (document.readyState === 'complete') {
console.log("readyState");
localStorage.setItem("timeisperslink", "test data description");
}
};
window.addEventListener('load', (event) => {
console.log("loaded");
let timedivneed = document.getElementById('timeisdynmdiv')
let usetimeis = localStorage.getItem("timeisperslink")
timedivneed.innerHTML += usetimeis;
});

Is there any way for more than one Google Translate widget to be loaded on a page

Is there any way possible to load a Google Translate widget in the sidebar and one in the footer, for example.
Every way I've tried has only loaded so that both appear in the location of the first instance on the page.
After a bit of tinkering I kinda felt obligated to solve the puzzle! You can skip to the good part by checking out the jsfiddle: (it works as of now but knowing google it might not tomorrow)
http://jsfiddle.net/melfy/15zr6ov0/
Lets begin:
First google translate is loaded and adds a listener for a select box it adds to the DOM after you call the right element but we need that change event to call a change for a select box we're going to clone from the original one to get google to update the translation, this gets a bit messy as we over take the prototype (which is usually bad practice)
Start by adding your header element:
<div id="google_translate_element"></div>
Then we add our footer element:
<div id="google_translate_element2"></div>
Next we pull in the google translator
<script type="text/javascript" src="https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
Now we get to the good part:
<script type="text/javascript">
// store google translate's change event
trackChange = null;
pageDelayed = 3000;
// overwrite prototype to snoop, reset after we find it (keep this right before translate init)
Element.prototype._addEventListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = function(a,b,c) {
reset = false;
// filter out first change event
if (a == 'change'){
trackChange = b;
reset = true;
}
if(c==undefined)
c=false;
this._addEventListener(a,b,c);
if(!this.eventListenerList)
this.eventListenerList = {};
if(!this.eventListenerList[a])
this.eventListenerList[a] = [];
this.eventListenerList[a].push({listener:b,useCapture:c});
if (reset){
Element.prototype.addEventListener = Element.prototype._addEventListener;
}
};
function googleTranslateElementInit() {
new google.translate.TranslateElement({ pageLanguage: 'en' }, 'google_translate_element');
let first = $('#google_translate_element');
let second = $('#google_translate_element2');
let nowChanging = false;
// we need to let it load, since it'll be in footer a small delay shouldn't be a problem
setTimeout(function(){
select = first.find('select');
// lets clone the translate select
second.html(first.clone());
second.find('select').val(select.val());
// add our own event change
first.find('select').on('change', function(event){
if (nowChanging == false){
second.find('select').val($(this).val());
}
return true;
});
second.find('select').on('change', function(event){
if (nowChanging){
return;
}
nowChanging = true;
first.find('select').val($(this).val());
trackChange();
// give this some timeout incase changing events try to hit each other
setTimeout(function(){
nowChanging = false;
}, 1000);
});
}, pageDelayed);
}
</script>
You can change the pageDelayed variable to trigger quicker or slower but if it's in your footer, bumping it up to delay longer may help it work more efficiently depending on your page load
Unfortunately, you can not have the widget be loaded more than once in a single page. Google just doesn't allow for that. One potential workaround would be putting the code in an iFrame and then putting two iFrames onto your webpage.
Create a file called iframe.html
<html>
<head>
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit">
</head>
<body>
<div id="google_translate_element"></div>
<script type="text/javascript">
function googleTranslateElementInit(){
new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element');
}
</script>
</body>
</head>
</html>
In your other file put code something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Google Translate</title>
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?b=googleTranslateElementInit"></script>
</head>
<body>
<div id="header" style="background-color: red;">
<iframe src="iframe.html"></iframe>
<strong>A</strong>
</div>
<div id="footer" style="background-color: blue;">
<iframe src="iframe.html"></iframe>
<strong>B</strong>
</div>
</body>
</html>

Revealing module pattern and jquery failed

I have a file call text.js and it has
var Text = function(canvas){
var textField = $('#textField'),
addTextButton = $('#addText');
var init = function(){
addTextButton.click(function(){
alert('won"t work?')
});
},
resetTextField = function(){
// it work if I put the selector here like var textField = $('#textField'),
textField.val(''); // won't work
};
return{
init:init
}
}();
It's included in my index.html. In there I do init like
$(function(){
Text.init();
}());
The problem is the even't can't be fired. I think I messed up something.
The code in Text is run immediately, and returns the object with init on it. If you run that code before the elements it looks up exist, for instance:
<!doctype html>
<html>
<head>
<!-- ... --->
<script src="text.js"></script><!-- Problem here -->
<script>
$(function(){
Text.init();
}());
</script>
</head>
<body>
<!-- ... --->
<input id="textField"><input id="addText" type="button" value="Add">
<!-- ... -->
</body>
</html>
... you'll end up with empty jQuery objects in textField and addTextButton.
Separately, you're also running the function you're trying to pass ready immediately (and then passing undefined into ready), the problem is here:
$(function(){
Text.init();
}());
// ^^---------- problem
You don't want those (). You want to pass the function into ready:
$(function(){
Text.init();
}); // <== Note no ()
If you're going to have the init method, it would be best to put all your initialization inside it rather than putting it in two places:
var Text = function(canvas){
var textField, addTextButton;
var init = function(){
textField = $('#textField');
addTextButton = $('#addText');
addTextButton.click(function(){
alert('won"t work?')
});
},
resetTextField = function(){
// it work if I put the selector here like var textField = $('#textField'),
textField.val(''); // won't work
};
return{
init:init
}
}();
Note, though, that if you follow the usual best practice of putting your scripts at the end of the document, just prior to the closing </body> tag, the elements defined above that will exist and be available, which would make using ready (and init) unnecessary. So if you control where the script tags go, that's an option.
So for instance:
<!doctype html>
<html>
<head>
<!-- ... --->
</head>
<body>
<!-- ... -->
<input id="textField"><input id="addText" type="button" value="Add">
<!-- ... -->
<script src="text.js"></script>
<script>
$(function(){
Text.init();
});
</script>
</body>
</html>
You are invoking the function once defined using () at a point where DOM is not loaded. Thus, all selectors return zero nodes.
var Text = function(canvas){
// ...
}();
^^
Remove that. And when you call it, you need to instance the function first, and keep that instance reference (if you wish to).
var text = new Text();
text.init();

Replacing an element on page using JavaScript

I have a video player that runs client-side, and I want to store a configuration for it so I don't have to write it each single time.
I had an idea where I could place a marker in the markup, such as:
<player id="Player1" #marker></player>
Or something to that effect, and then replace #marker with the settings I have stored in the javascript function.
I know some basic Javascript, but I have never done something so advanced.
Here is an example:
<script type="text/javascript" language="JavaScript">
flowplayer("player", "http://www.easymuaythai.com/Videos/FlowPlayer/flowplayer-3.2.7.swf", #marker);
</script>
Where it says #marker, I want to replace it with:
{
clip: {
Scaling: 'fit',
onStart: function (clip) {
var w = parseInt(clip.metaData.width, 10),
h = parseInt(clip.metaData.height, 10);
$(this.getParent()).css({
width: w,
height: h
});
}
}
}
You can use JQuery,
add this to the Head section of your page :
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
then write this in your js file or section
$('#player1').attr('playerConfiguration', 'Value');
that will cause <player id="Player1" playerConfiguration="value"></player>
hope that helps...
Maybe this will help you ? It creates and sets an attribute (marker) to the player node and it gives it a value (config)
<html>
<head>
<script type="text/javascript">
var p = {
onload: function() {
var markerAttribute = document.createAttribute("marker");
document.getElementById("Player1").setAttributeNode(markerAttribute);
markerAttribute.nodeValue = "config";
}
};
</script>
</head>
<body onload="p.onload()">
<div>
<player id="Player1"></player>
</div>
</body>
</html>
You could include Jquery and do the following:
$("#Player1").attr('config', 'write=all&settings;you,need');
Or something like:
$("#Player1").replaceWith('The html code u want');

Two Javascript scripts conflicting (show/hide)

I have two Javascript scripts on a site. One is an accordion (show/hide) and the other is a basic script to show/hide based on a hyperlink click. Both scripts work fine independently, but once together on the same page the accordion one stops working: the click to display the items in the accordion stops working. Here's the code:
<link rel="stylesheet" href="[template_url]/js/tinycord/tinycord.css" type="text/css" />
<style>
.inner-boxes .box3, .details1 {
display:none;
}
</style>
<script type="text/javascript">
var parentAccordion=new TINY.accordion.slider("parentAccordion");
parentAccordion.init("acc","h3",0,-1);
</script>
<script>
$(function(){
$(".para").click(function(){
$("#fillit").html($(this).next(".details1").html());
});
$(".details1:first").clone().appendTo("#fillit").show();
});
</script>
<script type="text/javascript" src="[template_url]/js/tinycord/script.js"></script>
content of script.js
var TINY={};
function T$(i){return document.getElementById(i)}
function T$$(e,p){return p.getElementsByTagName(e)}
TINY.accordion=function(){
function slider(n){this.n=n; this.a=[]}
slider.prototype.init=function(t,e,m,o,k){
var a=T$(t), i=s=0, n=a.childNodes, l=n.length; this.s=k||0; this.m=m||0;
for(i;i<l;i++){
var v=n[i];
if(v.nodeType!=3){
this.a[s]={}; this.a[s].h=h=T$$(e,v)[0]; this.a[s].c=c=T$$('div',v)[0]; h.onclick=new Function(this.n+'.pr(0,'+s+')');
if(o==s){h.className=this.s; c.style.height='auto'; c.d=1}else{c.style.height=0; c.d=-1} s++
}
}
this.l=s
};
slider.prototype.pr=function(f,d){
for(var i=0;i<this.l;i++){
var h=this.a[i].h, c=this.a[i].c, k=c.style.height; k=k=='auto'?1:parseInt(k); clearInterval(c.t);
if((k!=1&&c.d==-1)&&(f==1||i==d)){
c.style.height=''; c.m=c.offsetHeight; c.style.height=k+'px'; c.d=1; h.className=this.s; su(c,1)
}else if(k>0&&(f==-1||this.m||i==d)){
c.d=-1; h.className=''; su(c,-1)
}
}
};
function su(c){c.t=setInterval(function(){sl(c)},20)};
function sl(c){
var h=c.offsetHeight, d=c.d==1?c.m-h:h; c.style.height=h+(Math.ceil(d/2)*c.d)+'px';
c.style.opacity=h/c.m; c.style.filter='alpha(opacity='+h*100/c.m+')';
if((c.d==1&&h>=c.m)||(c.d!=1&&h==1)){if(c.d==1){c.style.height='auto'} clearInterval(c.t)}
};
return{slider:slider}
}();
I don't think these scripts actually conflict. You are loading the accordion code after you try to use it. Perhaps reorder your script tags.
<script type="text/javascript" src="[template_url]/js/tinycord/script.js"></script>
should go before the use of TINY.accordion which it defines:
var parentAccordion=new TINY.accordion.slider("parentAccordion");
I don't know enough about the meaning of the string arguments in the call to init, but perhaps you could change the script element that creates the accordion and initializes it to happen on document load, for example by delaying it using jQuery's $.ready or by moving it after any elements whose ids appear in those string arguments.
Also the accordion code is unintentionally using a global s. And short names like s can easily collide which is a maintenance hazard even if not the cause of your immediate problem.
var a=T$(t), i=s=0, ...
is not declaring s locally. Perhaps edit it to say
var a=T$(t), s, i=s=0, ...
<script language="javascript">
jQuery.noConflict();
var b=jQuery.noConflict() || $.noConflict;
b(document).ready(function(){
b(".btn-slide").click(function(){
b("#panel").slideToggle("slow");
b(this).toggleClass("active"); return false;
});
});
</script>
Then instead of $ use b to access jQuery.

Categories