Inline Table Editing with AJAX - javascript

I am trying to use this library that allows for inline table editing, and AJAX updates - well I've been having a ton of trouble figuring out how to communicate between it and my MySQL database that contains all the information contained in the rows.
Here's the code example provided:
Unless you just want people to dink around with the transient-by-nature current page, you'll probably want to define/override the InlineEditor.elementChanged function and do something that saves the user's changes. Here is an example using AJAX to immediately post a change. In this case, I used my handy ajax.js code to do it.
InlineEditor.elementChanged = function( theElement, oldVal, newVal )
{
mySavingIndicator( theElement );
var url = "http://www.myserver.com/update.php?id=" + cell.id + "&val="+newVal;
AJAX.getText( url, function( response ){
clearMySavingIndicator( theElement );
alert( 'Did the save work? ' + response );
}); // end ajax callback function
}; // end elementChanged
What I am really wondering about here is what is cell.id, is it normal Javascript, and what output does it give? How can I use this to allow my cells to be editable and go back to the database? My supervisor really wants inline editing and while I have been working in Javascript and with AJAX all week, it is very difficult for me to provide this to him!

I would think you'd have var url = "http://www.myserver.com/update.php?id=" + theElement + "&val="+newVal; which, may BE the id of the cell being edited.
Or, you may have some existing object 'cell' that, in some 'didStartEditing' type of function, would have the id property set to reflect the element being edited

Related

How do I send a parameter on click to be used in sql query?

My UI is a jquery grid. How can I send a parameter to the function (that creates my query) on click from my UI jquery grid?
For example, if this was my grid:
http://www.ok-soft-gmbh.com/jqGrid/OK/formEditOnDoubleClick-jqueryui-showlink.htm#
I would want the client name sent to the query to use as a filter.
The next page (not google link, as shown in the example when a client is clicked on) would have a grid that only listed companies with that client.
How do I create a query with this functionality?
I want to know how to send a parameter from my UI to the back-end query function.
EDIT ****
Here's what I came up with -
Inside of the UI code (that creates the jqgrid):
function returnHyperLink(cellValue, options, rowdata, action)
{
return '<a id="myLink" href="#" onclick="callCompanies(\''+cellValue+'\');">'+cellValue+'</a>'
}
function callCompanies(cellValue) {
$("#contents").load("jsp/companies.jsp");
}
and then in the back-end code:
I add
#GET
#Path("/{cellValue}")
to the top of my function and eventually can use cellValue to filter the query, like:
+ " where a.evt_type_id = cellValue " + "and "
I posted the demo for the answer on your previous question and described the properties of options parameter. The rowid is the rowid. Thus one can use getLocalRow (getRowData or getCell) to access to the data from the row. Then one can just append the
onClick: function (options) {
var item = $(this).jqGrid("getLocalRow", options.rowid);
window.location = "https://www.google.com/#q=" + encodeURIComponent(item.name);
}
You can see the results on the modified demo. I remind that onClick can be defined in formatoptions of formatter: 'showlink' for free jqGrid fork, which I develop.
If you prefer to use custom formatter then you can define the value of onclick using this and event. You can modify the code fragment onclick="callCompanies(\''+cellValue+'\');" used in your code to for example following
onclick="callCompanies.call(this, \''+cellValue+'\', event);"
Then you can use $(this).closest("tr.jqgrow").attr("id") inside of callCompanies function to get the rowid. It allows to use getLocalRow, getRowData or getCell to get the data from the row.

Ajax call in "for" loops skips odd/even iterations

If I am here asking it is because we are stuck on something that we do not know how to solve. I must admit, we already searched in StackOverflow and search engines about a solution.. but we didn't manage to implement it / solve the problem.
I am trying to create a JavaScript function that:
detects in my html page all the occurrences of an html tag: <alias>
replaces its content with the result of an Ajax call (sending the
content of the tag to the Ajax.php page) + localStorage management
at the end unwraps it from <alias> tag and leaves the content returned from ajax call
the only problem is that in both cases it skips some iterations.
We have made some researches and it seems that the "problem" is that Ajax is asynchronous, so it does not wait for the response before going on with the process. We even saw that "async: false" is not a good solution.
I leave the part of my script that is interested with some brief descriptions
// includes an icon in the page to display the correct change
function multilingual(msg,i) {
// code
}
// function to make an ajax call or a "cache call" if value is in localStorage for a variable
function sendRequest(o) {
console.log(o.variab+': running sendRequest function');
// check if value for that variable is stored and if stored for more than 1 hour
if(window.localStorage && window.localStorage.getItem(o.variab) && window.localStorage.getItem(o.variab+'_exp') > +new Date - 60*60*1000) {
console.log(o.variab+': value from localStorage');
// replace <alias> content with cached value
var cached = window.localStorage.getItem(o.variab);
elements[o.counter].innerHTML = cached;
// including icon for multilingual post
console.log(o.variab+': calling multilingual function');
multilingual(window.localStorage.getItem(o.variab),o.counter);
} else {
console.log(o.variab+': starting ajax call');
// not stored yet or older than a month
console.log('variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language);
$.ajax({
type: 'POST',
url: my_ajax_url,
data: 'variable='+o.variab+'&api_key='+o.api_key+'&lang='+o.language,
success: function(msg){
// ajax call, storing new value and expiration + replace <alias> inner html with new value
window.localStorage.setItem(o.variab, msg);
var content = window.localStorage.getItem(o.variab);
window.localStorage.setItem(o.variab+'_exp', +new Date);
console.log(o.variab+': replacement from ajax call');
elements[o.counter].innerHTML = content;
// including icon for multilingual post
console.log(o.variab+': calling multilingual function');
multilingual(msg,o.counter);
},
error: function(msg){
console.warn('an error occured during ajax call');
}
});
}
};
// loop for each <alias> element found
//initial settings
var elements = document.body.getElementsByTagName('alias'),
elem_n = elements.length,
counter = 0;
var i = 0;
for(; i < elem_n;i++) {
var flag = 0;
console.info('var i='+i+' - Now working on '+elements[i].innerHTML);
sendRequest({
variab : elements[i].innerHTML,
api_key : settings.api_key,
language : default_lang,
counter : i
});
$(elements[i]).contents().unwrap().parent();
console.log(elements[i].innerHTML+': wrap removed');
}
I hope that some of you may provide me some valid solutions and/or examples, because we are stuck on this problem :(
From our test, when the value is from cache, the 1st/3rd/5th ... values are replaced correctly
when the value is from ajax the 2nd/4th .. values are replaced
Thanks in advance for your help :)
Your elements array is a live NodeList. When you unwrap things in those <alias> tags, the element disappears from the list. So, you're looking at element 0, and you do the ajax call, and then you get rid of the <alias> tag around the contents. At that instant, element[0] becomes what used to be element[1]. However, your loop increments i, so you skip the new element[0].
There's no reason to use .getElementsByTagName() anyway; you're using jQuery, so use it consistently:
var elements = $("alias");
That'll give you a jQuery object that will (mostly) work like an array, so the rest of your code won't have to change much, if at all.
To solve issues like this in the past, I've done something like the code below, you actually send the target along with the function running the AJAX call, and don't use any global variables because those may change as the for loop runs. Try passing in everything you'll use in the parameters of the function, including the target like I've done:
function loadContent(target, info) {
//ajax call
//on success replace target with new data;
}
$('alias').each(function(){
loadContent($(this), info)
});

Dynamic table onclick

I have the following issue i would like to get some help for.
There is a combobox (select) where i choose an item and i get back a dinamic table from php. The table contains example names. Firstname, Lastname and ID(which is hidden). When i click on the table i get the value of the ID of the selected row. So far it is works fine. The problem that the event doesnt want to fire for first. After that it works fine but i need it for first as i have a function which auto click on the first row but this doesnt work until i solve this problem. I made a code which works fine with a html table. But not with the dinamic one. Please help.
Here is the code works fine with dinamic table but just after 2nd click:
function nametableclick() {
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data=(this.cells[3].innerHTML);
var data = data;
$.ajax({
type: "POST",
url: "list.php",
data: "data="+data,
Type: "json",
success: function(msg) {
msg = JSON.parse(msg);
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
}
});
};
};
};
And here is the code works well but just with html table:
(Actually is same but i use onload)
onload = function() {
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data=(this.cells[3].innerHTML);
var data = data;
$.ajax({
type: "POST",
url: "list.php",
data: "data="+data,
Type: "json",
success: function(msg) {
msg = JSON.parse(msg);
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
}
});
};
};
$("#nametable tr:eq(0) td:first-child").click();
};
When i use the onload function for the dinamic table it just doesnt work at all.
Thanks for any help in advance.
This question does not suit well for an answer. Instead, I'll do some code analysis.
onload = function() ... - well not terrible but kinda sloppy. Also looks like this is possible a global namespace leak. I'm going to assume this should be window.onload in which case I'd wonder why jQuery's ready event isn't used $(function() { ... }).
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++) {
rows[i].onclick = function() { ... };
}
Ok now were again running away from jQuery as if it was diseased some how. And then were looping over the array of rows only to construct a new function each time and attach them to the onclick (again avoiding jQuery)? Constructing functions inside a loop is a very bad idea and most linters will complain loudly about that. A suggestion:
$('#nametable tr').on('click', function() { ... });
This will attach the click handler to all the <TR> rows in the table with the id="nametable" attribute.
data=(this.cells[3].innerHTML);
var data = data;
My heart skipped a beat here!. First your pulling out the HTML content into (what I thought was a global variable) until I saw the next line and realized we have variable hoisting. But wait your assigning data to itself. Lastly, the name data doesn't provide any context as to the content of the innerHTML. Since I don't have the data I could only guess so in these examples I'll leave it as data. In the future think about picking names which provide context to their content and use. That way when you read the code you don't have to hunt for what the variables are for or how to use them.
var data = $(this, 'td:eq(3)').text();
Finally, the use of data is to directly concatenate it into a post request. I would assume HTML is not desired in that server API. Not to mention the avoidance of jQuery's parameter building by forcing the data to a string. Instead use a JS object:
$.ajax({
type: 'POST',
url: 'list.php',
data: {data: data} // This is a very poorly designed server API
}).then(function(data) {
...
});
Also, the use of Type: 'json' suggests that your server is not returning proper HTTP headers. First off there is no Type property for jQuery's ajax instead I think you wanted dataType. However the need for a dataType suggests the server is not sending the proper headers. If the PHP script were to return application/json instead of plain/text then jQuery could parse the response for you avoiding the need for JSON.parse on your own which can be a bit error prone.
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
Be warned by using html() your directly injecting HTML into the DOM that you received from a third party. This is a big cross site scripting vulnerability. Use text() instead to push data into the DOM unless you know and can assert the trust of your server and the connection to it (SSL to avoid man in the middle). Probably not important for this example but still worth keeping in mind because it's far to easy to have this show up in the wild.
$("#nametable tr:eq(0) td:first-child")
When you have a selector like this it is far easier and readable to instead provide contextual hooks instead of relying on the make up of the DOM. Add things like class="clickable-row" or class="person-data dob" to your HTML markup. It makes for maintenance and readability.
Thanks for the quick reply. Im sure if there are lot of mistakes as i just started to learn this(i mean php html ajax ect.) a few weeks ago so i dont clearly understand everything and i use things i should not use or should do it another way. But there is a simple program i would like to make it done and learn from that. So when i dont know something im trying to get some info (like: w3schools.com) or check other topics which similar what im looking for.
Sorry i left there the
Var data = data;
My mistake. Dont need there. i was trying out something before and left there. Does not make any different anyway.
next:
The onload = function() {
i found in another topic as solved result and it works with a static table but not with dynamic.
I have tried the following. i did not mentioned:
window.onload = nametableclick;
function nametableclick() {
data here
}
But does not work with dynamic table either.
Next:
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data2=(this.cells[3].innerHTML);
What it does for me it finds the selected row and comes back with the value of the 3rd(actually 4th) cell which is the ID in my prog. I need this cos i want to sent this value to the php to get all the data from the table where ID = the value. And it works fine.
As i mentioned the prog works fine even if it is not the best way to do it. Slowly i gonna learn how to do it better way. But at the moment the only problem with that is that the dynamic table onclick event fires only after the 1st click.
Thanks and sorry if im a bit hard case. :-)))
Oh 1 more thing:
"First off there is no Type property for jQuery's ajax instead I think you wanted dataType."
For some reason if i type dataType it just does not work at all. I have no idea why. I watched some training videos and read some short courses about ajax and some of them mentioned using dataType some of them just simple type. I followed everything but did not worked for me. i spent like 5 hours another day to find out why actually i have a topics here with that question as well.
get data from mysql with ajax and json into different textareas
And accidently i tried with uppercase T once and it worked. Have no idea why.

Variable not updating in script string, yet it updates

Very confused here.
I have a search box which reads a list of school names from my database. When I select a school, the id (from the db) gets put in a hidden textbox.
I also have a search box which reads a list of courses from my database. However, I made the query so that it only reads the courses from the selected school.
It does that, in theory.
I was planning to pass the school id, which I grab from the hidden box, to the search script which in turn passes it to my database query. However, the variable I put my school id in doesn't seem to be updating.. yet it does. Let me explain.
I come on the page. The school for my test account has id 1. The id number in my hidden box is indeed 1. I search for a school which I know has some courses assigned to it: the id number in the box changes to 3.
I have a JS variable called school_id which I declared outside of my $(document).ready. I assume that means it's global (that's what I got taught even though SO told me once it isn't really the correct way to do this. Still have to look into that). I wrote a function which updates this variable when the school search box loses focus:
$("#school").blur(function() {
school_id = $("#school_id").val();
});
A quick javascript:alert(school_id); in my browser bar also shows the updated variable: it is now 3 instead of 1.
Onto the search script part of my page (excerpt of the script):
script:"/profiel/search_richting?json=true&limit=6&id=" + school_id + "&"
As you can see, I pass the school_id variable to the script here. However, what seems to be happening is that it always passes '1', the default variable when the page loads. It simply ignores the updated variable. Does this string get parsed when the page loads? In other words, as soon as the page loads, does it actually say &id=1? That's the only idea I can come up with why it would always pass '1'.
Is there a way to make this variable update in my script string? Or what would be the best way to solve this? I'm probably missing out on something very simple here again, as usual. Thanks a lot.
EDIT
Updated per request. I added a function getTheString as was suggest and I use the value of this function to get the URL. Still doesn't work though, it still seems to be concatenating before I get a chance to update the var. HOWEVER, with this code, my ajax log says id:[object HTMLInputElement], instead of id:1. Not sure what that means.
<script type="text/javascript">
var school_id;
$(document).ready(function() {
$("#school").blur(function() {
school_id = $("#school_id").val();
});
// zoekfunctie
var scholen = {
script:"/profiel/search_school?json=true&limit=6&",
varname:"input",
json:true,
shownoresults:false,
maxresults:6,
callback: function (obj) { document.getElementById('school_id').value = obj.id; }
};
var as_json = new bsn.AutoSuggest('school', scholen);
var richtingen = {
script: getTheString(),
varname:"input",
json:true,
shownoresults:true,
maxresults:6
};
var as_json2 = new bsn.AutoSuggest('studierichting', richtingen);
});
function getTheString() {
return "/profiel/search_richting?json=true&limit=6&id=" + school_id + "&";
}
</script>
This is because the URL is static, it is not updated as the ID changes.
You should update the URL as part of the code you wrote to get the ID:
$("#school").blur(function() {
school_id = $("#school_id").val();
// update URL here ...
});
Aren't you concatenating script:"/profiel/search_richting?json=true&limit=6&id=" + school_id + "&" before the event is fired and the var updated?
Okay. So the problem was my third party plug-in instead of the code I wrote. I fixed this by editing the code of the autoSuggest plugin so it now includes my id field in the AJAX request.
var url = this.oP.script+this.oP.varname+"="+encodeURIComponent(this.sInp)+"&id="+ $("#school_id").val();
Thanks to everyone who tried to help me out!

Ajax not firing on prototype - I think I need to unset or remove a javascript method - causing havoc help!

I'm working using scriptaculous library. However I'm facing some issues with inclusion of the JSON library for the prototype library. It adds a toJSONSTring and parseJSONSTRING method to all objects automatically and frankly this is causing havoc in places. Like I can't seem to use the Ajax Updater function and I suspect its because of this toJSONSTring method that has been attached to my options object which I pass to it.
Is there anyway to unset or atleast somehow remove a function which has been added to the Object.
EDIT:::
Actually I'm trying to make an ajax request and I'm facing an issue in the
Ajax.Updater = Class.create(Ajax.Request,....
part of the prototype library. At the part where its supposed to execute and post an AJAX request it doesn't - especially at:
$super(url, options);
To be precise I'm using this sortable and editable table grid here at this url:
http://cloud.millstream.com.au/millstream.com.au/upload/code/tablekit/index.html
Basically you clcik on a table cell to edit it and push the OK button to confirm. Upon clicking the button an ajax request is made.
The editable feature of the table calls the Ajax updater as follows in a submit function:
submit : function(cell, form) {
var op = this.options;
form = form ? form : cell.down('form');
var head = $(TableKit.getHeaderCells(null, cell)[TableKit.getCellIndex(cell)]);
var row = cell.up('tr');
var table = cell.up('table');
var ss = '&row=' + (TableKit.getRowIndex(row)+1) + '&cell=' + (TableKit.getCellIndex(cell)+1) + '&id=' + row.id + '&field=' + head.id + '&' + Form.serialize(form);
this.ajax = new Ajax.Updater(cell, op.ajaxURI || TableKit.option('editAjaxURI', table.id)[0], Object.extend(op.ajaxOptions || TableKit.option('editAjaxOptions', table.id)[0], {
postBody : ss,
onComplete : function() {
var data = TableKit.getCellData(cell);
data.active = false;
data.refresh = true; // mark cell cache for refreshing, in case cell contents has changed and sorting is applied
}
}));
},
The problem is that the request is never made and I keep pushing the OK button to no avail.
EDIT::::::::::::::::
I'm still stumped here - I've even tried calling the Ajax.Updater function on my own and it won't work at all. Its like this function has officially been rendered as useless all of a sudden. I've made the changes you said but all to no avail :( frankly I'm running out of options here - another idea would be to ditch this tablekit and look for something else which has similar functionality in the hopes that THAT MIGHT work!
It sounds like those methods are being added to the prototype of Object. By adding to Object's prototype, the library is automatically giving everything that derives from Object (in other words, everything) those methods as well. You might want to take do some reading on Prototypal inheritance in Javascript to get a better handle on this.
Anyway, you can remove those methods by doing this:
delete Object.prototype.toJSONString;
delete Object.prototype.parseJSONString;
You can delete anything from an object using "delete":
a.toJSON = function () {};
delete a.toJSON;
a.toJSON() => error: toJSON is not a function
a.toJSON => undefined
However I don't think that what is happening happens because of what you think is happening :) Maybe give more details on the problem you have with Ajax.Updater?
Seen the edit. OK, can you also post the actual line of code that calls Ajax.Updater and, also important, explain in detail how the options object you feed to it is made?
Also, please make sure you're doing something like this:
new Ajax.Updater(stuff)
and NOT just:
Ajax.Updater(stuff)
You NEED to create a new Updater object and use "new" (most probably you're already doing that, just making sure).
OK I'm still not sure what is getting passed to ajax.Updater since you extend stuff that I can't see, but try this: remove the "&" from the beginning of the variable "ss"; in the options object use parameters: ss instead of postBody: ss.
delete obj.property
In this case:
delete obj.toJSONSTring;
delete obj.parseJSONSTRING;

Categories