Should Partial Views contain <head> element - web

I encounter in some web app that some partial view that is used has head element (it loads some Jquery things).
The thing is that with that and the _layout.xml I get this wierd HTML page structure
<head>
...
</head>
<body>
...
</body>
<head>
...
</head>
<body>
....
</body>
doesn't feel right..
What's the best practice to load some .css.js to particular page? is it all done by _layout.xml and bundles?
and in general - only _layout.xml should contain head element? no other view in my solution?

You want only one head. Use layout with sections and add MVC sections in normal pages to add CSS or JScript. See here on basic section usage http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx. If you want to use partial create a helper to render section from partial see this answer Using sections in Editor/Display templates

Related

Failing to render squishit bundal

If I have a partial view, named: _jquery.cshtml, view like so:
#(Bundle.JavaScript()
.Add("~/Scripts/jquery-3.1.0.js")
.Add("~/Scripts/jquery-ui.js")
)
and render the partial view, using:
<head>
...
#Html.Partial("_jquery", theme)
</head>
<body>
...
</body>
all I get rendered is:
<head>
...
</head>
<body>
SquishIt.Framework.JavaScript.JavaScriptBundle
I am doing something wrong obviously. This is inside an IFrame, within the main Layout. I would be grateful if someone is able to point out my problem. Thank You.
Always when learning a new, not so new anymore, thing, it takes some time. I missed the line:
.MvcRender("~/.../filename.js")
It is now rendering as it should. so the partial view now looks like this:
#(Bundle.JavaScript()
.Add("~/Scripts/jquery-3.1.0.js")
.Add("~/Scripts/jquery-ui.js")
.MvcRender("~/.../filename.js")
)
I hope others can learn from my mistake.

place external JavaScript after CSS file inside head element using JSF 2.3

I use JSF 2.3 for developing web application.
As a web developer, I care about the performance of loading speed of a site.
As I was exploring on how I could make my site faster, I encountered this post on Stack Overflow. And the quote from the accepted and most up-voted answer said
stylesheets should always be specified in the head of a document for better performance, it's important, where possible, that any external JS files that must be included in the head (such as those that write to the document) follow the stylesheets, to prevent delays in download time.
I know that JavaScript performs better when it is placed at the bottom of the <body>, but I want to include reCAPTCHA and Google instructs us to place the required external JavaScript before the closing </head> tag.
So, I decided to include the required external JavaScript before the closing </head> tag and after CSS files to boost the performance.
However, my CSS files are declared in a JSF way like <h:outputStylesheet name="css/default.css"/>, and I realized that the CSS files declared this way are always placed after files that are declared in a non-JSF way, which is <script src="https://www.google.com/recaptcha/api.js"></script>. I also considered making the external JavaScript behave in a JSF way by changing <script> to <h:outputScript>, but the <h:outputScript> can only render local scripts as described in this post .
So, the result will always be as follows.
<head>
<script src="https://www.google.com/recaptcha/api.js"></script>
<link type="text/css" rel="stylesheet" href="/project/javax.faces.resource/css/default.css.xhtml" />
</head>
insted of
<head>
<link type="text/css" rel="stylesheet" href="/project/javax.faces.resource/css/default.css.xhtml" />
<script src="https://www.google.com/recaptcha/api.js"></script>
</head>
Maybe I'm thinking too much, and the placement order of link and script doesn't affect the performance that much, but if the loading speed gets faster even a little, I want to follow the better way.

Automatically include assets into template

I'm using the linkedIn fork of Dust with Node.JS & Express.
My template hierarchy is having:
1 layout template - The base template
1 Page template - This is the template that will be rendered
Optional number of partials - Might be included by the page template
layout.dust (layout template):
<html>
<head>
<script src="/js/layout.js"></script>
<link rel="stylesheet" href="/css/layout.css">
<script src="/js/home.js"></script>
<link rel="stylesheet" href="/css/home.css">
<script src="/js/sidebar.js"></script>
<link rel="stylesheet" href="/css/sidebar.css">
<script src="/js/widget.js"></script>
<link rel="stylesheet" href="/css/widget.css">
</head>
<body>
{+content}{/content}
</body>
</html>
home.dust (page template):
{>layout/}
{<content}
<div>
{>sidebar/}
</div>
<div>
{>widget/}
</div>
{/content}
When the user visits the website homepage, then home.dust will be rendered, and the user will see a page with the sidebar and some widget. The content of sidebar.dust and widget.dust is irrelevant.
As you can see in layout.dust, there are 4 sets of JavaScript and CSS included in the head section, one for each of the templates and partials. My problem is finding a way to automatically include each asset into the layout (without hardcoding). Ideally I would like to be able to just do this:
{#scripts}
<script src="{.}"></script>
{/scripts}
Different pages may require different assets.
How can I push each script source path into the context of layout.dust?
What do other developers do, do they just hardcode them?
I'd be adding all scripts to the head of the layout without pushing any from the pages that extend from this layout. I'm not sure how knowledgeable you are on javascript minification but it's common practice to bundle all (or most) of your javascript assets into one file and serve them up to the user with a single HTTP request. This speeds up your page a lot; checkout what Google has to say about it here.
It's not hard because there are a few tools to do this for you automatically. You could go for an asset manager or Grunt.
ASSET MANAGER:
There are a few on npm. I found one called Express Asset Manager and another called Asset Pipeline.
GRUNT:
Use contrib-uglify and contrib-concat to handle you minification. There are plenty of others that you should find useful. You can do the exact same thing with all of your CSS too.
Obviously in development you don't really want to try to debug minified code so you can do something like the following:
{?production}
<script src="production-minified-script.js"></script>
{:else}
{#scripts}
<script src="{.}"></script>
{/scripts}
{/production}
where production is a variable passed to your template from process.env.NODE_ENV. To avoid manually adding in each script, you could pass them in as an array by
STILL WANT TO ADD FROM OTHER PAGES?
If you still want to add from other pages, add in a block to your head below your main scripts, something like:
{+otherScripts}{/otherScripts}

meteor real router for multi page apps without JavaScript render

I am new to meteor and I am trying to do multi-page application where http://www.mydomain.com/page1 will result a totally different page from http://www.mydomain.com/page2.
By totally different I mean that I don't want the page to be rendered by the client.
I tried to use meteor-router but What I got is something like:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/myapp.css?9297ad4aa173c4e0c19aebd27c62a5c43242bb93">
<script type="text/javascript">
__meteor_runtime_config__ = {"ROOT_URL":"http://localhost:3000","serverId":"iMp4kgzzeqDtktJoY"};
</script>
<script type="text/javascript" src="/packages/underscore/underscore.js?6d71e6711255f43c0de8090f2c8b9f60534a699b"></script>
<script type="text/javascript" src="/packages/meteor/client_environment.js?07a7cfbe7a2389cf9855c7db833f12202a656c6b"></script>
<script type="text/javascript" src="/packages/meteor/helpers.js?2968aa157e0a16667da224b8aa48edb17fbccf7c"></script>
...
...MANY MANY MANY SCRIPTS.... ?!?
...
...
<script type="text/javascript" src="/myapp.js?2866dcdb5c828b129cdd3b2498a4bf65da9ea43f"></script>
<title>myapp</title>
</head>
<body>
</body>
</html>
And this is not what I want. I want page1 route will return me:
<!DOCTYPE html>
<html>
<head>
My meta tags
</head>
<body>
page1
</body>
</html>
And I want page2 to return different meta tags with different content.
In order to be clear, lets assume that my clients sometime doesn't have javascript. I don't asking about whether meteor is the right framework! I am asking only if can I do this with meteor.
Meteor works a bit different compared to the traditional LAMP stack. Basically it works by patching out the DOM to only where the changes are needed as opposed to re-downloading the whole web page. It makes for a very satisfying end user experience on modern web browsers.
To use meteor router you need to find a spot that you want to patch out with new data for different pages with {{renderPage}}. You can use something like
<head>
<title>xx</title>
</head>
<body>
{{renderPage}}
</body>
<template name="page1">
<h2>Hello!</h2>
</template>
<template name="page2">
<h2>Ola!</h2>
</template>
Now you need to define a router in your client side javascript:
Meteor.Router.add({
'/page1': 'page1',
'/page2': 'page2'
});
So if you load /page1 you would see Hello! and if you load /page2 you would see Ola! as defined in the <template name="page2">..</template>
With the meta tags you need to use javascript to create them. With something like
$('head').append("<meta...");
Again this depends on your preference, personally I find these type of apps load ridiculously fast between web pages as compared to other 'thin' based websites. (Have a look at meteor.com to see how fast you can swap between the pages). The browser does need javascript, however.
Of note is in production mode there will only be 1 script tag.

Thickbox inline problem

I am trying to create a modal window with hidden content using thickbox
It opens the window fine , not sure whys its not showing the content inside the id="hiddencontent".
i am following as suggested in the examples for inline http://jquery.com/demo/thickbox/#
-thanks
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="thickbox.js"></script>
<link rel="stylesheet" href="thickbox.css" type="text/css" media="screen" />
</head>
<body>
Show Content
<div id="hiddenContent" style="display: none">inline content comes here</div>
</body>
</html>
It seems you don't have css file, you can copy thickbox css on http://jquery.com/demo/thickbox/#sectiona-3 to your page (or save as style.css file).
-- edit --
Yeh, sorry, didn't notice that css is already loaded :(
By the way, just found the solution, try to add p tag inside your hiddenContent div:
<div id="hiddenContent" style="display: none"><p>inline content comes here</p></div>
Hope helps ;)
This is a bug in thickbox. Here is how you can fix it:
Inside thickbox.js
on or about line 221 you should see this line of code:
$("#TB_ajaxContent").append($('#'+params['inlineId']).children());
change it to this:
$("#TB_ajaxContent").html($('#'+params['inlineId']).html())
and then, on or about line 223 you will see this line:
$('#'+params['inlineId']).append($("#TB_ajaxContent").children());
disable the line by adding two slashes before it like this:
//$('#'+params['inlineId']).append($("#TB_ajaxContent").children());
Explanation:
When thickbox copies the content from the hidden div into the thickbox container, it does so by copying all .children() elements. If you have only text inside your hidden div there ARE NO CHILDREN because text is not itself a child element. This is why wrapping your content in a <p> tag will work because now there is a child (the <p> tag).
So if you want to have text only in your hidden div using .html() instead will grab everything in your hidden div. The second line being disabled prevents thickbox from trying to copy the content back to the hidden div when the thickbox closes, which would cause any content within child tags to be duplicated in the hidden div.
There is no need to edit the .js file, the solution is quite simple.
Maybe a bit later :) but I overcomed the issue only changing the ? char in #TB_inline? by &
The issue is on the internal parseQuery tickbox function, that parses match pairs but it blows when the query have a double ? like in the case.
UPDATE: In some cases the <p> fix is also needed ;)
Hope it helps.
The function tb_position() needs to be updated.
this condition
if ( !(jQuery.browser.msie && jQuery.browser.version < 7))
is the reason for error.
jQuery does not support jQuery.browser anymore. For detecting IE6 in this case change the above condition to this
if ( !(/\bMSIE 6/.test(navigator.userAgent)))

Resources