livequery not always live when used with jquery.validate - asp.net-mvc

I use jquerylive plugin to add additional css classes to .field-validation-error class like this:
$(".field-validation-error").livequery(function () {
$(this).addClass('ui-state-error ui-corner-all');
});
when I get some spans with this class generated by jquery.validate the above code works, but at 2nd validation it doesn't.
here is the live link: http://mrgsp.md:8080/awesome/person
click on create after click save to get validation messages and click again on save

Why not hook your function into the same event that triggers validate()?
Update
I read the other comments and saw you were using xVal, read up a bit on jQuery.Validate as well. jQuery.Validate ties in with many events and registering on the event handlers would be messy. The reason that livequery works first time is that the labels are generated if they don't previously exist so that creation event makes the function run, everytime after this the label is just hidden/shown so it doesn't get triggered again but jQuery.validate's showLabel function resets the classes.
The ideal place is in xVal by making one small change in the xVal.jquery.validate.js file. In the _ensureFormIsMarkedForValidation method are the lines:
ensureFormIsMarkedForValidation: function(formElement, options) {
if (!formElement.data("isMarkedForValidation")) {
formElement.data("isMarkedForValidation", true);
var validationOptions = {
errorClass: "field-validation-error",
All you should need to do is change errorClass to:
errorClass: "field-validation-error ui-state-error ui-corner-all",
This is because xVal is doing the setting up of the validate plugin.

Can you not just the the errorClass option?
$(".selector").validate({
errorClass: "field-validation-error ui-state-error ui-corner-all"
})
Or maybe:
$.validator.setDefaults({
errorClass: "field-validation-error ui-state-error ui-corner-all"
});

Related

jQuery AutoComplete Trigger Change Event

How do you trigger jQuery UI's AutoComplete change event handler programmatically?
Hookup
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged
});
Misc Attempts Thus Far
$("#CompanyList").change();
$("#CompanyList").trigger("change");
$("#CompanyList").triggerHandler("change");
Based on other answers it should work:
How to trigger jQuery change event in code
jQuery Autocomplete and on change Problem
JQuery Autocomplete help
The change event fires as expected when I manually interact with the AutoComplete input via browser; however I would like to programmatically trigger the change event in some cases.
What am I missing?
Here you go. It's a little messy but it works.
$(function () {
var companyList = $("#CompanyList").autocomplete({
change: function() {
alert('changed');
}
});
companyList.autocomplete('option','change').call(companyList);
});
this will work,too
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
// deprecated
//$("#CompanyList").data("autocomplete")._trigger("change")
// use this now
$("#CompanyList").data("ui-autocomplete")._trigger("change")
It's better to use the select event instead. The change event is bound to keydown as Wil said. So if you want to listen to change on selection use select like that.
$("#yourcomponent").autocomplete({
select: function(event, ui) {
console.log(ui);
}
});
They are binding to keydown in the autocomplete source, so triggering the keydown will case it to update.
$("#CompanyList").trigger('keydown');
They aren't binding to the 'change' event because that only triggers at the DOM level when the form field loses focus. The autocomplete needs to respond faster than 'lost focus' so it has to bind to a key event.
Doing this:
companyList.autocomplete('option','change').call(companyList);
Will cause a bug if the user retypes the exact option that was there before.
Here is a relatively clean solution for others looking up this topic:
// run when eventlistener is triggered
$("#CompanyList").on( "autocompletechange", function(event,ui) {
// post value to console for validation
console.log($(this).val());
});
Per api.jqueryui.com/autocomplete/, this binds a function to the eventlistener. It is triggered both when the user selects a value from the autocomplete list and when they manually type in a value. The trigger fires when the field loses focus.
The simplest, most robust way is to use the internal ._trigger() to fire the autocomplete change event.
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
$("#CompanyList").data("ui-autocomplete")._trigger("change");
Note, jQuery UI 1.9 changed from .data("autocomplete") to .data("ui-autocomplete"). You may also see some people using .data("uiAutocomplete") which indeed works in 1.9 and 1.10, but "ui-autocomplete" is the official preferred form. See http://jqueryui.com/upgrade-guide/1.9/#changed-naming-convention-for-data-keys for jQuery UI namespaecing on data keys.
You have to manually bind the event, rather than supply it as a property of the initialization object, to make it available to trigger.
$("#CompanyList").autocomplete({
source: context.companies
}).bind( 'autocompletechange', handleCompanyChanged );
then
$("#CompanyList").trigger("autocompletechange");
It's a bit of a workaround, but I'm in favor of workarounds that improve the semantic uniformity of the library!
The programmatically trigger to call the autocomplete.change event is via a namespaced trigger on the source select element.
$("#CompanyList").trigger("blur.autocomplete");
Within version 1.8 of jquery UI..
.bind( "blur.autocomplete", function( event ) {
if ( self.options.disabled ) {
return;
}
clearTimeout( self.searching );
// clicks on the menu (or a button to trigger a search) will cause a blur event
self.closing = setTimeout(function() {
self.close( event );
self._change( event );
}, 150 );
});
I was trying to do the same, but without keeping a variable of autocomplete. I walk throught this calling change handler programatically on the select event, you only need to worry about the actual value of input.
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged,
select: function(event,ui){
$("#CompanyList").trigger('blur');
$("#CompanyList").val(ui.item.value);
handleCompanyChanged();
}
});
Well it works for me just binding a keypress event to the search input, like this:
... Instantiate your autofill here...
$("#CompanyList").bind("keypress", function(){
if (nowDoing==1) {
nowDoing = 0;
$('#form_459174').clearForm();
}
});
$('#search').autocomplete( { source: items } );
$('#search:focus').autocomplete('search', $('#search').val() );
This seems to be the only one that worked for me.
This post is pretty old, but for thoses who got here in 2016. None of the example here worked for me. Using keyup instead of autocompletechange did the job. Using jquery-ui 10.4
$("#CompanyList").on("keyup", function (event, ui) {
console.log($(this).val());
});
Hope this help!
Another solution than the previous ones:
//With trigger
$("#CompanyList").trigger("keydown");
//With the autocomplete API
$("#CompanyList").autocomplete("search");
jQuery UI Autocomplete API
https://jsfiddle.net/mwneepop/

ASP.NET Remote Validation only on blur?

I'm using the remote validation in MVC 3, but it seems to fire any time that I type something, if it's the second time that field's been active. The problem is that I have an autocomplete box, so they might click on a result to populate the field, which MVC views as "leaving" it.
Even apart from the autcomplete thing, I don't want it to attempt to validate when they're halfway through writing. Is there a way that I can say "only run validation n milliseconds after they are finished typing" or "only run validation on blur?"
MVC 3 relies on the jQuery Validation plugin for client side validation. You need to configure the plugin to not validate on key up.
You can switch it globally off using
$.validator.setDefaults({
onkeyup: false
})
See http://docs.jquery.com/Plugins/Validation/Validator/setDefaults and the onkeyup option here http://docs.jquery.com/Plugins/Validation/validate.
For future reference, I found it's possible to do this in combination with the typeWatch plugin (http://archive.plugins.jquery.com/project/TypeWatch).
Basically what you want to do is (in my case for a slug):
/*Disable keyup validation on focus and restore it to onkeyup validation mode on blur*/
$("form input[data-val-remote-url]").on({
focus: function () {
$(this).closest('form').validate().settings.onkeyup = false;
},
blur: function () {
$(this).closest('form').validate().settings.onkeyup = $.validator.defaults.onkeyup;
}
});
$(function () {
/*Setup the typeWatch for the element/s that's using remote validation*/
$("#Slug").typeWatch({ wait: 300, callback: validateSlug, captureLength: 5 });
});
function validateSlug() {
/*Manually force revalidation of the element (forces the remote validation to happen) */
var slug = $("#Slug");
slug.closest('form').validate().element(slug);
}
If you're using the vanilla typeWatch plugin, you'll have to setup a typeWatch for every element because the typeWatch callback doesn't give you access to the current element via $(this), it only passes the value.
Alternatively you can modify the typeWatch plugin to pass in the element (timer.el) and then you can apply a delay to all.
For some reason (maybe because of conflicts with the unobtrusive plugin), hwiechers' answer didn't work for me. Instead, I had to get the validator of my form with .data('validator') (as mentioned in this answer) and set onkeyup to false on it.
var validator = $('#form').data('validator');
validator.settings.onkeyup = false;
We had the same problem of focusing out the autocomplete textbox "DealingWithContactName" when autocomplete suggestion list pops up. Here we select the dynamically generated autocomplete list item on which the user clicks and set focus on to it. After 50ms we take the focus out from the textbox. It solved our problem.
$('body').on('click', 'ul.ui-autocomplete li a', function () {
$('#DealingWithContactName').focus();
window.setInterval(function () {
$('#DealingWithContactName').blur();
}, 50);
});
I wanted local validation to remain during onkeyup so that the user had a tighter feedback loop. This should only affect the remote validation (that results from RemoteAttribute):
$("[data-val-remote]").keyup(function () {
// Avoid hitting server validation during onkeyup. Wait for onfocusout.
return false;
});

Setting dialog overlay Jquery

I want to set the overlay of a jQuery dialog to an image, and can't seem to manage the task.
I have other dialogs on the pages that I want to no have the background images, so setting the css for the overlay background won't work as a blanket solution.
I have tried a lot of different methods, and I believe there is a timing issue with the appliction of the jQuery command to set the overlay with css and the actual dialog div's and css getting added to the DOM.
Here is what I have tried so far.
$('#submitUpload').click(function(){
$("#uploadStart").dialog('open');
$(".ui-widget-overlay").css({'background-image': 'url("http://www.mydomain.com/images/ftp-page-bg.gif")','opacity':'1'})
$("#uploadForm").submit();
});
OR
$("#uploadStart").dialog({
autoOpen: false,
width: 400,
modal: true,
closeOnEscape: false,
draggable: false,
resizable: false,
open: function(event, ui) {
$(".ui-dialog-titlebar-close").hide();
$(".ui-widget-overlay").css({'background-image': 'url("http://www.mydomain.com/images/ftp-page-bg.gif")','opacity':'1'})
}
});
I have also tried using the dialogClass method on the dialog code with no success.
With both the absolute url and the relative, and the url in quotes or with no quotes.
The image exists in the directory.
Anyone have any ideas on how to get jQuery to apply with the correct timing to display the image as the overlay?
Thanks!
Update
The dialog class designation will allow you to set classes for the overal dialog. I was actually looking to just tap into the specific ui-widget-overlay class and over-ride the background image there. I found that trying to override the background using the dialogClass worked for overriding the background of the dialog, not the overlay background.
When the dialog is added to the DOM, jQuery loads it's div's right before the body tag.
I found a solution, being that in the open method for the dialog, I used
$(".ui-widget-overlay").addClass('artFTP');
to add a class
.artFTP{background-image: url(../../images/ftp-page-bg.gif); opacity:1;}
and made sure it was the last class in the file that would overwrite the overlay background image.
I hope this helps someone.
Thanks and +1 to jjross, your answer got me to jump back into the jQuery docs.
If anyone has a better solution, please post. I would be happy to see it. I think there might be a way to use CSS to accomplish the task, but (for the life of me) couldn't figure it out.
You should be able to add the class to the div in your HTML code prior to jquery being called on it. In my testing, this automatically added that class to the dialog when it was created.
In the new class, you should be able to specify a background image.
For example:
calling:
$("#dialog").dialog();
on
<div id="dialog" class="thisClass" title="Edit Case Status">
<div>some stuff</div>
</div>
causes the dialog to be created with the
"thisClass" class.
as an alternative option, it looks like the dialog has a "dialogClass" method. It will let you add your own class to the dialog (in that class, you can define the background). From the docs:
The specified class name(s) will be added to the dialog, for additional theming.
Code examples
Initialize a dialog with the dialogClass option specified.
$( ".selector" ).dialog({ dialogClass: 'alert' });
Get or set the dialogClass option, after init.
//getter
var dialogClass = $( ".selector" ).dialog( "option", "dialogClass" );
//setter
$( ".selector" ).dialog( "option", "dialogClass", 'alert' );
I encountered the same problem and found In this case your question. I didn't find any solution that could satisfy me, so I did something on my own.
First, let me introduce my problem.
I have a page, where I have two kinds of dialogs. Dialogs with video and dialogs with message (like alert, confirmation, error etc.). As we know, we can set a different class for a dialog, but we can't set class for different overlay. So question was, how to set a different behavior for different overlays?
So I dig, I dig deeper than Dwarves in Moria into jQuery ui code itself. I found out, that actualy there is an unique overlay for each dialog. And it is created in "private" function _createOverlay which is not accessible. In fact, I found function via jquery ui namespace as $.ui.dialog.prototype._createOverlay. So I was able to make a small extension with logic based on class:
(function() {
// memorize old function
var originFn = $.ui.dialog.prototype._createOverlay;
// make new function
$.ui.dialog.prototype._createOverlay = function() {
originFn.call(this); // call old one
// write your own extension code there
if (this.options["dialogClass"] === "video-dialog") {
var overlay = this.overlay; // memorize overlay (it is in old function call as this.overlay)
var that = this; // just cause bind is event
// my own extenstion, when you click anywhere on overlay, dialog is closed + I change css
overlay.bind('click', function() {
that.close(); // it is same like element.dialog('close');
}).css({
"background": "none",
"background-image": "url(\'files/main-page/profile1.png\')" // this didnt work for you, but works for me... maybe I have newer version of jQuery.UI
// anyway, once you have overlay as variable, Im sure you will be able to change its css
});
}
};
})();
I hope this will help others :)

Bind jQuery UI autocomplete using .live()

I've searched everywhere, but I can't seem to find any help...
I have some textboxes that are created dynamically via JS, so I need to bind all of their classes to an autocomplete. As a result, I need to use the new .live() option.
As an example, to bind all items with a class of .foo now and future created:
$('.foo').live('click', function(){
alert('clicked');
});
It takes (and behaves) the same as .bind(). However, I want to bind an autocomplete...
This doesn't work:
$('.foo').live('autocomplete', function(event, ui){
source: 'url.php' // (surpressed other arguments)
});
How can I use .live() to bind autocomplete?
UPDATE
Figured it out with Framer:
$(function(){
$('.search').live('keyup.autocomplete', function(){
$(this).autocomplete({
source : 'url.php'
});
});
});
jQuery UI autocomplete function automatically adds the class "ui-autocomplete-input" to the element. I'd recommend live binding the element on focus without the "ui-autocomplete-input"
class to prevent re-binding on every keydown event within that element.
$(".foo:not(.ui-autocomplete-input)").live("focus", function (event) {
$(this).autocomplete(options);
});
Edit
My answer is now out of date since jQuery 1.7, see Nathan Strutz's comment for use with the new .on() syntax.
If you are using the jquery.ui.autocomplete.js try this instead
.bind("keydown.autocomplete") or .live("keydown.autocomplete")
if not, use the jquery.ui.autocomplete.js and see if it'll work
If that doesn't apply, I don't know how to help you bro
Just to add, you can use the .livequery plugin for this:
$('.foo').livequery(function() {
// This will fire for each matched element.
// It will also fire for any new elements added to the DOM.
$(this).autocomplete(options);
});
To get autocomplete working when loaded dynamically for the on() event used in jQuery > 1.7, using the syntax Nathan Strutz provides in his comment:
$(document).on('focus', '.my-field:not(.ui-autocomplete-input)', function (e) {
$(this).autocomplete(options)
});
where .my-field is a selector for your autocomplete input element.
.live() does not work with focus.
also keyup.autocmplete does not make any sense.
Instead the thing I have tried and working is this
$(document).ready(function(){
$('.search').live('keyup' , function()
{
$(this).autocomplete({ source : 'url.php' });
});
})
This works perfectly fine.
You can't. .live() only supports actual JavaScript events, not any custom event. This is a fundamental limitation of how .live() works.
You can try using this:
$('.foo').live('focus.autocomplete', function() {
$(this).autocomplete({...});
});
After reading and testing everyone else's answers I have updated it for the current version of JQuery and made a few tweaks.
The problem with using keydown as the event that calls .autocomplete() is that it fails to autocomplete for that first letter typed. Using focus is the better choice.
Another thing I have noticed is that all of the given solutions result in .autocomplete() being called multiple times. If you are adding an element dynamically to the page that will not be removed again, the event should only be fired once. Even if the item is to be removed and added again, the event should be removed and then added back each time the element is removed or added so that focusing on the field again will not unnecessarily call .autocomplete() every time.
My final code is as follows:
$(document).on('focus.autocomplete', '#myAutocomplete', function(e){
$(this).autocomplete(autocompleteOptions);
$(document).off('focus.autocomplete', '#myAutocomplete');
});
autocomplete is not an event rather a function that enables autocomplete functionality for a textbox.
So if you can modify the js that creates the textboxes dynamically to wrap the textbox element in as a jquery object and call autocomplete on that object.
I just noticed you edited your post with this answer. It was obvious to me so I'm posting it below for others. Thank you.
$(function()
{
$('.search').live('keyup.autocomplete', function()
{
$(this).autocomplete({ source : 'url.php' });
});
});
This works for me:
$(function()
{
$('.item_product').live('focus.autocomplete', function()
{
$(this).autocomplete("/source.php/", {
width: 550,
matchContains: true,
mustMatch: false,
selectFirst: false,
});
});
});
You can just put the autocomplete inside input live event, like this:
$('#input-element').live('input', function(){
$("#input-element").autocomplete(options);
});

Return Functions using prototype's Event.observe

I'm trying to migrate from using inline event triggers to using event listeners using Prototype's Event.observe function. There are a few inline commands that I don't know how to handle using the function call.
I want to move from:
<form id='formFoo' action='whatever.php' onsubmit="return Foo.verify(this);">
To an event call:
Event.observe('formFoo', 'submit', Foo.verify);
This of course will not work, as I need a return value from the function I call to determine whether the form gets submitted or not.
How do I do this using event handlers?
The easiest way to do this is probably Event.Stop from prototype. This works for me (put this in any script block):
Foo = { verify: function(){ return false } };
Event.observe(window, 'load', function() {
Event.observe('formFoo', 'submit', function(e){
if(! Foo.verify($('formFoo'))){
e.stop();
}
});
});
It stops every form submission; you will just have to change Foo.verify to do what you wanted.
Explanation: When the submit event is triggered, prototype passes the handler a prototype Event object representing the event, and the stop method on that object prevents the submit. The rest is just setting up the event.
Minor note: Among other things, passing Foo.verify directly as a handler will cause verify to be called as a function, not a method (this will be the global object within the call, rather than Foo). That situation might be okay - if verify doesn't use this, you're fine. Be aware of the difference, though.

Resources