Skip to content

Restructure JS to be AMD-compatible #440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 8, 2013

Conversation

singingwolfboy
Copy link
Contributor

This pull request refactors the Javascript a bit to make it AMD-compatible. It also drops JS compression, because this is a debug toolbar, and there's no reason to compress assets that are only going to be used in debugging -- in fact, if someone discovered a problem with an interaction between the Django Debug Toolbar and their Javascript code, having compressed JS is only going to make it harder to debug. I also removed the jQuery.noConflict(true) call from toolbar.js in favor of only loading the jQuery library if it hasn't already been defined on the page, which should solve the same problem more neatly.

This diff contains a fair number of whitespace-only changes in toolbar.js; to ignore those changes when viewing the diff on Github, you can add ?w=1 to the URL. I find that makes pull requests like these easier to review.

convert tabs to spaces
This change makes Django-Debug-Toolbar use the existing version of jQuery
on the page if one exists, and only loads jQuery if it isn't already loaded.
It also explicitly loads the jQuery cookie plugin and the toolbar script
as separate files. Finally, we are no longer compressing/minimizing scripts;
this is for debug purposes, and presumably will not be served in production.
@@ -3,7 +3,9 @@
@media print { #djDebug {display:none;}}
</style>
<link rel="stylesheet" href="{{ STATIC_URL }}debug_toolbar/css/toolbar.min.css" type="text/css" />
<script type="text/javascript" src="{{ STATIC_URL }}debug_toolbar/js/toolbar.min.js"></script>
<script>window.jQuery || document.write('<script src="{{ STATIC_URL }}debug_toolbar/js/jquery.js"><\/script>')</script>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use document.createElement('script')?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the <script> tag, I simply copied that line from the HTML5 Boilerplate project; it's less code than using JS to create a script element, attach the src attribute, and attach it to the DOM. I also think it's more readable this way.

jQuery would already be in the window if the Django project using Django Debug Toolbar was already loading jQuery -- something that I think is highly likely.

@singingwolfboy
Copy link
Contributor Author

I'm not going to address issues with the Javascript itself -- those are perfectly valid, but outside the scope of this pull request. This pull request is solely about refactoring the existing Javascript to support AMD loading. Fixing issues about the Javascript itself should be tackled in a separate pull request.

@singingwolfboy
Copy link
Contributor Author

I can't figure out why my Travis build is failing; I've only changed HTML and JS, but the errors appear to be in Python logic. When I run make test locally, the tests all run just fine. Anyone know what's going on?

@singingwolfboy
Copy link
Contributor Author

@cvan Alright, I fixed the test issue, and addressed your comment about using document.createElement. Is this pull request ready to be merged? (As I said, I agree with your comments about modifying the Javascript, but that should be done in a separate pull request.)

script.src = "{{ STATIC_URL }}debug_toolbar/js/jquery.js";
var exist = document.getElementsByTagName('script')[0];
exist.parentNode.insertBefore(script, exist);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be a problem if there are no <script> tags in the document?

In another solution I've done this before, the latter handling badly formed HTML (e.g. blank line at the top of the file):
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are at least three <script> tags in the document: these three here. :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But doesn't Javascript block document loading? If the <script> tag that this is in currently counts, then awesome. Works for me. It might be worth a few quick tests of abnormal HTML that this is injected into to make sure this change is good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a test, I created a file with the exact contents <script>alert(document.getElementsByTagName('script').length);</script> and I opened it in Chrome, Firefox, and Internet Explorer 9. In all three, I got a popup alert with the number 1. I think it's fine. :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@singingwolfboy -- As noted yesterday, this turned out to be an issue in practice. An inline script runs immediately, while a script file runs once it's loaded. That's why your test didn't detect the problem.

I committed an old-school fix in 2b6f5d6. I don't know if it's compatible with AMD, but I need a way to work on the toolbar until we figure out a solution. If you have a better alternative, let me know!

EDIT: I just realized my "fix" reverts 62b2e37. We need something else.

@cvan
Copy link

cvan commented Nov 6, 2013

lgtm

robhudson added a commit that referenced this pull request Nov 8, 2013
Restructure JS to be AMD-compatible
@robhudson robhudson merged commit 363c4a8 into django-commons:master Nov 8, 2013
@aaugustin
Copy link
Contributor

Thank you!

@aaugustin
Copy link
Contributor

After this pull request, the example -- which you can run with make example -- doesn't show the toolbar anymore.

The console says:

ReferenceError: jQuery is not defined @ http://localhost:8000/static/debug_toolbar/js/jquery.cookie.js:14

aaugustin added a commit that referenced this pull request Nov 10, 2013
When jQuery wasn't loaded yet, the <script> tag was inserted properly,
but jQuery wasn't loaded before jquery.cookie.js and toolbar.js. As a
consequence these scripts crashed.

Refs #440.
@gavinwahl
Copy link
Contributor

This is causing problems for me when I'm using require.js for other purposes on the page. Isn't it better for the debug toolbar javascript to be completely isolated from the application?

@djfarrelly
Copy link
Contributor

I use AMD on my projects, but this change actually caused it to break in AMD environments. I am curious as to why AMD compatibly was desired in DDT. DDT isn't using an AMD loader itself and is just using multiple script tags (which is against the point of AMD). Using AMD like this could actually conflict with plugins like in #525.

In my opinion, DDT should be self contained and stay out of the way of any code in the page. Having DDT use RequireJS/Dojo/another AMD library if it's in the page can introduce more issues with little upside. I don't mean to seem non grateful for the work done by all the contributors to this item, but I think AMD-compatibility doesn't make sense for DDT.

@arcanis
Copy link

arcanis commented Sep 5, 2014

I have the same question : why is DjDt amd-aware ? What's the rational behind this ? oõ

ryneeverett pushed a commit to ryneeverett/django-debug-toolbar that referenced this pull request Oct 2, 2016
ryneeverett pushed a commit to ryneeverett/django-debug-toolbar that referenced this pull request Oct 2, 2016
When jQuery wasn't loaded yet, the <script> tag was inserted properly,
but jQuery wasn't loaded before jquery.cookie.js and toolbar.js. As a
consequence these scripts crashed.

Refs django-commons#440.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants