We have a Web Application written with ASP.NetCore and Razor pages.
We would like to use it as a Teams App within a Tab.
However, I notice that submit (which triggers the OnPost event) fails to work under Teams even though it all works fine as a standard Web Application.
I suspect that this may be to do with the fact the App is running under a Teams IFrame and submission is not possible.
Can anyone offer me any suggestions or code samples to what I need to modify to a submit like the one below to trigger the OnPost when running under Teams. I attach one simple form (a login form) with code behind.
Thanks.
Login.cshtml
#page
#model AreoWeb.Pages.Registration.Login
<br />
<h2 class="text-info">Login</h2>
<br />
<div class="border container" style="padding:30px">
<form id="frm" method="post" >
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<div class="form-group row">
<div class="col-2">
<label>Email Address</label>
</div>
<div class="col-5">
<input asp-for="LoginDetails.EmailAddress" class="form-control" />
</div>
<span asp-validation-for="LoginDetails.EmailAddress" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-2">
<label>Password</label>
</div>
<div class="col-5">
<input asp-for="LoginDetails.Password" class="form-control" />
</div>
<span asp-validation-for="LoginDetails.Password" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-2 offset-2">
<input type="submit" value="Login" class=" btn btn-primary form-control" asp-page="Login" />
</div>
<div class="col-1">
</div>
<div class="col-2">
<a asp-page="/Index" class="btn btn-success form-control">Cancel</a>
</div>
</div>
</form>
</div>
</script>
#section Scripts
{
<partial name="_ValidationScriptsPartial"/>
}
Login.cshtml.cs
using System.Threading.Tasks;
using areo;
using AreoErr;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using AreoWeb.Model;
using AreoWeb.Pages.Shared;
namespace AreoWeb.Pages.Registration
{
public class Login : PageModel
{
[BindProperty]
public LoginDetails LoginDetails { get; set; }
public async Task <IActionResult> OnPost()
{
if(ModelState.IsValid)
{
ErrConsts.ErrorCode ret = await DoLogin(LoginDetails.EmailAddress,LoginDetails.Password);
if (ret==ErrConsts.ErrorCode.Success)
return RedirectToPage("/Messages/Index");
else
return RedirectToPage("Error");
}
else
{
return Page();
}
}
public async Task<ErrConsts.ErrorCode> DoLogin(string emailAddress,string password)
{
//
}
When run directly from a browser the app logs the following under the browser debugger. Page load and successful submit :
DOM7011: The code on this page disabled back and forward caching. For more information, see: http://go.microsoft.com/fwlink/?LinkID=291337
repost.htm
HTML1300: Navigation occurred.
Login
DOM7011: The code on this page disabled back and forward caching. For more information, see: http://go.microsoft.com/fwlink/?LinkID=291337
repost.htm
When run under Microsoft Team, the same page load and submit generates the following in the browser debugger (the last entry appears after submit is pressed. First two and last entries are Errors):
2020-07-23T07:08:37.621Z ChannelService: Empty threadId 0-angular-jquery.min-eee9041.js:114:37
2020-07-23T07:08:38.574Z ChannelService: Empty threadId 0-angular-jquery.min-eee9041.js:114:37
Feature Policy: Skipping unsupported feature name “midi”. 0-angular-jquery.min-eee9041.js:1:49340
Feature Policy: Skipping unsupported feature name “encrypted-media”. 0-angular-jquery.min-eee9041.js:1:49340
Feature Policy: Skipping unsupported feature name “midi”. 0-angular-jquery.min-eee9041.js:1:49340
Feature Policy: Skipping unsupported feature name “encrypted-media”. 0-angular-jquery.min-eee9041.js:1:49340
Content Security Policy: Ignoring “'unsafe-inline'” within script-src or style-src: nonce-source or hash-source specified 2
Feature Policy: Skipping unsupported feature name “midi”. 0-angular-jquery.min-eee9041.js:27:416
Feature Policy: Skipping unsupported feature name “encrypted-media”. 0-angular-jquery.min-eee9041.js:27:416
Feature Policy: Skipping unsupported feature name “midi”. 0-angular-jquery.min-eee9041.js:1:48779
Feature Policy: Skipping unsupported feature name “encrypted-media”. 0-angular-jquery.min-eee9041.js:1:48779
Content Security Policy: Ignoring “'unsafe-inline'” within script-src or style-src: nonce-source or hash-source specified 2
Feature Policy: Skipping unsupported feature name “midi”. 3.2-app.min-0f0e437.js:5:662533
Feature Policy: Skipping unsupported feature name “encrypted-media”. 3.2-app.min-0f0e437.js:5:662533
Content Security Policy: Ignoring “'unsafe-inline'” within script-src or style-src: nonce-source or hash-source specified
The character encoding of the plain text document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the file needs to be declared in the transfer protocol or file needs to use a byte order mark as an encoding signature. Login
?
The HEAD section generated by the App does define the charset, and is as follows :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title> - Areo Web</title>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="/css/site.css" />
</head>
<body>
Related
I am currently working on an ePubv3 book and have run into a problem. I'm using Sigil as the IDE. My goal is to allow the reader to type in the page number that they would like to jump to. Here is my code:
<head>
<title>testing</title>
<script>
function goToPage() {
var pageNumber = document.getElementById('page-number').value;
</script>
</head>
<body>
<p> </p>
<form method="post" onsubmit="goToPage" action="#">
<label for="page-number">Enter page number:</label>
<input type="text" id="page-number" name="page-number"><BR>
<p class="submit">
<input type="submit" value="Go to page"></input>
</p>
</form>
</body>
</html>
I have tried a few different ways. With and without the "class" option, changing the javascript. But haven't been able to get it to work.
Would someone please tell me what I am doing wrong?
Thank you
The goal is to allow the reader to type in a number to go to that page. An example being that they want to go to page 33 (from say page 2). They would just type in 33 in the input box and go to that page.
Python/Plone: Getting all keywords and showing for EDIT content is very slow (keywords.pt)
No of keywords is 20000 so traversing these huge no of keywords is taking one minute.
Keywords which no has grown large is taking time....any solution is welcomed
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="plone">
<head><title></title></head>
<body>
<!-- Keyword Widgets -->
<metal:view_macro define-macro="view"
tal:define="kssClassesView context/##kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;">
<div metal:define-macro="keyword-field-view"
tal:define="kss_class python:getKssClasses(fieldName,
templateId='widgets/keyword', macro='keyword-field-view');
uid context/UID|nothing"
tal:attributes="class kss_class;
id string:parent-fieldname-$fieldName-$uid">
<ul metal:define-slot="inside">
<li tal:repeat="item accessor"
tal:content="item"/>
</ul>
</div>
</metal:view_macro>
<metal:define define-macro="edit">
<metal:use use-macro="field_macro | context/widgets/field/macros/edit">
<tal:define metal:fill-slot="widget_body" define="contentKeywords accessor;
allowedKeywords python: context.collectKeywords(fieldName, field.accessor, widget.vocab_source);
site_props context/portal_properties/site_properties|nothing;
format widget/format | string:select;
allowRolesToAddKeywords site_props/allowRolesToAddKeywords|nothing;">
<div tal:condition="allowedKeywords" id="existingTagsSection">
<tal:comment tal:replace="nothing">
dl semantically associates selector name with values
</tal:comment>
<dl id="existingTags">
<label for="subject">
<dt id="existingTagsTitle">uuuuuuuuuuuuuuuuuuuuuuuuu
<span i18n:translate="label_select_existing_tags">
Select from existing tags.
</span>
</dt>
<span id="existingTagsHelp" class="formHelp" i18n:translate="label_existingTagsHelp">
Use Control/Command/Shift keys to select multiple tags.
</span>
<tal:comment tal:replace="nothing">
Type-to-skip functionality with javascript enabled
could be described as
"Hover and type the first letter to skip through tags."
However, on touch-driven devices, vertical hover typically
scrolls the page, so horizontal hover is necessary to enable this.
Alternatively, clicking any of the tags also enables type-to-skip.
So the help could technically be extended to handle this special case
as "Hover or click and type the first letter to skip through tags.",
but I think this would be confusing to the majority of users.
The decision at this point is to not try to explain any of this on the page.
</tal:comment>
</label>
<div class="visualClear"><!-- --></div>
<select id="predefined_subjects"
name="predefined_subjects:list"
size="14"
multiple="multiple"
tal:condition="python:format!='checkbox'"
tal:attributes="id string:${fieldName};
name string:${fieldName}_existing_keywords:list;">
<option value="#" tal:repeat="keyword allowedKeywords"
tal:content="keyword" tal:attributes="value keyword;
selected python:test(context.unicodeTestIn(keyword, value), 'selected', None)">
An existing tag
</option>
</select>
<tal:comment tal:replace="nothing">
These spans are hidden by css, and used by the JavaScript called below.
</tal:comment>
<span id="noTagsSelected" i18n:translate="label_noTagsSelected">No tags currently selected.</span>
<span id="oneOrMoreTagsSelected" i18n:translate="label_oneOrMoreTagsSelected">% tags currently selected.</span>
<tal:comment tal:replace="nothing">
Call js to modify this widget with both a scrollbar and checkboxes.
There may be a better place to put this js call;
examples exist in others' widget.py and js files,
but having it here covers cases where some but not all select elements
call js to be modified.
Todo: The #subject should eventually refer to the template variable.
</tal:comment>
<script type="text/javascript">
jq(document).ready( function() {
jq("#subject").multiSelect();
});
</script>
<input type="hidden"
value=""
tal:condition="not:field/required | nothing"
tal:attributes="name string:${fieldName}_existing_keywords:default:list" />
<tal:loop tal:repeat="keyword allowedKeywords"
tal:condition="python:format=='checkbox'">
<div class="ArchetypesKeywordValue" id=""
tal:attributes="id string:archetypes-value-${fieldName}_${repeat/keyword/number}">
<input class="blurrable"
tal:attributes="
type string:checkbox;
name string:${fieldName}_existing_keywords:list;
id string:${fieldName}_${repeat/keyword/number};
checked python:test(context.unicodeTestIn(keyword, value), 'checked', None);
value keyword" />
<label
tal:content="keyword"
tal:attributes="for string:${fieldName}_${repeat/keyword/number}">
An existing tag
</label>
</div>
</tal:loop>
</dl>
<dl id="selectedTagsSection">
<dt id="selectedTagsHeading" class="formHelp"></dt>
<dd id="selectedTags"></dd>
</dl>
<div class="visualClear"><!-- --></div>
</div>
<!-- <tal:condition condition="python:not widget.roleBasedAdd or (allowRolesToAddKeywords and [role for role in user.getRolesInContext(context) if role in allowRolesToAddKeywords])">-->
<dl id="newTagsSection">
<label for="subject_keywords">
<dt id="newTagsTitle">
<span i18n:translate="label_create_new_tags">
Create and apply new tags.
</span>
</dt>
<span id="newTagsHelp" i18n:translate="label_newTagsHelp" class="formHelp">
Enter one tag per line, multiple words allowed.
</span>
</label>
<br />
<dd id="newTags">
<textarea
id="entered_subjects"
name="subject:lines"
rows="4"
tal:attributes="id string:${fieldName}_keywords;
name string:${fieldName}_keywords:lines;"
tal:define="subject python:[item for item in value if not context.unicodeTestIn(item,allowedKeywords)]"
tal:content="python:'\n'.join(subject)">
A new tag
</textarea>
</dd>
</dl>
<!-- </tal:condition>-->
</tal:define>
</metal:use>
</metal:define>
<div metal:define-macro="search">
<div metal:use-macro="context/widgets/keyword/macros/edit">
</div>
</div>
</body>
</html>
I fear is a know issue of the old Plone 4 keyword widget.
You should probably change the widget.
An add-on like eea.tags should help.
You can also try to use Plone 5 widget from plone.app.widgets, but this probably it's a more complex task (and not without side effects).
All of the files are available at http://gist.github.com/tonyahowe -- page.html, app.xql, upload.html, and form1.html. The app:upload function in appxql is at line 378.
I am trying to add an upload feature to my application here (http://nic.cerosia.org) and have been able to get the upload to work without integrating it into the whole application. Once I integrate it, I get a 400 error message, included below. I think the problem might be a controller issue, but I'm not sure?
I have added a simple link from the index to upload.html page, as follows:
<div xmlns="http://www.w3.org/1999/xhtml" data-template="templates:surround" data-template-with="templates/page.html" data-template-at="main">
<form enctype="multipart/form-data" method="post" action="form1.html">
<fieldset>
<legend>Upload Document:</legend>
<input type="file" name="file"/>
<button id="f-btn-upload" name="f-btn-upload" value="true" type="submit" class="btn btn-danger">Upload</button>
</fieldset>
</form>
</div>
That sends the upload file to form1.html, which basically figures out what to do with different form actions (it works with the first two options):
<div xmlns="http://www.w3.org/1999/xhtml" data-template="templates:surround" data-template-with="templates/page.html" data-template-at="main">
<div/>
<!-- if a query search -->
<div data-template="templates:if-parameter-set" data-template-param="query">
<div data-template="templates:include" data-template-path="search.html" class="col-md-12"/>
</div>
<!-- if a coursepack search -->
<div data-template="templates:if-parameter-set" data-template-param="f-btn-coursepack">
<div data-template="templates:include" data-template-path="coursepack.html" class="col-md-12"/>
</div>
<!-- if an upload -->
<div data-template="templates:if-parameter-set" data-template-param="f-btn-upload">
<div data-template="templates:include" data-template-path="success.html" class="col-md-12"/>
<div data-template="app:upload"/>
</div>
</div>
The app:upload is here:
declare function app:upload($node as node(), $model as map(*), $type as xs:string?) {
let $collection := '/db/apps/NiC/inReview/'
let $filename := request:get-uploaded-file-name('file')
(: make sure you use the right user permissions that has write access to this collection :)
let $login := xmldb:login($collection, 'public', 'public')
let $store := xmldb:store($collection, $filename, request:get-uploaded-file-data('file'))
return
<results>
<message>File {$filename} has been stored at collection={$collection}.</message>
</results>
};
I keep getting an error that I think has something to do with the controller, but I'm not sure. Can anyone help me figure out where the problem is? It may also be a templating issue?
Here's the error:
HTTP ERROR 400
Problem accessing /exist/apps/NiC/works/form1.html. Reason:
SAX exception while parsing request: Content is not allowed in prolog.
I don't know for sure, but I wonder if it is an issue with the templating framework reading the data from the request body and then it not being available in your app:upload function.
I wonder if we could test this, perhaps instead of checking for f-btn-upload which will be in the body of the HTTP request, you could instead check for a query-string parameter. If you change your form in the upload.html page to be like this:
<form enctype="multipart/form-data" method="post" action="form1.html?do-upload=true">
and the switch in your form1.html to be like this:
<div data-template="templates:if-parameter-set" data-template-param="do-upload">
Does that help you at all?
I want to access my Powerschool (powerschool.avon.k12.ct.us), and I find the need to type in my password and username every time rather tedious. To try and fix this I downloaded the page's source in Chrome, below:
<!DOCTYPE html>
<!-- saved from url=(0052)http://powerschool.avon.k12.ct.us/guardian/home.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Parent Sign In</title>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<meta name="robots" content="noindex">
<link href="./Powerschool_files/screen.css" rel="stylesheet" type="text/css" media="screen">
<meta name="viewport" content="width=device-width">
<script src="./Powerschool_files/jquery-1.4.2.min.js"></script><style type="text/css"></style>
<script language="JavaScript" src="./Powerschool_files/md5.js" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript"><!--
var pskey = "4EDE156E2FAD0F1A427D2AD066530F496ADC3EEA78CE43E70F28053576FD4EA1";
//-->
</script>
<script language="JavaScript" type="text/javascript">
function deleteCookie(cookieName){
var cookieDate = new Date();
cookieDate.setTime(cookieDate.getTime()-1);
document.cookie = cookieName + "=; expires='" + cookieDate.toGMTString()+"'; path=/";
}
deleteCookie("InformAuthToken");
function getURLParameter(name) {
return unescape(
(RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
);
}
var $j = jQuery.noConflict();
$j(document).ready(function() {
// Hide or show the translator login input field
// if the URL parameter "translator" is present
var translator = getURLParameter("translator");
if (translator == "null") {
$j('#translatorInput').hide();
} else {
if (translator == "true") {
$j('#translatorInput').show();
} else {
$j('#translatorInput').hide();
}
}
$j('a.popWin').click(function(){
var winURL = $j(this).attr('href');
window.open(winURL);
return false;
});
});
</script>
</head>
<body class="pslogin" id="palogin">
<div id="container">
<div id="branding-powerschool"><img src="./Powerschool_files/ps7-logo-lrg.png" alt="PowerSchool" width="280" height="41"></div>
<div id="content" class="group">
<form action="./Powerschool_files/Powerschool.htm" method="post" name="LoginForm" target="_top" id="LoginForm" onsubmit="doPCASLogin(this);">
<input type="hidden" name="pstoken" value="2465670387a1nxrEimrKqPMN0c7QbxxKLNZe16PRC">
<input type="hidden" name="contextData" value="4EDE156E2FAD0F1A427D2AD066530F496ADC3EEA78CE43E70F28053576FD4EA1">
<input type="hidden" name="dbpw" value="">
<input type="hidden" name="translator_username" value="">
<input type="hidden" name="translator_password" value="">
<input type="hidden" name="translator_ldappassword" value="">
<input type="hidden" name="returnUrl" value="">
<input type="hidden" name="serviceName" value="PS Parent Portal">
<input type="hidden" name="serviceTicket" value="">
<input type="hidden" name="pcasServerUrl" value="/">
<input type="hidden" name="credentialType" value="User Id and Password Credential">
<h2>Parent Sign In</h2>
<!--box content-->
<div id="noscript" class="feedback-alert" style="display: none;"> To sign in to PowerSchool, you must use a browser that supports and has JavaScript enabled. </div>
<fieldset id="login-inputs" class="group">
<div>
<label>Username</label>
<input type="text" id="fieldAccount" name="account" value="" size="39">
</div>
<div>
<label>Password</label>
<input type="password" name="pw" value="" size="39"><div id="login-help">Having trouble signing in?</div>
</div>
<div id="translatorInput" style="display: none;">
<label>Translator Sign In</label>
<input type="password" name="translatorpw" value="" size="39">
</div>
<div class="button-row">
<button type="submit" id="btn-enter" title="Sign In To PowerSchool Parent Access" value="Enter" border="0">Sign In</button>
</div>
</fieldset>
<!-- box content-->
</form>
</div>
<div id="footer" class="group">
<p>Copyright© 2005 - 2013 Pearson Education, Inc., or its affiliate(s). All rights reserved.</p>
<p id="pearsoncorplink">Join us on Facebook</p>
</div>
</div>
<div id="branding-pearson">
<div id="logo-pearson"></div>
<div id="tagline-pearson"></div>
</div>
<script type="text/javascript">
/**
* Set the page's locale via a request_locale URL parameter. If there is already a URL parameter by
* this name, then substitute it with the passed-in locale. NOTE: This function will actually cause the page
* to be re-submitted with the new locale, so it really should not be used with pages submitted via POST
* requests (if there are any, which I hope there are not).
* #param locale the locale to set (e.g. en_US)
*/
function setPageLocale (locale) {
var c=String (window.location);
var rlpos = c.indexOf("request_locale=");
var afterPart = "";
if (rlpos > 0) {
var afterBegin = c.indexOf("&", rlpos);
if (afterBegin > 0) {
afterPart = c.substring(afterBegin);
}
c = c.substring(0, rlpos-1);
}
var s=(c.indexOf('?') > 0 ? '&' : '?');
var np = c + s + 'request_locale=' + locale + afterPart;
window.location = np;
}
function jsCheck() {
document.getElementById("login-inputs").className = 'group';
}
jsCheck();
</script>
<script>
$j('#noscript').hide();
function jsEnabled() {
if(typeof $j != 'function'){
alert('Developer: This page is missing key components required for functionality!\n\nPossible causes include:\n - Commonscripts might be missing.\n - Page customization might enabled, and incomplete.');
//document.write('<script...');
} else {
$j('#login-inputs').removeClass('hide');
$j("#fieldAccount").focus();
}
}
$j(document).ready(function(){
jsEnabled();
});
</script>
</body></html>
I was wondering if it was possible to directly modify the downloaded source to automatically fill the input boxes (the below block is where I think it would be done) to always fill in the username and pass fields with "myUsername" and "myPassword," or something like that. I tried setting the value of the Input and Username fields, but that (chrome) gave me an, shown here:
No webpage was found for the web address: file:///C:/Users/Me/Desktop/Powerschool_files/Powerschool.htm
Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.
Do you guys know how this could be done?
Instead of copying the entire page, it's probably simpler to make a bookmarklet that fills in the form. Just edit a normal bookmark and change the link to be this:
javascript:(function() { document.forms[0].elements[0].value="hi" })()
That will set the value of the first field in the first form. (It may take some experimenting to see which form number and which field number.)
You can probably use Chrome to remember your passwords for you automatically, but what you have should actually work. You just need to change any paths to urls for it to work perfectly. One that you definitely need to change is the form action:
- ./Powerschool_files/Powerschool.htm
+ https://example.com/Powerschool_files/Powerschool.htm
This should allow you to submit directly to that site unless they have a CSRF token in the form that I don't see.
I have the below code that is being used in cms page pop up
the problem im having is if you leave email address input field blank and hit the submit (in the case "Get Code" button, you briefly see the red validation message but then hides the form, shows the hidden div.
why or how can I prevent this process, i want it to validate but proceed to show the hidden div content. Below is the code.
<div id="pop-confirm" style="display: none;">
<h1 style="color: #000000; font-weight: bold;">THANKS!</h1>
<p> </p>
<h2>Use code: <strong>extra15</strong><br /> for 15% off your purchase.</h2>
</div>
<form id="newsletter-validate-detail" action="home/send" method="post" onSubmit="new Ajax.Updater({success:'newsletter-validate-detail'}, 'newsletter/subscriber/new', {asynchronous:true, evalScripts:false, onComplete:function(request, json){Element.hide('newsletter-validate-detail');Element.show('pop-confirm');}, onLoading:function(request, json){}, parameters:Form.serialize(this)}); return false;">
<div class="block-content">
<h2>ENTER YOUR EMAIL<br /> AND GET</h2>
<div class="form-subscribe-header">
<h1>15% OFF</h1>
<br />
<h1>EVERYTHING!</h1>
</div>
<div class="input-box"><input id="newsletter" class="input-text required-entry validate-email" title="Sign up for our newsletter" type="text" name="email" /></div>
<br />
<div class="actions"><button class="button" title="Get Code" type="submit"><span><span>Get Code</span></span></button></div>
<br />
<p><em>* Promotion ends April 6th</em></p>
</div>
</form>
<script type="text/javascript">// <![CDATA[
var newsletterSubscriberFormDetail = new VarienForm('newsletter-validate-detail');
// ]]></script>
Im very new to ajax so maybe ive done something wrong.
any ideas or suggestion would be greatly appreciated.
Thanks
Try changing your onSubmit to the following:
onSubmit="if(newsletterSubscriberFormDetail.validator.validate()){ new Ajax.Updater({success:'newsletter-validate-detail'}, 'newsletter/subscriber/new', {asynchronous:true, evalScripts:false, onComplete:function(request, json){Element.hide('newsletter-validate-detail');Element.show('pop-confirm');}, onLoading:function(request, json){}, parameters:Form.serialize(this)}); } return false;"`
This wil trigger the validator before submitting the form with AJAX. Works perfect for me :)