Using HTML5, how do I use contenteditable fields in a form submission? - html

So I have a bunch of paragraph elements which are dynamically populated from a db. I have made the elements contenteditable. I now want to submit edits back the the db via a standard form submission. Is there a way to post the contenteditable elements back?

You have to use javascript one way or the other, it won't work as a "standard" form element as it would with a textarea or the like. If you like, you could make a hidden textarea within your form, and in the form's onsubmit function copy the innerHTML of the contenteditable to the textarea's value. Alternatively you could use ajax/xmlHttpRqeuest to submit the stuff a bit more manually.
function copyContent () {
document.getElementById("hiddenTextarea").value =
document.getElementById("myContentEditable").innerHTML;
return true;
}
<form action='whatever' onsubmit='return copyContent()'>...

If anyone is interested I patched up a solution with VueJS for a similar problem. In my case I have:
<h2 #focusout="updateMainMessage" v-html="mainMessage" contenteditable="true"></h2>
<textarea class="d-none" name="gift[main_message]" :value="mainMessage"></textarea>
In "data" you can set a default value for mainMessage, and in methods I have:
methods: {
updateMainMessage: function(e) {
this.mainMessage = e.target.innerText;
}
}
"d-none" is a Boostrap 4 class for display none.
Simple as that, and then you can get the value of the contenteditable field inside "gift[main_message]" during a normal form submit for example, no AJAX required. I'm not interested in formatting, therefore "innerText" works better than "innerHTML" for me.

Does it NEED to be standard form submission? If you cannot or do not want use a form with inputs, you may try AJAX (XMLHttpRequest + FormData), through which you could perform asynchronous requests and control better how response shows up.
If you want it even simpler, try jQuery's $.ajax function (also $.get and $.post). It sends data using simple JS objects.

Made a fully working example based on Rob's idea:
After hitting submit, the (hidden) textarea is updated with the table-data, in JSON-format.
(return true to submit)
function copyContent() {
const table = [];
$("tr").each(function() {
const row = [];
$("th, td", this).each(function() {
row.push($(this).text());
});
table.push(row);
});
$("#rows").val(JSON.stringify(table));
// return true to submit
return false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form onsubmit='return copyContent()'>
<textarea name="rows" id="rows" rows="4"></textarea>
<button type="submit">Submit</button>
</form>
<table class="table table-striped">
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
</tr>
</thead>
<tbody>
<tr>
<td contenteditable="true">edit </td>
<td contenteditable="true">me</td>
</tr>
<tr>
<td contenteditable="true">please</td>
<td contenteditable="true">😊</td>
</tr>
</tbody>
</table>

Related

Manipulate Html table with Angular

very simple
what is the equivalent of this jQuery code
$('#message tr').eq(index).addClass('negative') in angular,
or how can i achieve the same result with angular
can't use [class.bind] the above job should be done in by clicking the button.
the button will pass some data to the function and based on some condition and checking the negative class will be added to the related row not to all of them.
You have not added any code, so I imagine you have something like:
<table>
<tr *ngFor="let data of arrayData;let i=index" [class.negative]="indexSelected==i">
<td>{{data?.prop1}}</td>
<td>{{data?.prop2}}</td>
<td><button
(click)="indexSelected=(indexSelected==i)?-1:i;
indexSelected!=-1 && diifer(data)">
select
</button>
</td>
</tr>
</table>
(or instead use a button add the "click" to the <tr>)
You can also pass the "index" to the function diifer like
(click)="diifer(data,i)"
And
diifer(data:any,index)
{
this.indexSelected=this.indexSelected==index?-1:index
if (this.indexSelected!=-1)
{
...do something..
}
}
NOTE: See that you check if indexSelected is the "row" you select. If true, you "unselect" making indexSelected=-1
NOTE2: remember that index goes from 0 to arrayData.length-1

Passing innerHtml value as parameter for play framework routes

hello i am trying to pass inline edited table value as a parameter to play routes can someone help me with the same
here is my html code
<table class="gradienttable">
<thead>
<tr>
<th>Task</th>
<th>TimeSheetdate</th>
<th>Hours</th>
<th>IsBilled</th>
<th>Work Place</th>
</tr>
</thead>
<tbody>
#for(element <- CurrentPage) {
<tr>
<td contenteditable="true" id="task1">#element.getTask()</td>
<td>#element.getTimeSheetDate()</td>
<td contenteditable="true" id="hours">#element.getHours()</td>
<td contenteditable="true" id="isbilled">#element.getIsBilled()</td>
<td contenteditable="true"id="workplace">#element.getWorkPlace()</td>
<td>
</tr>
}
</tbody>
</table>
routes
GET /Application/edit controllers.Application.edit(task1:String)
application.java
public static Result edit(String task1)
{
return ok(DisplayTimeSheet.render(task1));
}
It looks like you're confusing the server-side rendered Scala template with the DOM actions of the client. For #{routes.Application.edit(task1.innerHTML)}, task1 doesn't exist as far as the non-DOM template is concerned.
Your use of <a href="..."> is kind of weird, because that would make a synchronous call and if you're into inline editing then maybe that's not what you want. This answer covers an asynchronous approach using Play's JavaScript router support (which, if you haven't seen it before, is very cool).
You'll need to expose edit in the JavaScript router:
// You can also return an F.Promise<Result>
public static Result jsRoutes() {
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("appRoutes", //appRoutes will be the JS object available in our view
routes.javascript.Application.edit()));
}
And then expose that method in the routes:
GET /assets/js/routes controllers.Application.jsRoutes()
That will generate a chunk of JavaScript that you can import
<script src="#controllers.routes.Application.jsRoutes()" type="text/javascript"></script>
And finally, write some JavaScript to handle the inline editing completion.
function doInlineEdit(taskName) {
appRoutes.controllers.Application.edit(taskName).ajax( {
success : function ( data ) {
target.closest('li').remove();
}
});
}
Then you just need to wire that method to be called when your inline-editable element changes content.
You can find additional info here.

How to make TableSorter.js working with the table on demad via some JS and inc.php file

I have a table that I want to make sortable. The problem is that this table has been loaded from the external file (inc.php) via some JS (filter-data.js) function. To be more precisely, I have a main.php page with the Submit button. When I click on it, that triggers some JS code which calls inc.php file to populate my table with its data on demand from MySQL base and then puts them both (table + data) back to the main page:
This is the table placeholder on the main page.
<div id="tableData"></div>
This is the submit button on the main page:
<input type="submit" onclick="genTable()" value="Populate users data">
This is what I am geting form the table.inc.php page:
<table id="my-table">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>45</td>
<td>34</td>
</tr>
<tr>
<td>23</td>
<td>17</td>
</tr>
</tbody>
</table>
I am not sure how and where to call TS function - should it be on the main.php page or table.inc.php page?
I tried almost everything but with no success.
$("#my-table").tablesorter();
If I skip JS and just require my table.inc.php file from main.php page, it works properly.
Thank you!
It is better practice to separate the HTML from scripting, so to do this, add this to your page (or even better, move the stuff inside the script tag into an external file):
<script>
// dom ready
$(function(){
// do something when the submit button is clicked
$('input[type=submit]').click(function(){
// generate table
genTable();
// add sorting
$("#my-table").tablesorter();
});
});
</script>
Then modify your submit button code by removing the onclick attribute:
<input type="submit" value="Populate users data">
If that doesn't work, could you share the genTable(); code with us?
Sadly, I'm about to go out of town for a week... hopefully I can help you before then.
What I would recommend doing is download my fork of tablesorter because it has an option to disable client-side sorting: serverSideSorting (reference).
Then you can bind to tablesorter's sortEnd function:
$("#my-table").on("sortEnd", function(e, table) {
// get sorting information
// [[0,0]] means sort the first column (zero-based index) in ascending direction
// [[0,1]] means sort the first column in a descending direction
// [[0,0], [2,0]] means sort the first and third columns, both in the ascending direction
var sortList = table.config.sortList,
// set the sort direction
// this is why I need to know what is stored in the #sort element,
// or how the server knows how to sort the data
d = 'something';
$('#sort').val( d );
genTable();
// initialize tablesorter again, because the entire table is being replaced
// Otherwise if you only update the tbody, use:
// $("#my-table").trigger('update');
$("#my-table").tablesorter({
theme : 'blue', // required theme option (tablesorter fork)
serverSideSorting : true
});
});

jQuery event bound to dynamically created DOM elements fires erronously

I have this markup.
<form action='xxx.php' method='post'>
<table>
<tr>
<th>Branch Id</th>
<td><input id="branchId" type="text" size="15%" name="branchId"></input></td>
<th>Branch Name</th>
<td colspan="3"><input id="branchName" type="text" size="75%" name="branchName"></input></td>
<td>
<div id="button">
<input type="button" id="btnAdd" value="Add" name="submit"/>
</div>
</td>
</table>
</form>
<!------- Something here--------------->
<table class="divTable" id="exisBranch">
<tr><th id="thBranchId">Branch Id</th>
<th id="thBranchName">Branch Name</th>
<th class="btn" id="tcEdit">Edit</th>
<th class="btn" id="tcDelete">Delete</th>
</tr>
</table>
What basically happens is I populate the second table records retrieved through AJAX. Each row has a 'branchId','branchName' and two buttons of class 'bt'. When I click the edit button, I need the corresponding 'branchId' and 'branchName' values inserted into input elements in the first table, so that I can edit them and later, when I click the "btnAdd", I can save them.
This is the jQuery I have.
function fun(){
var branchId=$(this).closest("tr").find("td").eq(0).html();
$("#btnAdd").click(function () {
if($("#btnAdd").val()=='Save')
{
alert(branchId);
//ajax call
}
});
}
$(document).ready(function(){
$("#exisBranch").on('click','.bt',fun);
$("input[type='button']").click(function(e){
e.preventDefault();
});
});
Everything works fine when I click the 'btnAdd' for the first time. The problem starts with the second and successive clicks on this button.Consider that there are 6 rows in the dynamically populated content, and that 'branchId' of each row is the corresponding row number.
When I first click on 'EDIT' button on the 2nd row, and then the 'btnAdd', an alert correctly pops up showing 2.
Problem is , if I then go on to click 'EDIT' on the 6th row, and then the 'btnAdd' , I get two alerts. The first one shows 2, then 6.I just want 6.
For the third round, it goes like 2,6, and what ever is clicked next. This is making my AJAX fire as many no. of times as the no. of clicks.
This is really infuriating.I just can't seem to figure out why. I am a jQuery novice, so please bear with me if this is something fundamental and I messed it up.Please let me know how to make it fire only once with the latest value, instead of it stacking up on my history of calls?
You shouldn't keep binding your Add button w/ each Edit click--move it out to your document ready.
<script>
var branchId; //keep track of which branch is under edit
function fun(){
branchId = $(this).closest("tr").find("td").eq(0).html();
var branchName = $(this).closest("tr").find("td").eq(1).html();
$('#branchId').val(branchId);
$('#branchName').val(branchName);
}
$(document).ready(function(){
$("#exisBranch").on('click','.btn',fun);
$("#btnAdd").click(function () {
if($("#btnAdd").val()=='Save') {
alert(branchId);
//ajax call
}
});
$("input[type='button']").click(function(e){
e.preventDefault();
});
});
<script>
*you have a number of typos in your stack post.
The problem is that you are attaching a new click handler each time that fun is called. These handlers are not unbound after they fire, so the handlers are building up. You could use jquery's one to ensure that each event fires only once.
Really though, your entire approach is not ideal. Off the top of my head, one possible improvement which wouldn't take too much re-engineering would be to store the IDs in an array, then when add is clicked, process the array and clear it. This would let you only have one handler on add as well as allow for batch ajax calls instead of one per id.

How to pass the listid to servlet when I click a hyperlink in jsp

I have a list of items being displayed in a html table, where there is a hyperlink in every row.
When I click the hyperlink, I want to call the servlet with that particular item id.
how can i achieve it?
for 10 items.
<tr>
<td>
<input type="hidden" name="" value="%=request.getAttribute("item_id")%>"
</td>
<td align="center">
<font> (String)providerDetail.get("tripTime")<font />
</td>
<td align="center">
<font>(String) providerDetail.get("noOfSeats")</font>
<td align="center">
<font> Select font </font>
</td>
</tr>
endfor
So, when I click the hyperlink, I need to pass the appropriate item_id to the servlet.
How to have the appropriate input element for the running item_id and to pass the same to servlet?
I am not being able to add html elements as it is not formatted correctly.
On assumption you are using ajax, onclick call a javascript method, pass item_id as parameter to that method.
Then send this to your server as data (I am using jQuery to do this, you can use any other library )
function sendData(item_id){
jQuery.ajax({
type:"POST",
data:"itemId="+item_id,
success: function(data){
//Your code for a successful request goes here.
},
error: function(data){
//Errors treatment goes here.
}
})
}
In case you are doing something like download of a document based on the item id, this is a good example code for that:
var form = '<form action="downloadme"><input type="hidden" name="itemid" value='+item_id+'</form>';
jQuery(form).submit();
Create a form and submit it, and as an hidden parameter pass item_id.
On completion remove that form from body(as you do not need it anymore).
Hope this helps.