2

I have a content type which contains the following fields

  • title
  • text body
  • image

An I need to achieve something like below

enter image description here

The 4-image grid is a view which covers 50% of the page. The green coloured box represents the clicked image. I need the text-area right next to the view to contain the the text corresponding to the image which is clicked.

Is it possible to achieve this using views alone?

  • Yes, it is absolutely possible! Apart from views it goes without saying that ajax is essential, except if you want a page reload when an image is clicked. – mchar Sep 18 '16 at 20:46
  • @mchar : thanks , I don't want a page reload. I've enabled ajax for this view. – sjsam Sep 19 '16 at 5:32
1

Step 1: Create the View, the block and the required fields (order matters).

Block's instructions (page can be different):

  • Format:

    • Grid
    • Number of columns: 2
  • Fields:

    • Nid: Exclude from display
    • Title:

      • Link this field to the original piece of content: Unchecked
      • REWRITE RESULTS -> Rewrite the output of field -> Output this field as a link -> Link path: ajax-link/nojs/[nid]
      • Link class: use-ajax
    • Image:

      • Link image to: Nothing
      • REWRITE RESULTS -> ... Same as "Title"
      • Link class: use-ajax

So, the title's or image's url should have this structure: hook-menu-registered-path/nojs/argument

Step 2: Create a custom module and implement the following code.

/**
 * Implements hook_menu.
 */
function custom_module_menu() {
  // A menu callback is required when using ajax outside of the Form API.
  $items['ajax-link'] = array(
    'page callback' => '_custom_module_response',
    'access callback' => 'user_access',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 *  Callback function.
 * 
 * @param int $nid
 *   Either a valid node id or 0 (zero) if not available.
 *
 *  @param string $type
 *   Either 'ajax' or 'nojs. Type is simply the normal URL argument to this URL.
 *
 *  @return string|array
 *    If $type == 'ajax', returns an array of AJAX Commands,
 *   otherwise, just returns the content, which will end up being a page.
 */
function _custom_module_response($type, $nid = 0) {
  $output = _custom_module_node_load($nid);
  if ($type == 'ajax') {
    $commands = array();
    // Selector: A jQuery selector string, either a .class or #id.
    $commands[] = ajax_command_replace('.selector', '<div class="selector">' . $output . '</div>');
    $page = array('#type' => 'ajax', '#commands' => $commands);
    ajax_deliver($page);
  }
  else {
    $output = isset($output) ? '<div class="no-content">' . $output . '</div>' : t('Node does not exist!');
    return $output;
  }
}

/**
 *  Node loader function.
 *  
 *  @return string
 *   The themed node in its define view mode.
 */
function _custom_module_node_load($nid = 0) {
  $node = node_load($nid);
  if ($node) {
    $pre_rendered_node = node_view($node, $view_mode = 'full');
    return theme('node', $pre_rendered_node);
  }
}

Step 3: Load the necessary library. I chose the template.php file to do it.

/**
 * Implements template_preprocess_views_view.
 */
function custom_theme_preprocess_views_view(&$vars) {
  $view = $vars['view'];
  if ($view->name == 'my_view_name') {
    // 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');
    $output = '<div class="selector">' . $vars['rows'];
    $output .= '</div>';
    $vars['rows'] = $output;
  }
}

Now, should only the body field must be displayed (or a certain set of fields) I suggest the definition of a view mode per case, then define that view mode to the node_view function.


Note:

Ajax framework's "magic" class: use-ajax

By adding the 'use-ajax' class to a link, the link will be loaded via an Ajax call. When using this method, the href of the link can contain '/nojs/' as part of the path. When the Ajax framework makes the request, it will convert this to '/ajax/'. The server is then able to easily tell if this request was made through an actual Ajax request or in a degraded state, and respond appropriately.

Ref.: Drupal examples modules, How to use Drupal 7's built-in Ajax Framework

  • Thankyou so much. I've already had found a workaround since I ran out of time. I used two view grids and wrote some jquery to add an class which then is used to selectively display content at the right pane. However, this looks exactly like what I was looking for. I'll keep you posted when I implement this. Again, hats off !! – sjsam Sep 20 '16 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.