When users click on a button (with id graph), I'd like to fill the default Drupal content div (<div class="content">) with a graphael instance.
The JavaScript:
jQuery(document).ready(function($) {
$('#toggle #graph').click(function() {
$.ajax({
url: "http://www.mysite.com/?q=publications/callback",
type: 'POST',
data: {
'format' : 'graph'
},
success: function(response) {
$('div#content div.content').html(response);
}
});
});
});
The PHP:
$items['publications/callback'] = array(
'type' => MENU_CALLBACK,
'title' => 'All Publications Callback',
'page callback' => '_process_publications',
'page arguments' => array(t('journal')),
'access callback' => TRUE,
);
which leads to the page callback: (I'm concerned with the if code block)
function _process_publications($venue) {
if( isset($_POST['format']) && $_POST['format'] == "graph" ){
_make_bar_chart($venue);
}
elseif( isset($_POST['format']) && $_POST['format'] == "list" ) {
_make_list($venue);
}
else{
return("<p>blah</p>");
}
}
and finally the function called within the callback function:
function _make_bar_chart($venue) {
// get active database connection
$mysql = Database::getConnection();
// if connection is successful, proceed
if($mysql){
// do stuff
$graphael = array(
'method' => 'bar',
'values' => $ycoordinates,
'params' => array(
'colors' => $colors,
'font' => '10px Arial, sans-serif',
'opts' => array(
'gutter' => '20%',
'type' => 'square',
),
'label' => array(
'values' => $xcoordinates,
'isBottom' => true,
),
),
'extend' => array(
'label' => array(
'values' => $ycoordinates,
'params' => array('attrText' => array(
'fill' => '#aaa',
'font' => '10px Arial, sans-serif',
)),
),
),
);
return theme('graphael', $graphael);
}
// else, connection was unsuccessful
else{
print("<p>bad connection</p>");
}
}
THE PROBLEM: returning a theme doesn't really send anything back to the AJAX request (unlike print statements). I tried to print the theme, but that produces a white screen of death. How would I generate the graph without printing something?
Much thanks to nevets on the Drupal forums for the helpful hint: http://drupal.org/node/1664798#comment-6177944
If you want to use AJAX with Drupal, you are best off actually using Drupal-specific AJAX-related functions. In my theme's page.tpl.php file, I added the following to make the links which would call AJAX:
<?php
// drupal_add_library is invoked automatically when a form element has the
// '#ajax' property, but since we are not rendering a form here, we have to
// do it ourselves.
drupal_add_library('system', 'drupal.ajax');
// The use-ajax class is special, so that the link will call without causing
// a page reload. Note the /nojs portion of the path - if javascript is
// enabled, this part will be stripped from the path before it is called.
$link1 = l(t('Graph'), 'ajax_link_callback/graph/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link2 = l(t('List'), 'ajax_link_callback/list/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link3 = l(t('Create Alert'), 'ajax_link_callback/alert/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$output = "<span>$link1</span><span>$link2</span><span>$link3</span><div id='myDiv'></div>";
print $output;
?>
When one of the links above is clicked, the callback function is called (e.g. ajax_link_callback/graph):
// A menu callback is required when using ajax outside of the Form API.
$items['ajax_link_callback/graph'] = array(
'page callback' => 'ajax_link_response_graph',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
.. and the callback to which it refers:
function ajax_link_response_graph($type = 'ajax') {
if ($type == 'ajax') {
$output = _make_bar_chart('journal');
$commands = array();
// See ajax_example_advanced.inc for more details on the available commands
// and how to use them.
$commands[] = ajax_command_html('div#content div.content', $output);
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);
}
else {
$output = t("This is some content delivered via a page load.");
return $output;
}
}
This replaces any HTML within <div class="content"> with the graphael chart returned from _make_bar_chart above.
Related
In my Yii web application, any type of Ajax call like Ajax validation, Ajax for dependent dropdown etc.... Is not working.
My codes are,
In my form page:
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'workdetails-form',
'enableClientValidation' => true,
'clientOptions' => array(
'validateOnChange' => true,
'validateOnSubmit' => true,
),
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation' => true,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
));
?>
in controller:
public function actionCreate() {
$model = new Workdetails;
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if (isset($_POST['Workdetails'])) {
$model->attributes = $_POST['Workdetails'];
if ($model->validate()) {
if ($model->save()) {
$this->redirect(array('create'));
}
}
}
$this->render('create', array(
'model' => $model,
));
}
For dependant dropdown:
<div class="form-group col-sm-6">
<?php echo $form->label($model, 'designationid', array('class' => 'req')); ?>
<?php
$designation = CHtml::listData(Designation::model()->findAll(), 'designationid', 'designation_name');
echo $form->dropDownList($model, 'designationid', $designation, array(
'class' => 'form-control',
'prompt' => 'Please Select',
'ajax' => array(
'type' => 'POST',
'url' => $this->createUrl('workdetails/Fetchemployee'), // here for a specific item, there should be different URL
'update' => '#' . CHtml::activeId($model, 'employeeid'), // here for a specific item, there should be different update
'data'=>array('designationid'=>'js:this.value'),
)));
?>
<?php echo $form->error($model, 'designationid', array('class' => 'school_val_error')); ?>
</div>
How to solve this...
Please help me..
Arya I had the same problem with Yii1 and i gave up using yii-ajax validation cause i could not find a way to fix it. First make sure you have initialize/ register Yii-js file these are
yiiactiveform and yii.js
If you don't have these files on your project, it means you have not registered them. To register the core JS file proceed with this config in your main.
'clientScript' => array(
'scriptMap' => array(
'jquery.js' => true,
'jquery.min.js' => true,
),
),
or if that doesn't work use this on your main view in the header section.
Yii::app()->clientScript->registerCoreScript('jquery');
You can also add it to your base controller which is at components/Controller.php
public function init() {
parent::init();
Yii::app()->clientScript->registerCoreScript('jquery');
}
On your view have this when creating your forms. It will help in placing the error messages. to your elements
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'patient-registration-form',
'enableClientValidation' => True,
'enableAjaxValidation' => FALSE,
'clientOptions' => array(
'validateOnSubmit' => true,
'afterValidate' => 'js:function(form, data, hasError) {
if(hasError) {
for(var i in data) $("#"+i).parent().addClass("has-error");
return false;
}
else {
form.children().removeClass("has-error");
return true;
}
}',
'afterValidateAttribute' => 'js:function(form, attribute, data, hasError) {
if(hasError) $("#"+attribute.id).parent().addClass("has-error");
else $("#"+attribute.id).parent().removeClass("has-error");
$("#"+attribute.id).parent().addClass("has-success");
}'
),
'htmlOptions' => array(
'class' => 'form-horizontal form-bordered form-row-stripped',
),
));
?>
alternatively use Yii2 it has fixed alot of stufff and if you are loading the current page with ajax you need to render the the whole page including the js file again. since when you use renderPartial it doesn't initalize the js files hence no js scripts will work, including validation.
These are my code, I have done the form alter in template.php.
Please advice me ! I created a webform by webform module.My aim is to submit the form without the page load.
My code follows here:
function business_form_alter(&$form, &$form_state, $form_id) {
if($form_id == 'webform_client_form_7') {
$form['actions']['submit']['#ajax'] = array(
'callback' => 'business_webform_js_submit',
'wrapper' => 'webform-client-form-7',
'method' => 'replace',
'effect' => 'fade',
);
}
function business_webform_ajax_submit($form, $form_state) {
$sid = $form_state['values']['details']['sid'];
if ($sid) {
$node = node_load($form_state['values']['details']['nid']);
$confirmation = array(
'#type' => 'markup',
'#markup' => check_markup($node->webform['confirmation'], $node- >webform['confirmation_format'], '', TRUE),
);
return $confirmation;
}
else {
return $form;
}
}
There is a small mistake in your code. The name of the #ajax['callback'] function is different than the actual function.
You might want to rename the function:
function business_webform_js_submit($form, $form_state)
And it should work.
I have situation like on this screen:
I have column where user check rows. After that user can call some actions like example delete data.
To show menu with multi actions for users i use button dropdown in yii-booster TbButtonGroup. I tried all possible buttonType and all doesnt work.
All what i need is send information about what rows are selected, do some action inside controller and after that reload grid. I dont have any idea how...
To generate button dropdown i use code:
Yii::app()->controller->widget('bootstrap.widgets.TbButtonGroup', array(
'size'=>'mini',
'type'=>'link',
'buttons'=>array(
array('icon'=>'edit', 'items'=>$this->filter),
),
));
To generate grid i use code:
$this->widget('bootstrap.widgets.TbJsonGridView', array(
'dataProvider' => $model->search(),
'filter' => $model,
'type' => 'striped condensed',
'summaryText' => false,
'cacheTTL' => 10, // cache will be stored 10 seconds (see cacheTTLType)
'cacheTTLType' => 's', // type can be of seconds, minutes or hours
'selectableRows'=>2,
'columns' => array(
array(
'class'=>'ext._TbJsonCheckBoxColumn._TbJsonCheckBoxColumn',
'id'=>'selectedTickets',
'filter'=>array(
array('label'=>'close', 'url'=>'javascript:'.CHtml::ajax(array('type'=>'POST', 'url'=>array('','multi_action'=>'close'), 'success'=>'function(data, status){ console.log(data); console.log(status); }', 'error'=>"function(data, status){ console.log(data); console.log(status); }")) ),
array('label'=>'Another action', 'url'=>'#'),
array('label'=>'Something else', 'url'=>'#'),
'---',
array('label'=>'Separate link', 'url'=>'#'),
),
),
'id',
'email_from',
'subject',
'status',
array(
'name'=>'last_update',
'value'=>'$data->last_update_from_now',
//'filter'=>false,
),
array(
'header' => Yii::t('ses', 'Edit'),
'class' => 'bootstrap.widgets.TbJsonButtonColumn',
'template' => '{view} {update} {delete}',
),
),
));
To generate form i use code:
$this->widget('bootstrap.widgets.TbButton',array(
'label' => 'Add new ticket',
'type' => 'primary',
'size' => 'medium',
'url' => $this->createUrl('create'),
));
<?php
$form = $this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id'=>'tickets',
'type'=>'horizontal',
'enableAjaxValidation'=>true,
));
echo $this->renderPartial('_grid', array('model'=>$model));
echo CHtml::ajaxSubmitButton('Activate',array('menu/ajaxupdate','act'=>'doActive'), array('success'=>'reloadGrid'));
$this->endWidget();
After many spent hours i wrote something like that and it solved my problem:
Yii::app()->clientScript->registerScript('multi_button', "
$('[data-multi=action]').delegate('li a', 'click', function(event){
event.preventDefault();
var th = $(this),
action = th.attr('href').substr(1);
if( action=='delete' && !confirm('Are you sure you want to delete selected items?') ) return true;
".
CHtml::ajax(array(
'type'=>'POST',
'data'=>'js:th.closest("form").serialize()',
'url'=>'js:location.href+(/\?/.test(location.href) ? "&" : "?")+"multi_action="+action',
'success'=>'function(data, status){ th.closest("div.grid-view").yiiJsonGridView("update"); }',
'error'=>'function(data, status){ alert(status); }',
'cache'=>false
))."
});
");
I'm creating a custom user settings page. I have one field: zip_code that get's it's initial value from a custom user field. I have a custom function that pulls external data using the value of the zip_code.
I currently have the default value of the field set to the custom user field (if it's available). This is working as designed; however, I want to give the user the ability to change their zip code via an Ajax callback. This would replace the already populated radio buttons with new ones. I can't seem to wrap my head around this. Here's my code:
function settings_shopping_form($form, &$form_state) {
include_once "external.inc";
// Get user fields
global $user;
$user_fields = user_load($user->uid);
$zipcode = $user_fields->zip_code['und']['0']['value'];
if(isset($zipcode)) {
$form['zip_code'] = array(
'#title' => t('Zip Code'),
'#type' => 'textfield',
'#required' => TRUE,
'#default_value' => $zipcode,
'#ajax' => array(
'callback' => 'settings_form_callback',
'wrapper' => 'textfields',
),
);
$storename = getmystorename($zipcode);
if(count($storename) > 0) {
$form['textfields'] = array(
'#prefix' => '<div id="textfields">',
'#suffix' => '</div>',
'#type' => 'fieldset' );
$form['textfields']['stores'] = array(
'#type' => 'radios',
'#title' => t('Choose your store:'),
'#options' => $storename,
'#default_value' => $storename[1], );
} else {
$form['textfields']['incorrect'] = array(
'#title' => t('Sorry, there are no stores available near you. Check back later'),
'#type' => 'fieldset', );
}
}
My callback function is very simple:
function settings_form_callback($form, $form_state) {
return $form['textfields'];
}
To reiterate: I want to add the ability to replace the populated radio buttons with new buttons generated by the getmystorename function when the zip_code field is changed.
I ended up taking an example from the examples module (love it!):
$defaults = !empty($form_state['values']['zip_code']) ? $form_state['values']['zip_code'] : $zipcode;
$storename = getmystorename($defaults);
I put this before the start of my form so that the values load before the form builder.
When I run the code with an admin user, the module returns what it should. However, when I run it with a normal user, I get a 403 error. The module returns data from an AJAX call. I've already tried adding a 'access callback' => 'user_access'); line to the exoticlang_chat_logger_menu() function. I'd appreciate any pointers you might have.
Thanks for the help
The AJAX call:
jQuery.ajax({
type: 'POST',
url: '/chatlog',
success: exoticlangAjaxCompleted,
data:'messageLog=' + privateMessageLogJson,
dataType: 'json'
});
The module code:
function exoticlang_chat_logger_init(){
drupal_add_js('misc/jquery.form.js');
drupal_add_library('system', 'drupal.ajax');
}
function exoticlang_chat_logger_permission() {
return array(
'Save chat data' => array(
'title' => t('Save ExoticLang Chat Data'),
'description' => t('Send private message on chat close')
),
);
}
/**
* Implementation of hook_menu().
*/
function exoticlang_chat_logger_menu() {
$items = array();
$items['chatlog'] = array(
'type' => MENU_CALLBACK,
'page callback' => 'exoticlang_chat_log_ajax',
'access arguments' => 'Save chat data');
//'access callback' => 'user_access');
return $items;
}
function exoticlang_chat_logger_ajax(){
$messageLog=stripslashes($_POST['messageLog']);
$chatLog= 'Drupal has processed this. Message log is: '.$messageLog;
$chatLog=str_replace('":"{[{','":[{',$chatLog);
$chatLog=str_replace(',,',',',$chatLog);
$chatLog=str_replace('"}"','"}',$chatLog);
$chatLog=str_replace('"}]}"','"}]',$chatLog);
echo json_encode(array('messageLog' => $chatLog));
// echo $chatLog;
echo print_r(privatemsg_new_thread(array(user_load(1)), 'The subject', 'The body text'));
drupal_exit();
}
access arguments needs to be an array:
$items['chatlog'] = array(
'type' => MENU_CALLBACK,
'page callback' => 'exoticlang_chat_log_ajax',
'access arguments' => array('Save chat data')
);