How to handle conflicting libraries? - mathquill vs bootstrap - javascript

I'm having a sort of conflict between two libraries I'm using, Bootstrap and Mathquill. I'm using bootstrap for the layout, structure, and overall UI of the website, and Mathquill for interactive LaTeX rendering- basically, letting the user type in math in a nice, "textbook style" format.
My problem is that bootstrap seems to conflict with Mathquill, in the rendering of the math. Here is the structure of my page:
HTML
<div id="container">
<span id="input" class="mathquill-editable"></span>
</div>
CSS
#container {
padding: 5px;
width: 80%;
}
#input {
width: 100%;
padding: 15px;
margin: 5px;
}
Without Bootstrap running, the math renders perfectly. Here is a fiddle, and below is a screenshot:
With Bootstrap, I have the same code, except that I add the classes panel and panel-default to div#container. User inputted math, doesn't render well, because the spacing seems to be wrong, and it doesn't respect the boundaries of span#input. Here is a fiddle, and below is a screenshot:
I think the problem here is the bootstrap causes MathQuill's math spans (inside of span#input) to have more padding, thus the problems with MathQuill. Is there a way to let bootstrap ignore the area inside span#input?
Obviously, I could just copy the styling I need from bootstrap and just apply it to the areas I need the styling for, but this would be a hassle considering that I'm using it quite extensively.
Any thoughts?

This can be corrected by modifying the mathquill-rendered-math class in mathquill.css file.
just add the following.
.mathquill-rendered-math * {
box-sizing: content-box;
top: auto;}

You could use a iframe for applying the mathematical stylesheet only. I don't think it will cost too much speed to load if you're using MathQuill extensively.
I would do something like this:
<html>
<head>
<link href="bootstrap.css" rel="stylesheet" type="text/css" />
</head>
<body>
<iframe src="math.php#f=2*2"></iframe>
<iframe src="math.php#f=3*5"></iframe>
</body>
</html>
And then let math.php output something like this:
<html>
<head>
<link href="mathquill.css" rel="stylesheet" type="text/css" />
</head>
<body>
<script>
// Generate content dynamically with JavaScript from parameter `f` so the this page can be cached.
</script>
</body>
</html>
Another approach would be creating your own custom bootstrap stylesheet. You can download the LESS sourcecode on its website.

Thanks #Tim for the great answer, but I found a better solution here. I will wrap the rules in my own class bootstrap-enabled, so that bootstrap's styles only apply where I want them to.

What I've done to solve this is find the areas where they conflict and use my custom CSS to override Bootstrap for those elements.
For instance, the powers look bad/go beyond the border because of
sup {
top: -0.5em;
}
in Bootstrap. I've reset this to 0 for mathquill elements in my CSS.
You correctly point out that Bootstrap is fiddling with padding, which makes the denominator wrap around. Specifically Bootstrap uses "border-box" rather than the default "content-box" for box-sizing. Setting:
.denominator {
box-sizing: content-box;
}
fixes this.
This fixes the two problems in your example. I'll update this post as I find more conflicts (and their sources).

I just solved mathquill + bootstrap conflict by adding css-resetter from this answer into beginning of mathquill.css (change .reset-this to .mathquill-rendered-math *)

Related

AOS (animate-on-scroll) elements invisible on static site

I'm making a site for a client and trying to implement AOS library to make it look more dynamic.
I've followed instructions from the GitHub :
Add to <head>
<link rel="stylesheet" href="https://unpkg.com/aos#next/dist/aos.css" />
Add before </body>
<script src="https://unpkg.com/aos#next/dist/aos.js"></script>
<script>
AOS.init();
</script>
No luck. I've applied data-aos="fade-in" to a div in the Services section of this site (it should be obvious with the missing box) and it doesn't display at all for me.
Can anyone help?
Thank you,
Jack
I've looked at the site and I think it has something to do with this css:
html, body {
overflow: hidden;
overflow-y: scroll;
}
This also caused a double scrollbar for me, you should remove those two lines.

Swapping two style-sheets CSS file using Javascript

I am writing a web-app for a mobile device, what I am doing is to change dynamically the css and store that option for the user, I have been looking all night long, googling methods and way to achieve my objective but nothing worked for me.
This is the type of button that I am using, and here comes up another problem, because I wasn't able to Check and Uncheck the checkbox.
HTML
<input id="#checkbox" type="checkbox" checked onclick="swapStyleSheet()">
The only thing that worked fine for me is this:
<head>
<link id="pagestyle" rel="stylesheet" type ="text/css" href="default.css">
<script type="text/javascript">
function swapStyleSheet(sheet) {
document.getElementById('pagestyle').setAttribute('href',sheet);
}
</script>
</head>
and in the body
<input id="#checkbox" type="checkbox" checked onclick="swapStyleSheet("Second.css")">
But this is not dynamically because once the user taps the button is not able to go back and I am not sure that works on a mobile device
Any suggestion how to proceed?
You forgot the quotes around Second.css
onclick="swapStyleSheet('Second.css')"
Without quotes, it's a syntax error (but your console is already telling you this).
Here there is an exemptional link that shows step by step how to how to switch two CSS sheet-file
But for the type of input, I am not sure how you can do
I would not recommend to change your stylesheets like this.
Here are my reasons why:
Loading another file will probably cause a "hard" transition between your two styles. You writing a mobile web-app, so imagine someone with unstable internet connection loads your application. Your web-app will be unstyled for a couple of seconds.
Browser needs to load another file (if you want to switch back, it will probably load the original file again, depending on cache settings)
Can be solved much easier with .scss for example (but also with plain .css). I have got an example for you down below. You can even add transitions, so your changes are much more pleasant.
function rotateStyle () {
document.body.id = document.body.id == 'alternate' ? '' : 'alternate';
}
body {
background-color: #FFFFFF;
color: #000000;
/* you could also add transitions */
transition: background-color 2s;
}
body#alternate {
background-color: #000000;
color: #FFFFFF;
}
<body>
<!-- your content -->
<button onclick="rotateStyle()">Change your style</button>
</body>

jQuery Mobile Beta: can no longer use $('[data-role=header]')?

I used to be able to get hold of
$('[data-role=header]').first().height()
in alpha with jQuery 1.5.2, but no longer can in beta with jQuery 1.6.1. Has something changed?
Full code - this writes 0 to console.log...
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript"
src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
console.log($('[data-role=header]').first().height());
});
</script>
</head>
<body>
<div data-role="page" id="home">
<div data-role="header">
<h1>Header</h1>
</div>
<div data-role="content">
//lots of code
</div>
</div>
</body>
</html>
However, change this to jQuery 1.5.2 and jQuery Mobile alpha:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a4/jquery.mobile-1.0a4.min.js"></script>
and it writes the non-zero height of the header div.
Incidentally, it is also non-zero with jQuery 1.6.1 but without jQuery Mobile. So it's something to do with the jQuery Mobile rendering.
Can't see anything in the release notes to suggest what might have happened, but I'm no jQuery expert.
The change that is causing the difference is "Responsive design helper classes: Now deprecated"
We include a set of responsive design helper classes designed to make it easy to build a responsive design that adapts the layout for various screen widths. At the time, we went with a system of dynamically appended min- and max-width classes on the body that are updated on load, resize and orientation change events as a workaround for the limitation that Internet Explorer doesn’t support media queries.
Basically, the page is getting min-height set to the current page height in the beta which is overriding the .landscape { min-height: 300px; } in the alpha.
It looks like you need to use CSS Media Queries if you want a page layout that changes or you could just add CSS style="height:43px" on the the header if you need a fixed height.
Seems like the page is not ready when you query the height(). There is no document.ready for jQuery.mobile. It doesn't explain why there is a difference between alpha and beta, but I guess a code path changed that exposed the issue.
Wrapping the query in a different event, returns the height as expected.
$("div:jqmData(role='page')").live('pageshow',function(){
console.log($('[data-role=header]').first().height());
});
I found this by examining the offsetHeight of the DOM element in the Chrome console which was non-zero but, as you reported, the height() was always reporting 0. I then created an link when clicked output the height and it was non-zero. I then realised that the height() was being called before the page was fully ready.
Relevant - jQuery mobile $(document).ready equivalent
Looks like they did change some of the syntax, Docs:
http://jquerymobile.com/demos/1.0b1/docs/api/methods.html
When finding elements by their jQuery
Mobile data attribute, please use the
custom selector :jqmData(), as it
automatically incorporates namespaced
data attributes into the lookup when
they are in use. For example, instead
of calling $("div[data-role='page']"),
you should use
$("div:jqmData(role='page')"), which
internally maps to $("div[data-"+
$.mobile.ns +"role='page']") without
forcing you to concatenate a namespace
into your selectors manually.
Try this:
$("div:jqmData(role='header')").first().height()

Clean Progressive Enhancement

I am using progressive enhancement to build a website. This includes menu, slideshow, etc. The items are included in the page as unordered lists, then JavaScript applies the formatting.
My concern: how can I avoid the flash of unformatted content, where the unordered lists are visible before the formatting is applied? Are there best practices for this?
Important: the site must remain SEO friendly and accessible (this is why I am using progressive enhancement in the first place). So for example it is out of question to set the initial style of the unordered lists to display:none.
Use CSS for formatting instead of JavaScript.
So for example it is out of question to set the initial style of the unordered lists to display:none.
You can indirectly cause the style to get set to display: none when you detect JavaScript is available by using CSS and some script run before any of the content is included:
<head>
<style type="text/css">
body.withjs #menu { display: none; }
</style>
</head>
<body>
<script type="text/javascript">
document.body.className= 'withjs';
window.onload= function() {
...do stuff with menu...
document.getElementById('menu').style.display= 'block';
};
</script>
...
<ul id="menu">
...
</ul>
</body>

Valid way to add noscript in head for wrapping redirect

So I was thinking a simple way to deal with javascript being disabled by the browser would be the following:
<head>
<title>JavaScript Test</title>
<noscript>
<meta http-equiv="Refresh"
content="1;url=nojs.html" />
</noscript>
</head>
And having the nojs.html have something like:
<p>Return to test after enabling javascrpt.</p>
At the crash page.
This isn't my preferred method, but it's nice and simple until something more graceful can be worked out for users without javascript.
However, it is not valid to put a <noscript> element in the head section. The preliminary tests worked anyway, of course, but I'm superstitious when it comes to my code being valid, plus I'd hate for this to actually fail a field test.
So is there a valid way to do this? Perhaps wrapping the noscript in another element, like an object tag? Or some even simpler way I'm not thinking of?
I am not sure why you need to redirect to another page instead of just showing a message. I use JS and a little CSS to handle these situations for me. Something like this:
<head>
....
<script type="text/javascript"> document.documentElement.className += " js"</script>
<link rel="stylesheet" type='text/css' href="css/layout.css" media="all" />
</head>
<body>
<div id="noscript">Please enable JavaScript, then refresh this page. JavaScript is required on this site</div>
<div id="wrapper">
...
</div>
</body>
Then in layout.css:
#wrapper { display: none } /* Hide if JS disabled */
.js #wrapper { display: block } /* Show if JS enabled */
.js #noscript { display: none } /* Hide if JS enabled */
By doing it this way, the class is applied to the html element before the page is rendered so you won't get a flicker as the non-JS content is swapped out for the JS content.
Doug's solution is pretty good, but it has a few drawbacks:
It is not valid to have a class attribute on the html element. Instead, use the body.
It requires that you know what display type to set the element to (i.e. ".js #wrapper { display: block }").
A simpler, more valid and flexible solution using the same approach could be:
<html>
<head>
<!-- put this in a separate stylesheet -->
<style type="text/css">
.jsOff .jsOnly{
display:none;
}
</style>
</head>
<body class="jsOff">
<script type="text/javascript">
document.body.className = document.body.className.replace('jsOff ','');
</script>
<noscript><p>Please enable JavaScript and then refresh the page.</p></noscript>
<p class="jsOnly">I am only shown if JS is enabled</p>
</body>
</html>
With this, it's valid html (no class attribute on the html element). It is simpler (less CSS). It's flexible. Just add the "jsOnly" class to any element that you want to only display when JS is enabled.
The <noscript> tag cannot be in the <head>, it must be in the <body>
The common practice is to show a message instead of redirecting, as there is no way to redirect only if javascript is disabled.
You could do it the other way around, have the first page be nojs.html, and on that page use javascript to redirect to the main content.
If you truly want a valid way to do it, make your main page the nojs.htm page and use JS to hide all content before it's shown to the user and immediately redirect to the real main page using javascript.
I like Doug's solution. However, if you need to redirect, I would remember that while there is a spec and a standard, the world of web browsers is a dirty, imperfect world. Whether or not something is allowed by the spec is not as important as whether or not it works in the set of browsers you care about.
Just look at the source code of any major site... Most of them won't validate I'd bet :)
What about:
noscript{
z-index:100;
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
min-height:1024px; background:#FFF;
}
And:
<noscript>
<p>Please enable Javascript on your browser.</p></noscript>

Categories