I'm working on a new Moodle Assignment plugin.
How can I include a custom CSS to my plugin?
I'm using Moodle 1.9.7.
Thanks in advance.
just add a file called styles.php into the Module's folder.
the file should output CSS code when it is parsed.
Moodle goes into each Module's folder and looks for that file, when the page's CSS layout is constructed.
Some themes can ignore these files using a special setting in the theme's config.php file
$THEME->modsheets = true;
/// When this is enabled, then this theme will search for
/// files named "styles.php" inside all Activity modules and
/// include them. This allows modules to provide some basic
/// layouts so they work out of the box.
/// It is HIGHLY recommended to leave this enabled.
here is a short sample of what could be the content of this styles.php file:
/* simple CSS code */
.left { float:left; }
/* php that generate CSS code */
< ?php if ( right_to_left() ) {echo ".right:text-align:left;"}
else {echo ".right:text-align:right;"} ?>
Perhaps could take a look at the function print_header_simple() defined in lib/weblib.php.
If you are writing a module which generates module specific pages, and they use the normal moodle libraries then stick something in $meta to be added to the <head> section while the page is being generated.
in lib/weblib.php:
function print_header_simple($title='', $heading='', $navigation='', $focus='', $meta='', $cache=true, $button=' ', $menu='', $usexml=false, $bodytags='', $return=false) {
This means that you probably want something like the following in your module:
$extra_css = $CFG->wwwroot.'/theme/SUPA4/supa_report.css';
$extra_css_meta = '<link rel="stylesheet" type="text/css" href="'.$extra_css.'" />';
print_header_simple($mytitle, "", $navigation, "", "", true, "", navmenu($course), '', $extra_css_meta);
Related
I would like my custom Drupal 8 module to force a different template for pages that match a certain URL. Here is my module structure:
/sass_edit
/css
/js
/template
builder_template.html.twig // this is the template file
sass_edit.module
...
sass_edit.*.yml // various yml files
These are the contents of builder_template.html.twig:
<h1>test</h1>
Here are the relevant lines of code in my .module file:
function sass_edit_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
$current_path = \Drupal::service('path.current')->getPath();
if(\Drupal::currentUser()->isAuthenticated() && strpos($current_path, "/builder/") >= 0) {
$suggestions[] = 'builder_template';
}
// kint($suggestions);
// die();
}
When I visit a page whose URL contains /builder/, the code runs and adds the string builder_template to the $suggestions array. However, when the page is rendered, the new template is ignored. I have tried flushing caches, with no results.
I'm not sure how to proceed. All the documentation I've found refers to adding theme suggestions from a custom theme, not a custom module.
Any idea what I'm doing wrong? Thank you so much for any help!
Maybe you have a typo in the code you pasted but the folder where you have your templates overrides should be templates and not template as you wrote. Don't forget to flush caches after changing the name of the directory ;)
My website is www.kipclip.com and it's running on Kohana. I created a new rental page. But it's not taking my CSS and JS files. I tried to find how this is included or if Kohana has a special method for do that. But still not successful. Do you have any idea regarding this?
A quick and dirty way to do so is to tack on the name of the script(s) and style(s) in the view you're implementing using regular html script and style tags and go on from there.
But, if you don't like quick and dirty, and prefer to do it better and more concrete, if you use Kohana 3.2, you can do the following. I haven't tried this on the older or newer versions, so it may or may not work in them (If you try to port it to that version, consult the transitioning document relative to the version in question that you wish to port):
/**
* /application/classes/controller/application.php
*/
abstract class Controller_Application extends Controller_Template {
public function before() {
parent::before();
if($this->auto_render) {
//Initialize empty values for use by ALL other derived classes
$this->template->site_name = '';//this is a psuedo-global set in this class
$this->template->title = '';//this too is set by the controller and action
$this->template->content = ''; //this is set by the controller and action
$this->template->styles = array();
$this->template->scripts = array();
$this->template->admin_scripts = array();
}
}
/**
* The after() method is called after your controller action.
* In our template controller we override this method so that we can
* make any last minute modifications to the template before anything
* is rendered.
*/
public function after()
{
if ($this->auto_render) {
//set the CSS files to include
$styles = array(
'style1', //the css file with all the defaults for the site
'jquery-library-css'
);
//set the JavaScript files to include
$scripts = array(
'myscript1',
'myscript2'
);
$admin_scripts = array(
'jquery-admin-functions',
);
//now, merge all this information into one so that it can be accessed
//by all derived classes:
$this->template->styles = array_merge($this->template->user_styles, $user_styles);
$this->template->scripts = array_merge($this->template->user_scripts, $user_scripts);
$this->template->admin_scripts = array_merge($this->template->admin_scripts, $admin_scripts);
}
//bind the site_name to the template view
$this->template->site_name = 'My Site Name';
//OLD WAY shown below:
View::set_global('site_name', 'My Site Name'); //set the site name
//now that everything has been set, use parent::after() to finish setting values
//and start rendering
parent::after();
}
}
So, how does this work? Remember that the application.php class is the base controller class from which all other controller classes are derived from. By implementing this type of binding to the base controller, every derived controller has access to what scripts, styles, etc. are available. And, as a result every associated view called by that controller also has access to those variables.
So, now to access those variables in your view:
Example, the template PHP file: /application/views/template.php
If it's defined like this (using PHP short tags - but do not use short tags in production code!):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>
<html>
<head>
<meta charset='utf-8'/>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<?php
/**
* Link the css files stored in the `static` folder from the project root.
* This will vary depending on how you have your files saved.
*/
foreach($user_styles as $style) : ?>
<link rel="stylesheet" href="<?php echo URL::base() . 'static/css/' . $style ?>.css" type="text/css"/>
<?php endforeach; ?>
<?php //Create AND set a dynamic page title - much like Facebook ?>
<title><?php echo $site_name; if(!empty($title)) echo ' - ' . $title; ?></title>
</head>
<body>
<!-- Fill in the body with HTML, PHP - whatever you want -->
<?php
/**
* Now, load the scripts:
* According to Yahoo, for better site performance, all scripts should be loaded after the body has been loaded
*/
foreach($user_scripts as $script) : ?>
<script src="<?php echo URL::base() . 'static/js/' . $script; ?>.js" type="text/javascript"></script>
<?php endforeach; ?>
</body>
</html>
There are two takeaway points from all of this:
One: If you want something to be global, or available to all controllers (and subsequent views), define them and bind them in the base application controller class.
Two: As a result, this functionality also gives you tremendous leverage and power in that if you have derived classes, you can them implement this same type of binding to that particular controller class making it available to any subsequent derived controller classes. That way, if you have two classes that should not have access to certain files and their associated functionality, e.g. an admin JavaScript file that loads all posts by some user, then this kind of implementation can make your life much, much, much easier.
And, a third hidden option is that give Kohana is PHP, you can use regular vanilla PHP / HTML in an associated view if you can't figure it out immediately. Although, that is something that I would dissuade you from doing in production code.
Whichever way, I hope this can assist you.
I am developing one module in prestashop 1.5 . i need to give some designs(css) when my module is accessed by the admin in admin panel.I am new to prestashop.. can anyone help me..
Simply add in hookHeader :
$this->context->controller->addCSS($this->_path.'style.css', 'all');
I hope this help,
Mike
I've found a better way. There's a more specific hook for this: displayBackOfficeHeader.
That ensure your context will be only back office and never front office.
Also, to be sure it will work only in specific circumstances (for example only in the configure page), you can check the url vars.
So, first, in install() add the register function (and be sure to reset the module so the hook will work):
$this->registerHook('displayBackOfficeHeader');
Also add the unregister code in uninstall():
$this->unregisterHook('displayBackOfficeHeader');
Then add the relative function. In this example I'm checking if I'm in the configure page (imagebanner is the name of the module):
public function hookDisplayBackOfficeHeader($params){
if(!(Tools::getValue('controller') == 'AdminModules' && Tools::getValue('configure') == 'imagebanner')){
return;
}
$this->context->controller->addCSS($this->_path.'back-office.css', 'all');
}
Also, take a look to the docs.
Hope it helps!
[EDIT]
I've just found that the code above adds the files at the beginning of the stack, not at the end. That means, for example, BEFORE jquery. It seems there's no way to control the injection order. Anyway, for now, I've found a simple solution: return directly the html code:
public function hookDisplayBackOfficeHeader($params){
if(!(Tools::getValue('controller') == 'AdminModules' && Tools::getValue('configure') == 'homebanners')){
return;
}
$html = '';
$html .= '<link href="'.$this->_path.'back-office.css" rel="stylesheet" type="text/css" media="all" />';
$html .= '<script src="'.$this->_path.'back-office.js" type="text/javascript" ></script>';
return $html;
}
It works because if you take a look to the admin header.tpl, you see that that Hook is in fact placed AFTER the js/css incusion code. So it just works. The addCSS/JS methods instead, work independently, and do not take into account the hook position at all.
im facing the same issue too...
i think the only way is to hack into
[path-to-project]/[admin-path]/themes/default/template/helper/form/form.tpl
and add in block {block name="before"}{/block}
and add this block into your form.tpl into your controller template:
[path-to-project]/[admin-path]/themes/default/template/controllers/[yourcontrollername]/helpers/form/form.tpl
{block name="before"}
<style>
/* your style here */
</style>
{/block}
for more information, you may refer my blog post here:
http://mercstudio-tech.blogspot.com/2013/05/prestashop-form-field-type.html
How can I modify or pre-process the <body> tag to add the class body? I don't want to create a whole html.tpl.php just to add a class.
In your theme's template.php file use the preprocess_html hook:
function mytheme_preprocess_html(&$vars) {
$vars['classes_array'][] = 'new-class';
}
Remember to clear the caches once you've implemented the hook or Drupal won't pick it up.
The documentation for the html.tpl.php template documents the $classes variables as String of classes that can be used to style contextually through CSS.. If you look at the code for the template, this variable is used in the class attributes of the produced body element:
<body class="<?php print $classes; ?>" <?php print $attributes;?>>
The $classes variables is actually already set by template_process() for any template file and build from the content of the $classes_array variable.
So to add a class to the body of your page, you should add this class to the $classes_array value from your theme (or module)'s implementation of hook_preprocess_html():
function THEME_preprocess_html(&$variables) {
$variables['classes_array'][] = 'new-class';
}
Since this is the core defined template and process function, any well-behaving theme should re-use the same variables.
I had to use different array keys in the same hook to make it work:
function THEME_preprocess_html(&$vars) {
$vars['attributes_array']['class'][] = 'foo2';
}
The Context module allows you to add a class to the body tag as well.
This can be useful if you need the class to be added under certain conditions.
You find this options under the reaction "Theme HTML" :
The answer appears to depend on context. Here's what I've found via trial-and-error:
If your hook_preprocess_html() is in a module, use $vars['classes_array'][].
If it's in a theme, use $vars['attributes_array']['class'][].
Common Body Class module provide users to add classes to any page through the an interface.
The interface has options to select multiple user roles as well as pages where the class can be rendered.
I applied this technique on a site that someone else built. It didn't work at first but then dug deeper and found that the $classes variable was not being output in the tpl file. So if it's not working, check that.
For Drupal 7 install http://drupal.org/project/body_class. It will help you to add seperate classes for each node in body tag
You can check "https://www.drupal.org/project/page_specific_class" to add class to body tag of any page
It's a simple way to add a class based on the URL, Drupal 9.
No need to enable the Modules.
/**
* Implements hook_preprocess_html().
*/
function THEME_NAME_preprocess_html(&$variables) {
// Get the current path
$current_path = \Drupal::service('path.current')->getPath();
$internal_path = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);
// Assign it to body class
$variables['attributes']['class'][] = str_replace("/", "", $internal_path);
}
Refer: http://www.thirstysix.com/how-can-i-add-body-class-based-path-page-specific-class-drupal-9
EDIT: My question applies to Drupal 6 & 7, though my code example is Drupal 6. People have provided answers are useful for both versions of Drupal.
I'm currently working in Drupal creating a mobile theme for a Drupal 6 website and trying to remove all unnecessary core and module JavaScript and css through the preprocess_page function in my template.php file. The css files are successfully removed, but I can't seem to get the JavaScript to be removed. Here's what I've got. In this example, everything is successfully removed except for the the ajax scripts.
Any idea what I'm doing wrong?
<?php
function mytheme_preprocess_page(&$vars) {
//////// remove unneccesary drupal head files for mobile version
// CSS
$css = drupal_add_css();
// core
unset($css['all']['module']['modules/user/user.css']);
unset($css['all']['module']['modules/node/node.css']);
unset($css['all']['module']['modules/system/defaults.css']);
unset($css['all']['module']['modules/system/system.css']);
unset($css['all']['module']['modules/system/system-menus.css']);
// contributed -- automatically generate the path—— just easier this way
$rm[] = drupal_get_path('module','filefield').'/filefield.css';
$rm[] = drupal_get_path('module','flickr').'/flickr.css';
$rm[] = drupal_get_path('module','logintoboggan').'/logintoboggan.css';
$rm[] = drupal_get_path('module','logintoboggan').'/logintoboggan.css';
$rm[] = drupal_get_path('module','fieldgroup').'/fieldgroup.css';
$rm[] = drupal_get_path('module','views').'/css/views.css';
$rm[] = drupal_get_path('module','content').'/theme/content-module.css';
// remove the contribs from the array
foreach ($rm as $key => $value) {
unset($css['all']['module'][$value]);
}
// JAVASCRIPT
$scripts = drupal_add_js();
unset($scripts['module']['sites/all/modules/ajax/ajax.js']);
unset($scripts['module']['sites/all/modules/ajax/jquery/jquery.a_form.packed.js']);
// recreate the tempalate variables
$vars['styles'] = drupal_get_css($css);
$vars['scripts'] = drupal_get_js('header', $scripts);
}
?>
ETA: Here is the way the scripts print out in the header:
<script type="text/javascript" src="/sites/all/modules/ajax/jquery/jquery.a_form.packed.js?P"></script>
<script type="text/javascript" src="/sites/all/modules/ajax/ajax.js?P"></script>
I found a potentially better solution for this sort of problem. I tried Kerri's approach since Matt V says it worked for him, but I really didn't want to edit template.php if I could avoid it and regardless it wasn't working in my environment. My problem was that a couple JS files throw errors on one particular page. All I did was write a very simple new module that only runs on the desired page. So- I created a basic .info file and below is the .module code. Worked like a charm for me. Just replace "mysite_mymodule" with whatever you name your module and replace "my-page-alias" with whatever page alias you're trying to effect.
<?php
/**
* Implements hook_js_alter().
*/
function mysite_mymodule_js_alter(&$javascript) {
$alias = drupal_get_path_alias($_GET['q']);
if ($alias == "my-page-alias") {
/**
* documentation about what I did and why I did it...
*/
unset($javascript['sites/all/modules/dhtml_menu/dhtml_menu.js']);
unset($javascript['sites/all/modules/apachesolr_autocomplete/apachesolr_autocomplete.js']);
}
}
You can directly use the drupal header in drupal 7.
you can clean the other module javascript you don't need
function module_preprocess_page(&$vars) {
// clean unnecesary script from the page
if (arg(0) != 'admin' || !(arg(1) == 'add' && arg(2) == 'edit') || arg(0) != 'panels' || arg(0) != 'ctools') {
$javascript = &drupal_static('drupal_add_js', array());
unset($javascript['misc/jquery.js']);
unset($javascript['misc/jquery.once.js']);
drupal_static('drupal_add_js', $javascript);
}
}
The Ajax module uses hook_preprocess_page to add its scripts. The Ajax module may be executing its hook implementation after your module. If that's the case, you could adjust the weight of your module, to fire after Ajax. You could check first to make sure, by outputting the contents of $scripts (using something like the Devel module's dpm() function), just before you do the unsetting.
UPDATE: Since you're making the changes in a template preprocess function, my initial hypothesis about it being an issue of module weights wouldn't apply. I added your template function on a test site and it removed those two scripts, for me. I had to adjust the path because my ajax module was under /sites/all/modules/contrib. That's just where I happen to keep my contrib modules, but you might double check that you're using the right path.
Another thing that threw me off for a few minutes was that I accidentally added the code to the wrong theme; so, that's another thing to check. Also, check that Javascript caching is disabled on the Performance page.
You have to do it the other way around. Unsetting files of other contrib modules explicitly couples your module to every other module that outputs js to the header. You won't be able to maintain that for too long before it breaks. What happens when more js files get added by contrib modules?
You're best to create a mask of paths you want to output and unset everything except those.
Drupal 7 has some hooks that will let you do that but I can't remember them. If you're on D6 you're kinda stuck.
I did write a dirty workaround for Drupal 6 for this same problem with css files. Here is the whole module (it was only 3 functions). I'm sure you can adapt it to js files too.
Create your mask (expose it to the variables table)
function destroy_mask_styles() {
return variable_get('destroy_mask_styles', array('all/modules/mymodule', 'themes/mytheme'));
}
Then here comes the dodgey part. This function looks for the paths of the css files in the header and unsets them if they don't match.
function destroy_styles($var_styles) {
//this is a bit dodgey. But it's probably the easiest way to implement
$masks = destroy_mask_styles();
$styles = array();
foreach(explode("\n", $var_styles) as $style) {
foreach($masks as $mask) {
if(strpos($style, $mask) > 0) {
$styles[] = $style;
}
}
}
return implode("\n", $styles);
}
Then in preprocess_page, (this might be considered where the dodgyness happens)
function destroy_preprocess_page(&$variables) {
//destroy some css and scripts we don't want
$styles = destroy_styles($variables['styles']);
$variables['styles'] = empty($styles) ? $variables['styles'] : $styles;
}
If you want to include everything from one module (for example), just alter the paths that get matched to include the path to the module's root folder. Don't worry about file names.
Remember that this is not the ideal way to do this. There might be a better way in D6 but there are no hooks here so probably not.
Good luck!