Why content appears misplaced? - drupal

I am building a custom module which should display a calendar created by a third-part library. So far, so good. The only problem is, the calendar appears on top of page, even above header. It does not seems to be css-related.
This is the way it looks:
This is my module file:
require_once 'includes/apphp-calendar/calendar.class.php';
function calendario_menu(){
$items = array();
$items['eventos/calendario'] = array(
'title' => 'Calendario',
'description' => 'Calendario de Eventos.',
'page callback' => '_page_calendario',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
function _page_calendario() {
$objCalendar = new Calendar();
$calendar = $objCalendar->Show();
return array(
'#markup' => $calendar
);
}

Seems to me like the Show function of the calendar class outputs rather than returning a string.
try this:
function _page_calendario() {
$objCalendar = new Calendar();
ob_start();
$objCalendar->Show();
$calendar = ob_get_contents();
ob_end_clean();
return array(
'#markup' => $calendar
);
}

Related

Batching with Google Places: Is it possible?

I was wondering if it's possible to send batched requests to maps.googleapis.com. As far as I can tell, it isn't.
I was using the Google API Client Library with supports batching, but it's only for www.googleapis.com. I went ahead and hacked it so that I could call the Places API, and it worked fine for normal calls, but when I actually tried to batch them, I got a 404 error:
"The requested URL /batch was not found on this server. That’s all we know."
So it appears that maps.googleapis.com does not support batching, but I wanted to be sure this is true. If anyone knows otherwise, please tell me how. Thanks!
inside google-api-php-client/src/Google/Config.php:
- 'base_path' => 'https://www.googleapis.com',
+ 'base_path' => 'https://maps.googleapis.com',
google-api-php-client/src/Google/Service/Maps.php:
(I added this file to make Places calls possible.)
<?php
class Google_Service_Maps extends Google_Service
{
const MAPS = "https://maps.googleapis.com/auth/maps";
public function __construct(Google_Client $client)
{
parent::__construct($client);
$this->servicePath = 'maps/api/';
$this->version = 'v3';
$this->serviceName = 'maps';
$this->places = new Google_Service_Maps_Places_Resource(
$this,
$this->serviceName,
'places',
array(
'methods' => array(
'autocomplete' => array(
'path' => 'place/autocomplete/json',
'httpMethod' => 'GET',
'parameters' => array(
'input' => array(
'location' => 'query',
'type' => 'string',
'required' => true,
),
'sensor' => array(
'location' => 'query',
'type' => 'boolean',
'required' => true,
),
'location' => array(
'location' => 'query',
'type' => 'string',
),
'radius' => array(
'location' => 'query',
'type' => 'integer',
),
),
),
)
)
);
}
}
class Google_Service_Maps_Places_Resource extends Google_Service_Resource
{
public function autocomplete($input, $lat, $lng, $radius, $optParams = array())
{
$params = array('input' => $input, 'location' => "$lat,$lng", 'radius' => $radius, 'sensor' => false);
$params = array_merge($params, $optParams);
return $this->call('autocomplete', array($params));
}
}
API batch calling code:
<?php
const API_KEY = 'MY_API_KEY';
set_include_path("google-api-php-client/src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Maps.php';
require_once 'Google/Http/Batch.php';
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey(API_KEY);
$client->setUseBatch(true);
$batch = new Google_Http_Batch($client);
$service = new Google_Service_Maps($client);
$inputs = array(
'Dolore',
'MacAl',
'App Aca'
);
foreach($inputs as $input) {
$req = $service->places->autocomplete($input, 37.7833, -122.4167, 500);
$batch->add($req, $input);
}
$results = $batch->execute();
print_r($results);
print_r($req);

How do I trigger a Drupal-Function with Javascript/jQuery?

I have a Checkbox with different values. When a user change the Checkbox I will trigger the Drupal-Function field_attach_update http://api.drupal.org/api/drupal/modules!field!field.attach.inc/function/field_attach_update/7
I know how I check the checkbox-change with jQuery but how can I trigger the Drupal-Function then?
You'll want to check out the Form API ajax options. Specifically I think you'll want to define an ajax['callback'] function that calls field_attach_update.
<?php
function my_form_func($form, $form_state) {
$my_checkbox_val = isset($form_state['values']['my_checkbox']) ? $form_state['values']['my_checkbox'] : NULL;
$form['my_checkbox'] = array(
'#type' => 'checkbox',
'#title' => t('Check me'),
'#default_value' => $my_checkbox_val,
'#return_value' => $nid, // Assuming you are working with a node, but could be any entity
'#ajax' => array(
'callback' => 'my_form_field_update_func',
'event' => 'click',
),
);
return $form;
}
function my_form_field_update_func($form, $form_state) {
if (isset($form_state['values']['my_checkbox'])) {
$node = node_load($form_state['values']['my_checkbox']);
field_attach_update('node', $node);
}
return $form['my_checkbox'];
}
?>

how to pass variable from custom module to its tpl

I need to know the simplest method to pass variable from custom module to its template
I have created the custom.module and placed custom.tpl.php in the module folder
function custom_menu(){
$items = array();
$items['custom'] = array(
'title' => t('custom!'),
'page callback' => 'custom_page',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
function custom_page() {
$setVar = 'this is custom module';
return theme('custom', $setVar);
}
i have added theme function but it is not working, can any one suggest me what is wrong with this code
function theme_custom($arg) {
return $arg['output'];
}
function custom_theme() {
return array(
'Bluemarine' => array(
'variables' => 'output',
'template' => 'Bluemarine',
),
);
}
You are calling the wrong theme function. Instead of function theme_custom it should be function theme_Bluemarine. You also need to pass an array to the variables piece of hook_theme(). See a simple example here.
Using your example:
function custom_menu(){
$items = array();
$items['custom'] = array(
'title' => t('custom!'),
'page callback' => 'custom_page',
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function custom_page() {
$setVar = 'this is custom module';
return theme('custom', array('output' => $setVar));
}
function custom_theme() {
$path = drupal_get_path('module', 'custom');
return array(
'custom' => array(
'variables' => array('output' => null),
'template' => 'custom',
),
);
}
Now in custom.tpl.php just need <?php print $output; ?>
This works for me:
function custom_menu(){
$items = array();
$items['custom'] = array(
'title' => t('custom!'),
'page callback' => 'custom_page',
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function custom_page() {
$result = db_query('SELECT * from node');
return theme('custom', array('output' => $result));
}
function custom_theme() {
return array(
'custom' => array(
'arguments' => array('output' => NULL),
'template' => 'custom',
),
);
}
function template_preprocess_custom(&$variables) {
}
First, you've to declare you theme and how its behave with the help of hook_theme. After you can easily use the function theme.
Also, maybe you will need to use the hook_preprocess.

Drupal autocomplete, callback with multiple parameters

I am adding some autocomplete on a form alter. The problem is that in the callback, only the string in the textfield The autocomplete is on, is available. I also want to access a value from another textfield in the callback. How is this possible ?
/**
* Implements hook_form_alter().
*/
function webform_conversion_jquery_form_webform_client_form_1_alter(&$form, &$form_state, $form_id) {
//Load some extra function to process data
module_load_include('inc', 'webform_conversion_jquery', '/includes/dataqueries');
//Add extra js files
drupal_add_js(drupal_get_path('module', 'webform_conversion_jquery') . '/js/conversionform.js');
$form['submitted']['correspondentadress']['cor_street']['#autocomplete_path'] = 'conversionform/conversion_street';
}
}
/**
* Implements hook_menu().
*/
function webform_conversion_jquery_menu() {
$items = array();
$items['conversionform/conversion_street'] = array(
'title' => 'Conversion street autocomplete',
'page callback' => 'conversion_street_autocomplete',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Retrieve a JSON object containing autocomplete suggestions for streets depending on the zipcode.
*/
function conversion_street_autocomplete($street = '') {
$street = "%" . $street . "%";
$matches = array();
$result = db_select('conversion_adresslist')
->fields('conversion_adresslist', array('street'))
->condition('street', $street, 'like')
->execute();
foreach ($result as $street) {
$matches[$street->street] = $street->street;
}
drupal_json_output($matches);
}
I just want to be able to post extra information in the function:
conversion_street_autocomplete($street = '', $extraparameter)
I had the same problem and have figured out a way, which is not too strenuous. It involves overriding the textfield theme and then passing your parameter to the theme function.
First create declare your theme function:
function mymodule_theme() {
$theme_hooks = array(
'my_module_autocomplete' => array(
'render element' => 'element',
),
);
return $theme_hooks;
}
Next we need to add the theme and the variable to our form element. In my case, the form element is part of a field widget:
function my_module_field_widget_form($form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
if($instance['widget']['type'] == 'my_module_field_type') {
$element['my_module_field'] = array(
'#type' => 'textfield',
'#autocomplete_path' => 'my-module/autocomplete',
// THIS IS THE IMPORTANT PART - ADD THE THEME AND THE VARIABLE.
'#theme' => 'my_module_autocomplete',
'#my_module_variable' => $field['field_name'],
);
}
return $element;
}
Then implement the theme function. This is a copy of theme_textfield from includes/form.inc with one important difference - we append the variable to the autocomplete path:
function theme_my_module_autocomplet($variables) {
$element = $variables['element'];
$element['#attributes']['type'] = 'text';
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
_form_set_class($element, array('form-text'));
$extra = '';
if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
drupal_add_library('system', 'drupal.autocomplete');
$element['#attributes']['class'][] = 'form-autocomplete';
$attributes = array();
$attributes['type'] = 'hidden';
$attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
// THIS IS THE IMPORTANT PART. APPEND YOUR VARIABLE TO THE AUTOCOMPLETE PATH.
$attributes['value'] = url($element['#autocomplete_path'] . '/' . $element['#my_module_variable'], array('absolute' => TRUE));
$attributes['disabled'] = 'disabled';
$attributes['class'][] = 'autocomplete';
$extra = '<input' . drupal_attributes($attributes) . ' />';
}
$output = '<input' . drupal_attributes($element['#attributes']) . ' />';
return $output . $extra;
}
Now the variable will be available as the first parameter on the autocomplete callback function:
function _my_module_autocomplete($my_module_variable, $search_string) {
// Happy days, we now have access to our parameter.
}
Just in case anyone is still having trouble with this I found a great solution while trying to figure out how to do this. I had a year select list and that dictated what data was displayed in the autocomplete field. The solution basically has an ajax callback function for the select list that can then update the autocomplete field with an extra parameter in the url. Anyways, it is really well explained in the following article.
http://complexdan.com/passing-custom-arguments-drupal-7-autocomplete/
*A note of caution, I was going crazy trying to figure out why it did not work and it turns out you can't have the same form on the page twice (I needed to because I was displaying it differently for mobile devices) because you are using an id for the ajax callback. I added an extra argument to accomplish that. It is called uniqueid in the below example.
function report_cards_comparison_form($form, &$form_state, $uniqueid) {
$curryear = t('2012');
$form['year_select'] = array(
'#title' => t('School Year'),
'#type' => 'select',
'#options' => array(
'2012' => t('2012'),
'2013' => t('2013'),
'2014' => t('2014'),
'2015' => t('2015'),
),
'#default_value' => $curryear,
'#ajax' => array(
'callback' => 'report_cards_comparison_form_callback',
'wrapper' => $uniqueid,
'progress' => array(
'message' => 'Updating Schools...',
'type' => 'throbber'
),
),
);
$form['choice'] = array(
//'#title' => t('Search By: School Name'),
'#type' => 'textfield',
'#attributes' => array(
'class' => array('school-choice'),
'placeholder' => t('Start Typing School Name...'),
),
'#required' => TRUE,
'#autocomplete_path' => 'reportcards/autocomplete/' . $curryear,
'#prefix' => '<div id="' . $uniqueid . '">',
'#suffix' => '</div>',
);
$form['submit'] = array(
'#type' => 'submit',
'#prefix' => '<div class="submit-btn-wrap">',
'#suffix' => '</div>',
'#value' => t('Search'),
'#attributes' => array('id' => 'add-school-submit'),
);
return $form;
}
/**
* Ajax Callback that updates the autocomplete ajax when there is a change in the Year Select List
*/
function report_cards_comparison_form_callback($form, &$form_state) {
unset($form_state['input']['choice'], $form_state['values']['choice']);
$curryear = $form_state['values']['year_select'];
$form_state['input']['choice'] = '';
$form['choice']['#value'] = '';
$form['choice']['#autocomplete_path'] = 'reportcards/autocomplete/' . $curryear;
return form_builder($form['#id'], $form['choice'], $form_state);
}
and I can call the form by doing this...
print render(drupal_get_form('report_cards_comparison_form', 'desktop-schoolmatches'));
You can do it by overriding methods from autocomplete.js in your own js. Here is example:
(function($) {
Drupal.behaviors.someModuleOverrideAC = {
attach: function(context, settings) {
// Next is copied and adjusted method from autocomplete.js
Drupal.jsAC.prototype.populatePopup = function() {
var $input = $(this.input);
var position = $input.position();
// Show popup.
if (this.popup) {
$(this.popup).remove();
}
this.selected = false;
this.popup = $('<div id="autocomplete"></div>')[0];
this.popup.owner = this;
$(this.popup).css({
top: parseInt(position.top + this.input.offsetHeight, 10) + 'px',
left: parseInt(position.left, 10) + 'px',
width: $input.innerWidth() + 'px',
display: 'none'
});
$input.before(this.popup);
// Do search.
this.db.owner = this;
if ($input.attr('name') === 'field_appartment_complex') {
// Overriden search
// Build custom search string for apartments autocomplete
var $wrapper = $('div.apartments-autocomplete');
var $elements = $('input, select', $wrapper);
var searchElements = {string: this.input.value};
$elements.each(function() {
searchElements[$(this).data('address-part')] = $(this).val();
});
var string = encodeURIComponent(JSON.stringify(searchElements));
this.db.search(string);
}
else {
// Default search
this.db.search(this.input.value);
}
};
}
};
}(jQuery));
In your server callback:
function some_module_autocomplete_ajax($string) {
// Decode custom string obtained using overriden autocomplete js.
$components = drupal_json_decode(rawurldecode($string));
// Do you search here using multiple params from $components
}
Ok, for as far as I can see it is not possible. maybe you can roll your own with the ajax functionality in fapi http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#ajax
For now I solved it by implementing jquery.ui.autocomplete which is included in drupal 7

Drupal module function theming with ahah

My main question is:
Does the theme_hook() function gets called whenever the form gets rebuilt via ahah (ahah_helper) ?
I'm trying to show a select box, with some filtering options, when the user changes it, the table below it changes too.
I have this by now:
function veiculos_listar_form($form_state)
{
$form = array();
ahah_helper_register($form, $form_state);
//biulds $options
$form['listar_veics'] = array(
'#type' => 'fieldset',
'#prefix' => '<div id="listar-veics-wrapper">',
'#suffix' => '</div>',
'#tree' => TRUE,
);
if (!isset($form_state['values']['listar_veics']['filial']))
$form['#filial_veic'] = 1;
else
$form['#filial_veic'] = $form_state['values']['listar_veics']['filial'];
$form['listar_veics']['filial'] = array(
'#type' => 'select',
'#title' => "Listar veículos da filial",
'#options' => $filiais,
'#default_value' => $form['#filial_veic'],
'#ahah' => array(
'event' => 'change',
'path' => ahah_helper_path(array('listar_veics')),
'wrapper' => 'listar-veics-wrapper',
'method' => 'replace',
),
);
return $form;
}
function veiculos_listar_form_submit($form, &$form_state)
{
}
function _listar_veiculos_tabela($filial)
{
//builds $header and $data
$table = theme_table($header, $data);
return $table;
}
function theme_veiculos_listar_form($form)
{
$output = drupal_render($form);
$filial = $form['#filial_veic'];
$output .= '<br>' . $filial . '<br>';
$output .= _listar_veiculos_tabela($filial);
return $output;
}
function veiculos_theme() {
return array(
'veiculos_listar_form' => array(
'arguments' => array('form' => NULL),),
);
}
In my little and innocent world, it should work if theme_hook is called on every ahah event (change).
The problem is, the variable printed is always the same, like what the user is choosing isn't being stored. If the user select a different options, it shows the new option, but the $filial variable is always the same when the theme prints.
Like this:
http://img230.imageshack.us/img230/9646/62144334.jpg
Any suggestion on what i could do to make this work? I'm developing our own module, so using views module isn't a good idea.
Thanks.
You should redo code this way.
Ahah callback I do not wrote, I think you would not have problem with it.
Check some examples on drupal.org
function veiculos_listar_form($form_state)
{
$form = array();
ahah_helper_register($form, $form_state);
//biulds $options
// remove divs because we do not want to reload selector with ahah
$form['listar_veics'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
);
if (!isset($form_state['values']['listar_veics']['filial']))
$form['#filial_veic'] = 1;
else
$form['#filial_veic'] = $form_state['values']['listar_veics']['filial'];
// add cover div here, because we will reload table
$form['table'] = array(
'#prefix' => '<div id="listar-veics-wrapper">',
'#suffix' => '</div>',
'#type' => 'markup',
'#value' => _listar_veiculos_tabela($form['#filial_veic']),
);
$form['listar_veics']['filial'] = array(
'#type' => 'select',
'#title' => "Listar veículos da filial",
'#options' => $filiais,
'#default_value' => $form['#filial_veic'],
'#ahah' => array(
'event' => 'change',
'path' => ahah_helper_path(array('listar_veics')),
'wrapper' => 'listar-veics-wrapper',
'method' => 'replace',
),
);
return $form;
}
function veiculos_listar_form_submit($form, &$form_state)
{
}
function _listar_veiculos_tabela($filial)
{
//builds $header and $data
$table = theme_table($header, $data);
return $table;
}
function theme_veiculos_listar_form($form)
{
$output = drupal_render($form);
return $output;
}
function veiculos_theme() {
return array(
'veiculos_listar_form' => array(
'arguments' => array('form' => NULL),),
);
}

Resources