getting exception "error processing sql: object SQLTransaction" - android

I am getting the following exception:
error processing SQL: object SQLTransaction
in phone gap Android app every time, when I query an sqlite database.
Thanks,here is the complete source code
<html>
<head>
<script type="text/javascript">
function validate()
{
var p=document.getElementById('searchid');
var a=new Array();
a[0]="PatientID";
a[1]="FirstName";
a[2]="DateOfBirth";
for(var i=0;i<a.length;i++)
{
if(a[i]==p.getAttribute('placeholder'))
{
if(i==a.length-1)
{
p.placeholder=a[0];
break;
}
else
{
p.placeholder=a[i+1];
break;
}
}
}
}
function validate1()
{
var db = window.openDatabase("Databases", "1.0", "PhoneGap Demo", 200000);
db.transaction(queryDB, errorCB);
}
function queryDB(tx)
{
var placeholdervalue=document.getElementById('searchid').getAttribute('placeholder');
var searchname=document.getElementById('searchid').value;
alert(placeholdervalue+","+searchname);
tx.executeSql("select * from Patient", [], querySuccess, errorCB);
}
function querySuccess(tx, results)
{
alert('inside query success');
var len = results.rows.length;
if(len>0)
{
document.getElementById('tt').innerHTML="search found";
}
}
function errorCB(err) {
alert("Error processing SQL: "+err);
}
</script>
</head>
<body>
<h3>Search</h3>
<input type="button" value="&gt" onclick="validate()">
<input type="text" name="search" id="searchid" placeholder="PatientID"/>
<input type="button" value="search" onclick="validate1()">
<span id="tt"></span>
</body>
</html>
the function querySuccess(tx,results) is not called(before that i am getting the exception).pls help

Related

How to access and update Sqlite db file stored locally[asset folder] in project file using cordova

I have a sqlite db file stored in assets folder of my cordova project ,which i want to access inside my application and also want to update the db.
So far i had a look on i found there cordova sqlite plug-in which can create a sqlite db and update it,but not sure how to update a existing db file from asset folder in cordova
Here is my below code:
<!DOCTYPE html>
<html>
<head>
<title>Storage Example</title>
<script type="text/javascript" charset="utf-8" src="cordova-2.0.0.js"></script>
<script type="text/javascript" charset="utf-8" src="index.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/conf-room1.min.css" rel="stylesheet" />
<link href="css/jquery.mobile.icons.min.css" rel="stylesheet" />
<link href="css/jquery.mobile.structure-1.4.4.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="css/custom_color.css" rel="stylesheet" />
<script src="js/jquery-2.1.3.min.js"></script>
<script src="js/jquery.mobile-1.4.4.min.js"></script>
<script src="cordova.js"></script>
<script src="js/jquery-2.1.3.min.js"></script>
<script src="js/jquery.mobile-1.4.4.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>
document.addEventListener("deviceready", onDeviceReady, false);
var db = "";
function populateDB(tx) {
tx.executeSql('DROP TABLE IF EXISTS SoccerPlayer');
tx.executeSql('CREATE TABLE IF NOT EXISTS SoccerPlayer (Name TEXT NOT NULL, Club TEXT NOT NULL)');
tx.executeSql('INSERT INTO SoccerPlayer(Name,Club) VALUES ("Test1", "Team1")');
tx.executeSql('INSERT INTO SoccerPlayer(Name,Club) VALUES ("Test2", "Team2")');
}
function queryDB(tx) {
tx.executeSql('SELECT * FROM SoccerPlayer', [], querySuccess, errorCB);
}
function querySuccess(tx,result){
var playerlist = document.getElementById("SoccerPlayerList");
var players = "";
alert("The show is on");
var len = result.rows.length;
for (var i=0; i<len; i++){
alert(result.rows.item(i).Name + result.rows.item(i).Club);
players = players + '<li><p class="record">'+result.rows.item(i).Name+'</p><p class="small">Club '+result.rows.item(i).Club+'</p></li>';
}
playerlist.innerHTML = players;
$("#SoccerPlayerList").listview("refresh");
}
function errorCB(err) {
alert("Error processing SQL: "+err.code);
}
function successCB() {
db.transaction(queryDB, errorCB);
}
function onDeviceReady() {
<!--db = window.openDatabase("SimpleTestOne", "1.0", "PhoneGap Demo", 200000);-->
db = window.openDatabase({name: "SimpleTestOne.db", createFromLocation: 1});
db.transaction(populateDB, errorCB, successCB);
}
</script>
</head>
<body>
<div data-role="page">
<div data-role="header" data-position="fixed" data-theme="b">
<h1>Soccer Player</h1>
</div>
<div data-role="content">
<ul id="SoccerPlayerList">
</ul>
</div>
</div>
<!--end of Soccer Player Page--->
</body>
</html>
Note: I have SimpleTestOne.db in my assets folder
You can try with below Snippet.
This snippet contains all the part from Data base creation to Insert , Edit , Delete , Update and Display data of your database.
Note: Change your Database name and Table name and Database fields here whatever you want to keep.
<script type="text/javascript" charset="utf-8">
// Wait for Cordova to load
//
document.addEventListener("deviceready", onDeviceReady, false);
var currentRow;
// Populate the database
//
function populateDB(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id INTEGER PRIMARY KEY AUTOINCREMENT, name,number)');
}
// Query the database
//
function queryDB(tx) {
tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}
function searchQueryDB(tx) {
tx.executeSql("SELECT * FROM DEMO where name like ('%"+ document.getElementById("txtName").value + "%')",
[], querySuccess, errorCB);
}
// Query the success callback
//
function querySuccess(tx, results) {
var tblText='<table id="t01"><tr><th>ID</th> <th>Name</th> <th>Number</th></tr>';
var len = results.rows.length;
for (var i = 0; i < len; i++) {
var tmpArgs=results.rows.item(i).id + ",'" + results.rows.item(i).name
+ "','" + results.rows.item(i).number+"'";
tblText +='<tr onclick="goPopup('+ tmpArgs + ');"><td>' + results.rows.item(i).id +'</td><td>'
+ results.rows.item(i).name +'</td><td>' + results.rows.item(i).number +'</td></tr>';
}
tblText +="</table>";
document.getElementById("tblDiv").innerHTML =tblText;
}
//Delete query
function deleteRow(tx) {
tx.executeSql('DELETE FROM DEMO WHERE id = ' + currentRow, [], queryDB, errorCB);
}
// Transaction error callback
//
function errorCB(err) {
alert("Error processing SQL: "+err.code);
}
// Transaction success callback
//
function successCB() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(queryDB, errorCB);
}
// Cordova is ready
//
function onDeviceReady() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(populateDB, errorCB, successCB);
}
//Insert query
//
function insertDB(tx) {
tx.executeSql('INSERT INTO DEMO (name,number) VALUES ("' +document.getElementById("txtName").value
+'","'+document.getElementById("txtNumber").value+'")');
}
function goInsert() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(insertDB, errorCB, successCB);
}
function goSearch() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(searchQueryDB, errorCB);
}
function goDelete() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(deleteRow, errorCB);
document.getElementById('qrpopup').style.display='none';
}
//Show the popup after tapping a row in table
//
function goPopup(row,rowname,rownum) {
currentRow=row;
document.getElementById("qrpopup").style.display="block";
document.getElementById("editNameBox").value = rowname;
document.getElementById("editNumberBox").value = rownum;
}
function editRow(tx) {
tx.executeSql('UPDATE DEMO SET name ="'+document.getElementById("editNameBox").value+
'", number= "'+document.getElementById("editNumberBox").value+ '" WHERE id = '
+ currentRow, [], queryDB, errorCB);
}
function goEdit() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(editRow, errorCB);
document.getElementById('qrpopup').style.display='none';
}
</script>
I am using this code for one of my app and it's working fine.
Edit 1 :
NOTE : Please place your db file in wwww directory like for e.g projectpath/www/dbname.db.
For accessing db file from asset folder.
window.openDatabase({name: "dbname.db", createFromLocation: 1});
Edit 2:
Just install below plugin in your app.
cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin.git
And Try this.
var db = window.sqlitePlugin.openDatabase({name: "my.db", createFromLocation: 1});

Return More Than One Data with Ionic, SQLite

i am trying to retrive some data with sqlite from ionic framework. But i am newbie, so i need your help.
I want to retrieve data from db with sqlite as a list, all data.
If // console.log line command is open, i only get one data, not the others.
If app.js is like this, i get this error.
TypeError: Cannot read property 'push' of undefined
at app.js:65
at processQueue (ionic.bundle.js:20962)
at ionic.bundle.js:20978
at Scope.$get.Scope.$eval (ionic.bundle.js:22178)
at Scope.$get.Scope.$digest (ionic.bundle.js:21994)
at Scope.scopePrototype.$digest (hint.js:1468)
at ionic.bundle.js:22216
at completeOutstandingRequest (ionic.bundle.js:12714)
at ionic.bundle.js:13094
app.js
var db = null;
var example = angular.module('starter', ['ionic', 'ngCordova'])
.run(function($ionicPlatform, $cordovaSQLite) {
$ionicPlatform.ready(function() {
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
if (window.cordova) {
db = $cordovaSQLite.openDB({ name: "my.db" }); //device
}else{
db = window.openDatabase("my.db", '1', 'my', 1024 * 1024 * 100); // browser
}
$cordovaSQLite.execute(db, "CREATE TABLE IF NOT EXISTS people (id integer primary key, firstname text, lastname text)");
});
});
example.controller("ExampleController", function($scope, $cordovaSQLite) {
$scope.insert = function(firstname, lastname) {
var query = "INSERT INTO people (firstname, lastname) VALUES (?,?)";
$cordovaSQLite.execute(db, query, [firstname, lastname]).then(function(result) {
console.log("INSERT ID -> " + result.insertId);
}, function (error) {
console.error(error);
});
}
$scope.select = function(lastname) {
var query = "SELECT firstname, lastname FROM people WHERE lastname = ?";
$cordovaSQLite.execute(db, query, [lastname]).then(function(result) {
if(result.rows.length > 0) {
console.log("SELECTED -> " + result.rows.item(0).firstname + " " + result.rows.item(0).lastname);
} else {
console.log("No results found");
}
}, function (error) {
console.error(error);
});
}
$scope.selectAll = function() {
var query = "SELECT firstname, lastname FROM people";
var outputs = [];
$cordovaSQLite.execute(db, query, []).then(function(result) {
if(result.rows.length > 0) {
for(var i = 0; i < result.rows.length; i++) {
//console.log("SELECTED -> " + result.rows.item(i).firstname + " " + result.rows.item(i).lastname);
/* $scope.outputs = [
{"firstname": result.rows.item(i).firstname}
]; */
$scope.outputs.push({
"firstname" : result.rows.item(i).firstname,
});
}
} else {
console.log("No results found");
}
}, function (error) {
console.error(error);
});
}
});
example.controller("PeopleCtrl", function($scope) {
$scope.people = [
{firstName: 'John', lastName: 'Doe', address: {city: 'Chandler', state: 'AZ', zip: 85248}},
{firstName: 'Jane', lastName: 'Doe', address: {city: 'Chandler', state: 'AZ', zip: 85248}},
{firstName: 'Johnny', lastName: 'Doe', address: {city: 'Phoenix', state: 'AZ', zip: 85003}}
];
});
and index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="js/ng-cordova.min.js"></script>
<script src="cordova.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app="starter">
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Ionic Blank Starter</h1>
</ion-header-bar>
<ion-content>
<div ng-controller="ExampleController">
<button class="button" ng-click="insert('Arzu','Acar')">Insert</button>
<button class="button" ng-click="selectAll()">Select</button>
<ul>
<li ng-repeat="output in outputs">
<span class="bold">{{output.firstname}}</span>
</li>
</ul>
</div>
<div ng-controller="PeopleCtrl">
<div id="peopleContainer">
People:<br /><br />
<ul>
<li ng-repeat="person in people">
<span class="bold">{{person.firstName}} {{person.lastName}}</span>
<br />
{{person.address.city}}, {{person.address.state}} {{person.address.zip}}
</li>
</ul>
</div>
</div>
</ion-content>
</ion-pane>
</body>
</html>
Thank you.
In ExampleController:selectAll, you have the following declaration:
var outputs = [];
Then push to an array that doesn't exist on $scope:
$scope.outputs.push({
"firstname" : result.rows.item(i).firstname,
});
I think you meant to initialize the $scope.outputs array each time selectAll is called:
$scope.outputs = [];
You must declare in the controller's main scope:
$scope.outputs = [];
Your "selectAll" function should be like this:
$scope.selectAll = function() {
var query = "SELECT firstname, lastname FROM people";
$scope.outputs.length = 0;
$cordovaSQLite.execute(db, query).then(function(result) {
if(result.rows.length > 0) {
for(var i = 0; i < result.rows.length; i++) {
$scope.outputs.push({
firstName : result.rows.item(i).firstname
});
}
} else {
console.log("No results found");
}
}, function (error) {
console.error(error);
});
}
Hope this works! :)

values not inserting in sqlite database using cordova

I have created a form for inserting data from textbox into the database and when I run it in the browser I can see the table is created and values are inserted.
I tried implementing the same using cordova and table getting created and values are not getting inserted..
Here is my coding..
document.addEventListener("deviceready", function()
{
var db=window.sqlitePlugin.openDatabase({name : "mydb"});
var createStatement = "CREATE TABLE IF NOT EXISTS login(id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT,password TEXT,firstname TEXT, lastname TEXT,hobby TEXT,email TEXT)";
var insertStatement = " INSERT INTO login(username,password,firstname,lastname,hobby,email) VALUES (?,?,?,?,?,? ) ";
function initDatabase() // Function Call When Page is ready.
{
try {
if (!window.openDatabase) // Check browser is supported SQLite or not.
{
// alert('Databases are not supported in this browser.');
}
else {
createTable(); // If supported then call Function for create table in SQLite
}
}
catch (e) {
if (e == 2) {
// Version number mismatch.
console.log("Invalid database version.");
} else {
console.log("Unknown error " + e + ".");
}
return;
}
}
function createTable() // Function Call When Page is ready.
{
var res=db.transaction(function (tx) { tx.executeSql(createStatement, [], onError); });
alert("Successfully created the table");
}
function onError(tx, error) // Function for Hendeling Error...
{
// alert(error.message);
}
});
document.addEventListener("deviceready", function()
{
var db=window.sqlitePlugin.openDatabase({name : "mydb"});
function insertRecord()
{
var usernameold = $('input:text[id=username]').val();
var passwordold = $('input:password[id=pass]').val();
var firstnameold = $('input:text[id=firstname]').val();
var lastnameold = $('input:text[id=lastname]').val();
var hobbyold = $('input:text[id=hobby]').val();
var emailold = $('input:text[id=email]').val();
db.transaction(function (tx) { tx.executeSql(insertStatement, [usernameold,passwordold,firstnameold, lastnameold,hobbyold,emailold]/*,loadAndReset, onError*/) });
alert("Successfully created the table");
}
});
$(document).ready(function()
{
initDatabase();
$("#submit").click(insertRecord);
});
Tried saving and importing the database from fileexprorer->data->data->projectpackage->databases->mydb.db
then firefox->sqlitemanager->connectdb
I can see the table is getting created and the values are not inserting
Plz help...
can insert the values:
db.transaction(function (tx)
{
tx.executeSql('INSERT INTO login (username,pass,firstname,lastname,hobby,email)VALUES("'+un+'","'+ps+'","'+fs+'","'+ls+'","'+hb+'","'+ed+'")');
});
});
}
Where
var un= $("#username").val();
var ps= $("#pass").val();
var fs = $('input:text[id=firstname]').val();
var ls = $('input:text[id=lastname]').val();
var hb = $('input:text[id=hobby]').val();
var ed = $('input:text[id=email]').val();
http://docs.phonegap.com/en/1.2.0/phonegap_storage_storage.md.html check the above link for db storage queries.
Try with the below code . Hope this will help you.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
document.addEventListener("deviceready", onDeviceReady, false);
var nameval,pwdval,fnameval,lnameval,hobbyval,emailval;
function onDeviceReady() {
var db = window.openDatabase("Logindetails_DB", "1.0", "Logindetails_DB", 100000);
db.transaction(populateDB, errorCB, successCB);
}
function validationCheck(){
nameval=document.getElementById('u_name').value;
pwdval=document.getElementById('u_pwd').value;
fnameval=document.getElementById('u_firstname').value;
lnameval=document.getElementById('u_lastname').value;
hobbyval=document.getElementById('u_hobby').value;
emailval=document.getElementById('u_email').value;
if(document.getElementById('u_name').value==""){
alert('Enter Your Name');
}
if(document.getElementById('u_pwd').value==""){
alert('Enter Your Password');
}
if(document.getElementById('u_firstname').value==""){
alert('Enter Your FirstName');
}
if(document.getElementById('u_lastname').value==""){
alert('Enter Your LastName');
}
if(document.getElementById('u_hobby').value==""){
alert('Enter Your HobbyName');
}
if(document.getElementById('u_email').value==""){
alert('Enter Your Email');
}
if(nameval!='' && pwdval!='' && fnameval!='' && lnameval!='' && hobbyval!='' && emailval!=''){
alert('Name'+nameval+'Pwd'+pwdval);
Insertvalue();
}
}
function Insertvalue(){
var db = window.openDatabase("Logindetails_DB", "1.0", "Logindetails_DB", 100000);
db.transaction(getregistdata, transaction_error);
}
function getregistdata(tx){
tx.executeSql('INSERT INTO login (username, password, firstname,lastname,hobby,email) VALUES ("'+nameval+'", "'+pwdval+'","'+fnameval+'","'+lnameval+'","'+hobbyval+'","'+emailval+'")');
alert('Record Inserted Successfully');
}
function transaction_error(tx, error) {
alert("Database Error: " + error);
}
// Populate the database
function populateDB(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS login(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, password TEXT NOT NULL, firstname TEXT NOT NULL,lastname TEXT NOT NULL,hobby TEXT NOT NULL,email TEXT NOT NULL)');
}
// Transaction error callback
//
function errorCB(tx, err) {
alert("Error processing SQL: "+err);
}
// Transaction success callback
//
function successCB() {
alert("success!");
}
</script>
</head>
<body>
<h1>Hello PhoneGap</h1>
<form name="form1" id="form1" method="post">
User Name: <br><input type="text" name="u_name" id="u_name"><br><br>
Password:<br><input type="text" name="u_pwd" id="u_pwd"><br><br>
First Name<br> <input type="text" name="u_firstname" id="u_firstname"><br><br>
Last Name<br> <input type="text" name="u_lastname" id="u_lastname"><br><br>
Hobby<br> <input type="text" name="u_hobby" id="u_hobby"><br><br>
Email<br> <input type="text" name="u_email" id="u_email"><br><br>
<div style="text-align:center;">
<input type="button" name="submitbtn" id="submitbtn" value="Submit" onclick="validationCheck()">
</div>
</form>
</body>
</html>

Cannot submit the data to another page using jquery mobile

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css">
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
</head>
<body>
<div data-role="page" id="home">
<div data-role="header">
<h1>jQuery Mobile loadPage() Method</h1>
</div>
<div data-role="content" id="content_container">
<form id="my_form">
<input type="text" id="name" />
<input type="text" id="surname"/>
<input type="button" id="yes">
</form>
</div>
</div>
<script>
var storePageLoaded = false;
$(document).on('click', '#yes', function() {
$.ajax({
type: "POST",
url: "searchresult.php",
data: $("form#my_form").serialize(),
success: function(data){
$.each(data, function(i, elem) {
nic_list.push({label: elem['p_nic']});
});
}
}).done(function (data) {
$.mobile.changePage('next-page.html',{transition:"slide"});
}).fail(function (jqXHR, textStatus) {
alert(error);
});
return false;
});
</script>
I created this page to send some form data to php file and print the data in a another page.But when i try this i get following error .I have change the code little bit to retrieve the data .It works fine but i need to populate the data next-page.html
10-14 11:10:05.108: E/Web Console(9066): Uncaught TypeError: Object #<Object> has no method 'jqmData' at http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js:2
$(document).on('click', '#yes', function() {
$.ajax({
type: "POST",
url: "searchresult.php",
data: $("form#my_form").serialize(),
success: function(response){
alert(success);
}
}).done(function (data) {
$.mobile.changePage('next-page.html',{transition:"slide"});
}).fail(function (jqXHR, textStatus) {
alert(error);
});
return false;
});

Phonegap Can't Redirecting to a page

So I have this form where upon submission I do a SQL query and redirect it to another page. But when I try to test this on the android tablet it doesnt redirect, nor does it error meaning the SQL call is valid and works...can someone please help me out
<div class="wrapper">
<div class="oneSection">
<form method="post" action="" id="barcodeForm">
Barcode: <br/>
<input name="barcode" id="barcode" type="text" class="sub"/><br/>
<input type="submit" class="open" id="before" value="SUBMIT" onclick="check()" />
</form>
</div>
</div>
<script type="text/javascript">
function check() {
var barcode = $('#barcode').val();
if(barcode.length <= 0) {
$('#barcode').css('border', '2px solid red');
e.preventDefault();
return;
} else {
alert(barcode.length);
var barcode = $('#barcode').val();
checkBarcode(false, barcode);
}
}
function checkBarcode(doAuto, id) {
var successCall;
if (doAuto) {
successCall = function (tx, result) {
var item = result.rows.item(0);
$('[name="client"]').val(item['cname']);
$('[name="address"]').val(item['address']);
$('[name="sitename"]').val(item['sname']);
$('[name="model"]').val(item['model']);
$('[name="lasttested"]').val(item['ltest']);
$('[name="nounits"]').val(item['units']);
$('[name="comments"]').val(item['comments']);
}
} else {
test.innerHTML += 'at the start<br/>';
successCall = function () {
var URL = 'test.html?id=' + id;
window.location.href = URL;
}
}
var queryDB = function queryDB(tx) {
tx.executeSql(getBarcode, [id], successCall, onError);
}
db.transaction(queryDB, onError);
}
</script>
What happens at the moment is that it submit's the input value and resets the form without forwarding the page or anything...

Categories

Resources