I'm using ajax to load new post pages into the content section of my site and using pushstate to edit the url each time. I'm looking for a way to move when the forward and back buttons are clicked on the browser.
My thinking was to create an array of post id's adding one to the list every time I move forward
$(document).on("click", ".title[data-ajax='post']", function() {
$post_id = $(this).data("id");
$post_type = $(this).data("type");
$post_url = $(this).data("url");
var historyData = $(".wrapper").attr("data-history");
if (!historyData){
historyData = [];
}
else{
historyData = JSON.parse(historyData);
}
historyData.push({
id: $post_id,
type: $post_type,
url: $post_url
});
var data = {
action : 'new_ajax_'+ $post_type +'_template',
post_id : $post_id
};
$("#main").empty().hide();
$.ajax({
url : ajax_object.ajax_url,
type : 'post',
data : data,
success: function(html) {
$("#main").append(html);
history.pushState('data', '', $post_url);
$(".wrapper").attr("data-id", $post_id);
$(".wrapper").attr("data-history", JSON.stringify(historyData));
$("#main").fadeIn("fast");
}
});
});
But instead of this I want to create two seperate arrays for forward and back id's so when back is triggered, I can snag the last post id in the "back" array to get the content I need.
My question is how to detect forward or backward on popstate to achieve this or a better way in general to implement this.
$(window).on('popstate', function(event) {
<---detect direction---->
});
Related
I want to test a conroller which generates a page with a field that changes dynamically with ajax.
Here is the code of ajax:
<script>
var $groupeCompetence = $('#requete_prestataire_groupeCompetence');
// When sport gets selected ...
$groupeCompetence.change(function() {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected sport value.
var data = {};
data[$groupeCompetence.attr('name')] = $groupeCompetence.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
// Replace current position field ...
$('#requete_prestataire_competence').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#requete_prestataire_competence')
);
// Position field now displays the appropriate positions.
}
});
});
</script>
How can I call this code from phpunit using client or crawler?
I tried :
$this->client->request(
'POST',
'/',
array('requete_prestataire[groupeCompetence]' =>2),
array(),
array(),
array('HTTP_X-Requested-With' => 'XMLHttpRequest',
));
But it doesn't work.
Thanks a lot !
I found the solution :
you have to disable validation, and send the form as it was generated :
$crawler = $this->client->request('GET', '/');
$form = $crawler->selectButton('requete_prestataire_Rechercher')->form();
$form['requete_prestataire[groupeCompetence]'] = 2;
$form['requete_prestataire[competence]']->disableValidation()->select(50);
$crawler = $this->client->submit($form);
here is the explanation in doc :
doc symfony dom crawler component
function postToGoogle() {
var name = $('#name').val();
var phone = $('#phone').val();
var college = $('#college').val();
var email = $('#email').val();
var year = $("input[type='radio'][name='qs6']:checked").val();
$.ajax({
url: "https://docs.google.com/forms/u/1/d/e/KEY/formResponse",
data: {
"entry.1735346271": name,
"entry.393911750": phone,
"entry.1827584616": email,
"entry.1041274008": college,
"entry.334726096":year
},
type: "POST",
dataType: "xml",
statusCode: {
0: function() {
window.location.href("URL");
// window.open("URL");
alert("Thank you for sending us your details.");
},
200: function() {
window.location.href("URL");
// window.open("URL");
alert("Thank you for sending us your details.");
}
}
});
}
Well am trying to send data into the google sheet through above function which I succeeded but I want after submitting the form when status code is O or 200 ,I want an alert box and the page is redirected to another page. While trying I was able to manage to show the alert box but not able to redirect the page.Can anyone suggest me where I am going wrong?
You are using window.location.href incorrectly. It is not a function that you call, but rather a property that you change by assigning a new value.
Change the part of your code that does the redirect to this:
window.location.href = "URL";
(I assume that "URL" in your example is actually a valid URL in your actual code).
You should also put the alert statement after the redirect statement, otherwise it won't be displayed because the page location has changed before that.
Hi all I have an app in Backbone where inside a function I want to convert price from GBP to EUR for example using a php file called with ajax.
In the success function I want to assign the converter data to my object.
But seems that not setting this because into the template uin underscore there is always the old value.
This is my function inside my model:
toJSON: function() {
var json = _.clone(this.attributes);
json.rooms = this.rooms.toJSON();
_.each(json.rooms, function(room){
var converter ="<?php echo(site_url('/backend/hotel/ajax_currency')); ?>";
$.ajax({
url: converter,
type: "POST",
data: {
from_currency : room.currency,
amount : room.price_adult
},
dataType: "json",
success: function(data) {
console.log(data);
room.price_adult = data;
}
});
});
return json;
},
I have also tried:
room.model.set('price_adult',data);
but return me error that don't find model.
How can I solve?
This is not a thing you want to put in toJSON function, I can think of several reason why it should work for you. The most important one is that toJSON function is synchronous and the AJAX response is async. so your render function is happening before you get the response from your ajax.
I would suggest having a Room model that will be responsible for the concurrency, and it's view will render it when ajax has returned and the price_adult is ready.
var Room = Backbone.Model.extend({
initialize:function(){
this.convertConcurrency();
},
convertConcurrency:function(){
var model = this;
$.ajax(.....,
success:function(data){
model.set("price_adult", data);
}
);
},
});
var RoomView = Backbone.View.extend({
initialize: function(){
this.listenTo(this.model, "change:price_adult", this.render);
if (this.model.has("price_adult")) this.render();
},
.....
});
var Rooms = Backbone.Collection.extend({...})
var RoomsView = // Rooms collection view
This way the view will be rendered only when there is a price_adult ready.
Maybe you should create a model on the client that gather the concurrency information from the server and compute the concurrency conversation by itself, so you will only have one ajax and the model will compute it for you instead of the server.
I am updating my Model through a resource controller via jQuery Ajax Put. No problems at all the first time. This works fine:
$(".addNest").click(function() {
var nid = msg; //once the LI is added, we grab the return value which is the nest ID
var name = $('.nestIn').val();
if(name == '') {
$("textarea").css("border", "1px solid red");
}else {
$.ajax({
type: 'PUT', // we update the default value
url: 'nests/' + nid,
data: {
'name': name
},
success: function(msg) {
alert(msg)
window.location.replace('nests/' + nid ); //redirect to the show view
}
});
}
});
Later in a separate code block, I try to call the PUT again like this:
$(".nestEdit").click(function() {
$(".nestEdit").hide();
var name = $('.nestName').data("name");
var nid = $('.nestName').data("id");
$(".nestName").html("<textarea class='updateNest'>"+ name +"</textarea> <span><a href='#' class='btn btn-mini nestUpdate'><i class='icon-plus'></i> Update</a></span>");
$(".nestUpdate").click(function() {
var updatedName = $('.updateNest').val();
$.ajax({
type: 'PUT', // we update the default value
url: 'nests/' + nid,
data: {
'name': updatedName
},
success: function(msg) {
alert(msg) // showing the error here
location.reload( ); //refresh the show view
}
});
});
The 'updatedName' values and the 'nid' values are passing fine when I 'alert' them. When I view the return for the first PUT it comes back fine. However, when I view the return for the second PUT I get this:
{"error":{"type":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException","message":"","file":"\/Applications\/MAMP\/htdocs\/n4\/bootstrap\/compiled.php","line":8643}}
Anyone have some insights here? As you can tell, I am trying to do an inline edit. I have tried to wrap everything into a function but still not helping...
Laravel does not use PUT and DELETE natively since it is not supported in all browsers, you need to send a POST request with '_method' set to either put or delete.
$.ajax({
type: 'POST',
url: 'nests/' + nid,
data: {
'name': updatedName,
'_method': update
},
success: function(msg) {
alert(msg) // showing the error here
location.reload( ); //refresh the show view
}
EDIT: Ajax request do support PUT AND DELETE.
In your JavaScript code, for the inline editing, you are not making proper use of $.
If you click on .nestEdit, it's inner function should not be calling it by name, provided you have multiple objects of the same class on that page. This is why you get the error. Instead of sending the nest ID, it's sending an array object, which your Laravel Router will not pick up, because it is more than likely not defined.
Simply put, you should not be doing this:
$(".nestEdit").click(function() {
$(".nestEdit").hide();
...
You should be making a call to this:
$(".nestEdit").click(function() {
$(this).hide();
...
So, for every .nestEdit within the inner function, you need to call for this instead.
I'm trying to use Ajax in CakePHP, and not really getting anywhere!
I have a page with a series of buttons - clicking one of these should show specific content on the current page. It's important that the page doesn't reload, because it'll be displaying a movie, and I don't want the movie to reset.
There are a few different buttons with different content for each; this content is potentially quite large, so I don't want to have to load it in until it's needed.
Normally I would do this via jQuery, but I can't get it to work in CakePHP.
So far I have:
In the view, the button control is like this:
$this->Html->link($this->Html->image('FilmViewer/notes_link.png', array('alt' => __('LinkNotes', true), 'onclick' => 'showNotebook("filmNotebook");')), array(), array('escape' => false));
Below this there is a div called "filmNotebook" which is where I'd like the new content to show.
In my functions.js file (in webroot/scripts) I have this function:
function showNotebook(divId) {
// Find div to load content to
var bookDiv = document.getElementById(divId);
if(!bookDiv) return false;
$.ajax({
url: "ajax/getgrammar",
type: "POST",
success: function(data) {
bookDiv.innerHTML = data;
}
});
return true;
}
In order to generate plain content which would get shown in the div, I set the following in routes.php:
Router::connect('/ajax/getgrammar', array('controller' => 'films', 'action' => 'getgrammar'));
In films_controller.php, the function getgrammar is:
function getgrammar() {
$this->layout = 'ajax';
$this->render('ajax');
}
The layout file just has:
and currently the view ajax.ctp is just:
<div id="grammarBook">
Here's the result
</div>
The problem is that when I click the button, I get the default layout (so it's like a page appears within my page), with the films index page in it. It's as if it's not finding the correct action in films_controller.php
I've done everything suggested in the CakePHP manual (http://book.cakephp.org/view/1594/Using-a-specific-Javascript-engine).
What am I doing wrong? I'm open to suggestions of better ways to do this, but I'd also like to know how the Ajax should work, for future reference.
everything you show seems fine. Double check that the ajax layout is there, because if it's not there, the default layout will be used. Use firebug and log function in cake to check if things go as you plan.
A few more suggestions: why do you need to POST to 'ajax/getgrammar' then redirect it to 'films/getgrammar'? And then render ajax.ctp view? It seems redundant to me. You can make the ajax call to 'films/getgrammar', and you don't need the Router rule. You can change ajax.ctp to getgrammar.ctp, and you won't need $this->render('ajax');
this is ajax call
$(function() {
$( "#element", this ).keyup(function( event ) {
if( $(this).val().length >= 4 ) {
$.ajax({
url: '/clients/index/' + escape( $(this).val() ),
cache: false,
type: 'GET',
dataType: 'HTML',
success: function (clients) {
$('#clients').html(clients);
}
});
}
});
});
This the action called by ajax
public function index($searchterm=NULL) {
if ( $this->RequestHandler->isAjax() ) {
$clients=$this->Client->find('list', array(
'conditions'=>array('LOWER(Client.lname) LIKE \''.$searchterm.'%\''),
'limit'=>500
));
$this->set('clients', $clients);
}
}
This is a function I use to submit forms in cakephp 3.x it uses sweet alerts but that can be changed to a normal alert. It's very variable simply put an action in your controller to catch the form submission. Also the location reload will reload the data to give the user immediate feedback. That can be taken out.
$('#myForm').submit(function(e) {
// Catch form submit
e.preventDefault();
$form = $(this);
// console.log($form);
// Get form data
$form_data = $form.serialize();
$form_action = $form.attr('action') + '.json';
// Do ajax post to cake add function instead
$.ajax({
type : "PUT",
url : $form_action,
data : $form_data,
success: function(data) {
swal({
title: "Updated!",
text: "Your entity was updated successfully",
type: "success"
},
function(){
location.reload(true);
});
}
});
});