Is there a standard practice for localizing the JQuery Validation messages?
I've been able to hack something together by declaring my own ClassRules and referencing them instead of the default ones.
My code.
<input class="localized-required" id="myTextInput" name="myTextInput" type="text" value="" />
<script language="javascript" type="text/javascript">
jQuery(document).ready(function () {
$.validator.addMethod("localized-required", $.validator.methods.required, '<%: Resources.Strings_ValidationMessages.SelectionRequired %>');
$.validator.addClassRules(
{
"localized-required": { "localized-required": true }
});
jQuery("#myForm").validate();
})
</script>
I'm just looking to see if there is a better way.
You could overwrite the messages object in the validator object.
$.validator.messages = {
required: '<%: Resources.Strings_ValidationMessages.SelectionRequired %>'
};
Or you could potentially use your own defaultMessage function.
$.validator.prototype.defaultMessage = function(element, method) {
var locale = magicFunctionToGetLocale();
var message = $.validator.localizedMessages[locale][method];
return this.findDefined(
this.customMessage( element.name, method ),
this.customMetaMessage( element, method ),
// title is never undefined, so handle empty string as undefined
!this.settings.ignoreTitle && element.title || undefined,
message,
"<strong>Warning: No message defined for " + element.name + "</strong>"
);
};
In the above example, $.validator.localizedMessages is an object created elsewhere in your code. The standard validation plugin does not have a localizedMessages object.
There are validation files available if you want:
https://github.com/jzaefferer/jquery-validation/tree/master/src/localization
Just get the ones you need and reference the .js file(s) in your page.
<script type="text/javascript" src="localization/messages_XX.js"></script>
Related
So I have a Default Search page that calls 2 UserControls
<uc1:BasicSearch ID="BasicSearch" runat="server" />
<uc1:AdvancedSearch ID="AdvancedSearch" runat="server" />
Both of my usercontrols have multiple date Fields that I wish to validate but I'm having a few issues
Since I'm using .net, the Controls get renamed, I got around this but using <%=specificDateTextbox.UniqueID%>, however, this ONLY works in the page, once I try to move all the Script to a .JS page it stops working.
For some reason, the validation never fires on the AdvancedSearch control when both are loaded. If I comment out the BasicSearch usercontrol, the AdvancedSearch validation fires as it should.
This obviously leads me to believe there's a naming conflict or perhaps I can only use a sinlge validation script on a a page?
The code im using
BasicSearch.ascx
<asp:TextBox ID="specificDateTextbox" runat="server" CssClass="form-control" placeholder="YYYY-MM-DD"></asp:TextBox>
The Script
<script>
$(function () {
$("#form1").validate({
rules: {
<%=specificDateTextbox.UniqueID%>: {
dateISO:true,
},
<%=RangeStartDateTextbox.UniqueID%>: {
dateISO:true,
},
<%=RangeEndDateTextbox.UniqueID%>: {
dateISO:true
}
},
messages:
{
<%=specificDateTextbox.UniqueID%>: "* Please use a proper Date Format (YYYY-MM-DD)",
<%=RangeStartDateTextbox.UniqueID%>: "* Please use a proper Date Format (YYYY-MM-DD)",
<%=RangeEndDateTextbox.UniqueID%>: "* Please use a proper Date Format (YYYY-MM-DD)"
},
highlight: function (element) {
$(element).closest('.form-horizontal').addClass('has-error');
},
unhighlight: function (element) {
$(element).closest('.form-horizontal').removeClass('has-error');
},
errorElement: 'span',
errorClass: 'help-block',
errorPlacement: function (error, element) {
if (element.parent('.input-group').length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
});
});
</script>
AdvancedSearch.ascx
The Script
<script>
$(function () {
$("#form1").validate({
rules: {
<%=AdvSpecificDateTextbox.UniqueID%>: {
dateISO:true
}
},
messages:
{
<%=AdvSpecificDateTextbox.UniqueID%>: "* Please use a proper Date Format (YYYY-MM-DD)"
},
highlight: function (element) {
$(element).closest('.form-horizontal').addClass('has-error');
},
unhighlight: function (element) {
$(element).closest('.form-horizontal').removeClass('has-error');
},
errorElement: 'span',
errorClass: 'help-block',
errorPlacement: function (error, element) {
if (element.parent('.input-group').length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
});
});
</script>
Edit
The two rendered controls look like the below
<input name="ctl00$MainContent$BasicSearch$specificDateTextbox" type="text" id="MainContent_BasicSearch_specificDateTextbox" class="form-control " placeholder="YYYY-MM-DD" />
<input name="ctl00$MainContent$AdvancedSearch$AdvSpecificDateTextbox" type="text" id="MainContent_AdvancedSearch_AdvSpecificDateTextbox" class="form-control " placeholder="YYYY-MM-DD" />
Any help would be greatly appreciated.
For the record, I was able to make the validator work with usercontrols by using the fully rendered control name and chaining the rules together in a .js for the page that calls the user controls.
see below
search.aspx
<%# Register TagPrefix="uc1" TagName="BasicSearch" Src="~/_usercontrols/BasicSearch.ascx" %>
<%# Register TagPrefix="uc1" TagName="AdvancedSearch" Src="~/_usercontrols/AdvancedSearch.ascx" %>
<uc1:BasicSearch ID="BasicSearch" runat="server" />
<uc1:AdvancedSearch ID="AdvancedSearch" runat="server" />
<script src="<%= ResolveUrl("~/scripts/search/_actions.js")%>"></script>
_actions.js
$(function () {
$("#form1").validate({
rules: {
ctl00$MainContent$BasicSearch$specificDateTextbox: {
dateISO: true
},
ctl00$MainContent$BasicSearch$RangeStartDateTextbox: {
dateISO: true
},
ctl00$MainContent$BasicSearch$RangeEndDateTextbox: {
dateISO: true
},
ctl00$MainContent$AdvancedSearch$AdvSpecificDateTextbox: {
dateISO: true
},
ctl00$MainContent$AdvancedSearch$AdvRangeStartDateTextbox: {
dateISO: true
},
ctl00$MainContent$AdvancedSearch$AdvRangeStartEndTextbox: {
dateISO: true
}
},
messages:
{
ctl00$MainContent$BasicSearch$specificDateTextbox: "* Please use a proper Date Format (YYYY-MM-DD)",
ctl00$MainContent$BasicSearch$RangeStartDateTextbox: "* Please use a proper Date Format (YYYY-MM-DD)",
ctl00$MainContent$BasicSearch$RangeEndDateTextbox: "* Please use a proper Date Format (YYYY-MM-DD)",
ctl00$MainContent$AdvancedSearch$AdvSpecificDateTextbox: "* Please use a proper Date Format (YYYY-MM-DD)",
ctl00$MainContent$AdvancedSearch$AdvRangeStartDateTextbox: "* Please use a proper Date Format (YYYY-MM-DD)",
ctl00$MainContent$AdvancedSearch$AdvRangeStartEndTextbox: "* Please use a proper Date Format (YYYY-MM-DD)"
},
highlight: function (element) {
$(element).closest('.form-horizontal').addClass('has-error');
},
unhighlight: function (element) {
$(element).closest('.form-horizontal').removeClass('has-error');
},
errorElement: 'span',
errorClass: 'help-block',
errorPlacement: function (error, element) {
if (element.parent('.input-group').length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
});
});
I just thought that I would throw in my .02 here. Client Id's do not work when in script files ( but you already knew that) because ASP.NET renders the controls (and the ID's) on the page when servicing the request for the page. I have found 2 ways around this and have been able to add code to my script files.
If you are using .NET 4.0 or higher you can use ClientIDMode="Static" on the element which will cause the rendered control to maintain the ID that you assigned it in the markup. You can use this per control, at the page level, and application level in the web.config. This makes it much easier to find it with jQuery in your script files. This would be the preferred way to do it.
If you are using an older version of .NET where ClientIDMode is not available you can use an "ends with" selector with jQuery like this $('input[id$="myServerId"]') to look for your item with its ID property being at the end of the rendered id from ASP.NET.
I realize this is pretty old and most people aren't even using usercontrols much anymore, but I've had to do it here after moving some code in an older application from a page to a usercontrol in order to reuse it somewhere else, and I've had to deal with this. So just in case someone else has to deal with this, here is what I ended up doing:
function convertUserControlValidationRules($container, rules, msgs) {
var association = {},
newRules = {},
newMsgs = {};
for (var key in rules) {
var name = "";
if (association.hasOwnProperty(key))
name = association[key];
else {
name = $container.find("#" + key).attr("name");
association[key] = name;
}
newRules[name] = rules[key];
if (msgs.hasOwnProperty(key))
newMsgs[name] = msgs[key];
}
return { rules: newRules, messages: newMsgs };
}
Where $container is the form's jQuery object, and rules/msgs are the original rules/messages. Obviously, you will need to use this with a ClientIDMode="Static" declaration in your usercontrol.
A small example of usage here, would be:
var ucRules = convertUserControlValidationRules($form, { txtDate: { required: true }}, { txtDate: { required: "Please enter the date!" }});
$form.validate({ rules: ucRules.rules, messages: ucRules.message });
instead of
$form.validate({
rules: { txtDate: { required: true }},
messages: { txtDate: { required: "Please enter the date!" }}
});
very minimal code to change, mucho time saved! Hope that can help somebody!
I'm having a bit of an issue with RequireJS.
I have a .NET site with several controls that contains JS code which requires parameters generated by .NET. I've been trying to implement RequireJS into my site, but I ran into a small problem.
I've included the script tag that references RequireJS at the top of the page, as well as reference to main.js within that script tag. Inside my main.js I have the following code;
require.config({
paths: {
'jquery' : '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min'
}
});
Then I have a web control that is supposed to display a flash video. This web control contains the following piece of code;
require(['jquery'], function ($) {
if (!eval('<%= FlashAvailable.ToString().ToLowerInvariant() %>')) {
var url = '<%= FallbackImageUrl %>';
if (!url) {
$("#flashcontent").remove();
}
return;
}
var link = '<%= Page.ResolveUrl("~/Templates/AlloyTech/scripts/slideshow.swf") %>';
var width = '<%= Width %>';
var height = '<%= Height %>';
var variables = { xml: '<%= ConfigXml %>' };
var params = { wmode: 'transparent' };
var attributes = { };
swfobject.embedSWF(link, 'flashcontent', width, height, '10', false, variables, params, attributes);
});
This should be working fine right? However, executing the page results in two sets of errors.
1. GET http://episerversite6/scripts/jquery.js 404 (Not Found)
2. Uncaught Error: Script error http://requirejs.org/docs/errors.html#scripterror
Why is it trying to find jquery.js when I've defined the path for jquery is 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min'. I've tried adding a second parameter for the path, which is a local fallback jQuery file, and that makes everything work, but I'd still get the first error in my console.
Secondly, why am I getting the scripterror message? I've checked my code several times and I can't seem to find anything wrong with it. Does it have something to do with the code being executed before jQuery has time to load?
So I guess what I'm asking is, what's the best way to use RequireJS with inline scripts? I hope someone can help. Thanks in advance.
It seems I have misunderstood how RequireJS works and the need to rewrite my code accordingly.
So what I decided to do instead is append all ASP.NET generated variables to the elements they're affecting as data-* attributes, and moving all JavaScript codes to individual files which are then referenced in the main.js script that runs on page load. The data-* attribute values are fetched later when the script and its dependencies have been loaded.
So here's what I did to the project I mentioned in my initial question, which is actually an EPiServer CMS demo project called Alloytech.
Flash.ascx
<div id='flashcontent' data-flash-available="<%= FlashAvailable.ToString(CultureInfo.InvariantCulture).ToLowerInvariant() %>"
data-fallback-image="<%= FallbackImageUrl %>"
data-flash-link="<%= Page.ResolveUrl("~/Templates/AlloyTech/scripts/slideshow.swf") %>"
data-flash-width="<%= Width %>"
data-flash-height="<%= Height %>"
data-flash-variables="<%= ConfigXml %>">
<img src='<%= FallbackImageUrl %>' alt='<%= FallbackImageAlt %>' />
</div>
main.js
require.config({
shim: {
'swfobject' : {
exports: 'swfobject'
}
},
paths: {
'jquery': ['http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min', '/Scripts/jquery-1.7.2.min'],
'alloytech': '/templates/alloytech/scripts/alloytech',
'mobile': '/templates/alloytech/scripts/mobile/mobile',
'swfobject': '/Templates/AlloyTech/scripts/swfobject'
}
});
define(['jquery', 'alloytech', 'mobile', 'swfobject'], function ($, A, M, swfobject) {
$.fn.addFlash = function () {
return this.each(function () {
var el = $(this);
var flashAvailable = el.data('flash-available'),
fallbackImage = el.data('fallback-image'),
flashLink = el.data('flash-link'),
flashWidth = el.data('flash-width'),
flashHeight = el.data('flash-height'),
flashVariables = el.data('flash-variables');
if (!eval(flashAvailable)) {
var url = fallbackImage;
if (!url) {
el.remove();
}
return;
}
var link = flashLink;
var width = flashWidth;
var height = flashHeight;
var variables = { xml: flashVariables };
var params = { wmode: 'transparent' };
var attributes = {};
swfobject.embedSWF(link, 'flashcontent', width, height, '10', false, variables, params, attributes);
});
};
$(function () {
$("#flashcontent").addFlash();
});
});
I hope someone else will find this useful.
Its looking for the required module "jquery" before the config paths have loaded. So basically what require.js does it assume that "jquery" is a javascript file and tries to look for it in the same directory as your "data-main" (defined in your HTML header).
I don't know what the solution is for this particular situation as I am fighting the same battle, but this seems to be different to the way that the jquery.js creators intended their plugin to be used judging by the content of this page: Common Errors
I'm trying to call a server side method, using jquery, on the textchange event of a textbox which is generated dynamically on the clientside (I dont know how to fetch the id of this). Can somebody help me to do this stuff? The script im using is as follows:
<script type="text/javascript">
$(init);
function init() {
$('#test').droppable( //Div Control where i'll be dropping items
{
drop: handleDropEvent
});
$('a').each(function(idx, item) {
$(item).draggable({ cursor: 'move', helper: 'clone' })
});
}
function handleDropEvent(event, ui) {
var draggable = ui.draggable;
document.getElementById('test').innerHTML += addColumn(draggable.attr('text')) + '<br>';
}
$('.textChangeClass').live('change', function() {
/* Evokes on the text change event for the entire textboxes of class .textChangeClass. Is it possible to specify the dynamic textbox generated # clientside here? (like for e.g. : $('#mytextbox').click(function () ) */
$.ajax({
type: "POST",
url: "Webtop.aspx/ServerSideMethod", //This is not getting called at all.
data: "{'param1': AssignedToID}",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
cache: false,
success: function(msg) {
alert("From Server");
}
})
});
});
function addColumn(column) {
var iHtml;
//This is how i'm generating the textboxes along with a checkbox bound by a div.
iHtml = '<div id="dv' + column + '" width="100px;" height="20px;" padding: "0.5em;"> ' + '<span title="ToolTipText">' + '<input type="checkbox" id="cb' + column + '" value="' + column + '" /> <label for="cb' + column + '">' + column + '</label></span><input class="textChangeClass" type="text" id="aln' + column + '"> </div>';
return iHtml
}
</script>
I think you have an extra "});" although this probably isn't the problem.
What is "AssignedToID"? Try adding single quotes around that. I seem to remember having a weird problem a couple years ago related to quoting in the json.
Can you see the request in Fiddler/firebug/etc? Is the content correct?
You should be careful of your use of inferred semi-colons too. If you ever minify your javascript (yeah, I know this is embedded, but I'd like to hope that one day it will be moved to a seperate js file) you're eventually going to have a problem. Imagine some other developer comes along, does some refactoring and needs to add a return value after the ajax call.
$.ajax({...})return foo}
EDIT
Fiddler/Firebug Net panel are your friends... They will allow you to inspect the request and the response from the server. This way you don't have to add the error handler (although you may want to for other reasons eventually)
EDIT
To answer the other part of your question, you can access the textbox for which the change event was triggered through the use of the 'this' keyword inside of the event handler.
$('.textChangeClass').live('change', function(event) {
//Note that the 'event' parameter has interesting things in it too.
var changedText = $(this).val();
alert("The value in the textbox is: '" + changedText + "'");
var data = {
param1: changedText
};
$.ajax({
...
//Using json2 library here to create json string
data: JSON.stringify(data),
...
});
});
Note that I added the optional 'event' parameter to the event handler. It has interesting things in it and it's something that is often overlooked by people who are new to jQuery. Read about it here.
You need to write you code of adding the event to textbox after generation of textbox otherwise it's not get fire.
add text box
After that write code to add event to text box or bind event to text box
just follow the above step will do your work
EDIT
Add the error function to your ajax call you will get the error ... will allow you to proceed further
$.ajax({
type: "post", url: "/SomeController/SomeAction",
success: function (data, text) {
//...
},
error: function (request, status, error) {
alert(request.responseText);
}
});
I'm trying to submit form data with jQuery. I'm using ASP.NET WebMatrix. In a .cshtml file I have
#{
// other code
if(IsPost)
{
var item = new Item();
item.Title = Request.Form["title"];
item.Description = Request.Form["description"];
// aditional code here
}
}
<script type="text/javascript">
$(document).ready(function(){
$("form#itemForm").submit(function(){
$.post("form.cshtml", {
title: $("#title").val(),
description: $("#description").val(),
price: $("#price").val()},
function(data){
},
"json");
})
});
</script>
<form>
<!-- html form here -->
</form>
How can I pass values from form to Request.Form object? And how can I than response with json back to html?
A better way would be to just have jQuery post the form data using $(this).serialize() instead of building an object with all the values in it it to pass. After that, yah, Request["title"], etc will get the values that were posted.
This is what you want.
http://www.mikesdotnetting.com/Article/155/WebMatrix-And-jQuery-Forms
Values are passed through jQuery.post() to Request.Parameters.
I am using the .alphanumeric plugin for jQuery which is certainly doing what I would expect as users type directly into the textbox. But, if a user were to copy and paste a value into the text box, all bets are off.
$("#<%= txtNumber.ClientID %>").alphanumeric({allow:"-"});
I can certainly do this:
$(document).ready(function() {
$("#<%= txtNumber.ClientID %>").blur(function() {
$("#<%= txtNumber.ClientID %>").val(
RemoveInvalidCharacters(
$("#<%= txtNumber.ClientID %>").val()
)
);
});
});
//FUNCTION REMOVES ANY ; IN TEXT TO PREVENT SQL INJECTION
function RemoveInvalidCharacters(text) {
return text.replace(';', '');
}
But... I'd rather not have to kluge up my code even further with .blur() functions. Are there any other ways around this?
Handling the paste event is fairly straightforward. I'm using this technique in my masked input plugin with good results. Feel free to browse the source to see it in use.
Here is the relevant bits modified for your example above.
var pasteEventName = $.browser.msie ? 'paste' : 'input';
$("#<%= txtNumber.ClientID %>").bind(pasteEventName, function() {
setTimeout(function() {
RemoveInvalidCharacters(
$("#<%= txtNumber.ClientID %>").val()
);
}, 0);
});
I found this solution here:
http://www.devcurry.com/2009/10/allow-only-alphanumeric-characters-in.html
<script type="text/javascript">
$(function() {
$('input.alpha').keyup(function() {
if (this.value.match(/[^a-zA-Z0-9 ]/g)) {
this.value = this.value.replace(/[^a-zA-Z0-9 ]/g, '');
}
});
});
</script>
<input type="text" name="test" value="" class="alpha">
I too was needing a solution to the paste problem, and I figured out something that will work for me. A person can still use the Edit > Paste in the browsers menu, but Ctrl-V, as well as right click paste is handled. Tested in FF,IE,Opera,Safari,Chrome:
<!DOCTYPE html>
<html>
<head>
<title>Only Allow Certain Characters</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
</head>
<body>
<br>
<form id="myform" action="">
<input id="element1" name="mytext1" type="text">
<input id="element2" name="mytext2" type="text">
</form>
<script>
/* removes evil chars while typing */
(function($){
$.fn.disableChars = function(a) {
a = $.extend({
allow: ''
}, a);
b = a.allow.split('');
for ( i=0; i<b.length; i++) b[i] = "\\" + b[i];
a.allow = b.join('');
var regex = new RegExp('[^a-z0-9' + a.allow + ']', 'ig');
$(this)
.bind('keyup blur', function() {
if (this.value.search(regex) != '-1') {
this.value = this.value.replace(regex, '');
}
})
.bind('contextmenu',function () {return false});
}
})(jQuery);
$("#element1").disableChars();
$("#element2").disableChars({allow:".,:-() "});
</script>
</body>
</html>
Copy and Paste is definitely a challenge for masked inputs.
Have you considered "encoding" special characters when the form is submitted as opposed to when the user enters values? We do the same thing to allow users to enter the < and > characters in TextBoxes (we convert them to < and > via javascript and then back in to < and > in the code behind.
This way you will not prevent an SQL injection. I’m not required to use your form, I can make mine and POST it to your script. Even easier: I can disable javascript and go drop your database.
Instead, check the input validity on server side.
The easiest ways are escaping it or using parametrised queries.