Skip to content
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

Allow inline css and script tags to be updated. #26

Open
jedjones-uk opened this issue Jun 27, 2013 · 12 comments
Open

Allow inline css and script tags to be updated. #26

jedjones-uk opened this issue Jun 27, 2013 · 12 comments

Comments

@jedjones-uk
Copy link

Firstly I want to say this is a great plugin and I hope to be able to use it often, the only problem I have is my sites have a lot of inline JS (jquery, ajax, etc) and the JS is different on each page. When I move page, everything else updates except the inline JS which is removed, but not replaced with the new pages content. I even tried putting it in a div tag with no luck.

I there something I am missing, or is it just not supported?

@ryanschmidt
Copy link

The way I handled this is by calling my css/js/etc from within the updateable zone.

<body>
    <div class="updateable">
        [call your css here]
    </div>
</body>

I'm new to djax so there may be a better way. I notice a slight flicker when going back and forth between the pages. I haven't put this on production yet but if the flicker continues there, I may resort to just compiling the css all to together and wrapping each set of styles with a selector for that page. In LESS, this is very easy.

@jedjones-uk
Copy link
Author

I actually ended up forking it to work on a bigger fix, now I just need to tag inline JS and CSS the same way as a normal DIV. I haven't thoroughly tested it but I didn't see any flashing issues. There also the issue of JS functions having the same name for different pages, as removing the element from the DOM doesn't unload it.

<script type="text/javascript" class="updatable">

@ryanschmidt
Copy link

I ended up combining the stylesheets. While my method above worked, you could notice a small flash as the stylesheet was added each time. I ended up just dynamically adding the path as the id of the page's container, wrapping my area stylesheet in that id, and it works pretty good. You can see what I'm doing here: http://skycatchfire.com

@Hadryan
Copy link

Hadryan commented Jul 17, 2013

non of the above methods really works for me. developing web app hugely based on inline javascript. any idea??

@ryanschmidt
Copy link

@Hadryan I gave all of my ideas above. Could you provide more detail? If you're trying to load unique js files for different pages, simple calling those files within the updateable zone would be sufficient.

@jedjones-uk
Copy link
Author

@Hadryan Same as @ryanschmidt has said, If you could say how it wasn't working we might be able to give better help. If the JS is inline, then copying it into the page isn't all that is required (and the default script wont do it), any new JS needs to be added to the DOM correctly. In mine I do this with standard JS, not JQuery.

@Hadryan
Copy link

Hadryan commented Jul 18, 2013

Thanks guys, but the problem still exists: I have an app (very similar to wordpress different post formats), that fetch the posts through djax. on the other hand, each post has its inline javascript to let's say play an audio file by soundmanager2. the problem is when the new page (blocks) arrive(s), the inline javascripts are cut. I tried using above methods to assign ids or classes to that javascript even by means of random numbers that are completely unique, but with no success. each time those inline scripts cut. I also wrap them inside a div or an a, but nothing changed.

@jedjones-uk
Copy link
Author

I may not have been clear, I was having the same problem as you where it appeared my JS was just being cut out, but I was sure it was in the response data. This is due to the way the blocks are copied and they way Jquery handles JS. My solution was to actually modifie the jquery.djax.js file with this code placed after the code block beginning $.each(newBlocks, function () {. It deals with the inline JS itself and allows you to tag it as I explained above.

var oldScripts = $('script'+blockSelector); $.each(oldScripts, function () { $(this).remove(); });

var newScripts = $(result).filter('script'+blockSelector); $.each(newScripts, function () { var newScript = $(this).text(); var script = document.createElement("script"); script.type = "text/javascript"; script.text = newScript; // use this for inline script script.className = blockSelector.replace('.', ''); document.body.appendChild(script); });

I'm not sure of github etticate and if this is kosher, but I'll link to my jquery.djax.js version and you can try that and see if it helps if you like. The block of code is at line 220, plus there is some code for pulling CSS in the header at 150.

https://github.com/ragnaruss/djax/blob/master/jquery.djax.js

@beezee
Copy link
Owner

beezee commented Jul 18, 2013

really cool to see you guys all digging in on this issue, thanks!

@ragnaruss totally kosher to link but even better would be to get a pull request cooking to bring this into the main repo. From the reading I've been doing it looks like this is a browser behavior and your implementation is the best way of dealing with it. If you don't mind opening one I'll read through it and pull in.

@Hadryan
Copy link

Hadryan commented Jul 18, 2013

unfortunately this doesn't work again - but some strange behavior figured out.
On line 153 of the original djax newBlock.html() got the wrong(?!) answer, I mean all the inline javascripts being cut off, while block.html() has the correct answer. Although in both cases the actual response has inline javascripts. Maybe it tries to pull down the inline javascripts to the end of the web page &|| assumes they are javascript files that they already cached.

@jedjones-uk
Copy link
Author

@Hadryan This is the exact issue I was getting, I could see I was getting the full page in var result but that when it came to processing the JS later, It couldn't find it. I tracked the issue down to newBlocks = $(result).find(blockSelector); The way JQuery deals with JS is weird and was causing it to be lost, the solution to this is to directly process result for the incoming inline JS using filter(), and to then create the DOM object ourselves, this is what the code above does.

We are using just standard JS to do this and treating the inline JS as text so there's no JQuery funny business, It is also important to add the JS using document.createElement("script"); because just copying text into the document will not mean it has been evaluated and added to the DOM.

I hope this helps you figure out the issue, and if it does, I would suggest using a naming convention in your JS functions and variables which indicates which page it belongs too as well as the DOM can be difficult and deleting the text for the HTML will not remove it from being run.

@Hadryan
Copy link

Hadryan commented Jul 20, 2013

@ragnaruss Thank you for the code and also explanations. However after looking more deeply in codes and testing them, I changed a bit of them to work more properly. In this case I could run my codes successfully. So, I decide to share them if anybody else interest in them and find them useful.

  • On line 242 https://github.com/ragnaruss/djax/blob/master/jquery.djax.js#L242, I changed document.body.appendChild(script); to document.getElementById(updateId).appendChild(script); where updateId is var updateId = blockSelector.replace('#', '');. Since if the updateable zone is a part of the web page not the whole (the rest) of the page, those scripts pulled down to the end of the body wouldn't remove after second calling of the page. and after few djax click tons of scripts (non related to the current page) would remain at the end of the body.
  • I also change the replace('.', '') to replace('#', ''), since I asked djax to find an updatable zone by its id not its class.
  • a class-name of " no-djax " added to the script to have a secure, non-updateable class to add to any elements in the webpage. I added this to the inline javascript to protect against djax change and also to simply find inline scripts by their class of "no-djax". so, for example line 232 instead of var newScripts = $(result).filter('script'+blockSelector); it would be var newScripts = $(result).filter('script.no-ajax');
  • also some modification to the original djax made, in order to fulfill my requests of having " no-djax " class. for example on line 270, now we have $(this).find('a').not('.no-djax').filter(function () .
  • a copy of my file with above modifications can be found here: https://gist.github.com/Hadryan/6045111

Thanks again @beezee for his beautiful djax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants