edit-in-place, how to make more db fields editable - ajax

Good evening guys!
I just managed to implant a really sweet working edit-in-place function with jQuery and AJAX. I'm able to edit 1 db field. I would like to be able to edit multiple db fields.
These are all the scripts:
Update query (handler.php)
<?php
include('../../core/additional/connect-db.php');
if (isset($_POST['id']) && isset($_POST['firstname'])) {
$firstname = mysql_real_escape_string($_POST['firstname']);
$id = mysql_real_escape_string($_POST['id']);
$query = "UPDATE players SET firstname ='$firstname' WHERE id='$id'";
$result = mysql_query($query) or die ('Query couldn\'t be executed');
if ($result) {echo 1;}
}
?>
And the ajax in the head
<script type="text/javascript">
$(document).ready(function()
{
$(".editable").hover(
function()
{
$(this).addClass("editHover");
},
function()
{
$(this).removeClass("editHover");
}
);
$(".editable").bind("dblclick", replaceHTML);
$(".btnSave, .btnDiscard").live("click", handler);
UI("Ready");
function UI(state)
{
var status = {};
status.Ready = "Ready";
status.Post = "Saving your data. Please wait...";
status.Success = "Success! Your edits have been saved.";
status.Failure = "Attempts to save data failed. Please retry.";
var background = {};
background.Ready = "#E8F3FF";
background.Post = "#FAD054";
background.Success = "#B6FF6C";
background.Failure = "#FF5353";
$("#status").animate({opacity: 0}, 200, function (){$("#status").html(status[state]).css({background: background[state]}).animate({opacity: 1}, 200)});
}
function handler()
{
var selector="";
var code="21";
if ($(this).hasClass("btnSave"))
{
UI("Post");
var str = $(this).siblings("form").serialize();
$.ajax({
type: "POST",
async: false,
timeout: 100,
url: "core/actions/handler.php",
data: str,
success: function(msg){code = msg; $(".message_edit").show(); $(".message_edit").fadeOut(2500);},
});
if(code == 1)
{
UI("Success");
selector = "editBox";
}
else
{
UI("Failure");
selector = "buffer";
}
}
else {selector = "buffer"}
$(this).parent()
.html($(this).siblings("form")
.children("."+selector)
.val())
.removeClass("noPad editHover")
.bind("dblclick", replaceHTML);
return false;
}
function replaceHTML()
{
var buffer = $(this).html()
.replace(/"/g, """);
$(this).addClass("noPad")
.html("")
.html("<form class=\"editor\"><input type=\"text\" name=\"firstname\" class=\"editBox\" value=\"" + buffer + "\" /> <input type=\"hidden\" name=\"buffer\" class=\"buffer\" value=\"" + buffer + "\" /><input type=\"hidden\" name=\"id\" class=\"record\" value=\"" + $(this).attr("id") + "\" /></form>Save Cancel")
.unbind('dblclick', replaceHTML);
}
}
);
</script>
Then the field is displayed and editable by using this:
<td class="editable" id="' .($id). '" width="180">' .($task). ' </td>
I might be able to copy and rename all scripts, but I'm positive that's not the ideal way to do it. I tried to copy the script in the handler.php file and renamed the db fields, and did the same for the ajax script. But it didn't work. I hope my 'problem' is clear to you, any suggestions?
Note: I think the solution lies somewhere in this line (bottom of the ajax script):
.html("<form class=\"editor\"><input type=\"text\" name=\"firstname\" class=\"editBox\" value=\"" + buffer + "\" /> <input type=\"hidden\" name=\"buffer\" class=\"buffer\" value=\"" + buffer + "\" /><input type=\"hidden\" name=\"id\" class=\"record\" value=\"" + $(this).attr("id") + "\" /></form>Save Cancel")
Thanks in advance for helping out! :)

You may want to look at using the Jeditable jQuery plugin (http://www.appelsiini.net/projects/jeditable) and for a good example of various uses you can look at the demo page:
http://www.appelsiini.net/projects/jeditable/default.html
Also, I hope you are not actually going to use that php script to update the database, as that is vulnerable to SQL injection attacks, so it is bad practice.
And I don't see any element with the class editable in the html, just editBox.
And finally, you are submitting all the elements each time there is to be a change? That is quite inefficient, as one advantage of editing in-place is to just send small changes each time.

Related

Updating "tr" data in laravel

I'm facing difficulty in doing this task :
- I have a table that have an add delete , update buttons for every single row I've done the add and delete thing by adding data-attribute for each button according to the row's data Id. It works perfectly for deleting and inserting elements. Yet i can't find a way to update every single row so i need help !
Note: I'm updating my elements using Ajax.
Any strategy ? i can post a screenshot for my code/view cause it is a bit too long .
More explanation : when you click on the edit button $(this) and delete button hide , and check button appears . inputs are no longer hidden for this row so the user updates the data of this row then he checks it.
The data must update inside the database .
I'm stuck nowhere because every row has its own id and its own values and only one query must be run for every row ( which is the same query for all the rows ) . It's more likely having one form for the whole table that updates only the row that must be updated .
After you click on edit button
$(document).on('click', '.btn-edit-interview', function() {
var id = $(this).attr('data-interview-id');
var selector = ('' + '.tr' + id + '');
var selectordelt = ('' + '.' + id + '');
var selectorsave = ('' + '#save-'+id + '');
$(this).hide();
$(selectordelt).hide();
$(selectorsave).show();
$(selector).prop('disabled', false);
$(selector).addClass("form-control");
$(selector).css('border: 1px solid rgb(204, 204, 204);margin-top: 16px;');
});
I just need help in finding a way do make the update query for every single row .
//HTML
<tr data-unique="{!! $yourVariable->id !!}">
<td><input value="{!! $yourVariable->value !!}"></td>
<td><button data-update="{!! $yourVariable->id !!}">Update</button></td>
</tr>
//AJAX
$('button[data-update]').click(function() {
var itemID = $(this).attr('data-update');
//Will contain value of input in that tr only
var input = $('tr[data-unique="+itemID+"] input').val();
$.ajax({
url: '/update',
type: 'POST',
dataType: 'json',
data: {item: itemID, anotherValue: input},
success:function(data){
if(data['status'] == "success"){
alert("Updated");
}
}
});
return false;
});
//Controller
public function update(Request $req){
YourModel::where('id', $req->input('item'))->update(['column' => 'value']);
return response()->json(['status' => 'success']);
}
//Route
Route::post('/update', 'YourController#update');
Hope that help

Ajax in a Joomla 3.x component's view

I'm building a Component for Joomla 3.x and I encounter a problem handling an ajax request.
The source is available on Github: JomCity
My request is made from the venues view : /com_jomcity/site/views/venues/tmpl/default.php
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery('#main_search_request').keyup(function() {
var request_content = jQuery(this).val();
jQuery.get(
// Specify the server URL and the $_GET datas to send
'index.php?option=com_jomcity&task=searchVenues&format=json',
{ search: request_content },
// The server will respond with some data encoded in JSON
function(data){
jQuery('#results').html('');
for (var i = 0; i < data.venues.length; i++) {
var venue = data.venues[i];
console.log(venue);
jQuery('#results').append(
'<div class="grid-item">' +
'<a href="#">' +
'<img src="http://placekitten.com/g/80/80" alt="">' +
'<div>' +
'<div>' +
'<h3>'+venue.name+'</h3>' +
'<span>* * * * *</span>' +
'</div>' +
'<div>Short descrption</div>' +
'</div>' +
'</a>' +
'</div>'
);
}
}
);
});
});
</script>
This ajax script communicate with the main controller of the component (site part), so I'm wondering how can I get the values from the model com_jomcity/site/models/venues.php.
Is it possible with this code ? Or should I handle the ajax request in the controller of the view (I didn't find how to do that) ?
Thanks #Torreto and #GDP for your participation.
I finally kept on creating a task in the main controller exchanging with the database directly, so without using any model. I think it should exist a better and cleaner way to code this ajax call, so I'm open to any advice for further improvement.
The code I used, if it can help someone :
In /com_jomcity/site/views/venues/tmpl/default.php:
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery('#main_search_request').keyup(function() {
var request_content = jQuery(this).val();
jQuery.get(
// Specify the server URL and the $_GET datas to send
'index.php?option=com_jomcity&task=searchVenues&format=json',
{ search: request_content },
// The server will respond with some data encoded in JSON
function(data){
// Clean the #result div between two search results
jQuery('#results').html('');
// Read and display each objects returned in the json response
for (var i = 0; i < data.length; i++) {
var venue = data[i];
jQuery('#results').append(
'<div class="grid-item">' +
'<a href="#">' +
'<img src="http://placekitten.com/g/80/80" alt="">' +
'<div>' +
'<div>' +
'<h3>'+venue.en_name+'</h3>' +
'<span>* * * * *</span>' +
'</div>' +
'<div>Short descrption</div>' +
'</div>' +
'</a>' +
'</div>'
);
}
}
);
});
});
</script>
In /com_jomcity/site/controller.php:
class JomCityController extends JControllerLegacy
{
/**
* Search in all the venues
* #return string The message to be displayed to the user
*/
public function searchVenues() {
if (isset($_GET['search'])) {
// Get a db connection
$db = JFactory::getDBO();
// Create a new query object
$query = $db->getQuery(true);
// Select all records from the jomcity_venues_items table
// Where the name or the description correspond to the user's search keywords
// Order it by the en_score field
$query
->select('*')
->from('#__jomcity_venues_items')
->where('`local_name` like "%'.$_GET['search'].'%" OR `en_name` like "%'.$_GET['search'].'%" OR `description` like "%'.$_GET['search'].'%"')
->order('en_name ASC');
// Reset the query using our newly populated query object
$db->setQuery((string)$query);
// Load the results as a list of stdClass objects.
$this->venues = $db->loadObjectList();
}
echo json_encode($this->venues);
}
}

Jquery returning all to much data I only want the table

Hi im attempting to use jquerys ajax to update a form after a GET request, I simply want the table to update but it send through the page headers as well.
First Here is my script, its small so i will include it all,
var wishorder = {
init: function(config){
this.config = config;
this.bindEvents();
},
bindEvents: function(){
this.config.itemSelection.on('click',this.addWish);
},
addWish: function(e){
console.log('working');
var self = wishorder;
$.ajax({
url: $(this).attr('href'),
type: 'GET',
data: {
sku: $(this).data('sku'),
action: $(this).data('action'),
qty: $(this).data('qty')
},
success: function(results){
//here is where is would like to repopulate the div
//but its outputting the whole page
console.log(results);
}
});
e.preventDefault();
}
};
wishorder.init({
itemSelection: $('#carttable a'),
form: $('#cartfrm')
});
I can see that it is returning the results i want but it wraps it in html as in page header.
Here are the php function its calling.
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_GET['action'] == 'move'){
list($sp_type, $pid) = $this->parse_sku($_GET['sku']);
$qty = (filter_var($_GET['qty'], FILTER_VALIDATE_INT, array('min_range' >= 1)))?$_GET['qty']:1;
$q = "CALL add_to_wish_list('$this->uid', '$sp_type', $pid, $qty)";
$this->query($q);
$q = "CALL remove_from_cart('$this->uid', '$sp_type', $pid)";
$this->query($q);
$q = "CALL get_shopping_cart_contents('$this->uid')";
$this->query($q);
$this->read();
$this->outcart();
exit();
}
and the outcart function wich generates the html for the div
function outcart(){
echo "<div id=\"cartcont\" class=\"cartitems\"><form action=\"/cart.php\" method=\"post\"><table id=\"carttable\"><tr class=\"theads\"> <th class=\"titm\" >Item</th> <th >Quantity</th> <th >Price</th> <th>Subtotal</th> <th class=\"topt\" >Options</th>";
$total = 0;
while($row = $this->_result->fetch_object()){
$price = $this->get_just_price($row->price, $row->sale_price);
$subtotal = $price * $row->quantity;
$total += $subtotal;
echo "<tr class=\"tdata\">
<td>".$row->category." :: ".$row->name."</td>
<td><input type=\"text\" name=\"quantity[".$row->sku."]\" value=\"$row->quantity\" size=\"2\">
<td>$".$price."</td>
<td>$".number_format($subtotal, 2)."</td>
<td> Move To Wishlist <br> Remove From Cart </td>";
}
echo "</tr><tr class=\"ttotals\"><td colspan=\"3\" ><strong id=\"carttotal\">TOTAL:</strong></td>
<td colspan=\"2\" > $".number_format($total,2) ." </td>
</tr>";
echo "</table>";
echo "<div id=\"cartmnbtns\"><p><input type=\"submit\" value=\"UPDATE QUANTITIES\" class=\"buttoncart1 green\"><br>Checkout</p> </div></form>";
}
So i just want to repopulate the table really or the cartcont div with the results, where am missing the point?
The page you're calling is url: $(this).attr('href') and that's a web-page you're just on with all headers and stuff... You have to put your functions in a separate .php file that doesn't contain a whole web-page frame and only outputs the text you want.
If that's not possible then create in your success callback function with document.createDocumentFragment(), pass the whole response inside the fragment and pull out your stuff you need with something like myHTML = docFrag.getElementsByTagName('div')[0] and then pass this with append to your form.
You might also want to set something like contentType: "text/plain; charset=utf-8" in your ajax call.
By the way: If you're not using the convenience of parsing variables inside strings you might want to use a different way (the other quotes) of writing your strings, as it's then faster, so:
echo '<tr class="tdata">...'

Ajax and output pdf file are not working together

I have a file named download.php and call getpdf function inside it.
I call download.php via ajax to download pdf file when users click download button. but nothing happend and no download window appears. I checked it in firebug Net tab and download.php are requested on click event. Its size also changes that shows the file is reading from its location,but no download window.
Here's getpdf code:
function getpdf($id) {
header('Content-Type: application/pdf');
readfile('/san/theo-books/PDFs/'.$id.'.pdf');
exit;
}
And here's download.php code:
$pdf_id = $_POST('pdi');
echo getpdf($pdf_id);
What is the problem? Would you help me?
Here is the full postback version. It's not using the jQuery Ajax, because Popup download window needs the full postback:
<a id="pdf-10" href="#">PDF Export</a>
$(document).ready(function () {
$('a[id^="pdf"]').click(function (event) {
event.preventDefault();
var pdfExportPath = "/san/theo-books/PDFs/";
var $a = $(this);
var postId = $a.attr('id').replace("pdf-","");
var form = $('<form action="' + pdfExportPath + '" name="pdf' + postId + '" id="pdf' + postId + '" method="POST"> <input id="id" name="id" type="hidden" value="' + postId + '" /></form>');
$(form).appendTo('body');
form.submit();
});
});

Prototype observers attached to a class firing multiple times

Thanks in advance for your help guys.
I consider myself pretty well-versed in jQuery but as I was helping my sister with her Prototype homework, this frustrated the crap out of me. She couldn't solve it in time so that's moot but for my sanity's sake, I hope you can tell me what's going on.
We were simply creating a netflix-style queue with add, reorder and delete through AJAX. The items were in a UL and had a delete link inside each LI with unique IDs to be used for deletion. Please don't fixate on why we were using text files to save data, etc. - her professor made that impractical choice a requirement, along with a few others...
JS:
function softRefresh() {
$$('.delete').invoke('observe','click',function() { taskDelete(this.id); });
Sortable.create("taskList", { onUpdate: function(list){ saveOrder(list); } });
}
function taskDelete(a) {
var tempArr = a.split('-');
var keyToDelete = tempArr[1];
var output;
var ajaxRequest = new Ajax.Request("todolist.php",
{
method: "post",
parameters: {
action: 'delete',
id: keyToDelete
},
onSuccess: function(response) {
$('taskList').update(response.responseText);
softRefresh();
}
});
}
PHP for the 'delete' action:
$jsonOutput = file_get_contents($myFile);
$fetchedArr = json_decode($jsonOutput);
$newArr = array();
foreach($fetchedArr as $key => $task) {
if(($key != $_POST['id'])) {
array_push($newArr, $task);
}
}
$jsonOutput = json_encode($newArr);
file_put_contents($myFile, $jsonOutput);
$output = '';
foreach($newArr as $key => $task) {
$output .= '<li id="list_'.$key.'">';
$output .= $task;
$output .= 'X';
$output .= '</li>';
}
echo $output;
The problem was that if I deleted, say, the 2nd item, all the following items would delete as well. Through firebug console I found out that this is because when you click any link of that class ('delete') all the following listeners fire, and keeps deleting the 2nd item off the new list. Can you tell me why and how I can set it so it only fires off the link you click? It drove me nuts all day. I'm used to having .click() on jQuery... much hatred for Prototype at the moment.
Thanks again!
JS:
You shouldn't need the softRefresh if you set the events well. Likewise, the <ul> element is never disposed nor replaced so only one Sortable should be necessary, there is no need to remake that each time.
Event.on('taskList', 'click', '.delete', taskDelete);
Sortable.create("taskList", { onUpdate: saveOrder });
function taskDelete(event, element) {
var id = element.id;
var tempArr = id.split('-');
var keyToDelete = tempArr[1];
new Ajax.Updater({success: 'taskList'}, "todolist.php",
{parameters: {
action: 'delete',
id: keyToDelete
}}
);
}
(Ajax objects in prototype are already POSTs so that doesn't need to be specified. Use of an Updater is neater too. There is little point in wrapping a function call in an anonymous function, it may be the jQuery way but it isn't adding any functionality, javascript functions are objects so use them as such.)
PHP:
I felt $newArr was a waste of a loop and some memory so here is a shorter way.
$jsonOutput = file_get_contents($myFile);
$fetchedArr = json_decode($jsonOutput);
unset($fetchArr[$_POST['id']]);
// Keys are preserved here, if you need to reorder use:
// $fetchedArr = array_values($fetchArr);
$jsonOutput = json_encode($fetchedArr);
file_put_contents($myFile, $jsonOutput);
foreach($fetchedArr as $key => $task) {
echo '<li id="list_'.$key.'">';
echo $task;
echo 'X';
echo '</li>';
}

Resources