I'm not sure how to achieve the following in javascript, or even if I'm thinking about it correctly. Basically I want to attach a javascript member function to each custom object rendered, so I could have something like this in C#:
public class NumericTextBox : TextBox
{
...
string clientScript = "function isValid() { return isNumericValue(this.value); }";
AttachValidationFunction(clientScript);
}
public class EmailTextBox : TextBox
{
...
string clientScript = "function isValid() { return isEmail(this.value); }";
AttachValidationFunction(clientScript);
}
and then use the following javascript function in the page
function isFormValid() {
var controls = getElementsByClass("validatingControl");
...
if (!controls[i].isValid()) return false;
...
}
obvisouly in pseudo-code, but hopefully that gives the idea of what I need to achieve. Any suggestions?
what i would do, is to make sure that AttachValidationFunction receives this.ClientID along with the validation function, adds to a list (say, Dictionary<String, String>) and at render time, registers a javascript block with an array of all the added controls, where the result would look like this:
<script type="text/javascript">
var controlsToValidate = [
{ id: 'ctl00_txtNumeric', validate: function(e) { return isNumeric(e.value); } },
{ id: 'ctl00_txtEmail', validate: function(e) { return isEmail(e.value); } }
];
</script>
And then you could iterate over that array like so:
<script type="text/javascript">
function isFormValid() {
for(var i = 0; i < controlsToValidate.length; i++) {
var control = controlsToValidate[i];
var field = document.getElementById(control.id);
if(!control.validate(field))
return false;
}
return true;
}
</script>
I hope that's quite clear.
Related
I am tying to validate the textboxes for achieving 'alphabets only' property in asp.net page with Jquery.
Here is the code
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
.............codes.............
<script type="text/javascript">
$('.alph').keypress(function (e) {
var regex = new RegExp("^[a-zA-Z\s]+$");
var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
if (regex.test(str)) {
return true;
}
else {
e.preventDefault();
alert('Alphabets only');
return false;
}
});
</script>
.............codes.............
<asp:TextBox ID="txt_name" CssClass="alph" BorderColor="Gray" Font-Size="Large" Height="25" Width="250" runat="server"></asp:TextBox>
This code didn't work and I am sure my computer is connected to the internet to reach code.jquery.com. Help me please.
try this script code after Document.ready block
$(document).ready(function(){
$('.alph').keypress(function (e) {
var regex = new RegExp("^[a-zA-Z\s]+$");
var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
if (regex.test(str)) {
return true;
}
else {
e.preventDefault();
alert('Alphabets only');
return false;
}
});
});
Before you can safely use jQuery you need to ensure that the page is in a state where it's ready to be manipulated. With jQuery, we accomplish this by putting our code in a function, and then passing that function to $(document).ready(). The function we pass can just be an anonymous function.
My mistake! Since I am new to Jquery I didn't know about 'doc.ready' I corrected the code as
$(document).ready(function () {
$('#<%=txt_name.ClientID %>').keypress(function (e) {
var regex = new RegExp("^[a-zA-Z\s]+$");
var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
if (regex.test(str)) {
return true;
}
else {
e.preventDefault();
alert('Alphabets only');
return false;
}
});
});
Code works perfect!
I have a problem in How to use javascript variables in C# and vise versa : I have this Model passing to the view:
public List<Tache> Get_List_Tache()
{
Equipe _equipe = new Equipe();
List<Tache> liste_initiale = _equipe.Get_List_tache();
return liste_initiale;
}
It's a list of objects Tache in which I'd like to use it's three fields Tache_description, Begin_date and End_date.
In my JavaScript code I have this function and it works fine:
<script>
$(document).ready(function () {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#calendar').fullCalendar({
theme: true,
header: {left: 'prev,next today',center: 'title',right: 'month,agendaWeek,agendaDay'},
editable: true,
events: [
#foreach (var m in Model.Get_List_Tache())
{
#:{title : #m.Tache_description , start: #m.Begin_date , end : #m.Begin_date }
}
]
});
});
</script>
The values of the array events are just for test, and I need to fill events by the value of the Model. For each element like this: title = Tache_description, start = Begin_date and end = End_date.
So how can I do this task? Any suggestions?
Try this,
foreach (var item in YourList)
{
events: [{ title: '#item.title', start: '#item.start', end: '#item.end'}]
}
So, in this code just replace name your model entity.
Make a foreach razor loop within javascript :
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#calendar').fullCalendar({
theme: true,
header: {left: 'prev,next today',center: 'title',right: 'month,agendaWeek,agendaDay'},
editable: true,
events: [
#
{
bool isFirst = true;
}
#foreach(var m in Model)
{
if(!isFirst)
{
#:,
}
#:{title: #m.Tache_description, ...<other properties here>}
isFirst = false;
}
]
});
For title, you can do title = "#Tache_description"
Not sure about the format/type of your Begin_date and End_date, you may need some function to read the date into a javascript format. Shouldnt be that hard.
Loop through each element and add the elements to the events array. It is something like...
events = new Array()
#foreach(tache in list){
item = { blah : blah, blah : blah };
events.push(item);
}
for each c# item in this c# list, write these lines of javascript. You may end up with a very long javascript code block, but it should do the trick. Above is pseudocode.
To add to Darin's answer: If you need the server-side variables in an external JavaScript file, take a look this blog post: Generating External JavaScript Files Using Partial Razor Views
1: if your model is expecting the list of Tache then you have the whole list you can manipulate.
2: you can get the data using jquery ajax as json data by calling your action Get_List_Tache().
Assuming this javascript is inline in your page you could do the following:
#model IList<Tache>
<script type="text/javascript">
var events = #Html.Raw(Json.Encode(Model.Select(x => new { title = x.Description, start = x.Begin.ToString("o"), end = x.End.ToString("o") })));
$('#calendar').fullCalendar({
theme: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
events: events
});
</script>
This example assumes that your Tache model has properties Description, Begin and End:
public class Tache
{
public string Description { get; set; }
public DateTime Begin { get; set; }
public DateTime End { get; set; }
}
And if this script is in a separate javascript file you could still set a global events variable in your view which will later be used by your script. Alternatively you could fetch this model using an AJAX call.
I am using GeckoFX16 and xulrunner-16.0.2.en-US.win32 in my project.
The thing is, I want to call a C# method in javascript.
I am curious, is there a way to do this?
Just like below:
C# part:
private GeckoWebBrowser weBrowser;
public browser()
{
InitializeComponent();
Gecko.Xpcom.Initialize("xulrunner");
weBrowser = new GeckoWebBrowser();
weBrowser.Parent = this;
weBrowser.Dock = DockStyle.Fill;
weBrowser.Navigate("test.html");
}
public string loadData(){
//load data from local file.
return str;
}
javascript part:
<script type='text/javascript'>
var data = window.loadData();
alert(data);
</script>
I am new in this area, I’ll appreciate if it is possible!
Important update:
Currently code with event.initMessageEvent does not work because this construction has been replaced on
var event = new MessageEvent('yourEventName', { 'view': window, 'bubbles': false, 'cancelable': false, 'data': 'some data' });
You can use a MessageEvent to invoke code in c#, but as far as I know you can't then return a string like you're wanting to. One of the unit tests demonstrates how to invoke the c# code:
[Test]
public void AddEventListener_JScriptFiresEvent_ListenerIsCalledWithMessage()
{
string payload = null;
browser.AddMessageEventListener("callMe", ((string p) => payload = p));
browser.LoadHtml(
#"<!DOCTYPE html>
<html><head>
<script type='text/javascript'>
window.onload= function() {
event = document.createEvent('MessageEvent');
var origin = window.location.protocol + '//' + window.location.host;
event.initMessageEvent ('callMe', true, true, 'some data', origin, 1234, window, null);
document.dispatchEvent (event);
}
</script>
</head><body></body></html>");
browser.NavigateFinishedNotifier.BlockUntilNavigationFinished();
Assert.AreEqual("some data", payload);
}
I know it's awkward, but you could then use a c#-->javascript call to get data back to javascript-land. See This Question for how to do that. So your javascript would first send this message to c# land, then it would get a callback with the string value you need.
Hope that helps.
You can add message event listener to your web browser and call your method like this:
private void load()
{
browser.AddMessageEventListener("myFunction", ((string s) => this.showMessage(s)));
browser.LoadHtml
(
#"<!DOCTYPE html>
<html><head>
<meta http-equiv=""Content-Type"" content=""text/html; charset=UTF-8"">
<script type=""text/javascript"">
function fireEvent(name, data)
{
event = document.createEvent('MessageEvent');
event.initMessageEvent(name, false, false, data, null, null, null, null);
document.dispatchEvent(event);
}
</script>
</head>
<body>
<input type=""button"" onclick=""fireEvent('myFunction', 'some data');"" value=""SHOW DATA"" />
</body></html>"
);
}
...
private void showMessage(string s)
{
MessageBox.Show(s);
}
Now you can add more msg events to your msg listener (if you need to) and fire them all in the same way.
I am using select2 library for replacing select boxes. I rearranged example 7 that you can find on Select2 library page (scroll down with id
$("#e7").select2 etc...). I made my own generic handler that return serialized json data:
GetData.asxh view :
public class GetData : IHttpHandler
{
public bool IsReusable
{
get
{
return false;
}
}
public class RecipesList
{
public int total { get; set; }
public List<TopRecipeTable> recipes { get; set; }
public RecipesList() { }
public RecipesList(int total, List<TopRecipeTable> recipes)
{
this.total = total;
this.recipes = recipes;
}
}
private string GenerateJsonSerializedObject(int languageId, string orderBy)
{
RecipesList recipeList = new RecipesList(15, DBDataBase.GetTopRecipesByNumberOfRecipes(languageId, 15));
return new JavaScriptSerializer().Serialize(recipeList);
}
public void ProcessRequest(HttpContext context)
{
int languageId;
bool languageParsed = int.TryParse(context.Request["languageId"], out languageId);
string orderBy = (string)context.Request["orderBy"];
if (languageParsed && orderBy != string.Empty)
{enter code here
context.Response.ContentType = "application/json";
var jsonValue = GenerateJsonSerializedObject(languageId, orderBy);
context.Response.Write(jsonValue);
}
}
This generic handler returns the right format of json (I checked it with this URL ). My result (json) is also the same as the one in example on above mentioned page. But after this jquery doesn`t fire anymore.
My script :
$(document).ready(function () {
$("#e8").select2({
placeholder: "Search for a recipe",
//minimumInputLength: 1,
ajax: {
url: "/Handlers/GetData.ashx",
dataType: 'jsonp',
data: function (term, page) {
return {
languageId: 1,
orderBy: "TA"
};
},
results: function (data, page) {
alert(data.total);
var more = (page * 10) < data.total; // whether or not there are more results available
// notice we return the value of more so Select2 knows if more results can be loaded
return { results: data.recipes, more: more };
}
},
formatResult: movieFormatResult, // omitted for brevity, see the source of this page
formatSelection: movieFormatSelection, // omitted for brevity, see the source of this page
dropdownCssClass: "bigdrop", // apply css that makes the dropdown taller
escapeMarkup: function (m) { return m; } // we do not want to escape markup since we are displaying html in results
});
});
I tried to write the same alert(data.total) in the original example and it worked but not in my version. So I have the right json format, the jquery calls my generic handler and also recieved parameters languageId ... and also return the right json format but than nothing. I don't know if I am missing something here, because I am sure that this thing could also work with a generic handler as well. I hope I gave enough information about my problem.
I can also add my result in jquery .ajax error handler :
xhr.status = 200
ajaxOptions = parsererror
horwnError = SyntaxError : invalid label
If this is any helpful information
This question is quite old, so pretty sure you have a solution by now...but:
Remove all of these functions:
formatResult: movieFormatResult
formatSelection: movieFormatSelection
dropdownCssClass: ...
escapeMarkup:....
You did not provide those functions to format your data did you? All of those are only needed if you are making a custom drop down of items.
You are returning data.recipes - that needs to be an array of {Text:"", Id:""} or you need to build it from what you return right there.
First, get it working with just a very basic list with very basic data...then go from there.
Additionally, when you get that working try using WebApi or ServiceStack to handle your data instead of an IHttpHandler.
I'm working through a SignalR demo that displays database info in a list when a button is hit.
My Hub has 2 functions: One to remove DB objects from a list, and one to re-add DB objects to that list.
These functions are performed in my View and perform great when I only have the page open once. But if I open the page in another tab (can be the same browser or a different one), the pages do not stay in sync.
Meaning, when one page's button is hit, the other page is not displaying the data correctly.
Often times one page will do fine, while the other will perform the remove but not the add! It's mind-boggling. They should just be reflections of each other from my understanding.
Has anyone else run into something similar?
Thanks in advance for any help!
Here's my Hub :
[HubName("hubtest")]
public class HubTest : Hub
{
CmsContext db = new CmsContext();
public void showdata()
{
var f = from x in db.Data
select x;
Clients.remove();
Clients.add(f);
}
}
And here's the javascript in my View for the functions:
<script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-0.5.2.min.js" type="text/javascript"></script>
<script src="/signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
var hubtest = $.connection.hubtest;
hubtest.remove = function () {
//clear list of any prior values
var list = document.getElementById('dataList');
while (list.hasChildNodes()) {
list.removeChild(list.childNodes[0])
}
};
hubtest.add = function (data) {
//populate with updated values
for (var i = 0; i < data.length; i++) {
var element = data[i];
$('#dataList').append('<li>' + element.Question + '</li>');
}
};
$("#broadcast").click(function () {
hubtest.showdata();
});
// Start the connection
$.connection.hub.start();
});
</script>
<input type="button" id="broadcast" value="broadcast" />
<ul id="dataList">
</ul>
Try this instead:
<script type="text/javascript">
$(function () {
var hubtest = $.connection.hubtest;
hubtest.add = function (data) {
//clear the values first.
var list = $('#dataList');
list.empty();
//populate with new values
for (var i = 0; i < data.length; i++) {
var element = data[i];
list.append('<li>' + element.Question + '</li>');
}
};
$("#broadcast").click(function () {
hubtest.showdata();
});
// Start the connection
$.connection.hub.start();
});
</script>
And this:
[HubName("hubtest")]
public class HubTest : Hub
{
TestDatabaseEntities db = new TestDatabaseEntities();
public void showdata()
{
var f = from x in db.FAQs
select x;
Clients.add(f);
}
}
First of all thanks for your replies. I really appreciate your feedback!
I eventually got it to where my pages are staying in sync when open in multiple tabs by altering how my data is sent to the View.
Where I was performing the for loop in my Javascript to display each piece of data, now I am doing that in my Hub like so:
[HubName("hubtest")]
public class HubTest : Hub
{
CmsContext db = new CmsContext();
public void showdata()
{
Clients.clearlist();
var faqs = from x in db.Faqs
select x;
foreach (Faq faq in faqs)
{
Clients.add(faq.Question.ToString());
}
}
}
Then my Javascript is just appending that FAQ question to the list:
$(function () {
var hubtest = $.connection.hubtest;
hubtest.clearlist = function () {
var list = $('#datalist');
list.empty();
};
hubtest.add = function (data) {
$('#datalist').append('<li>' + data + '</li>');
};
$("#broadcast").click(function () {
hubtest.showdata();
});
// Start the connection
$.connection.hub.start();
});
Sending just a simple string of my data to be printed individually seems to allow my page to stay in sync.
Before the data I was sending was a list of DB objects and my Javascript was looping through each and adding that object's Question column to the list. Not sure why this was such an issue - especially since it would work on one open tab but not all open tabs - but that simple change fixed my site sync issues.
Thanks again!