Monday, October 13, 2014

Drupal ajax form submit progress overlay

Use below code to show progress bar while submitting ajax form in Drupal.

/* ajax form submit throbber style */ 
.custom_wrap .ajax-progress .message,
.custom_wrap .ajax-progress-throbber .message{
  color: white;
  font-size: 20px;
  padding: 30px;
}
.custom_wrap .ajax-progress .throbber,
.custom_wrap .ajax-progress-throbber .throbber {
  float: none;
  margin: 250px auto 0 auto;
  width: 128px;
  height: 128px;
  background: url("../images/ajax-throbber.gif") no-repeat center center;
}
.custom_wrap .ajax-progress,
.custom_wrap .ajax-progress-throbber {
  width: 100%;
  height: 100%;
  background-color: #000;
 opacity: 0.6;
 filter: alpha(opacity=60);
  position: fixed;
  top: 0;
  left: 0;
  z-index: 500;
  vertical-align: middle;
  text-align: center;
}


Monday, September 22, 2014

Drupal batch process for custom function callback

Drush is a very powerful command line tool to manage Drupal site.

Other than core Drush command, we can also write our own custom drush command to perform some task like cron setup, etc, ...

we can do it by using below 3 steps.

Steps :
1) Write hook_drush_help.
2) Write hook_drush_command.
3) Write drush_hook_command.

1) hook_drush_help.
/**
 * Implements hook_drush_help().
 */
function my_module_drush_help($command) {
  switch ($command) {
    case 'drush:test-import':
     return dt('Import test contents.');
  }
}

2) hook_drush_command.
/**
 * Implements hook_drush_command().
 */
function my_module_drush_command() {
  $items = array();
  $items['test-import'] = array(
    'description' => dt('Import test contents.'),
    'arguments'   => array(
      'arg1'    => dt('An optional example argument'),
    ),
    'examples' => array(
      'Standard example' => 'drush test-import',
      'Argument example' => 'drush test-import 5',
    ),
    'aliases' => array('ti'),
  );
  return $items;
}

3) drush_hook_command().
/**
 * Implements drush_hook_command().
 */
function drush_my_module_test_import($arg = NULL) {
  batch_custom_function();
}

4) batch_custom_function().
/**
 * Batch start function. In this example, I'm downloading XML file.
 */
function batch_custom_function() {
  $batch = array(
    'title' => t('Download XML file.'),
    'operations' => array(
      array('_batch_xml_download', array()),
    ),
    'progress_message' => t('Downloading XML file ...'),
    'error_message' => t('Error! while downloading XML file ...'),
    'finished' => '_batch_download_finished',
  );
  //Get the batch process all ready!
  batch_set($batch);
  $batch = &batch_get();

  //Because we are doing this on the back-end, we set progressive to false.
  $batch['progressive'] = FALSE;

  //Start processing the batch operations.
  drush_backend_batch_process();
}

5) _batch_xml_download callback.
/**
 * XML download.
 */
function _batch_xml_download(&$context) {
  $xml_read_return = '';
  $context['message'] = 'Downloading XML file ...';
  $xml_read_return = custom_callback_to_download_xml();

  if($xml_read_return == 200) {
    drush_log('XML file downloaded and saved successfully.', 'ok');
  }
  elseif (!empty($xml_read_return)) {
    drush_log('Unable to download XML file. (' . $xml_read_return . ')', 'error');
  }
}

6) _batch_download_finished callback.
/**
 * Finish of butch. Messagess
 */
function _batch_download_finished($success, $results, $operations) {
  if ($success) {
    drupal_set_message(t('Your success msg.'));
  }
  else {
    drupal_set_message(t('An error occurred while processing operation.'));
  }
}

Friday, September 19, 2014

PHP create XML file

Pragmatically create XML using PHP.

  $xml = "<company>";
  $xml .= "<employee>";
  $xml .= "<id>100</id>";  
  $xml .= "<name>name</name>";
  $xml .= "<email>email</email>";  
  $xml .= "<salary>salary</salary>";    
  $xml .= "</employee>";  
  $xml .= "</company>";
  $xml_obj = new SimpleXMLElement($xml);
  $xml_obj->asXML('public://myfile.xml'); // Drupal file path.


Wednesday, August 27, 2014

Drupal feeds batch import - Feeds batch process

Feeds module is a one of the best module to import nodes from external URL, xls file or from  xml file, etc..

After creating feeds import for particular action, we can run it via batch process. Like via cron instead of running it manually.

I will create new post to create about feeds import.

Below line of codes worked perfect for one of  my project:

$file = 'your-xml-file.xml';
$my_importer = feeds_source('your_importer_name');
$config = array('FeedsFileFetcher'=>array('source'=>'sites/default/files/' . $file));
$my_importer->addConfig($config);
while (FEEDS_BATCH_COMPLETE != $my_importer->import());

use below link to integrate above batch process via cron.

http://kali-dasan.blogspot.in/2014/08/drush-custom-command-drush-in-our.html

Tuesday, August 19, 2014

Drush custom command - Drush in our custom module

Drush is a very powerful command line tool to manage Drupal site.

Other than core Drush command, we can also write our own custom drush command to perform some task like cron setup, etc, ...

we can do it by using below 3 steps.

Steps :
1) Write hook_drush_help.
2) Write hook_drush_command.
3) Write drush_hook_command.

1) hook_drush_help.
/**
 * Implements hook_drush_help().
 */
function my_module_drush_help($command) {
  switch ($command) {
    case 'drush:test-import':
     return dt('Import test contents.');
  }
}

2) hook_drush_command.
/**
 * Implements hook_drush_command().
 */
function my_module_drush_command() {
  $items = array();
  $items['test-import'] = array(
    'description' => dt('Import test contents.'),
    'arguments'   => array(
      'arg1'    => dt('An optional example argument'),
    ),
    'examples' => array(
      'Standard example' => 'drush test-import',
      'Argument example' => 'drush test-import 5',
    ),
    'aliases' => array('ti'),
  );
  return $items;
}

3) drush_hook_command.
/**
 * Implements drush_hook_command().
 */
function drush_my_module_test_import($arg = NULL) {
  // print arg if any.
  if (isset($arg)) {
   drush_print($arg);
  } 
  drush_log('importing test contents...', 'ok');
}

Now Goto drush command line interface and try > drush test-import or > drush ti

Monday, July 21, 2014

Drupal 7 ajax without jquery using use-ajax

Using "use-ajax" attribute, we can achieve ajax in Drupal.
Follow below steps to do it.

Steps :
1) hook_menu entry
2) function definition to declare ajax element (Hyperlink)
3) Ajax definition

1) hook_menu entry.
function yourModuleName_menu() {
  $items = array();
  $items['Mymodule/ajax'] = array(
    'page callback' => 'Mymodule_ajax_test',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['Mymodule/ajax/%/%'] = array(
    'page callback' => 'Mymodule_ajax_callback',
    'page arguments' => array(2, 3),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

2) function definition to declare ajax element (Hyperlink).
function Mymodule_ajax_test() {
  drupal_add_library('system', 'drupal.ajax');
  drupal_add_library('system', 'jquery.form');
  $arg = 'arg';
  $output = l(t('AJAX'), 'pm/ajax/nojs/' . $arg, array('attributes' => array('class' => array('use-ajax'))));
  $output .='<div id="some-wrapper"></div>'; // udadate result here.
  return $output;
}
// Another method.
function Mymodule_ajax_test() {
  drupal_add_library('system', 'drupal.ajax');
  drupal_add_library('system', 'jquery.form');
  $some_argument = 'arg';
  $output = l(t('AJAX'), 'Mymodule/ajax/nojs/' . $arg, array('attributes' => array('class' => array('use-ajax'), 'id' => array('some-wrapper')))); // overwrite result here.
  return $output;
}

3)  Ajax definition.
function Mymodule_ajax_callback($type = 'ajax', $arg) {

 if ($type == 'ajax') {
    $commands[] = ajax_command_replace('#some-wrapper', 'Ajax result '  );
    $page = array('#type' => 'ajax', '#commands' => $commands);
    ajax_deliver($page);
  }
  else {
    $output = t("Ajax fail or page load contents.");
    return $output;
  }
}

Friday, July 18, 2014

Drupal 7 ajax form validation and submit - Ajax framework commands

Ajax is one of the best interactive way to validate and submit Drupal custom form.
Using below steps, we can achieve ajax form validation and submit.

Steps :
1) Declare form elements
2) Call back definitions.

1) Declare form elements.
$form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('SUBMIT'),
  '#validate' => array('validate_callback'), // custom form validate.
  '#ajax' => array(
    'callback' => 'submit_callback',
    'effect' => 'fade',
    'wrapper' => 'specific-wrapper',
    'event' => 'click',
    'progress' => array('message' => '', 'type' => 'throbber'),
  ),
);

2) Call back definitions.
function submit_callback($form, $form_state) {
  if (form_get_errors()) {
    $form_state['rebuild'] = TRUE;
    return $form;
  }

  $response = my_form_submit($form, $form_state); // write your form submit logic here.
  return $response;
}
"validate_callback" is our normal hook_form_validate(). 

NOTE : Reach me through the contact form if you have any question.

Update:
Recently I have worked on "Ajax framework commands", this is also very useful Technic to achieve ajax form submit & validation.

1) Declare form elements to use ajax framework.
$form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('SUBMIT'),
  '#ajax' => array(
    'callback' => 'ajax_command_callback',    
  ),
);

2) Call back definitions.
function ajax_command_callback($form, $form_state) {
  // Collect error.
  $error = form_get_errors();
  // Clear error for all the cases.
  drupal_get_messages();
 // Logic behind error.
if (!empty($error) && $error['title']) {
   $form_state['rebuild'] = TRUE;
    // Create place holder to display error(class name / ID).
    $selector = '.error_place_holder';
    // Java script function to process error.
    $commands[] = ajax_command_invoke(NULL, "error_javascript_call");
    $commands[] = ajax_command_replace($selector, '<div class="error_place_holder"><div class = "error-msgs">' .    $error['title'] . '</div></div>');
    return array('#type' => 'ajax', '#commands' => $commands);
  }
  else {
    // Same thing you can do it for success.
    // Passing dynamic value to java script.
    $commands[] = ajax_command_invoke(NULL, "success_javascript_call", array(array('url'=>url('some_url_to_redirect_on_success'))));
    return array('#type' => 'ajax', '#commands' => $commands);
  }
}


ajax_command_replace on error:
It contains $selector as a first argument & "error_place_holder" class name is the second argument.

Selector: <div class="error_place_holder"> </div>
Error result : <div class="error_place_holder"><div class = "error-msgs">' . $error['title'] . '</div></div>

In the final, your selector will be updated with error result. Means,
<div class="error_place_holder"> <div class="error_place_holder"><div class = "error-msgs">' . $error['title'] . '</div></div> </div>



ajax_command_invoke usage.
 // Redirect on success.
  $.fn.success_javascript_call= function(val){
    window.location.href = val.url;
  }
  // Hide or do something on error.
  $.fn.error_javascript_call= function(val){
    $('.class').removeClass().addClass('some-test');
  }

Wednesday, June 4, 2014

Drupal date popup in custom form

Lets we see how to integrate date_popup on drupal custom form.
We can achieve it using drupal core functionality.
No need to go for jquery plugin.

Follow below 3 steps to achieve it :
1. custom form entry
2. hook_element_info_alter
3. Js for settings.

1. Create field in your custom form :
$form['birth_date'] = array(
 '#type' => 'date_popup',
 '#date_format' => 'd-m-Y',
 '#title' => t('Birth Date'),
 '#required' => TRUE,
 '#attributes' => array('class' => array('date-picker')),
);

2. hook_element_info_alter() to alter date_popup field. :
// For example :
date_popup by default come with time field. You can hide it.
Similarly you can hide description , title , etc ...
function myModule_element_info_alter(&$type) {
  if (isset($type['date_popup'])) {
    $type['date_popup']['#process'][] = 'myModule_date_popup_process';
  }
}


function myModule_date_popup_process($element, $form_state, $complete_form) {
  unset($element['date']['#description']);
  unset($element['date']['#title']);
  return $element;
}
3. Add below JS file settings. :
(function ($) {
  Drupal.behaviors.custom_js = {
    attach: function(context) {
      $('.date-picker').datepicker({   
        showOn: "both", // Another one option is "button".
        buttonImage: Drupal.settings.datePicker.iconPath + '/images/datepicker-icon.png',
        buttonImageOnly: true,
        dateFormat: "dd-mm-yy",
        changeMonth : true, // To edit month field.
        changeYear : true, // To edit date field.
        yearRange: "-120:",
      }); 
    }
  };
})(jQuery);


Final step is to create Drupal settings to hold theme_path to hold date picker icon image.
// We can get theme path using Drupal settings variable.
global $theme_path;
drupal_add_js(array('datePicker' => array('iconPath' => $theme_path)), 'setting');



Wednesday, May 14, 2014

Autocomplete Drupal Form Tutorial.

I got a chance to use drupal form '#autocomplete_path' attribute to my one of the project.

Example usage :
// Autocomplete field
$form['autocomplete'] = array(

 '#type' => 'textfield',

 '#title' => 'Autocomplete field',

 '#description' => 'Autocomplete field example',

 '#autocomplete_path' => 'article/autocomplete',

  );


I have found one good resource about it at http://www.coalmarch.com/blog/autocomplete-drupal-form-tutorial

It may be useful to you. Happy coding :)

Thursday, April 24, 2014

Drupal 7 theme two custom forms in a tpl file or a single page


Let's we discuss How to theme two Drupal 7 custom forms in tpl file or in a single page.

First I would like to thank this guy for his post.

Steps :
1. Create menu call back for landing page where do you want to display two forms.
2. Create two forms.
3. Link two forms into theme function.
4. Write logic into hook_theme.

1. First step to create menu call back for landing page.
function example_menu() {
  $items['user-login'] = array(
  'title' => 'Multiple Forms on Single Page', 
  'page callback' => 'custom_salesforce_user_login_page',
  'access callback' => 'user_is_anonymous', );
  return $items; 
}

2.Create Two forms.
// First form.
function custom_salesforce_login_form($form, &$form_state) {
$form['rtc_registered_email'] = array(
'#type' => 'textfield',
'#required' => TRUE,
'#title' => t('Registered Email'),
);
$form['rtc_password'] = array(
'#type' => 'password',
'#required' => FALSE,
'#title' => t('Password'),
);
$form['rtc_submit'] = array(
'#type' => 'submit',
'#id' => 'salesforce_ret_couple_login',
'#value' => t('Login'),
);
return $form;
}

// Second form.
function custom_salesforce_update_form($form, &$form_state) {
$form['fth_registered_email'] = array(
'#type' => 'textfield',
'#required' => TRUE,
'#title' => t('Registered Email 2'),
);
$form['fth_create_password'] = array(
'#type' => 'password',
'#required' => FALSE,
'#title' => t('Password'),
);
$form['fth_confirm_password'] = array(
'#type' => 'password',
'#required' => FALSE,
'#title' => t('Confirm Password'),
);
$form['fth_submit'] = array(
'#type' => 'submit',
'#id' => 'salesforce_fth_login',
'#value' => t('Create Password'),
);
return $form;
}

3. Link two forms into theme function.
 //Link your both forms into theme() function.  You can also pass form elements if its necessary. 
function custom_salesforce_user_login_page() {
 $custom_salesforce_login_form = drupal_get_form('custom_salesforce_login_form'); $custom_salesforce_update_form = drupal_get_form('custom_salesforce_update_form'); 
 $combine_form = array('arg1' => $custom_salesforce_login_form, 'arg2' => $custom_salesforce_update_form); 
 $output = theme('custom_salesforce_login_and_update', $combine_form); 
 return $output; 
}

4. Write logic into hook_theme.
 /**
 * Implements hook_theme(). 
 */ 
function moduleName_theme($existing, $type, $theme, $path) {
$items['custom_salesforce_update_form'] = array(
 'render element' => 'form', 
 'template' => 'custom_salesforce_update_form',
 'path' => drupal_get_path('module', 'moduleName') .'/template', );
 $items['custom_salesforce_login_form'] = array( 
 'render element' => 'form', 
 'template' => 'custom_salesforce_login_form',
 'path' => drupal_get_path('module', 'moduleName') .'/template', ); $items['custom_salesforce_login_and_update'] = array(
 'template' => 'custom_salesforce_login_and_update', 
 'path' => drupal_get_path('module', 'moduleName') .'/template',
 'arguments' => array('combine_form' => NULL), ); 
 return $items;
 }

/**
 * Implements Template Preprocessor For Login and Update User().
 */
function template_preprocess_
custom_salesforce_login_and_update(&$variables) {
  $variables['arg_return_couple_form'] = drupal_render($variables['arg1']);
  $variables['arg_first_time_login_form'] = drupal_render($variables['arg2']);
}


5. custom_salesforce_login_and_update.tpl.php
//Print your both forms in the above tpl file.
 <div class="login-form-fields parent">
<?php print $arg_return_couple_form; ?>
 </div> <div class="login-form-fields parent"> 
<?php print $arg_first_time_login_form; ?> 
</div>

Note : Create tpl files for those two forms separately and print form elements as your wish. So totally three tpl files are needed.