I have an MVC 5 project (.NET Framework) where a set of Views have the same set of #section styles and #section scripts blocks.
#section styles {
<link href="~/Content/DataTables/css/jquery.dataTables.css" rel="stylesheet" />
<link href="~/Content/DataTables/css/buttons.dataTables.css" rel="stylesheet" />
}
#section scripts {
<script src="~/Scripts/DataTables/jquery.dataTables.js"></script>
<script src="~/Scripts/DataTables/dataTables.buttons.js"></script>
<script src="~/Scripts/DataTables/buttons.print.js"></script>
<script src="~/Scripts/DataTables/buttons.html5.js"></script>
<script src="~/Scripts/jszip.js"></script>
<script>
$(() => {
// source js file defined in BundleConfig.cs
TableController.init();
});
</script>
}
Just as the one TableController.init() jQuery function rests in a single location and can be called in any View I choose, is there a way I can have only a single definition of this set of <link> and <script> elements be able to call it in any view I choose? The reason I did not put this in the _Layout file is that I might not want it on all Views -- just most of them.
I don't know what this technique is called, or even if it is possible in MVC. I just figured that it would be a useful way to avoid repeating myself. Furthermore, if I wanted to make any tweaks, I would only make a change in one place and not multiple Views.
Is there a technique I can use to achieve this goal?
You can create Bundles for anything you want, You can create a Bundle for an area or a single page.
//scripts
bundles.Add(new ScriptBundle("~/bundles/Custom").Include(
"~/Scripts/Custom.js"));
bundles.Add(new ScriptBundle("~/bundles/Custom2").Include(
"~/Scripts/Custom2.js"));
//styles
bundles.Add(new StyleBundle("~/Content/Custom").Include(
"~/Content/Custom.css"));
bundles.Add(new StyleBundle("~/Content/Custom2").Include(
"~/Content/Custom2.css"));
Now you can separate theese scripts and styles and add them only on page that you need.
Also I suppose it's good to define 2 sections in your _Layout.cshtml in head tag.
<head>
//other scripts and styles here
#RenderSection("scriptslib", required: false)
#RenderSection("csslib", required: false)
</head>
So now in your Views (Cabinet.cshtml and AdminPanel.cshtml) you can place your libs where they suppose to be like this:
#section scriptslib{
#Scripts.Render("~/bundles/Custom")
#Scripts.Render("~/bundles/Custom2")
}
By doing this it allows you to build complete bundles for sections or pages to use how you wish.
**
EDIT: thanks Adrian
**
You can add bundles as folders for future scripts using wildcards so you do not have to recompile, aswell as place a custom.js and custom.css in each folder for future edits or overrides you may want to add.
ADDING A CUSTOM FOLDERS:
Scripts
Custom
YourFiles.js
YourFiles.min.js
Content
Custom
YourFiles.css
YourFiles.min.css
Custom Bundles:
bundles.Add(new ScriptBundle("~/bundles/Custom").Include(
"~/Scripts/Custom/*.js"));
bundles.Add(new ScriptBundle("~/bundles/Custom2").Include(
"~/Scripts/Custom/*.*.js"));
bundles.Add(new StyleBundle("~/Content/Custom").Include(
"~/Content/Custom/*.css"));
bundles.Add(new StyleBundle("~/Content/Custom2").Include(
"~/Content/Custom/*.*.css"));
Now anything you place in those folders will be processed with a IIS App restart, I usually add a function to my applications to be able to perform the App Restart.
Hope this helps
Try the pool pro's idea, it's a great answer. For me I simply prefer to use partial views for referencing it.
Why ?
You need to compile the code again once you modify the c# file and add a another CSS or JS file. If you use partial views you don't need to compile the project again, you can just change views and upload.
Not pretty: You could use partialview and use it in views you want your links.
Put your partialview in your shared folder.
Then call this inside your view #await Html.PartialAsync("_SomeNamePartial")
More beautiful: Put all css in 1 file and all javascript in 1 file.
Best way and as it should be: Your way of doing it, #section is there for a reason.
Related
I am trying to include my plugins and custom js files in
frontend/views/layouts/main.php
So I used this code for js and css
<link rel="stylesheet" href="<?= Yii::$app->homeUrl; ?>chosen/chosen.css">
<script type="text/javascript" src="<?= Yii::$app->homeUrl; ?>js/jquery.fancybox.pack.js?v=2.1.5"></script>
but its not working. So what should I include to get my js and css files in view file?
If Your want to include script or css file in specific view you can use this :
$this->registerJsFile("/path/to/your/file/in/web/folder/script.js");
or
$this->registerCssFile("/path/to/your/file/in/web/folder/style.css");
For JS:
<?php
$script = <<< JS
// Js Code Here
JS;
$this->registerJs($script);
For CSS:
<?php $style= <<< CSS
// CSS code here
CSS;
$this->registerCss($style);
?>
This works fine.
Including it like you mentioned is not welcomed and definetely not "Yii style".
There are couple of ways to do that:
1) Use asset bundles. It's not necessarily to place it in AppAsset bundle. By default it's common bundle and included in main layout so all included assets will be published in every view.
You can create your own AssetBundle.
Note that for external assets (that are outside web accessible directory) you need to use sourcePath, otherwise - basePath and baseUrl properties.
With both options all you have to do in common case - fill $js and $css arrays and $depends for setting dependencies if it's needed.
You can read more by the link below.
2) Use registerCssFile() and registerJsFile().
First approach is preferable and recommended in official docs. It gives you dependencies handling and much more.
Official docs:
Assets
yii\web\AssetBundle
yii\web\View registerCssFile()
yii\web\View registerJsFile()
This seems like a ridiculous thing to be hung up on, but I would like to display html files from within app.get() methods. It seems like every answer I've come across uses the solution app.use(express.static(__dirname + '/public'));, but then that does not allow for logic from the server.
What I would like to do, is have my .html files be rendered by express, so I can keep some basic logic:
app.get('/', function(res, req) {
if (condition) {
res.render('this.html');
}
else {
res.render('that.html');
}
}
It seems so silly to me that this is only meant for template files, and that I must not be seeing something simple to make this work.
Edit: Using sendFile does not seem to allow the HTML to include external files, javascript / css.
You can use res.sendfile() (res.sendFile() for new version) to render html files.
Update for question in comment:
You can include your css and javascript files in the html file (you might need to specify the paths for your resources correct to get them loaded):
<head>
<link rel="stylesheet" type="text/css" href="mystyle.css">
<script src="myscripts.js"></script>
</head>
I was wondering how do you add link tag/google font to head in yii2.
I want to add the following
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700' rel='stylesheet' type='text/css'>
I have found this documentation but doesn't mention anything about link/adding google font etc
The correct answer is to create a new AssetBundle.
While you can directly place the HTML for the fonts into the of your main.php file, this isn't the Yii way. If you have tried to load jQuery files this way, you might notice odd behavior when directly putting them into the HTML.
For example: Directly place the HTML tag for Bootstrap CDN into the head of your main.php. Then, somewhere in your code try to use the tooltip. You will get an error in your console that tooltip is not a function. - This is because the way Yii puts all your template files together, and at that time, Bootstrap is not available.
While simply loading a font probably won't cause any problems, it is a good idea to do things the way they were intended. Following MVC rules, properly documenting your code, and following the Yii best practices, will go a long way. Not only will you thank yourself a year later when you have to go back into a project, but the next guy will appreciate it. I can't stand going into systems, and seeing stuff thrown everywhere, chincy hacks, and spaghetti code, and no documentation or comments.
Correct Way:
Create a new AssetBundle. In your assets folder, you probably already have AppAsset.php. Duplicate it, and name it FontAsset.php.
Here is an example from my project, using 3 Google fonts.
FontAsset.php
<?php
namespace app\assets;
use yii\web\AssetBundle;
class FontAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $css = [
'//fonts.googleapis.com/css?family=Open+Sans:400,700',
'//fonts.googleapis.com/css?family=Ubuntu:400,700',
'//fonts.googleapis.com/css?family=Oswald:400,700'
];
public $cssOptions = [
'type' => 'text/css',
];
}
In your layout, main.php for example. Right under where you see AppAsset::register($this)
main.php
use app\assets\FontAsset;
FontAsset::register($this);
For every layout file that you want to load those fonts, include the FontAsset.
The AssetBundle is basically a bundle of CSS and/or JS files and options. You could add another one for say JWPlayer say named VideoAsset, and add your JS/CSS files for JWPlayer in it.
Point being, you shouldn't be adding these things directly into the HTML of the layouts directly, as it can cause problems. Let the AssetManager handle them by declaring AssetBundles.
It might save you later down the road!
The best way is to create an asset bundle and add the link to the bundle.
You can find a complete guide here:
http://www.yiiframework.com/doc-2.0/guide-structure-assets.html
You can put it directly in the head of the layout (file views/layouts/main.php)
I am trying to get a custom css file to load after the plugin stylesheets. I was thinking I could use the $deps parameter of wp_register_style(), but the css file does not load at all when I add the array(). This happens no matter what is included in the $deps array(), ie (array('style')
, array('style.css')).
Is there an issue with the call, or a better way of doing this?
In my functions.php
// Load custom css
add_action('wp_enqueue_scripts', 'prefix_add_my_stylesheet');
function prefix_add_my_stylesheet() {
wp_register_style( 'custom-supersized-styles', get_template_directory_uri(). '/css/custom-supersized-styles.css', array('style','supersized');
wp_enqueue_style( 'custom-supersized-styles' );
}
If you're using the WP Supersized plugin try registering your function like so:
// Load custom css
add_action('wp_enqueue_scripts', 'prefix_add_my_stylesheet', 999);
The dependencies array (the parameter you're attempting to use to add supersized with) depends on supersized having already been registered by WordPress. If you set the priority of your own prefix_add_my_stylesheet to a higher number, it should then load after the plugin has registered and loaded its CSS (and thus will be available).
In addition, you can remove the style as a dependency. (style is never registered by WordPress as a dependency handler, and your enqueued scripts / css should be loading after style.css loads anyway).
Hope that helps!
Is there a decent way with static HTML/XHTML to create common header/footer files to be displayed on each page of a site? I know you can obviously do this with PHP or server side directives, but is there any way of doing this with absolutely no dependencies on the server stitching everything together for you?
Edit: All very good answers and was what I expected. HTML is static, period. No real way to change that without something running server side or client side. I've found that Server Side Includes seem to be my best option as they are very simple and don't require scripting.
There are three ways to do what you want
Server Script
This includes something like php, asp, jsp.... But you said no to that
Server Side Includes
Your server is serving up the pages so why not take advantage of the built in server side includes? Each server has its own way to do this, take advantage of it.
Client Side Include
This solutions has you calling back to the server after page has already been loaded on the client.
JQuery load() function can use for including common header and footer. Code should be like
<script>
$("#header").load("header.html");
$("#footer").load("footer.html");
</script>
You can find demo here
Since HTML does not have an "include" directive, I can think only of three workarounds
Frames
Javascript
CSS
A little comment on each of the methods.
Frames can be either standard frames or iFrames. Either way, you will have to specify a fixed height for them, so this might not be the solution you are looking for.
Javascript is a pretty broad subject and there probably exist many ways how one might use it to achieve the desired effect. Off the top of my head however I can think of two ways:
Full-blown AJAX request, which requests the header/footer and then places them in the right place of the page;
<script type="text/javascript" src="header.js"> which has something like this in it: document.write('My header goes here');
Doing it via CSS would be really an abuse. CSS has the content property which allows you to insert some HTML content, although it's not really intended to be used like this. Also I'm not sure about browser support for this construct.
The simplest way to do that is using plain HTML.
You can use one of these ways:
<embed type="text/html" src="header.html">
or:
<object name="foo" type="text/html" data="header.html"></object>
You can do it with javascript, and I don't think it needs to be that fancy.
If you have a header.js file and a footer.js.
Then the contents of header.js could be something like
document.write("<div class='header'>header content</div> etc...")
Remember to escape any nested quote characters in the string you are writing.
You could then call that from your static templates with
<script type="text/javascript" src="header.js"></script>
and similarly for the footer.js.
Note: I am not recommending this solution - it's a hack and has a number of drawbacks (poor for SEO and usability just for starters) - but it does meet the requirements of the questioner.
you can do this easily using jquery. no need of php for such a simple task.
just include this once in your webpage.
$(function(){
$("[data-load]").each(function(){
$(this).load($(this).data("load"), function(){
});
});
})
now use data-load on any element to call its contents from external html file
you just have to add line to your html code where you want the content to be placed.
example
<nav data-load="sidepanel.html"></nav>
<nav data-load="footer.html"></nav>
The best solution is using a static site generator which has templating/includes support. I use Hammer for Mac, it is great. There's also Guard, a ruby gem that monitors file changes, compile sass, concatenate any files and probably does includes.
The most practical way is to use Server Side Include. It's very easy to implement and saves tons of work when you have more than a couple pages.
HTML frames, but it is not an ideal solution. You would essentially be accessing 3 separate HTML pages at once.
Your other option is to use AJAX I think.
You could use a task runner such as gulp or grunt.
There is an NPM gulp package that does file including on the fly and compiles the result into an output HTML file. You can even pass values through to your partials.
https://www.npmjs.com/package/gulp-file-include
<!DOCTYPE html>
<html>
<body>
##include('./header.html')
##include('./main.html')
</body>
</html>
an example of a gulp task:
var fileinclude = require('gulp-file-include'),
gulp = require('gulp');
gulp.task('html', function() {
return gulp.src(['./src/html/views/*.html'])
.pipe(fileInclude({
prefix: '##',
basepath: 'src/html'
}))
.pipe(gulp.dest('./build'));
});
You can try loading them via the client-side, like this:
<!DOCTYPE html>
<html>
<head>
<!-- ... -->
</head>
<body>
<div id="headerID"> <!-- your header --> </div>
<div id="pageID"> <!-- your header --> </div>
<div id="footerID"> <!-- your header --> </div>
<script>
$("#headerID").load("header.html");
$("#pageID").load("page.html");
$("#footerID").load("footer.html");
</script>
</body>
</html>
NOTE: the content will load from top to bottom and replace the content of the container you load it into.
No. Static HTML files don't change. You could potentially do this with some fancy Javascript AJAXy solution but that would be bad.
Short of using a local templating system like many hundreds now exist in every scripting language or even using your homebrewed one with sed or m4 and sending the result over to your server, no, you'd need at least SSI.
The only way to include another file with just static HTML is an iframe. I wouldn't consider it a very good solution for headers and footers. If your server doesn't support PHP or SSI for some bizarre reason, you could use PHP and preprocess it locally before upload. I would consider that a better solution than iframes.