I would like to prevent Server-Side Blazor from firing the OnSubmit event handler (that I can't get rid of for some other reasons) of the EditForm when I hit Enter in the input field. It seems to be an easy task, and I just can't solve it.
I made up the smallest example I could think of:
_Index.razor:
#page "/"
#inject IJSRuntime JSRuntime;
<EditForm Model="Model" OnSubmit="HandleOnSubmit">
<input id="testInput"/>
<button type="submit" value="unneeded submit button"></button>
</EditForm>
#code
{
private CModel Model { get; set; } = new CModel() { ID = "ID", Name = "Name" };
private async Task HandleOnSubmit()
{
await JSRuntime.InvokeAsync<object>("alert", new object[] { "This alert shouldn't be shown!!" });
}
}
the CModel class (although it has no relevance to the question):
public class CModel
{
public string ID { get; set; }
public string Name { get; set; }
}
and the _Host.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PreventSubmitOnForm</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" />
</app>
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
Reload
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.server.js"></script>
<script>
document.getElementById("testInput").addEventListener('keypress', function (event) {
if (event.which === 13) {
event.preventDefault();
alert('Form submit prevented');
}
});
</script>
</body>
</html>
In the _Host.cshtml I register a new keypress eventhandler, and as I debug, on page creation it will be really registered. But it never will be triggered on keypress Enter.
And I already have tried to trick the situation with #onkeypress:preventDefault and #onkeypress:stopPropagation but they don't seem to help (as Steve Sanderson declared in his issue comment) when I want to prevent the default behavior only for my input field and in that specific field only for the event: Enter pressed.
In a normal HTML + JS case it works like a charm: https://jsfiddle.net/wmk608gh/1/
So I ended up by the JS Interop solution and added the script
<script>
document.getElementById("testInput").addEventListener('keypress', function (event) {
if (event.which === 13) {
event.preventDefault();
alert('Form submit prevented');
}
});
</script>
to the _Host.cshtml.
But yet it doesn't seem to work. I presume I'm supposed to register my script to another event (instead of keypress), or maybe there is already a best practice I could follow here.
Any help appreciated.
The problem is that you try to add the EventListener at a time where your <input /> element is not rendered yet.
To make this work you can call your JS function after blazor has rendered your page:
In your _Index.razor #code block add:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("PreventDefault");
}
}
In _Host.cshtml wrap your addEventListener with a function:
<script>
function PreventDefault() {
document.getElementById("testInput").addEventListener('keypress', function (event) {
if (event.which === 13) {
event.preventDefault();
alert('Form submit prevented');
}
});
}
</script>
Related
Fairly basic question here. I've run into a situation where I can't seem to access Javascript functions from within my HTML file, even though I've linked the JS file as a script src. It seems like a pretty simple issue but I can't figure out what the problem is.
I'm trying to add a function called startLogin to an HTML button. I added it as an onclick, but then when I try to click the button, the console says the function is undefined. However the function is clearly defined in the JS file and as far as I can tell the syntax I'm using for the onclick and the script src link is correct.
In addition I've confirmed that the JS file is linked to the HTML file. If I try to manipulate the DOM from the JS file just to do something simple, like set the background to red, that works fine. The problem is when I try to call a function defined in the JS file. Also I've made sure the function I'm trying to call does actually work. If I stick it right in the HTML file inside script tags, it works fine.
I've already tried moving the script tags inside the body at the end of the HTML, as I know that's often the issue, but in this case it didn't work. Can anyone help me identify why I'm unable to access the "startLogin" function from the HTML button?
FYI, this is a javascript project and I'm using Vite.js for bundling. All the other HTML/JS files in my project are playing nicely together, I'm only having an issue with the Login page.
file structure:
|-pages
|-login.html
|-login.js
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-
scale=1.0" />
<title>Document</title>
<!-- LINK JS FILE -->
<!-- MODULE TYPE IS RELATED TO VITE.JS -->
<script type="module" src="./login.js"></script>
</head>
<body>
<!-- email login form -->
<form name="emailLogin" id="emailLogin" style="display: none">
<div class="row" style="width: 600px">
<div class="col">
<div class="form-row" style="padding-bottom: 10px">
<input
type="email"
class="form-control"
id="emailAddress"
placeholder="email associated with your login"
style="width: 576px"
/>
</div>
</div>
<div class="form-row">
<br />
<button type="button" class="btn btn-primary" onclick="startLogin('email')">
Send Email Login
</button>
</div>
</div>
</form>
</body>
</html>
login.js
// start the login process by generating a code sent either SMS or EMAIL
function startLogin(login_type) {
// local variables
var ajaxResult;
var subs;
var tempString;
// get the login values and set up the call
if (login_type == "phone") {
// get the values
use_country_code = $("#country").val();
use_phone = $("#phoneNumber").val();
use_phone = use_phone.replace(/\D/g, "");
// do the validation
if (use_phone.length < 10) {
$("#errorText").html(
"Phone number doesn't have enough digits, please try again."
);
$("#errorModal").modal("show");
return;
}
// build the url
post_url =
"https://us-central1-dev-api-327415.cloudfunctions.net/user-login?cc=" +
use_country_code +
"&phone=" +
use_phone;
} else {
// get the values
use_email = $("#emailAddress").val();
// do the validation
if (!validateEmail(use_email)) {
$("#errorText").html(
"Email address does not appear to be valid, please check the format and try again."
);
$("#errorModal").modal("show");
return;
}
// build the url
post_url =
"https://us-central1-dev-api-327415.cloudfunctions.net/user-login?email=" +
use_email;
}
// send the request to the server and process the results
$.LoadingOverlay("show");
$.ajax({
type: "POST",
url: post_url,
// process the returned result of the Ajax call
success: function (ajaxResult) {
// see if we have a session token and handle the response
session_token = ajaxResult["session_token"];
if (session_token == "None") {
// hide the login and show the text message area if phone, otherwise hide email and show email message
if (login_type == "phone") {
$("#loginMethod").hide();
$("#phoneLogin").hide();
$("#codeLogin").show();
$("#loginMessage").hide();
$("#textMessage").show();
} else {
$("#loginMethod").hide();
$("#emailLogin").hide();
$("#loginMessage").hide();
$("#codeLogin").show();
$("#emailMessage").show();
}
} else {
// hide everything since already logged in and show the right message
$("#phoneLogin").hide();
$("#emailLogin").hide();
$("#loginMethod").hide();
$("#loginMessage").hide();
$("#codeLogin").hide();
$("#continueLoginAlready").show();
}
},
// process after the Ajax call has been fully completed
complete: function () {
$.LoadingOverlay("hide");
},
// handle total failure
error: function (jqXHR, exception) {
console.log(jqXHR);
console.log(exception);
json_error = jqXHR["responseJSON"];
$("#errorText").html(json_error.error_message);
$("#errorModal").modal("show");
},
});
}
Javascript modules work a bit differently. There, variables and functions are not exposed to the global scope.
If you want to use your function from other parts of the code, you have to set it explicitly on the window object:
function startLogin(...) {
...
}
window.startLogin = startLogin;
an other solution is to set the js at end of the html, than you don't need to use the window object (memory lag)
<html lang="en">
<head>...</head>
<body>
<button type="button" id="myButton">Title</button>
</body>
<script>
function myFunction(){
console.log('running myFunction');
}
const button = document.querySelector('#myButton');
button.addEventListener('click', function clickListener(
{
myFunction();
}
</script>
</html>
the browser is simply stupid, it loads the page from top to bottom and if you load your js after the body all your html is present and you can do it this way.
I'm trying to integrate Stripe into my JSF application and am having difficulty navigating away from the "add credit card" page. Everything works, except after the user hits submit, the page does not navigate away.
Below is the addCreditCard.xhtml facelet. Adding the javascript logic as a submit eventListener and triggering the bean update method() using onclick="#{stripeCCBean.update()}" was the only way I could get the javascript to successfully create the token (the createToken method would fail if the javascript was triggered by onclick for some unknown reason) AND get the bean to recognize the hidden fields.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/template.xhtml"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<head>
<title>Facelet Title</title>
<link rel="stylesheet" type="text/css" href="/css/StripeCCTokenize.css"/>
<script src="https://js.stripe.com/v3/" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.2.0.js" type="text/javascript"></script>
<script src="/js/StripeCCTokenize.js" type="text/javascript"></script>
</head>
<h:body>
<h:form id="addCC" pt:action="/secure/addCreditCard.xhtml" pt:method="POST">
<h:inputHidden id="cardholder-name" value="#{userManagerBean.user.fullName}"/>
We loaded your customer details (name, email and customer ID) from the backend database:
<label>
Hello #{userManagerBean.user.firstName} #{userManagerBean.user.lastName}
</label>
<label>
E-Mail - #{userManagerBean.user.email}
</label>
<label>
Stripe Customer ID - #{userManagerBean.stripeUser.id}
</label>
<h:outputText value="Please enter the requested credit card and billing information below"/>
<span>Address</span>
<h:panelGrid columns="2">
<h:outputText value="Address" />
<h:inputText class="field" id="address1" value="#{stripeCCBean.card.address1}" pt:placeholder="Street address"/>
<h:outputText value="Address"/>
<h:inputText class="field" id="address2" value="#{stripeCCBean.card.address2}" pt:placeholder="Street address"/>
<h:outputText value="City" />
<h:inputText class="field" id="city" value="#{stripeCCBean.card.city}" pt:placeholder="city"/>
<h:outputText value="State" />
<h:inputText class="field" id="state" value="#{stripeCCBean.card.state}" pt:placeholder="state"/>
<h:outputText value="zip" />
<h:inputText class="field" id="address-zip" value="#{stripeCCBean.card.zipcode}" pt:placeholder="zipcode"/>
<h:outputText value="cc"/>
</h:panelGrid>
<div id="card-element" class="field"></div>
<h:commandButton value="Add Credit Card" onclick="#{stripeCCBean.update()}" type="submit" id="addButton"/>
</h:form>
</h:body>
Here is the StripeCCTokenize.js:
var stripe; var card;
$(document).ready(function () {
stripe = Stripe('pk_test_key');
var elements = stripe.elements();
card = elements.create('card', {
hidePostalCode: true,
style: {
base: {
iconColor: '#F99A52',
color: '#32315E',
lineHeight: '48px',
fontWeight: 400,
fontFamily: '"Helvetica Neue", "Helvetica", sans-serif',
fontSize: '15px',
'::placeholder': {
color: '#CFD7DF'
}
}
}
});
card.mount('#card-element');
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('addCC');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
function setOutcome(result) {
if (result.token) {
// Use the token to create a charge or a customer
// https://stripe.com/docs/charges
console.log("Token: " + result.token.id);
stripeTokenHandler(result.token);
}
}
card.on('change', function (event) {
setOutcome(event);
});
document.querySelector('form').addEventListener('submit', function (e) {
e.preventDefault();
var extraDetails = {
address_line1: document.getElementById('addCC:address1').value,
address_line2: document.getElementById('addCC:address2').value,
address_city: document.getElementById('addCC:city').value,
address_state: document.getElementById('addCC:state').value,
address_zip: document.getElementById('addCC:address-zip').value,
name: document.getElementById('addCC:cardholder-name').value
};
console.log(extraDetails);
stripe.createToken(card, extraDetails).then(setOutcome);
});
});
Here is the stripeCCBean class:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import lombok.Data;
import lombok.ToString;
#Data
#ToString
#RequestScoped
#ManagedBean(name = "stripeCCBean")
public class StripeCCBean implements Serializable {
StripeCard card;
#ManagedProperty(value = "#{stripeServiceBean}")
private StripeServiceBean stripeServiceBean;
#ManagedProperty(value = "#{userManagerBean}")
private UserManagerBean userManagerBean;
#PostConstruct
public void init() {
System.out.println("StripeCCBean.init()");
card = new StripeCard();
card.setName(userManagerBean.getUser().getFullName());
}
public void update() throws IOException {
String token = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("stripeToken");
if (token == null) {
return;
}
System.out.println("StripeCCBean.update()");
System.out.println("Token: " + token);
System.out.println("Card: " + card);
try {
StripeService.addCard(userManagerBean.getStripeUser().getId(), token);
} catch (AuthenticationException | APIConnectionException | CardException | APIException | InvalidRequestException ex) {
ex.printStackTrace();
}
}
}
I tried adding action="#{stripeCCBean.viewAccount()}" to the <h:commandButton .../> and the corresponding method to the StripeCCBean:
public String viewAccount() {
return "AccountView";
}
However the form simply runs the Javascript, calls the stripeCCBean.update() (everything works) and then stays on that page. The customer information fields do not get cleared, however the credit card element does.
I tried adding FacesContext.getCurrentInstance().getExternalContext().redirect("/secure/AccountView.xhtml");
as well as
FacesContext.getCurrentInstance().getExternalContext().dispatch("/secure/AccountView.xhtml"); to the stripeCCBean.update() method and neither works. In fact, they throw an exception.
Can anyone see what I'm doing wrong? If I'm triggering the JS incorrectly or inefficiently, I'm happy to change that as well.
Another one of those "I have no idea why this worked", but I tried adding FacesContext.getCurrentInstance().getExternalContext().redirect("/secure/AccountView.xhtml"); to the end of the stripeCCBean.update() method and now it works.
Still no idea why I have to have the update() method called via the commandButton's onclick though...
Please remove the preventDefault function which prevents the browse default behaviour and you need not use the onclick event.
If you want to navigate by a f:commandButton / f:commandLink, use the action attribute instead of onclick.
<f:commandButton ... action="#{myBean.actionHandler}".../>
If you don't use any ajax mechanism, the bean can be #RequestScoped, other case #ViewScoped
#Named
#RequestScoped
public class MyBean
{
public String actionHandler()
{
...
return "navigationRuleName";
}
...
}
Where navigationRuleName is registered in the faces-config.xml:
<navigation-rule>
<from-view-id>/path/source.xhtml</from-view-id>
<navigation-case>
<from-outcome>navigationRuleName</from-outcome>
<to-view-id>/path/targetPageName.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
Or it can be a page name:
#Named
#RequestScoped
public class MyBean
{
public String actionHandler()
{
...
return "/path/targetPageName.xhtml?faces-redirect=true";
}
...
}
Or the xhtml extension can be omitted.
The '' entity or the faces-redirect=true parameter necessary if you want the location URL of the browser changing to targetPageName.xhtml after the HTTP POST request-response navigation. Redirection do it by another HTTP GET call after the HTTP POST one.
I have been learning javascript and jquery for short period. I even know that the jquery is a library for the javascript. Now, I made a sample work on both and want to know the difference between the actions. Here is my code :
$(document).ready(function() {
$("#buttonOne").click(function() {
document.getElementById('paragraph').innerHTML = "You are yet to perform";
})
});
function checkButton() {
alert("Hello There");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button type="button" id="buttonOne" onClick="checkButton()">Click Me and Understand</button>
<p id="paragraph"></p>
index.html
<!DOCTYPE html>
<head>
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/style.css">
<title>Wifi Wizard</title>
</head>
<body>
<br>
<br>
Start Wifi <input type="button" value="wifi" name="Wifi" id="wifi"/> <br>
Search Wifi <input type="button" value="search" name="Search" id="search"/> <br>
Scan Wifi <input type="button" value="scan" name="Scan" id="scan"/> <br>
<div id = "dataTable">
</div>
<input type = "password" name = "password" id = "passValue"></input>
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
app.js
$(document).ready(function() {
$("#passValue").hide();
document.addEventListener("deviceready", onDeviceReady, false);
});
function onDeviceReady() {
$('#wifi').click( function()
{
try {
WifiWizard.isWifiEnabled(win, fail);
}
catch(err) {
alert("Plugin Error - " + err.message);
}
});
function win(e) {
if(e) {
alert("Wifi enabled already");
}
else {
WifiWizard.setWifiEnabled(true, winEnable, failEnable);
}
}
function fail(e) {
alert("Error checking Wifi status");
}
function winEnable(e) {
alert("Wifi enabled successfully");
}
function failEnable(e) {
alert("Error enabling Wifi ");
}
$('#search').click( function()
{
try {
WifiWizard.listNetworks(listHandler, fail);
}
catch(err) {
alert("Plugin Error - " + err.message);
}
});
function listHandler(a){
alert(a);
}
$('#scan').click( function()
{
try {
WifiWizard.getScanResults({numLevels: 1},listHandler1, fail);
}
catch(err) {
alert("Plugin Error - " + err.message);
}
});
function listHandler1(a) {
alert(JSON.stringify(a));
var network_array = [];
var content = "<table>"
for (i = 0; i < a.length; i++) {
content += '<tr><td><button onclick="clickWifi(\'' + a[i].SSID + '\');">' + network_array.push(a[i].SSID) + '</button></td></tr>';
}
content += "</table>"
alert(network_array);
$('#dataTable').append(content);
}
function clickWifi(ssid) {
alert("Hello");
var networkSSID = ssid;
$("#passValue").show();
var passWord = document.getElementById("passValue");
var config = WifiWizard.formatWPAConfig(networkSSID, passWord);
}
WifiWizard.addNetwork(config, function() {
WifiWizard.connectNetwork(networkSSID, connectSuccess, connectFailed);
});
}
For above scenario, I have a made a button to call its click function dynamically, so please help as I have no idea whether the button declared is correct or wrong.
Here I have made a click function using id in jquery and onclick function using javascript. But the alert first pops up and then the jquery does it's work. I would like to know why doesn't jquery go first. Please give a suggestion.
https://jsfiddle.net/m3prjL8q/
here is the answer to the question in the comments. As far as the original post goes, it was answered in the comments, there is no need to repeat that.
When you use $(document).ready(function(){}) what you are doing is actually creating an event listener that will 'trigger' once the document is ready and giving it a handler function. This is yourJQuery function in the example. If you declare a function within the handler, this function is not accessible to the native javascript outside of the handler.
function yourJQuery(){
function innerDeclare(){
alert("I cannot be accessed outside of yourJQuery function");
}
}
innerDeclare();
IF i understood your Question correctly you want to know why html onclick method runs before jQuery click method.
That is simply because sequence you are adding click event on element.
HTML onclick method does not wait for DOM to render and attach event directly to the element.
But your jQuery method waiting for for Dom to be ready then it goes and attach the click event to element.
Hence events are getting executed in sequence.
For better performance, use the native JavaScript. For faster development, use jQuery. Check the comparison in performance at jQuery vs Native Element Performance.
I am completely new to Phonegap and Javascript. I am trying to save the username value and password value from the login form to sqlite database.
This is my login.html file:-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Login</title>
<link href="css/style.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="js/iscroll.js"></script>
<script type="text/javascript" src="js/login.js"></script>
</head>
<body>
<div class="wrapper">
<form action="submit" id="login" name="login_form">
<input type="text" id="uName" name = "UserName" placeholder="Username" value="Admin"/>
<br/>
<input type="password" id="password" name = "Password" placeholder="Password" value="super#1234"/>
<br/>
<button type="submit" id="submit" value="Submit">Login</button>
</form>
<script type="text/javascript">
$(document).ready(function() {
$("#submit").click(function() {
if($("#uName").val()==""){
alert("Please fill username field.");
//$("#uName").focus();
}
else if($("#password").val()==""){
alert("Please fill password field.");
//$("#password").focus();
}
else {
onDeviceReady();
}
});
});
</script>
</div>
</body>
</html>
and this is my login.js file:-
var db;
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
db = window.openDatabase("UserDB", "1.0", "Login", 10000);
db.transaction(populateDB, transaction_err, populateDB_success);
}
function populateDB(tx) {
var userName = document.getElementById("uName").value;
var password = document.getElementById("password").value;
tx.executeSql('CREATE TABLE IF NOT EXISTS users (ID INT, USERNAME VARCHAR UNIQUE, PASSWORD VARCHAR)');
tx.executeSql('INSERT INTO users (ID,USERNAME,PASSWORD) VALUES ("'+1+'","'+userName+'","'+password+'")');
alert("" + userName + " " + password);
}
function transaction_err(tx, error) {
alert("Database Error: " + error);
}
function populateDB_success(tx) {
alert("Data successfully entered.");
window.open("file:///assets/www/view_login.html");
}
My problem is when I am running this code in my android device it gives me application error : There is a network error and
error log is:-
04-30 10:16:35.080 31868-31868/com.itpp.trt D/CordovaWebViewImpl onPageDidNavigate(file:///android_asset/www/submit?UserName=Admin&Password=super%401234)
04-30 10:16:35.080 31868-31934/com.itpp.trt E/AndroidProtocolHandler﹕ Unable to open asset URL: file:///android_asset/www/submit?UserName=Admin&Password=super%401234
04-30 10:16:35.090 31868-31868/com.itpp.trt D/SystemWebViewClient﹕ CordovaWebViewClient.onReceivedError: Error code=-1 Description=There was a network error. URL=file:///android_asset/www/submit?UserName=Admin&Password=super%401234
I cant find where is the problem please help me.
Thanks and sorry for the long question. :)
The form is trying to submit the provided data to the url: 'file:///android_asset/www/submit'.
The url is submitted via the action attribute inside the <form> tag:
<form action="submit" id="login" name="login_form">
To prevent this from happening just take the action attribute out of the tag.
Since you are new to Phonegap/Cordova you probably don't know that you shouldn't wait for the document.ready event but instead for the deviceready. Now when you change this, your form submit will probably no longer work. This is because the deviceready event fires once when the App is launched and ready to use. It doesn't wait for a button click or a function declared inside the deviceready function.
How can we get this to work again? That's simple, just call a function that when the submit button is clicked. You will need to do something like this:
<form id="login" name="login_form" onsubmit="mySubmitFunction();">
The called function should look something like this:
function mySubmitFunction(){
$("login").unbind("submit"); //this removes the submit event-handler from the form
if($("#uName").val()==""){
alert("Please fill username field.");
}
else if($("#password").val()==""){
alert("Please fill password field.");
}
else {
//insert into your database
db.transaction(populateDB, transaction_err, populateDB_success);
}
}
Inside the onDeviceReady function just open the database:
function onDeviceReady() {
db = window.openDatabase("UserDB", "1.0", "Login", 10000);
}
The code provided below doesn't show all the content of that page.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Document</title>
<script type="text/javascript">
var rootdomain="http://"+window.location.hostname
alert(rootdomain);
function ajaxinclude(url) {
var url=rootdomain+url;
var page_request = false
if (window.XMLHttpRequest) // if Mozilla, Safari etc
page_request = new XMLHttpRequest()
else if (window.ActiveXObject){ // if IE
try {
page_request = new ActiveXObject("Msxml2.XMLHTTP")
}
catch (e){
try{
page_request = new ActiveXObject("Microsoft.XMLHTTP")
}
catch (e){}
}
}
else
return false
page_request.open('GET', url, false) //get page synchronously
page_request.send(null)
writecontent(page_request)
}
function writecontent(page_request){
if (window.location.href.indexOf("http")==-1 ||
page_request.status==200)
document.getElementById("write").innerHTML=page_request.responseText;
}
</script>
</head>
<body>
<div id="write">
</div>
<input type="button" value="Submit !" onclick="ajaxinclude('/songcake/index.php');"/>
</body>
</html>
Please Help
Thanks.
You need to add a closure that reacts upon the completion of the document loading process.
page_request.onreadystatechange = function() {
if(page_request.readystate == 4) {
// data handling here
}
}
As pointed out though, using jQuery will make things a lot easier.
Edit: To clarify, your AJAX call does check for the connection status (request.status), but not for the loading status (request.readystate). Your document probably did not load completely.
Here's a reference for the W3.org XMLHTTPRequest API: http://www.w3.org/TR/XMLHttpRequest/ .
Edit2: Btw, an <iframe> element would solve your problem with a lot less code.
Edit 3: Code
function ajaxinclude(url) {
//...
page_request.open('GET', url, false) //get page synchronously
//<> add onreadystatechange handler
page_request.onreadystatechange = function() {
if(page_request.readystate === 4) {
if(page_request.state === 200) {
//call function on success
writecontent(page_request.responseXML)
}
}
}
page_request.send(null)
}
Some additions:
if you put your ajax call into the <HEAD> you need to either create the dom elements you want to append data to as they are not available when the runtime runs through (which might lead to a dom error); or you need to add an on dom load event handler.
Synchronous calls are not properly implemented in some browsers and this might lead to errors too.
Why you should not use jQuery? You can do this simple as below..
$("#write").load("/songcake/index.php");
[EDITED]
Below you can see the completed code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Document</title>
<script type="text/javascript" src='scripts/jquery.js'></script>
</head>
<body>
<div id="write">
</div>
<input type="button" value="Submit !"
onclick="$('#write').load('/songcake/index.php');"/>
</body>
</html>
You can download jQuery from here : http://jquery.com/
The source for my answer you can find here : http://api.jquery.com/load/
try to use FireBug
FireBug show you state of your request.
If it 200 and you see that in reqest answer (in firebug) broken data then
you should check your index.php script