I'm creating an inline editable table using jQuery and the editable plug-in.
It works well so far but will only submit and save to the database upon pressing ENTER. I found a thread on here which helped me to tab between boxes but it doesn't submit the data when TAB is pressed.
My code that allows me to switch between boxes is as follows:
$('.editScheduleRow').bind('keydown', function(evt) {
if (evt.keyCode==9) {
var nextBox='';
var currentBoxIndex=$(".editScheduleRow").index(this);
if (currentBoxIndex == ($(".editScheduleRow").length-1)) {
nextBox=$(".editScheduleRow:first"); //last box, go to first
} else {
nextBox=$(".editScheduleRow").eq(currentBoxIndex+1); //Next box in line
}
$(this).find("input").blur();
$(nextBox).click(); //Go to assigned next box
return false; //Suppress normal tab
};
});
To submit using ENTER I use this:
$(".editScheduleRow").editable("../../includes/ajax/save-schedule-row.php", {
"submitdata": function ( value, settings ) {
return { fieldname: this.getAttribute('fieldname'), rowID: this.getAttribute('id') };
},
});
I also found a thread with a suggestion but it didn't work for me: jEditable submit on TAB as well as ENTER
Please let me know if you need any more information.
My original answer was based on reading the documentation of jQuery Editable, which is a jQuery extension that is similarly named, but not the same as jEditable from the question. Let's try again with the correct library.
The problem is that you are moving the focus away from the input box when pressing tab, but when the focus is moved away from it, it doesn't save the contents. To illustrate this, try this: click one of the fields and edit it, then click elsewhere on the document. You'll see that the value in the table - and this is what you where simulating using the blur() jQuery function on the element.
There are (again) two ways to solve this problem. First, we can modify what the program does when a field loses focus:
[..]
"submitdata": function ( value, settings ) {
return { fieldname: this.getAttribute('fieldname'), rowID: this.getAttribute('id')
};
"onblur": "submit";
},
[..]
This has the effect that when doing the experiment I described above to help you understand why it wasn't working, you'll now also see that it gets saved. This may not be what you want. In that case, you can instead make sure that you trigger a submit instead of a blur:
replace this line:
$(this).find("input").blur();
by this one:
$(this).find("form").submit();
Now the experiment will no longer cause the value to be changed, but it's no longer an accurate simulation of what we're doing and when pressing tab the value will be changed.
Related
At the moment I'm working on a project that requires the submission of a form for 'voting' for specific posts. At the moment clicking on the submit button works as it should, although if the button is clicked more than once, it does exactly that - submits the POST variables more than once causing them to be able to 'vote' for the item multiple times in one set of clicks.
I've looked at every jQuery code example I can find to solve this but nothing works. It works to disable the button, but after that the redirection page that grabs the data and runs the queries returns an error as nothing has been submitted. In short, it seems to disable the button but at the same time disable the information from being submitted.
Here's my jQuery code:
$('#vote').submit(function(){
$(this).children($btn).attr('disabled', true);
return true;
});
Any help would be great.
Thanks.
Use jquery .one
Description: Attach a handler to an event for the elements. The handler is executed at most once per element.
$(document).one("click","#vote",function(){
$(this).children($btn).attr('disabled', true);
return true;
});
Probably your best option is to only allow a single submission and adjust the button appearance some other way:
var submitted = false;
$('#vote').submit(function(){
if(submitted) {
// cancel additional submits
return false;
}
submitted = true;
$(this).children($btn).val('Please wait...');
});
you could add an click event. Instead of using submit button use a button click event.
the code might look like this
$($button).click(function(){
$(this).attr("disabled","disabled");
$($form).submit();
});
Jquery's on and off can be used here.
for example after submission,you can completely disable the click by
$('#vote').off('click');
and then switch it back if you want by
$('#vote').on('click');
How to get an array of all checkboxes selected on the page, and then passing it to the next page (in this case php, so it can be picked up by php _POST function). I have come up with this :
<script type="text/javascript">
var selected = new Array();
$(document).ready(function() {
$("input:checkbox:checked").each(function() {
selected.push($(this).val());
});
$('#od').submit(function() {
alert(this.selected); // *See note below
$.post('receiver.php', {'registration': selected});
return false;
});
});
</script>
But is does not seem to work :( It returns null, as if no checkboxes would have been added to the array, or maybe the post function is wrong. Can you point me in the right direction here?
I've found the following of issues:
You read the checked items on page load, thus ignoring all changes made by the user. Move that code to the submit() handler.
Your debugging code (alert(this.selected)) tries to display the value of the selected property for the form node. It isn't a reference to your JavaScript global variable selected. I suggest you use a proper debugging tool such as Firebug; alerts are highly unsuitable.
You sucessfully send the values of checked items. You just ignore the field name and rename everything to registration. That looks intended, otherwise report back:
{'registration': selected}
I suppose you can make jQuery serialize the values for you but fixing these little details in your code should do the trick anyway.
I think $("input:checkbox:checked") should be `$("input[type="checkbox"]:checked")
Or simply: $('input:checked', '#form-container');
$('#od').submit(function() {
var selected = $('input[type="checkbox"]:checked').toArray();
$.post('receiver.php', {'registration': selected});
return false;
});
The Data being posted might need to be split up.....
I think I got a classic problem but I was not able to find a working solution so far.
I have got a form , the user clicks "Send" and everything works fine using a PRG pattern and doing both client-side and server-side validation.
The problem arises when any user (let's assume he entered valid inputs) clicks more then once quickly before the server script ends its execution...
I do not get any duplicated entry because I took care of that but the browser does not go to my "thanks for submitting page".
Instead it re-submits the same page with the same values and what I get are the custom errors I set to warn the user he is trying to enter details already stored in the database. The details sent in the first place are all in the database but the user has no chance to know that.
I tried to disable the submit button on a submit event using jQuery but in that case the data are not submitted.
HTML
<div id="send-button-container">
<input id="send-emails" type="submit" name="send_emails" value="Send"/>
</div>
jQuery
$(document).ready(function(){
$('#mail-form').submit(function(){
$('#send-emails').attr('disabled','disabled');
});
});
I am wondering if I can force a submission using Javascript after disabling the button and also how to deal with UAs with Javascript disabled
Thanks in advance
Depending on server-side language, the submit button being disabled could cause problems. This is because disabled elements are not POSTed to the server. Languages like ASP.NET require the button value to be submitted so it knows what event handler to fire. What I usually do is hide the submit button, and insert a disabled dummy button after it, which appears identical to the user. Then in your onsubmit handler, you can return false and submit the form programmatically...
$('#mail-form').submit(function(){
var btn = $('#send-emails');
var disBtn = $("<input type='button'/>").val(btn.val()).attr("disabled", "disabled");
btn.hide().after(disBtn);
this.submit();
return false;
});
Contradictory to the other up-voted answers, please note that you do not need to explicitly return true from your submit handler for natural form submission: http://jsfiddle.net/XcS5L/3/
I assume this means you are depending on the value of the submit button to service the request? That is you are checking
$_REQUEST['send_emails'] == 'Send';
This is not good practice. You should never depend on the value of the submit button because that is the just what is displayed to the user. Instead, you should add a hidden input that contains the event you want to fire. After the form is submitted, you don't need to care what the value of the submit button is and you can disable it. All other non-disabled data in the form is still submitted.
You can indeed force the submission after disabling the button.
$(function () {
$("#mail-form").submit(function () {
$("#send-emails").attr('disabled', 'disabled');
window.location = '?' + $("#mail-form").serialize() + '&send_mails=Send';
return false;
});
});
Server side set a $_SESSION variable that keeps track of the last time they made a submission and block submissions within a certain time.
<?php
session_start();
if (isset($_REQUEST['send_emails'])) {
if (isset($_SESSION['mail_sent'])
&& strtotime($_SESSION['mail_sent']) < strtotime('5 seconds ago')
) {
redirect_to_thanks();
}
do_post();
}
function do_post() {
if (do_validate()) {
$_SESSION['mail_sent'] = time();
redirect_to_thanks();
}
else {
yell_at_user_a_lot();
}
}
?>
You have to return true; You could try this if u want a simple button to submit the form.
$(function(){
$('#submitID').one('click',function(){
$('#formTobeSubmitted').submit();
$(this).attr('disabled','disabled');
})
});
On server side, generate a random number into each form, store the number when the form is submitted, and discard the submit if that number has already been stored earlier. When the user has disabled javascript, this is the best you can do. (Concurrency issues can be tricky as the two identical requests are handled at the same time - make sure you use some sort of locking mechanism, such as a table with a unique field or the flock() command in PHP.)
On browser side, just set a flag when the form is submitted, and discard all later submits:
$('#mail-form').submit(function() {
if ($(this).data('submitted') {
return false;
} else {
$(this).data('submitted', true).addClass('submitted');
}
});
You can use the submitted class to make the buttons gray or something. This has a few advantages to simply disabling them; Josh already said one. Another is that Firefox likes to remember disabled states when you hit refresh, which can cause your users getting stuck in certain situations.
I have some tabs which have been created using Javascript and Mootools, my client wants the 'next button' at the bottom of the page to be disabled, until the tabs have been read(clicked). The page is dynamic (created with PHP and MySQL) and there could be two tabs or three, depending on the set-up. I am struggling today to think of the best solution.
Any help more than welcome...
view example working on jsfiddle:
http://www.jsfiddle.net/dimitar/THMxa/
it can work with some classes and logic added to tab clicks and next click.
// fade out next button and set it to disabled, then define the event to check state.
document.id("next").store("disabled", true).set("opacity", .5).addEvent("click", function() {
if (this.retrieve("disabled")) {
alert("please view all tabs first!");
// console.log(document.getElement("div.notclicked"));
return;
}
// insert code here that goes next.
alert("allowed to run");
});
// this is pseudo - you probably already have a function that assigns events on your tabs to change
document.getElements("div.tabs").each(function(tab) {
// first tab may already be open so no click needed
if (!tab.hasClass("clicked"))
tab.addClass("notclicked");
// add click event
tab.addEvent("click", function() {
if (document.getElement("div.notclicked"))
this.addClass("clicked").removeClass("notclicked");
// check again if that was the last one, if so, enable next button...
if (!document.getElement("div.notclicked"))
document.id("next").store("disabled", false).fade("in"); // or whatever
// regular code for tabs here...
});
});
Since the number of tabs is dynamic, I'd probably use an attribute on the tab's header/label/whatever indicating that it has not been read, and then when the tab's header/label/whatever is clicked, I'd change that attribute to indicate that it had been read and then trigger a function that may enable the button depending on whether all the other tabs had been read.
I'm not a MooTools person, but IIRC it's a fork of Prototype (although it's been a while and they've probably diverged). The click handler could look something like this in Prototype:
$$('.tabClass').invoke('observe', 'click', function(event) {
this.setAttribute("data-read", "Y");
if ($$('.tabClass[data-read=N]').length == 0) {
$('buttonId').disabled = false;
}
});
...where $$ is Prototype's "search the DOM for elements matching this CSS selector" function and $ is Prototype's "get me the element with this ID". The invoke there just calls observe for each matching element (you could do this with event delegation instead), and I think observe is fairly self-evident. :-)
The code above makes these assumptions:
Your tab header or whatever has the class "tabClass".
You've created the tables with the attribute "data-read" set to "N" (e.g., <div class="tabClass" data=read="N"> or similar). The data- prefix is to be HTML5-friendly. (Yes, we're finally allowed to put any old arbitrary attribute name on elements if we want to! We just have to prefix them with data-.)
The button has an ID, "buttonId"
The button starts off disabled
Edit Or use a marker class if you prefer, all tabs start out with class="tabClass unread":
$$('.tabClass').invoke('observe', 'click', function(event) {
this.removeClassName("unread");
if ($$('.tabClass.unread').length == 0) {
$('buttonId').disabled = false;
}
});
Double-check that MooTools supports the ".tabClass.unread" selector (it really should, I'm just saying, check). Some implementations may work more quickly with class-based selectors than attribute-based ones.
You should disable the button where you send the request to load the content,
and enable it from the callback that handles the returned content.
I would add a class to the tab when it's clicked - like "clicked". Also, check if the 'click' is the last tab, so..
$('myElement').set('class', 'clicked');
then get all of the tab elements (a elements i assume) and count them.
Then get all of the tab elements with class "clicked"
If they match, they were all 'clicked'.
I have had a look at sticky notes with php and jquery and jStickyNote, and while both seem to look pretty nifty they lack some elements I am after. I haven't been able to find a way to allow particular users to modify the stickies they create, nor have I found a good way to save their stickies into my database. I am, and would like to keep using php, mysql and jquery. I have thought with the first link that I could just save the image created into a folder and save the url into that database but then I cannot go back and allow the user to change the content of the sticky. With the second link there does not seem to be support for saving the sticky at all. I'd also like to create a function where adding stickies to a message board (for everyone to see) does so in a randomly placed way that looks natural. Any ideas for either of these problems?
Here is some javascript that should help:
// Called when the edit (A) button is pressed
function edit(event, editButton)
{
// Get existing title and change element to textarea
var stickyTitle = $(editButton).parent().find('p.stickyTitle');
var textareaTitle = $(document.createElement('textarea')).addClass('textareaTitle');
$(textareaTitle).text(stickyTitle.html());
// Get existing description and change element to textarea
var stickyDescription = $(editButton).parent().find('p.stickyDescription');
var textareaDescription = $(document.createElement('textarea')).addClass('textareaDescription');
$(textareaDescription).text(stickyDescription.html());
// Create save button
var saveButton = $(document.createElement('div')).addClass('jSticky-create');
// Add save button, then replace title, then replace description, then remove edit button
$(editButton).before(saveButton);
$(editButton).parent().find('p.stickyTitle').before(textareaTitle).remove();
$(editButton).parent().find('p.stickyDescription').before(textareaDescription).remove();
$(editButton).remove();
// Set description textarea focus and set button actions
textareaTitle.focus();
setActions();
}
// Called when the save (tick) button is pressed
function save(event, saveButton)
{
// Get existing title and change element to paragraph
var textareaTitle = $(saveButton).parent().find('textarea.textareaTitle');
var stickyTitle = $(document.createElement('p')).addClass('stickyTitle');
var newTitleValue = textareaTitle.val();
$(stickyTitle).html(newTitleValue);
// Get existing description and change element to paragraph
var textareaDescription = $(saveButton).parent().find('textarea.textareaDescription');
var stickyDescription = $(document.createElement('p')).addClass('stickyDescription');
var newDescriptionValue = textareaDescription.val();
$(stickyDescription).html(newDescriptionValue);
// Create edit button
var editButton = $(document.createElement('div')).addClass('jSticky-edit');
// Add edit button, then replace title, then replace description, then remove save button
$(saveButton).before(editButton);
$(saveButton).parent().find('textarea.textareaTitle').before(stickyTitle).remove();
$(saveButton).parent().find('textarea.textareaDescription').before(stickyDescription).remove();
$(saveButton).remove();
// Set button actions
setActions();
// Add the object to the ads div
$('#ads').append(object);
// Update your database here
// by calling the saveAd.php
}
function setActions()
{
// call these after changes are made to anything
$('.jSticky-create').unbind('click').click(function(e)
{
save(e, this);
});
$('.jSticky-edit').unbind('click').click(function(e)
{
edit(e, this);
});
$('.jSticky-delete').unbind('click').click(function(e)
{
remove(e, this);
});
}
function remove(event, deleteButton)
{
var stickyMaster = $(deleteButton).parent();
$(stickyMaster).remove();
//then call savead.php with delete parameter
}
Have you looked at any of the code? I took a really quick look at jStickyNote.
Basically, the "sticky note" is a css-styled, text area (that is surround by a div element).
If you want users to be able to save sticky notes/edit past notes, here's what I'd recommend:
Add some button to each note that says "Save" or with a similar meaning.
When a user clicks the "Save" button, you'll need to grab the text from that specific textarea element and then save that text to a database.
With that said, you'll probably need to design some sort of database with a user table and sticknote table. The sticknote table can have a foreign key to the user table.
You'll also want to add some sort of login functionality to your site and then load the correct sticky notes for the authenticated user.
Good Luck!
You can have a look at http://sticky.appspot.com - the code has been released by the google appengine team.
Sorry for not going into specifics, but you could modify the plugin code to load a php script whenever a save button is clicked (or the box is moved, or even on keyup) with $.ajax(), passing it the horizontal and vertical positions and content of the note ( say, $("#note-content").text() ) and have the script plug those things into a database with a MySQL query. Just serialize your data and send it away. This gets more complicated if you want let your users have multiple notes, but start with one. Where is you hangup, exactly? I would be more specific, but I'm not sure what you already know.
I was thinking earlier about adding this feature to an app I'm working on. The thing is, I don't like those plugins. It should be very simple to write your own though. Let me know if you need help with something specifically.