Adding HTML to Drupal closure? - drupal-7

To add javascript, you can use:
drupal_add_js
And similar for css:
drupal_add_css
But what if I just want to add html at the end of my page. I.e. Add a div with some text in it at the end of the page?

A lot of suggestions here work if you want your alteration to be theme-based, but if you want this to come from a module, using a block region, page template or page prepocess won't cut it, because you're tying the alteration to the theme.
From a modular standpoint, the following options are best:
hook_footer() -- http://api.drupal.org/api/function/hook_footer/6 :: my_module_footer() should return a string of HTML, which can even be javascript. E.g.
function my_module_footer(){
return "<script type='text/javascript'>//your script</script>"
}
You can use drupal $_GET['q'] to get the page URL and have that return be conditional for the page URL.
Otherwise, I sometimes use $GLOBALS["_add_my_footer"] as a boolean, and set it at various points in the module, then in hook_footer(), see if it is true.
drupal_add_js -- api.drupal.org/api/drupal/includes--common.inc/function/drupal_add_js/6 :: You can use this to add javascript to the footer by setting the $scope parameter to "footer" -- e.g.
function my_module_init(){
$script = "your script "; // notice no <script> tags
drupal_add_js($script, 'inline', 'footer');
// you can also use this function to grab a .js file
}
Note that I put that drupal_add_js into hook_init() -- I did that because if you don't, the script could get lost when using Drupal's aggressive caching feature.
Unfortunately, there is no $scope parameter for drupal_add_css

As hook_footer did not survive Drupal 6, here's the equivalent function and how to implement it in Drupal 7:
/**
* Implements hook_page_alter().
*/
function example_page_alter(&$page) {
if (variable_get('dev_query', 0)) {
$page['page_bottom']['devel']= array(
'#type' => 'markup',
'#markup' => '<div style="clear:both;">' . devel_query_table() . '</div>',
);
}
}
(From http://preprocess.me/drupal-hookfooter-in-drupal-7)

You can add the following to your theme's template.php file:
function phptemplate_preprocess_page(&$vars) {
$vars['closure'] .= 'Add markup here';
}

Drupal has a hook you can implement and add in whatever code you'd like to the footer of the page - hook_footer. See http://api.drupal.org/api/function/hook_footer/6

You could write a block to do it and put the block in the closure.

...or, probably not as recommended as the other answers, but more direct, you can add the html straight to the page.tpl.php file.

There have already beed made some good suggestions:
Using a block
Editing templates
Using preprocess function.
The easiest thing would be to add a block that you create, where you can put your custom markup. You could even create a special template for it, so you don't get your usual drupal block markup, but only what you write in the block content.
That should cover your needs:
You have 100% control over where the markup is generated (You can define the region in your them)
You have 100% control over what markup is generated
Now if you don't want to use blocks, because you don't want the site admins to know about the block, the 2nd best thing would be:
Add a checkbox to your theme settings.
In your preprocess page hook, set a boolean variable if the checkbox is checked or not.
In your page template, you check for the variable, if it's TRUE you write your markup where you want it.
This will basically do the same thing as above, only you have the setting in your theme, instead of adding a block. It will require more work.
You can do pretty much the same in a custom module, but it wont make much sense to do this in a module, since it's purely presentation and you are dependent on your theme anyways.

here is a little trick that works in drupal 6 and 7
$script = '//--><!]]></script><strong>this is bold html code</strong><script type="text/javascript"><!--//--><![CDATA[//><!--';
drupal_add_js($script, 'inline', 'footer');
since it is apparent you don't want to modify the template files or use any of the other methods suggested above, this should work to add html to the page just like it does for js and css

I dont' recommend using block , as its overkill for just adding some elements on the footer.
Here is the hook that you can use to add the content before </body> tag for Drupal 7 .
function hook_page_build(&$page) {
$page['page_bottom']['YOUR_MODULE'] = array(
'#markup' => '<div> I want to get inserted at the bootom of the page </div>',
);
}

Related

Drupal 7 pass value from javascript to webform hidden field

I have a webform with some normal fields, but also some hidden fields which are set to Secure value (allows use of all tokens), so I am able to use tokens.
How do I pass values from JavaScript into those hidden fields so they are submitted with the form?
I tried using the %post[f1], %post[f2], and %post[f3] tokens, but I still don't know how to add those values with JavaScript.
You can use some basic jQuery for this.
$('input[name=INPUT_NAME]').val('NEW_VALUE');
To fully comply with Drupal theming, you probably want to wrap this up in a Drupal behavior:
(function ($) {
Drupal.behaviors.CUSTOMNAME = {
attach: function(context) {
$('input[name=INPUT_NAME]').val('NEW_VALUE');
}
}
})(jQuery);
...and of course change INPUT_NAME with the name attribute of the hidden input field and CUSTOMNAME with a descriptive camelcase name (e.g ChangeHiddenValuesForm).
As a final note: be sure to include this javascript file on the page of your form.
EDIT:
Sorry, I overlooked the Secure value reference.
Anyway, if you want the value to be secure then you shouldn't be altering it by Javascript as anyone can change it to whatever he or she likes through the DOM... That's why Webform implements the Secure value feature: the value does get submitted along with the form but simply won't be sent to the end user's browser and hereby disabling possible abuse. (For the record: Secure value uses the 'value' type from Drupal's Form API)
If you do want to change such a hidden value, you should opt for Hidden element (less secure, changeable via JavaScript) which already mentions its ability to be changed through Javascript and then use the Drupal behavior described above. Only if you do it like this it gets printed as a hidden input.
If you just want to add some JavaScript then use drupal_add_js(), for example in hook_preprocess_page() in a theme.
function mytheme_preprocess_page(&$vars, $hook) {
drupal_add_js(drupal_get_path('theme', 'mytheme') . '/mytheme.js');
$vars['scripts'] = drupal_get_js();
}

CakePHP - render whole page as HTML to attach to email

I have successfully created a report accessed at /controller/report
I now want to create a separate controller method to create this report as an HTML file and email it to designated useds. I have done this but have hit one snag. When the HTML file is rendered, it is only the view element from the /report method - the layout (including the CSS) is not rendered.
Here's the basic structure:
public function email_report() {
$render = $this->requestAction('/controller/report');
//$render is then used by fwrite to create a .HTML file, which is then attached to an email
}
public function report() {
//yada yada
//render in report layout rather than default
$this->render('report', 'reports');
}
So the problem is that $render only contains the view stuff, not the stuff from my "reports" layout. What do I need to do to get the layout in my HTML file as well?
I could put all of the HTML in the view but I would like to create other reports using the same layout in future and would like to avoid repetition.
use the following instead. Note the extra array argument passed to the function
bare indicates whether or not to include layout. setting it to 0 i.e false forces it to include layout. Including return sets requested to 1. requested indicates whether request is from requestAction or not.
Visit http://book.cakephp.org/2.0/en/controllers/request-response.html and http://book.cakephp.org/2.0/en/controllers.html for reference
$this->requestAction('/controller/report', array('return', 'bare' =>
0));

Marionette.js: Should regions replace instead of insert?

The default behavior of marionette.js is to append a template into the element specified by the regions selector. However, I usually end up having to create a special region type and override the appendHtml function to do a replace instead.
That is not too difficult, but why is append the default?
I usually will create the layout template with an empty div to specify where the region should go. Then I replace that div with sub template when I show it.
I guess am wondering if there I'm missing the design pattern for templates that makes append more intuitive.
Thanks for the help.
Update:
So I usually will have some view for something I want rendered into the page and will want to todd n element onto the page where I want it. I will do javascript that will look something like this:
ReplaceRegion = Marionette.Region.extend({
open: function(view){
this.$el.replaceWith(view.el);
}
});
App = new Backbone.Marionette.Application();
App.addRegions({
myRegion: {
selector: "#someRegion",
regionType: ReplaceRegion
}
};
var view = new CoolWidgetView();
App.myRegion.show(view);
And then somewhere in my html I'll throw an empty div in the mix where I want my template to show up.
<div id="mywidget"></div>
Now if it is the only child element, I can use a selector that would just be the parent, but that becomes more tricky when the view i'm inserting has siblings.
Also, I'm not really asking for a change to the default, as much as I'm wondering if there's a better way to insert items where you would like them in your layouts. I'm still relatively new to the layout and design of these things so anything helps!
Thanks Derick for writing great software!
Marionette regions provide both a show and a close method. Have you tried closing the region before you show the new one?
Marionette.Region docs

render a blank view in cakephp

i need to prevent a view to be rendered in a specified case but i can't understand how to prevent it to render.
I tried
$this->autoRender=false
but nothing happened, probably because i'm using an API engine that manage rendering differently from regular controllers. Anyone know any trick to do this?
Using $this->layout = 'ajax' does not seem to be enough.
But using these both lines works:
$this->layout = 'ajax';
$this->render(false);
While searching for a solution, I found this answer. Now when using CakePHP 2.4.x, you could use the following code in your controller:
$this->layout = false;
This will lead to just the view being rendered, without a layout.
It's an old question. The current cake-version is 3.x and there is a easy way to use a blank layout.
Only add the in the controller:
$this->viewBuilder()->autoLayout(false);
Try to use ajax layout $this->layout = 'ajax' this is the default empty layout, which is used for ajax methods.
public function function_without_layout(){
$this->viewBuilder()->autoLayout(false);
echo "hello Brij";
exit;
}
$this->layout = false; is deprecated in CakePHP version 3.
Use $this->viewBuilder()->autoLayout(false); for CakePHP version 3.
Add this in your controller:
$this->autoRender = false;
This works in my project.
The CakePHP 3 autoLayout(false) method from the other answer will still have the system try to locate a corresponding view/template file for the action you're calling. Since I needed no output at all, this didn't work for me, so I needed to also render an empty template.
Creating a blank .ctp file for every empty action you might need isn't an option really, because you'd normally want to have one and reuse it. CakePHP 2 had a $this->viewPath property which would let you configure the controller to look into the app/View folder, but it's CakePHP 3 alternative still looks into the corresponding controller and prefix folders. There is a not-so-obvious way to force CakePHP3 to look for a template in a root view path.
Create src/Template/my_blank_view.ctp
Add the following to your controller action:
$this->viewBuilder()->layout(false);
$this->viewBuilder()->templatePath('.'); // this
$this->viewBuilder()->template('my_blank_view');
Also, I'm using $this->viewBuilder()->layout(false) instead of autoLayout(false) because the latter kind of implies that there might be another layout set later, where the layout(false) just explicitly sets that there's no layout needed.
without knowing anything about API engine you're using, maybe try to make empty layout with empty content and call it in controller as $this->layout = 'empty_layout'

CakePHP - How to have a modal layout

I am dynamically loading content into my modals, and often it will be a page that is already a normally accessible page on my site.
So I want to be able to reuse that controller/action and load it into my modal but obviously the controller already uses a layout. So when I load the page into my modal, the header and footer of my site is all in the modal again, which I don't want.
One solution I thought of that might work, but seems like a dirty workaround, is to have in my Appcontroller a check for a URL parameter that says it is a modal call for the page (not a regular call). It then overrides the layout with a special modal one.
//app_controller.php
public function beforeRender() {
if (isset($this->params['passed']['_modal'])) {
$this->layout = 'modal';
}
}
// In my jQuery call to open the modal:
myModal.load('users/view/5/_modal').dialog('open');
Then in the modal.ctp layout I would include a stylesheet that looks something like:
// modal_layout.css
#import url("normal_layout.css");
.header, .footer {display:none;}
So I don't have to redefine all of my normal layout's CSS but I can just hide the parts I don't want to show.
This seems like a bit of a stupid method of doing it, and I don't know if it even works, but surely someone has had to do this before with CakePHP, so what would you guys suggest?
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
}
Now you can configure your Layout/ajax.ctp as you want.
You could create an element.
$('#myModal').load("<?=url('users/view/5/_modal')?>", {type:'post'}, function(){
$('#myModal').dialog({title:'open',autoOpen:false, modal:false, height:600, width:700});
$('#myModal').dialog('open');
});
function view($my_customer_id, action) {
//do stuff here
$this->render(DS.'elements'.DS.'users'.DS.'modal');
}
use RequestHandler to detect ajax request. Put this line at the end of your action:
if ($this->RequestHandler->isAjax())$this->render('view_name','ajax');
It turned out I didn't need to anything so complex. I simply created a hidden div in my layout:
<div id="modal"></div>
And then in my layout's existing CSS I added certain rules to hide elements I don't want to see when a page is loaded in a modal:
#header, #footer {display:none;}
That way I can load a page into the modal but it still has all the normal styling that is already defined in the layout's CSS. Pages are loaded into the modal by using their normal CakePHP URL:
$('#modal').load('controller/action/param:whatever').dialog('open');
If you want the content of your modal dialog box to be simply the content of the view of an action you simply need to add the following a the top of the controller's action:
$this->layout = null;
This will disable the layout and all output the content{html} of the view

Resources