On a previous ajax call I get all articles for a selected Page.
Then I display them and bind this function - on click - to each of them. This is working only one time.
When I want to change a second or third article the article id inside the ajax call keeps holding its first value.
CKEDITOR.replace( 'editor1' );
function editArticle(article){
// id changes for each article as it is supposed to
var id = article.attr('data-id');
var text = article.html();
$('#ckModal').modal();
$('.modal-title').text('Editing Article: '+id+' on Page: '+pageTitle);
CKEDITOR.instances.editor1.setData(text);
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.on('save', function(e){
e.cancel();
var html = CKEDITOR.instances.editor1.getData();
if(html){
$.ajax({
type: 'POST',
url: '/admin/nodes/edit',
cache: false,
data: {'html' : html,
'articleId' : id }
}).done(function(msg){
// next two lines did not work
//CKEDITOR.instances.editor1.fire('save');
//CKEDITOR.instances.editor1.stop('save');
// id stays the same
console.log(id);
// I echo an 'ok' string when update worked from php
if(msg === 'ok'){
article.html(html);
$('#ckModal').modal('hide');
}else{
//alert(msg);
}
}).fail(function(xhr, status, error){
console.log(JSON.stringify(xhr));
console.log("AJAX error: " + status + ' : ' + error);
});
}
});
}
I had to cancel the save event to get and set Data and perform the ajax call.
But how do I restart or reset the 'save' event - if this is what is causing the problem. I am not so shure anymore ....
Got it working by destroying editor instance in ajax done function and creating a new one after it.
function editArticle(article){
var id = article.attr('data-id');
var text = article.html();
//CKEDITOR.replace( 'editor1' );
$('#ckModal').modal();
$('.modal-title').text('Editing Article: '+id+' on Page: '+pageTitle);
CKEDITOR.instances.editor1.setData(text);
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.on('save', function(e){
e.cancel();
var html = CKEDITOR.instances.editor1.getData();
if(html){
var title = $('.modal-title').html()
$('.modal-title').prepend(spinner);
$.ajax({
type: 'POST',
url: '/admin/nodes/edit',
cache: false,
data: {'html' : html,
'articleId' : id }
}).done(function(msg){
//console.log(id);
$('.modal-title').html(title);
if(msg === 'ok'){
article.html(html);
$('#ckModal').modal('hide');
CKEDITOR.instances.editor1.destroy();
CKEDITOR.replace( 'editor1' );
}else{
//alert(msg);
}
}).fail(function(xhr, status, error){
console.log(JSON.stringify(xhr));
console.log("AJAX error: " + status + ' : ' + error);
});
}
});
}
You are assigning multiple event listeners on your editor instance 'editor1', one for each article. What happens is when you click save, the first listener (the first article assigned) called cancels all others with e.cancel().
I see you achieved what you wanted by destroying your editor. Doing this removes event listeners, and solves your problem. You could achieve the same with calling e.removeListener() in the handler, this way removing itself after the first run and avoiding the need to recreate the editor. Also note that destroying editors and recreating them is leaking memory (some versions worse than others #13123, #12307), so one should probably avoid doing that if possible.
Both solutions make the save button unusable after a save; of course it will work after another article is chosen for editing. So my suggestion is to remove all previous listeners from your save command before assigning a new one, like this:
// ... in function editArticle ...
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.getCommand('save').removeAllListeners();
CKEDITOR.instances.editor1.on('save', function(e){
// ...
Related
I am building a website using php + jquery.
In a jquery ajax page, I have to clear caches every time by ctrl +F5, otherwise, the buttons of this page can not be clicked.
My thought is refresh this page mandatorily by "window.location.reload(true);" , but I could not clear the caches at the same time!
Is there any Jquery or something can clear the caches automatically after clicking the buttons instead of ctrl +F5?
my codes are below:
...
$("[id = One_Click_Accept]").click(function(){
...
$.ajax({
url: WebsitePath + '/accreditation_check/' + CurAccreditationId,
data: {
accreditation_id: CurAccreditationId,
IsAccredited: 1,
CheckerName:$('#CheckerName').val(),
CheckTime: Math.round(new Date().getTime()/1000).toString(), //it need a 10 digit timestamp to save to the db.
TheCountry : TheCountry,
TheSchool: TheSchool,
TheDegree: TheDegree,
TheMajor: TheMajor,
YearOfGraduation: YearOfGraduation
},
type: "POST",
dataType: 'json',
cache: false,
success: function (Result) {
if (Result.Status == 1) {
alert('认证成功');
} else {
alert('认证失败');
$("#One_Click_Accept").val('再次认证');
}
},
error: function () {
alert('认证失败');
$("#One_Click_Accept").val('再次认证');
}
});
}
//window.location.reload(true);
});
Thank you guys!
I resolved it by using "setTimeout(function()" to delay the load time.
Not only that, I had to use a different selector, It looks like "$(document).on('click',"[id = One_Click_Accept]",function(e) ".
I have an AJAX call to the create_pdf.php page:
$('body').on('click', '.PrintButtonWithClass', function (event) {
var1 = $('#id1').val();
var2 = $('#id2').val();
dataString='var1='+var1+'&var2='+var2+'&pdf_name=PdfName&pdf_creator=myname';
$.ajax({
type: 'post',
url: '/path/to/createpdf/file/create_pdf.php',
data: dataString,
success: function (data) {
alert('success');
}
});
});
In create_pdf.php I tried to use this line to download the file:
$pdf->Output(str_replace(' ','_',utf8_decode($_POST['pdf_name'])).'.pdf', 'D');
I tried also the FD and I parameters with no success, the file does not get downloaded.
How can I force downloading the file created without saving it to the webserver and without redirecting user to any other page? I want him to stay on the same page, and that the browser pops up a (download or preview dialog box) for the PDF. Is there any way to do it?
EDIT : create_pdf.php is Waiting for POST variables. and uses them to create the HMTL for the pdf.
You can try to submit the form to a new window( like a popup ):
<form method="post" id="myform" action="your_url">
<input name="param1">
</form>
And in javascript
// create popup window
var wind = window.open('about:blank', '__foo', 'width=700,height=500,status=yes,resizable=yes,scrollbars=yes');
// submit form to popup window
$("#myform").attr("target", "__foo");
Do not forget to send content-type header from php:
header("Content-Type", "application/pdf");
Edit:
Browsers should display your pdf content and also show download or print options.
The code is not tested but I think it would do what you requested;
I found a work-around for my problem.
I did an AJAX call inside another AJAX call.
the first AJAX call creates the file on webServer and opens the file in a new Window.
In his success parameter I do the following:
The second AJAX call that deletes the file from Server.
$.ajax({
type: 'post',
url: '/path/to/create_pdf.php',
data: dataString,
success: function (data) {
window.open(
data,
'_blank' // <- This is what makes it open in a new window.
);
window.setTimeout(function () {
dataString2 = 'Downloaded=true';
$.ajax({
type: 'post',
url: '/path/to/create_pdf.php',
data: dataString2,
success: function (data) { alert(data); }, // handler if second request succeeds
});
}, 5000);
},
});
Using this answer to my similar request : send a csv file from php to browser
I needed to (1) get and display a pdf in another window; and
(2) get a CSV file and prompt for saving.
I have 2 simple buttons on the page (http://potoococha.net/) for each. Here is the code:
function getCSVText(evt) {
if (currentChecklistCountry) {
var form = $('<form method="post" action="../php/sendCSV.php?country=' + currentChecklistCountry + '"></form>');
$('body').append(form);
form.submit();
form.remove();
}
else checklistCountryButton.classList.add("needsAttention");
}
function openChecklistPage() {
if (!currentChecklistCountry) {
checklistCountryButton.innerHTML = "Select Country";
checklistCountryButton.classList.add("needsAttention");
return;
}
if (gNumDays == undefined) gNumDays = 12;
vars = "?country=" + currentChecklistCountry;
vars += "&num_days=" + gNumDays;
vars += "&line_nos=" + lineNumbers.checked;
vars += "&left_check=" + leftCheck.checked;
vars += "&endemics=" + showEndemics.checked;
vars += "&sci_names=" + !sciNames.checked;
vars += "&italics=" + !italics.checked;
window.open( '../php/makePDF.php' + vars, '_blank' );
}
So the getCSVText() methods downloads a file using a temporary form appended and then immediately removed, and openChecklistPage() successfully opens another browser window with a pdf file. The pdf file is never saved on the server. The CSV file is already stored there and just retrieved. Perhaps you can modify the code for your purposes.
At this moment I am using laravel. In this context I am having a form which is successfully submitted by using ajax to a controller. and that controller make it to the database. But the problem is as the ajax is doing its job the whole page remain unmoved / unchanged after the submission even the database is updated.
Now what I want
I want to give feedback to the user that your post is successfully submitted there. or what I want to do in further, I want to refresh the section in which the post is collected from the database as this post can be retrieved from there. But by using ajax only.
So there is no need to collect the whole page or refresh.
here is my form structure
`
{{ Form::open(array('route' => array('questions.store'), 'class' => 'form-horizontal' )) }}
blah blah blaaa .......
<script type="text/javascript">
$(".form-horizontal").submit(function(e){
$(this).unbind("submit")
$("#ask").attr("disabled", "disabled")
var that = $(this),
url = that.attr('action'),
type = that.attr('method'),
data = {};
that.find('[name]').each(function(index, value){
var that = $(this),
name = that.attr('name'),
value = that.val();
data[name] = value;
});
$.ajax({
url: url,
type: type,
data: data,
success: function(response){
console.log(response);
}
});
return false;
});
</script>
{{ Form::close() }}
`
As it is very much visible that the post is updated through a route & controller I want to have another dive and a success message at this script to be displayed after the success of posting. I am looking for some professional structure using what there is minimal need to have interaction with the server side and give user a better page viewing experience.
Thanks a lot for helping me in this research.
I am not sure if I understand you well, but if you want to notify the user about the result of an ajax-called db update you need to have
a route for the ajax save db call - it should point to a method that does the db update.
the db update method should return some value indicating the success/failure of update (for example OK or FAIL)
the only result of calling the method will be just plain text page with OK or FAIL as body
fetch the result by ajax and inform user accordingly (after form submit button)
check out the below code for ajax call itself (inside the form submit handler) to see what I mean
var db_ajax_handler = "URL_TO_YOUR_SITE_AND_ROUTE";
var $id = 1; //some id of post to update
var $content = "blablabla" //the cotent to update
$.ajax({
cache: false,
timeout: 10000,
type: 'POST',
tryCount : 0,
retryLimit : 3,
url: db_ajax_handler,
data: { content: $content, id: $id }, /* best to give a CSRF security token here as well */
beforeSend:function(){
},
success:function(data, textStatus, xhr){
if(data == "OK")
{
$('div.result').html('The new Question has been created');
}
else
{
$('div.result').html('Sorry, the new Question has not been created');
}
},
error : function(xhr, textStatus, errorThrown ) {
if (textStatus == 'timeout') {
this.tryCount++;
if (this.tryCount <= this.retryLimit) {
//try again
$.ajax(this);
return;
}
return;
}
if (xhr.status == 500) {
alert("Error 500: "+xhr.status+": "+xhr.statusText);
} else {
alert("Error: "+xhr.status+": "+xhr.statusText);
}
},
complete : function(xhr, textStatus) {
}
});
EDIT: as per comment, in step 2 (the method that is called with AJAX) replace
if($s)
{
return Redirect::route('questions.index') ->with('flash', 'The new Question has been created');
}
with
return ($s) ? Response::make("OK") : Response::make("FAIL");
EDIT 2:
To pass validation errors to the ajax-returned-results, you cannot use
return Response::make("FAIL")
->withInput()
->withErrors($s->errors());
as in your GIST. Instead you have to modify the suggested solution to work on JSON response instead of a plain text OK/FAIL. That way you can include the errors in the response and still benefit from the AJAX call (not having to refresh the page to retrieve the $errors from session). Check this post on the Laravel Forum for a working solution - you will get the idea and be able to fix your code.
I am allowing users to upvote an item. When they click the up arrow, I have jQuery change the class of the arrow so that it turns green. Now, if the user clicks that same arrow again, I want to create an event to change that arrow back to its original class, so they are undoing their vote (like stackoverflow voting: click once to upvote, click again to undo). Anyway here is my code.
These are the arrow classes in php generated on page load.
<a href="javascript:void(0)" id = "' . $row['item_id'] . 'up"
'; if ($row['upVote'] > 0) { echo '
class = "used_upArrow"
';} else {echo '
class = "new_upArrow"
';} echo '
rowid="' . $row['item_id'] . '">
</a>
Here is my jQuery changing the class on an upvote (among other things). This all works perfectly.
//upArrow
$('.new_upArrow').click(function(){
var row = $(this).attr('rowid');
$.ajax({
type: "GET",
url: "upVote.php?id="+row,
cache: false,
async: false,
success: function() {
$('.'+row).html(parseInt($('.'+row).html()) + 1);
document.getElementById(row+'up').className = "used_upArrow";
},
error: function(result){
alert('Voting error, please try again.');
}
});
});
Here is where the undoing should occur. So, new_upArrow should now be used_upArrow, and this script should fire on click.
$('.used_upArrow').click(function(){
var row = $(this).attr('rowid');
$.ajax({
type: "GET",
url: "downVote.php?id="+row,
cache: false,
async: false,
success: function(result) {
$('.'+row).html(parseInt($('.'+row).html()) - 1);
document.getElementById(row+'up').className = "new_upArrow";
},
error: function(result){
alert('Voting error, please try again.');
}
});
});
Checking firebug, the class is in fact changing FROM new_upArrow TO used_upArrow, but it continues to UPVOTE when clicked as if the class has no changed. Any ideas what is going on? Thank you in advance.
Use jQuery live event binding, eg
$('.new_upArrow').live('click', function(){
and
$('.used_upArrow').live('click', function(){
The reason your event binding isn't working is because the normal bind, eg element.click() is processed only once at the time of execution.
The live binder uses event delegation which will attach the handler to matching elements now and in the future.
I would guess your problem is that the event handlers aren't getting installed for the .used_upArrow class when your code thinks it is. When you change the className to "used_upArrow" here:
$('.new_upArrow').click(function(){
...
success: function() {
$('.'+row).html(parseInt($('.'+row).html()) + 1);
document.getElementById(row+'up').className = "used_upArrow";
},
}
The event handler for the other class will not be bound to the other .used_upArrow class. So, the same event handler will get called when you click the element, instead of switching event handlers. That is, calling $('.used_upArrow').click(function() { }) will only bind that event handler for any elements that currrently have that class assigned to them at the time the event is bound, and not any elements that may acquire that class in the future through the triggering of other events. Since the element doesn't get the .used_upArrow class until the .new_upArrow class is called, that event handler is probably never called.
You could rebind the event handler in the first event handler, but it's probably a lot simpler to add another class to both the .used_upArrow and .new_upArrow and then change behavior/state based on whether the element has one or the other classes, something like this:
<div class="upArrow <?php echo $row['upVote'] > 0 ? 'used' : 'new'; ?>"
id="<?php echo $row['item_id'] . 'up'; ?>"
data-rowid="<?php echo $row['id']; ?>">
</div>
$('.upArrow').click(function() {
var row = $(this).attr('data-rowid');
var id = $(this).attr('id');
var list = [{
incr: 1,
url: 'upVote.php',
thisClass: 'new',
otherClass: 'used'
},{
incr: -1,
url: 'downVote.php',
thisClass: 'used',
otherClass: 'new'
}];
var params = list[$(this).hasClass('new') ? 0 : 1];
$.ajax({
type: "GET",
url: params.url + "?id=" + row,
cache: false,
async: false,
success: function() {
$('.'+row).html(parseInt($('.'+row).html()) + params.incr);
$(id).removeClass(params.thisClass).addClass(params.otherClass);
},
error: function(result){
alert('Voting error, please try again.');
}
});
});
(This would also need you to change any CSS classes from .upArrow_used and .upArrow_new to .upArrow.new and .upArrow.used)
This way you don't have to change the event handler when the element changes state.
When you first bound the click events to used .new_upArrow, those events are registered to those who have the .new_upArrow class. That being said, when you changed the class to .used_upArrow, the event bindings did not change. Thus, you'll need to rebind the click event to the updated class.
Hope it helped. Cheers!
I have a form that uses ajax to submit data to a mysql database, then sends the form on to PayPal.
However, after submitting, if I click the back button on my browser, change some fields, and then submit the form again, the mysql data isn't updated, nor is a new entry created.
Here's my Jquery:
$j(".submit").click(function() {
var hasError = false;
var order_id = $j('input[name="custom"]').val();
var order_amount = $j('input[name="amount"]').val();
var service_type = $j('input[name="item_name"]').val();
var order_to = $j('input[name="to"]').val();
var order_from = $j('input[name="from"]').val();
var order_message = $j('textarea#message').val();
if(hasError == false) {
var dataString = 'order_id='+ order_id + '&order_amount=' + order_amount + '&service_type=' + service_type + '&order_to=' + order_to + '&order_from=' + order_from + '&order_message=' + order_message;
$j.ajax({ type: "GET", cache: false, url: "/gc_process.php", data: dataString, success: function() { } });
} else {
return false;
}
});
Here's what my PHP script looks like:
<?php
// Make a MySQL Connection
include('dbconnect.php');
// Get data
$order_id = $_GET['order_id'];
$amount = $_GET['order_amount'];
$type = $_GET['service_type'];
$to = $_GET['order_to'];
$from = $_GET['order_from'];
$message = $_GET['order_message'];
// Insert a row of information into the table
mysql_query("REPLACE INTO gift_certificates (order_id, order_type, amount, order_to, order_from, order_message) VALUES('$order_id', '$type', '$amount', '$to', '$from', '$message')");
mysql_close();
?>
Any ideas?
You really should be using POST instead of GET, but regardless, I would check the following:
That jQuery is executing the ajax call after you click back and change the information, you should probably put either a console.log or an alert calls to see if javascript is failing
Add some echos in the PHP and some exits and go line by line and see how far it gets. Since you have it as a get, you can just load up another tab in your browser and change the information you need to.
if $j in your jQuery is the form you should be able to just do $j.serialize(), it's a handy function to get all the form data in one string
Mate,
Have you enclosed your jquery in
$j(function(){
});
To make sure it is only executed when the dom is ready?
Also, I'm assuming that you've manually gone and renamed jquery from "$" to "$j" to prevent namespace conflicts. If that isn't the case it should be $(function and not $j(function
Anyway apart from that, here are some tips for your code:
Step 1: rename all the "name" fields to be the name you want them to be in your "dataString" object. For example change input[name=from] to have the name "order_from"
Step 2:
Use this code.
$j(function(){
$j(".submit").click(function() {
var hasError = false;
if(hasError == false) {
var dataString = $j('form').serialize();
$j.ajax({ type: "GET", cache: false, url: "/gc_process.php?uu="+Math.random(), data: dataString, success: function() { } });
} else {
return false;
}
});
});
You'll notice i slapped a random variable "uu=random" on the url, this is generally a built in function to jquery, but to make sure it isn't caching the response you can force it using this method.
good luck. If that doesn't work, try the script without renaming jquery on a fresh page. See if that works, you might have some collisions between that and other scripts on the page
Turns out the problem is due to the fact that I am using iframes. I was able to fix the problem by making the page without iframes. Thanks for your help all!