[Picfinity-commit] SF.net SVN: picfinity: [70] trunk/.themes
Status: Beta
Brought to you by:
espadav8
From: <esp...@us...> - 2007-09-11 11:49:37
|
Revision: 70 http://picfinity.svn.sourceforge.net/picfinity/?rev=70&view=rev Author: espadav8 Date: 2007-09-11 04:49:39 -0700 (Tue, 11 Sep 2007) Log Message: ----------- Import initial jQuery theme (clean) Added Paths: ----------- trunk/.themes/clean/ trunk/.themes/clean/addComment.php trunk/.themes/clean/backgrounds.css trunk/.themes/clean/borders.css trunk/.themes/clean/clean.css trunk/.themes/clean/clean.js trunk/.themes/clean/clean.xsl trunk/.themes/clean/colours.css trunk/.themes/clean/empty.png trunk/.themes/clean/emptyicon.png trunk/.themes/clean/folder.png trunk/.themes/clean/foldericon.png trunk/.themes/clean/getComments.php trunk/.themes/clean/jquery-1.1.4.js trunk/.themes/clean/jquery.flydom-3.0.8.js trunk/.themes/clean/loadingAnimation.gif trunk/.themes/clean/plus.png trunk/.themes/clean/plus.svg trunk/.themes/clean/thickbox-3.1.css trunk/.themes/clean/thickbox-3.1.js Added: trunk/.themes/clean/addComment.php =================================================================== --- trunk/.themes/clean/addComment.php (rev 0) +++ trunk/.themes/clean/addComment.php 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,62 @@ +<?php + require_once('../../db.inc'); + + $image_md5 = mysql_real_escape_string($_POST['image_id']); + $ajax = mysql_real_escape_string($_POST['ajax']); + $name = mysql_real_escape_string($_POST['name']); + $email = mysql_real_escape_string($_POST['email']); + $web = mysql_real_escape_string($_POST['web']); + $comment = mysql_real_escape_string($_POST['comment']); + $user_ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']); + $approved = "1"; + + $query = "SELECT image_id FROM images WHERE image_md5 = '$image_md5'"; + $select_result = mysql_query($query); + + if ($select_result) + { + $image_id = mysql_fetch_row($select_result); + + $query = " + INSERT INTO comments + ( image_id + , user_name + , user_www + , user_email + , user_comment + , user_ip + , comment_rating + , approved + ) + VALUES + ( $image_id[0] + , '$name' + , '$web' + , '$email' + , '$comment' + , '$user_ip' + , 0 + , $approved + )"; + + $insert_result = mysql_query($query); + if ($insert_result) + { + header('Content-Type: text/xml'); + echo "<success><message>Comment added successfully</message></success>"; + } + else + { + header('Content-Type: text/xml'); + echo "<error><message>Error inserting comment</message>\n" + ."<message>".mysql_error()."</message>\n" + ."<message>".$query."</message>\n</error>"; + } + } + else + { + header('Content-Type: text/xml'); + echo "<error><message>Image md5 doesn't exist</message></error>"; + } + +?> Added: trunk/.themes/clean/backgrounds.css =================================================================== --- trunk/.themes/clean/backgrounds.css (rev 0) +++ trunk/.themes/clean/backgrounds.css 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,33 @@ +.folder a:hover, +.thumbnail a:hover, +.background1 +{ + background: #BCC557; +} + +#nav, +#welcomehelp, +#album, +#TB_window, +.background2 +{ + background: #CDE660; +} + +#nav li a:hover, +.background3 +{ + background: #FFD91B; +} + + +.background4 +{ + background: #F6C031; +} + +body, +.background5 +{ + background: #768047; +} \ No newline at end of file Added: trunk/.themes/clean/borders.css =================================================================== --- trunk/.themes/clean/borders.css (rev 0) +++ trunk/.themes/clean/borders.css 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,63 @@ +#nav, +#welcomehelp, +#album, +#TB_window, +.border1 +{ + border: #BCC557 solid 2px; +} + +.border2 +{ + border: #CDE660 solid 2px; +} + +.border3 +{ + border: #FFD91B solid 2px; +} + +.border4 +{ + border: #F6C031 solid 2px; +} + +.border5 +{ + border: #768047 solid 2px; +} + + + +#nav li a, +.border1.thin +{ + border: #BCC557 solid 1px; +} + +.border2.thin +{ + border: #CDE660 solid 1px; +} + +.border3.thin +{ + border: #FFD91B solid 1px; +} + +.border4.thin +{ + border: #F6C031 solid 1px; +} + +.folder, +.thumbnail, +.border5.thin +{ + border: #768047 solid 1px; +} + +.title +{ + border-top: #768047 solid 1px; +} \ No newline at end of file Added: trunk/.themes/clean/clean.css =================================================================== --- trunk/.themes/clean/clean.css (rev 0) +++ trunk/.themes/clean/clean.css 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,134 @@ +@import "thickbox-3.1.css"; +@import "colours.css"; +@import "borders.css"; +@import "backgrounds.css"; + +* +{ + padding: 0; + margin: 0; +} + +img +{ + display: block; + border: 0; +} + +h1 +{ + margin-bottom: 0.3em; + font-size: 2em; + text-align: center; +} + +#nav +{ + float: left; + padding: 0.2em; + width: 9em; + margin: 0 0.3em; +} + +#nav ul +{ + list-style: none; + font-size: 0.7em; +} + +#nav ul ul +{ + padding-left: 0.5em; + font-size: 1em; + display: none; +} + +#nav li +{ + padding: 0.1em 0; +} + +#nav li img +{ + float: left; + margin: 0.3em 0 0 0; +} + +#nav li img:hover +{ + cursor: pointer; +} + +#nav li a +{ + font-weight: bold; + text-decoration: none; + display: block; + margin-left: 12px; + padding: 0 0.3em; +} + +#album, +#welcomehelp +{ + overflow: hidden; + padding: 0.3em; + margin: 0 0.3em 0 0; +} + +#album +{ + display: none; +} + +.folder a, +.thumbnail a +{ + display: block; + height: 1.5em; + text-decoration: none; +} + + +.folder, +.thumbnail +{ + width: 9.5em; + height: 9.5em; + overflow: hidden; + text-align: center; + float: left; + margin: 0.3em 0.3em 0 0; +} + +.image img +{ + margin: 0 auto; +} + +.image +{ + width: 9.5em; + height: 8em; + display: block; + overflow: hidden; +} + +.image a +{ + padding: 0.3em 0 0 0; + width: 9.5em; + height: 7.7em; + display: block; +} + +.title +{ + display: block; + font-size: 0.8em; +} + +.title a +{ + padding: 0.3em 0 0 0; +} \ No newline at end of file Added: trunk/.themes/clean/clean.js =================================================================== --- trunk/.themes/clean/clean.js (rev 0) +++ trunk/.themes/clean/clean.js 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,250 @@ +var galleryXML; +var aniSpeed = 1000; + +$(document).ready( function() { + $.get("gallery.xml", + null, + function(xml) { + galleryXML = xml; + runSetup(); + preloadThumbnailImages(); + } + ); +}); + +function runSetup() +{ + $("body h1 a").click( function() + { + showWelcome(); + return false; + } + ); + + $("#nav a").click( function() + { + openFolder( $(this).parent().attr("id") ); + return false; + } + ); + + if ( $("#nav li img").length > 0 ) + { + $("#nav li img").click( function() + { + toggleFolder( $(this).parent().attr("id") ); + } + ); + } + else + { + $("#nav li a").css("margin-left", 0); + } +} + +function openFolder(folderID) +{ + var node = $("#"+folderID, galleryXML); + + if ( $("#welcomehelp").is(":visible") ) + { + $("#welcomehelp").slideUp(aniSpeed, function() { showFolder(folderID); } ); + } + else + { + showFolder(folderID); + } + + return false; +} + +function showFolder(folderID) +{ + // fade out the old album if one exists + if ($("#album").length > 0) + { + $("#album").slideUp(aniSpeed, function() { + $("#album").remove(); + showFolder(folderID); + }); + return; + } + + // show the sub-folders if there are any and hidden + if ( ($("#" + folderID + " ul").length > 0) && ( $("#" + folderID + " ul").is(":hidden") ) ) + { + toggleFolder(folderID); + } + + // get the node from the XML file + var galleryXmlNode = $("#"+folderID, galleryXML); + // get the name of the node (folder) + var folderName = galleryXmlNode.attr("name"); + // get the number of sub-folders + var folderChildren = galleryXmlNode.children("folder").length; + // get the number of images + var imageChildren = galleryXmlNode.children("image").length; + + // append the album div + $(document.body).createAppend( + 'div', { id: 'album' }, [ + 'p', { id: 'albumtitle' }, folderName + ] + ); + + // if we have any folders then append them + if ( folderChildren > 0 ) + { + // get a list of the folders + var child = galleryXmlNode.children("folder"); + + for (var i = 0; i < folderChildren; i++) + { + var folderId = child.attr("id"); + var folderName = child.attr("name"); + // append the folder to the album div + $("#album").createAppend( + 'div', { className: "folder" }, [ + 'p', { }, [ + 'a', { + href: "index.php?id="+folderId, + onclick: function() { openFolder( folderId ); return false; } + }, folderName + ] + ] + ); + + // move on to the next one + child = child.next(); + } + } + + // if we have any image then append them + if ( imageChildren > 0 ) + { + // get a list of the folders + var child = galleryXmlNode.children("image"); + + for (var i = 0; i < imageChildren; i++) + { + var imageFile = child.attr("file"); + var imageId = child.attr("id"); + var imageLoc = getImageFilePath( imageId ); + var imageThumbLoc = "./.thumbs/" + imageLoc; + var folderId = child.parent().attr("id"); + + // append the folder to the album div + $("#album").createAppend( + 'div', { className: "thumbnail" }, [ + 'span', { className: "image" }, [ + 'a', { + href: imageLoc, + className: "thickbox", + rel: "" + folderId + }, [ + 'img', { src: imageThumbLoc, alt: imageFile }, "", + ] + ], + 'span', { className: "title" }, [ + 'a', { + href: imageLoc, + onclick: function() { openImage( imageId ); return false; } + }, imageFile + ] + ] + ); + + // move on to the next one + child = child.next(); + } + } + + $("#album .folder a").click( function() + { + openFolder( $(this).parent().attr("id") ); + return false; + } + ); + + tb_init('a.thickbox'); + + $("#album").slideDown(aniSpeed); + return; +} + +function openImage(imageId) +{ + alert( getImageFilePath(imageId) ); +} + +function getImageFilePath(imageId) +{ + var imageNode = $("#"+imageId, galleryXML); + var parentNodes = imageNode.parents("folder"); + + var imageFilePath = ""; + + for (var i = 0; i < parentNodes.length; i++) + { + imageFilePath = $(parentNodes[i]).attr("name") + "/" + imageFilePath; + } + + imageFilePath = imageFilePath + imageNode.attr("file"); + imageFilePath = escape( imageFilePath ); + + return imageFilePath; +} + +function toggleFolder(folderID) +{ + if ( $("#" + folderID + " ul").is(":visible") ) + { + $("#" + folderID + " ul").slideUp(aniSpeed); + $("#" + folderID).removeClass("open"); + } + else + { + $("#" + folderID + " ul").slideDown(aniSpeed); + $("#" + folderID).addClass("open"); + } +} + +function showWelcome() +{ + if ( $("#album").length > 0 ) + { + $("#album").slideUp(aniSpeed, function() { + $("#album").remove(); + showWelcome(); + }); + } + else if ( $("#welcomehelp").is(":hidden") ) + { + $("#welcomehelp").slideDown(aniSpeed); + } + + return; +} + +function preloadThumbnailImages() +{ + var galleryImages = $("image", galleryXML); + var galleryImageFiles = Array(); + + for (var i = 0; i < galleryImages.length; i++) + { + var gall = $(galleryImages[i]); + var imageFilePath = "./.thumbs/" + getImageFilePath( gall.attr("id") ); + galleryImageFiles.push( imageFilePath ); + } + + $(document.createElement('img')).bind('load', + function() + { + if(galleryImageFiles[0]) + { + this.src = galleryImageFiles.shift(); + } + } + ).trigger('load'); +} Added: trunk/.themes/clean/clean.xsl =================================================================== --- trunk/.themes/clean/clean.xsl (rev 0) +++ trunk/.themes/clean/clean.xsl 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + <xsl:output + method="xml" + omit-xml-declaration="yes" + indent="yes" + doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" + doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" + /> + + <xsl:param name="title" /> + <xsl:param name="post_id" /> + <xsl:param name="themename">clean</xsl:param> + + <xsl:template match="/"> + <html> + <head> + <title><xsl:value-of select="$title" /></title> + + <link rel="stylesheet" type="text/css"> + <xsl:attribute name="href"><xsl:value-of select="concat('.themes/', $themename, '/', $themename, '.css')" /></xsl:attribute> + </link> + <script type="text/javascript"> + <xsl:attribute name="src"><xsl:value-of select="concat('.themes/', $themename, '/jquery-1.1.4.js')" /></xsl:attribute> + </script> + <script type="text/javascript"> + <xsl:attribute name="src"><xsl:value-of select="concat('.themes/', $themename, '/jquery.flydom-3.0.8.js')" /></xsl:attribute> + </script> + <script type="text/javascript"> + <xsl:attribute name="src"><xsl:value-of select="concat('.themes/', $themename, '/thickbox-3.1.js')" /></xsl:attribute> + </script> + <script type="text/javascript"> + <xsl:attribute name="src"><xsl:value-of select="concat('.themes/', $themename, '/', $themename, '.js')" /></xsl:attribute> + </script> + </head> + + <body> + <h1> + <a href="index.php"> + <xsl:value-of select="$title" /> + </a> + </h1> + + <xsl:apply-templates select="layout" mode="nav" /> + + <xsl:choose> + <xsl:when test="$post_id = 0"> + <xsl:apply-templates select="layout" /> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="layout" mode="post"/> + </xsl:otherwise> + </xsl:choose> + </body> + </html> + </xsl:template> + + <xsl:template match="layout"> + <div id="welcomehelp"> + <p> + Welcome to the <xsl:value-of select="$title" /> image gallery. To the left you'll see + all the main folders in this gallery, to look inside one please just click on the name. + This will open up the folder in this space as well as expanding the folder structure + should there be any sub-folders. If you just wish to expand the folder just click on the + [+] next to the folder name. + </p> + <p> + Enjoy looking around. + </p> + </div> + </xsl:template> + + <xsl:template name="replaceCharsInString"> + <xsl:param name="stringIn"/> + <xsl:param name="charsIn"/> + <xsl:param name="charsOut"/> + <xsl:choose> + <xsl:when test="contains($stringIn,$charsIn)"> + <xsl:value-of select="concat(substring-before($stringIn,$charsIn),$charsOut)"/> + <xsl:call-template name="replaceCharsInString"> + <xsl:with-param name="stringIn" select="substring-after($stringIn,$charsIn)"/> + <xsl:with-param name="charsIn" select="$charsIn"/> + <xsl:with-param name="charsOut" select="$charsOut"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$stringIn"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="nl2br"> + <xsl:param name="contents" /> + <xsl:choose> + <xsl:when test="contains($contents, ' ')"> + <xsl:value-of select="substring-before($contents, ' ')" /> + <br /> + <xsl:call-template name="nl2br"> + <xsl:with-param name="contents" select="substring-after($contents, ' ')" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$contents" /> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="layout" mode="nav"> + <div id="nav"> + <ul> + <xsl:apply-templates select="folder" mode="nav" /> + </ul> + </div> + </xsl:template> + + <xsl:template match="folder" mode="nav"> + <li> + <xsl:attribute name="id"><xsl:value-of select="@id" /></xsl:attribute> + <xsl:if test="count(folder) > 0"> + <img alt="Expand folder"> + <xsl:attribute name="src"><xsl:value-of select="concat('.themes/', $themename, '/plus.png')" /></xsl:attribute> + </img> + </xsl:if> + <a> + <xsl:attribute name="href">index.php?id=<xsl:value-of select="@id" /></xsl:attribute> + <xsl:value-of select="@name" /> + </a> + <xsl:if test="count(folder) > 0"> + <ul> + <xsl:apply-templates select="folder" mode="nav" /> + </ul> + </xsl:if> + </li> + </xsl:template> + +</xsl:stylesheet> Property changes on: trunk/.themes/clean/clean.xsl ___________________________________________________________________ Name: svn:executable + * Added: trunk/.themes/clean/colours.css =================================================================== --- trunk/.themes/clean/colours.css (rev 0) +++ trunk/.themes/clean/colours.css 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,25 @@ +.colour1 +{ + color: #BCC557; +} + +.colour2 +{ + color: #CDE660; +} + +h1 a, +.colour3 +{ + color: #FFD91B; +} + +.colour4 +{ + color: #F6C031; +} + +.colour5 +{ + color: #768047; +} \ No newline at end of file Added: trunk/.themes/clean/empty.png =================================================================== (Binary files differ) Property changes on: trunk/.themes/clean/empty.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: trunk/.themes/clean/emptyicon.png =================================================================== (Binary files differ) Property changes on: trunk/.themes/clean/emptyicon.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: trunk/.themes/clean/folder.png =================================================================== (Binary files differ) Property changes on: trunk/.themes/clean/folder.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: trunk/.themes/clean/foldericon.png =================================================================== (Binary files differ) Property changes on: trunk/.themes/clean/foldericon.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: trunk/.themes/clean/getComments.php =================================================================== --- trunk/.themes/clean/getComments.php (rev 0) +++ trunk/.themes/clean/getComments.php 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,48 @@ +<?php + require_once('../../db.inc'); + + header('Content-Type: text/xml'); + header("Cache-Control: no-cache, must-revalidate"); + + $image_md5 = mysql_real_escape_string($_GET['md5']); + + $query = " + SELECT user_name + , user_www + , user_email + , user_comment + , comment_rating + , date_added + FROM comments + INNER JOIN images + WHERE images.image_id = comments.image_id + AND images.image_md5 = '$image_md5' + ORDER BY date_added DESC"; + + $result = mysql_query($query); + + if ($result) + { + $comments_xml = "<?xml version=\"1.0\"?>" + . "<comments>"; + while ($row = mysql_fetch_assoc($result)) + { + $comments_xml .= "<comment>" + . "<name>".stripslashes($row['user_name'])."</name>" + . "<www>".stripslashes($row['user_www'])."</www>" + . "<email>".stripslashes($row['user_email'])."</email>" + . "<comment_text>".stripslashes($row['user_comment'])."</comment_text>" + . "<rating>".stripslashes($row['comment_rating'])."</rating>" + . "<added>".stripslashes($row['date_added'])."</added>" + . "</comment>"; + } + $comments_xml .= "</comments>"; + + echo $comments_xml; + } + else + { + + echo "<error><message>Error in getting the results</message></error>"; + } +?> Added: trunk/.themes/clean/jquery-1.1.4.js =================================================================== --- trunk/.themes/clean/jquery-1.1.4.js (rev 0) +++ trunk/.themes/clean/jquery-1.1.4.js 2007-09-11 11:49:39 UTC (rev 70) @@ -0,0 +1,2508 @@ +(function(){ +/* + * jQuery 1.1.4 - New Wave Javascript + * + * Copyright (c) 2007 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2007-08-23 21:49:27 -0400 (Thu, 23 Aug 2007) $ + * $Rev: 2862 $ + */ +// Map over jQuery in case of overwrite +if ( typeof jQuery != "undefined" ) + var _jQuery = jQuery; + +var jQuery = window.jQuery = function(a,c) { + // If the context is global, return a new object + if ( window == this || !this.init ) + return new jQuery(a,c); + + return this.init(a,c); +}; + +// Map over the $ in case of overwrite +if ( typeof $ != "undefined" ) + var _$ = $; + +// Map the jQuery namespace to the '$' one +window.$ = jQuery; + +var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; + +jQuery.fn = jQuery.prototype = { + init: function(a,c) { + // Make sure that a selection was provided + a = a || document; + + // Handle HTML strings + if ( typeof a == "string" ) { + var m = quickExpr.exec(a); + if ( m && (m[1] || !c) ) { + // HANDLE: $(html) -> $(array) + if ( m[1] ) + a = jQuery.clean( [ m[1] ] ); + + // HANDLE: $("#id") + else { + var tmp = document.getElementById( m[3] ); + if ( tmp ) + // Handle the case where IE and Opera return items + // by name instead of ID + if ( tmp.id != m[3] ) + return jQuery().find( a ); + else { + this[0] = tmp; + this.length = 1; + return this; + } + else + a = []; + } + + // HANDLE: $(expr) + } else + return new jQuery( c ).find( a ); + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction(a) ) + return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( a ); + + return this.setArray( + // HANDLE: $(array) + a.constructor == Array && a || + + // HANDLE: $(arraylike) + // Watch for when an array-like object is passed as the selector + (a.jquery || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType) && jQuery.makeArray( a ) || + + // HANDLE: $(*) + [ a ] ); + }, + jquery: "1.1.4", + + size: function() { + return this.length; + }, + + length: 0, + + get: function( num ) { + return num == undefined ? + + // Return a 'clean' array + jQuery.makeArray( this ) : + + // Return just the object + this[num]; + }, + pushStack: function( a ) { + var ret = jQuery(a); + ret.prevObject = this; + return ret; + }, + setArray: function( a ) { + this.length = 0; + Array.prototype.push.apply( this, a ); + return this; + }, + each: function( fn, args ) { + return jQuery.each( this, fn, args ); + }, + index: function( obj ) { + var pos = -1; + this.each(function(i){ + if ( this == obj ) pos = i; + }); + return pos; + }, + + attr: function( key, value, type ) { + var obj = key; + + // Look for the case where we're accessing a style value + if ( key.constructor == String ) + if ( value == undefined ) + return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined; + else { + obj = {}; + obj[ key ] = value; + } + + // Check to see if we're setting style values + return this.each(function(index){ + // Set all the styles + for ( var prop in obj ) + jQuery.attr( + type ? this.style : this, + prop, jQuery.prop(this, obj[prop], type, index, prop) + ); + }); + }, + + css: function( key, value ) { + return this.attr( key, value, "curCSS" ); + }, + + text: function(e) { + if ( typeof e != "object" && e != null ) + return this.empty().append( document.createTextNode( e ) ); + + var t = ""; + jQuery.each( e || this, function(){ + jQuery.each( this.childNodes, function(){ + if ( this.nodeType != 8 ) + t += this.nodeType != 1 ? + this.nodeValue : jQuery.fn.text([ this ]); + }); + }); + return t; + }, + + wrap: function() { + // The elements to wrap the target around + var a, args = arguments; + + // Wrap each of the matched elements individually + return this.each(function(){ + if ( !a ) + a = jQuery.clean(args, this.ownerDocument); + + // Clone the structure that we're using to wrap + var b = a[0].cloneNode(true); + + // Insert it before the element to be wrapped + this.parentNode.insertBefore( b, this ); + + // Find the deepest point in the wrap structure + while ( b.firstChild ) + b = b.firstChild; + + // Move the matched element to within the wrap structure + b.appendChild( this ); + }); + }, + append: function() { + return this.domManip(arguments, true, 1, function(a){ + this.appendChild( a ); + }); + }, + prepend: function() { + return this.domManip(arguments, true, -1, function(a){ + this.insertBefore( a, this.firstChild ); + }); + }, + before: function() { + return this.domManip(arguments, false, 1, function(a){ + this.parentNode.insertBefore( a, this ); + }); + }, + after: function() { + return this.domManip(arguments, false, -1, function(a){ + this.parentNode.insertBefore( a, this.nextSibling ); + }); + }, + end: function() { + return this.prevObject || jQuery([]); + }, + find: function(t) { + var data = jQuery.map(this, function(a){ return jQuery.find(t,a); }); + return this.pushStack( /[^+>] [^+>]/.test( t ) || t.indexOf("..") > -1 ? + jQuery.unique( data ) : data ); + }, + clone: function(deep) { + deep = deep != undefined ? deep : true; + var $this = this.add(this.find("*")); + if (jQuery.browser.msie) { + // Need to remove events on the element and its descendants + $this.each(function() { + this._$events = {}; + for (var type in this.$events) + this._$events[type] = jQuery.extend({},this.$events[type]); + }).unbind(); + } + + // Do the clone + var r = this.pushStack( jQuery.map( this, function(a){ + return a.cloneNode( deep ); + }) ); + + if (jQuery.browser.msie) { + $this.each(function() { + // Add the events back to the original and its descendants + var events = this._$events; + for (var type in events) + for (var handler in events[type]) + jQuery.event.add(this, type, events[type][handler], events[type][handler].data); + this._$events = null; + }); + } + + // copy form values over + if (deep) { + var inputs = r.add(r.find('*')).filter('select,input[@type=checkbox]'); + $this.filter('select,input[@type=checkbox]').each(function(i) { + if (this.selectedIndex) + inputs[i].selectedIndex = this.selectedIndex; + if (this.checked) + inputs[i].checked = true; + }); + } + + // Return the cloned set + return r; + }, + + filter: function(t) { + return this.pushStack( + jQuery.isFunction( t ) && + jQuery.grep(this, function(el, index){ + return t.apply(el, [index]); + }) || + + jQuery.multiFilter(t,this) ); + }, + + not: function(t) { + return this.pushStack( + t.constructor == String && + jQuery.multiFilter(t, this, true) || + + jQuery.grep(this, function(a) { + return ( t.constructor == Array || t.jquery ) + ? jQuery.inArray( a, t ) < 0 + : a != t; + }) + ); + }, + + add: function(t) { + return this.pushStack( jQuery.merge( + this.get(), + t.constructor == String ? + jQuery(t).get() : + t.length != undefined && (!t.nodeName || t.nodeName == "FORM") ? + t : [t] ) + ); + }, + is: function(expr) { + return expr ? jQuery.multiFilter(expr,this).length > 0 : false; + }, + + val: function( val ) { + return val == undefined ? + ( this.length ? this[0].value : null ) : + this.attr( "value", val ); + }, + + html: function( val ) { + return val == undefined ? + ( this.length ? this[0].innerHTML : null ) : + this.empty().append( val ); + }, + + slice: function() { + return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); + }, + domManip: function(args, table, dir, fn){ + var clone = this.length > 1, a; + + return this.each(function(){ + if ( !a ) { + a = jQuery.clean(args, this.ownerDocument); + if ( dir < 0 ) + a.reverse(); + } + + var obj = this; + + if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") ) + obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody")); + + jQuery.each( a, function(){ + if ( jQuery.nodeName(this, "script") ) { + if ( this.src ) + jQuery.ajax({ url: this.src, async: false, dataType: "script" }); + else + jQuery.globalEval( this.text || this.textContent || this.innerHTML || "" ); + } else + fn.apply( obj, [ clone ? this.cloneNode(true) : this ] ); + }); + }); + } +}; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, a = 1, al = arguments.length, deep = false; + + // Handle a deep copy situation + if ( target.constructor == Boolean ) { + deep = target; + target = arguments[1] || {}; + } + + // extend jQuery itself if only one argument is passed + if ( al == 1 ) { + target = this; + a = 0; + } + + var prop; + + for ( ; a < al; a++ ) + // Only deal with non-null/undefined values + if ( (prop = arguments[a]) != null ) + // Extend the base object + for ( var i in prop ) { + // Prevent never-ending loop + if ( target == prop[i] ) + continue; + + // Recurse if we're merging object values + if ( deep && typeof prop[i] == 'object' && target[i] ) + jQuery.extend( target[i], prop[i] ); + + // Don't bring in undefined values + else if ( prop[i] != undefined ) + target[i] = prop[i]; + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function(deep) { + window.$ = _$; + if ( deep ) + window.jQuery = _jQuery; + return jQuery; + }, + + // This may seem like some crazy code, but trust me when I say that this + // is the only cross-browser way to do this. --John + isFunction: function( fn ) { + return !!fn && typeof fn != "string" && !fn.nodeName && + fn.constructor != Array && /function/i.test( fn + "" ); + }, + + // check if an element is in a XML document + isXMLDoc: function(elem) { + return elem.documentElement && !elem.body || + elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; + }, + + // Evalulates a script in a global context + // Evaluates Async. in Safari 2 :-( + globalEval: function( data ) { + data = jQuery.trim( data ); + if ( data ) { + if ( window.execScript ) + window.execScript( data ); + else if ( jQuery.browser.safari ) + // safari doesn't provide a synchronous global eval + window.setTimeout( data, 0 ); + else + eval.call( window, data ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); + }, + // args is for internal usage only + each: function( obj, fn, args ) { + if ( args ) { + if ( obj.length == undefined ) + for ( var i in obj ) + fn.apply( obj[i], args ); + else + for ( var i = 0, ol = obj.length; i < ol; i++ ) + if ( fn.apply( obj[i], args ) === false ) break; + + // A special, fast, case for the most common use of each + } else { + if ( obj.length == undefined ) + for ( var i in obj ) + fn.call( obj[i], i, obj[i] ); + else + for ( var i = 0, ol = obj.length, val = obj[0]; + i < ol && fn.call(val,i,val) !== false; val = obj[++i] ){} + } + + return obj; + }, + + prop: function(elem, value, type, index, prop){ + // Handle executable functions + if ( jQuery.isFunction( value ) ) + value = value.call( elem, [index] ); + + // exclude the following css properties to add px + var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; + + // Handle passing in a number to a CSS property + return value && value.constructor == Number && type == "curCSS" && !exclude.test(prop) ? + value + "px" : + value; + }, + + className: { + // internal only, use addClass("class") + add: function( elem, c ){ + jQuery.each( (c || "").split(/\s+/), function(i, cur){ + if ( !jQuery.className.has( elem.className, cur ) ) + elem.className += ( elem.className ? " " : "" ) + cur; + }); + }, + + // internal only, use removeClass("class") + remove: function( elem, c ){ + elem.className = c != undefined ? + jQuery.grep( elem.className.split(/\s+/), function(cur){ + return !jQuery.className.has( c, cur ); + }).join(" ") : ""; + }, + + // internal only, use is(".class") + has: function( t, c ) { + return jQuery.inArray( c, (t.className || t).toString().split(/\s+/) ) > -1; + } + }, + swap: function(e,o,f) { + for ( var i in o ) { + e.style["old"+i] = e.style[i]; + e.style[i] = o[i]; + } + f.apply( e, [] ); + for ( var i in o ) + e.style[i] = e.style["old"+i]; + }, + + css: function(e,p) { + if ( p == "height" || p == "width" ) { + var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"]; + + jQuery.each( d, function(){ + old["padding" + this] = 0; + old["border" + this + "Width"] = 0; + }); + + jQuery.swap( e, old, function() { + if ( jQuery(e).is(':visible') ) { + oHeight = e.offsetHeight; + oWidth = e.offsetWidth; + } else { + e = jQuery(e.cloneNode(true)) + .find(":radio").removeAttr("checked").end() + .css({ + visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0" + }).appendTo(e.parentNode)[0]; + + var parPos = jQuery.css(e.parentNode,"position") || "static"; + if ( parPos == "static" ) + e.parentNode.style.position = "relative"; + + oHeight = e.clientHeight; + oWidth = e.clientWidth; + + if ( parPos == "static" ) + e.parentNode.style.position = "static"; + + e.parentNode.removeChild(e); + } + }); + + return p == "height" ? oHeight : oWidth; + } + + return jQuery.curCSS( e, p ); + }, + + curCSS: function(elem, prop, force) { + var ret, stack = [], swap = []; + + // A helper method for determining if an element's values are broken + function color(a){ + if ( !jQuery.browser.safari ) + return false; + + var ret = document.defaultView.getComputedStyle(a,null); + return !ret || ret.getPropertyValue("color") == ""; + } + + if (prop == "opacity" && jQuery.browser.msie) { + ret = jQuery.attr(elem.style, "opacity"); + return ret == "" ? "1" : ret; + } + + if (prop.match(/float/i)) + prop = styleFloat; + + if (!force && elem.style[prop]) + ret = elem.style[prop]; + + else if (document.defaultView && document.defaultView.getComputedStyle) { + + if (prop.match(/float/i)) + prop = "float"; + + prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase(); + var cur = document.defaultView.getComputedStyle(elem, null); + + if ( cur && !color(elem) ) + ret = cur.getPropertyValue(prop); + + // If the element isn't reporting its values properly in Safari + // then some display: none elements are involved + else { + // Locate all of the parent display: none elements + for ( var a = elem; a && color(a); a = a.parentNode ) + stack.unshift(a); + + // Go through and make them visible, but in reverse + // (It would be better if we knew the exact display type that they had) + for ( a = 0; a < stack.length; a++ ) + if ( color(stack[a]) ) { + swap[a] = stack[a].style.display; + stack[a].style.display = "block"; + } + + // Since we flip the display style, we have to handle that + // one special, otherwise get the value + ret = prop == "display" && swap[stack.length-1] != null ? + "none" : + document.defaultView.getComputedStyle(elem,null).getPropertyValue(prop) || ""; + + // Finally, revert the display styles back + for ( a = 0; a < swap.length; a++ ) + if ( swap[a] != null ) + stack[a].style.display = swap[a]; + } + + if ( prop == "opacity" && ret == "" ) + ret = "1"; + + } else if (elem.currentStyle) { + var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}); + ret = elem.currentStyle[prop] || elem.currentStyle[newProp]; + } + + return ret; + }, + + clean: function(a, doc) { + var r = []; + doc = doc || document; + + jQuery.each( a, function(i,arg){ + if ( !arg ) return; + + if ( arg.constructor == Number ) + arg = arg.toString(); + + // Convert html string into DOM nodes + if ( typeof arg == "string" ) { + // Trim whitespace, otherwise indexOf won't work as expected + var s = jQuery.trim(arg).toLowerCase(), div = doc.createElement("div"), tb = []; + + var wrap = + // option or optgroup + !s.indexOf("<opt") && + [1, "<select>", "</select>"] || + + !s.indexOf("<leg") && + [1, "<fieldset>", "</fieldset>"] || + + s.match(/^<(thead|tbody|tfoot|colg|cap)/) && + [1, "<table>", "</table>"] || + + !s.indexOf("<tr") && + [2, "<table><tbody>", "</tbody></table>"] || + + // <thead> matched above + (!s.indexOf("<td") || !s.indexOf("<th")) && + [3, "<table><tbody><tr>", "</tr></tbody></table>"] || + + !s.indexOf("<col") && + [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"] || + + // IE can't serialize <link> and <script> tags normally + jQuery.browser.msie && + [1, "div<div>", "</div>"] || + + [0,"",""]; + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + arg + wrap[2]; + + // Move to the right depth + while ( wrap[0]-- ) + div = div.lastChild; + + // Remove IE's autoinserted <tbody> from table fragments + if ( jQuery.browser.msie ) { + + // String was a <table>, *may* have spurious <tbody> + if ( !s.indexOf("<table") && s.indexOf("<tbody") < 0 ) + tb = div.firstChild && div.firstChild.childNodes; + + // String was a bare <thead> or <tfoot> + else if ( wrap[1] == "<table>" && s.indexOf("<tbody") < 0 ) + tb = div.childNodes; + + for ( var n = tb.length-1; n >= 0 ; --n ) + if ( jQuery.nodeName(tb[n], "tbody") && !tb[n].childNodes.length ) + tb[n].parentNode.removeChild(tb[n]); + + // IE completely kills leading whitespace when innerHTML is used + if ( /^\s/.test(arg) ) + div.insertBefore( doc.createTextNode( arg.match(/^\s*/)[0] ), div.firstChild ); + + } + + arg = jQuery.makeArray( div.childNodes ); + } + + if ( 0 === arg.length && (!jQuery.nodeName(arg, "form") && !jQuery.nodeName(arg, "select")) ) + return; + + if ( arg[0] == undefined || jQuery.nodeName(arg, "form") || arg.options ) + r.push( arg ); + else + r = jQuery.merge( r, arg ); + + }); + + return r; + }, + + attr: function(elem, name, value){ + var fix = jQuery.isXMLDoc(elem) ? {} : jQuery.props; + + // Safari mis-reports the default selected property of a hidden option + // Accessing the parent's selectedIndex property fixes it + if ( name == "selected" && jQuery.browser.safari ) + elem.parentNode.selectedIndex; + + // Certain attributes only work when accessed via the old DOM 0 way + if ( fix[name] ) { + if ( value != undefined ) elem[fix[name]] = value; + return elem[fix[name]]; + } else if ( jQuery.browser.msie && name == "style" ) + return jQuery.attr( elem.style, "cssText", value ); + + else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName(elem, "form") && (name == "action" || name == "method") ) + return elem.getAttributeNode(name).nodeValue; + + // IE elem.getAttribute passes even for style + else if ( elem.tagName ) { + + if ( value != undefined ) elem.setAttribute( name, value ); + if ( jQuery.browser.msie && /href|src/.test(name) && !jQuery.isXMLDoc(elem) ) + return elem.getAttribute( name, 2 ); + return elem.getAttribute( name ); + + // elem is actually elem.style ... set the style + } else { + // IE actually uses filters for opacity + if ( name == "opacity" && jQuery.browser.msie ) { + if ( value != undefined ) { + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + elem.zoom = 1; + + // Set the alpha filter to set the opacity + elem.filter = (elem.filter || "").replace(/alpha\([^)]*\)/,"") + + (parseFloat(value).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")"); + } + + return elem.filter ? + (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() : ""; + } + name = name.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();}); + if ( value != undefined ) elem[name] = value; + return elem[name]; + } + }, + trim: function(t){ + return (t||"").replace(/^\s+|\s+$/g, ""); + }, + + makeArray: function( a ) { + var r = []; + + // Need to use typeof to fight Safari childNodes crashes + if ( typeof a != "array" ) + for ( var i = 0, al = a.length; i < al; i++ ) + r.push( a[i] ); + else + r = a.slice( 0 ); + + return r; + }, + + inArray: function( b, a ) { + for ( var i = 0, al = a.length; i < al; i++ ) + if ( a[i] == b ) + return i; + return -1; + }, + merge: function(first, second) { + // We have to loop this way because IE & Opera overwrite the length + // expando of getElementsByTagName + + // Also, we need to make sure that the correct elements are being returned + // (IE returns comment nodes in a '*' query) + if ( jQuery.browser.msie ) { + for ( var i = 0; second[i]; i++ ) + if ( second[i].nodeType != 8 ) + first.push(second[i]); + } else + for ( var i = 0; second[i]; i++ ) + first.push(second[i]); + + return first; + }, + unique: function(first) { + var r = [], num = jQuery.mergeNum++; + + try { + for ( var i = 0, fl = first.length; i < fl; i++ ) + if ( num != first[i].mergeNum ) { + first[i].mergeNum = num; + r.push(first[i]); + } + } catch(e) { + r = first; + } + + return r; + }, + + mergeNum: 0, + grep: function(elems, fn, inv) { + // If a string is passed in for the function, make a function + // for it (a handy shortcut) + if ( typeof fn == "string" ) + fn = eval("false||function(a,i){return " + fn + "}"); + + var result = []; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, el = elems.length; i < el; i++ ) + if ( !inv && fn(elems[i],i) || inv && !fn(elems[i],i) ) + result.push( elems[i] ); + + return result; + }, + map: function(elems, fn) { + // If a string is passed in for the function, make a function + // for it (a handy shortcut) + if ( typeof fn == "string" ) + fn = eval("false||function(a){return " + fn + "}"); + + var result = []; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, el = elems.length; i < el; i++ ) { + var val = fn(elems[i],i); + + if ( val !== null && val != undefined ) { + if ( val.constructor != Array ) val = [val]; + result = result.concat( val ); + } + } + + return result; + } +}); + +/* + * Whether the W3C compliant box model is being used. + * + * @property + * @name $.boxModel + * @type Boolean + * @cat JavaScript + */ +var userAgent = navigator.userAgent.toLowerCase(); + +// Figure out what browser is being used +jQuery.browser = { + version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1], + safari: /webkit/.test(userAgent), + opera: /opera/.test(userAgent), + msie: /msie/.test(userAgent) && !/opera/.test(userAgent), + mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) +}; + +var styleFloat = jQuery.browser.msie ? "styleFloat" : "cssFloat"; + +jQuery.extend({ + // Check to see if the W3C box model is being used + boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat", + + styleFloat: jQuery.browser.msie ? "styleFloat" : "cssFloat", + + props: { + "for": "htmlFor", + "class": "className", + "float": styleFloat, + cssFloat: styleFloat, + styleFloat: styleFloat, + innerHTML: "innerHTML", + className: "className", + value: "value", + disabled: "disabled", + checked: "checked", + readonly: "readOnly", + selected: "selected", + maxlength: "maxLength" + } +}); + +jQuery.each({ + parent: "a.parentNode", + parents: "jQuery.parents(a)", + next: "jQuery.nth(a,2,'nextSibling')", + prev: "jQuery.nth(a,2,'previousSibling')", + siblings: "jQuery.sibling(a.parentNode.firstChild,a)", + children: "jQuery.sibling(a.firstChild)" +}, function(i,n){ + jQuery.fn[ i ] = function(a) { + var ret = jQuery.map(this,n); + if ( a && typeof a == "string" ) + ret = jQuery.multiFilter(a,ret); + return this.pushStack( jQuery.unique(ret) ); + }; +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after" +}, function(i,n){ + jQuery.fn[ i ] = function(){ + var a = arguments; + return this.each(function(){ + for ( var j = 0, al = a.length; j < al; j++ ) + jQuery(a[j])[n]( this ); + }); + }; +}); + +jQuery.each( { + removeAttr: function( key ) { + jQuery.attr( this, key, "" ); + this.removeAttribute( key ); + }, + addClass: function(c){ + jQuery.className.add(this,c); + }, + removeClass: function(c){ + jQuery.className.remove(this,c); + }, + toggleClass: function( c ){ + jQuery.className[ jQuery.className.has(this,c) ? "remove" : "add" ](this, c); + }, + remove: function(a){ + if ( !a || jQuery.filter( a, [this] ).r.length ) + this.parentNode.removeChild( this ); + }, + empty: function() { + while ( this.firstChild ) + this.removeChild( this.firstChild ); + } +}, function(i,n){ + jQuery.fn[ i ] = function() { + return this.each( n, arguments ); + }; +}); + +// DEPRECATED +jQuery.each( [ "eq", "lt", "gt", "contains" ], function(i,n){ + jQuery.fn[ n ] = function(num,fn) { + return this.filter( ":" + n + "(" + num + ")", fn ); + }; +}); + +jQuery.each( [ "height", "width" ], function(i,n){ + jQuery.fn[ n ] = function(h) { + return h == undefined ? + ( this.length ? jQuery.css( this[0], n ) : null ) : + this.css( n, h.constructor == String ? h : h + "px" ); + }; +}); + +var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ? + "(?:[\\w*_-]|\\\\.)" : + "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)", + quickChild = new RegExp("^[/>]\\s*(" + chars + "+)"), + quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"), + quickClass = new RegExp("^([#.]?)(" + chars + "*)"); + +jQuery.extend({ + expr: { + "": "m[2]=='*'||jQuery.nodeName(a,m[2])", + "#": "a.getAttribute('id')==m[2]", + ":": { + // Position Checks + lt: "i<m[3]-0", + gt: "i>m[3]-0", + nth: "m[3]-0==i", + eq: "m[3]-0==i", + first: "i==0", + last: "i==r.length-1", + even: "i%2==0", + odd: "i%2", + + // Child Checks + "first-child": "a.parentNode.getElementsByTagName('*')[0]==a", + "last-child": "jQuery.nth(a.parentNode.lastChild,1,'previousSibling')==a", + "only-child": "!jQuery.nth(a.parentNode.lastChild,2,'previousSibling')", + + // Parent Checks + parent: "a.firstChild", + empty: "!a.firstChild", + + // Text Check + contains: "(a.textContent||a.innerText||'').indexOf(m[3])>=0", + + // Visibility + visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"', + hidden: '"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"', + + // Form attributes + enabled: "!a.disabled", + disabled: "a.disabled", + checked: "a.checked", + selected: "a.selected||jQuery.attr(a,'selected')", + + // Form elements + text: "'text'==a.type", + radio: "'radio'==a.type", + checkbox: "'checkbox'==a.type", + file: "'file'==a.type", + password: "'password'==a.type", + submit: "'submit'==a.type", + image: "'image'==a.type", + reset: "'reset'==a.type", + button: '"button"==a.type||jQuery.nodeName(a,"button")', + input: "/input|select|textarea|button/i.test(a.nodeName)", + + // :has() + has: "jQuery.find(m[3],a).length" + }, + // DEPRECATED + "[": "jQuery.find(m[2],a).length" + }, + + // The regular expressions that power the parsing engine + parse: [ + // Match: [@value='test'], [@foo] + /^\[ *(@)([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/, + + // DEPRECATED + // Match: [div], [div p] + /^(\[)\s*(.*?(\[.*?\])?[^[]*?)\s*\]/, + + // Match: :contains('foo') + /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/, + + // Match: :even, :last-chlid, #id, .class + new RegExp("^([:.#]*)(" + chars + "+)") + ], + + multiFilter: function( expr, elems, not ) { + var old, cur = []; + + while ( expr && expr != old ) { + old = expr; + var f = jQuery.filter( expr, elems, not ); + expr = f.t.replace(/^\s*,\s*/, "" ); + cur = not ? elems = f.r : jQuery.merge( cur, f.r ); + } + + return cur; + }, + find: function( t, context ) { + // Quickly handle non-string expressions + if ( typeof t != "string" ) + return [ t ]; + + // Make sure that the context is a DOM Element + if ( context && !context.nodeType ) + context = null; + + // Set the correct context (if none is provided) + context = context || document; + + // DEPRECATED + // Handle the common XPath // expression + if ( !t.indexOf("//") ) { + //context = context.documentElement; + t = t.substr(2,t.length); + + // DEPRECATED + // And the / root expression + } else if ( !t.indexOf("/") && !context.ownerDocument ) { + context = context.documentElement; + t = t.substr(1,t.length); + if ( t.indexOf("/") >= 1 ) + t = t.substr(t.indexOf("/"),t.length); + } + + // Initialize the search + var ret = [context], done = [], last; + + // Continue while a selector expression exists, and while + // we're no longer looping upon ourselves + while ( t && last != t ) { + var r = []; + last = t; + + // DEPRECATED + t = jQuery.trim(t).replace( /^\/\//, "" ); + + var foundToken = false; + + // An attempt at speeding up child selectors that + // point to a specific element tag + var re = quickChild; + var m = re.exec(t); + + if ( m ) { + var nodeName = m[1].toUpperCase(); + + // Perform our own iteration and filter + for ( var i = 0; ret[i]; i++ ) + for ( var c = ret[i].firstChild; c; c = c.nextSibling ) + if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName.toUpperCase()) ) + r.push( c ); + + ret = r; + t = t.replace( re, "" ); + if ( t.indexOf(" ") == 0 ) continue; + foundToken = true; + } else { + // (.. and /) DEPRECATED + re = /^((\/?\.\.)|([>\/+~]))\s*(\w*)/i; + + if ( (m = re.exec(t)) != null ) { + r = []; + + var nodeName = m[4], mergeNum = jQuery.mergeNum++; + m = m[1]; + + for ( var j = 0, rl = ret.length; j < rl; j++ ) + if ( m.indexOf("..") < 0 ) { + var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild; + for ( ; n; n = n.nextSibling ) + if ( n.nodeType == 1 ) { + if ( m == "~" && n.mergeNum == mergeNum ) break; + + if (!nodeName || n.nodeName.toUpperCase() == nodeName.toUpperCase() ) { + if ( m == "~" ) n.mergeNum = mergeNum; + r.push( n ); + } + + if ( m == "+" ) break; + } + // DEPRECATED + } else + r.push( ret[j].parentNode ); + + ret = r; + + // And remove the token + t = jQuery.trim( t.replace( re, "" ) ); + foundToken = true; + } + } + + // See if there's still an expression, and that we haven't already + // matched a token + if ( t && !foundToken ) { + // Handle multiple expressions + if ( !t.indexOf(",") ) { + // Clean the result set + if ( context == ret[0] ) ret.shift(); + + // Merge the result sets + done = jQuery.merge( done, ret ); + + // Reset the context + r = ret = [context]; + + // Touch up the selector string + t = " " + t.substr(1,t.length); + + } else { + // Optimize for the case nodeName#idName + var re2 = quickID; + var m = re2.exec(t); + + // Re-organize the results, so that they're consistent + if ( m ) { + m = [ 0, m[2], m[3], m[1] ]; + + } else { + // Otherwise, do a traditional filter check for + // ID, class, and element selectors + re2 = quickClass; + m = re2.exec(t); + } + + m[2] = m[2].replace(/\\/g, ""); + + var elem = ret[ret.length-1]; + + // Try to do a global search by ID, where we can + if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) { + // Optimization for HTML document case + var oid = elem.getElementById(m[2]); + + // Do a quick check for the existence of the actual ID attribute + // to avoid selecting by the name attribute in IE + // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form + if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] ) + oid = jQuery('[@id="'+m[2]+'"]', elem)[0]; + + // Do a quick check for node name (where applicable) so + // that div#foo searches will be really fast + ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : []; + } else { + // We need to find all descendant elements + for ( var i = 0; ret[i]; i++ ) { + // Grab the tag name being searched for + var tag = m[1] != "" || m[0] == "" ? "*" : m[2]; + + // Handle IE7 being really dumb about <object>s + if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" ) + tag = "param"; + + r = jQuery.merge( r, ret[i].getElementsByTagName( tag )); + } + + // It's faster to filter by class and be done with it + if ( m[1] == "." ) + r = jQuery.classFilter( r, m[2] ); + + // Same with ID filtering + if ( m[1] == "#" ) { + var tmp = []; + + // Try to find the element with the ID + for ( var i = 0; r[i]; i++ ) + if ( r[i].getAttribute("id") == m[2] ) { + tmp = [ r[i] ]; + break; + } + + r = tmp; + } + + ret = r; + } + + t = t.replace( re2, "" ); + } + + } + + // If a selector string still exists + if ( t ) { + // Attempt to filter it + var val = jQuery.filter(t,r); + ret = r = val.r; + t = jQuery.trim(val.t); + } + } + + // An error occurred with the selector; + // just return an empty set instead + if ( t ) + ret = []; + + // Remove the root context + if ( ret && context == ret[0] ) + ret.shift(); + + // And combine the results + done = jQuery.merge( done, ret ); + + return done; + }, + + classFilter: function(r,m,not){ + m = " " + m + " "; + var tmp = []; + for ( var i = 0; r[i]; i++ ) { + var pass = (" " + r[i].className + " ").indexOf( m ) >= 0; + if ( !not && pass || not && !pass ) + tmp.push( r[i] ); + } + return tmp; + }, + + filter: function(t,r,not) { + var last; + + // Look for common filter expressions + while ( t && t != last ) { + last = t; + + var p = jQuery.parse, m; + + for ( var i = 0; p[i]; i++ ) { + m = p[i].exec( t ); + + if ( m ) { + // Remove what we just matched + t = t.substring( m[0].length ); + + m[2] = m[2].replace(/\\/g, ""); + break; + } + } + + if ( !m ) + break; + + // :not() is a special case that can be optimized by + // keeping it out of the expression list + if ( m[1] == ":" && m[2] == "not" ) + r = jQuery.filter(m[3], r, true).r; + + // We can get a big speed boost by filtering by class here + else if ( m[1] == "." ) + r = jQuery.classFilter(r, m[2], not); + + else if ( m[1] == "@" ) { + var tmp = [], type = m[3]; + + for ( var i = 0, rl = r.length; i < rl; i++ ) { + var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ]; + + if ( z == null || /href|src|selected/.test(m[2]) ) + z = jQuery.attr(a,m[2]) || ''; + + if ( (type == "" && !!z || + type == "=" && z == m[5] || + type == "!=" && z != m[5] || + type == "^=" && z && !z.indexOf(m[5]) || + type == "$=" && z.substr(z.length - m[5].length) == m[5] || + (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not ) + tmp.push( a ); + } + + r = tmp; + + // We can get a speed boost by handling nth-child here + } else if ( m[1] == ":" && m[2] == "nth-child" ) { + var num = jQuery.mergeNum++, tmp = [], + test = /(\d*)n\+?(\d*)/.exec( + m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" || + !/\D/.test(m[3]) && "n+" + m[3] || m[3]), + first = (test[1] || 1) - 0, last = test[2] - 0; + + for ( var i = 0, rl = r.length; i < rl; i++ ) { + var node = r[i], parentNode = node.parentNode; + + if ( num != parentNode.mergeNum ) { + var c = 1; + + for ( var n = parentNode.firstChild; n; n = n.nextSibling ) + if ( n.nodeType == 1 ) + n.nodeIndex = c++; + + parentNode.mergeNum = num; + } + + var add = false; + + if ( first == 1 ) { + if ( last == 0 || node.nodeIndex == last ) + add = true; + } else if ( (node.nodeIndex + last) % first == 0 ) + add = true; + + if ( add ^ not ) + tmp.push( node ); + } + + r = tmp; + + // Otherwise, find the expression to execute + } else { + var f = jQuery.expr[m[1]]; + if ( typeof f != "string" ) + f = jQuery.expr[m[1]][m[2]]; + + // Build a custom macro to enclose it + f = eval("false||function(a,i){return " + f + "}"); + + // Execute it against the current filter + r = jQuery.grep( r, f, not ); + } + } + + // Return an array of filtered elements (r) + // and the modified expression string (t) + return { r: r, t: t }; + }, + parents: function( elem ){ + var matched = []; + var cur = elem.parentNode; + while ( cur && cur != document ) { + matched.push( cur ); + cur = cur.parentNode; + } + return matched; + }, + nth: function(cur,result,dir,elem){ + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) + if ( cur.nodeType == 1 && ++num == result ) + break; + + return cur; + }, + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType == 1 && (!elem || n != elem) ) + r.push( n ); + } + + return r; + } +}); +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code orignated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function(element, type, handler, data) { + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( jQuery.browser.msie && element.setInterval != undefined ) + element = window; + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) + handler.guid = this.guid++; + + // if data is passed, bind to handler + if( data != undefined ) { + // Create temporary function pointer to original handler + var fn = handler; + + // Create unique handler function, wrapped around original handler + handler = function() { + // Pass arguments and context to original handler + return fn.apply(this, arguments); + }; + + // Store data in unique handler + handler.data = data; + + // Set the guid of unique handler to the same of original handler, so it can be removed + handler.guid = fn.guid; + } + + // Init the element's event structure + if (!element.$events) + element.$events = {}; + + if (!element.$handle) + element.$handle = function() { + // returned undefined or false + var val; + + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + if ( typeof jQuery == "undefined" || jQuery.event.triggered ) + return val; + + val = jQuery.event.handle.apply(element, arguments); + + return val; + }; + + // Get the current list of functions bound to this event + var handlers = element.$events[type]; + + // Init the event handler queue + if (!handlers) { + handlers = element.$events[type] = {}; + + // And bind the global event handler to the element + if (element.addEventListener) + element.addEventListener(type, element.$handle, false); + else + element.attachEvent("on" + type, element.$handle); + } + + // Add the function to the element's handler list + handlers[handler.guid] = handler; + + // Keep track of which events have been used, for global triggering + this.global[type] = true; + }, + + guid: 1, + global: {}, + + // Detach an event or set of events from an eleme... [truncated message content] |