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)
Related
The code is here:
But i couldn't link with the css.
I tried using
{{asset('public/added')}}
All the templates css,vendor,js are kept in the public/added folder.
The result in the browser is here:
By Default the asset helper will look under the public directory
From looking inthe picture your project structure is
public > added > css > css-files.css
For this you could use
<link rel="stylesheet" href="{{asset('added/css/css-files.css')}}">
You can omit the public since laravel asset helper will pick it for you
Alternatively you could use {{url}} helper or you could paste the whole url
Hope this would help you,
I don't really understand how the wrapper works. I understood the example of the catalyst tutorial but I don't know how to apply specific CSS file for a specific template.
Should I use [% IF %] statement in my wrapper.tt in order to select a specific template ? Do I call the CSS file with stash, like I do for a template in the controller ?
Some examples or hints would be great, thanks
You can certainly assign the CSS file to a stash variable in your controller.
sub frobnicate :Local {
my ($self, $c) = #_;
# ...
# this would probably be implied, i.e. in a properly configured Catalyst
# you don't have to actually set this, it will just load the right thing
$c->stash->{template} = 'frobnicate';
# this one is for loading the right CSS
$c->stash->{css_file} = 'frobnication.css';
}
And then in your TT wrapper, possibly wrapped in [% IF css_file %]...[% END %]:
<head>
<link rel="stylesheet" href="[% css_file %]">
</head>
That would work, but it is not good practice, because you are breaking the separation of concerns. The way the page looks should have nothing to do with your application controller.
You could also just load each CSS file whenever it's needed, but that is bad practice too, because it will impact page load times and the order in which things are loaded. Typically one puts CSS at the top in the <head>, and most javascript files at the end of the page, just before the </body> so that there is already content rendered before the browser goes off and fetches and runs javascript.
A more flexible, but also more complex solution is to write a method in your View that can be exposed as a TT vmethod to the Template Toolkit, and use it to add CSS files to the stash when needed. You can do that with expose_methods.
package MyApp::View::TT; # or whatever you have called this
# ...
expose_methods => [qw/add_css_file/],
# ...
sub add_css_file {
my ( $c, $self, $css_file ) = #_;
push #{ $c->stash->{_css_files} }, $css_file;
return;
}
Now you can use that in your template files. You can have a block at the very top or very bottom of each file to add CSS files to the list of files that should be loaded right where they belong to logically.
<h1>Order Confirmation</h1>
[% add_css_file('confirmation.css') %]
In your wrapper, you can iterate that list of files and load each of them. As you can see this approach comes with the benefit of allowing you to have more than one file.
<head>
[% FOREACH file IN _css_files %]
<link rel="stylesheet" href="[% file %]">
[% END %]
</head>
They'll be available in the stash because the wrapper gets rendered after the inner part of the page, but you can't do it from the template directly, because you cannot change the stash within Template Toolkit. If there are no files, this will not do anything because the loop has nothing to iterate over.
Note how I called the stash key _css_file. The underscore _ indicates that it's meant to be a private variable. Perl has no concept of private or public, but that's a convention to tell other developers not to mess with this.
It would be advisable to now add a second method to the View to read the list and return it. That would decouple the implementation detail of how the list of files is stored completely from the template. You could change it entirely without having to touch the template files at all.
If you have that exposed method, it would be smart to for example make sure that each file is only included once, e.g. with List::Util::uniq, or by using a hash and accessing the keys instead of going for an array.
I originally used this approach for javascript files rather than CSS. For CSS in your application I actually believe it would be smarter to condense all the styles into one file, and minify it. Your users will download most of them anyway, so why have the overhead of loading multiple files and making each initial page load a little bit slower, and blowing up their cache, if you can just have the very first page load be a tiny bit longer and then read everything from cache?
I'm building a Rails app, but I'm using a plugin in which I have to render my images using only html.
Since I haven't deployed yet, all my images are in RAILS_ROOT/app/assets/images/, so to render an image I have to write the following code:
<img src="/assets/image.jpg">
But when I'm ready to deploy to the web and I perform a precompile, all my images are supposedly going to be moved to my public folder. Will the html still work to link to the image, or will I have to change to link to a different path?
The plugin I'm using is Typeahead:
application.html.erb*
<script type="text/javascript">
//....
$('#typeahead').typeahead(null, {
maxLength: 5,
displayKey: function(thing) {
return "<div class='typeahead'><img src='" + thing.image_url + "'></div>";
},
source: bloodhound.ttAdapter(),
});
</script>
things_controller.rb
def typeahead
#render json: Thing.where(name: params[:query])
q = params[:query]
render json: Thing.where('name LIKE ?', "%#{q}%")
end
*Thing.image_tag is currently set to "/assets/[image.jpg]", except for each thing it's adjusted with the proper file name.
Not only are they going to be in the public folder, but they'll be renamed to include the fingerprint.
You must use the Rails helpers for all assets, see how to here and read the rest of the guide while you're at it :)
I think you should use non-stupid-digest-assets gem as it copies all your assets(mentioned in assets precompile list) in public/assets folder and then you need not to change your code before/after compiling.To install, you just need to add it into your Gemfile.
gem 'non-stupid-digest-assets'
I hope it might help you.
Joe, my suggestion would be to create a directory in your public folder to house your images, instead us using the app/assets directory. The public folder will allow the assets to not be altered by the rails pipeline, and you can link to them reliably using any external services that need the images.
As stated in RailsGuides:
Assets can still be placed in the public hierarchy. Any assets under
public will be served as static files by the application or web server
when config.serve_static_files is set to true. You should use
app/assets for files that must undergo some pre-processing before they
are served.
So you would need to add this line in config/application.rb
config.serve_static_files = true
As described in Rails general configuration.
It looks like you're storing your image_url in your model, and that's not working because assets don't have fixed URLs in Rails. I would override the getter in your model to use the asset_path helper, so it translates the path when that attribute is read (e.g., when the JSON is generated).
Something like:
# thing.rb
[...]
def image_url
ActionController::Base.helpers.asset_path(read_attribute(:image_url))
end
[...]
Short answer, no.
But it isn't that big a deal to remedy. Just move the images you need to reference with html into your Public folder. Then you can simply reference them with this code:
<img src="/image_name.image_type">
and the html will link to the correct path, both before and after precompile. So you don't have to change any code before you deploy.
BTW: I assume image_tag and image_url are the same column and you just made a mistake in one of the two times you mentioned it. If that's the case, then don't forget to change it to simply "/[image.jpg]".
I'm creating a site using Magnolia - CMS. Now I am implementing a blog page. On each blog page, there are several share buttons. Now I'm busy implementing the twittershare button. Here I am going to use the twitter cards. For that, I need to provide the URL of an image in a metatag. Main problem: I retreive my image like this: ${damfn.getAssetLink(content.blogImage)}. This only returns a relative path to my resource. Is there a quick way (in freemarker), that will convert tis to an absolute link?
Many thanks in advance!
usually you define magnolia.default.base.url in the magnolia.properties.
then you can retrieve it with Components.getComponent(ServerConfiguration.class).getDefaultBaseUrl()
now you have to install the service into freemarker. you can do that by adding installer-tasks into the renderers on startup. you do that in your module-version-handler. there you overwrite the getStartupTasks(...), something like this:
#Override
protected List<Task> getStartupTasks(InstallContext installContext) {
final List<Task> tasks = new ArrayList<>();
tasks.add(new InstallRendererContextAttributeTask("rendering", "freemarker", "serverConf", ServerConfiguration.class.getName()));
tasks.add(new InstallRendererContextAttributeTask("site", "site", "serverConf", ServerConfiguration.class.getName()));
return tasks;
}
now you can call in freemarker:
"${serverConf.defaultBaseUrl}/${ctx.contextPath}/${damfn.getAssetLink(content.blogImage)}"
checkout if the slashes are necesarry and make sure that defaultBaseUrl is set properly in your magnolia configuration ("/server/...")
edit: there should be an easier by calling the current request in freemarker ${Request} so it could be something like "${Request.domain}/${ctx.contextPath}/${damfn.getAssetLink(content.blogImage)}" without injecting the serverConfiguration into the renderer
I want to wrap a mediawiki site inside another site - using the header.inc and footer.inc files that the rest of the website's html files use.
I'm not familiar with php, is there a 'masterpage' file somewhere I can put them in?
Your best bet would be to create a custom skin, or edit one of the default skins, such as monobook. They control most of the basic presentation code. Here is one short tutorial on creating a custom skin. The files usually live in the /skins/ folder; if you skim through one, you can find where the HTML begins and ends.
You can include another file using the PHP include function, like so:
<html>
...
<body>
<?php
include 'header.inc';
?>
...
For future reference in the LocalSettings.php you can also prevent users from using any other skin.
$wgDefaultSkin = 'myskin';
$wgAllowUserSkin = false;
$wgSkipSkins = array( "chick", "cologneblue", "monobook", "modern", "myskin", "nostalgia", "simple", "standard" );