Refresh the browser once on load or clear DOM - jquery-mobile

I have a dynamic MVC4, jQuery Mobile application that works for the most part quite well. I have an auto posting dropdown list that selects a list from the database via the following code.
<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>
<p>
#using (Html.BeginForm("SearchTown", "Home", FormMethod.Post, new { id = "TheForm1" }))
{
#Html.DropDownList("TownID", (SelectList)ViewBag.TownId, "Select a Town")
}
</p>
The problem is it only works properly the first time a search is performed unless I click refresh. I don’t think this has anything to do with MVC, I think the problem is with AJAX and jQuery Mobile.
Edit:
The first time I search www.mysite.com/Home/Search/2 yields a result and woks fine, but the second time something seems to be left behind in the DOM??? and it looks for:
www.mysite.com/Home/Search/2/2 also
I get 404 errors in my log and “Error Loading Page” but it still finds the results and displays the page correctly!
Then with a third search I get the error 404’s in my log and “Error Loading Page” but it has grown and now looks for:
www.mysite.com/Home/Search/2/2
www.mysite.com/Home/Search/2/2/2 also
This then continues to grow after every search until at some seemingly random point on each test, it seems to give up and I get error 505
Additional Edit:
The code works perfectly if I take jQuery Mobile out of the question
Can anyone tell me what might be going on here?

Get rid of: $(function () {
And replace it with: $(document).delegate('[data-role="page"]', 'pageinit', function () {
Please read the big yellow sections at the top of this page: http://jquerymobile.com/demos/1.1.0/docs/api/events.html
You can't rely on document.ready or any other event that only fires once per page. Instead you have to get used to using jQuery Mobile's custom page events like pageinit so your code will work no-matter when the page is added to the DOM (which you don't know when this will happen in a jQuery Mobile website). There are a ton of events, so again, please read the documentation I linked-to above.

Firstly, dynamically generated html using a server side templating engine blows. I really don't understand what value people see in it.
My guess is that it used to make sense 10 years ago before AJAX became popular, and has just hung in there ever since because people have this feeling that it is "the right way to do it". It isn't. ESPECIALLY for mobile web apps.
Secondly, it looks like you are trying to do pretty simple search. All this MVC4 garbage makes it difficult for you to see what is really happening though. You don't need to append parameters to your URL for a simple form submission like this. In fact your TownId should already be part of the POST data when you submit, so you can just remove the URL modification bit.
Alternatively, don't use a form submission, but just a GET and AJAX. I don't know what your app is doing here, but I imagine you want to display the results on the page dynamically somehow, so a GET is more than enough.
Use your developer browser tools (F12) to see what exactly is getting submitted when you do the submit - it really helps. And for your next project, abandon MVC4! "Well established design patterns" my foot.

I have been bothered by this problem for a long time
There are same select element in the DOM I think so...
and I used $('.SelectCSS:last').val()
It seen work well.
I come from China , English is poor...

I guess this is one for the future, MVC and jQuery Mobile don't seem to blend completely right now. Maybe MS's response to the issue is Single Page Applications!
SPA may satisfy Danial also?

Related

What kind of questions should be asked when choosing between straight MVC4 and a SPA framework like Durandal or Angular?

I'm in the middle of making this choice right now and I don't know what kinds of questions I should be asking. One that I believe is valid:
Do I need SEO / natively crawlable pages? If so, stick with MVC4.
One question that I'm not sure about is the impact on performance - I think this is valid:
Is initial load time very important? If so, stick with MVC4 (like stackoverflow).
What are some other questions that should be asked that can help point a developer in the right direction here?
PS - if this question is being asked in a way that doesn't meet quality standards, I'd appreciate any help modifying it so that it does.
I have been asked and had to be a part of decision making groups recently that made this same decision. Here is what was important for us -
How many of the devs that will be working are familiar with MVC4 vs Javascript?
How much is performance an issue? (Is single page app really necessary?)
How big is the data we will be working with? (Remember that extremely large data sets don't work well in a spa)
Durandal requires using a lot of different libraries - is it ok to have to learn each of the different usages? Each library is important in its own regard and you must know when and why to use each library.
Angular is very set in its ways and harder for a new javascript dev coming from c# and .net to understand, are you willing to provide time for learning?
Last, which browsers are you targeting? Ie6+ works great with mvc4 and durandal, angular needs some massaging.
Hope this is helpful!
Why not combine the best of both worlds? SPA and straight MVC!
I was also investigating a lot of time in durandal, sammyjs, angular frameworks. I then decided to go with sammy.js for just the routing. This way I could still make use of the easy MVC 4 razor view engine to generate my views at server side. Even though it would be more performant to generate your html and bindings at client side by using knockout, I felt more secure by doing this at the server side.
But then of course you have to deal with those hashbangs? Therefor I started to investigate more time into the history.js (or HTML 5 history API). And then things got clear to me.
My solution
What is the essential part of a SPA? Well, in fact, that your layout.cshtml is only loaded once right. From then on you you only want to load content from the server and display it in the main content div. Does it need to be json? No, in fact it does not.
By default MVC 4 controllers returns an html string. So what if your < a href="">< /a> tags would be intercepted by a simple jQuery script to get the html string from the controller and load it into a div.
I went even further and wrote my own jQuery engine on top of the HTML 5 history api. I just intercept every link that is clicked and load the content from its href attribute and then place it into the desired div. Further I push the URL with history api pushSate. Another big advantage of this approach is that your application is not broken when javascript is disabled or when HTML 5 is not supported.
My views have the following layout page:
#{
Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
}
This way when javascript is disabled or html 5 is not supported, the view will render inside the _Layout.cshtml.
This also allows for URL linking. The link will hit the address bar and will be routed to the controller. As this is not an ajax request, the view will render with _Layout.cshtml.
But once your _Layout.cshtml and javascript is loaded correctly and once, all < a href="">< /a> will be intercepted, loaded by AJAX (partial with layout = null) into the content div and the url is pushed on the address bar. So it seems that you are at that location, but in fact you are not. It's just an illusion to make things more responsive and efficient. Et voila, SPA in straight MVC.
The minimum routing code would be something like this
Interception of Links
$('.spalink').click(function () {
$.ajax({
url: this.href,
success: function (content) {
$('body>#content').css({ opacity: 0 });
$('body>#content').html(content);
$('body>#content').animate({ opacity: 1 }, 300, 'swing');
history.pushState({ state : 'spa' }, null, this.href);
}
});
return false;
});
BACK and FORWARD event
window.addEventListener("popstate", function (e) {
if (e.state != null) {
$.ajax({
url: location.href,
success: function(content) {
$('body>#content').css({ opacity: 0 });
$('body>#content').html(content);
$('body>#content').animate({ opacity: 1 }, 300, 'swing');
},
cache: false
});
return false;
}
});
return true;
}
PS: if you don't feel like writing your own SPA engine, take a look at history.js (it does the same out of the box)
Ajaxify on top of History.js on top of HTML 5 history API

Anchor link to open jquery mobile popups just redirects

I previously used javascript dialogs for confirmation on a mobile web app, but am now trying to switch over to using the new popups feature in JQM 1.2. My initial test doesn't work - no popup appears and I'm simply redirected to the anchor I'm trying to call.
My test code is simple, albeit a bit obfuscated because I'm using haml:
%a{:href => "#popupBasic", :"data-rel" => "popup"} Show popup
%div{:id => "popupBasic", :"data-role" => "popup"} Basic popup div
That said, I don't believe the haml is causing the issue based on reading the final HTML output. Both elements are at equal depth and contained within the element.
In addition, the div does "popup" without issue when I use the following at the console:
$( "#popupBasic" ).popup( "open" )
That makes me believe that the issue lies somewhere in the link or the URL handling. When I do click the link, it instead takes me straight to
http://localhost:3000/#popupBasic
Any ideas on how I should be handling the URL differently so that it shows the popup as intended?
After realizing the problem was probably some part of my Javascript, I went through and tried turning off each bit of javascript individually, until I figured out that the problem was with this in my application.js file:
$(document).bind("mobileinit", function(){
$.mobile.linkBindingEnabled = false;
});
which prevents all anchor click handling. Obviously now that I've removed this code the anchor links are working properly. Of course, that means I'm now left with trying to figure out why I added that in the first place and what I just broke by removing it...

In a Rails app, how can I make a link load in a div as opposed to refreshing the whole page?

I'm still a beginner at web development. It's not my profession. So go easy.
I started building a rails app today, and realized it would make my application so much better if I could get certain links to display in a separate div instead of a new page, or refreshing the entire page. I'm not quite sure how to search for this, and I keep chasing red herrings with google.
Basically, I have a list in a div on the left side of the page, and when one item from that list is clicked, it should appear in the right div. (Nothing else on the page need be changed)
That's really as simple as it is. Do I need to use Javascript for this? Can I get away with the rails js defaults, or should I be using JQuery?
Is there a way to do this without javascript? I really just need a push in the right direction here, I'm tired of not even knowing how to search for this, or what documentation I should be reading.
Like I said, go easy, and you should just go ahead and err to the side of caution, and assume I know nothing. Seriously. :)
Thanks in advance,
-Kevin
(By the way, I'm developing with Rails 3)
Create your views (along with controllers) to be shown inside the div for each item on the left menu. Lets say we have the following structure now:
Item1 (Clicking on it will fetch:
http://myapp.com/item1)
Item2 (Clicking on it will fetch:
http://myapp.com/item2)
and so on...
make sure you only render the html to be put inside your content div. Should not include <head> <body> etc. tags
In your main page you may have your markup like this >
<div id="leftMenu">
Item 1
Item 2
</div>
<div id="content">
Please click on an item on the left menu to load content here
</div>
Finally, add the following Javascript (you'll need jQuery; trust me it's a good decision).
$("#leftMenu a").click(function () {
$("#content").load($(this).attr("href")); //load html from the url and put it in the #content element
return false; //prevent the default href action
});
You will need JavaScript if you want to avoid reloading the page. You can use link_to for links in your lists, and you'll need to use :remote => true to make it send AJAX requests to the server. The server will need to respond appropriately and supply HTML for your div.
link_to documentation is here: http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to (and admittedly it isn't very useful for AJAX functionality).
The last post in this thread shows one possible solution you could use.

ASP.NET MVC and Ajax slow?

I've just started out trying MVC 2 and Ajax, and I'm wondering if I'm doing something wrong, because I was under the impression that Ajax would make changes in a webpage very fast. The example I have is with the Ajax actionlink:
<div>
<%: Ajax.ActionLink("Dita", "AjaxView", new AjaxOptions { UpdateTargetId = "myDiv" })%>
</div>
<div id="myDiv">
Change this text</div>
And the Action method:
public ActionResult AjaxView(string id)
{
return Content("Text changed!"); ;
}
This is a rather short simple text string, and still it takes about 1-2 seconds before the text shows up. Maybe ajax isn't supposed to do what I thought it would, but I was thinking I could use it for instant previews of text and images sort of like a rollover function (by the way I was wondering if the actionlink can be set to invoke the action method on mouseover rather than click?)
Is it normal that it is this slow or am I missing something?
It might be an IPv6 DNS resolution issue with FF and Chrome when working with localhost. Fixes described here:
Firefox and Chrome slow on localhost; known fix doesn't work on Windows 7
and here
https://superuser.com/questions/174715/is-there-a-way-to-disable-ipv6-in-googles-chrome
I would try in IE and Opera first to check if it works faster.
Note: if that's actually the problem, this has nothing to do with AJAX.
I think you've misunderstood slightly.. There is nothing about AJAX that will necessarily make your Web application faster. What AJAX does is to only load the information you need instead of loading the entire page over again. That way you can make subtle changes to the page you're viewing without having to refresh the entire page.
The point being - when you call AjaxView it still has to do a call back to the server which will take time no matter what you do. The reason why this action is slow might rely on different factors;
- Your server might be busy doing something else, hence consuming resources
- You just built the assembly, making the call slower the first time around

Changing the hash but not moving the page using jquery ui tabs

I added the following code to change the hash to the tab name:
$("#tabs > ul").tabs({
select: function(event, ui){
window.location.hash = ui.tab.hash;
}
} );
This works fine in FF3 but in IE7 it moves down the page (depending on the tab selected anywhere from somewhere near the top of the page all the way down to the very end of the page).
I tried changing it to:
$("#tabs > ul").tabs();
$("#tabs > ul").bind("tabsshow", function(event, ui) {
window.location = ui.tab.hash;
})
This leads to identical behavior in both IE7 and FF3, which moves the page down to the top of the selected tab.
I would like the tab to be changed, the hash to be updated, but the page not moved at all, which is how it works in FF3 in my first example, but not in IE7.
Thanks.
Notes: JQuery 1.3.1 / JQuery-UI 1.6rc6
If there's an element on the page that has the same id as what you're setting the hash to, for instance you're trying to set the browser hash to #cars and there's already a div#cars on the page, the browser will scroll you down to where that div is.
To my knowledge, there are 3 possible workarounds
1) Change the browser hash to something else such as #thecars.
2) Change your existing markup in some similar manner.
3) On some event, changing the id of your similarly named markup, then changing the browser hash, then rechanging the name of markup back to it's original value should also theoretically work. This is obviously a bad and slow workaround, just thought I'd mention it.
You could try having a "return false;" after you set the window location but I can't be sure.
Unfortunately, your problems won't end there. There are other issues with navigating back and forth across multiple browsers--nothing may change, page may reload, page state might be mangled, javascript may get reinitialized etc.
You may want to have a look at Tabs v2 which uses the History/Remote plugin though it has not been updated for jQuery 1.3+.
This demo is easier to understand. If you look at the javascript source, you'll notice the use of iframes to handle states.
There is also the History Event plugin and the jHistory plugin to achieve what you want.
Would like to hear back how things turns out and what solution you went with.
What Chris suggested worked for me, had no clue even a div could link via the #. So my solution is quite simple, in the show: event handler, I do the following, it's not perfect in that back button won't be in history, but that's another job for BBQ history plugin. All my divs simply have id="tab-cars", id="tab-trucks"... strip out the 'tab-' part and put it into the url hash.
var name = ui.panel.id.substr(4);
location.hash = '#'+name;

Resources