Application Displays Unstyled Html Before It Renders Jquery Mobile - javascript

I am dynamically adding markup to my application an example code below..
$(document).bind("pagechange", function (event, ui) {
var header = '<h3>' + appNames[i] + '</h3>';
var ulHeader = '<ul data-role="listview" id="myAppsGridTable" data-inset="true">';
..
$('.myBodyContent', ui.toPage).append(collapse + header + ulHeader + entire_list + '</ul>' + '</div>');
$('#NicksPage').trigger('create');
});
I have a reference to this page in my Default.aspx page and a reference to jquery mobile in the master page. When you navigate to Default the user sees raw unstlyed html added to the page then a flicker and the jquery mobile styles come in. Is there anyway I can get rid of displaying the unstlyed html to the user sees before the jquery mobile styles are added?
Here is a copy of my master page:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="UserMobile.master.cs" Inherits="User.Mobile.UserMobile" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head id="Head1" runat="server">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="Css/jquery.mobile.custom.structure.min.css" rel="stylesheet" type="text/css" />
<link href="Css/jquery.mobile.custom.theme.min.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<div data-role="page" data-theme="b" id="NicksPage">
<div data-role="header" data-position="fixed" data-theme="b">
<asp:ContentPlaceHolder ID="TopHeaderContent" runat="server"></asp:ContentPlaceHolder>
</div><!-- /header -->
<div data-role="content" class="myBodyContent">
<asp:ContentPlaceHolder ID="MainContent" runat="server"></asp:ContentPlaceHolder>
</div><!-- /content -->
<div data-role="footer" data-position="fixed" data-theme="b">
<asp:ContentPlaceHolder ID="FooterContent" runat="server"></asp:ContentPlaceHolder>
<input type="hidden" id="collapse_value" value="false" />
</div><!-- /footer -->
</div><!-- /page -->
//Combined jquery 1.8 and jquery mobile files in one
<script src="Js/JQ_JQM_combined.js" type="text/javascript"></script>
//Makes ajax calls to get data
<script src="Js/UserMobile.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
// disable page transitions
$.mobile.ajaxEnabled = false;
$.mobile.defaultPageTransition = 'none';
});
</script>
<asp:ContentPlaceHolder ID="ScriptContent" runat="server"></asp:ContentPlaceHolder>
</body>
</html>
Even the Home page has the flicker problem, where it renders unstyled and then after a period of time properly styled to jquery mobile..
<%# Page Title="" Language="C#" MasterPageFile="~/Mobile/UserMobile.Master" AutoEventWireup="true" CodeBehind="Home.aspx.cs" Inherits="User.Mobile.Home" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="TopHeaderContent" runat="server">
<h1>
Applications</h1>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<div data-role="controlgroup">
My Stuff
Employees
List
</div>
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="FooterContent" runat="server">
<div class="lines">
<div class="footerCopyrightContainer">
<div class="footerCopyright">
©2012 NICK ALL RIGHTS RESERVED.</div>
</div>
</div>
</asp:Content>
I changed my code to reflect your fiddle example but am still getting the flicker. But the "period of time where the flicker the unstyled to styled is shorter the user still sees the unstyled page in the mobile browser. Can you take a look fo how I got it setup am I missing something?
$(document).bind("pagecreate", function (event, ui) {
//gets params needed from querystring
arrQrStr = getQueryStringParams();
name = arrQrStr["name"];
id = arrQrStr["id"];
});
$(document).delegate('div[data-role=page]', 'pagebeforeshow', function (e, data) {
var employees = null;
//returns string of html needed
employees = getData(name, id);
$('.myBodyContent', this).html(employees);
$(this).trigger('create');
});
getData ajax call..
$.ajax({
type: "POST",
url: "MobileService.svc/REST/GetData",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ id: id}),
dataType: "json",
async: false,
success: function (msg) {
The problem has comes from this:
<script type="text/javascript">
$(document).ready(function () {
// disable page transitions
$.mobile.ajaxEnabled = false;
$.mobile.defaultPageTransition = 'none';
});
</script>
If I take this out of the master page the flicker goes away, it navigates a page fine but the data will not show. Taking this script out breaks the ajax calls and jquery mobile events dont engage (I am not sure why)

It sounds like you misunderstood how the ajax enabled settings works.
By default this setting is enabled and when you link to another page JQM pulls in the the first JQM page that it finds (data-role="page") on the linked page (so you can't link to a multipage document) and enhances it (initializing all the JQM widgets) and then attaches it to the DOM of the current page. When JQM does this it only pulls in the JQM page and nothing else on that page (so any scripts and styling on the second page won't have any effect). The way to deal with this is to have all your scripts in the current main page. One thing you will need to look out for if you do this is that you might end up with multiple pages with the same id (actually with your current setup you definitely will have duplicate ids) so you might want to select them by class instead.
With ajax enabled set to false on the other hand it behaves like a regular link in which case the full page is loaded and if your JQM scripts are on the bottom then then until it's loaded it won't be able to enhance the DOM which is why you are seeing that flicker.
As a side point page transistions are only available ifajax enabledis set totrue`.
To sum up, unless you have a reason not to you probablly should go with ajax enabled set to true, and inlcude the relevant scripts on your main page. If you need to go with ajax enabled set to false then try placing your jQuery scripts in the header so that they load before the rest of the DOM.
Alternaticely what you can do is hide the container element where you will be appending you html and then once your done display it, for example
CSS
.displayNone { display: none; }
HTML
<div data-role="content" class="myBodyContent displayNone">
<asp:ContentPlaceHolder ID="MainContent" runat="server"></asp:ContentPlaceHolder>
</div>
JS
$('.myBodyContent', this).html(employees);
$(this).trigger('create');
$('.myBodyContent', this).reomveClass('displayNone');

Try putting your jquery mobile source scripts in the head, instead of at the end of the body.
This is the only way I could guarantee that the user never sees unstyled html.

Try using the pagebeforeshow instead of pagechange. Like so:
$(document).delegate('div[data-role=page]', 'pagebeforeshow', function(e, data){
var toPage = this; // this references the page that is about to be shown
// Add items to the page
});
The pagebeforeshow event is triggered on the "toPage" being transisioned to, before the actual transition animation starts. This allows you to add in elements and styles before it is displayed to the user.
I hope this helps!
EDIT
Here is a JSFiddle with the suggested fix implemented.

Related

Css Rules in UserControls

I'm sorry if the title of this question is quite vague...
I have a Web Application composed by a MasterPage in wich I include all my css and js files and any other page will be loaded into the content of the MasterPage.
In a page I call another page via javascript with this call:
<script type=text/javascript>window.open('ApriOrdine.aspx?ID=B300&MODE=UPD',null,'scrollbars=1')</script>
the page ApriOrdine.aspx contains 2 UserControls. I have a problem with css rules, I cannot set the padding using css rules written in css external files.
This is the whole code of my ApriOrdine.aspx:
<%# Page Title="Orders" Language="C#" AutoEventWireup="true" CodeBehind="ApriOrdine.aspx.cs" Inherits="WebApplication1.ApriOrdine" EnableEventValidation="false" %>
<%# Register TagPrefix="UC" TagName="UserControlCom" Src="~/Commessa.ascx" %>
<%# Register TagPrefix="UC" TagName="UserControlCli" Src="~/Cliente.ascx" %>
<head runat="server">
<link href="css/css.css" rel="stylesheet">
</head>
<body>
<form runat="server">
<div class="ApriOrdine">
<div>
<UC:UserControlCom runat="server" ID="ucCommessa" />
</div>
<div>
<UC:UserControlCli runat="server" ID="ucCliente" />
</div>
</div>
</form>
</body>
As you can see, the css.css file it's included behind head tags.
The problem in that if I write this css rule in my css.css like this it doesn't works.
.ApriOrdine
{
padding:50px;
}
Instead, if I assign the padding using style attributes to the div it works perfectly...
<div class="ApriOrdine" style = "padding:50px;">
EDIT
this is my complete source code
and this is the css
So, what is wrong here? Please help me, thanks!
If you need some more details please ask me!
The only reason i see is that your reference to the css is not good.
I don't know the structure of your project but i guess the master page is not at the same place as your .aspx page. So if you copy and paste the reference from the master page it's not working in the .aspx page cause the structure is not the same.
An other thing you could do is once the page is loaded, open the source code of the page and look at the reference generated in the page and make sure the path is good.
Hope this help.

Access content page control from master page using javascript

I want to access the content page Ajax combobox control in the master page and that too by using Javascript.
I have been trying the same by using the contentpageholder of the content page, but also one of the problem I get is there are around 10 content pages, so when some other page like Page 1 is opened , the code show object reference exception as contentplaceholder is not matched.
How to get that which content page is opened up?
Also I am not able to get the code working to get the maincontentplaceholder id in master page.
What I have done till now:
function accessControlContentPage() {
var txtCont = document.getElementById("Page.Master.FindControl('ContentPlaceHolder1').FindControl('txtContent')").value;
var text=txtCont;
}
But this is not working.
Any help with the same?
The suggested approach is add a specific content place holder controls for such scripts to be placed in the web page you are rendering. Take a look at the following master/content page markup:
Master page:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="WebApp.PageMethods.Site1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
There is a content place holder head wherein I must write some js functions trying to access the dropdown list in the other content place holder ContentPlaceHolder1.
Content page markup:
<%# Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="WebApp.PageMethods.WebForm3" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<script>
function foo() {
var ddl = document.getElementById('<%= DropDownList1.ClientID %>');
}
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:DropDownList ID="DropDownList1" runat="server"></asp:DropDownList>
</asp:Content>
Here I didn't have to worry so much about trying to access controls nested in ContentPlaceHolderID.
Alternatively, if you don't have that option/freedom, you can always write something as follows in your master page itself:
var d = document.getElementById('<%= this.ContentPlaceHolder1.FindControl("DropDownList1").ClientID %>');
Access content page control from master page using javascript
we can find div id or control id of content page from master page in asp.net
Explanation of content page:-
don't forgot to mention runat="server",
ContentPlaceHolderID="content_body" //observation,
main_content is the ID of div tag
MasterPage.master
var d = document.getElementById('<%= this.content_body.FindControl("main_content").ClientID %>');
Do whatever you want with d
Thank you

ASP.NET, Master Pages and jQuery

I'm trying to create a little script to allow me to set the style of a couple of menu items (done via a simple div with li items, which contain an each to send me to the correct page) but I'm not getting nowhere so I'm in need of help.
I have the following code on the master page:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="MILLS001_PAINEL.Site1" EnableTheming="True" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Title</title>
<script type="text/javascript" src="../js/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="../js/menu.js"></script>
<link href="../css/reset.css" rel="Stylesheet" type="text/css" />
<link href="../css/style.css" rel="Stylesheet" type="text/css" />
<!--[if gte IE 9]>
<style type="text/css">
.gradient {
filter: none;
}
</style>
<![endif]-->
<asp:ContentPlaceHolder ID="head" runat="server"></asp:ContentPlaceHolder>
</head>
<body>
<div id="banner" class="gradient">
<div id="menu">
<ul>
<li>Painel de Gestão</li>
<li>Cockpit Operacional</li>
</ul>
</div>
<div id="logo"></div>
</div>
<div>
<asp:ContentPlaceHolder ID="Placeholder" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
The menu is defined in the master page, now I have this script to add certain classes (already created in CSS) to allow me to add/remove styles to the menu items:
$(document).ready(function () {
$('menu').find('li').hover(function() {
$(this).addClass("hovered");
},
function() {
$(this).removeClass("hovered");
});
$('menu').find('a').click(function(e) {
alert(e);
$(this).parent().addClass("active");
});
});
For some reason, I can't make this to work although I do not see any errors.
I had a problem with another script in which I had to reference names by using '[id$=name]', because Master page name mangling creates that problem, but it doesn't seem to be the case here...
Could anyone help me see what is wrong here?
Thanks in advance
EDIT
Got the hover thing working, but now I can't make to seem the active class to stay in place after the page refresh (apparently, a default behaviour of ASP).
You need to do:
$('#menu') <-- note the # sign
in your selectors.... Otherwise it looks like it should work OK
API Reference: jQuery ID Selector
To address your edit:
Element state is not automatically preserved between page loads. The browser doesn't look for "the same element" and try to make it appear the same. If you want the menu to remain open, you need to persist some data (whether through postback data or (I would recommend) some browser side state saving (e.g. localStorage)) and handle it manually in your menu code
Oh....rereading your question I think it might be simpler than that....
On page load, you could do something like:
$('[href=' + window.location.path + ']').addClass('active');
the window.location.path would likely need some pre-processing before the selector though to handle extra url parameters and variations of the path (e.g. ./index.html and index.html) in the href. However, note the various types of matching available with the attribute selector...namely *=...might make your href matching a lot easier...but I'm not gonna write all your code =0D
API Reference: jQuery Attribute Selector
Your selector looks incorrect, looks like your missing the # which notes it's an ID. Should be:
$('#menu').find('a').click()
And a slightly different approach:
$('#menu a').click()

Facebook Open Graph - 'Like Button' - Hidden Content Revealed Upon 'Like'

I was wondering, I wish to have a landing page with Facebook's Open Graph (specifically the like button) and I wanted to basically have content set to display:none (can't remember the specific until a user likes a page. An example being a div on an e-commerce store that when a user likes the page, the div is set to display:block and users can redeem a coupon code for discount.
I would like to be able to do this with div displays.
I saw this little snippet of code on the Facebook developers forum:
| ( taken from http://fbrell.com/xfbml/fb:like )
(Note: The event that's fired when you click "like")
<script>
// this will fire when any of the like widgets are "liked" by the user
FB.Event.subscribe('edge.create', function(href, widget) {
Log.info('You liked ' + href, widget);
});
</script>
Can this be modified to effective set a div from display:none to display:block?
Thank you SO.
If you specifically want to update your div to display:block, use...
<script>
// this will fire when any of the like widgets are "liked" by the user
FB.Event.subscribe('edge.create', function(href, widget) {
$('#divid').css('display','block');
});
</script>
One caveat...
Your edge.create event WON'T fire unless the URL you use as part of your call is EXACTLY the same as the URL you're attempting to fire this from.
I had a site I was running on example.DEV (my local laptop dev env) which referenced a link on example.com (the live server) and anything in the FB.Event.subscribe() block wouldn't run until I uploaded the file, and fired it from the LIVE server.
That could be why you're having trouble if it's not working so far!
I found the following solution, but you will need jQuery to do it. (possibly not, but that's what I used to do it).
Here is the code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="facebook.js"></script>
<script src="jquery.min.js" type="text/javascript"></script>
</head>
<body>
<div id="fb-root"></div>
<script type="text/javascript">
<!--
window.fbAsyncInit = function() {
FB.init({appId: '133387220039676', status: true, cookie: true, xfbml: true});
FB.Event.subscribe('edge.create', function(href, widget) {
// Do something, e.g. track the click on the "Like" button here
$('#slidingDiv').show();
});
};
(function() {
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
//-->
</script>
<fb:like href="http://www.facebook.com/TheRightMind" layout="standard" show-faces="false" width="450" action="like" colorscheme="light"></fb:like>
<div id="slidingDiv" style="display:none;">
Fill this space with really interesting content that you can
</div>
</body>
</html>
Just replace the Log.info() call with JavaScript that displays the div. In jQuery:
<script>
// this will fire when any of the like widgets are "liked" by the user
FB.Event.subscribe('edge.create', function(href, widget) {
$('#yourdiv').show();
});
</script>
After verifying that liking the page will trigger that code (try console.log("AOK!")), you can make a <div> appear using this code:
Plain Old JavaScript:
FB.Event.subscribe('edge.create', function(href, widget) {
document.getElementById("topsecret").style.display = "block";
});
The HTML:
<div id="topsecret" style="display:none;">
Content Goes Here
</div>
If you're using the jQuery library or something similar, you can use a show() function to make the box appear instead:
FB.Event.subscribe('edge.create', function(href, widget) {
$("#topsecret").show();
//$("#topsecret").slideDown("fast");
//$("#topsecret").fadeIn("fast");
});
You might also consider using an AJAX load command instead, because otherwise it's fairly easy to make the box appear when the content is only hidden.
FB.Event.subscribe('edge.create', function(href, widget) {
$("#topsecret").load("mycontent.html");
});

How do I add JavaScript to an ASP.NET MVC View?

I have a simple View and I wish to add a JQuery DatePicker JavaScript to this view (and not every view, via a masterpage).
I'm not sure what is the best way to do this.
Second, I'm conscious of where/when my JavaScript loads. I'm a fan of YSlow and it recommends that I add any scripts to the bottom of the page, which I do.
So, how could I do both?
Here's the view:
<%# Page
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h2>Index</h2>
<% using (Html.BeginForm()) {%>
<p>
<label for="StartDate">Start Date:</label>
<!-- JQuery DatePicker to be added, here. -->
</p>
<% } %>
</asp:Content>
In ASP.NET MVC3, you can now use a RenderSection to achieve this, at least for simpler scenarios. Just add a RenderSection to the bottom of the layout page, and from your view fill in the appliation code
RenderSections: http://www.dotnetcurry.com/ShowArticle.aspx?ID=636
Your MasterPage should have a ContentPlaceHolder for the head.
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server" />
</head>
Then you're able to include head elements (JavaScripts, StyleSheets, etc...) in your views:
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<script src="/Scripts/jquery/ui/ui.datepicker.js" type="text/javascript">
</script>
<link href="/Styles/myStyle.css" rel="stylesheet" type="text/css" />
</asp:Content>
One way is put a content placeholder at the bottom of your master page, then the specific slave page that needs the javascript can specify the placeholders contents as the required javascript. Other pages that don't need the javascript simply don't specify any content for the placeholder.

Categories