jQuery Mobile and MVC3 auto submit - javascript

The following code works perfectly if I take jQuery Mobile out of the question!
The form:
#using (Html.BeginForm("SearchTown", "Home", FormMethod.Post, new { id = "TheForm1" }))
{
#Html.DropDownList("TownID", (SelectList)ViewBag.TownId, "Select a Town")
}
The Javascript:
<script type="text/javascript">
$(function () {
$("#TownID").live('change', function () {
//$("#TownID").change(function () {
var actionUrl = $('#TheForm1').attr('action') + '/' + $('#TownID').val();
$('#TheForm1').attr('action', actionUrl);
$('#TheForm1').submit();
});
});
</script>
But if I wrap jQuery Mobile around the site, then every time I submit the form, in my log only it tacks the ID field again and again to the end of the URL string. This only happens in my log, not in the browser. In the browser it still looks like it’s doing the right thing! E.g..
www.mysite.com/Home/SearchTown/2 the first time
www.mysite.com/Home/SearchTown/2/2 the second time
www.mysite.com/Home/SearchTown/2/2/2 the third time
But in the browser it still looks correct www.mysite.com/Home/SearchTown/2
Why is jQuery Mobile doing this?

This is most likely happening because each time you POST the form, it uses AJAX to load the response and the loaded page has repeated element IDs in it.
I'm guessing here, but based on what you described it sounds like your form posts back to a page with the same form markup on it. Each time your form post renders the next page you'll get another #TheForm1 added to your DOM (as jQuery Mobile keeps previously loaded pages in the DOM and simply swaps between active data-role="page" elements). Due to this behavior, once you have more than one #TheForm1 on the page, the selector $('#TheForm') will only ever return the first element in the DOM matching that ID- which will be the form which you posted the very first time. Thus, each time you you post, your code will use the action attribute of the form element you modified originally- which is why you see multiple values appended to the URL.
In jQuery Mobile it is almost always better to identify elements using a class name and the active page as the container, as you never know how many times an ID might be repeated in the DOM across multiple page changes. So, instead of using $('#TheForm1'), assign a class name and use that in conjunction with $.mobile.activePage: $('.Form1', $.mobile.activePage). (The same goes for your select box).
As an alternative, you can tell jQuery Mobile to not enhance your form by adding data-ajax="false" to the form tag. This will cause it to behave like a normal full page postback without any AJAX.
Edit
The point I am making in paragraph 3 is that you need to make sure you're always selecting the correct form element for the currently visible page, rather than unintentionally returning one which is hidden from view. The $.mobile.activePage global variable will give you the context of the currently visible page, and then a class-based selector (rather than Id-based) will ensure that the correct form element is retrieved in the change handler. Something like this:
<form class="town-form" action="#">
<select class="town-selector">
<option value="1">Town A</option>
<option value="2">Town B</option>
<option value="3">Town C</option>
</select>
</form>
<script type="text/javascript">
$(function () {
$(".town-selector").live('change', function () {
var form = $('.town-form', $.mobile.activePage);
var actionUrl = form.attr('action') + '/' + $(this).val();
form.attr('action', actionUrl);
alert('submitting to: ' + form.attr('action'));
form.submit();
});
});
</script>

because you are submitting the hole page and jQuery mobile does not fancy such thing, and after each POST it just appends the ID into the document.location... I have learned that in some mobile projects...
instead of this line $('#TheForm1').submit(); do something like this:
var url = $('#TheForm1').attr('action') + '/' + $('#TownID').val();
$.post(url, $('#TheForm1').serialize(), function(data) {
// do something with data if you send back something...
// or just change page with jQuery Mobile API
});
return false;

Iv'e left this one up long enough and no one has an answer!

Related

With select2, how to access the original select/input element after it's been processed?

I'm using a combination of JQuery EasyUI and Select2 to be able to drag options from a right panel, onto a left select box.
In the original HTML, the select boxes are empty, and I only "add" anything to them if I drop an option on them,
<form id="section1">
<select class="select2" class="drop_target" id="selected_options" name="selected_options"></select>
<div>
<div class="draggable_option" data-id="1234">1234</div>
</div>
</form>
<form id="section2">
<select class="select2" class="drop_target"></select>
<div>
<div class="draggable_option" data-id="1235" id="selected_options" name="selected_options">1235</div>
</div>
</form>
Then in javascript, I do something like this,
$('.drop_target').droppable({
accept: '.draggable_option',
onDrop:function(e, source){
var $dragged_source = $(source);
var $drop_target = $(this);
}
});
The problem comes at this point, if you're dynamically adding things to the select, you have to check it doesn't exist, and if it doesn't, you create a new option, and add it,
var new_option = {
id: $drag_source.data('id'), data_id: $drag_source.data('id'),
text: $drag_source.val(), selected: true};
// Set the value, creating a new option if necessary
if (!$drop_target.find("option[value='" + new_option.id + "']").length) {
// Append it to the select
$drop_target.append(new Option(
new_option.text, new_option.id, true, true)).trigger('change');
}
var data = $drop_target.select2('data');
$drop_target.select2('data', data.concat([new_option]));
Clear as mud? Unfortunately it goes wrong at this point. While all calls to .select2 from $drop_target work as expected, this is not the select that was originally in the HTML, this is a div that select2 created, after hiding the original select, with an id attribute like id="s2id_selected_options". So when we append the new option to it, it doesn't get added to the select, and gets added to select2's div incorrectly instead.
My HTML pseudocode is deliberately set up in this "obtuse" way, because my page is like that. I have multiple forms, and multiple "identical" selects in those forms, generated by WTForms. So the "general" method of selecting your select by id, $('#selected_options') doesn't work correctly.
What I need to do, within the javascript, is gain access directly to the original, now hidden, select, and I can't access it via id.
When you have access to one of the elements that's "associated" with the generated by select2, you can access meta information for it via .data('select2'), or in this instance,
$(this).data('select2');
In here, there's loads of metadata that select2 uses (which you can see if you browse the source). For this question, to get the original select or input element, you can use,
var $drop_target = $(this).data('select2').opts.element;
Whether you're using a select, or an input, this gives you a jQuery element linking to it. If you're using a select, and are only interested in that, you can use the shorter option,
var $drop_target = $(this).data('select2').select;
This may be in the docs somewhere, but I was unable to find it, and I'm also not able to find it by searching now, because searching the docs for "data" and "select2" returns a result for nearly every page of their docs (hence the reason I'm answering this question myself, to hopefully save others the trouble).

Using .get() and .find()/.filter() to show only a specific div from a html page search result

I have a search bar on a page (/Search), & when the user searches for something, it will run a filter on the input text and refresh the page with the filtered results.
If someone searched the word "banana", the URL of the search results will be
/Search?searchBoxText=banana
I'm trying to make that happen without refreshing the page.
In site.js is:
$(function () {
$("#searchBox").keyup(function (e) {
var searchBoxText= $("#searchBox").val();
$.get("/Search?searchBoxText=" + searchBoxText, function (getHtml) {
$("#resultsDiv").html(getHtml);
});
});
});
The problem is that it displays the whole body of the page in #resultsDiv and I want it to just display #resultsDiv. So it displays the header, search bar & button again.
Essentially I want to display the new results (which would be in #resultsDiv) in the old #resultsDiv but I can't seem to constrain the .get() to only get a specific element from the resulting page.
I tried to do
$.get("/Search?searchBoxText=" + searchBoxText + " #resultsDiv", function (getHtml)
$("#resultsDiv").html(getHtml).find("#resultsDiv");
And other alterations like that but nothing seemed to work.
You can do:
$("#resultsDiv").html($(getHtml).find("#resultsDiv").html());
However, this is not the best way. Your call to /Search? should return only the HTML code of the page section that you want to update. This should be done server-side (you didn't say how you are returning the result, so I cannot help you about that).

jQuery: show html elements when a disabled select menu is loaded

In my application users can edit information for their reservation but I don't want them to change the type of reservation. So I have thought to load a page with a select menu displaying the type of reservation but it is also disabled. What I would like to happen is that on page load if the select menu is disabled then the relative elements are showed according to the selected but disabled type. Reading the documentation this is what I have thought I need:
jQuery("#tipologia_piazzola").load(function(){
alert("something");
if (this.value == "mensile" && this.is(":disabled")) {
jQuery(".both").show();
jQuery(".mensile").show();
jQuery(".giornaliera").hide();
}
});
Obviously I have inserted it inside the ready function but neither the alert nor the html elements appear. Is this the correct way? Or, how can I reach my goal?
You need to use jQuery(this) instead of this to call is(':disabled') function because it need jQuery object and not javascript object. Also use document.ready as shown below to ensure that all DOM element is ready.
jQuery(document).ready(function(){
var $this = jQuery('#tipologia_piazzola');
if ($this.val() == "mensile" && $this.is(":disabled")) {
jQuery(".both").show();
jQuery(".mensile").show();
jQuery(".giornaliera").hide();
}
});
NOTE : - please exclude document.ready if you have it already and put above code in your existing document.ready

Couldn't pass value to textbox for more than one time without refreshing the page using Javascript

When i pass a value to textbox using Javascript it is working fine for the first time before updating data, after the update table will be refreshed. Then I couldn't pass value to textbox in the same way, but its working if I refresh the browser.
<div id="div_for_values">Edit</div>
$(function(){
$("#div_for_values a").click(function(){
var key_id = $(this).attr("key_id");
var key_value = $(this).attr("key_value");
$('#txt_name_id').val(key_id);
$('#txt_name').val(key_value);
return false;
})
});
This line only parsed before page load.
<div id="div_for_values">Edit</div>
The browser will only see this:
<div id="div_for_values">Edit</div>
You might want to use some ajax calls to insert fresh data into your fields.

Change Text Field Once Drop Down Has Been Selected (Multiple forms on 1 page)

I'm looking to change the value of a <p> tag once an option from a drop down has been selected. I have that working but my issue is I am going to have lots of forms on one page and feel like I am repeating my code. Is there a way to do this with a function for example? To save me writing a new section of javascript everytime a form gets added to my page?
My javascript code:
$('.orderProduct select#packageOption').change(function(){
$('#packagePrice').html($(this).val());
});
$('.orderProduct2 select#packageOption').change(function(){
$('#packagePrice2').html($(this).val());
});
Thanks.
Add a data-element-id attribute to each select like:
<select data-element-id="packagePrice">...</select>
<select data-element-id="packagePrice2">...</select>
then you simply need this jQuery code:
$('select[data-element-id]').change(function(){
var $this = $(this);
var id = $this.data('element-id');
$('#' + id).html($this.val());
});
If you want to avoid the extra attribute you could use jQuery's DOM traversing functions, to locate which p you should update.

Categories