I have a heavily ajax based application wherein i only have a login page and the main page.
Most of my links are "ajaxed" and i have them done like this:
//get the href of the link that has been clicked, ajaxify ANY links
$(document).on('click', '.tree a', function () {
var link = $(this).attr('href'); //get the href off the list
$.ajax({ //ajax request to post the partial View
url: link,
type: 'POST',
cache: false,
success: function (result) {
$('#target').html(result);
$.validator.unobtrusive.parse($("form#ValidateForm"));
}
});
return false; //intercept the link
});
I want to implement "pushState" on my application and the first step that i have done so far is to add this code:
$(document).on('click', 'a', function () {
history.pushState({}, '', $(this).attr("href"));
});
Now it updates my address bar whenever i click on any of my links and the ajax content gets successfully loaded.
I am kinda new to this API so i don't know what am i missing but here are my issues so far:
when i press the "back" button, nothing happens. I read about "popstate" and browsed through SO to look for solutions but i can't
seem to make them work.
When i click the link from the history, i get the "raw" view of the child html w/o the layout from the master html. What do i need to do if i want it to be displayed like
it was clicked from my main application?
Most of my child views are either forms or list.
This code should help you :
function openURL(href){
var link = href; //$(this).attr('href');
$.ajax({
url: link,
type: 'POST',
cache: false,
success: function (result) {
$('#target').html(result);
$.validator.unobtrusive.parse($("form#ValidateForm"));
}
});
window.history.pushState({href: href}, '', href);
}
$(document).ready(function() {
$(document).on('click', 'a', function () {
openURL($(this).attr("href"));
return false; //intercept the link
});
window.addEventListener('popstate', function(e){
if(e.state)
openURL(e.state.href);
});
});
Related
I have some JS files included in my page that are simple for displaying blocks on click ant etc..
On another part of page, I have a button. When I click it an ajax call is made that returns some values that I display on the page. To display it, I'm reloading part of page like this:
$(document).ready(function () {
$(document).on('click', '.add', function (e) {
$this = $(this);
$.ajax({
type: 'POST',
url: 'add',
dataType: 'JSON',
data: {product: $this.parent('.input-append').find('input').data('id'),quantity: $this.parent('.input-append').find('input').val()},
success: function (data) {
if(data.success == false){
alert('error')
}else{
$('.test').load(" .test");
$('.sidebar').load(" .sidebar");
$('.top').load(" .top");
}
}
});
});
This reloads part of page, displays values and etc..
However, after the ajax call is made, the JS stops working. When I click my buttons, nothing happens. No errors or anything.
I think it has to do with the ajax when I refresh part of twig and it messes up the previously loaded JS files. But what can I do in that situation? Somehow refresh the loaded JS files? How?
You have to attach event listener on button starting from the container which doesn't get reloaded by Ajax request, like this:
//#mainCont is a container that doesn't get reloaded by Ajax
$("#mainCont").on("click", ".yourBtn", function(){
//do something
});
As said #Nacho M, you need to reinit listener from the loaded element, so you hsould have something like this :
function init() {
$(document).on('click', '.yourclass', function (e) {
//your content
}
// add every button who needs to be reloaded.
}
Init them on loading page first :
$("document").ready(function() {
init();
})
And on success of Ajax call :
$.ajax({
type: 'POST',
url: 'add',
dataType: 'JSON',
data: {product: $this.parent('.input-append').find('input').data('id'),quantity: $this.parent('.input-append').find('input').val()},
success: function (data) {
if(data.success == false){
alert('error')
}else{
$('.test').load(" .test");
$('.sidebar').load(" .sidebar");
$('.top').load(" .top");
init();
}
}
});
I currently have this code:
crossroads.addRoute('/login', function(){
$.ajax({
url: '/login',
type: 'GET',
data: {
},
success: function(msg) {
$('#' + main_window).html(msg);
}
})
});
Along with this hasher.js for maintaining history:
function parseHash(newHash, oldHash){
crossroads.parse(newHash);
}
hasher.initialized.add(parseHash); //parse initial hash
hasher.changed.add(parseHash); //parse hash changes
hasher.init(); //start listening for history change
$('a').on('click', function(e) {
e.preventDefault();
hasher.setHash($(this).attr('href'));
});
Now when I have a link that says #/login and click it, the login page is loaded fine. However, if the user clicks the login link again, the page doesn't reload. I know the click is registering, but the routing/hashing isn't firing. How do I manage to do this?
Any help would be greatly appreciated. Thanks!
You are not changing anything with hasher.setHash("#/currentpage") because you are already on that page. So the change event never gets fired. You could probably just go:
$('a').on('click', function(e) {
e.preventDefault();
hasher.setHash('');
hasher.setHash($(this).attr('href'));
});
But that would clutter the history, so you could force a reload on the click, if you make the loading method available:
var loadLogin = function(){
$.ajax({
.... your ajax settings ....
});
};
crossroads.addRoute('/login', loadLogin);
$('a').on('click', function(e) {
e.preventDefault();
var newHash = $(this).attr('href');
if(newHash === '/login' && hasher.getHash() === '/login') {
loadLogin()
} else {
hasher.setHash(newHash);
}
});
EDIT
As #Patchesoft pointed out, crossroads has a property called ignoreState, which will force any request to go though the router function, even if on the current page - https://millermedeiros.github.io/crossroads.js/#crossroads-ignoreState
Your can force the call of your route by this:
// add this dummy route first
crossroads.addRoute('noop', function() { } );
$('a').on('click', function(e) {
// route to dummy route
hasher.setHash('noop');
// and then replace by your login route
hasher.replaceHash('login');
}
On a page with a tab control, each tab contains a table, each tr contains a td with a button which has a value assigned to it.
<td>
<button type="button" class="btn" name="deleteEventBtn" value="1">Delete</button>
</td>
This code below works for the first delete. After the AJAX call & the refresh of the div, no further delete buttons can be clicked. The .on is attached to the document. The same happens if I attach it to the body or anything closer to the buttons.
function deleteRecord(url, id, container) {
$.ajax({
type: "POST",
url: url,
data: { id: id },
success: function (data) {
$('#delete-popup').hide();
$(container).trigger('refresh');
}
});
}
$(document).ready(function () {
$(document).on('click', '[name^="delete"]', function (e) {
e.preventDefault();
var id = $(this).val();
$('#current-record-id').val(id);
$('#delete-popup').modal('show');
});
$('#delete-btn-yes').on('click', function (e) {
e.preventDefault();
var recordId = $('#current-record-id').val();
var recordType = location.hash;
switch (recordType) {
case "#personList":
deleteRecord(url, recordId, recordType);
break;
}
});
});
Any ideas? Could it be related to the wildcard for starts with [name^="delete"]? There are no other elements where the name starts with 'delete'.
EDIT
When replacing
$(container).trigger('refresh');
with
location.reload();
it "works", however that refreshes the whole page, loses the users position and defeats the point of using AJAX.
As the button click is firing at first attempt, there is no issue in that code. All you have to do is, put the button click event in a method and call it after the refresh. This way, the events will be attached to the element again. See the code below,
function deleteRecord(url, id, container) {
$.ajax({
type: "POST",
url: url,
data: { id: id },
success: function (data) {
$('#delete-popup').hide();
$(container).trigger('refresh');
BindEvents();
}
});
}
$(document).ready(function () {
BindEvents();
});
function BindEvents()
{
$(document).on('click', '[name^="delete"]', function (e) {
e.preventDefault();
var id = $(this).val();
$('#current-record-id').val(id);
$('#delete-popup').modal('show');
});
$('#delete-btn-yes').on('click', function (e) {
e.preventDefault();
var recordId = $('#current-record-id').val();
var recordType = location.hash;
switch (recordType) {
case "#personList":
deleteRecord(url, recordId, recordType);
break;
});
}
Apologies to all and thanks for your answers. The problem was due to the way the popup was being shown & hidden.
$('#delete-popup').modal('show');
and
$('#delete-popup').hide();
When I changed this line to:
$('#delete-popup').modal('hide');
it worked. Thanks to LShetty, the alert (in the right place) did help!
If you are using Bootstrap Modal
After Ajax Request before Refreshing page add
$('.modal').modal('hide');
This Line will Close your Modal and reload your page. Before that it will complete all Ajax Request things.
But for google chrome there is no issues :) hope this help someone.
i create a nav on my site. Navigation works good but when i back on the main site all script from js file doesn't work. Script for my nav:
var default_content="";
$(document).ready(function(){
//Ajax navigate
checkURL();
$('footer a').click(function(){
checkURL(this.hash);
});
default_content = $('#login_box').html();
setInterval("checkURL()",250);
.........
Methods:
var lasturl="";
function checkURL(hash)
{
if(!hash) hash=window.location.hash;
if(hash != lasturl)
{
lasturl=hash;
if(hash=="")
$('#login_box').html(default_content);
else
loadPage(hash);
}
}
function loadPage(url)
{
url=url.replace('#page','');
$.ajax({
type: "POST",
url: "include/help4meApi.php",
data: 'page='+url+'&tag=navigation',
dataType: "html",
success: function(msg){
if(parseInt(msg)!=0)
{
$('#login_box').html(msg);
}
}
});
}
Problem is when i back to the main site scripts doesn't work.
the issue comes from here $('#login_box').html(default_content);. When u calle the .html() the event binded within the element will be cleaned.
When you backspace, back to the main page, the event handler is already not there, so you have to register it again
//For show and hide register values
$("#registerInputsBtn").click(function(){
$(".register_information").hide(1000);
$(".register_values").show(1000);
$("#firstname").focus();
});
register again on the piece of code that you assign the content to #login_box. For example the quick fix:
if(hash==""){
$('#login_box').html(default_content);
$("#registerInputsBtn").click(function(){
$(".register_information").hide(1000);
$(".register_values").show(1000);
$("#firstname").focus();
});
}
but here the codes are not DRY :( rearrange the flow on how the page load and the register the event in the correct flow is recommended.
I have two problems
I am trying to open a jQuery colorbox and it is very slow. The reason is I am trying to get html content from a different page (I cannot use iframe because I just need a part of this page). The following code works but it takes time after the button is clicked:
$(document).ready(function() {
$(".cart-link a").click(function(event) {
$(this).colorbox.close();
});
$(".rest-menuitem a").click(function(event) {
event.preventDefault();
var result = null;
var sURL = $(this).attr("href");
$.colorbox({
html: function() {
$.ajax({
url: sURL,
type: 'get',
dataType: 'html',
async: false,
success: function(data) {
result = data;
}
});
return $(result).find('.product');
},
width: '650px',
height: '10px',
onComplete: function() {
$(this).colorbox.resize();
}
});
});
});
I want to know if there is a alternative way to do it. I dont mind if the colorbox popup and then takes time to load the content. The above version can be fount at this url (http://delivery3.water-7.com/index.php/restaurants/manufacturers/3/Barcelona-Restaurant-&-Winebar/products).
I am also trying to close the colorbox when a user clicks on add to cart. But some reason it is not triggered. $(".cart-link a").click is not triggered when I click on add to cart. Is there a special way to add jquery to colorbox content?
Try this instead:
$(".rest-menuitem a").colorbox({
href: function(){
return $(this).attr('href') + ' .products';
},
width: '650px',
height: '10px',
onComplete: function() {
$(this).colorbox.resize();
}
});
ColorBox uses jQuery's load() method for it's ajax handling, so you just need to add the desired selector to the link's href.
For your question 2 can you try this ?
$(document).ready(function() {
$(".cart-link a").live('click',function(event) {
$(this).colorbox.close();
});
});
For your question 1..it will be slow since you are fetching it from different page.Use a different logic for that
For your question no 1
$('selector').colorbox({onLoad: function() { /*Intially load a empty color box with only <div id="contenttoload"></div> (No other html content */
$.ajax({
url :'Your url',
data : {}, //data to send if any
type : "POST" //or get
success:function(data){ /*data means the stuff you want to show in color box which you must return from the other page*/
$('#contenttoload').html(data); //data should be well formatted i mean add your css,classes etc from the server itself */
}
});
}});