original source : http://drupal.stackexchange.com/questions/26290/what-is-the-basic-concept-behind-hooks
The other answers are great, accurate, detailed, but I’m not sure they’re the “simple words” explaining the bare bones of the concept that the asker was looking for.
I think of hooks as a point where the code pauses and shouts “Anyone else got anything to add here?”. Any module can have a function that replies to this, and gets triggered with appropriate data passed to it at that point in the code.
A nice straightforward example is hook_node_delete(). Any module can use it to make things happen every time a node is deleted. The docs tell you this hook passes the module the object of that deleted node to work with, and outlines other useful information such as about the exact timing of when it’s called (e.g. that it is before the node data is actually deleted from the database), and where in Drupal’s code the hook is called (which can be more than one place).
You can explore what hooks exist and find out what data is passed to them by exploring things starting with “hook_” in the Drupal api.
Hooks work by a name conventions: using hook_node_delete as our example, when the node deletion process reaches the point where the hook is called, for every module with a function like this [modulename]_node_delete() where the word hook in the hook’s name is replaced with the module’s name (e.g. my_amazing_module_node_delete() ), those functions get called.
Why? So any module can do anything at these key points: for example you could look at the deleted node and do things if it meets a certain condition (say, email an administrator, or launch some long process).
Some hooks let you alter things that have been generated just before they’re processed. For example, hook_menu_alter() passes you the current menu items that the system has generated. Any module can define a function some_modulename_menu_alter() and look at them, optionally change them (delete some, add some, sort them…), and pass the newly altered menu back in.
It’s simple, really powerful and is at the heart of how Drupal works as a modular system. Implementations of hooks are at the heart of most Drupal modules.
When looking through the code of a Drupal module, you can spot which functions come from hooks (as opposed to functions that are simply called from within the module code itself), as the Drupal community enforce a convention whereby each implementation of a hook has a comment in front of it like this (note the “Implements hook_…” bit):
/**
* Implements hook_some_hook().
*
* Some descriptive summary of what this does
*/
function my_amazing_module_some_hook() {
Some modules that act as APIs define their own hooks. For example, Views defines many hooks that allow you to add to, read and edit data at various points in the process of creating or displaying a view. You can find information about hooks created in custom modules from two places (assuming the module follows conventions etc):
The code and comments in the modulename.api.php file in the module folder
Bootstrapping is, as others explained, basically booting up – I won’t duplicate the other good clear explanations.
One of the core developers wrote up an article a while ago called “Drupal programming from an object-oriented perspective”. It does a good job of explaining how hooks can be thought of as implementing many of the common design patterns. The best explanation of hooks comes from the article:
Drupal’s hook system is the basis for its interface abstraction. Hooks define the operations that can be performed on or by a module. If a module implements a hook, it enters into a contract to perform a particular task or return a particular type of information when the hook is invoked. The calling code need not know anything about the module or the way the hook is implemented in order to get useful work done by invoking the hook.
The Bootstrap is the process Drupal goes through to build a page, basically running over all the core, theme and module code in order. It’s basically how Drupal boots up, and prepares to do it’s job as CMS.
It’s clever, in that it allows us to put hooks anywhere in our modules and themes, and the bootstrap process makes sure they get run at the right point. For example if you use ‘hook_form_alter’ to add a custom check-box to a form, Drupal’s bootstrap will make sure it runs that code, just before it renders your form.
One issue with the bootstrap is that the entire process takes time to run, even if you are only returning a small amount of data. When using Drupal with the services module as an API and returning many small XHTML or JSON responses, running through the entire bootstrap isn’t very performant. Some clever people are looking at clever ways around this for Drupal 8.
But for rendering normal Drupal pages, the bootstrap process works great, it uses Drupals caching system to speed things up, and gives you total control over every part of your site. If you do find your site slow, you can always use something like APC or MemCached to help speed things up.
I hope my answer was accurate and explains things simply for you, I’m no expert, but I think that’s how it works.
Bootstrap is the process during the which Drupal initializes itself; the process actually includes:
Setting the error, and the exception handlers
Initializing the value of some spec-global variables contained in $_SERVER
Initializing some variables with init_set()
Finding the cached version of the page to serve
Initializing the database
Setting the handlers that load files when a class, or an interface is not found
Initializing the Drupal variables
Initializing the PHP session
Initializing the language variable
Loading the enabled modules
Some of the operations I described are specific for Drupal 7, or higher, but most of the operations are independent from the Drupal version.
A hook is a PHP function that can be called from Drupal, or third-party modules, when necessary to do a task. Instead of having a prefixed list of functions to call, the list is build checking the enabled modules, and the functions they implement. For example, Drupal uses hook_node_update(); when a node is being saved with node_save(), the following code is executed.
// Call the node specific callback (if any). This can be
// node_invoke($node, 'insert') or
// node_invoke($node, 'update').
node_invoke($node, $op);
Checking if the enabled modules has a function whose name ends in “_node_update” and starts with the short name of the module
Calling that function, passing $node as parameter
Hooks can save their own data in a database, or alter the value returned from a function. The last case is, for example, what happens with hook_form_alter(), which alters the value of $form passed as reference to drupal_prepare_form().
Drupal hooks are generally invoked using three functions:
There are other functions that are used to invoke hooks, such as node_invoke(), but those functions essentially use one of the functions I listed before.
original source : http://www.sitepoint.com/web-foundations/media-queries/
Media queries are an extension to HTML5 that allows features of a user’s display to determine the CSS delivered to the device, as defined by the CSS3 Module. device in portrait orientation with a viewport width of 320px can be detected and given different styles compared to a desktop device with a viewport width of 1024px. Conventionally, the different styling would normally be restricted to layout, backgrounds, and images; in essence, a completely new set of styles can be delivered.
As in media types, there are three ways to invoke media-query-dependent styles. First of all, as stylesheets in the linkelement of HTML or XHTML:
<link rel="stylesheet" type="text/css" media="all and
(color)" href="/style.css">
Secondly, in XML:
<?xml-stylesheet media="all and (color)" rel="stylesheet"
href="/style.css" ?>
And finally, in CSS stylesheets using @import rules:
@import url("/style.css") all and (color);
Or using @media rules:
@media all and (color) { /* one or more rule sets… */ }
Once again, responsive web design is providing the tools to create a fire-and-forget approach that produces layouts we can trust. It leaves us free to concentrate on the content that keeps our users returning to our applications.
As we can see from Figure 4.1, modern devices have vastly distinct capabilities and requirements when it comes to assets and styling. Luckily, the syntax for media queries is straightforward.
Figure 4.1. The image assets in their target devices
We typically try to limit the CSS delivered to each target. Starting from styles that are common, we build device-specific styles. But it’s not just the styles themselves that we target, there are also the assets delivered by those styles. Figure 4.2 shows that if we send the 1920px-wide background to our 320px-wide display from Figure 4.1, we’ll be sending an asset around 14 times larger than required. That’s a bandwidth and performance hit to your application that you can easily do without.
Figure 4.2. Our small image fits approximately 14 times in our large image
Let’s take a look at a media query that will target the iPhone 5:
@media only screen and (min-device-width: 640px) and
(max-device-width: 1136px) and
(-webkit-min-device-pixel-ratio: 2) {
/* iPhone 5 only – at least for now */
}
By now, that syntax is going to be looking partly familiar at the least. We’ve seen device-width in our viewportmeta element, and device-pixel-ratio in the picture element from adaptive images. And as if that weren’t enough, media queries are the cousins of media types that were released in May 1998 as part of the CSS2.0 recommendation.
Exploring Media Features
You can do a lot with media queries even if you just rely on device-width. Remember, though, that you can look at features other than a device’s width. There are currently 13 media features catered for in the specification:width,height, device-width, device-height, orientation, aspect-ratio, device-aspect-ratio,color, color-index, monochrome, resolution, scan, and grid. All but orientation, scan, andgrid can accept min- and max- prefixes as well. The level of control you have is refreshing—and a little awe-inspiring!
If you were yet to be in awe of the number of options before you, remember that as the media query features are controlled by CSS, browser vendors can add vendor-prefixed additions to that list; for example, -webkit-device-min-pixel-ratio, which is Apple’s addition to enable you to target its Retina devices. And don’t forget that there are many more we can access beyond -webkit-:
@media only screen and (-webkit-min-device-pixel-ratio: 2)
and (min-width: 320px),
only screen and (min--moz-device-pixel-ratio: 2)
and (min-width: 320px),
only screen and (-o-min-device-pixel-ratio: 2/1)
and (min-width: 320px),
only screen and (min-device-pixel-ratio: 2)
and (min-width: 320px) {
/* Small screen retina/amoled styles */
}
Just like standard vendor-prefixed styles, the last property has no vendor prefix in the hope that one day property alone will be enough to reach our target devices.
Gone are the days when handheld would get you out of trouble. Today, you need to consider all your options for targeting devices and judge how to balance your design and development budgets. And that’s a judgment that’s becoming harder and harder to make with the constant temptation to over-specify queries. With the release of Apple’s iPhone 5 with iOS6, the new handset gained an extra 176px in height. It’s unlikely you’d be targeting iPhones usingmax-device-height: 960px—however, if you did, you’d have missed all the iPhone 5s that viewed your application. Consider Figure 4.3.
Figure 4.3. Size comparison of iPhone 4 and iPhone 5 screen heights
True, you can now differentiate iPhone 5 from its predecessors by using device-height, but you need to balance that against the possibility that the footer you so painstakingly fixed to the bottom of the screen in iPhone 4S and below will now eerily float 176px above the bottom of the screen. We also need to consider that if the iPhone 5 gained an extra 176px, what can we expect from the iPhone’s next generation? Or the one after? Remember our goal: to trust that our style will just work on any device—present or future—without having to rewrite code with each new size.
That being the case, it could be worth a quick look at the syntax we use to pick between features. A media query list is a comma-separated string that uses a series of media queries to target device features:
<link rel="stylesheet" media="screen and (color),
projection and (color)" rel="stylesheet"
href="example.css">
If at least one media query in a media query list is true, the list is considered true and any true feature matches will be honored. For example, if the screen and (color) media query in a media query list such as "screen and (color), projection and (color)" in the previous code example is true, the list is regarded as true.
The comma separating each media query expresses a logical OR, and each query can use the and keyword to express a logical AND. For the OR query to match, either feature must be present and for the AND query to match, both features must be present. The previous query caters for when your application is viewed on either a screen or projector that’s capable of displaying color. If the device falls within that range, it will receive the contained CSS styles.
The not keyword can be used to exclude a feature, so this next query will target iPhones but NOT those with Retina displays; it will catch an iPhone 3 but not an iPhone 5, for example:
@media only screen (min-device-width: 640px) and
not (-webkit-min-device-pixel-ratio: 2) {
/* stylesheet for non-high density phone goes here */
}
All in all, the media query syntax is straightforward and can be readily understood and simply read, as long as you keep an eye out for those implicit logical ORs. Had the W3C and WHATWG opted for the picture element over the image’ssrc-set attribute, the extra exposure that the media query syntax would have gained would have made investment in learning it even more valuable.
Query Feature Support
You can go a long way with media queries concentrating largely on dimension-based features—width and height, and device-width and device-height. These have the twin benefits of being both easy to understand and widely supported by browsers. Well, easy to understand as long as you remember that width is the width of the browser, anddevice-width is the width the device reports, as shown in Figure 4.4.
Figure 4.4. Comparison of width and device-width
Let’s look through the remaining features for an idea of how we can use them:
orientation
accepts either portrait or landscape
aspect-ratio
such as 16:9, or 4:3
resolution
the Dots Per Inch (DPI), or Dots Per Centimetre (DPCM)
scan
a display type that targets televisions that use progressive scanning
grid
matches Teletype displays or devices that only show a single fixed font
monochrome
checks the number of bits per pixel in a monochrome frame buffer, with 0 being falsey
color
checks the number of bits per color of the device, with 0 being falsey
color-index
checks the number of entries in the color lookup table of the device, with 0 being falsey
For a thorough grasp of features, you’ll need to master the device’s aspect and resolution, which way it is rotated, and whether it displays in color. These are all terms you’d be familiar with when you’ve created graphics for the Web. Once again, we’re back on familiar turf with the HTML5 specification drawing on typical terms when it sets the standard. It makes the learning curve so much more approachable.
While support may vary on features, even the non-dimension-based features are within our reach, as the terminology used is relevant to the target industries. scan and grid might not be immediately obvious to today’s desktop-focused designers, but those features are targeted to other devices, and those terms are second nature for developers of such devices. If your work targeted television displays, for example, you’d be well-acquainted with scan andprogressive scanning.
What happened to media types?
It’s important to remember that while we’re concerned here with responsive web design, there are other considerations that can and should impact your application. Just because we’re undertaking RWD, doesn’t mean we’d overlook accessibility, internationalization, or how your application appears on non-Web displays.
When we talk about Cascading Style Sheets (CSS), we associate it with styling an HTML page in a browser. But CSS is capable of handling more that just that. Since CSS2 was introduced, we could specify stylesheets for specific media types such as screen or print. Now with ‘media queries’ in CSS3, we are able to target specific screen sizes.
We can have different blocks of CSS code for different screen and device sizes. If this idea doesn’t make you jump from your seat, then you’re probably missing the point. In today’s world, users view web pages on a wide range of screens. Screens can range from the large displays on their work stations, to their laptops on the air plane, to their iPad or other tablets while sitting in the park and finally on their small mobile phone screens on the go.
Imagine, as a web developer, if you had to build and maintain multiple version of each page to cater to each screen. I, for one, would certainly have switch careers and probably worked at a bakery. Anyway, thankfully for me and all my happy clients, I didn’t join a bakery. CSS3 introduced media queries and made life for web developers exciting once again.
If you’ve styled print documents with CSS, then you are already familiar with defining different styles for different devices. With media queries, we’ll take this to a new level. Rather than looking at what device it is, we will look at what capabilities the device has. More specifically, we will look at the following:
height and width of the device
height and width of the browser
screen resolution
orientation of the device (for mobile phones and tablets; portrait or landscape)
If your browser supports media queries, then you’re good to go. Before we jump into seeing how it works, click here to see if a working example. If you have a mobile phone that allows you to browser, open the link on it and see the difference. As an alternative, reduce the width of the window to 480 pixels and you will immediately see the difference.
Here are screenshots of the page at different widths.
Page layout of desktop screen.
Page layout of mobile phone.
Different Styles for Different Screens: How it Works
You must be thinking that to achieve this, you will have to learn a whole new chapter of CSS. Fortunately you don’t have to. All it takes is a few extra lines of code, or sometimes just a few words. The simplest way to use media queries is to have a block of CSS code in the same stylesheet file. So all the CSS that is specific to mobile phones, would be defined in the following block:
@media only screen and (max-device-width: 480px) { /* define mobile specific styles come here */ }
Usually we would define this at the end of the file in order to leverage the cascading property of CSS. The background color, the borders and other common attributes would typically be defined above and wont be changed here. The following properties are the ones that we would replace most often:
width
height
float
margins
For example, let’s say the logo of the company is 600 pixel wide on the desktop version of the website. Now on a device with a width of 480 pixels, the scroller will appear and that is not desirable. So we should have a smaller version of the logo and the CSS file would look like this:
If you notice, we have not over-written the border property for the logo, so the border will continue to show on mobile devices. Simple isn’t it?
Linking to Different Stylesheets Using Media Queries
Adding all the styles in the same CSS file is acceptable for the above example, but for a full-fledged website, it will become a pain to manage the code. That is why I prefer to link a new stylesheet for specific screen sizes. The way to do that is to use the media attribute of the link tag.
<link rel=“stylesheet” type=“text/css” media=“only screen and (max-device-width: 480px)” href=“mobile-device.css” />
Now you can define all the mobile specific styles in the mobile-devices.css file.
How to Test Multiple Devices?
Being able to style your website for various devices is one part of the problem. You need to be able to test too. If you are a proud owner of an iPhone, an android device, an iPad etc, then you’re can test it on each of these devices directly. For the rest of us, there is a brilliant site called ProtoFluid. It allows you to enter a URL (which can be a local URL too) and it renders the page as if it were being viewed on the browser of an iPhone, iPad and a wide variety of devices. Another huge advantage of using ProtoFluid is that it allows you to use Firebug on your site. Being able to use Firebug will hugely speed up the development process.
Conclusion
Media query is a powerful tool in a world where websites are viewed on a huge range of devices. With very little change, you can make an existing website mobile and tablet compliant. Today, when building a new website, many developers build it for the desktop screen and then use media queries to retro-fit it for the mobile and tablet. While this will work, its not the optimal way to do it. Media queries are meant for design presentation, not optimization. To optimize for the mobile, you have to optimize pictures and the markup.
Using JavaScript adds dynamic presentation effects to a theme. In addition to custom JavaScript files many Drupal developers find jQuery useful. jQuery is a lightweight JavaScript library which is built into Drupal. jQuery contains all the common DOM, event, effects, and Ajax functions.
Drupal 7 includes jQuery 1.4.4 and jQuery UI 1.8.7. Drupal 6.0 to 6.2 included jQuery 1.2.3 while Drupal 6.3 includes an update to jQuery 1.2.6. For use in module development which requires a later version of jQuery, apply the jQuery update module. When JavaScript is added to a page through Drupal, jQuery is automatically added to the page.
More comprehensive information on the JavaScript APIs and the use of JavaScript in Drupal can be found in the Developer Guide.
Drupalize.Me offers a free, 11-minute video introduction to using jQuery in Drupal 6&7… Intro to jQuery in Drupal
Adding JavaScript
There are two ways for Themes to easily add JavaScript to a page.
In .info File
JavaScript files can be added to a theme’s .info file using the scripts tag. For example, to add the script foo.js to every page on a Drupal site add the following to the theme’s .info file.
Scripts added in a theme’s .info file are added at the theme level of ordering and will come after core/library JavaScript and module JavaScript. This ordering is important because it allows the theme JavaScript an opportunity to act on the page after the JavaScript providing the functionality within the page.
In Drupal 6 there is a default script file, named script.js that can be added to a theme without specifying it in the .info file. If that script is included in the theme it will be automatically added to all pages. In Drupal 7 all script files need to be specified.
In template.php
Alternately, scripts can be added in the template.php file using drupal_add_js() or, in Drupal 7,drupal_add_library(). For example, adding a script in the root directory of a theme named foo.js would go like:
In Drupal 6:
<?php function example_preprocess_page(&$variables) { drupal_add_js(drupal_get_path('theme', 'example'). '/foo.js', 'theme'); // We need to rebuild the scripts variable with the new script included. $variables['scripts'] = drupal_get_js(); } ?>
Note, in Drupal 7 the $scripts variable does not need to be rebuilt. $scripts is built intemplate_process_html which happens after this function.
Drupal 7 includes library management. Libraries are collections of JavaScript, CSS, and dependent libraries. For example, Drupal 7 includes jQuery UI. jQuery UI is a component library with internal dependencies. When ui.autocomplete is included it needs ui.core and ui.position to be included as well. Drupal libraries takes care of this for us. Adding ui.autocomplete with all of it’s CSS, JS, and dependencies can be accomplished with the following code:
This one command includes jquery.ui.autocomplete.js, jquery.ui.autocomplete.css, and the dependencies of jquery.ui.position.js, jquery.ui.widget.js, jquery.ui.core.js, jquery.ui.core.css, and jquery.ui.theme.css. For more information on drupal_add_library see the API documentation.
JavaScript closures
It’s best practice to wrap your code in a closure. A closure is nothing more than a function that helps limit the scope of variables so you don’t accidentally overwrite global variables.
// Define a new function. (function () { // Variables defined in here will not affect the global scope. var window = "Whoops, at least I only broke my code."; console.log(window); // The extra set of parenthesis here says run the function we just defined. }()); // Our wacky code inside the closure doesn't affect everyone else. console.log(window);
A closure can have one other benefit, if we pass jQuery in as a parameter we can map it to the $ shortcut allowing us to use use $() without worrying if jQuery.noConflict() has been called.
// We define a function that takes one parameter named $. (function ($) { // Use jQuery with the shortcut: console.log($.browser); // Here we immediately call the function with jQuery as the parameter. }(jQuery));
Note that there are two acceptable syntaxes for closures: the parenthesis that closes the first parenthesis can come either before or after the (jQuery).
The .ready() function also has the ability to alias the jQuery object:
jQuery(document).ready(function($) { // Code that uses jQuery's $ can follow here. });
In Drupal 7 jQuery.noConflict() is called to make it easier to use other JS libraries, so you’ll either have to type out jQuery() or have the closure rename it for you. More examples can be found onjQuery’s api site.
JavaScript behaviors / JavaScript on AJAX forms
Drupal uses a “behaviors” system to provide a single mechanism for attaching JavaScript functionality to elements on a page. The benefit of having a single place for the behaviors is that they can be applied consistently when the page is first loaded and then when new content is added during AHAH/AJAX requests. In Drupal 7 behaviors have two functions, one called when content is added to the page and the other called when it is removed.
Behaviors are registered by setting them as properties of Drupal.behaviors. Drupal will call each and pass in a DOM element as the first parameter (in Drupal 7 a settings object will be passed as the second parameter). For the sake of efficiency the behavior function should do two things:
Limit the scope of searches to the context element and its children. This is done by passing context parameter along to jQuery: jQuery('.foo', context);
Avoid processing the same element multiple times. In Drupal 6 assign a marker class to the element and use that class to restrict selectors: jQuery('.foo:not(.foo-processed)', context).addClass('foo-processed').css('color', 'red');
In Drupal 7 use the jQuery Once plugin that’s bundled with core: jQuery('.foo', context).once('foo').css('color', 'red');
As a simple example lets look at how you’d go about finding all the https links on a page and adding some additional text marking them as secure, turning <a href="https://example.com">Example</a> into <a href="https://example.com">Example (Secure!)</a>. This should make the importance of only running the code once apparent, if our code ran twice the link would end up reading “Example (Secure!) (Secure!)”.
In Drupal 6 it would be done like this:
// Using the closure to map jQuery to $. (function ($) { // Store our function as a property of Drupal.behaviors. Drupal.behaviors.myModuleSecureLink = function (context) { // Find all the secure links inside context that do not have our processed // class. $('a[href^="https://"]:not(.secureLink-processed)', context) // Add the class to any matched elements so we avoid them in the future. .addClass('secureLink-processed') // Then stick some text into the link denoting it as secure. .append(' (Secure!)'); }; // You could add additional behaviors here. Drupal.behaviors.myModuleMagic = function(context) {}; }(jQuery));
In Drupal 7 it’s a little different because behaviors can be attached when content is added to the page and detached when it is removed:
// Using the closure to map jQuery to $. (function ($) { // Store our function as a property of Drupal.behaviors. Drupal.behaviors.myModuleSecureLink = { attach: function (context, settings) { // Find all the secure links inside context that do not have our processed // class. $('a[href^="https://"]', context) // Only process elements once. .once('secureLink') // Then stick some text into the link denoting it as secure. .append(' (Secure!)'); } }; // You could add additional behaviors here. Drupal.behaviors.myModuleMagic = { attach: function (context, settings) { }, detach: function (context, settings) { } }; }(jQuery));
JavaScript on your AJAX form
Attach jQuery to Drupal.behaviors, that way it can be run anytime new DOM elements are inserted. One example, if you’re using AJAX in Views, each time a section of the page reloads, it will reload/run jQuery.
Here’s how to do it!
Create a new file in your theme directory(i.e. /sites/all/themes/[mytheme]/), called script.js
Insert this into your theme .info file(i.e. /sites/all/themes/[mytheme]/[mytheme].info): scripts[] = script.js
Insert the following into script.js (the file you created in step 1):
Clicking anywhere on your website, now alerts – Hello World.
JavaScript theming
Drupal provides a theming mechanism for JavaScript code in a similar manner to the way theming works within the rest of Drupal. This enables themes to customize the markup generated by JavaScript.
Modules provide theme functions for their markup. For example, the following code uses the theme function powered (This displays a “powered by Drupal” icon):
When a theme wants to provide a different markup it can do so by providing an alternate theme function. Following our example the following function provides an a theme function for the theme.
While the modules theme function is at Drupal.theme.prototype.powered the theme’s is at Drupal.theme.powered. Including this function in the themes JavaScript will cause the markup generated by the snippet:
JavaScript theme functions are entirely free in their return value. They can vary from simple strings to complex data types like objects, arrays, and jQuery elements. Refer to the original (default) theme function to see what your custom theme function should return.
Cross reference to related community documentation (Drupal.org “Developer Guide” as well as “Theming Guide”):
Developer Guide – For more information on using JavaScript and jQuery in Drupal, see theJavaScript section of the developer guide. Also, join the JavaScript group on Groups.Drupal.org to get advice on JavaScript and jQuery:http://groups.drupal.org/javascript
I often see posts on the drupal.org forums and elsewhere in regard to implementing jQuery scripts and code into Drupal. It seems common that users try to attach JQuery right within page.tpl.php or html.tpl.php. In other words, it’s hard-coding a script into a page and it’s not ideal. Some try to render it using the PHP filter within a block or node. The disadvantages of these methods are that code added like this cannot be included in any caching or aggregation methods and can also cause conflicts that would be tricky to troubleshoot. For best Drupal theming practices, I have outlined some methods below.
A Few Methods
There are a few methods that work well for adding additional custom JQuery scripts to Drupal 7 and some of this depends on the use case. Do you have some general code that will be used sitewide or do you have specific code that just needs to be added to the home page or a specific content type for example? Here are the two most common ways:
drupal_add_js
This method is good for one-offs such as adding code to specific pages and not the entire site. Use the drupal_add_js method by adding code to your theme’s template.php file. In the snippet below, we test to see if it’s the drupal home page and then if it is, add the code.
function my_theme_preprocess_html(&$variables) {
if (drupal_is_front_page()) {
drupal_add_js(drupal_get_path('theme', 'my_theme') . '/js/my_script.js');
}
}
In the above code sample, you would replace ‘my_theme’ with the actual machine name of your theme. ‘js’ is a folder within your theme folder that contains your script(s). We can also use the drupal_add_js method to a specific content type like this:
This would add the script to all pages that are of content type “page”.
You can also use drupal_add_js method for adding a script to one specific node path (nid). Below we give a node id (nid) to add a custom script to a specific node path id, in this case /node/8
If you need to add a script to your entire site in every page, then you can use the above method without any conditions or you can include the script in your theme’s .info file like this:
scripts[] = js/custom.js
The Code
So now you are all set adding your script but how do you format JQuery calls for Drupal 7? A lot has changed with the way in which JQuery is called in Drupal 7. In Drupal 6, we used to do something like this:
One addtional hint is if you need to execute some JQuery where there is an Ajax event, you need to make JQuery aware of that. You can do that with an event handler for Ajax:
(function ($) {
//add drupal 7 code
Drupal.behaviors.MyfunctionTheme = {
attach: function(context, settings) {
//end drupal 7 calls
//Tell JQuery that there's an Ajax event first
$('.mydiv').ajaxComplete(function() {
// now your actual code
$(this).remove() // or whatever code you need to execute
});
}}})
(jQuery);
Note that I have used and tested all these methods in various sites I have designed, developed and themed. Let me know in the comments if you have any additional tips that I might have missed. Happy Drupal JQuery-ing!
JQuery Theming Tips for Drupal 7
I often see posts on the drupal.org forums and elsewhere in regard to implementing jQuery scripts and code into Drupal. It seems common that users try to attach JQuery right within page.tpl.php or html.tpl.php. In other words, it’s hard-coding a script into a page and it’s not ideal. Some try to render it using the PHP filter within a block or node. The disadvantages of these methods are that code added like this cannot be included in any caching or aggregation methods and can also cause conflicts that would be tricky to troubleshoot. For best Drupal theming practices, I have outlined some methods below.
A Few Methods
There are a few methods that work well for adding additional custom JQuery scripts to Drupal 7 and some of this depends on the use case. Do you have some general code that will be used sitewide or do you have specific code that just needs to be added to the home page or a specific content type for example? Here are the two most common ways:
drupal_add_js
This method is good for one-offs such as adding code to specific pages and not the entire site. Use the drupal_add_js method by adding code to your theme’s template.php file. In the snippet below, we test to see if it’s the drupal home page and then if it is, add the code.
function my_theme_preprocess_html(&$variables) {
if (drupal_is_front_page()) {
drupal_add_js(drupal_get_path('theme', 'my_theme') . '/js/my_script.js');
}
}
In the above code sample, you would replace ‘my_theme’ with the actual machine name of your theme. ‘js’ is a folder within your theme folder that contains your script(s). We can also use the drupal_add_js method to a specific content type like this:
This would add the script to all pages that are of content type “page”.
You can also use drupal_add_js method for adding a script to one specific node path (nid). Below we give a node id (nid) to add a custom script to a specific node path id, in this case /node/8
If you need to add a script to your entire site in every page, then you can use the above method without any conditions or you can include the script in your theme’s .info file like this:
scripts[] = js/custom.js
The Code
So now you are all set adding your script but how do you format JQuery calls for Drupal 7? A lot has changed with the way in which JQuery is called in Drupal 7. In Drupal 6, we used to do something like this:
One addtional hint is if you need to execute some JQuery where there is an Ajax event, you need to make JQuery aware of that. You can do that with an event handler for Ajax:
(function ($) {
//add drupal 7 code
Drupal.behaviors.MyfunctionTheme = {
attach: function(context, settings) {
//end drupal 7 calls
//Tell JQuery that there's an Ajax event first
$('.mydiv').ajaxComplete(function() {
// now your actual code
$(this).remove() // or whatever code you need to execute
});
}}})
(jQuery);
Note that I have used and tested all these methods in various sites I have designed, developed and themed. Let me know in the comments if you have any additional tips that I might have missed. Happy Drupal JQuery-ing!
original source: https://www.packtpub.com/books/content/drupal-7-social-networking-managing-users-and-profiles
What are we going to do and why?
Before we get started, let’s take a closer look at what we are going to do in this article and why. At the moment, our users can interact with the website and contribute content, including through their own personal blog. Apart from the blog, there isn’t a great deal which differentiates our users; they are simply a username with a blog! One key improvement to make now is to make provisions for customizable user profiles. Our site being a social network with a dinosaur theme, the following would be useful information to have on our users:
Details of their pet dinosaurs, including:
Name
Breed
Date of birth
Hobbies
Their details for other social networking sites; for example, links to their Facebook profile, Twitter account, or LinkedIn page
Location of the user (city / area)
Their web address (if they have their own website)
Some of these can be added to user profiles by adding new fields to profiles, using the built in Field API; however we will also install some additional modules to extend the default offering.
Many websites allow users to upload an to associate with their user account, either a photograph or an avatar to represent them. Drupal has provisions for this, but it has some drawbacks which can be fixed using Gravatar. Gravatar is a social avatar service through which users upload their avatar, which is then accessed by other websites that request the avatar using the user’s e-mail address. This is convenient for our users, as it saves them having to upload their avatars to our site, and reduces the amount of data stored on our site, as well as the amount of data being transferred to and from our site. Since not all users will want to use a third-party service for their avatars (particularly, users who are not already signed up to Gravatar) we can let them upload their own avatars if they wish, through the Upload module.
There are many other social networking sites out there, which don’t complete with ours, and are more generalized, as a result we might want to allow our users to promote their profiles for other social networks too. We can download and install the Follow module which will allow users to publicize their profiles for other social networking sites on their profile on our site.
Once our users get to know each other more, they may become more interested in each other’s posts and topics and may wish to look up a specific user’s contribution to the site. The tracker module allows users to track one another’s contributions to the site. It is a core module, which just needs to be enabled and set up.
Now that we have a better idea of what we are going to do in this , let’s get started!
Getting set up
As this article covers features provided by both core modules and contributed modules (which need to be downloaded first), let’s download and enable the modules first, saving us the need for continually downloading and enabling modules throughout the article.
These modules can be downloaded and then the contents extracted to the /sites/all/modules folder within our Drupal installation. Once extracted they will then be ready to be enabled within the Modules section of our admin area.
Users, roles, and permissions
Let’s take a detailed look at users, roles, and permissions and how they all fit together. Users, roles, and permissions are all managed from the People section of the administration area:
User management
Within the People section, users are listed by default on the main screen. These are user accounts which are either created by us, as administrators, or created when a visitor to our site signs up for a user account. From here we can search for particular types of users, create new users, and edit users—including updating their profiles, suspending their account, or delete them permanently from our social network. Once our site starts to gain popularity it will become more difficult for us to navigate through the user list. Thankfully there are search, sort, and filter features available to make this easier for us. Let’s start by taking a look at our user list:
(Move the mouse over the image to enlarge.)
This user list shows, for each user:
Their username
If their user account is active or blocked (their status)
The roles which are associated with their account
How long they have been a member of our community
When they last accessed our site
A link to edit the user’s account
Users: Viewing, searching, sorting, and filtering
Clicking on a username will take us to the profile of that particular user, allowing us to view their profile as normal. Clicking one of the headings in the user list allows us to sort the list from the field we selected:
This could be particularly useful to see who our latest members are, or to allow us to see which users are blocked, if we need to reactivate a particular account.
We can also filter the user list based on a particular role that is assigned to a user, a particular permission they have (by virtue of their roles), or by their status (if their account is active or blocked). This is managed from the SHOW ONLY USERS WHERE panel:
Creating a user
Within the People area, there is a link Add user, which will allow us to create a new user account for our site:
This takes us to the new user page where we are required to fill out the Username, E-mail address, andPassword (twice to confirm) for the new user account we wish to create. We can also select the status of the user (Active or Blocked), any roles we wish to apply to their account, and indicate if we want to automatically e-mail the user to notify them of their new account:
Editing a user
To edit a user account we simply need to click the edit link displayed next to the user in the user list. This takes us to a page similar to the create user screen, except that it is pre-populated with the users details. It also contains a few other settings related to some default installed modules. As we install new modules, the page may include more options.
Inform the user! If you are planning to change a user’s username, password, or e-mail address you should notify them of the change, otherwise they may struggle the next time they try to log in!
Suspending / blocking a user
If we need to block or suspend a user, we can do this from the edit screen by updating their status toBlocked:
This would prevent the user from accessing our site. For example, if a user had been posting inappropriate material, even after a number of warnings, we could block their account to prevent them from accessing the site.
Why block? Why not just delete? If we were to simply delete a user who was troublesome on the site, they could simply sign up again (unless we went to a separate area and also blocked their e-mail address and username). Of course, the user could still sign up again using a different e-mail address and a different username, but this helps us keep things under control.
Canceling and deleting a user account
Also within the edit screen is the option to cancel a user’s account:
On clicking the Cancel account button, we are given a number of options for how we wish to cancel the account:
The first and third options will at least keep the context of any discussions or contributions to which the user was involved with. The second option will unpublish their content, so if for example comments or pages are removed which have an impact on the community, we can at least re-enable them. The final option will delete the account and all content associated with it.
Finally, we can also select if the user themselves must confirm that they wish to have their account deleted. Particularly useful if this is in response to a request from the user to delete all of their data, they can be given a final chance to change their mind.
Bulk user operations
For occasions when we need to perform specific operations to a range of user accounts (for example, unblocking a number of users, or adding / removing roles from specific users) we can use the Update options panel, in the user list to do these:
From here we simply select the users we want to apply an action to, and then select one of the following options from the UPDATE OPTIONS list:
Unblock the selected users
Block the selected users
Cancel the selected user accounts
Add a role to the selected users
Remove a role from the selected users
Roles
Users are grouped into a number of roles, which in turn have permissions assigned to them. By default there are three roles within Drupal:
Administrators
Anonymous users
Authenticated users
The anonymous and authenticated roles can be edited but they cannot be renamed or deleted. We can manage user roles by navigating to People | Permissions | Roles:
The edit permissions link allows us to edit the permissions associated with a specific role. To create a new role, we simply need to enter the name for the role in the text box provided and click the Add role button.
The permissions section provides us with a grid view for roles and the available permissions. This allows us to see at a glance which roles can do what, and also allows us to quickly change the permissions of multiple roles:
This screen is particularly useful once new modules are installed; we can simply visit this page and select which roles should have permissions related to that module.
Permissions work on a “granted” basis; if a user is a member of a role which has a particular permission, then they have that permission. If they are members of other roles as well which don’t have that permission, it won’t make any difference.
Creating customizable user profiles
The provisions within Drupal for dynamically extending the fields available for content aren’t just limited to content; we can also change the fields related to a users profile. These fields can be set up to allow the user to add another instance of the field. If for example, we have a field for the name of their dinosaur, they could duplicate this to add one for each of their dinosaurs. However, it doesn’t support duplicating a group of fields (such as dinosaur’s name, breed, date of birth, and hobbies), so we will use a field collection (a module we downloaded) for that.
From our initial planning earlier in this , there are two fields we can create using the default field functionality—location of the user, and their web address:
To manage the fields associated with a user’s profile, we need to go to Configuration | People |Account settings and then click the MANAGE FIELDS tab:
From here we can add fields just as we did to content types earlier in the book; let’s start with adding the user’s web address—we will make it a field which can be duplicated in case they wish to list more than one website they have.
We start by adding the label for the field, the name for the field, and selecting Text as the type of data to be stored in the field:
Once we click the Save button to save the field, we are prompted to supply the maximum length of the field:
After clicking Save field settings, we are then taken to the screen to edit the field in more detail. On this screen, we should select that the field is to be displayed on the registration form:
We also want to change the number of values to Unlimited, which allows the user to enter as many of their web addresses as they wish:
We should then repeat this process for the user’s location, except we should leave the Number of values option as 1.
Listing your dinosaurs
To allow our users to enter multiples of a group of fields, we need to create a field collection, thanks to our newly downloaded module:
After entering the new field details and clicking save, we are taken to a confirmation screen (as there are no specific settings, such as field length) to set. After clicking Save field settings (a confusingly named button in light of the lack of settings) we are taken to the edit field screen, where we can select it as a field to be displayed on the registration form, and as a field we want the user to be able to enter multiple values of.
The field collection we have created is simply a container for a group of fields; we now need to go and setup the fields for our field collection. These can be managed from Structure | Field-collections, this screen lists all field-collections which have been created and allows us to manage their fields:
If we click the manage fields link, we are taken to the standard screen for adding and managing fields for a content type or for user profiles, which we are already familiar with. From here we should create fields for:
Name of the dinosaur
Breed of dinosaur
Date of birth
Hobbies
All of the fields should have theirNumber of values setting set to 1 , except for the Hobbies box, which we would want to allow any number of.
Unfortunately at the time of writing, field collections don’t display on the registration page, and instead only work on the users profile itself, and are added and managed by the user viewing their own profile.
Linking to other social network profiles
The Follow module which we downloaded and installed allows our users to enter their profiles for various social networks; this includes the following social networks out of the box:
Twitter
Facebook
Virb
MySpace
Picasa
Flickr
YouTube
Vimeo
Blip.tv
Last.fm
LinkedIn
Delicious
Tumblr
The actual links to these social networking sites are displayed in a block, which needs to be enabled. We need to go to Structure | Blocks, and from here we need to find the Follow User block, and select it to be part of the Sidebar second region (remember to click Save at the bottom of the page to save the changes):
Profile in action
If we now take a look at a profile with these new fields and options, you can see the web addresses, location, links to follow the user on other social networking sites, and their pet dinosaurs:
Additional dinosaurs can be added using the Addlink, from which the details can be added and any number of hobbies listed:
Finally, the social networking links can be edited from the My follow links tab:
Globally recognized avatars: Enabling Gravatars
Gravatars are globally recognized avatars (an avatar being a small picture used to represent a user when making comments or posts), and are very popular among blogs and forums, with many blog and forum systems supporting Gravatars. Gravatars enable users to use the same avatar across all socially-oriented sites they use, should they wish to.
The settings for this module are accessed through Configuration | People | Gravatar. Configuration options available include:
What default should be used if a user doesn’t have a Gravatar
The preferred size for Gravatars to be displayed within the site
Which sort of s are permitted (based off Gravatars maturity filter)
The following screenshot shows these configuration options:
Now when a user edits their profile they are presented with an option to either upload an avatar or if they have a valid Gravatar associated with their e-mail address, whether to use that instead:
Tracking user activity
The tracker module allows users to view the recent contributions of a user to the site, by clicking the Tracktab on their profile:
This is particularly useful if a user finds another user’s posts interesting; they can use this to find other contributions the user made in the hope that they too will be interesting. This however, is primitive user interaction, as it is only one-way; we will look at full user interaction later in the book.
User centric home page
Once a user has logged into the site we will want to redirect them to a stream of user activity, to truly take them into the social network. We can do this using actions and triggers. At the moment we don’t have a stream of activity, so we will set it up to take them to their own profile page for now.
Triggers are events on our site, such as a user logging in. Through the trigger settings we can assign anaction to happen when the event is triggered. Actions are managed from Configuration | System |Actions. To redirect the user when they log in we need to create an advanced action, Redirect to URL:
To redirect the user to their profile page, we should enter user as the URL, and click Save:
Once we have created our action we can associate it with a trigger. Triggers are managed in Structure |Triggers, and we need to select the User tab to list triggers related to user events.
From here we select the newly created Redirect to URL action from the TRIGGER: AFTER A USER HAS LOGGED IN section:
Once we click Assign, the action is bound to the user login trigger.
Working with login blocks These instructions for redirecting the user won’t work when you try logging in through a login block on the page. There are two ways around this:
remove the login block and force the user to use the login page
update the login block HTML to match the HTML on the main login page. More information can be found on the Drupal website, including a patch around the issue and HTML to replace the login block, athttp://drupal.org/node/286668 .
Account settings
The final user and profile related feature we have left is the user account settings area, which is managed from Configuration | People | Account settings. From here we can:
Change the name given to users who are not logged in
Change the administrator role
Set who can register user accounts, and if e-mail or administrator verification is required
Set the default action when a user opts to cancel their own account
Enable or disable user signatures
Enable, disable, and configure user pictures
Configure e-mails which are sent out to users when:
Their account is created by an administrator
Their account is pending approval
Their account has been created
Their account has been activated
Their account has been blocked
To confirm their account cancelation
Their account has been canceled
They have forgotten their password
Summary
We have now expanded our social networking site to allow users to sign up and customize their experience on the site. This included custom user profiles complete with links to their profiles on other social networking sites and details of their pet dinosaurs. We used globally recognized avatars to automatically pull in our user’s Avatar if they have one. A custom home page was set for our logged in users, and we enabled the viewing of recent contributions from other members.
We also looked through features to make it possible for us, as administrators, to manage our users, including creating and editing user profiles, deleting and canceling user accounts, updating the e-mails sent to our users on key events (registration, forgotten password, and so on), as well as the management of user roles and permissions.