I have an application that uses jQuery and pjax (standalone). We're trying to experiment to see if we can use the possibly more flexible and smaller npm pjax over jquery-pjax.
One of my functions sets the html of a div after loading data, and this html includes links that we want as pjax links, for example $('#link-container').html('<a href="/account_detail.html?='+account.id+'" data-pjax >'). However clicking on this link causes a full page reload rather than a pjax request.
Is there a way to reimplement pjax? When I try new PJAX({elements:[a[data-pjax]]}) inside the pjax:success call (whenDOMReady from the project page - https://www.npmjs.org/package/pjax) it uses pjax... but then loads resources twice.
Perhaps the best solution is going with jquery-pjax ($(document).pjax(a[data-pjax] etc.) but I wanted to see if anyone has come across this type of issue before. Perhaps it is rare to include jQuery and non-jQuery pjax, but it seems like this can happen for any asynchronous data query and DOM modification, and I just want to re-PJAX.
I'm using jquery-pjax, and when you use it or configure it wrong - it also refresh the page, so you're experiencing one of the issues I've encountered.
In any way, I'm not sure if it will help your problem or not, but I suggest everyone to use Firefox with Firebug and in the "Console" tab to click on "Persist" you usually find some errors there that might be helpful, and since errors somewhere might cause the page to refresh - sometime you miss it as the console is being refreshed too.
What I learned is that you need to make sure that when you write:
<a href="/account_detail.html?=2" data-pjax>bla</a>
You need to have a container - that PJAX drops the content into, like:
<div id="pjax-container"></div>
And initially you configure PJAX to bind these objects:
<script>
// this is how I define it in jquery-pjax, so adjust it as you use it.
$(document).pjax('a[data-pjax]', '#pjax-container');
</script>
so the key points that I learned that causes refresh with PJAX:
I'm sending a header twice ( back-end code )
The container was suddenly removed from the HTML body ( the div id="pjax-container" ) and when the DOM is missing it doesn't have a
place to drop the HTML - so it just refresh the page.
When I initially bind the a[data-pjax] with jQuery, new DOM object are not automatically re-bind by jQuery ( unless using "live/on"), therefor they act as a regular <a> tag and reload the page with the new URL.
some JS/PJAX syntax error
In your case, if the pjax-container is "#link-container" I'm not sure if it's a good idea to place the tags inside it.
Related
I am currently trying to implement the Google Tag Manager but I run into a problem since the GTM appends the tags right before the closing tag of the body.
Whenever I have a template that needs to call a bit of code from one of the scripts in the Google Tag Manager I get an undefined error. This is obvious since it does not matter where I place my script in my view, GTM will always come after it since it appends right before the closing body tag.
Is there any way to fix this behaviour and why does Google do it like this? I understand that it helps with non-blocking but they might as well just place async attributes on the scripts and it will almost do the same?
An example I have Facebook Pixel as one of my tags in GTM and I need to be able to make a specific event call when I am loading a certain page as my view.
fbq('track', 'Search');
Ofcourse this needs a fbq instance to begin with. This leave me with only one option and that is to try and place my script in my footer which is a general template and it will get messy.
Any workaround for this behaviour?
The issue you are facing is that the Facebook library is not completely loaded when you are calling your function.
One method would be to migrate your Facebook code to GTM trigger it on all pages
and fire your specific code on dom ready
You could also use the code from below and see when the _fbq.loaded variable is set to true.
https://gist.github.com/chrisjhoughton/1dc91dd7bd95717e08d3
You would have to create trigger based on this javascript variable.
Hope this helps
I am creating an application with Symfony2, where I have a main menu of options depending on the option selected dynamically opens a tab at a lower div with the content for that option. Content is loaded with load() of Jquery in the container div.You can see in the picture below:
The first problem was that in the HTML loaded in each tab could not use the js file initially loaded in the index.html, as you can see in this example you should check out a notice when we click the content of each tab, but does nothing .
The solution to this problem was included in each HTML code to load the appropriate script, and it worked properly. But to do it this way, if two HTML carry the same js, when one of the contents some event runs is repetite many times as tabs we have created, that is, if I open two different options (each in its own tab both charge the same js) by clicking on the first event associated performed twice, whereas if I do it in the second only done once. In short, whenever a function of a js used, is repeated as many times as there are dynamically loaded on the tabs.
And I tried event.preventDefault();orevent.stopPropagation(); and it does not solve the problem.
Would it be okay that it js is included twice in the overall structure of HTML? (Included in the initial head and then the container div)
Dynamically loading HTML + JavaScript is not the best approach for this case. I suggest that you use some JavaScript SPA framework, like AngularJS or ReactJS. Both are very big and well supported projects, so you can find tons of documentation and tutorials. You'll most likely end up using Symfony only as a RESTful service and Angular/React taking care of the rest (template loading, sending request to server, etc). Also, js frameworks will take care of deep linking and in the end you'll have a better working, easier to maintain application.
It is a bit more work initially, especially until you bootstrap the application, but then it gets easier to maintain and implement new functionality, so it pays off in the end. With your current approach you soon will find yourself in a big mess full of 100s of templates, js callbacks, inclusions, etc. I'm saying this from a personal experience!
Well...
Jquery works like this: when you attach an event to html, if the html does not exist, the event is attached to nothing. If the element exists then the event is correctly attached. It attaches only to existing elements when the on function is execute. That is a correct behaviour. In the past it used to exist a .live method that did exactly what you want: you attached an event and if you create the element after the attachment, the new element also contained the event.
Adding the js twice is not the solution. As you said after a click the button will be executed twice.
Why do not attach the events after loading the content? If you load it in the page start you can do in the main file:
$(function(){ // will force to execute the on method after all the page is loaded.
$('.submenu .button').on ('click', function (){
...
});
});
If you load the menu by ajax, in the callback and after adding the html menu to the main you must use the code I wrote above.
I'm using a third-party commenting plugin right now, All it provides is a piece of script as follows:
<div id="uyan_frame"></div>
<script type="text/javascript"
id="UYScript"
src="http://v1.uyan.cc/js/iframe.js?UYUserId=1674366" async="">
</script>
As it is not a live commenting plugin, I want to add a refresh button next to it to reload it manually to see the latest comments instead of reloading the whole page.(I know Disqus is a good commenting plugin, but as we target Chinese users, I have to use the current one).
As it's a third party plugin, I don't have too much control over it. And I also think iframe is a ugly way to achieve this partly refreshing thing. So, is there any other way to achieve this? Like every time I click on the refresh button, it will erase out all the HTML element this script generated, recreate this script tag, append it to the appropriate place, and run it again?
you do not have to use iframe as it is slow. What you can do is create a div or section and give it an id or class, then create a button that when is clicked will fetch a script and append the right html contents in the div or section you've created. To make it easier to understand the code would look something like this.
<section id="content"></section>
<button id="refresher"></button>
<script>
$('#refresher').click(function(){
//Load your script like so
$.getScript('url of the script you are trying to get', function(){...})
//Load your content here
$('#content').html('Current contents will be erased and will be replaced by whatever you placed here')
//...or if you need ajax fetching
$.ajax({
url: url,
success: function(){
$('#content').html('place your content here and this will erase old content')
}
});
})
</script>
I would ask 3rd party company how to refresh comments without refreshing the whole page. They did developed this, and they must have a way to refresh it easily.
For example, UYComment.refresh(document.getElementById('comment'))
You may also find this kind of solution by looking at their javascript code if you don't want to ask them.
You can go around by not using 3rd-party provided code, i.e. ajax to replace div, refreshing iframe, etc., but, based on my experience, it always make your code little messier.
Since you tagged jQuery, I'm assuming you're using it.
Try adding a click handler to your refresh button and then use .html()
example:
$('#uyan_frame').html('');
When you call .html, it should replace the element you called it on and it should recall any scripts in the string you pass in. Just as a disclaimer, this is not tested.
At the moment I'm working on a mobile website that stores pages in a local database. At the bottom are some basic buttons to navigate to other pages and when you press them I wanted to use jquery's .html function to replace the body content with other html strings from the database. The problem I found is when we go to our contact form page the user can't really use the form fields. They show up, but they're not clickable. I've also noticed that you can't execute javascript functions that are loaded in trough the .html function.
Hopefully you can help me with this problem or suggest a workaround. Thanks
Some jQuery functions strip out script and style tags (e.g. .replace()). That isn't a bug but documented somewhere – unfortunately I can't find that piece of documentation right now.
But that should be no problem in the case of form fields. They should get inserted without any problems.
Here is an example that illustrates your problem.
Explanation:
jQuery html seems to not process some tags, although it does. The problem is when trying to execute jQuery UI related functions on an element not within the DOM
the exemple above shows the difference between calling button jqueryUI function after and before appending the element to the DOM
a generic workaround to solve this problem is:
var div = $('<div></div>').hide().appendTo('body');
then do whatever you want with the div
I'm trying to build a single-page app that has several views (screens, page contents)
My App's UI has a permanent menu bar and a "view area" which retrieves a view via Ajax, based on menu selections. This works great for simple HTML content and keeps my menu-script running on the background despite which view is being displayed.
But what if my view needs an additional script? How do you load and execute a script as a result of a view change (=a page fragment was loaded as a result of a button click) also, how do I get rid of that script when I choose a different view?
I know I can embed a script-tag into the page fragment and write the code there, but I'm really looking for a more robust way of doing this, preferably so that an instance of an object is created when the view is loaded and then discarded when the view changes.
yepnope.js is a great conditional loader. You could use it to check certain conditions (e.g. view, state) before loading a script. I don't think it has the ability to remove a script that's already been loaded, though.
You can use javascript to add a <script> tag in the same way you would any other tag.
The hardest part is knowing where to place it, but if you have control over your markup, this isn't too big a barrier.
Something along these lines:
function DST(url)
{
var s = document.createElement(’script’);
s.type=’text/javascript’;
s.src= url;
document.getElementsByTagName(’head’)[0].appendChild(s);
}
If you need something to happen automatically when you load that script, you should be able to use a self executing anonymous function to do the job.
(function(){alert('this happened automatically');})();
If you need to pass anything in to the function it would look like this:
(function($){alert('this happened automatically');})(jQuery);
If you really need to discard the scripts, you can delete the nodes, but it might be better to leave them in, in case a user reactivates a view, so you don't have to make the AJAX call and associated HTTP request, allowing the page to load faster.