I have a collection of AccordionPanes containing various TextBox controls and DropDownLists, each with their own validators.
If a few server-side validations occur on form submit, is there something that can automatically expand a previously minimized pane that contains the invalid validator message? Otherwise, it will seem to the user that the form isn't submittable without reason.
Another scenario: Let's say I have multiple panes with client side validators tied to the inputs. If a pane is minimized (and therefore you can't see the validator's ErrorMessage), is there a way to expand the appropriate pane when the AJAX page validation occurs on submit?
I know there's a brute-force way to this approach, where I keep track of every validator and their associated AccordionPane, but I was hoping for a better solution that can handle my situation for a large number of inputs/validators and panes.
How about something like this (using JQuery but I'm sure it can be converted into plain javascript)...
$(document).ready(function(){
if (isPostback()){
$.each(Page_Validators, function(index, validator) {
if (!validator.isvalid) {
// do something here to locate the accordion based on the validator
// $(this) is the currently invalid validator element as a jquery object/wrapped set
// so for example...
$(this).parent().slideDown();
// This assumes that the immediate parent of of the validator is the accordion which is unlikely but if you post your emitted html I can write the appropriate selector for you.
}
});
}
});
Because you dont want it to fire on initial load you can use a technique like this How to detect/track postback in javascript? and check if you are in a postback after the document.ready - I have assumed you've used the advice in the link and your function for postback detection is called isPostback().
there is a project built for this issue try to take a look at it....you can also download the source to analysis more details or use the same code-base if you want....http://www.codeproject.com/Articles/43397/Validating-Accordion-and-RadPanelBar-using-Ajax-an
Rich beat me to it, but here's the vanilla js version (ie9+):
Page_Validators
.filter(function(v) { return !v.isvalid; })
.forEach(function (v) { console.log(v.parentNode); });
Remember to place the code beneath the </form>-tag. I've had issues with using jQuerys document.ready and window.onload, since it might execute the code before all the needed JavaScript from asp.net is loaded.
Update: A more browser compatible version
for(var i = 0; i < Page_Validators.length; i++) {
var validator = Page_Validators[i];
if (!validator.isvalid) {
console.log(validator.parentNode);
}
}
Related
I'm trying (and failing) to make an ajax process work when people leave a form input field. I need it to happen for each input field, of any type, on the form.
I'm trying to modify the following (which does work):
$("document").ready(function() {
$("#getcontent").click(getContent);
});
function getContent() {
$("#example").load("sampletextcontent.txt");
}
(there would be a button with id="getcontent" in the html, and a div with id="example" also in the html. When button clicked, contents of external file sampletextcontent.txt is displayed within said div)
jquery IS being used, version 2.0.3 jquery.min.js
So I am trying (and this is where I am failing) is to convert the above to become:
$("document").ready(function() {
$("#input_1_1").onblur(doSend);
$("#input_1_2").onblur(doSend);
$("#input_1_3").onblur(doSend);
$("#input_1_4").onblur(doSend);
$("#input_1_5").onblur(doSend); // etc for as many fields there are
})
function doSend() {
// Do some ajax stuff to send the entire value of all form fields in here
}
But it does not seem to like the concept of using the replacement of the ".click" to ".onblur" here. Why is this? Isn't onblur a valid JS function/item?
Sorry I'm not a JS guru, I have great problems understanding JS.
C
Edit - sorry I was not clear about the code I am trying to get working. There is no button in the version I want to work, it's just wanting to trigger by when a user clicks/tabs away from each input field. Sorry about not making that clear before.
For dynamic jQuery event binding, I would try switching out the .click and .blur functions with the .on function.
As an example, I would try the following:
$('body').on('click', '#getcontent', function(){
DoSomething();
});
and
$('body').on('blur', '#input_1_1', function(){
DoSomething();
});
The documentation for the on function can be found http://api.jquery.com/on/.
Here is another Stack Overflow article that also explains this: Event binding on dynamically created elements?.
Thanks to the comments and answer attempts. However the answer that I'm using, that actually does answer the specific question is the following. Simply change:
$("document").ready(function() {
$("#input_1_1").onblur(doSend);
$("#input_1_2").onblur(doSend);
$("#input_1_3").onblur(doSend);
$("#input_1_4").onblur(doSend);
$("#input_1_5").onblur(doSend); // etc for as many fields there are
})
To become:
$("document").ready(function() {
$("#input_1_1").blur(doSend);
$("#input_1_2").blur(doSend);
$("#input_1_3").blur(doSend);
$("#input_1_4").blur(doSend);
$("#input_1_5").blur(doSend); // etc for as many fields there are
})
And it works. This retains the ability to call different functions per field if I so wish, and is very straightforward for a JS novice like me to work with.
A better cleaner solution may be implemented later, but for now this will do and directly answers the original question.
This is a jquery question, and since I am working with WordPress and options framework in the admin panel, I have to hide certain options with a checkbox. The problem is one of the elements is a dropdown menu and it seems that I cannot hide it at the beginning (meaning if I click twice the dropdown disappears as it should) although the code works for the text input. Here is the code:
jQuery('#telephone_hidden').click(function() {
if (jQuery('#telephone_hidden').attr('checked') ? true : false) {
jQuery('#section-telephone_dropdown_icons, #section-telephone_number_hidden').show();
} else {
jQuery('#section-telephone_dropdown_icons, #section-telephone_number_hidden').fadeToggle(400);
}
});
I am not very good with jQuery but I think that this should work, or at least there is a better way to do this.
An if statement with a ternary statement ... not going to work. Try this:
if (jQuery('#telephone_hidden').prop('checked')){
jQuery('#section-telephone_dropdown_icons, #section-telephone_number_hidden').show();
} else {
jQuery('#section-telephone_dropdown_icons, #section-telephone_number_hidden').fadeToggle(400);
}
The .prop('checked') returns a boolean, which I think is what you want to validate. Also, there really isn't a need to use jQuery if you properly set up your libraries to not conflict. You can consolidate it to:
if ($('#telephone_hidden').prop('checked')){
$('#section-telephone_dropdown_icons, #section-telephone_number_hidden').show();
} else {
$('#section-telephone_dropdown_icons, #section-telephone_number_hidden').fadeToggle(400);
}
This doesn't seem like much, but over an entire script file you reduce its size and therefore improve its performance. Depending on how big your file is, it can have a huge impact.
Also, noticed you were using the .click event for $('#telephone_hidden'), so rather than query the DOM again, try this:
var $tel = $('#section-telephone_dropdown_icons, #section-telephone_number_hidden');
$('#telephone_hidden').on('click',function() {
if ($(this).prop('checked')){
$tel.show();
} else {
$tel.fadeToggle(400);
}
});
The use of $(this) prevents needing to query the DOM for the selector again, and I cache the selector used for the show / fadeToggle, providing another performance boost.
I know this is a long answer, but I figured if I showed the step-by-step process of improvement you could learn and apply it to future jQuery endeavors.
Try .is()
if (jQuery('#telephone_hidden').is(':checked')) {
or .prop
if (jQuery('#telephone_hidden').prop('checked')){
You can use the is function in conjunction with the checked selector, like so:
if ($('#telephone_hidden').is(':checked')) {
// ... do something
}
I have the following problem.
To translate a website, I'm using the jQuery Localize plugin.
This works fine. However, I want a CSS styled selectbox with flags and languages, and when a different option is selected the call to $("[data-localize]").localize("example", { language: $(this).attr('value') should be made to translate the page.
This code I'm currenly using, and it works fine for a plain, not-styled selectbox.
<script type="text/javascript">
$(function() {
$('#polyglot-language-options').change(function() {
if ($(this).attr('value') == "en") {
$("[data-localize]").localize("example", {
language: $(this).attr('value')
});
}
else if ($(this).attr('value') == "nl") {
location.reload();
}
});
});
</script>
But I want to style it, so I tried to integrate the "polyglot" language switcher. However, the current code doesn't work.
How can I integrate the $("[data.localize]").localize(); function in this code:
$('#polyglotLanguageSwitcher').polyglotLanguageSwitcher({
effect: 'fade'
});
This plugin (source code) does not follow the guidelines for jQuery plugin design. The bugs I found quickly:
It does not allow chaining, because it does not return this
It works only on one element at a time (does not use each())
It has a queer element hierarchy. It seems to require an element with an id, containing a form containing a select (as in the demo). In my opinion, such a plugin should be called on the language select element only.
It seems to navigate automatically, wanting to be configured with the page structure. Each of the li items in that fancy box contains a link to the respective page.
Therefore, it does neither trigger the form it live in or fire the change event you want to listen to.
As it stands, you can't use this particular plugin as you want to. If you want to fix all the bugs, I wish you a happy time :-) Nonetheless it might be possible to manipulate the plugin code, to let you register callbacks on select events (where you can invoke the localisation plugin). Otherwise, you will need to choose an other select plugin (or build one yourself from scratch, adapting the existing code)
I have an app built using jQuery (and using various jQuery-UI tools).
For some reason, i have to port it to smartphones/tablet computer, and decided to use jQuery Mobile for that (in order to minimize the number of changes).
In my vanilla app, I created some elements of the page on the fly, depending of user interactions.
For example a slider could be created like that (p is an object with a bunch of params):
function createSlider(p){
return $("<div/>",{
"id":p.id,
"class":p.divClass,
}).slider({
"orientation": p.align,
"min":p.constraint.min,
"max":p.constraint.max,
"step":p.step,
"value":p.curVal,
"animate":"normal"
/*and some event handling here, but it doesn't matter*/
});
}
And it will produce a nice looking slider. Now it looks like:
function createSlider(p){
return $("<range/>",{
"id":p.id,
"class":p.divClass,
"min":p.constraint.min,
"max":p.constraint.max,
"step":p.step,
"value":p.curVal,
});
}
But as it's created on the fly, all the stuff done by jQuery Mobile on the page load isn't done on it.
Is there a way to force that initialization without writing the slider in the html?
Thanks.
EDIT: I found in the doc that it could be achieved using container.trigger("create");
However this does not work yet.
EDIT2: Ok create was the solution.
According to the documentation (see edit in the question), using trigger("create") on the containing element works.
And to make that work, you also need to remember that range is an input type and not a tag...
Working solution:
function createSlider(){
return $("<input/>",{
"type":"range",
"id":"sl",
"min":0,
"max":15,
"step":1,
"value":1,
});
}
function appendSlider(){
$("#yourdiv").append(createSlider()).trigger("create");
}
As a sidenote, the documentation for jQuery mobile lacks a search option.
Try calling .page() on the container the content is being added to. Alternatively, adding .page() to the content you're returning may also work.
Is it possible to mix the concept of Unobtrusive JavaScript with the event model of ASP.Net?
ASP.NET makes it very difficult, as every server side control requires a postback via the __doPostback javascript function.
You can make sure you are not using any server side controls, but this means you loose most of the benefits of ASP.NET.
Another option is to override the OnRender event and output different controls/javascript, but this is also quite a lot of work and defeats the purpose of ASP.NET.
You have much greater control when using ASP.NET-MVC.
yes, to a point. discounting standard controls and how they are built, there's not much stopping your from offloading all your own javascript to a separate file. the big hangup that comes to mind is referencing myControl.ClientID to render an element id in the middle of a script block. with a little planning, you can still minimize the amount of script you have to render in the page to work around this.
I realize that this question has already been answered but for anybody surfing in, I somewhat disagree with the accepted answer.
It depends on what controls you are using.
Not all the controls require JavaScript. The biggest culprit for me was always LinkButton. A regular button control does not use JavaScript at all however. On my pages, I actually use regular buttons and use CSS and JavaScript to make them into LinkButtons. The first step is to use CSS to make them look like links. If you really want to get fancy, you can detach the button, add an HTML anchor, and associate all the event handlers for the button with the anchor. This means that a user without JavaScript sees a regular button (HTML input) that is styled with CSS. Anybody using JavaScript will see an HTML link (
Also, if you use JQuery, it is very easy to select ASP.NET elements without worrying about all the extra mumbo-jumbo that ASP.NET adds to the IDs.
Example:
<asp:Button id='theButton' text='Click here' cssclass='linkbutton' runat='server' />
You can select this individual button using JQuery:
var theButton = $("input[name$='theButton']");
You can also replace everything of class 'linkbutton' with HTML anchors:
$(function() {
var buttons = $(".linkbutton");
buttons.each(function() {
var button = $(this);
var id = button.attr('id');
/*
* If a link button is not working
* it is likely because it does not
* have an ID attribute - check that
*/
if (id)
{
var text = button.attr('value');
var cssclass = button.attr('class');
button
.before("<a id='"+id+"' class='"+cssclass+"' href=''>"+text+"</a>")
.hide()
.detach();
$("a[id='"+id+"']").live('click', function(event) {
$(this).after(button);
button.click();
event.preventDefault();
});
}
});
});
Things like GridViews are a bit more work but also doable. I found that, after the initial honeymoon, I avoided those kinds of controls and just used repeaters anyway. Repeaters do not impose any nasty JavaScript either.
Anyway, it is certainly possible to do unobtrusive JavaScript with ASP.NET WebForms.