Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 41 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
41
Dung lượng
1,03 MB
Nội dung
Chapter 10 [ 307 ] The callback function hello_world_simple_form_callback() passes the $form and $form_state variables after they have gone through hello_world_ simple_form_example() . In this case we are returning the form element that is being replaced. Drupal knows this is a renderable array and renders it to the appropriate value. Drupal sends the updated HTML back to the page where the Drupal AJAX handlers retrieve the changes and replace the wrapper. AJAX automatically applied AJAX can be automatically applied to elements on a page. This is done by applying the use-ajax class to an element on a page. A typical use would be to apply the use-ajax class to a link within a page to trigger an AJAX action. Links are commonly used because the page the link points to might be for the cases when JavaScript is disabled as a fallback. In the following example we are going to provide a link that, when clicked, will add "Hello World" to a div within the page. To start, we have two menu callbacks that we add to hello_world_menu(). One item for the page we are generating and the other is the callback URL used for AJAX or when JavaScript is disabled. $items['hello_world/link'] = array( 'title' => 'Hello World: Link', 'page callback' => 'hello_world_link', 'access callback' => 'user_access', 'access arguments' => array('access content'), ); $items['hello_world_link_callback'] = array( 'page callback' => 'hello_world_link_response', 'access callback' => 'user_access', 'access arguments' => array('access content'), ); The rst menu item is to our page where the link is located and where the AJAX will add content. The second menu item is the callback that will handle the AJAX request or the page request, when JavaScript is unavailable. function hello_world_link() { drupal_add_js('misc/ajax.js'); $link = l(t('Say Hello'), 'hello_world_link_callback/nojs/', array('attributes' => array('class' => array('use-ajax')))); return '<div>' . $link . '</div><div id="saying-hello"></div>'; } JavaScript in Drupal [ 308 ] The page callback where the link lives, starts by using drupal_add_js() to add misc/ajax.js. This JavaScript does the work to automatically make the AJAX work. This is followed by a link with a callback to hello_world_link_callback/ nojs/ . The rst part of this link is the callback where the AJAX request is handled. The /nojs/ at the end is special. When JavaScript is not available it is passed to the response function so it knows it was called to be a full page load. When JavaScript is available it is replaced with /ajax/. This is passed into the callback function so it knows it was called via an AJAX request. What makes this link become an AJAX link is the class being added with the name use-ajax. The JavaScript le we added at the beginning, ajax.js, looks for links with this class and converts them into AJAX. function hello_world_link_response($type = 'ajax') { if ($type == 'ajax') { $output = t("Hello World!"); $commands = array(); $commands[] = ajax_command_append('#saying-hello', $output); $page = array('#type' => 'ajax_commands', '#ajax_commands' => $commands); ajax_deliver($page); } else { return t("Hello World in a new page."); } } When the callback to handle the request is called, the type of action is passed in. When no JavaScript is available, nojs is passed in. When the request is AJAX, ajax is passed in. This can be used in the callback functions logic to properly respond to each case. In this case we use an if statement. When the request is AJAX, we respond in one way and when JavaScript is not available we respond differently. When the request is an AJAX callback we start by creating the response text of "Hello World!". This is followed by creating an array to hold commands we want Drupal to execute and adding a command to it. A command is an action we want the JavaScript to perform when it receives the AJAX response. The commands provide ways in which jQuery can manipulate the content of the page with the responded data. In this case the command used is the ajax_command_append(). This command accepts a jQuery selector and content. The content is appended to the selector. This Drupal function utilizes the jQuery.append() function. Chapter 10 [ 309 ] Once the response is set up it is inserted into a renderable array. The type is ajax_commands, which will know how to render the AJAX command that was created in the callback. To send the AJAX response properly ajax_deliver() is used. This function properly formats the response for the JavaScript on the receiving side. Additionally, Drupal tracks the JavaScript and CSS les within a page. If a new le is added within an AJAX request that is not already loaded in the page the new le is sent as part of the response and added to the page along with the rest of the response. For cases when JavaScript is not available in the initial page view and the link is followed, it is treated as a full page request and the user is sent to a new page. This page lives at the same callback that built the AJAX response. The difference is nojs is passed into the callback so it knows the response is not in AJAX. In this case the else is executed generating a different message for the new page. AJAX commands Drupal provides several AJAX commands that can add or alter content in a page using jQuery methods. In the previous section we covered ajax_command_append(). Here are all the possible commands that can be used. ajax_command_after When ajax_command_after() is used, jQuery.after() is the method used to add content to the page. The arguments are $selector, $content, and $settings. $selector is the jQuery selector on the page and $content is the content to add after the selector. $settings, the third argument, is a set of settings used by the behaviors for this single command. ajax_command_alert The alert command is a core JavaScript command. ajax_command_alert($text) is used to alert returned text. The text is presented in an alert box. ajax_command_append This command is similar to ajax_command_after. Instead of adding the content after the selector it appends it to the end of the selector. The interface to the function is the same as ajax_command_after() with the $selector, $content, and $settings arguments. $selector is the jQuery selector on the page, $content is the content to append to the selector, and $settings is used by behavior for just this one command. JavaScript in Drupal [ 310 ] ajax_command_before To add content before an element use ajax_command_before(). It utilizes jQuery.before() to add content before a selector. Again the $selector, $content, and $settings arguments are used. ajax_command_changed To note that something within a page has changed ajax_command_ changed($selector, $asterisk) can be used. Elements found on the page with the given jQuery selector will have the ajax-changed class applied to them. $asterisk is an optional CSS selector, that resides inside $selector. This is used to optionally append an asterisk to that element. ajax_command_css ajax_command_css() uses the jQuery.css() command to update the CSS within the page. This command takes in $selector and $argument arguments. For example, changing a page's background color would look as follows: $commands[] = ajax_command_css('body', array('background-color' => '#FFFFFF')); ajax_command_data jQuery provides a 'data' command to store data within a page outside of element attributes. The ajax_command_data() function enables Drupal AJAX to add and update data inside jQuerys data cache. The three arguments are: $selector, the jQuery element selector $name, the name of the data item being accessed $value, the value for the item ajax_command_html ajax_command_html() utilizes jQuery.html() to update the html for a given selector. The arguments are $selector (the jQuery selector), $html (the HTML to update the selector to use), and $settings (optional settings for this command to use). • • • Chapter 10 [ 311 ] ajax_command_prepend To add content at the beginning of an element use the prepend command. This utilizes jQuery.prepend() to add the content. The arguments for ajax_command_prepend() are $selector, $content, and $settings. ajax_command_remove The remove command removes elements from a page. The single argument is the selector to be removed. jQuery.remove() is utilized to remove the elements from the page. ajax_command_replace The ajax_command_html replaces the html content within an element. For cases where the entire element needs to be replaced ajax_command_replace() should be used. It takes advantage of jQuery.replaceWith() to replace the entire element. The three arguments are $selector, $html, and $settings. $html is the full html the selector will be replaced with. For example, take the html: <div class="container"> <div class="inner">Hello World!</div> </div> An ajax_command_replace() looks like the following: $commands[] = ajax_command_replace('.inner', '<h2>Goodbye World! </h2>'; This will update the html to look like the following: <div class="container"> <h2>Goodbye World!</h2> </div> ajax_command_restripe The restripe command tells Drupal to restripe a table. This is useful when content inside the table has been altered. The only argument is the jQuery selector for the table. JavaScript in Drupal [ 312 ] ajax_command_settings ajax_command_settings() is used to add settings to the response. The rst argument is the settings to be sent with the response. If only the rst argument is given, or the second argument is FALSE, then the setting will only be used for the response. If the second argument, the $merge argument, is set to TRUE the settings will be merged into Drupal.settings. For more information on the jQuery APIs visit http://api.jquery.com. Summary We have covered the basic principles and commands of using JavaScript and jQuery within the context of Drupal. We started by adding JavaScript to a page as a le, inline, and as a setting. We continued by looking at adding complete libraries with dependencies and altering JavaScript right before the page was rendered. Drupal provides helper functions and libraries which are useful in creating Drupal modules. We covered how these libraries and some of the more commonly used elements work. Working with Files and Images Drupal 7 introduced a new API for les and images, bringing the functionality of popular contributed modules like Imagecache and Imagefield into core for the rst time. In this chapter, we will build two modules that take advantage of this new functionality. Some of the concepts we will cover are: Understanding Drupal's public and private lesystems Associating les and images with content Implementing a stream wrapper for custom le handling Programmatically manipulating images using image styles and effects Understanding Drupal's new Image Styles functionality Implementing your own image effects for use with Image Styles By the time you are done with this chapter, you should have a good understanding of how to manipulate les and images using Drupal, including some methods for retrieving remote les and images. The Twitpic and watermark modules In this chapter, we will be building the Twitpic module. This module will enable you to interact with images stored on the Twitpic website (http://twitpic. com ) and integrate them with Drupal in a variety of ways. It provides a stream wrapper that allows developers to pull images from Twitpic by referring to them with a custom URI, and offers a demo of how Drupal's Image API can be used to manipulate these images. • • • • • • Working with Files and Images [ 314 ] We will also be creating a second module, which allows users to add a simple text watermark to images. Users will be able to congure the watermark so that it displays custom text in a specied color. This effect will be available for use in Image Styles, the Drupal 7 implementation of the Imagecache module. Files in Drupal When you installed Drupal for the rst time, you probably got the following error and wondered why you needed to create three directories for les: Drupal denes three types of le storage, namely, public, private, and temporary. Public les are available to the world at large for viewing or downloading. This is where things such as image content, logos, and downloadable les are stored. Your public le directory must exist somewhere under Drupal's root, and it must be readable and writeable by whatever 'user' your web server is running under. Public les have no access restrictions. Anyone, at anytime, can navigate directly to a public le and view or download it. Private les are not available to the world for general download. The private les' directory should reside outside Drupal's root directory. However, it will still be writeable by the web server user. Isolating private les this way allows developers to control who can and can't access them as they wish. For instance, you could write a module that only allows users who have a specic role, to access PDFs in the private lesystem. Chapter 11 [ 315 ] It is very important that private les live outside of Drupal's web root, despite the fact that by default they do not. In order for private les to be useful, they must be readable to the user your web server runs as. However, if these les are then under Drupal's web root, they will be readable to anybody. Proper testing is extremely important for properly securing private les. For more information on how to properly secure your private le system, see the following site: http://drupal.org/node/344806 Temporary le storage is typically only used by Drupal for internal operations. When les are rst saved by Drupal, they are rst written into the temporary le area so they can be checked for security issues. After they have been deemed safe, they are written to their nal location. Each of the directories in the preceding error message reects the default location for each type of le. You can change these default locations after your installation is complete by logging in as administrator and visiting admin/config/media/file- system as seen in the following image: You can also indicate whether the default download method should be public or private. (After installation it is public.) Working with Files and Images [ 316 ] File API In Drupal 6, most le handling functionality was provided through a rough core API combined with contributed modules such as Filefield. Drupal 7 provides a more robust and consistent API that allows developers to interact with les in a standard set of functions that perform tasks like creating, opening, moving, and deleting les. In order for les to be associated with nodes and other Drupal content, they must have a record in Drupal's file table. Each record identies a le with a unique ID as well as associated metadata like le size and mime-type. Many File API functions, such as file_copy() and file_move(), take a le object as one of their arguments. The le object is a PHP standard class containing the metadata from the files table, and these API functions manage updating the information in the files table when les are moved or deleted. This is one reason it is so important to use these API functions for les associated with content—if you don't, the files table will be inconsistent and your les may not show up properly. If you need to work with les outside the context of Drupal content, there is a separate set of functions in the File API with unmanaged in their name. For instance, where file_copy() will update the les table and copy your le, file_unmanaged_copy() will just copy the le. For a full list of the functions available in the File API, refer to the API documentation at: http://api.drupal.org/api/group/file/7 Here is a simple example of how this works. A common task while building a Drupal site is importing data from another source and turning it into nodes. This will not only include textual information like the title and body, but also images. These images may live in a local directory, or they may live out on a website you're importing from. Let's look at how we can grab a le from an external site, save it to the default le system, and attach it to a node we create. For this example, you will be working with the eld image in the article content type. First we need to get a le and save it: $image = file_get_contents('http://drupal.org/files/issues/druplicon_ 2.png'); $file = file_save_data($image, 'public://druplicon.png',FILE_EXISTS_ REPLACE); [...]... brought into core for Drupal 7, along with an improved API for managing this functionality from code Image API The Drupal 7 Image API provides a variety of functions to manipulate images By default, Drupal uses the GD image management library that is included with PHP However Drupal also offers the ability to switch to a different library if needed For instance, a contributed module could implement... with your module For instance, a popular Drupal contributed module is the Pirate module, which translates your entire website to pirate-speak on Talk Like A Pirate Day It might be cool for the Pirate module to be able to ship a totally preconfigured image style that adds the YAR! watermark to images Rather than having to create this image style themselves, administrators could simply install the module. .. because this style is in code, it is more easily deployable between development environments Thankfully, this is quite easy to do and will provide our final demonstration of Drupal 7' s Image API Creating image styles from a module At this point in your Drupal experience, you can probably guess what is involved in creating an image style in your module a hook and an associative array The hook is hook_image_default_styles()... twitpic/munge/7nyr2/rotate: [ 330 ] Chapter 11 This is all very cool, but sometimes it might be nice to pre-create some manipulations for repeated use, or even a set of manipulations to be executed in order This is what Image Styles are for, and we'll look at that now Image Styles Image Styles is the Drupal 7 core replacement for the popular Imagecache module, which has been around since Drupal 5 Image... don't apply In these cases we simply return FALSE For the full implementation details of DrupalStreamWrapperInterface, refer to http://api .drupal org/api /drupal/ includes stream_wrappers.inc /7 You may also want to refer to PHP's prototype stream wrapper class at http:// php.net/manual/en/streamwrapper.stream-open.php DrupalStreamWrapperInterface is quite extensive, with over 20 functions to be defined... for schemes that PHP does not handle out of the box, and the Drupal File API has been built to take advantage of this For instance, Drupal defines the private scheme to allow Drupal developers to interact with files in Drupal' s private file system Let's look at how this works by creating a scheme to retrieve images from a remote website [ 3 19 ] Working with Files and Images Creating a stream wrapper... Summary The new File and Image APIs in Drupal 7 not only make management and maintenance of these assets much easier, they are also great fun to play around with and amazingly easy to use By now you should be comfortable with the central concepts of file management in Drupal You should know the difference between Drupal' s public and private file systems, and understand how Drupal associates file metadata... image functions compatible with multiple libraries, see the API documentation on image_toolkit_invoke() at: http://api .drupal. org/api/function/image_toolkit_ invoke /7 We will begin with the assumption that you have created a standard module info file with all the information needed for a module named watermark The first step in creating a new image effect is implementing hook_image_effect_info() /** *... Filefield module largely handled file handling in Drupal 6, two modules—Imagefield and Imagecache, largely handled image handling Imagefield was used for attaching images to nodes, and Imagecache was used to create derivations of those images by resizing or cropping them This was very popular for things like creating square thumbnails in a grid for image galleries The functionality of both modules has... class that implements Drupal' s stream • description: A sentence or two describing what this wrapper does • type: A constant indicating what type of stream wrapper this is—readable wrapper interface and/or writeable, local or remote, among other things These are defined in includes/stream_wrappers.inc and can be reviewed at: http://api drupal. org/api /drupal/ includes stream_wrappers.inc /7 Note that in our . effect will be available for use in Image Styles, the Drupal 7 implementation of the Imagecache module. Files in Drupal When you installed Drupal for the rst time, you probably got the following. The functionality of both modules has been brought into core for Drupal 7, along with an improved API for managing this functionality from code. Image API The Drupal 7 Image API provides a variety. Images [ 316 ] File API In Drupal 6, most le handling functionality was provided through a rough core API combined with contributed modules such as Filefield. Drupal 7 provides a more robust