2005-08-11 13:00:17 +00:00
// $Id$
2009-01-06 13:16:09 +00:00
var Drupal = Drupal || { 'settings' : { } , 'behaviors' : { } , 'locale' : { } } ;
2005-05-24 06:00:22 +00:00
2009-02-18 13:46:55 +00:00
// Allow other JavaScript libraries to use $.
jQuery . noConflict ( ) ;
// Indicate when other scripts use $ with out wrapping their code.
if ( $ === undefined ) {
2009-04-27 20:19:38 +00:00
$ = function ( ) {
alert ( 'Please wrap your JavaScript code in (function ($) { ... })(jQuery); to be compatible. See http://docs.jquery.com/Using_jQuery_with_Other_Libraries.' ) ;
2009-02-18 13:46:55 +00:00
} ;
}
2009-04-27 20:19:38 +00:00
( function ( $ ) {
2009-02-18 13:46:55 +00:00
2007-07-01 15:37:10 +00:00
/ * *
* Attach all registered behaviors to a page element .
*
* Behaviors are event - triggered actions that attach to page elements , enhancing
* default non - Javascript UIs . Behaviors are registered in the Drupal . behaviors
2008-10-29 10:01:28 +00:00
* object using the method 'attach' and optionally also 'detach' as follows :
2007-07-01 15:37:10 +00:00
* @ code
2008-10-29 10:01:28 +00:00
* Drupal . behaviors . behaviorName = {
2009-04-27 20:19:38 +00:00
* attach : function ( context ) {
2008-10-29 10:01:28 +00:00
* ...
* } ,
2009-04-27 20:19:38 +00:00
* detach : function ( context ) {
2008-10-29 10:01:28 +00:00
* ...
* }
2007-07-01 15:37:10 +00:00
* } ;
* @ endcode
*
* Drupal . attachBehaviors is added below to the jQuery ready event and so
* runs on initial page load . Developers implementing AHAH / AJAX in their
* solutions should also call this function after new page content has been
* loaded , feeding in an element to be processed , in order to attach all
* behaviors to the new content .
*
* Behaviors should use a class in the form behaviorName - processed to ensure
* the behavior is attached only once to a given element . ( Doing so enables
* the reprocessing of given elements , which may be needed on occasion despite
* the ability to limit behavior attachment to a particular element . )
*
* @ param context
* An element to attach behaviors to . If none is given , the document element
* is used .
2009-03-13 23:15:09 +00:00
* @ param settings
* An object containing settings for the current context . If none given , the
* global Drupal . settings object is used .
2007-07-01 15:37:10 +00:00
* /
2009-04-27 20:19:38 +00:00
Drupal . attachBehaviors = function ( context , settings ) {
2007-07-01 15:37:10 +00:00
context = context || document ;
2009-03-13 23:15:09 +00:00
settings = settings || Drupal . settings ;
2008-05-19 19:42:18 +00:00
// Execute all of them.
2009-04-27 20:19:38 +00:00
$ . each ( Drupal . behaviors , function ( ) {
2009-02-18 13:46:55 +00:00
if ( $ . isFunction ( this . attach ) ) {
2009-03-13 23:15:09 +00:00
this . attach ( context , settings ) ;
2008-10-29 10:01:28 +00:00
}
} ) ;
} ;
/ * *
* Detach registered behaviors from a page element .
*
* Developers implementing AHAH / AJAX in their solutions should call this
* function before page content is about to be removed , feeding in an element
* to be processed , in order to allow special behaviors to detach from the
* content .
*
* Such implementations should look for the class name that was added in their
* corresponding Drupal . behaviors . behaviorName . attach implementation , i . e .
* behaviorName - processed , to ensure the behavior is detached only from
* previously processed elements .
*
* @ param context
* An element to detach behaviors from . If none is given , the document element
* is used .
*
* @ see Drupal . attachBehaviors
* /
2009-04-27 20:19:38 +00:00
Drupal . detachBehaviors = function ( context , settings ) {
2008-10-29 10:01:28 +00:00
context = context || document ;
2009-03-13 23:15:09 +00:00
settings = settings || Drupal . settings ;
2008-10-29 10:01:28 +00:00
// Execute all of them.
2009-04-27 20:19:38 +00:00
$ . each ( Drupal . behaviors , function ( ) {
2009-02-18 13:46:55 +00:00
if ( $ . isFunction ( this . detach ) ) {
2009-03-13 23:15:09 +00:00
this . detach ( context , settings ) ;
2008-10-29 10:01:28 +00:00
}
2008-05-19 19:42:18 +00:00
} ) ;
2007-07-01 15:37:10 +00:00
} ;
2007-06-08 12:51:59 +00:00
/ * *
* Encode special characters in a plain - text string for display as HTML .
* /
2009-04-27 20:19:38 +00:00
Drupal . checkPlain = function ( str ) {
2007-06-08 12:51:59 +00:00
str = String ( str ) ;
var replace = { '&' : '&' , '"' : '"' , '<' : '<' , '>' : '>' } ;
for ( var character in replace ) {
2008-03-23 14:55:26 +00:00
var regex = new RegExp ( character , 'g' ) ;
str = str . replace ( regex , replace [ character ] ) ;
2007-06-08 12:51:59 +00:00
}
return str ;
} ;
/ * *
* Translate strings to the page language or a given language .
*
* See the documentation of the server - side t ( ) function for further details .
*
* @ param str
* A string containing the English string to translate .
* @ param args
* An object of replacements pairs to make after translation . Incidences
* of any key in this array are replaced with the corresponding value .
* Based on the first character of the key , the value is escaped and / or themed :
* - ! variable : inserted as is
* - @ variable : escape plain text to HTML ( Drupal . checkPlain )
* - % variable : escape text and theme as a placeholder for user - submitted
* content ( checkPlain + Drupal . theme ( 'placeholder' ) )
* @ return
* The translated string .
* /
2009-04-27 20:19:38 +00:00
Drupal . t = function ( str , args ) {
2007-06-08 12:51:59 +00:00
// Fetch the localized version of the string.
if ( Drupal . locale . strings && Drupal . locale . strings [ str ] ) {
str = Drupal . locale . strings [ str ] ;
}
if ( args ) {
2008-10-12 00:29:09 +00:00
// Transform arguments before inserting them.
2007-06-08 12:51:59 +00:00
for ( var key in args ) {
switch ( key . charAt ( 0 ) ) {
2008-10-12 00:29:09 +00:00
// Escaped only.
2007-06-08 12:51:59 +00:00
case '@' :
args [ key ] = Drupal . checkPlain ( args [ key ] ) ;
break ;
2008-10-12 00:29:09 +00:00
// Pass-through.
2007-06-08 12:51:59 +00:00
case '!' :
break ;
2008-10-12 00:29:09 +00:00
// Escaped and placeholder.
2007-06-08 12:51:59 +00:00
case '%' :
default :
args [ key ] = Drupal . theme ( 'placeholder' , args [ key ] ) ;
break ;
}
str = str . replace ( key , args [ key ] ) ;
}
}
return str ;
} ;
/ * *
* Format a string containing a count of items .
*
* This function ensures that the string is pluralized correctly . Since Drupal . t ( ) is
* called by this function , make sure not to pass already - localized strings to it .
*
* See the documentation of the server - side format _plural ( ) function for further details .
*
* @ param count
* The item count to display .
* @ param singular
* The string for the singular case . Please make sure it is clear this is
* singular , to ease translation ( e . g . use "1 new comment" instead of "1 new" ) .
* Do not use @ count in the singular string .
* @ param plural
* The string for the plural case . Please make sure it is clear this is plural ,
* to ease translation . Use @ count in place of the item count , as in " @ count
* new comments " .
* @ param args
* An object of replacements pairs to make after translation . Incidences
* of any key in this array are replaced with the corresponding value .
* Based on the first character of the key , the value is escaped and / or themed :
* - ! variable : inserted as is
* - @ variable : escape plain text to HTML ( Drupal . checkPlain )
* - % variable : escape text and theme as a placeholder for user - submitted
* content ( checkPlain + Drupal . theme ( 'placeholder' ) )
* Note that you do not need to include @ count in this array .
* This replacement is done automatically for the plural case .
* @ return
* A translated string .
* /
2009-04-27 20:19:38 +00:00
Drupal . formatPlural = function ( count , singular , plural , args ) {
2007-09-03 16:55:56 +00:00
var args = args || { } ;
2007-06-08 12:51:59 +00:00
args [ '@count' ] = count ;
// Determine the index of the plural form.
var index = Drupal . locale . pluralFormula ? Drupal . locale . pluralFormula ( args [ '@count' ] ) : ( ( args [ '@count' ] == 1 ) ? 0 : 1 ) ;
if ( index == 0 ) {
return Drupal . t ( singular , args ) ;
}
else if ( index == 1 ) {
return Drupal . t ( plural , args ) ;
}
else {
2009-04-26 19:18:46 +00:00
args [ '@count[' + index + ']' ] = args [ '@count' ] ;
2007-06-08 12:51:59 +00:00
delete args [ '@count' ] ;
2009-04-26 19:18:46 +00:00
return Drupal . t ( plural . replace ( '@count' , '@count[' + index + ']' ) ) ;
2007-06-08 12:51:59 +00:00
}
} ;
/ * *
* Generate the themed representation of a Drupal object .
*
* All requests for themed output must go through this function . It examines
* the request and routes it to the appropriate theme function . If the current
* theme does not provide an override function , the generic theme function is
* called .
*
* For example , to retrieve the HTML that is output by theme _placeholder ( text ) ,
* call Drupal . theme ( 'placeholder' , text ) .
*
* @ param func
* The name of the theme function to call .
* @ param ...
* Additional arguments to pass along to the theme function .
* @ return
* Any data the theme function returns . This could be a plain HTML string ,
* but also a complex object .
* /
2009-04-27 20:19:38 +00:00
Drupal . theme = function ( func ) {
2007-06-08 12:51:59 +00:00
for ( var i = 1 , args = [ ] ; i < arguments . length ; i ++ ) {
args . push ( arguments [ i ] ) ;
}
return ( Drupal . theme [ func ] || Drupal . theme . prototype [ func ] ) . apply ( this , args ) ;
} ;
- Patch #28483 by Steven: JavaScript enabled uploading.
Comment from Steven: It does this by redirecting the submission of the form to a hidden <iframe> when you click "Attach" (we cannot submit data through Ajax directly because you cannot read file contents from JS for security reasons). Once the file is submitted, the upload-section of the form is updated. Things to note:
* The feature degrades back to the current behaviour without JS.
* If there are errors with the uploaded file (disallowed type, too big, ...), they are displayed at the top of the file attachments fieldset.
* Though the hidden-iframe method sounds dirty, it's quite compact and is 100% implemented in .js files. The drupal.js api makes it a snap to use.
* I included some minor improvements to the Drupal JS API and code.
* I added an API drupal_call_js() to bridge the PHP/JS gap: it takes a function name and arguments, and outputs a <script> tag. The kicker is that it preserves the structure and type of arguments, so e.g. PHP associative arrays end up as objects in JS.
* I also included a progressbar widget that I wrote for drumm's ongoing update.php work. It includes Ajax status updating/monitoring, but it is only used as a pure throbber in this patch. But as the code was already written and is going to be used in the near future, I left that part in. It's pretty small ;). If PHP supports ad-hoc upload info in the future like Ruby on Rails, we can implement that in 5 minutes.
2005-08-31 18:37:30 +00:00
/ * *
2007-10-05 09:35:09 +00:00
* Parse a JSON response .
*
* The result is either the JSON object , or an object with 'status' 0 and 'data' an error message .
2006-02-05 19:04:58 +00:00
* /
2009-04-27 20:19:38 +00:00
Drupal . parseJson = function ( data ) {
2007-10-05 09:35:09 +00:00
if ( ( data . substring ( 0 , 1 ) != '{' ) && ( data . substring ( 0 , 1 ) != '[' ) ) {
return { status : 0 , data : data . length ? data : Drupal . t ( 'Unspecified error' ) } ;
2006-08-31 23:31:25 +00:00
}
2007-10-05 09:35:09 +00:00
return eval ( '(' + data + ');' ) ;
2006-10-14 02:39:48 +00:00
} ;
2006-08-31 23:31:25 +00:00
/ * *
* Freeze the current body height ( as minimum height ) . Used to prevent
* unnecessary upwards scrolling when doing DOM manipulations .
* /
2009-04-27 20:19:38 +00:00
Drupal . freezeHeight = function ( ) {
2006-08-31 23:31:25 +00:00
Drupal . unfreezeHeight ( ) ;
2009-04-26 19:18:46 +00:00
$ ( '<div id="freeze-height"></div>' ) . css ( {
2006-08-31 23:31:25 +00:00
position : 'absolute' ,
top : '0px' ,
left : '0px' ,
width : '1px' ,
height : $ ( 'body' ) . css ( 'height' )
2009-04-26 19:18:46 +00:00
} ) . appendTo ( 'body' ) ;
2006-10-14 02:39:48 +00:00
} ;
2006-08-31 23:31:25 +00:00
/ * *
2008-10-12 00:29:09 +00:00
* Unfreeze the body height .
2006-08-31 23:31:25 +00:00
* /
2009-04-27 20:19:38 +00:00
Drupal . unfreezeHeight = function ( ) {
2006-08-31 23:31:25 +00:00
$ ( '#freeze-height' ) . remove ( ) ;
2006-10-14 02:39:48 +00:00
} ;
2006-02-05 19:04:58 +00:00
- Patch #28483 by Steven: JavaScript enabled uploading.
Comment from Steven: It does this by redirecting the submission of the form to a hidden <iframe> when you click "Attach" (we cannot submit data through Ajax directly because you cannot read file contents from JS for security reasons). Once the file is submitted, the upload-section of the form is updated. Things to note:
* The feature degrades back to the current behaviour without JS.
* If there are errors with the uploaded file (disallowed type, too big, ...), they are displayed at the top of the file attachments fieldset.
* Though the hidden-iframe method sounds dirty, it's quite compact and is 100% implemented in .js files. The drupal.js api makes it a snap to use.
* I included some minor improvements to the Drupal JS API and code.
* I added an API drupal_call_js() to bridge the PHP/JS gap: it takes a function name and arguments, and outputs a <script> tag. The kicker is that it preserves the structure and type of arguments, so e.g. PHP associative arrays end up as objects in JS.
* I also included a progressbar widget that I wrote for drumm's ongoing update.php work. It includes Ajax status updating/monitoring, but it is only used as a pure throbber in this patch. But as the code was already written and is going to be used in the near future, I left that part in. It's pretty small ;). If PHP supports ad-hoc upload info in the future like Ruby on Rails, we can implement that in 5 minutes.
2005-08-31 18:37:30 +00:00
/ * *
2009-07-03 19:21:55 +00:00
* Wrapper around encodeURIComponent ( ) which avoids Apache quirks ( equivalent of
* drupal _encode _path ( ) in PHP ) . This function should only be used on paths , not
* on query string arguments .
- Patch #28483 by Steven: JavaScript enabled uploading.
Comment from Steven: It does this by redirecting the submission of the form to a hidden <iframe> when you click "Attach" (we cannot submit data through Ajax directly because you cannot read file contents from JS for security reasons). Once the file is submitted, the upload-section of the form is updated. Things to note:
* The feature degrades back to the current behaviour without JS.
* If there are errors with the uploaded file (disallowed type, too big, ...), they are displayed at the top of the file attachments fieldset.
* Though the hidden-iframe method sounds dirty, it's quite compact and is 100% implemented in .js files. The drupal.js api makes it a snap to use.
* I included some minor improvements to the Drupal JS API and code.
* I added an API drupal_call_js() to bridge the PHP/JS gap: it takes a function name and arguments, and outputs a <script> tag. The kicker is that it preserves the structure and type of arguments, so e.g. PHP associative arrays end up as objects in JS.
* I also included a progressbar widget that I wrote for drumm's ongoing update.php work. It includes Ajax status updating/monitoring, but it is only used as a pure throbber in this patch. But as the code was already written and is going to be used in the near future, I left that part in. It's pretty small ;). If PHP supports ad-hoc upload info in the future like Ruby on Rails, we can implement that in 5 minutes.
2005-08-31 18:37:30 +00:00
* /
2009-07-03 19:21:55 +00:00
Drupal . encodePath = function ( item , uri ) {
2006-08-31 23:31:25 +00:00
uri = uri || location . href ;
2007-07-13 20:07:15 +00:00
item = encodeURIComponent ( item ) . replace ( /%2F/g , '/' ) ;
return ( uri . indexOf ( '?q=' ) != - 1 ) ? item : item . replace ( /%26/g , '%2526' ) . replace ( /%23/g , '%2523' ) . replace ( /\/\//g , '/%252F' ) ;
2006-10-14 02:39:48 +00:00
} ;
2006-08-31 23:31:25 +00:00
2007-04-09 13:58:03 +00:00
/ * *
* Get the text selection in a textarea .
* /
2009-04-27 20:19:38 +00:00
Drupal . getSelection = function ( element ) {
2009-04-26 19:18:46 +00:00
if ( typeof element . selectionStart != 'number' && document . selection ) {
2008-10-12 00:29:09 +00:00
// The current selection.
2007-04-09 13:58:03 +00:00
var range1 = document . selection . createRange ( ) ;
var range2 = range1 . duplicate ( ) ;
// Select all text.
range2 . moveToElementText ( element ) ;
// Now move 'dummy' end point to end point of original range.
range2 . setEndPoint ( 'EndToEnd' , range1 ) ;
// Now we can calculate start and end points.
var start = range2 . text . length - range1 . text . length ;
var end = start + range1 . text . length ;
return { 'start' : start , 'end' : end } ;
}
return { 'start' : element . selectionStart , 'end' : element . selectionEnd } ;
2007-06-01 09:05:45 +00:00
} ;
2007-04-09 13:58:03 +00:00
2008-01-04 11:53:21 +00:00
/ * *
* Build an error message from ahah response .
* /
2009-04-27 20:19:38 +00:00
Drupal . ahahError = function ( xmlhttp , uri ) {
2009-05-03 07:35:37 +00:00
if ( xmlhttp . status == 200 || ( xmlhttp . status == 500 && xmlhttp . statusText == 'Service unavailable (with message)' ) ) {
2009-02-18 13:46:55 +00:00
if ( $ . trim ( xmlhttp . responseText ) ) {
2009-05-03 07:35:37 +00:00
var message = Drupal . t ( "An error occurred. \nPath: @uri\nMessage: !text" , { '@uri' : uri , '!text' : xmlhttp . responseText } ) ;
2008-01-04 11:53:21 +00:00
}
else {
2009-05-03 07:35:37 +00:00
var message = Drupal . t ( "An error occurred. \nPath: @uri\n(no information available)." , { '@uri' : uri } ) ;
2008-01-04 11:53:21 +00:00
}
}
else {
2009-05-03 07:35:37 +00:00
var message = Drupal . t ( "An HTTP error @status occurred. \nPath: @uri" , { '@uri' : uri , '@status' : xmlhttp . status } ) ;
2008-01-04 11:53:21 +00:00
}
2009-02-18 13:46:55 +00:00
return message . replace ( /\n/g , '<br />' ) ;
} ;
2008-01-04 11:53:21 +00:00
2009-04-26 00:59:24 +00:00
// Class indicating that JS is enabled; used for styling purpose.
$ ( 'html' ) . addClass ( 'js' ) ;
// 'js enabled' cookie.
document . cookie = 'has_js=1; path=/' ;
// Attach all behaviors.
2009-04-27 20:19:38 +00:00
$ ( function ( ) {
2009-04-26 00:59:24 +00:00
Drupal . attachBehaviors ( document , Drupal . settings ) ;
} ) ;
2007-06-08 12:51:59 +00:00
/ * *
* The default themes .
* /
Drupal . theme . prototype = {
/ * *
* Formats text for emphasized display in a placeholder inside a sentence .
*
* @ param str
* The text to format ( plain - text ) .
* @ return
* The formatted text ( html ) .
* /
2009-04-27 20:19:38 +00:00
placeholder : function ( str ) {
2007-06-08 12:51:59 +00:00
return '<em>' + Drupal . checkPlain ( str ) + '</em>' ;
}
} ;
2009-02-18 13:46:55 +00:00
} ) ( jQuery ) ;