project.index
# MediaWiki install & usage
-cache/*.cdb
+cache
images/[0-9a-f]
images/archive
images/deleted
resources/jquery.effects
resources/jquery.tipsy
resources/jquery.ui
-resources/mediawiki.libs/mediawiki.libs.jpegmeta.js
+resources/mediawiki.libs
tests/jasmine/lib/jasmine-1.0.1/jasmine-html.js
tests/jasmine/lib/jasmine-1.0.1/jasmine.js
"jquery": true,
"nomen": true,
- "onevar": false
+ "onevar": true
}
This only affects installations which have $wgAllowCopyUploads set to true.
* Removed f-prot support from $wgAntivirusSetup.
* New variable $wgDBerrorLogTZ to provide dates in the error log in a
- different timezone than the wiki timezone set by $wgLocalTimezone.
+ different timezone than the wiki timezone set by $wgLocaltimezone.
* New variables $wgDBssl and $wgDBcompress to enable SSL and compression for database
connections, if either are available for the selected DB type.
* &useskin=default will now always display the default skin. Useful for users with a
preference for the non-default skin to look at something using the default skin.
* (bug 27619) Remove preference option to display broken links as link?
-* (bug 34896) Update jQuery JSON plugin to v2.3 (2011-09-17).
+* (bug 34896) jQuery JSON plugin upgraded to v2.3 (2011-09-17).
* (bug 34302) Add CSS classes to email fields in user preferences.
* Introduced $wgDebugDBTransactions to trace transaction status (currently PostgreSQL only).
* (bug 23795) Add parser itself to ParserMakeImageParams hook.
* (bug 35685) api.php URL and other entry point URLs are now listed on
Special:Version
* Edit notices can now be translated.
-* (bug 35680) jQuery upgraded to 1.7.2.
-* jQuery UI upgraded to 1.8.22.
-* (bug 35705) QUnit upgraded from v1.2.0 to v1.8.0.
+* jQuery upgraded to 1.7.2
+* jQuery UI upgraded to 1.8.23.
+* QUnit upgraded from v1.2.0 to v1.10.0.
* (bug 37604) jquery.cookie upgraded to 2011 version.
* (bug 22887) Add warning and tracking category for preprocessor errors
* (bug 31704) Allow selection of associated namespace on the watchlist
* HTMLForm mutators can now be chained (they return $this)
* A new message, "api-error-filetype-banned-type", is available for formatting
API upload errors due to the file extension blacklist.
-* jsMessage: Redesigned in Vector/Monobook as floating bubble with auto-hide.
* New hook 'ParserTestGlobals' allows to set globals before running parser tests.
* Allow importing pages as subpage.
* Add lang and hreflang attributes to language links on Login page.
* Show change tags when transclude Special:Recentchanges(linked) or Special:Newpages.
* (bug 23226) Add |class= parameter to image links in order to add class(es) to HTML img tag.
* (bug 39431) SVG animated status is now shown in long description
-* (bug 39376) jquery.form upgraded to 3.14
+* (bug 39376) jquery.form upgraded to 3.14.
* SVG files will now show the actual width in the SVG's specified units
in the metadata box.
* Added ResourceLoader module "jquery.jStorage".
+* (bug 39273) Added AJAX support for "Show changes" (diff) in LivePreview.
+* Added ResourceLoader module "jquery.badge".
+* mw.util.$content now points to the overall content area in the skin rather than just
+ page text content area. If you need the old behaviour please use $( '#mw-content-text').
+* jsMessage has been replaced with a floating bubble notification system complete
+ with auto-hide, multi-message support, and message replacement tags.
+* jquery.messageBox which appears to be unused by both core and extensions has
+ been removed.
+* (bug 34939) made link parsking insensitive ([HttP://])
=== Bug fixes in 1.20 ===
* (bug 30245) Use the correct way to construct a log page title.
* (bug 27111) Cascading foreign file repos now fetch shared descriptions properly.
* EXIF below sea level GPS altitude data is now shown correctly.
* (bug 39284) jquery.tablesorter should not consider "."" or "?"" to be a currency.
+* (bug 39273) "Show changes" should not be incorrectly displayed in the Live Preview state.
+* Made body-content lang attribute honor the variant language when it is set.
=== API changes in 1.20 ===
* (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.
* (bug 34313) MediaWiki API intro message about "HTML format" should mention
the format parameter.
* (bug 32384) Allow descending order for list=watchlistraw.
-* (bug 31883) Limit of bkusers of list=blocks and titles of action=query is not documented in API help.
+* (bug 31883) Limit of bkusers of list=blocks and titles of action=query is
+ not documented in API help.
* (bug 32492) API now allows editing using pageid.
* (bug 32497) API now allows changing of protection level using pageid.
* (bug 32498) API now allows comparing pages using pageids.
* Watchlist notification timestamp may be queried by page and may be updated via the API.
* (bug 38904) prop=revisions&rvstart=... no longer blows up when continuing.
* (bug 39032) ApiQuery generates help in constructor.
-* (bug 11142) Improve file extension blacklist error reporting in API upload
-* (bug 39635) PostgreSQL LOCK IN SHARE MODE option is a syntax error
+* (bug 11142) Improve file extension blacklist error reporting in API upload.
+* (bug 39635) PostgreSQL LOCK IN SHARE MODE option is a syntax error.
+* (bug 36329) Accesskey tooltips for Firefox 14 on Mac should use "ctrl-option-" prefix.
=== Languages updated in 1.20 ===
* Deprecated DatabaseBase functions newFromParams(), newFromType(), set(),
quote_ident(), and escapeLike() were removed.
* Use of __DIR__ instead of dirname( __FILE__ ).
+* OutputPage::wrapWikiMsg() no longer supports the 'options' parameter. It was
+ not used and complicated migration to Message class.
== Compatibility ==
$tokenFunctions array and return true (returning false makes no sense)
$tokenFunctions: array(action => callback)
+'ApiMain::onException': Called by ApiMain::executeActionWithErrorHandling()
+when an exception is thrown during API action execution.
+$apiMain: Calling ApiMain instance.
+$e: Exception object.
+
'ApiRsdServiceApis': Add or remove APIs from the RSD services list.
Each service should have its own entry in the $apis array and have a
unique name, passed as key for the array that represents the service data.
return true;
}
+ /**
+ * Should MediaWiki store passwords in its local database?
+ *
+ * @return bool
+ */
+ public function allowSetLocalPassword() {
+ return true;
+ }
+
/**
* Set the given password in the authentication database.
* As a special case, the password may be set to null to request
'StubObject' => 'includes/StubObject.php',
'StubUserLang' => 'includes/StubObject.php',
'TablePager' => 'includes/Pager.php',
+ 'MWTimestamp' => 'includes/Timestamp.php',
'Title' => 'includes/Title.php',
'TitleArray' => 'includes/TitleArray.php',
'TitleArrayFromResult' => 'includes/TitleArray.php',
* Function that gets called when initialization is done.
*
* @since 1.20
- * @var function
+ * @var callable
*/
protected $onInitHandler = false;
+ /**
+ * Elements to build a cache key with.
+ *
+ * @since 1.20
+ * @var array
+ */
+ protected $cacheKey = array();
+
/**
* Sets if the cache should be enabled or not.
*
* @since 1.20
*
* @return string
+ * @throws MWException
*/
protected function getCacheKeyString() {
+ if ( $this->cacheKey === array() ) {
+ throw new MWException( 'No cache key set, so cannot obtain or save the CacheHelper values.' );
+ }
+
return call_user_func_array( 'wfMemcKey', $this->cacheKey );
}
return $with; # XXX: copy first?
} if ( $section == 'new' ) {
# Inserting a new section
- if ( $sectionTitle ) {
- $subject = wfMessage( 'newsectionheaderdefaultlevel' )
- ->inContentLanguage()->params( $sectionTitle )->text();
- $subject .= "\n\n";
- } else {
- $subject = '';
- }
+ $subject = $sectionTitle ? wfMessage( 'newsectionheaderdefaultlevel' )
+ ->rawParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
if ( wfRunHooks( 'PlaceNewSection', array( $this, $oldtext, $subject, &$text ) ) ) {
$text = strlen( trim( $oldtext ) ) > 0
? "{$oldtext}\n\n{$subject}{$text}"
{
$truncatedtext = $newContent->getTextForSummary(
250
- - strlen( wfMsgForContent( 'autoredircomment' ) )
+ - strlen( wfMessage( 'autoredircomment' )->inContentLanguage()->text() )
- strlen( $rt->getFullText() ) );
- return wfMsgForContent( 'autoredircomment', $rt->getFullText(), $truncatedtext );
+ return wfMessage( 'autoredircomment', $rt->getFullText() )
+ ->rawParams( $truncatedtext )->inContentLanguage()->text();
}
}
// the summary.
$truncatedtext = $newContent->getTextForSummary(
- 200 - strlen( wfMsgForContent( 'autosumm-new' ) ) );
+ 200 - strlen( wfMessage( 'autosumm-new' )->inContentLanguage()->text() ) );
- return wfMsgForContent( 'autosumm-new', $truncatedtext );
+ return wfMessage( 'autosumm-new' )->rawParams( $truncatedtext )
+ ->inContentLanguage()->text();
}
// Blanking auto-summaries
if ( !empty( $oldContent ) && $oldContent->getSize() > 0 && $newContent->getSize() == 0 ) {
- return wfMsgForContent( 'autosumm-blank' );
+ return wfMessage( 'autosumm-blank' )->inContentLanguage()->text();
} elseif ( !empty( $oldContent )
&& $oldContent->getSize() > 10 * $newContent->getSize()
&& $newContent->getSize() < 500 )
// Removing more than 90% of the article
$truncatedtext = $newContent->getTextForSummary(
- 200 - strlen( wfMsgForContent( 'autosumm-replace' ) ) );
+ 200 - strlen( wfMessage( 'autosumm-replace' )->inContentLanguage()->text() ) );
- return wfMsgForContent( 'autosumm-replace', $truncatedtext );
+ return wfMessage( 'autosumm-replace' )->rawParams( $truncatedtext )
+ ->inContentLanguage()->text();
}
// If we reach this point, there's no applicable auto-summary for our
// case, so our auto-summary is empty.
-
return '';
}
if ( $blank ) {
// The current revision is blank and the one before is also
// blank. It's just not our lucky day
- $reason = wfMsgForContent( 'exbeforeblank', '$1' );
+ $reason = wfMessage( 'exbeforeblank', '$1' )->inContentLanguage()->text();
} else {
if ( $onlyAuthor ) {
- $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor );
+ $reason = wfMessage(
+ 'excontentauthor',
+ '$1',
+ $onlyAuthor
+ )->inContentLanguage()->text();
} else {
- $reason = wfMsgForContent( 'excontent', '$1' );
+ $reason = wfMessage( 'excontent', '$1' )->inContentLanguage()->text();
}
}
*
* - articleUrl Equivalent to $wgArticlePath, e.g. http://en.wikipedia.org/wiki/$1
* - fetchDescription Fetch the text of the remote file description page. Equivalent to
- * $wgFetchCommonsDescriptions.
+ * $wgFetchCommonsDescriptions.
+ * - abbrvThreshold File names over this size will use the short form of thumbnail names.
+ * Short thumbnail names only have the width, parameters, and the extension.
*
* ForeignDBRepo:
* - dbType, dbServer, dbUser, dbPassword, dbName, dbFlags
$wgCacheSharedUploads = true;
/**
- * Allow for upload to be copied from an URL. Requires Special:Upload?source=web
+ * Allow for upload to be copied from an URL.
* The timeout for copy uploads is set by $wgHTTPTimeout.
* You have to assign the user right 'upload_by_url' to a user group, to use this.
*/
/**
* A list of domains copy uploads can come from
+ *
+ * @since 1.20
*/
$wgCopyUploadsDomains = array();
/**
* Timezone to use in the error log.
- * Defaults to the wiki timezone ($wgLocalTimezone).
+ * Defaults to the wiki timezone ($wgLocaltimezone).
*
* A list of useable timezones can found at:
* http://php.net/manual/en/timezones.php
* which are used when parsing certain text and interface messages.
*
* For available types see $wgMainCacheType.
+ *
+ * @since 1.20
*/
$wgLanguageConverterCacheType = CACHE_ANYTHING;
* );
* @endcode
*
+ * @since 1.20
+ *
* @see $wgHTCPMulticastTTL
*/
$wgHTCPMulticastRouting = array();
*/
$wgEditPageFrameOptions = 'DENY';
+/**
+ * Disallow framing of API pages directly, by setting the X-Frame-Options
+ * header. Since the API returns CSRF tokens, allowing the results to be
+ * framed can compromise your user's account security.
+ * Options are:
+ * - 'DENY': Do not allow framing. This is recommended for most wikis.
+ * - 'SAMEORIGIN': Allow framing by pages on the same domain.
+ * - false: Allow all framing.
+ */
+
+$wgApiFrameOptions = 'DENY';
+
/**
* Disable output compression (enabled by default if zlib is available)
*/
* The $wgShowRollbackEditCount variable is used to show how many edits will be
* rollback. The numeric value of the varible are the limit up to are counted.
* If the value is false or 0, the edits are not counted.
+ *
+ * @since 1.20
*/
$wgShowRollbackEditCount = 10;
/**
* Extensive database transaction state debugging
+ *
+ * @since 1.20
*/
$wgDebugDBTransactions = false;
* The value is the replacement for the key (it can contain $1, etc.)
* %h will be replaced by the short SHA-1 (7 first chars) and %H by the
* full SHA-1 of the HEAD revision.
+ *
+ * @since 1.20
*/
$wgGitRepositoryViewers = array(
'https://gerrit.wikimedia.org/r/p/(.*)' => 'https://gerrit.wikimedia.org/r/gitweb?p=$1;h=%H',
*/
$wgDisabledActions = array();
-/**
- * Allow the "info" action, very inefficient at the moment
- */
-$wgAllowPageInfo = false;
-
/** @} */ # end actions }
/*************************************************************************//**
/**
* Whether the user must enter their password to change their e-mail address
+ *
+ * @since 1.20
*/
$wgRequirePasswordforEmailChange = true;
$wgOut->addHTML( $this->editFormTextAfterContent );
- $wgOut->addWikiText( $this->getCopywarn() );
-
- $wgOut->addHTML( $this->editFormTextAfterWarn );
-
$this->showStandardInputs();
$this->showFormAfterText();
$checkboxes = $this->getCheckboxes( $tabindex,
array( 'minor' => $this->minoredit, 'watch' => $this->watchthis ) );
$wgOut->addHTML( "<div class='editCheckboxes'>" . implode( $checkboxes, "\n" ) . "</div>\n" );
+
+ // Show copyright warning.
+ $wgOut->addWikiText( $this->getCopywarn() );
+ $wgOut->addHTML( $this->editFormTextAfterWarn );
+
$wgOut->addHTML( "<div class='editButtons'>\n" );
$wgOut->addHTML( implode( $this->getEditButtons( $tabindex ), "\n" ) . "\n" );
$edithelp = '<a target="helpwindow" href="' . $edithelpurl . '">' .
wfMessage( 'edithelp' )->escaped() . '</a> ' .
wfMessage( 'newwindow' )->escaped();
- $wgOut->addHTML( " <span class='editHelp'>{$cancel}{$edithelp}</span>\n" );
+ $wgOut->addHTML( " <span class='cancelLink'>{$cancel}</span>\n" );
+ $wgOut->addHTML( " <span class='editHelp'>{$edithelp}</span>\n" );
$wgOut->addHTML( "</div><!-- editButtons -->\n</div><!-- editOptions -->\n" );
}
* @return Array: bits of the URL in an associative array, per PHP docs
*/
function wfParseUrl( $url ) {
- $obj = new Uri( $url );
- return $obj->getComponents();
+ global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
+
+ // Protocol-relative URLs are handled really badly by parse_url(). It's so bad that the easiest
+ // way to handle them is to just prepend 'http:' and strip the protocol out later
+ $wasRelative = substr( $url, 0, 2 ) == '//';
+ if ( $wasRelative ) {
+ $url = "http:$url";
+ }
+ wfSuppressWarnings();
+ $bits = parse_url( $url );
+ wfRestoreWarnings();
+ // parse_url() returns an array without scheme for some invalid URLs, e.g.
+ // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' )
+ if ( !$bits || !isset( $bits['scheme'] ) ) {
+ return false;
+ }
+
+ // parse_url() incorrectly handles schemes case-sensitively. Convert it to lowercase.
+ $bits['scheme'] = strtolower( $bits['scheme'] );
+
+ // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it
+ if ( in_array( $bits['scheme'] . '://', $wgUrlProtocols ) ) {
+ $bits['delimiter'] = '://';
+ } elseif ( in_array( $bits['scheme'] . ':', $wgUrlProtocols ) ) {
+ $bits['delimiter'] = ':';
+ // parse_url detects for news: and mailto: the host part of an url as path
+ // We have to correct this wrong detection
+ if ( isset( $bits['path'] ) ) {
+ $bits['host'] = $bits['path'];
+ $bits['path'] = '';
+ }
+ } else {
+ return false;
+ }
+
+ /* Provide an empty host for eg. file:/// urls (see bug 28627) */
+ if ( !isset( $bits['host'] ) ) {
+ $bits['host'] = '';
+
+ /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
+ if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
+ $bits['path'] = '/' . $bits['path'];
+ }
+ }
+
+ // If the URL was protocol-relative, fix scheme and delimiter
+ if ( $wasRelative ) {
+ $bits['scheme'] = '';
+ $bits['delimiter'] = '//';
+ }
+ return $bits;
}
/**
* wfGetCaller( 3 ) is the parent of that.
*
* @param $level Int
- * @return Bool|string
+ * @return string
*/
function wfGetCaller( $level = 2 ) {
$backtrace = wfDebugBacktrace( $level + 1 );
if ( isset( $backtrace[$level] ) ) {
return wfFormatStackFrame( $backtrace[$level] );
} else {
- $caller = 'unknown';
+ return 'unknown';
}
- return $caller;
}
/**
* Return a string representation of frame
*
* @param $frame Array
- * @return Bool
+ * @return string
*/
function wfFormatStackFrame( $frame ) {
return isset( $frame['class'] ) ?
/**
* Get a timestamp string in one of various formats
*
+ * @deprecated
* @param $outputtype Mixed: A timestamp in one of the supported formats, the
* function will autodetect which format is supplied and act
* accordingly.
* @return Mixed: String / false The same date in the format specified in $outputtype or false
*/
function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
- $uts = 0;
- $da = array();
- $strtime = '';
-
- if ( !$ts ) { // We want to catch 0, '', null... but not date strings starting with a letter.
- $uts = time();
- $strtime = "@$uts";
- } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/D', $ts, $da ) ) {
- # TS_DB
- } elseif ( preg_match( '/^(\d{4}):(\d\d):(\d\d) (\d\d):(\d\d):(\d\d)$/D', $ts, $da ) ) {
- # TS_EXIF
- } elseif ( preg_match( '/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/D', $ts, $da ) ) {
- # TS_MW
- } elseif ( preg_match( '/^-?\d{1,13}$/D', $ts ) ) {
- # TS_UNIX
- $uts = $ts;
- $strtime = "@$ts"; // http://php.net/manual/en/datetime.formats.compound.php
- } elseif ( preg_match( '/^\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}.\d{6}$/', $ts ) ) {
- # TS_ORACLE // session altered to DD-MM-YYYY HH24:MI:SS.FF6
- $strtime = preg_replace( '/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3",
- str_replace( '+00:00', 'UTC', $ts ) );
- } elseif ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
- # TS_ISO_8601
- } elseif ( preg_match( '/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
- #TS_ISO_8601_BASIC
- } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d*[\+\- ](\d\d)$/', $ts, $da ) ) {
- # TS_POSTGRES
- } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d* GMT$/', $ts, $da ) ) {
- # TS_POSTGRES
- } elseif (preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.\d\d\d$/', $ts, $da ) ) {
- # TS_DB2
- } elseif ( preg_match( '/^[ \t\r\n]*([A-Z][a-z]{2},[ \t\r\n]*)?' . # Day of week
- '\d\d?[ \t\r\n]*[A-Z][a-z]{2}[ \t\r\n]*\d{2}(?:\d{2})?' . # dd Mon yyyy
- '[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d/S', $ts ) ) { # hh:mm:ss
- # TS_RFC2822, accepting a trailing comment. See http://www.squid-cache.org/mail-archive/squid-users/200307/0122.html / r77171
- # The regex is a superset of rfc2822 for readability
- $strtime = strtok( $ts, ';' );
- } elseif ( preg_match( '/^[A-Z][a-z]{5,8}, \d\d-[A-Z][a-z]{2}-\d{2} \d\d:\d\d:\d\d/', $ts ) ) {
- # TS_RFC850
- $strtime = $ts;
- } elseif ( preg_match( '/^[A-Z][a-z]{2} [A-Z][a-z]{2} +\d{1,2} \d\d:\d\d:\d\d \d{4}/', $ts ) ) {
- # asctime
- $strtime = $ts;
- } else {
- # Bogus value...
- wfDebug("wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts\n");
-
- return false;
- }
-
- static $formats = array(
- TS_UNIX => 'U',
- TS_MW => 'YmdHis',
- TS_DB => 'Y-m-d H:i:s',
- TS_ISO_8601 => 'Y-m-d\TH:i:s\Z',
- TS_ISO_8601_BASIC => 'Ymd\THis\Z',
- TS_EXIF => 'Y:m:d H:i:s', // This shouldn't ever be used, but is included for completeness
- TS_RFC2822 => 'D, d M Y H:i:s',
- TS_ORACLE => 'd-m-Y H:i:s.000000', // Was 'd-M-y h.i.s A' . ' +00:00' before r51500
- TS_POSTGRES => 'Y-m-d H:i:s',
- TS_DB2 => 'Y-m-d H:i:s',
- );
-
- if ( !isset( $formats[$outputtype] ) ) {
- throw new MWException( 'wfTimestamp() called with illegal output type.' );
- }
-
- if ( function_exists( "date_create" ) ) {
- if ( count( $da ) ) {
- $ds = sprintf("%04d-%02d-%02dT%02d:%02d:%02d.00+00:00",
- (int)$da[1], (int)$da[2], (int)$da[3],
- (int)$da[4], (int)$da[5], (int)$da[6]);
-
- $d = date_create( $ds, new DateTimeZone( 'GMT' ) );
- } elseif ( $strtime ) {
- $d = date_create( $strtime, new DateTimeZone( 'GMT' ) );
- } else {
- return false;
- }
-
- if ( !$d ) {
- wfDebug("wfTimestamp() fed bogus time value: $outputtype; $ts\n");
- return false;
- }
-
- $output = $d->format( $formats[$outputtype] );
- } else {
- if ( count( $da ) ) {
- // Warning! gmmktime() acts oddly if the month or day is set to 0
- // We may want to handle that explicitly at some point
- $uts = gmmktime( (int)$da[4], (int)$da[5], (int)$da[6],
- (int)$da[2], (int)$da[3], (int)$da[1] );
- } elseif ( $strtime ) {
- $uts = strtotime( $strtime );
- }
-
- if ( $uts === false ) {
- wfDebug("wfTimestamp() can't parse the timestamp (non 32-bit time? Update php): $outputtype; $ts\n");
- return false;
- }
-
- if ( TS_UNIX == $outputtype ) {
- return $uts;
- }
- $output = gmdate( $formats[$outputtype], $uts );
- }
-
- if ( ( $outputtype == TS_RFC2822 ) || ( $outputtype == TS_POSTGRES ) ) {
- $output .= ' GMT';
- }
-
- return $output;
+ $timestamp = new MWTimestamp( $ts );
+ return $timestamp->getTimestamp( $outputtype );
}
/**
foreach ( $attribs as $attrib => $value ) {
$lcattrib = strtolower( $attrib );
- $value = strval( $value );
+ if( is_array( $value ) ) {
+ $value = implode( ' ', $value );
+ } else {
+ $value = strval( $value );
+ }
# Simple checks using $attribDefaults
if ( isset( $attribDefaults[$element][$lcattrib] ) &&
if ( $this->mPage->getID() ) {
# NS_FILE is in the user language, but this section (the actual wikitext)
# should be in page content language
- $pageLang = $this->getTitle()->getPageLanguage();
+ $pageLang = $this->getTitle()->getPageViewLanguage();
$out->addHTML( Xml::openElement( 'div', array( 'id' => 'mw-imagepage-content',
'lang' => $pageLang->getHtmlCode(), 'dir' => $pageLang->getDir(),
'class' => 'mw-content-'.$pageLang->getDir() ) ) );
* Make a "broken" link to an image
*
* @param $title Title object
- * @param $html String: link label in htmlescaped text form
+ * @param $label String: link label (plain text)
* @param $query String: query string
- * @param $trail String: link trail (HTML fragment)
- * @param $prefix String: link prefix (HTML fragment)
+ * @param $unused1 Unused parameter kept for b/c
+ * @param $unused2 Unused parameter kept for b/c
* @param $time Boolean: a file of a certain timestamp was requested
* @return String
*/
- public static function makeBrokenImageLinkObj( $title, $html = '', $query = '', $trail = '', $prefix = '', $time = false ) {
+ public static function makeBrokenImageLinkObj( $title, $label = '', $query = '', $unused1 = '', $unused2 = '', $time = false ) {
global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
if ( ! $title instanceof Title ) {
- return "<!-- ERROR -->{$prefix}{$html}{$trail}";
+ return "<!-- ERROR -->" . htmlspecialchars( $label );
}
wfProfileIn( __METHOD__ );
+ if ( $label == '' ) {
+ $label = $title->getPrefixedText();
+ }
+ $encLabel = htmlspecialchars( $label );
$currentExists = $time ? ( wfFindFile( $title ) != false ) : false;
- list( $inside, $trail ) = self::splitTrail( $trail );
- if ( $html == '' )
- $html = htmlspecialchars( $title->getPrefixedText() );
-
if ( ( $wgUploadMissingFileUrl || $wgUploadNavigationUrl || $wgEnableUploads ) && !$currentExists ) {
$redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title );
if ( $redir ) {
wfProfileOut( __METHOD__ );
- return self::linkKnown( $title, "$prefix$html$inside", array(), wfCgiToArray( $query ) ) . $trail;
+ return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
}
$href = self::getUploadUrl( $title, $query );
wfProfileOut( __METHOD__ );
return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' .
htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' .
- "$prefix$html$inside</a>$trail";
+ $encLabel . '</a>';
} else {
wfProfileOut( __METHOD__ );
- return self::linkKnown( $title, "$prefix$html$inside", array(), wfCgiToArray( $query ) ) . $trail;
+ return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
}
}
* @param $recursive Boolean: queue jobs for recursive updates?
*/
function __construct( $title, $parserOutput, $recursive = true ) {
- parent::__construct( );
+ parent::__construct( false ); // no implicit transaction
if ( !( $title instanceof Title ) ) {
throw new MWException( "The calling convention to LinksUpdate::LinksUpdate() has changed. " .
* @param $page WikiPage Page we are updating
*/
function __construct( Title $title ) {
- parent::__construct( );
+ parent::__construct( false ); // no implicit transaction
$this->mTitle = $title;
'dateFormats', 'datePreferences', 'datePreferenceMigrationMap',
'defaultDateFormat', 'extraUserToggles', 'specialPageAliases',
'imageFiles', 'preloadedMessages', 'namespaceGenderAliases',
- 'digitGroupingPattern', 'pluralRules'
+ 'digitGroupingPattern', 'pluralRules', 'compiledPluralRules',
);
/**
* by a fallback sequence.
*/
static public $mergeableMapKeys = array( 'messages', 'namespaceNames',
- 'dateFormats', 'imageFiles', 'preloadedMessages', 'pluralRules'
+ 'dateFormats', 'imageFiles', 'preloadedMessages'
);
/**
*/
public function getCompiledPluralRules( $code ) {
$rules = $this->getPluralRules( $code );
+ if ( $rules === null ) {
+ return null;
+ }
try {
$compiledRules = CLDRPluralRuleEvaluator::compile( $rules );
} catch( CLDRPluralRuleError $e ) {
}
}
if ( !isset( $this->pluralRules[$code] ) ) {
- return array();
+ return null;
} else {
return $this->pluralRules[$code];
}
}
+
/**
* Load a plural XML file with the given filename, compile the relevant
* rules, and save the compiled rules in a process-local cache.
*/
- private function loadPluralFile( $fileName ) {
+ protected function loadPluralFile( $fileName ) {
$doc = new DOMDocument;
$doc->load( $fileName );
$rulesets = $doc->getElementsByTagName( "pluralRules" );
}
}
+ /**
+ * Read the data from the source files for a given language, and register
+ * the relevant dependencies in the $deps array. If the localisation
+ * exists, the data array is returned, otherwise false is returned.
+ */
+ protected function readSourceFilesAndRegisterDeps( $code, &$deps ) {
+ $fileName = Language::getMessagesFileName( $code );
+ if ( !file_exists( $fileName ) ) {
+ return false;
+ }
+
+ $deps[] = new FileDependency( $fileName );
+ $data = $this->readPHPFile( $fileName, 'core' );
+
+ # Load CLDR plural rules for JavaScript
+ $data['pluralRules'] = $this->getPluralRules( $code );
+ # And for PHP
+ $data['compiledPluralRules'] = $this->getCompiledPluralRules( $code );
+
+ $deps['plurals'] = new FileDependency( __DIR__ . "/../languages/data/plurals.xml" );
+ $deps['plurals-mw'] = new FileDependency( __DIR__ . "/../languages/data/plurals-mediawiki.xml" );
+ return $data;
+ }
+
/**
* Merge two localisation values, a primary and a fallback, overwriting the
* primary value in place.
$deps = array();
# Load the primary localisation from the source file
- $fileName = Language::getMessagesFileName( $code );
- if ( !file_exists( $fileName ) ) {
+ $data = $this->readSourceFilesAndRegisterDeps( $code, $deps );
+ if ( $data === false ) {
wfDebug( __METHOD__ . ": no localisation file for $code, using fallback to en\n" );
$coreData['fallback'] = 'en';
} else {
- $deps[] = new FileDependency( $fileName );
- $data = $this->readPHPFile( $fileName, 'core' );
wfDebug( __METHOD__ . ": got localisation for $code from source\n" );
# Merge primary localisation
foreach ( $coreData['fallbackSequence'] as $fbCode ) {
# Load the secondary localisation from the source file to
# avoid infinite cycles on cyclic fallbacks
- $fbFilename = Language::getMessagesFileName( $fbCode );
-
- if ( !file_exists( $fbFilename ) ) {
+ $fbData = $this->readSourceFilesAndRegisterDeps( $fbCode, $deps );
+ if ( $fbData === false ) {
continue;
}
- $deps[] = new FileDependency( $fbFilename );
- $fbData = $this->readPHPFile( $fbFilename, 'core' );
-
foreach ( self::$allKeys as $key ) {
if ( !isset( $fbData[$key] ) ) {
continue;
# Decouple the reference to prevent accidental damage
unset( $page );
+ # If there were no plural rules, return an empty array
+ if ( $allData['pluralRules'] === null ) {
+ $allData['pluralRules'] = array();
+ }
+ if ( $allData['compiledPluralRules'] === null ) {
+ $allData['compiledPluralRules'] = array();
+ }
+
# Set the list keys
$allData['list'] = array();
foreach ( self::$splitKeys as $key ) {
$allData['list'][$key] = array_keys( $allData[$key] );
}
- # Load CLDR plural rules for JavaScript
- $allData['pluralRules'] = $this->getPluralRules( $code );
- # And for PHP
- $allData['compiledPluralRules'] = $this->getCompiledPluralRules( $code );
# Run hooks
wfRunHooks( 'LocalisationCacheRecache', array( $this, $code, &$allData ) );
*/
private static function reencodeBlob( $blob, $key, $lang ) {
$decoded = FormatJson::decode( $blob, true );
- $decoded[$key] = wfMessage( $key )->inLanguage( $lang )->text();
+ $decoded[$key] = wfMessage( $key )->inLanguage( $lang )->plain();
return FormatJson::encode( (object)$decoded );
}
$messages = array();
foreach ( $module->getMessages() as $key ) {
- $messages[$key] = wfMessage( $key )->inLanguage( $lang )->text();
+ $messages[$key] = wfMessage( $key )->inLanguage( $lang )->plain();
}
return FormatJson::encode( (object)$messages );
* message names, or arrays, in which case the first element is the message name,
* and subsequent elements are the parameters to that message.
*
- * The special named parameter 'options' in a message specification array is passed
- * through to the $options parameter of wfMsgExt().
- *
* Don't use this for messages that are not in users interface language.
*
* For example:
$args = $spec;
$name = array_shift( $args );
if ( isset( $args['options'] ) ) {
- $options = $args['options'];
unset( $args['options'] );
+ wfDeprecated(
+ 'Adding "options" to ' . __METHOD__ . ' is no longer supported',
+ '1.20'
+ );
}
} else {
$args = array();
$name = $spec;
}
- $s = str_replace( '$' . ( $n + 1 ), wfMsgExt( $name, $options, $args ), $s );
+ $s = str_replace( '$' . ( $n + 1 ), $this->msg( $name, $args )->plain(), $s );
}
$this->addWikiText( $s );
}
# Stupid hack
$encValue = preg_replace_callback(
- '/(' . wfUrlProtocols() . ')/',
+ '/((?i)' . wfUrlProtocols() . ')/',
array( 'Sanitizer', 'armorLinksCallback' ),
$encValue );
return $encValue;
foreach( $wgDisabledActions as $action ){
$wgActions[$action] = false;
}
-if( !$wgAllowPageInfo ){
- $wgActions['info'] = false;
-}
if ( !$wgHtml5Version && $wgHtml5 && $wgAllowRdfaAttributes ) {
# see http://www.w3.org/TR/rdfa-in-html/#document-conformance
* @return String URL
*/
static function makeInternalOrExternalUrl( $name ) {
- if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $name ) ) {
+ if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $name ) ) {
return $name;
} else {
return self::makeUrl( $name );
$text = $line[1];
}
- if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $link ) ) {
+ if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $link ) ) {
$href = $link;
// Parser::getExternalLinkAttribs won't work here because of the Namespace things
if ( !in_array( $title->getNamespace(), array( NS_SPECIAL, NS_FILE ) ) &&
in_array( $request->getVal( 'action', 'view' ), array( 'view', 'historysubmit' ) ) &&
( $title->exists() || $title->getNamespace() == NS_MEDIAWIKI ) ) {
- $pageLang = $title->getPageLanguage();
+ $pageLang = $title->getPageViewLanguage();
$realBodyAttribs['lang'] = $pageLang->getHtmlCode();
$realBodyAttribs['dir'] = $pageLang->getDir();
$realBodyAttribs['class'] = 'mw-content-'.$pageLang->getDir();
protected $mOptions; //!< SELECT options to be used (array)
private $mHasTransaction; //!< bool whether a transaction is open on this object (internal use only!)
+ protected $mUseTransaction; //!< bool whether this update should be wrapped in a transaction
/**
* Constructor
- **/
- public function __construct( ) {
+ *
+ * @param bool $withTransaction whether this update should be wrapped in a transaction (default: true).
+ * A transaction is only started if no transaction is already in progress,
+ * see beginTransaction() for details.
+ **/
+ public function __construct( $withTransaction = true ) {
global $wgAntiLockFlags;
parent::__construct( );
$this->mOptions = array( 'FOR UPDATE' );
}
+ // @todo: get connection only when it's needed? make sure that doesn't break anything, especially transactions!
+ $this->mDb = wfGetDB( DB_MASTER );
+
+ $this->mWithTransaction = $withTransaction;
$this->mHasTransaction = false;
}
/**
- * Begin a database transaction.
+ * Begin a database transaction, if $withTransaction was given as true in the constructor for this SqlDataUpdate.
*
- * Because nested transactions are not supportred by the Database class, this implementation
- * checkes Database::trxLevel() and only opens a transaction if none is yet active.
+ * Because nested transactions are not supported by the Database class, this implementation
+ * checks Database::trxLevel() and only opens a transaction if none is already active.
*/
public function beginTransaction() {
- $this->mDb = wfGetDB( DB_MASTER );
+ if ( !$this->mWithTransaction ) {
+ return;
+ }
// NOTE: nested transactions are not supported, only start a transaction if none is open
if ( $this->mDb->trxLevel() === 0 ) {
public function commitTransaction() {
if ( $this->mHasTransaction ) {
$this->mDb->commit( get_class( $this ) . '::commitTransaction' );
+ $this->mHasTransaction = false;
}
}
public function abortTransaction() {
if ( $this->mHasTransaction ) { //XXX: actually... maybe always?
$this->mDb->rollback( get_class( $this ) . '::abortTransaction' );
+ $this->mHasTransaction = false;
}
}
public static function prepareForStream(
$path, $info, $headers = array(), $sendErrors = true
) {
- global $wgLanguageCode;
-
if ( !is_array( $info ) ) {
if ( $sendErrors ) {
header( 'HTTP/1.0 404 Not Found' );
return false;
}
- header( "Content-Disposition: inline;filename*=utf-8'$wgLanguageCode'" .
- urlencode( basename( $path ) ) );
-
// Send additional headers
foreach ( $headers as $header ) {
header( $header );
--- /dev/null
+<?php
+/**
+ * Creation and parsing of MW-style timestamps.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.20
+ * @author Tyler Romeo, 2012
+ */
+
+/**
+ * Library for creating and parsing MW-style timestamps. Based on the JS
+ * library that does the same thing.
+ *
+ * @since 1.20
+ */
+class MWTimestamp {
+ /**
+ * Standard gmdate() formats for the different timestamp types.
+ */
+ private static $formats = array(
+ TS_UNIX => 'U',
+ TS_MW => 'YmdHis',
+ TS_DB => 'Y-m-d H:i:s',
+ TS_ISO_8601 => 'Y-m-d\TH:i:s\Z',
+ TS_ISO_8601_BASIC => 'Ymd\THis\Z',
+ TS_EXIF => 'Y:m:d H:i:s', // This shouldn't ever be used, but is included for completeness
+ TS_RFC2822 => 'D, d M Y H:i:s',
+ TS_ORACLE => 'd-m-Y H:i:s.000000', // Was 'd-M-y h.i.s A' . ' +00:00' before r51500
+ TS_POSTGRES => 'Y-m-d H:i:s',
+ TS_DB2 => 'Y-m-d H:i:s',
+ );
+
+ /**
+ * Different units for human readable timestamps.
+ * @see MWTimestamp::getHumanTimestamp
+ */
+ private static $units = array(
+ "milliseconds" => 1,
+ "seconds" => 1000, // 1000 milliseconds per second
+ "minutes" => 60, // 60 seconds per minute
+ "hours" => 60, // 60 minutes per hour
+ "days" => 24 // 24 hours per day
+ );
+
+ /**
+ * The actual timestamp being wrapped. Either a DateTime
+ * object or a string with a Unix timestamp depending on
+ * PHP.
+ */
+ private $timestamp;
+
+ /**
+ * Make a new timestamp and set it to the specified time,
+ * or the current time if unspecified.
+ *
+ * @param $timestamp Timestamp to set, or false for current time
+ */
+ public function __construct( $timestamp = false ) {
+ $this->setTimestamp( $timestamp );
+ }
+
+ /**
+ * Set the timestamp to the specified time, or the current time if unspecified.
+ *
+ * Parse the given timestamp into either a DateTime object or a Unix teimstamp,
+ * and then store it.
+ *
+ * @param $ts Timestamp to store, or false for now
+ */
+ public function setTimestamp( $ts = false ) {
+ $uts = 0;
+ $da = array();
+ $strtime = '';
+
+ if ( !$ts ) { // We want to catch 0, '', null... but not date strings starting with a letter.
+ $uts = time();
+ $strtime = "@$uts";
+ } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/D', $ts, $da ) ) {
+ # TS_DB
+ } elseif ( preg_match( '/^(\d{4}):(\d\d):(\d\d) (\d\d):(\d\d):(\d\d)$/D', $ts, $da ) ) {
+ # TS_EXIF
+ } elseif ( preg_match( '/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/D', $ts, $da ) ) {
+ # TS_MW
+ } elseif ( preg_match( '/^-?\d{1,13}$/D', $ts ) ) {
+ # TS_UNIX
+ $uts = $ts;
+ $strtime = "@$ts"; // http://php.net/manual/en/datetime.formats.compound.php
+ } elseif ( preg_match( '/^\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}.\d{6}$/', $ts ) ) {
+ # TS_ORACLE // session altered to DD-MM-YYYY HH24:MI:SS.FF6
+ $strtime = preg_replace( '/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3",
+ str_replace( '+00:00', 'UTC', $ts ) );
+ } elseif ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
+ # TS_ISO_8601
+ } elseif ( preg_match( '/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
+ #TS_ISO_8601_BASIC
+ } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d*[\+\- ](\d\d)$/', $ts, $da ) ) {
+ # TS_POSTGRES
+ } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d* GMT$/', $ts, $da ) ) {
+ # TS_POSTGRES
+ } elseif (preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.\d\d\d$/', $ts, $da ) ) {
+ # TS_DB2
+ } elseif ( preg_match( '/^[ \t\r\n]*([A-Z][a-z]{2},[ \t\r\n]*)?' . # Day of week
+ '\d\d?[ \t\r\n]*[A-Z][a-z]{2}[ \t\r\n]*\d{2}(?:\d{2})?' . # dd Mon yyyy
+ '[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d/S', $ts ) ) { # hh:mm:ss
+ # TS_RFC2822, accepting a trailing comment. See http://www.squid-cache.org/mail-archive/squid-users/200307/0122.html / r77171
+ # The regex is a superset of rfc2822 for readability
+ $strtime = strtok( $ts, ';' );
+ } elseif ( preg_match( '/^[A-Z][a-z]{5,8}, \d\d-[A-Z][a-z]{2}-\d{2} \d\d:\d\d:\d\d/', $ts ) ) {
+ # TS_RFC850
+ $strtime = $ts;
+ } elseif ( preg_match( '/^[A-Z][a-z]{2} [A-Z][a-z]{2} +\d{1,2} \d\d:\d\d:\d\d \d{4}/', $ts ) ) {
+ # asctime
+ $strtime = $ts;
+ } else {
+ throw new TimestampException( __METHOD__ . " : Invalid timestamp - $ts" );
+ }
+
+ if( !$strtime ) {
+ $da = array_map( 'intval', $da );
+ $da[0] = "%04d-%02d-%02dT%02d:%02d:%02d.00+00:00";
+ $strtime = call_user_func_array( "sprintf", $da );
+ }
+
+ if( function_exists( "date_create" ) ) {
+ try {
+ $final = new DateTime( $strtime, new DateTimeZone( 'GMT' ) );
+ } catch(Exception $e) {
+ throw new TimestampException( __METHOD__ . 'Invalid timestamp format.' );
+ }
+ } else {
+ $final = strtotime( $strtime );
+ }
+
+ if( $final === false ) {
+ throw new TimestampException( __METHOD__ . 'Invalid timestamp format.' );
+ }
+ $this->timestamp = $final;
+ }
+
+ /**
+ * Get the timestamp represented by this object in a certain form.
+ *
+ * Convert the internal timestamp to the specified format and then
+ * return it.
+ *
+ * @param $style Output format for timestamp
+ * @return string The formatted timestamp
+ */
+ public function getTimestamp( $style = TS_UNIX ) {
+ if( !isset( self::$formats[$style] ) ) {
+ throw new TimestampException( __METHOD__ . ' : Illegal timestamp output type.' );
+ }
+
+ if( is_object( $this->timestamp ) ) {
+ // DateTime object was used, call DateTime::format.
+ $output = $this->timestamp->format( self::$formats[$style] );
+ } elseif( TS_UNIX == $style ) {
+ // Unix timestamp was used and is wanted, just return it.
+ $output = $this->timestamp;
+ } else {
+ // Unix timestamp was used, use gmdate().
+ $output = gmdate( self::$formats[$style], $this->timestamp );
+ }
+
+ if ( ( $style == TS_RFC2822 ) || ( $style == TS_POSTGRES ) ) {
+ $output .= ' GMT';
+ }
+
+ return $output;
+ }
+
+ /**
+ * Get the timestamp in a human-friendly relative format, e.g., "3 days ago".
+ *
+ * Determine the difference between the timestamp and the current time, and
+ * generate a readable timestamp by returning "<N> <units> ago", where the
+ * largest possible unit is used.
+ *
+ * @return string Formatted timestamp
+ */
+ public function getHumanTimestamp() {
+ $then = $this->getTimestamp( TS_UNIX );
+ $now = time();
+ $timeago = ($now - $then) * 1000;
+ $message = false;
+
+ foreach( self::$units as $unit => $factor ) {
+ $next = $timeago / $factor;
+ if( $next < 1 ) {
+ break;
+ } else {
+ $timeago = $next;
+ $message = array( $unit, floor( $timeago ) );
+ }
+ }
+
+ if( $message ) {
+ $initial = call_user_func_array( 'wfMessage', $message );
+ return wfMessage( 'ago', $initial );
+ } else {
+ return wfMessage( 'just-now' );
+ }
+ }
+
+ public function __toString() {
+ return $this->getTimestamp();
+ }
+}
+
+class TimestampException extends MWException {}
* @return Title the new object
*/
public static function newMainPage() {
- $title = Title::newFromText( wfMsgForContent( 'mainpage' ) );
+ $title = Title::newFromText( wfMessage( 'mainpage' )->inContentLanguage()->text() );
// Don't give fatal errors if the message is broken
if ( !$title ) {
$title = Title::newFromText( 'Main Page' );
* queries by skipping checks for cascading protections and user blocks.
* @param $ignoreErrors Array of Strings Set this to a list of message keys
* whose corresponding errors may be ignored.
- * @return Array of arguments to wfMsg to explain permissions problems.
+ * @return Array of arguments to wfMessage to explain permissions problems.
*/
public function getUserPermissionsErrors( $action, $user, $doExpensiveQueries = true, $ignoreErrors = array() ) {
$errors = $this->getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries );
# Check $wgNamespaceProtection for restricted namespaces
if ( $this->isNamespaceProtected( $user ) ) {
$ns = $this->mNamespace == NS_MAIN ?
- wfMsg( 'nstab-main' ) : $this->getNsText();
+ wfMessage( 'nstab-main' )->text() : $this->getNsText();
$errors[] = $this->mNamespace == NS_MEDIAWIKI ?
array( 'protectedinterface' ) : array( 'namespaceprotected', $ns );
}
$id = $user->blockedBy();
$reason = $user->blockedFor();
if ( $reason == '' ) {
- $reason = wfMsg( 'blockednoreason' );
+ $reason = wfMessage( 'blockednoreason' )->text();
}
$ip = $user->getRequest()->getIP();
* @param $user User to check
* @param $doExpensiveQueries Bool Set this to false to avoid doing unnecessary queries.
* @param $short Bool Set this to true to stop after the first permission error.
- * @return Array of arrays of the arguments to wfMsg to explain permissions problems.
+ * @return Array of arrays of the arguments to wfMessage to explain permissions problems.
*/
protected function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries = true, $short = false ) {
wfProfileIn( __METHOD__ );
);
# Update the protection log
$log = new LogPage( 'protect' );
- $comment = wfMsgForContent( 'prot_1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() );
+ $comment = wfMessage(
+ 'prot_1movedto2',
+ $this->getPrefixedText(),
+ $nt->getPrefixedText()
+ )->inContentLanguage()->text();
if ( $reason ) {
- $comment .= wfMsgForContent( 'colon-separator' ) . $reason;
+ $comment .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . $reason;
}
// @todo FIXME: $params?
$log->addEntry( 'move_prot', $nt, $comment, array( $this->getPrefixedText() ) );
$formatter->setContext( RequestContext::newExtraneousContext( $this ) );
$comment = $formatter->getPlainActionText();
if ( $reason ) {
- $comment .= wfMsgForContent( 'colon-separator' ) . $reason;
+ $comment .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . $reason;
}
# Truncate for whole multibyte characters.
$comment = $wgContLang->truncate( $comment, 255 );
return false;
}
# Get the article text
- $rev = Revision::newFromTitle( $nt );
+ $rev = Revision::newFromTitle( $nt, false, Revision::READ_LATEST );
if( !is_object( $rev ) ){
return false;
}
if ( in_array( 'include_old', $options ) ) {
$old_cmp = '>=';
}
- if ( in_array( 'include_new', $options ) ) {\r
- $new_cmp = '<=';\r
- }\r
- if ( in_array( 'include_both', $options ) ) {\r
- $old_cmp = '>=';\r
+ if ( in_array( 'include_new', $options ) ) {
+ $new_cmp = '<=';
+ }
+ if ( in_array( 'include_both', $options ) ) {
+ $old_cmp = '>=';
$new_cmp = '<=';
}
// No DB query needed if $old and $new are the same or successive revisions:
return ( $old_cmp === '>' && $new_cmp === '<' ) ? 0 : 1;
}
return ( $old->getRawUserText() === $new->getRawUserText() ) ? 1 : 2;
- }\r
+ }
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( 'revision', 'DISTINCT rev_user_text',
array(
}
/**
- * Get the language in which the content of this page is written.
- * Defaults to $wgContLang, but in certain cases it can be e.g.
- * $wgLang (such as special pages, which are in the user language).
+ * Get the language in which the content of this page is written in
+ * wikitext. Defaults to $wgContLang, but in certain cases it can be
+ * e.g. $wgLang (such as special pages, which are in the user language).
*
* @since 1.18
* @return Language
wfRunHooks( 'PageContentLanguage', array( $this, &$pageLang, $wgLang ) );
return wfGetLangObj( $pageLang );
}
+
+ /**
+ * Get the language in which the content of this page is written when
+ * viewed by user. Defaults to $wgContLang, but in certain cases it can be
+ * e.g. $wgLang (such as special pages, which are in the user language).
+ *
+ * @since 1.20
+ * @return Language
+ */
+ public function getPageViewLanguage() {
+ $pageLang = $this->getPageLanguage();
+ // If this is nothing special (so the content is converted when viewed)
+ if ( !$this->isSpecialPage()
+ && !$this->isCssOrJsPage() && !$this->isCssJsSubpage()
+ && $this->getNamespace() !== NS_MEDIAWIKI
+ ) {
+ // If the user chooses a variant, the content is actually
+ // in a language whose code is the variant code.
+ $variant = $pageLang->getPreferredVariant();
+ if ( $pageLang->getCode() !== $variant ) {
+ $pageLang = Language::factory( $variant );
+ }
+ }
+ return $pageLang;
+ }
}
// Certain names may be reserved for batch processes.
foreach ( $reservedUsernames as $reserved ) {
if ( substr( $reserved, 0, 4 ) == 'msg:' ) {
- $reserved = wfMsgForContent( substr( $reserved, 4 ) );
+ $reserved = wfMessage( substr( $reserved, 4 ) )->inContentLanguage()->text();
}
if ( $reserved == $name ) {
return false;
# Local list
if ( self::isLocallyBlockedProxy( $ip ) ) {
$block = new Block;
- $block->setBlocker( wfMsg( 'proxyblocker' ) );
- $block->mReason = wfMsg( 'proxyblockreason' );
+ $block->setBlocker( wfMessage( 'proxyblocker' )->text() );
+ $block->mReason = wfMessage( 'proxyblockreason' )->text();
$block->setTarget( $ip );
} elseif ( $this->isAnon() && $this->isDnsBlacklisted( $ip ) ) {
$block = new Block;
- $block->setBlocker( wfMsg( 'sorbs' ) );
- $block->mReason = wfMsg( 'sorbsreason' );
+ $block->setBlocker( wfMessage( 'sorbs' )->text() );
+ $block->mReason = wfMessage( 'sorbsreason' )->text();
$block->setTarget( $ip );
}
}
if( $str !== null ) {
if( !$wgAuth->allowPasswordChange() ) {
- throw new PasswordError( wfMsg( 'password-change-forbidden' ) );
+ throw new PasswordError( wfMessage( 'password-change-forbidden' )->text() );
}
if( !$this->isValidPassword( $str ) ) {
$message = $valid;
$params = array( $wgMinimalPasswordLength );
}
- throw new PasswordError( wfMsgExt( $message, array( 'parsemag' ), $params ) );
+ throw new PasswordError( wfMessage( $message, $params )->text() );
}
}
if( !$wgAuth->setPassword( $this, $str ) ) {
- throw new PasswordError( wfMsg( 'externaldberror' ) );
+ throw new PasswordError( wfMessage( 'externaldberror' )->text() );
}
$this->setInternalPassword( $str );
* @todo Only rarely do all these fields need to be set!
*/
public function saveSettings() {
+ global $wgAuth;
+
$this->load();
if ( wfReadOnly() ) { return; }
if ( 0 == $this->mId ) { return; }
$this->mTouched = self::newTouchedTimestamp();
+ if ( !$wgAuth->allowSetLocalPassword() ) {
+ $this->mPassword = '';
+ }
$dbw = wfGetDB( DB_MASTER );
$dbw->update( 'user',
$message = 'confirmemail_body_' . $type;
}
- return $this->sendMail( wfMsg( 'confirmemail_subject' ),
- wfMsg( $message,
+ return $this->sendMail( wfMessage( 'confirmemail_subject' )->text(),
+ wfMessage( $message,
$this->getRequest()->getIP(),
$this->getName(),
$url,
$wgLang->timeanddate( $expiration, false ),
$invalidateURL,
$wgLang->date( $expiration, false ),
- $wgLang->time( $expiration, false ) ) );
+ $wgLang->time( $expiration, false ) )->text() );
}
/**
$action = 'create2';
if ( $byEmail ) {
if ( $reason === '' ) {
- $reason = wfMsgForContent( 'newuserlog-byemail' );
+ $reason = wfMessage( 'newuserlog-byemail' )->inContentLanguage()->text();
} else {
$reason = $wgContLang->commaList( array(
- $reason, wfMsgForContent( 'newuserlog-byemail' ) ) );
+ $reason, wfMessage( 'newuserlog-byemail' )->inContentLanguage()->text() ) );
}
}
}
/*
if ( $wgMinimalPasswordLength > 1 ) {
$ret['pattern'] = '.{' . intval( $wgMinimalPasswordLength ) . ',}';
- $ret['title'] = wfMsgExt( 'passwordtooshort', 'parsemag',
- $wgMinimalPasswordLength );
+ $ret['title'] = wfMessage( 'passwordtooshort' )
+ ->numParams( $wgMinimalPasswordLength )->text();
}
*/
if ( $this->oldid ) {
// Always show a link to the diff which triggered the mail. See bug 32210.
- $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_lastdiff',
- $this->title->getCanonicalUrl( 'diff=next&oldid=' . $this->oldid ) );
+ $keys['$NEWPAGE'] = wfMessage( 'enotif_lastdiff',
+ $this->title->getCanonicalUrl( 'diff=next&oldid=' . $this->oldid ) )
+ ->inContentLanguage()->text();
if ( !$wgEnotifImpersonal ) {
// For personal mail, also show a link to the diff of all changes
// since last visited.
- $keys['$NEWPAGE'] .= " \n" . wfMsgForContent( 'enotif_lastvisited',
- $this->title->getCanonicalUrl( 'diff=0&oldid=' . $this->oldid ) );
+ $keys['$NEWPAGE'] .= " \n" . wfMessage( 'enotif_lastvisited',
+ $this->title->getCanonicalUrl( 'diff=0&oldid=' . $this->oldid ) )
+ ->inContentLanguage()->text();
}
$keys['$OLDID'] = $this->oldid;
- $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'changed' );
+ $keys['$CHANGEDORCREATED'] = wfMessage( 'changed' )->inContentLanguage()->text();
} else {
- $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_newpagetext' );
+ $keys['$NEWPAGE'] = wfMessage( 'enotif_newpagetext' )->inContentLanguage()->text();
# clear $OLDID placeholder in the message template
$keys['$OLDID'] = '';
- $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'created' );
+ $keys['$CHANGEDORCREATED'] = wfMessage( 'created' )->inContentLanguage()->text();
}
$keys['$PAGETITLE'] = $this->title->getPrefixedText();
$keys['$PAGETITLE_URL'] = $this->title->getCanonicalUrl();
- $keys['$PAGEMINOREDIT'] = $this->minorEdit ? wfMsgForContent( 'minoredit' ) : '';
+ $keys['$PAGEMINOREDIT'] = $this->minorEdit ?
+ wfMessage( 'minoredit' )->inContentLanguage()->text() : '';
$keys['$UNWATCHURL'] = $this->title->getCanonicalUrl( 'action=unwatch' );
if ( $this->editor->isAnon() ) {
# real anon (user:xxx.xxx.xxx.xxx)
- $keys['$PAGEEDITOR'] = wfMsgForContent( 'enotif_anon_editor', $this->editor->getName() );
- $keys['$PAGEEDITOR_EMAIL'] = wfMsgForContent( 'noemailtitle' );
+ $keys['$PAGEEDITOR'] = wfMessage( 'enotif_anon_editor', $this->editor->getName() )
+ ->inContentLanguage()->text();
+ $keys['$PAGEEDITOR_EMAIL'] = wfMessage( 'noemailtitle' )->inContentLanguage()->text();
} else {
$keys['$PAGEEDITOR'] = $wgEnotifUseRealName ? $this->editor->getRealName() : $this->editor->getName();
$emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $this->editor->getName() );
# Now build message's subject and body
- $subject = wfMsgExt( 'enotif_subject', 'content' );
+ $subject = wfMessage( 'enotif_subject' )->inContentLanguage()->plain();
$subject = strtr( $subject, $keys );
$subject = MessageCache::singleton()->transform( $subject, false, null, $this->title );
$this->subject = strtr( $subject, $postTransformKeys );
- $body = wfMsgExt( 'enotif_body', 'content' );
+ $body = wfMessage( 'enotif_body' )->inContentLanguage()->plain();
$body = strtr( $body, $keys );
$body = MessageCache::singleton()->transform( $body, false, null, $this->title );
$this->body = wordwrap( strtr( $body, $postTransformKeys ), 72 );
array( '$WATCHINGUSERNAME',
'$PAGEEDITDATE',
'$PAGEEDITTIME' ),
- array( wfMsgForContent( 'enotif_impersonal_salutation' ),
+ array( wfMessage( 'enotif_impersonal_salutation' )->inContentLanguage()->text(),
$wgContLang->date( $this->timestamp, false, false ),
$wgContLang->time( $this->timestamp, false, false ) ),
$this->body );
/** @return string */
function getMessage() {
// '$1 at line $2, col $3 (byte $4): $5',
- return wfMsgHtml( 'xml-error-string',
+ return wfMessage( 'xml-error-string',
$this->mMessage,
$this->mLine,
$this->mColumn,
$this->mByte . $this->mContext,
- xml_error_string( $this->mXmlError ) );
+ xml_error_string( $this->mXmlError ) )->escaped();
}
function _extractContext( $context, $offset ) {
* Create a WikiPage object of the appropriate class for the given title.
*
* @param $title Title
+ * @throws MWException
* @return WikiPage object of the appropriate type
*/
public static function factory( Title $title ) {
* Determine whether a page would be suitable for being counted as an
* article in the site_stats table based on the title & its content
*
- * @param $editInfo Object or false: object returned by prepareTextForEdit(),
+ * @param $editInfo Object|bool (false): object returned by prepareTextForEdit(),
* if false, the current database state will be used
* @return Boolean
*/
* edit-already-exists error will be returned. These two conditions are also possible with
* auto-detection due to MediaWiki's performance-optimised locking strategy.
*
- * @param $baseRevId int the revision ID this edit was based off, if any
+ * @param bool|int $baseRevId int the revision ID this edit was based off, if any
* @param $user User the user doing the edit
*
+ * @throws MWException
* @return Status object. Possible errors:
* edit-hook-aborted: The ArticleSave hook aborted the edit but didn't set the fatal flag of $status
* edit-gone-missing: In update mode, but the article didn't exist
if ( $restrictions != '' ) {
$protectDescription .= $wgContLang->getDirMark() . "[$action=$restrictions] (";
if ( $encodedExpiry[$action] != 'infinity' ) {
- $protectDescription .= wfMsgForContent( 'protect-expiring',
+ $protectDescription .= wfMessage(
+ 'protect-expiring',
$wgContLang->timeanddate( $expiry[$action], false, false ) ,
$wgContLang->date( $expiry[$action], false, false ) ,
- $wgContLang->time( $expiry[$action], false, false ) );
+ $wgContLang->time( $expiry[$action], false, false )
+ )->inContentLanguage()->text();
} else {
- $protectDescription .= wfMsgForContent( 'protect-expiry-indefinite' );
+ $protectDescription .= wfMessage( 'protect-expiry-indefinite' )
+ ->inContentLanguage()->text();
}
$protectDescription .= ') ';
}
# Prepare a null revision to be added to the history
- $editComment = $wgContLang->ucfirst( wfMsgForContent( $revCommentMsg, $this->mTitle->getPrefixedText() ) );
+ $editComment = $wgContLang->ucfirst(
+ wfMessage(
+ $revCommentMsg,
+ $this->mTitle->getPrefixedText()
+ )->inContentLanguage()->text()
+ );
if ( $reason ) {
$editComment .= ": $reason";
}
$editComment .= " ($protectDescription)";
}
if ( $cascade ) {
- $editComment .= ' [' . wfMsgForContent( 'protect-summary-cascade' ) . ']';
+ // FIXME: Should use 'brackets' message.
+ $editComment .= ' [' . wfMessage( 'protect-summary-cascade' )
+ ->inContentLanguage()->text() . ']';
}
# Insert a null revision
* Take an array of page restrictions and flatten it to a string
* suitable for insertion into the page_restrictions field.
* @param $limit Array
+ * @throws MWException
* @return String
*/
protected static function flattenRestrictions( $limit ) {
$target = Revision::newFromId( $s->rev_id );
if ( empty( $summary ) ) {
if ( $from == '' ) { // no public user name
- $summary = wfMsgForContent( 'revertpage-nouser' );
+ $summary = wfMessage( 'revertpage-nouser' )->inContentLanguage()->text();
} else {
- $summary = wfMsgForContent( 'revertpage' );
+ $summary = wfMessage( 'revertpage' )->inContentLanguage()->text();
}
}
/**
* @deprecated since 1.18
+ * @param $oldid int
* @return bool
*/
public function useParserCache( $oldid ) {
'彩线' => '綵線',
'彩船' => '綵船',
'彩衣' => '綵衣',
+'綫' => '線',
'缉凶' => '緝凶',
'緝兇' => '緝凶',
'緝凶' => '緝凶',
);
$zh2HK = array(
+'505線' => '505綫',
+'505线' => '505綫',
+'507線' => '507綫',
+'507线' => '507綫',
+'610線' => '610綫',
+'610线' => '610綫',
+'614P線' => '614P綫',
+'614P线' => '614P綫',
+'614线' => '614綫',
+'614線' => '614綫',
+'615P線' => '615P綫',
+'615P线' => '615P綫',
+'615线' => '615綫',
+'615線' => '615綫',
+'705线' => '705綫',
+'705線' => '705綫',
+'706线' => '706綫',
+'706線' => '706綫',
+'751P線' => '751P綫',
+'751P线' => '751P綫',
+'751線' => '751綫',
+'751线' => '751綫',
+'761P线' => '761P綫',
+'761P線' => '761P綫',
'“' => '「',
'”' => '」',
'‘' => '『',
'動著者' => '動著者',
'動著述' => '動著述',
'動著錄' => '動著錄',
+'北环线' => '北環綫',
+'北環線' => '北環綫',
'医院里' => '医院裏',
'波札那' => '博茨瓦納',
'珍妮弗·卡普里亚蒂' => '卡佩雅蒂',
'寫著者' => '寫著者',
'寫著述' => '寫著述',
'寫著錄' => '寫著錄',
+'将军澳线' => '將軍澳綫',
+'將軍澳線' => '將軍澳綫',
'专辑里' => '專輯裏',
'專輯裡' => '專輯裏',
'尋著' => '尋着',
'本著錄' => '本著錄',
'村子里' => '村子裏',
'村子裡' => '村子裏',
+'东涌线' => '東涌綫',
+'東涌線' => '東涌綫',
+'東鐵線' => '東鐵綫',
+'东铁线' => '東鐵綫',
'枕著' => '枕着',
'枕著作' => '枕著作',
'枕著名' => '枕著名',
'樂著錄' => '樂著錄',
'寶獅' => '標致',
'標誌著' => '標誌着',
+'機場快線' => '機場快綫',
+'机场快线' => '機場快綫',
'機器人' => '機械人',
'机器人' => '機械人',
'历史里' => '歷史裏',
'沉著者' => '沉著者',
'沉著述' => '沉著述',
'沉著錄' => '沉著錄',
+'沙中线' => '沙中綫',
+'沙中線' => '沙中綫',
'沙地阿拉伯' => '沙特阿拉伯',
'沙烏地阿拉伯' => '沙特阿拉伯',
+'沙田至中環線' => '沙田至中環綫',
+'沙田至中环线' => '沙田至中環綫',
'马拉特·萨芬' => '沙芬',
'沿著' => '沿着',
'沿著作' => '沿著作',
'涼著錄' => '涼著錄',
'深淵裡' => '深淵裏',
'深渊里' => '深渊裏',
+'港岛线' => '港島綫',
+'港島線' => '港島綫',
'渴著' => '渴着',
'渴著作' => '渴著作',
'渴著名' => '渴著名',
'潤著者' => '潤著者',
'潤著述' => '潤著述',
'潤著錄' => '潤著錄',
+'無線劇集' => '無綫劇集',
+'无线剧集' => '無綫劇集',
+'無線收費' => '無綫收費',
+'无线收费' => '無綫收費',
+'无线节目' => '無綫節目',
+'無線節目' => '無綫節目',
+'无线电视' => '無綫電視',
+'無線電視' => '無綫電視',
'菸' => '煙',
'照著' => '照着',
'照著作' => '照著作',
'苦著錄' => '苦著錄',
'苦里' => '苦裏',
'苦裡' => '苦裏',
+'荃湾线' => '荃灣綫',
+'荃灣線' => '荃灣綫',
'莫三比克' => '莫桑比克',
'賴索托' => '萊索托',
'馬自達' => '萬事得',
'裹著者' => '裹著者',
'裹著述' => '裹著述',
'裹著錄' => '裹著錄',
+'西铁线' => '西鐵綫',
+'西鐵線' => '西鐵綫',
'見著' => '見着',
'見著作' => '見著作',
'見著名' => '見著名',
'見著者' => '見著者',
'見著述' => '見著述',
'見著錄' => '見著錄',
+'觀塘線' => '觀塘綫',
+'观塘线' => '觀塘綫',
'記著' => '記着',
'記著作' => '記著作',
'記著名' => '記著名',
'辦著錄' => '辦著錄',
'近角聪信' => '近角聰信',
'近角聰信' => '近角聰信',
+'迪士尼线' => '迪士尼綫',
+'迪士尼線' => '迪士尼綫',
'迫著' => '迫着',
'追著' => '追着',
'追著作' => '追著作',
'馬爾地夫' => '馬爾代夫',
'馬利共和國' => '馬里共和國',
'土豆' => '馬鈴薯',
+'馬鞍山線' => '馬鞍山綫',
+'马鞍山线' => '馬鞍山綫',
'駕著' => '駕着',
'駕著作' => '駕著作',
'駕著名' => '駕著名',
'笨豬跳' => '绑紧跳',
'蹦极跳' => '绑紧跳',
'笑星' => '谐星',
-);
+);
\ No newline at end of file
$content = '';
$table = '';
+ // Header
+ if ( !$this->msg( 'pageinfo-header' )->isDisabled() ) {
+ $content .= $this->msg( 'pageinfo-header ' )->parse();
+ }
+
// Basic information
$content = $this->addHeader( $content, $this->msg( 'pageinfo-header-basic' )->text() );
$content = $this->addTable( $content, $table );
}
+ // Footer
+ if ( !$this->msg( 'pageinfo-footer' )->isDisabled() ) {
+ $content .= $this->msg( 'pageinfo-footer' )->parse();
+ }
+
return $content;
}
if ( $titleObj->isRedirect() ) {
$oldTitle = $titleObj;
- $titles = Revision::newFromTitle( $oldTitle )->getContent( Revision::FOR_THIS_USER )->getRedirectChain();
+ $titles = Revision::newFromTitle( $oldTitle, false, Revision::READ_LATEST )
+ ->getContent( Revision::FOR_THIS_USER )
+ ->getRedirectChain();
// array_shift( $titles );
$redirValues = array();
if ( !is_null( $params['summary'] ) ) {
$requestArray['wpSummary'] = $params['summary'];
}
-
+
if ( !is_null( $params['sectiontitle'] ) ) {
$requestArray['wpSectionTitle'] = $params['sectiontitle'];
}
$this->getMain()->getRequest()->response()->header( "Content-Type: $mime; charset=utf-8" );
+ //Set X-Frame-Options API results (bug 39180)
+ global $wgApiFrameOptions;
+ if ( $wgApiFrameOptions ) {
+ $this->getMain()->getRequest()->response()->header( "X-Frame-Options: $wgApiFrameOptions" );
+ }
+
if ( $isHtml ) {
?>
<!DOCTYPE HTML>
// identify URLs
$protos = wfUrlProtocolsWithoutProtRel();
// This regex hacks around bug 13218 (" included in the URL)
- $text = preg_replace( "#(($protos).*?)(")?([ \\'\"<>\n]|<|>|")#", '<a href="\\1">\\1</a>\\3\\4', $text );
+ $text = preg_replace( "#(((?i)$protos).*?)(")?([ \\'\"<>\n]|<|>|")#", '<a href="\\1">\\1</a>\\3\\4', $text );
// identify requests to api.php
$text = preg_replace( "#api\\.php\\?[^ <\n\t]+#", '<a href="\\0">\\0</a>', $text );
if ( $this->mHelp ) {
try {
$this->executeAction();
} catch ( Exception $e ) {
+ // Allow extra cleanup and logging
+ wfRunHooks( 'ApiMain::onException', array( $this, $e ) );
+
// Log it
if ( !( $e instanceof UsageException ) ) {
wfDebugLog( 'exception', $e->getLogMessage() );
if ( $fld_groups ) {
if ( !isset( $lastUserData['groups'] ) ) {
if ( $lastUserObj ) {
- $lastUserData['groups'] = ApiQueryUsers::getAutoGroups( $lastUserObj );
+ $lastUserData['groups'] = $lastUserObj->getAutomaticGroups();
} else {
// This should not normally happen
$lastUserData['groups'] = array();
}
if ( $fld_implicitgroups && !isset( $lastUserData['implicitgroups'] ) && $lastUserObj ) {
- $lastUserData['implicitgroups'] = ApiQueryUsers::getAutoGroups( $lastUserObj );
+ $lastUserData['implicitgroups'] = $lastUserObj->getAutomaticGroups();
$result->setIndexedTagName( $lastUserData['implicitgroups'], 'g' );
}
if ( $fld_rights ) {
}
if ( isset( $this->prop['groups'] ) ) {
- $autolist = ApiQueryUsers::getAutoGroups( $user );
-
- $vals['groups'] = array_merge( $autolist, $user->getGroups() );
+ $vals['groups'] = $user->getEffectiveGroups();
$result->setIndexedTagName( $vals['groups'], 'g' ); // even if empty
}
if ( isset( $this->prop['implicitgroups'] ) ) {
- $vals['implicitgroups'] = ApiQueryUsers::getAutoGroups( $user );
+ $vals['implicitgroups'] = $user->getAutomaticGroups();
$result->setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
}
if ( isset( $this->prop['groups'] ) ) {
if ( !isset( $data[$name]['groups'] ) ) {
- $data[$name]['groups'] = self::getAutoGroups( $user );
+ $data[$name]['groups'] = $user->getAutomaticGroups();
}
if ( !is_null( $row->ug_group ) ) {
}
if ( isset( $this->prop['implicitgroups'] ) && !isset( $data[$name]['implicitgroups'] ) ) {
- $data[$name]['implicitgroups'] = self::getAutoGroups( $user );
+ $data[$name]['implicitgroups'] = $user->getAutomaticGroups();
}
if ( isset( $this->prop['rights'] ) ) {
/**
* Gets all the groups that a user is automatically a member of (implicit groups)
+ *
+ * @deprecated since 1.20; call User::getAutomaticGroups() directly.
* @param $user User
* @return array
*/
public static function getAutoGroups( $user ) {
- // FIXME this logic is duplicated from User::getEffectiveGroups(), centralize this
- $groups = array();
- $groups[] = '*';
+ wfDeprecated( __METHOD__, '1.20' );
- if ( !$user->isAnon() ) {
- $groups[] = 'user';
- $groups = array_merge( $groups, Autopromote::getAutopromoteGroups( $user ) );
- }
-
- return $groups;
+ return $user->getAutomaticGroups();
}
public function getCacheMode( $params ) {
}
# Try loading it from the database
- $revision = Revision::newFromTitle( Title::makeTitle( NS_MEDIAWIKI, $title ) );
+ $revision = Revision::newFromTitle(
+ Title::makeTitle( NS_MEDIAWIKI, $title ), false, Revision::READ_LATEST
+ );
if ( $revision ) {
$content = $revision->getContent();
if ( !$content ) {
protected $mServer, $mUser, $mPassword, $mDBname;
- /**
- * @var DatabaseBase
- */
protected $mConn = null;
protected $mOpened = false;
+ /** @var Array */
+ protected $trxIdleCallbacks = array();
+
protected $mTablePrefix;
protected $mFlags;
protected $mTrxLevel = 0;
}
if ( isset( $options['HAVING'] ) ) {
- $preLimitTail .= " HAVING {$options['HAVING']}";
+ $having = is_array( $options['HAVING'] )
+ ? $this->makeList( $options['HAVING'], LIST_AND )
+ : $options['HAVING'];
+ $preLimitTail .= " HAVING {$having}";
}
if ( isset( $options['ORDER BY'] ) ) {
* - GROUP BY: May be either an SQL fragment string naming a field or
* expression to group by, or an array of such SQL fragments.
*
- * - HAVING: A string containing a HAVING clause.
+ * - HAVING: May be either an string containing a HAVING clause or an array of
+ * conditions building the HAVING clause. If an array is given, the conditions
+ * constructed from each element are combined with AND.
*
* - ORDER BY: May be either an SQL fragment giving a field name or
* expression to order by, or an array of such SQL fragments.
}
}
+ /**
+ * Run an anonymous function as soon as there is no transaction pending.
+ * If there is a transaction and it is rolled back, then the callback is cancelled.
+ * Callbacks must commit any transactions that they begin.
+ *
+ * This is useful for updates to different systems or separate transactions are needed.
+ *
+ * @param Closure $callback
+ * @return void
+ */
+ final public function onTransactionIdle( Closure $callback ) {
+ if ( $this->mTrxLevel ) {
+ $this->trxIdleCallbacks[] = $callback;
+ } else {
+ $callback();
+ }
+ }
+
+ /**
+ * Actually run the "on transaction idle" callbacks
+ */
+ protected function runOnTransactionIdleCallbacks() {
+ $e = null; // last exception
+ do { // callbacks may add callbacks :)
+ $callbacks = $this->trxIdleCallbacks;
+ $this->trxIdleCallbacks = array(); // recursion guard
+ foreach ( $callbacks as $callback ) {
+ try {
+ $callback();
+ } catch ( Exception $e ) {}
+ }
+ } while ( count( $this->trxIdleCallbacks ) );
+
+ if ( $e instanceof Exception ) {
+ throw $e; // re-throw any last exception
+ }
+ }
+
/**
* Begin a transaction
*
* @param $fname string
*/
- public function begin( $fname = 'DatabaseBase::begin' ) {
+ final public function begin( $fname = 'DatabaseBase::begin' ) {
+ if ( $this->mTrxLevel ) { // implicit commit
+ $this->doCommit( $fname );
+ $this->runOnTransactionIdleCallbacks();
+ }
+ $this->doBegin( $fname );
+ }
+
+ /**
+ * @see DatabaseBase::begin()
+ * @param type $fname
+ */
+ protected function doBegin( $fname ) {
$this->query( 'BEGIN', $fname );
$this->mTrxLevel = 1;
}
*
* @param $fname string
*/
- public function commit( $fname = 'DatabaseBase::commit' ) {
+ final public function commit( $fname = 'DatabaseBase::commit' ) {
+ $this->doCommit( $fname );
+ $this->runOnTransactionIdleCallbacks();
+ }
+
+ /**
+ * @see DatabaseBase::commit()
+ * @param type $fname
+ */
+ protected function doCommit( $fname ) {
if ( $this->mTrxLevel ) {
$this->query( 'COMMIT', $fname );
$this->mTrxLevel = 0;
*
* @param $fname string
*/
- public function rollback( $fname = 'DatabaseBase::rollback' ) {
+ final public function rollback( $fname = 'DatabaseBase::rollback' ) {
+ $this->doRollback( $fname );
+ $this->trxIdleCallbacks = array(); // cancel
+ }
+
+ /**
+ * @see DatabaseBase::rollback()
+ * @param type $fname
+ */
+ protected function doRollback( $fname ) {
if ( $this->mTrxLevel ) {
$this->query( 'ROLLBACK', $fname, true );
$this->mTrxLevel = 0;
/**
* Start a transaction (mandatory)
*/
- public function begin( $fname = 'DatabaseIbm_db2::begin' ) {
+ protected function doBegin( $fname = 'DatabaseIbm_db2::begin' ) {
// BEGIN is implicit for DB2
// However, it requires that AutoCommit be off.
* End a transaction
* Must have a preceding begin()
*/
- public function commit( $fname = 'DatabaseIbm_db2::commit' ) {
+ protected function doCommit( $fname = 'DatabaseIbm_db2::commit' ) {
db2_commit( $this->mConn );
// Some MediaWiki code is still transaction-less (?).
/**
* Cancel a transaction
*/
- public function rollback( $fname = 'DatabaseIbm_db2::rollback' ) {
+ protected function doRollback( $fname = 'DatabaseIbm_db2::rollback' ) {
db2_rollback( $this->mConn );
// turn auto-commit back on
// not sure if this is appropriate
/**
* Begin a transaction, committing any previously open transaction
*/
- function begin( $fname = 'DatabaseMssql::begin' ) {
+ protected function doBegin( $fname = 'DatabaseMssql::begin' ) {
sqlsrv_begin_transaction( $this->mConn );
$this->mTrxLevel = 1;
}
/**
* End a transaction
*/
- function commit( $fname = 'DatabaseMssql::commit' ) {
+ protected function doCommit( $fname = 'DatabaseMssql::commit' ) {
sqlsrv_commit( $this->mConn );
$this->mTrxLevel = 0;
}
* Rollback a transaction.
* No-op on non-transactional databases.
*/
- function rollback( $fname = 'DatabaseMssql::rollback' ) {
+ protected function doRollback( $fname = 'DatabaseMssql::rollback' ) {
sqlsrv_rollback( $this->mConn );
$this->mTrxLevel = 0;
}
* @throws DBConnectionError
*/
function open( $server, $user, $password, $dbName ) {
- global $wgAllDBsAreLocalhost;
+ global $wgAllDBsAreLocalhost, $wgDBmysql5, $wgSQLMode;
wfProfileIn( __METHOD__ );
# Load mysql.so if we don't have it
$connFlags |= MYSQL_CLIENT_COMPRESS;
}
- wfProfileIn("dbconnect-$server");
+ wfProfileIn( "dbconnect-$server" );
# The kernel's default SYN retransmission period is far too slow for us,
# so we use a short timeout plus a manual retry. Retrying means that a small
#wfLogDBError("Connect loop error $iplus of $max ($server): " . mysql_errno() . " - " . mysql_error()."\n");
#}
}
- $phpError = $this->restoreErrorHandler();
+ $error = $this->restoreErrorHandler();
+
+ wfProfileOut( "dbconnect-$server" );
+
# Always log connection errors
if ( !$this->mConn ) {
- $error = $phpError;
if ( !$error ) {
$error = $this->lastError();
}
wfLogDBError( "Error connecting to {$this->mServer}: $error\n" );
- wfDebug( "DB connection error\n" );
- wfDebug( "Server: $server, User: $user, Password: " .
+ wfDebug( "DB connection error\n" .
+ "Server: $server, User: $user, Password: " .
substr( $password, 0, 3 ) . "..., error: " . $error . "\n" );
- }
- wfProfileOut("dbconnect-$server");
+ wfProfileOut( __METHOD__ );
+ $this->reportConnectionError( $error );
+ }
- if ( $dbName != '' && $this->mConn !== false ) {
+ if ( $dbName != '' ) {
wfSuppressWarnings();
$success = mysql_select_db( $dbName, $this->mConn );
wfRestoreWarnings();
if ( !$success ) {
- $error = "Error selecting database $dbName on server {$this->mServer} " .
- "from client host " . wfHostname() . "\n";
- wfLogDBError(" Error selecting database $dbName on server {$this->mServer} \n");
- wfDebug( $error );
- }
- } else {
- # Delay USE query
- $success = (bool)$this->mConn;
- }
+ wfLogDBError( "Error selecting database $dbName on server {$this->mServer}\n" );
+ wfDebug( "Error selecting database $dbName on server {$this->mServer} " .
+ "from client host " . wfHostname() . "\n" );
- if ( $success ) {
- // Tell the server we're communicating with it in UTF-8.
- // This may engage various charset conversions.
- global $wgDBmysql5;
- if( $wgDBmysql5 ) {
- $this->query( 'SET NAMES utf8', __METHOD__ );
- } else {
- $this->query( 'SET NAMES binary', __METHOD__ );
- }
- // Set SQL mode, default is turning them all off, can be overridden or skipped with null
- global $wgSQLMode;
- if ( is_string( $wgSQLMode ) ) {
- $mode = $this->addQuotes( $wgSQLMode );
- $this->query( "SET sql_mode = $mode", __METHOD__ );
+ wfProfileOut( __METHOD__ );
+ $this->reportConnectionError( "Error selecting database $dbName" );
}
+ }
- // Turn off strict mode if it is on
+ // Tell the server we're communicating with it in UTF-8.
+ // This may engage various charset conversions.
+ if( $wgDBmysql5 ) {
+ $this->query( 'SET NAMES utf8', __METHOD__ );
} else {
- $this->reportConnectionError( $phpError );
+ $this->query( 'SET NAMES binary', __METHOD__ );
+ }
+ // Set SQL mode, default is turning them all off, can be overridden or skipped with null
+ if ( is_string( $wgSQLMode ) ) {
+ $mode = $this->addQuotes( $wgSQLMode );
+ $this->query( "SET sql_mode = $mode", __METHOD__ );
}
- $this->mOpened = $success;
+ $this->mOpened = true;
wfProfileOut( __METHOD__ );
- return $success;
+ return true;
}
/**
wfSuppressWarnings();
$row = mysql_fetch_object( $res );
wfRestoreWarnings();
- if( $this->lastErrno() ) {
+
+ $errno = $this->lastErrno();
+ // Unfortunately, mysql_fetch_object does not reset the last errno.
+ // Only check for CR_SERVER_LOST and CR_UNKNOWN_ERROR, as
+ // these are the only errors mysql_fetch_object can cause.
+ // See http://dev.mysql.com/doc/refman/5.0/es/mysql-fetch-row.html.
+ if( $errno == 2000 || $errno == 2013 ) {
throw new DBUnexpectedError( $this, 'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() ) );
}
return $row;
wfSuppressWarnings();
$row = mysql_fetch_array( $res );
wfRestoreWarnings();
- if ( $this->lastErrno() ) {
+
+ $errno = $this->lastErrno();
+ // Unfortunately, mysql_fetch_array does not reset the last errno.
+ // Only check for CR_SERVER_LOST and CR_UNKNOWN_ERROR, as
+ // these are the only errors mysql_fetch_object can cause.
+ // See http://dev.mysql.com/doc/refman/5.0/es/mysql-fetch-row.html.
+ if( $errno == 2000 || $errno == 2013 ) {
throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() ) );
}
return $row;
return $this->fieldInfoMulti ($table, $field);
}
- function begin( $fname = 'DatabaseOracle::begin' ) {
+ protected function doBegin( $fname = 'DatabaseOracle::begin' ) {
$this->mTrxLevel = 1;
$this->doQuery( 'SET CONSTRAINTS ALL DEFERRED' );
}
- function commit( $fname = 'DatabaseOracle::commit' ) {
+ protected function doCommit( $fname = 'DatabaseOracle::commit' ) {
if ( $this->mTrxLevel ) {
$ret = oci_commit( $this->mConn );
if ( !$ret ) {
}
}
- function rollback( $fname = 'DatabaseOracle::rollback' ) {
+ protected function doRollback( $fname = 'DatabaseOracle::rollback' ) {
if ( $this->mTrxLevel ) {
oci_rollback( $this->mConn );
$this->mTrxLevel = 0;
return false;
}
- function begin( $fname = '' ) {
+ protected function doBegin( $fname = '' ) {
if ( $this->mTrxLevel == 1 ) {
$this->commit( __METHOD__ );
}
$this->mTrxLevel = 1;
}
- function commit( $fname = '' ) {
+ protected function doCommit( $fname = '' ) {
if ( $this->mTrxLevel == 0 ) {
return;
}
$this->mTrxLevel = 0;
}
- function rollback( $fname = '' ) {
+ protected function doRollback( $fname = '' ) {
if ( $this->mTrxLevel == 0 ) {
return;
}
// Create a new temporary file with the same extension...
$ext = FileBackend::extensionFromPath( $params['src'] );
- $tmpFile = TempFSFile::factory( wfBaseName( $source ) . '_', $ext );
+ $tmpFile = TempFSFile::factory( 'localcopy_', $ext );
if ( !$tmpFile ) {
return null;
}
* All "storage paths" are of the format "mwstore://<backend>/<container>/<path>".
* The "<path>" portion is a relative path that uses UNIX file system (FS)
* notation, though any particular backend may not actually be using a local
- * filesystem.
- * Therefore, the relative paths are only virtual.
+ * filesystem. Therefore, the relative paths are only virtual.
*
* Backend contents are stored under wiki-specific container names by default.
* For legacy reasons, this has no effect for the FS backend class, and per-wiki
* 'dst' => <storage path>,
* 'content' => <string of new file contents>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* );
* @endcode
*
* 'src' => <file system path>,
* 'dst' => <storage path>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
*
* 'src' => <storage path>,
* 'dst' => <storage path>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
*
* 'src' => <storage path>,
* 'dst' => <storage path>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
*
* - overwriteSame : An error will not be given if a file already
* exists at the destination that has the same
* contents as the new contents to be written there.
+ * - disposition : When supplied, the backend will add a Content-Disposition
+ * header when GETs/HEADs of the destination file are made.
+ * Backends that don't support file metadata will ignore this.
+ * See http://tools.ietf.org/html/rfc6266 (since 1.20).
*
* $opts is an associative of boolean flags, including:
* - force : Operation precondition errors no longer trigger an abort.
* array(
* 'op' => 'create',
* 'dst' => <storage path>,
- * 'content' => <string of new file contents>
+ * 'content' => <string of new file contents>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
* b) Copy a file system file into storage
* array(
* 'op' => 'store',
* 'src' => <file system path>,
- * 'dst' => <storage path>
+ * 'dst' => <storage path>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
* c) Copy a file within storage
* array(
* 'op' => 'copy',
* 'src' => <storage path>,
- * 'dst' => <storage path>
+ * 'dst' => <storage path>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
* d) Move a file within storage
* array(
* 'op' => 'move',
* 'src' => <storage path>,
- * 'dst' => <storage path>
+ * 'dst' => <storage path>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
* e) Delete a file within storage
* @par Boolean flags for operations (operation-specific):
* - ignoreMissingSource : The operation will simply succeed and do
* nothing if the source file does not exist.
+ * - disposition : When supplied, the backend will add a Content-Disposition
+ * header when GETs/HEADs of the destination file are made.
+ * Backends that don't support file metadata will ignore this.
+ * See http://tools.ietf.org/html/rfc6266 (since 1.20).
*
* $opts is an associative of boolean flags, including:
* - bypassReadOnly : Allow writes in read-only mode (since 1.20)
return ( self::normalizeContainerPath( $path ) !== null );
}
+ /**
+ * Build a Content-Disposition header value per RFC 6266
+ *
+ * @param $type string One of (attachment, inline)
+ * @param $filename string Suggested file name (should not contain slashes)
+ * @return string
+ * @since 1.20
+ */
+ final public static function makeContentDisposition( $type, $filename ) {
+ $type = strtolower( $type );
+ $type = in_array( $type, array( 'inline', 'attachment' ) ) ? $type : 'inline';
+ return "$type; filename*=UTF-8''" . rawurlencode( basename( $filename ) );
+ }
+
/**
* Validate and normalize a relative storage path.
* Null is returned if the path involves directory traversal.
// Actually attempt the operation batch on the master backend...
$masterStatus = $mbe->doOperations( $realOps, $opts );
$status->merge( $masterStatus );
- // Propagate the operations to the clone backends...
- foreach ( $this->backends as $index => $backend ) {
- if ( $index !== $this->masterIndex ) { // not done already
- $realOps = $this->substOpBatchPaths( $ops, $backend );
- $status->merge( $backend->doOperations( $realOps, $opts ) );
+ // Propagate the operations to the clone backends if there were no fatal errors.
+ // If $ops only had one operation, this might avoid backend inconsistencies.
+ if ( !count( $masterStatus->getErrorsArray() ) ) {
+ foreach ( $this->backends as $index => $backend ) {
+ if ( $index !== $this->masterIndex ) { // not done already
+ $realOps = $this->substOpBatchPaths( $ops, $backend );
+ $status->merge( $backend->doOperations( $realOps, $opts ) );
+ }
}
}
// Make 'success', 'successCount', and 'failCount' fields reflect
* - content : the raw file contents
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
} else {
$status = $this->doCreateInternal( $params );
$this->clearCache( array( $params['dst'] ) );
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
}
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
* - src : source path on disk
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
} else {
$status = $this->doStoreInternal( $params );
$this->clearCache( array( $params['dst'] ) );
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
}
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
* - src : source storage path
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
wfProfileIn( __METHOD__ . '-' . $this->name );
$status = $this->doCopyInternal( $params );
$this->clearCache( array( $params['dst'] ) );
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
return $status;
* - src : source storage path
* - dst : destination storage path
* - overwrite : overwrite any file that exists at the destination
+ * - disposition : Content-Disposition header value for the destination
* - async : Status will be returned immediately if supported.
* If the status is OK, then its value field will be
* set to a FileBackendStoreOpHandle object.
$status = $this->doMoveInternal( $params );
$this->clearCache( array( $params['src'], $params['dst'] ) );
$this->deleteFileCache( $params['src'] ); // persistent cache
- $this->deleteFileCache( $params['dst'] ); // persistent cache
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->deleteFileCache( $params['dst'] ); // persistent cache
+ }
wfProfileOut( __METHOD__ . '-' . $this->name );
wfProfileOut( __METHOD__ );
return $status;
}
/**
- * Set the cached stat info for a file path
+ * Set the cached stat info for a file path.
+ * Negatives (404s) are not cached. By not caching negatives, we can skip cache
+ * salting for the case when a file is created at a path were there was none before.
*
* @param $path string Storage path
* @param $val mixed Information to cache
/**
* Store a file into the backend from a file on the file system.
- * Parameters similar to FileBackendStore::storeInternal(), which include:
- * - src : source path on file system
- * - dst : destination storage path
- * - overwrite : do nothing and pass if an identical file exists at destination
- * - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
*/
class StoreFileOp extends FileOp {
/**
* @return array
*/
protected function allowedParams() {
- return array( array( 'src', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+ return array( array( 'src', 'dst' ),
+ array( 'overwrite', 'overwriteSame', 'disposition' ) );
}
/**
/**
* Create a file in the backend with the given content.
- * Parameters similar to FileBackendStore::createInternal(), which include:
- * - content : the raw file contents
- * - dst : destination storage path
- * - overwrite : do nothing and pass if an identical file exists at destination
- * - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
*/
class CreateFileOp extends FileOp {
protected function allowedParams() {
- return array( array( 'content', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+ return array( array( 'content', 'dst' ),
+ array( 'overwrite', 'overwriteSame', 'disposition' ) );
}
protected function doPrecheck( array &$predicates ) {
/**
* Copy a file from one storage path to another in the backend.
- * Parameters similar to FileBackendStore::copyInternal(), which include:
- * - src : source storage path
- * - dst : destination storage path
- * - overwrite : do nothing and pass if an identical file exists at destination
- * - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
*/
class CopyFileOp extends FileOp {
/**
* @return array
*/
protected function allowedParams() {
- return array( array( 'src', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+ return array( array( 'src', 'dst' ),
+ array( 'overwrite', 'overwriteSame', 'disposition' ) );
}
/**
/**
* Move a file from one storage path to another in the backend.
- * Parameters similar to FileBackendStore::moveInternal(), which include:
- * - src : source storage path
- * - dst : destination storage path
- * - overwrite : do nothing and pass if an identical file exists at destination
- * - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
*/
class MoveFileOp extends FileOp {
/**
* @return array
*/
protected function allowedParams() {
- return array( array( 'src', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+ return array( array( 'src', 'dst' ),
+ array( 'overwrite', 'overwriteSame', 'disposition' ) );
}
/**
/**
* Delete a file at the given storage path from the backend.
- * Parameters similar to FileBackendStore::deleteInternal(), which include:
- * - src : source storage path
- * - ignoreMissingSource : don't return an error if the file does not exist
+ * Parameters for this operation are outlined in FileBackend::doOperations().
*/
class DeleteFileOp extends FileOp {
/**
if ( !strlen( $obj->content_type ) ) { // special case
$obj->content_type = 'unknown/unknown';
}
+ // Set the Content-Disposition header if requested
+ if ( isset( $params['disposition'] ) ) {
+ $obj->headers['Content-Disposition'] = $params['disposition'];
+ }
if ( !empty( $params['async'] ) ) { // deferred
- $handle = $obj->write_async( $params['content'] );
- $status->value = new SwiftFileOpHandle( $this, $params, 'Create', $handle );
- $status->value->affectedObjects[] = $obj;
+ $op = $obj->write_async( $params['content'] );
+ $status->value = new SwiftFileOpHandle( $this, $params, 'Create', $op );
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $status->value->affectedObjects[] = $obj;
+ }
} else { // actually write the object in Swift
$obj->write( $params['content'] );
- $this->purgeCDNCache( array( $obj ) );
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->purgeCDNCache( array( $obj ) );
+ }
}
} catch ( CDNNotEnabledException $e ) {
// CDN not enabled; nothing to see here
if ( !strlen( $obj->content_type ) ) { // special case
$obj->content_type = 'unknown/unknown';
}
+ // Set the Content-Disposition header if requested
+ if ( isset( $params['disposition'] ) ) {
+ $obj->headers['Content-Disposition'] = $params['disposition'];
+ }
if ( !empty( $params['async'] ) ) { // deferred
wfSuppressWarnings();
$fp = fopen( $params['src'], 'rb' );
if ( !$fp ) {
$status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
} else {
- $handle = $obj->write_async( $fp, filesize( $params['src'] ), true );
- $status->value = new SwiftFileOpHandle( $this, $params, 'Store', $handle );
+ $op = $obj->write_async( $fp, filesize( $params['src'] ), true );
+ $status->value = new SwiftFileOpHandle( $this, $params, 'Store', $op );
$status->value->resourcesToClose[] = $fp;
- $status->value->affectedObjects[] = $obj;
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $status->value->affectedObjects[] = $obj;
+ }
}
} else { // actually write the object in Swift
$obj->load_from_filename( $params['src'], true ); // calls $obj->write()
- $this->purgeCDNCache( array( $obj ) );
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->purgeCDNCache( array( $obj ) );
+ }
}
} catch ( CDNNotEnabledException $e ) {
// CDN not enabled; nothing to see here
// (b) Actually copy the file to the destination
try {
$dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD
+ $hdrs = array(); // source file headers to override with new values
+ if ( isset( $params['disposition'] ) ) {
+ $hdrs['Content-Disposition'] = $params['disposition'];
+ }
if ( !empty( $params['async'] ) ) { // deferred
- $handle = $sContObj->copy_object_to_async( $srcRel, $dContObj, $dstRel );
- $status->value = new SwiftFileOpHandle( $this, $params, 'Copy', $handle );
- $status->value->affectedObjects[] = $dstObj;
+ $op = $sContObj->copy_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs );
+ $status->value = new SwiftFileOpHandle( $this, $params, 'Copy', $op );
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $status->value->affectedObjects[] = $dstObj;
+ }
} else { // actually write the object in Swift
- $sContObj->copy_object_to( $srcRel, $dContObj, $dstRel );
- $this->purgeCDNCache( array( $dstObj ) );
+ $sContObj->copy_object_to( $srcRel, $dContObj, $dstRel, null, $hdrs );
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->purgeCDNCache( array( $dstObj ) );
+ }
}
} catch ( CDNNotEnabledException $e ) {
// CDN not enabled; nothing to see here
try {
$srcObj = new CF_Object( $sContObj, $srcRel, false, false ); // skip HEAD
$dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD
+ $hdrs = array(); // source file headers to override with new values
+ if ( isset( $params['disposition'] ) ) {
+ $hdrs['Content-Disposition'] = $params['disposition'];
+ }
if ( !empty( $params['async'] ) ) { // deferred
- $handle = $sContObj->move_object_to_async( $srcRel, $dContObj, $dstRel );
- $status->value = new SwiftFileOpHandle( $this, $params, 'Move', $handle );
+ $op = $sContObj->move_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs );
+ $status->value = new SwiftFileOpHandle( $this, $params, 'Move', $op );
$status->value->affectedObjects[] = $srcObj;
- $status->value->affectedObjects[] = $dstObj;
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $status->value->affectedObjects[] = $dstObj;
+ }
} else { // actually write the object in Swift
- $sContObj->move_object_to( $srcRel, $dContObj, $dstRel );
- $this->purgeCDNCache( array( $srcObj, $dstObj ) );
+ $sContObj->move_object_to( $srcRel, $dContObj, $dstRel, null, $hdrs );
+ $this->purgeCDNCache( array( $srcObj ) );
+ if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
+ $this->purgeCDNCache( array( $dstObj ) );
+ }
}
} catch ( CDNNotEnabledException $e ) {
// CDN not enabled; nothing to see here
$sContObj = $this->getContainer( $srcCont );
$srcObj = new CF_Object( $sContObj, $srcRel, false, false ); // skip HEAD
if ( !empty( $params['async'] ) ) { // deferred
- $handle = $sContObj->delete_object_async( $srcRel );
- $status->value = new SwiftFileOpHandle( $this, $params, 'Delete', $handle );
+ $op = $sContObj->delete_object_async( $srcRel );
+ $status->value = new SwiftFileOpHandle( $this, $params, 'Delete', $op );
$status->value->affectedObjects[] = $srcObj;
} else { // actually write the object in Swift
$sContObj->delete_object( $srcRel );
return null;
}
- # Check the recursion guard to avoid loops when filling metadata
- if ( empty( $params['nostat'] ) && !$this->fileExists( $params ) ) {
- return null;
- }
-
+ // Blindly create a tmp file and stream to it, catching any exception if the file does
+ // not exist. Also, doing a stat here will cause infinite loops when filling metadata.
$tmpFile = null;
try {
$sContObj = $this->getContainer( $srcCont );
// Get source file extension
$ext = FileBackend::extensionFromPath( $srcRel );
// Create a new temporary file...
- $tmpFile = TempFSFile::factory( wfBaseName( $srcRel ) . '_', $ext );
+ $tmpFile = TempFSFile::factory( 'localcopy_', $ext );
if ( $tmpFile ) {
$handle = fopen( $tmpFile->getPath(), 'wb' );
if ( $handle ) {
}
} catch ( NoSuchContainerException $e ) {
$tmpFile = null;
+ } catch ( NoSuchObjectException $e ) {
+ $tmpFile = null;
} catch ( CloudFilesException $e ) { // some other exception?
$tmpFile = null;
$this->handleException( $e, null, __METHOD__, $params );
*/
public static function factory( $prefix, $extension = '' ) {
wfProfileIn( __METHOD__ );
- $base = wfTempDir() . '/' . $prefix . dechex( mt_rand( 0, 99999999 ) );
+ $base = wfTempDir() . '/' . $prefix . wfRandomString( 12 );
$ext = ( $extension != '' ) ? ".{$extension}" : "";
for ( $attempt = 1; true; $attempt++ ) {
$path = "{$base}-{$attempt}{$ext}";
var $pathDisclosureProtection = 'simple'; // 'paranoid'
var $descriptionCacheExpiry, $url, $thumbUrl;
var $hashLevels, $deletedHashLevels;
+ protected $abbrvThreshold;
/**
* Factory functions for creating new files
? $info['deletedHashLevels']
: $this->hashLevels;
$this->transformVia404 = !empty( $info['transformVia404'] );
+ $this->abbrvThreshold = isset( $info['abbrvThreshold'] )
+ ? $info['abbrvThreshold']
+ : 255;
$this->isPrivate = !empty( $info['isPrivate'] );
// Give defaults for the basic zones...
$this->zones = isset( $info['zones'] ) ? $info['zones'] : array();
*
* @param $src string File system path
* @param $dst string Virtual URL or storage path
+ * @param $disposition string|null Content-Disposition if given and supported
* @return FileRepoStatus
*/
- final public function quickImport( $src, $dst ) {
- return $this->quickImportBatch( array( array( $src, $dst ) ) );
+ final public function quickImport( $src, $dst, $disposition = null ) {
+ return $this->quickImportBatch( array( array( $src, $dst, $disposition ) ) );
}
/**
* This function can be used to write to otherwise read-only foreign repos.
* This is intended for copying generated thumbnails into the repo.
*
- * @param $pairs Array List of tuples (file system path, virtual URL or storage path)
+ * When "dispositions" are given they are used as Content-Disposition if supported.
+ *
+ * @param $pairs Array List of tuples (file system path, virtual URL/storage path, disposition)
* @return FileRepoStatus
*/
public function quickImportBatch( array $pairs ) {
list ( $src, $dst ) = $pair;
$dst = $this->resolveToStoragePath( $dst );
$operations[] = array(
- 'op' => 'store',
- 'src' => $src,
- 'dst' => $dst
+ 'op' => 'store',
+ 'src' => $src,
+ 'dst' => $dst,
+ 'disposition' => isset( $pair[2] ) ? $pair[2] : null
);
$status->merge( $this->initDirectory( dirname( $dst ) ) );
}
public function storeTemp( $originalName, $srcPath ) {
$this->assertWritableRepo(); // fail out if read-only
- $date = gmdate( "YmdHis" );
- $hashPath = $this->getHashPath( $originalName );
- $dstRel = "{$hashPath}{$date}!{$originalName}";
- $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $originalName );
+ $date = gmdate( "YmdHis" );
+ $hashPath = $this->getHashPath( $originalName );
+ $dstRel = "{$hashPath}{$date}!{$originalName}";
+ $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $originalName );
+ $virtualUrl = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;
- $result = $this->store( $srcPath, 'temp', $dstRel, self::SKIP_LOCKING );
- $result->value = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;
+ $result = $this->quickImport( $srcPath, $virtualUrl );
+ $result->value = $virtualUrl;
return $result;
}
/**
- * Concatenate a list of files into a target file location.
+ * Remove a temporary file or mark it for garbage collection
+ *
+ * @param $virtualUrl String: the virtual URL returned by FileRepo::storeTemp()
+ * @return Boolean: true on success, false on failure
+ */
+ public function freeTemp( $virtualUrl ) {
+ $this->assertWritableRepo(); // fail out if read-only
+
+ $temp = $this->getVirtualUrl( 'temp' );
+ if ( substr( $virtualUrl, 0, strlen( $temp ) ) != $temp ) {
+ wfDebug( __METHOD__.": Invalid temp virtual URL\n" );
+ return false;
+ }
+
+ return $this->quickPurge( $virtualUrl )->isOK();
+ }
+
+ /**
+ * Concatenate a list of temporary files into a target file location.
*
* @param $srcPaths Array Ordered list of source virtual URLs/storage paths
* @param $dstPath String Target file system path
$status = $this->newGood();
$sources = array();
- $deleteOperations = array(); // post-concatenate ops
foreach ( $srcPaths as $srcPath ) {
// Resolve source to a storage path if virtual
$source = $this->resolveToStoragePath( $srcPath );
$sources[] = $source; // chunk to merge
- if ( $flags & self::DELETE_SOURCE ) {
- $deleteOperations[] = array( 'op' => 'delete', 'src' => $source );
- }
}
// Concatenate the chunks into one FS file
}
// Delete the sources if required
- if ( $deleteOperations ) {
- $opts = array( 'force' => true );
- $status->merge( $this->backend->doOperations( $deleteOperations, $opts ) );
+ if ( $flags & self::DELETE_SOURCE ) {
+ $status->merge( $this->quickPurgeBatch( $srcPaths ) );
}
- // Make sure status is OK, despite any $deleteOperations fatals
+ // Make sure status is OK, despite any quickPurgeBatch() fatals
$status->setResult( true );
return $status;
}
- /**
- * Remove a temporary file or mark it for garbage collection
- *
- * @param $virtualUrl String: the virtual URL returned by FileRepo::storeTemp()
- * @return Boolean: true on success, false on failure
- */
- public function freeTemp( $virtualUrl ) {
- $this->assertWritableRepo(); // fail out if read-only
-
- $temp = "mwrepo://{$this->name}/temp";
- if ( substr( $virtualUrl, 0, strlen( $temp ) ) != $temp ) {
- wfDebug( __METHOD__.": Invalid temp virtual URL\n" );
- return false;
- }
- $path = $this->resolveVirtualUrl( $virtualUrl );
-
- return $this->cleanupBatch( array( $path ), self::SKIP_LOCKING )->isOK();
- }
-
/**
* Copy or move a file either from a storage path, virtual URL,
* or FS path, into this repository at the specified destination location.
return wfMessageFallback( 'shared-repo-name-' . $this->name, 'shared-repo' )->text();
}
+ /**
+ * Get the portion of the file that contains the origin file name.
+ * If that name is too long, then the name "thumbnail.<ext>" will be given.
+ *
+ * @param $name string
+ * @return string
+ */
+ public function nameForThumb( $name ) {
+ if ( strlen( $name ) > $this->abbrvThreshold ) {
+ $ext = FileBackend::extensionFromPath( $name );
+ $name = ( $ext == '' ) ? 'thumbnail' : "thumbnail.$ext";
+ }
+ return $name;
+ }
+
/**
* Returns true if this the local file repository.
*
* @return string
*/
function thumbName( $params ) {
- return $this->generateThumbName( $this->getName(), $params );
+ $name = $this->repo ? $this->repo->nameForThumb( $this->getName() ) : $this->getName();
+ return $this->generateThumbName( $name, $params );
}
/**
}
} elseif ( $this->repo && $thumb->hasFile() && !$thumb->fileIsSource() ) {
// Copy the thumbnail from the file system into storage...
- $status = $this->repo->quickImport( $tmpThumbPath, $thumbPath );
+ $disposition = $this->getThumbDisposition( $thumbName );
+ $status = $this->repo->quickImport( $tmpThumbPath, $thumbPath, $disposition );
if ( $status->isOK() ) {
$thumb->setStoragePath( $thumbPath );
} else {
return is_object( $thumb ) ? $thumb : false;
}
+ /**
+ * @param $thumbName string Thumbnail name
+ * @return string Content-Disposition header value
+ */
+ function getThumbDisposition( $thumbName ) {
+ $fileName = $this->name; // file name to suggest
+ $thumbExt = FileBackend::extensionFromPath( $thumbName );
+ if ( $thumbExt != '' && $thumbExt !== $this->getExtension() ) {
+ $fileName .= ".$thumbExt";
+ }
+ return FileBackend::makeContentDisposition( 'inline', $fileName );
+ }
+
/**
* Hook into transform() to allow migration of thumbnail files
* STUB
$path = '/common/images/icons/' . $icon;
$filepath = $wgStyleDirectory . $path;
if ( file_exists( $filepath ) ) { // always FS
- return new ThumbnailImage( $this, $wgStylePath . $path, 120, 120 );
+ $params = array( 'width' => 120, 'height' => 120 );
+ return new ThumbnailImage( $this, $wgStylePath . $path, false, $params );
}
}
return null;
# Add the log entry
$log = new LogPage( 'upload' );
$action = $reupload ? 'overwrite' : 'upload';
- $log->addEntry( $action, $descTitle, $comment, array(), $user );
+ $logId = $log->addEntry( $action, $descTitle, $comment, array(), $user );
wfProfileIn( __METHOD__ . '-edit' );
if ( $descTitle->exists() ) {
wfRunHooks( 'NewRevisionFromEditComplete', array( $wikiPage, $nullRevision, $latest, $user ) );
$wikiPage->updateRevisionOn( $dbw, $nullRevision );
}
+ $dbw->update( 'logging', array( 'log_page' => $descTitle->getArticleID() ), array( 'log_id' => $logId ), __METHOD__ );
+
# Invalidate the cache for the description page
$descTitle->invalidateCache();
$descTitle->purgeSquid();
# There's already a log entry, so don't make a second RC entry
# Squid and file cache for the description page are purged by doEditContent.
$content = ContentHandler::makeContent( $pageText, $descTitle );
- $wikiPage->doEditContent( $content, $comment, EDIT_NEW | EDIT_SUPPRESS_RC, false, $user );
+ $status = $wikiPage->doEditContent( $content, $comment, EDIT_NEW | EDIT_SUPPRESS_RC, false, $user );
+
+ if ( isset( $status->value['revision'] ) ) {
+ $dbw->update( 'logging', array( 'log_page' => $status->value['revision']->getPage() ), array( 'log_id' => $logId ), __METHOD__ );
+ }
}
wfProfileOut( __METHOD__ . '-edit' );
return false;
}
- $targetRev = Revision::newFromTitle( $this->title );
+ $targetRev = Revision::newFromTitle( $this->title, false, Revision::READ_LATEST );
if ( !$targetRev ) {
wfDebug( __METHOD__.": target redirect already deleted, ignoring\n" );
return true;
if ( $flags & self::TRANSFORM_LATER ) {
wfDebug( __METHOD__ . ": Transforming later per flags.\n" );
- return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'],
- $scalerParams['clientHeight'], false );
+ $params = array(
+ 'width' => $scalerParams['clientWidth'],
+ 'height' => $scalerParams['clientHeight']
+ );
+ return new ThumbnailImage( $image, $dstUrl, false, $params );
}
# Try to make a target path for the thumbnail
} elseif ( $mto ) {
return $mto;
} else {
- return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'],
- $scalerParams['clientHeight'], $dstPath );
+ $params = array(
+ 'width' => $scalerParams['clientWidth'],
+ 'height' => $scalerParams['clientHeight']
+ );
+ return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
}
}
* client side
*
* @param $image File File associated with this thumbnail
- * @param $params array Array with scaler params
+ * @param $scalerParams array Array with scaler params
* @return ThumbnailImage
*
* @todo fixme: no rotation support
*/
- protected function getClientScalingThumbnailImage( $image, $params ) {
- return new ThumbnailImage( $image, $image->getURL(),
- $params['clientWidth'], $params['clientHeight'], null );
+ protected function getClientScalingThumbnailImage( $image, $scalerParams ) {
+ $params = array(
+ 'width' => $scalerParams['clientWidth'],
+ 'height' => $scalerParams['clientHeight']
+ );
+ return new ThumbnailImage( $image, $image->getURL(), null, $params );
}
/**
if ( !$this->normaliseParams( $image, $params ) ) {
return new TransformParameterError( $params );
}
- return new ThumbnailImage( $image, $image->getURL(), $params['width'],
- $params['height'], $image->getLocalRefPath() );
+ return new ThumbnailImage( $image, $image->getURL(), $image->getLocalRefPath(), $params );
}
}
}
if ( $flags & self::TRANSFORM_LATER ) {
- return new ThumbnailImage( $image, $dstUrl, $width, $height, $dstPath, $page );
+ $params = array(
+ 'width' => $width,
+ 'height' => $height,
+ 'page' => $page
+ );
+ return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
}
if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
wfHostname(), $retval, trim($err), $cmd ) );
return new MediaTransformError( 'thumbnail_error', $width, $height, $err );
} else {
- return new ThumbnailImage( $image, $dstUrl, $width, $height, $dstPath, $page );
+ $params = array(
+ 'width' => $width,
+ 'height' => $height,
+ 'page' => $page
+ );
+ return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
}
}
) {
continue;
}
- $tags[$tag] = intval( $h[0] / $h[1] )
+ $tags[$tag] = str_pad( intval( $h[0] / $h[1] ), 2, '0', STR_PAD_LEFT )
. ':' . str_pad( intval( $m[0] / $m[1] ), 2, '0', STR_PAD_LEFT )
. ':' . str_pad( intval( $s[0] / $s[1] ), 2, '0', STR_PAD_LEFT );
return false;
}
$url = $script . '&' . wfArrayToCGI( $this->getScriptParams( $params ) );
- $page = isset( $params['page'] ) ? $params['page'] : false;
if( $image->mustRender() || $params['width'] < $image->getWidth() ) {
- return new ThumbnailImage( $image,
- $url, $params['width'], $params['height'], false, $page );
+ return new ThumbnailImage( $image, $url, false, $params );
}
}
* Get a thumbnail object from a file and parameters.
* If $path is set to null, the output file is treated as a source copy.
* If $path is set to false, no output file will be created.
+ * $parameters should include, as a minimum, (file) 'width' and 'height'.
+ * It may also include a 'page' parameter for multipage files.
*
* @param $file File object
* @param $url String: URL path to the thumb
- * @param $width Integer: file's width
- * @param $height Integer: file's height
* @param $path String|bool|null: filesystem path to the thumb
- * @param $page Integer: page number, for multipage files
+ * @param $parameters Array: Associative array of parameters
* @private
*/
- function __construct( $file, $url, $width, $height, $path = false, $page = false ) {
+ function __construct( $file, $url, $path = false, $parameters = array() ) {
+ # Previous parameters:
+ # $file, $url, $width, $height, $path = false, $page = false
+
+ if( is_array( $parameters ) ){
+ $defaults = array(
+ 'page' => false
+ );
+ $actualParams = $parameters + $defaults;
+ } else {
+ # Using old format, should convert. Later a warning could be added here.
+ $numArgs = func_num_args();
+ $actualParams = array(
+ 'width' => $path,
+ 'height' => $parameters,
+ 'page' => ( $numArgs > 5 ) ? func_get_arg( 5 ) : false
+ );
+ $path = ( $numArgs > 4 ) ? func_get_arg( 4 ) : false;
+ }
+
$this->file = $file;
$this->url = $url;
+ $this->path = $path;
+
# These should be integers when they get here.
# If not, there's a bug somewhere. But let's at
# least produce valid HTML code regardless.
- $this->width = round( $width );
- $this->height = round( $height );
- $this->path = $path;
- $this->page = $page;
+ $this->width = round( $actualParams['width'] );
+ $this->height = round( $actualParams['height'] );
+
+ $this->page = $actualParams['page'];
}
/**
$physicalHeight = $params['physicalHeight'];
if ( $flags & self::TRANSFORM_LATER ) {
- return new ThumbnailImage( $image, $dstUrl, $clientWidth, $clientHeight, $dstPath );
+ return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
}
if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
$srcPath = $image->getLocalRefPath();
$status = $this->rasterize( $srcPath, $dstPath, $physicalWidth, $physicalHeight );
if( $status === true ) {
- return new ThumbnailImage( $image, $dstUrl, $clientWidth, $clientHeight, $dstPath );
+ return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
} else {
return $status; // MediaTransformError
}
* @ingroup Cache
*/
class APCBagOStuff extends BagOStuff {
-
/**
* @param $key string
* @return mixed
$val = apc_fetch( $key );
if ( is_string( $val ) ) {
- $val = unserialize( $val );
+ if ( $this->isInteger( $val ) ) {
+ $val = intval( $val );
+ } else {
+ $val = unserialize( $val );
+ }
}
return $val;
* @return bool
*/
public function set( $key, $value, $exptime = 0 ) {
- apc_store( $key, serialize( $value ), $exptime );
+ if ( !$this->isInteger( $value ) ) {
+ $value = serialize( $value );
+ }
+
+ apc_store( $key, $value, $exptime );
return true;
}
return true;
}
+ public function incr( $key, $value = 1 ) {
+ return apc_inc( $key, $value );
+ }
+
+ public function decr( $key, $value = 1 ) {
+ return apc_dec( $key, $value );
+ }
+
/**
* @return Array
*/
return $keys;
}
}
-
}
/**
+ * Increase stored value of $key by $value while preserving its TTL
* @param $key String: Key to increase
* @param $value Integer: Value to add to $key (Default 1)
* @return null if lock is not possible else $key value increased by $value
- * @return bool success
+ * @return integer
*/
public function incr( $key, $value = 1 ) {
if ( !$this->lock( $key ) ) {
}
/**
+ * Decrease stored value of $key by $value while preserving its TTL
* @param $key String
* @param $value Integer
- * @return bool success
+ * @return integer
*/
public function decr( $key, $value = 1 ) {
return $this->incr( $key, - $value );
return $exptime;
}
}
+
+ /**
+ * Check if a value is an integer
+ *
+ * @param $value mixed
+ * @return bool
+ */
+ protected function isInteger( $value ) {
+ return ( is_int( $value ) || ctype_digit( $value ) );
+ }
}
$params['dir'] = wfTempDir();
}
- $this->mFile = $params['dir']."/mw-cache-" . wfWikiID();
- $this->mFile .= '.db';
+ $this->mFile = $params['dir'] . '/mw-cache-' . wfWikiID() . '.db';
wfDebug( __CLASS__ . ": using cache file {$this->mFile}\n" );
$this->mHandler = $wgDBAhandler;
}
*
* @return string
*/
- function encode( $value, $expiry ) {
+ protected function encode( $value, $expiry ) {
# Convert to absolute time
$expiry = $this->convertExpiry( $expiry );
* @param $blob string
* @return array list containing value first and expiry second
*/
- function decode( $blob ) {
+ protected function decode( $blob ) {
if ( !is_string( $blob ) ) {
return array( null, 0 );
} else {
/**
* @return resource
*/
- function getReader() {
+ protected function getReader() {
if ( file_exists( $this->mFile ) ) {
$handle = dba_open( $this->mFile, 'rl', $this->mHandler );
} else {
/**
* @return resource
*/
- function getWriter() {
+ protected function getWriter() {
$handle = dba_open( $this->mFile, 'cl', $this->mHandler );
if ( !$handle ) {
* @param $key string
* @return mixed|null|string
*/
- function get( $key ) {
+ public function get( $key ) {
wfProfileIn( __METHOD__ );
wfDebug( __METHOD__ . "($key)\n" );
* @param $exptime int
* @return bool
*/
- function set( $key, $value, $exptime = 0 ) {
+ public function set( $key, $value, $exptime = 0 ) {
wfProfileIn( __METHOD__ );
wfDebug( __METHOD__ . "($key)\n" );
* @param $time int
* @return bool
*/
- function delete( $key, $time = 0 ) {
+ public function delete( $key, $time = 0 ) {
wfProfileIn( __METHOD__ );
wfDebug( __METHOD__ . "($key)\n" );
* @param $exptime int
* @return bool
*/
- function add( $key, $value, $exptime = 0 ) {
+ public function add( $key, $value, $exptime = 0 ) {
wfProfileIn( __METHOD__ );
$blob = $this->encode( $value, $exptime );
if ( !$ret ) {
list( $value, $expiry ) = $this->decode( dba_fetch( $key, $handle ) );
- if ( $expiry < time() ) {
+ if ( $expiry && $expiry < time() ) {
# Yes expired, delete and try again
dba_delete( $key, $handle );
$ret = dba_insert( $key, $blob, $handle );
}
/**
- * @return Array
+ * @param $key string
+ * @param $step integer
+ * @return integer|bool
*/
+ public function incr( $key, $step = 1 ) {
+ wfProfileIn( __METHOD__ );
+
+ $handle = $this->getWriter();
+
+ if ( !$handle ) {
+ wfProfileOut( __METHOD__ );
+ return false;
+ }
+
+ list( $value, $expiry ) = $this->decode( dba_fetch( $key, $handle ) );
+ if ( !is_null( $value ) ) {
+ if ( $expiry && $expiry < time() ) {
+ # Key is expired, delete it
+ dba_delete( $key, $handle );
+ wfDebug( __METHOD__ . ": $key expired\n" );
+ $value = null;
+ } else {
+ $value += $step;
+ $blob = $this->encode( $value, $expiry );
+
+ $ret = dba_replace( $key, $blob, $handle );
+ $value = $ret ? $value : null;
+ }
+ }
+
+ dba_close( $handle );
+
+ wfProfileOut( __METHOD__ );
+
+ return is_null( $value ) ? false : (int)$value;
+ }
+
function keys() {
$reader = $this->getReader();
$k1 = dba_firstkey( $reader );
return $result;
}
}
-
<?php
-/*
+/**
* Session storage in object cache.
*
* This program is free software; you can redistribute it and/or modify
* @file
* @ingroup Cache
*/
+
+/**
+ * Session storage in object cache.
+ * Used if $wgSessionsInObjectCache is true.
+ *
+ * @ingroup Cache
+ */
class ObjectCacheSessionHandler {
/**
* Install a session handler for the current web request
}
/**
- * Shutdown function. See the comment inside ObjectCacheSessionHandler::install
+ * Shutdown function. See the comment inside ObjectCacheSessionHandler::install
* for rationale.
*/
static function handleShutdown() {
<?php
+/**
+ * Object caching using Redis (http://redis.io/).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
class RedisBagOStuff extends BagOStuff {
protected $connectTimeout, $persistent, $password, $automaticFailover;
protected $servers;
/**
- * A cache of Redis objects, representing connections to Redis servers.
+ * A cache of Redis objects, representing connections to Redis servers.
* The key is the server name.
*/
protected $conns = array();
/**
- * An array listing "dead" servers which have had a connection error in
- * the past. Servers are marked dead for a limited period of time, to
+ * An array listing "dead" servers which have had a connection error in
+ * the past. Servers are marked dead for a limited period of time, to
* avoid excessive overhead from repeated connection timeouts. The key in
- * the array is the server name, the value is the UNIX timestamp at which
+ * the array is the server name, the value is the UNIX timestamp at which
* the server is resurrected.
*/
protected $deadServers = array();
/**
* Construct a RedisBagOStuff object. Parameters are:
*
- * - servers: An array of server names. A server name may be a hostname,
+ * - servers: An array of server names. A server name may be a hostname,
* a hostname/port combination or the absolute path of a UNIX socket.
- * If a hostname is specified but no port, the standard port number
+ * If a hostname is specified but no port, the standard port number
* 6379 will be used. Required.
*
* - connectTimeout: The timeout for new connections, in seconds. Optional,
* - persistent: Set this to true to allow connections to persist across
* multiple web requests. False by default.
*
- * - password: The authentication password, will be sent to Redis in
+ * - password: The authentication password, will be sent to Redis in
* clear text. Optional, if it is unspecified, no AUTH command will be
* sent.
*
* - automaticFailover: If this is false, then each key will be mapped to
* a single server, and if that server is down, any requests for that key
* will fail. If this is true, a connection failure will cause the client
- * to immediately try the next server in the list (as determined by a
- * consistent hashing algorithm). True by default. This has the
- * potential to create consistency issues if a server is slow enough to
+ * to immediately try the next server in the list (as determined by a
+ * consistent hashing algorithm). True by default. This has the
+ * potential to create consistency issues if a server is slow enough to
* flap, for example if it is in swap death.
*/
function __construct( $params ) {
}
$this->servers = $params['servers'];
- $this->connectTimeout = isset( $params['connectTimeout'] )
+ $this->connectTimeout = isset( $params['connectTimeout'] )
? $params['connectTimeout'] : 1;
$this->persistent = !empty( $params['persistent'] );
if ( isset( $params['password'] ) ) {
$result = false;
$this->handleException( $server, $e );
}
-
+
$this->logRequest( 'set', $key, $server, $result );
wfProfileOut( __METHOD__ );
return $result;
}
/**
- * Non-atomic implementation of replace(). Could perhaps be done atomically
+ * Non-atomic implementation of replace(). Could perhaps be done atomically
* with WATCH or scripting, but this function is rarely used.
*/
public function replace( $key, $value, $expiry = 0 ) {
$result = false;
$this->handleException( $server, $e );
}
-
+
$this->logRequest( 'replace', $key, $server, $result );
wfProfileOut( __METHOD__ );
return $result;
}
/**
- * Non-atomic implementation of incr().
+ * Non-atomic implementation of incr().
*
- * Probably all callers actually want incr() to atomically initialise
- * values to zero if they don't exist, as provided by the Redis INCR
- * command. But we are constrained by the memcached-like interface to
- * return null in that case. Once the key exists, further increments are
+ * Probably all callers actually want incr() to atomically initialise
+ * values to zero if they don't exist, as provided by the Redis INCR
+ * command. But we are constrained by the memcached-like interface to
+ * return null in that case. Once the key exists, further increments are
* atomic.
*/
public function incr( $key, $value = 1 ) {
$result = false;
$this->handleException( $server, $e );
}
-
+
$this->logRequest( 'incr', $key, $server, $result );
wfProfileOut( __METHOD__ );
return $result;
if ( substr( $server, 0, 1 ) === '/' ) {
// UNIX domain socket
- // These are required by the redis extension to start with a slash, but
+ // These are required by the redis extension to start with a slash, but
// we still need to set the port to a special value to make it work.
$host = $server;
$port = 0;
/**
* The redis extension throws an exception in response to various read, write
- * and protocol errors. Sometimes it also closes the connection, sometimes
- * not. The safest response for us is to explicitly destroy the connection
+ * and protocol errors. Sometimes it also closes the connection, sometimes
+ * not. The safest response for us is to explicitly destroy the connection
* object and let it be reopened during the next request.
*/
protected function handleException( $server, $e ) {
* Send information about a single request to the debug log
*/
public function logRequest( $method, $key, $server, $result ) {
- $this->debug( "$method $key on $server: " .
+ $this->debug( "$method $key on $server: " .
( $result === false ? "failure" : "success" ) );
}
}
$val = xcache_get( $key );
if ( is_string( $val ) ) {
- $val = unserialize( $val );
+ if ( $this->isInteger( $val ) ) {
+ $val = intval( $val );
+ } else {
+ $val = unserialize( $val );
+ }
}
return $val;
* @return bool
*/
public function set( $key, $value, $expire = 0 ) {
- xcache_set( $key, serialize( $value ), $expire );
+ if ( !$this->isInteger( $value ) ) {
+ $value = serialize( $value );
+ }
+
+ xcache_set( $key, $value, $expire );
return true;
}
xcache_unset( $key );
return true;
}
-}
+ public function incr( $key, $value = 1 ) {
+ return xcache_inc( $key, $value );
+ }
+
+ public function decr( $key, $value = 1 ) {
+ return xcache_dec( $key, $value );
+ }
+}
<?php
-
/**
- * @todo document
+ * Parser cache specific expiry check.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* @file
* @ingroup Parser
*/
+
+/**
+ * Parser cache specific expiry check.
+ *
+ * @ingroup Parser
+ */
class CacheTime {
var $mVersion = Parser::VERSION, # Compatibility check
version_compare( $this->mVersion, Parser::VERSION, "lt" );
}
-}
\ No newline at end of file
+}
public function __construct( $conf = array() ) {
$this->mConf = $conf;
$this->mUrlProtocols = wfUrlProtocols();
- $this->mExtLinkBracketedRegex = '/\[((' . $this->mUrlProtocols . ')'.
+ $this->mExtLinkBracketedRegex = '/\[(((?i)' . $this->mUrlProtocols . ')'.
self::EXT_LINK_URL_CLASS.'+)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F]*?)\]/Su';
if ( isset( $conf['preprocessorClass'] ) ) {
$this->mPreprocessorClass = $conf['preprocessorClass'];
'!(?: # Start cases
(<a[ \t\r\n>].*?</a>) | # m[1]: Skip link text
(<.*?>) | # m[2]: Skip stuff inside HTML elements' . "
- (\\b(?:$prots)$urlChar+) | # m[3]: Free external links" . '
+ (\\b(?i:$prots)$urlChar+) | # m[3]: Free external links" . '
(?:RFC|PMID)\s+([0-9]+) | # m[4]: RFC or PMID, capture number
ISBN\s+(\b # m[5]: ISBN, capture number
(?: 97[89] [\ \-]? )? # optional 13-digit ISBN prefix
# Don't allow internal links to pages containing
# PROTO: where PROTO is a valid URL protocol; these
# should be external links.
- if ( preg_match( '/^(?:' . $this->mUrlProtocols . ')/', $m[1] ) ) {
+ if ( preg_match( '/^(?i:' . $this->mUrlProtocols . ')/', $m[1] ) ) {
$s .= $prefix . '[[' . $line ;
wfProfileOut( __METHOD__."-misc" );
continue;
* @return String: less-or-more HTML with NOPARSE bits
*/
function armorLinks( $text ) {
- return preg_replace( '/\b(' . $this->mUrlProtocols . ')/',
+ return preg_replace( '/\b((?i)' . $this->mUrlProtocols . ')/',
"{$this->mUniqPrefix}NOPARSE$1", $text );
}
$paramName = 'no-link';
$value = true;
$validated = true;
- } elseif ( preg_match( "/^$prots/", $value ) ) {
- if ( preg_match( "/^($prots)$chars+$/u", $value, $m ) ) {
+ } elseif ( preg_match( "/^(?i)$prots/", $value ) ) {
+ if ( preg_match( "/^((?i)$prots)$chars+$/u", $value, $m ) ) {
$paramName = 'link-url';
$this->mOutput->addExternalLink( $value );
if ( $this->mOptions->getExternalLinkTarget() ) {
# @todo FIXME: Not tolerant to blank link text
# I.E. [http://www.mediawiki.org] will render as [1] or something depending
# on how many empty links there are on the page - need to figure that out.
- $text = preg_replace( '/\[(?:' . $this->mUrlProtocols . ')([^ ]+?) ([^[]+)\]/', '$2', $text );
+ $text = preg_replace( '/\[(?i:' . $this->mUrlProtocols . ')([^ ]+?) ([^[]+)\]/', '$2', $text );
# Parse wikitext quotes (italics & bold)
$text = $this->doQuotes( $text );
# Don't allow internal links to pages containing
# PROTO: where PROTO is a valid URL protocol; these
# should be external links.
- if( preg_match('/^\b(?:' . wfUrlProtocols() . ')/', $titleText) ) {
+ if( preg_match('/^\b(?i:' . wfUrlProtocols() . ')/', $titleText) ) {
wfProfileOut( __METHOD__ );
return $wt;
}
* @param $args array
* @return PPCustomFrame_HipHop
*/
- function newCustomFrame( array $args ) {
+ function newCustomFrame( $args ) {
return new PPCustomFrame_HipHop( $this, $args );
}
* @throws MWException
* @return PPNode_HipHop_Tree
*/
- function preprocessToObj( string $text, int $flags = 0 ) {
+ function preprocessToObj( $text, $flags = 0 ) {
wfProfileIn( __METHOD__ );
// Check cache.
*
* @param $args PPNode_HipHop_Array|array|bool
* @param $title Title|bool
+ * @param $indexOffset A number subtracted from the index attributes of the arguments
*
* @throws MWException
* @return PPTemplateFrame_HipHop
*/
- function newChild( $args = false, $title = false ) {
+ function newChild( $args = false, $title = false, $indexOffset = 0 ) {
$namedArgs = array();
$numberedArgs = array();
if ( $title === false ) {
if ( !$title->isCssJsSubpage() && !$title->isCssOrJsPage() ) {
return null;
}
- $revision = Revision::newFromTitle( $title );
+ $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
if ( !$revision ) {
return null;
}
// We're dealing with a subclass that doesn't have a DB
return array();
}
-
+
$hash = $context->getHash();
if ( isset( $this->titleMtimes[$hash] ) ) {
return $this->titleMtimes[$hash];
$form->setSubmitTextMsg( $msg );
# Don't need to do anything if the form has been posted
- if( !$this->getRequest()->wasPosted() && $this->preErrors ){
+ if ( !$this->getRequest()->wasPosted() && $this->preErrors ) {
$s = HTMLForm::formatErrors( $this->preErrors );
- if( $s ){
+ if ( $s ) {
$form->addHeaderText( Html::rawElement(
'div',
array( 'class' => 'error' ),
* Get the HTMLForm descriptor array for the block form
* @return Array
*/
- protected function getFormFields(){
+ protected function getFormFields() {
global $wgBlockAllowsUTEdit;
$user = $this->getUser();
),
);
- if( self::canBlockEmail( $user ) ) {
+ if ( self::canBlockEmail( $user ) ) {
$a['DisableEmail'] = array(
'type' => 'check',
'label-message' => 'ipbemailban',
);
}
- if( $wgBlockAllowsUTEdit ){
+ if ( $wgBlockAllowsUTEdit ) {
$a['DisableUTEdit'] = array(
'type' => 'check',
'label-message' => 'ipb-disableusertalk',
);
# Allow some users to hide name from block log, blocklist and listusers
- if( $user->isAllowed( 'hideuser' ) ) {
+ if ( $user->isAllowed( 'hideuser' ) ) {
$a['HideUser'] = array(
'type' => 'check',
'label-message' => 'ipbhidename',
}
# Watchlist their user page? (Only if user is logged in)
- if( $user->isLoggedIn() ) {
+ if ( $user->isLoggedIn() ) {
$a['Watch'] = array(
'type' => 'check',
'label-message' => 'ipbwatchuser',
* @return Bool whether fields were altered (that is, whether the target is
* already blocked)
*/
- protected function maybeAlterFormDefaults( &$fields ){
+ protected function maybeAlterFormDefaults( &$fields ) {
# This will be overwritten by request data
$fields['Target']['default'] = (string)$this->target;
$block = Block::newFromTarget( $this->target );
- if( $block instanceof Block && !$block->mAuto # The block exists and isn't an autoblock
+ if ( $block instanceof Block && !$block->mAuto # The block exists and isn't an autoblock
&& ( $this->type != Block::TYPE_RANGE # The block isn't a rangeblock
|| $block->getTarget() == $this->target ) # or if it is, the range is what we're about to block
)
$fields['CreateAccount']['default'] = $block->prevents( 'createaccount' );
$fields['AutoBlock']['default'] = $block->isAutoblocking();
- if( isset( $fields['DisableEmail'] ) ){
+ if ( isset( $fields['DisableEmail'] ) ) {
$fields['DisableEmail']['default'] = $block->prevents( 'sendemail' );
}
- if( isset( $fields['HideUser'] ) ){
+ if ( isset( $fields['HideUser'] ) ) {
$fields['HideUser']['default'] = $block->mHideName;
}
- if( isset( $fields['DisableUTEdit'] ) ){
+ if ( isset( $fields['DisableUTEdit'] ) ) {
$fields['DisableUTEdit']['default'] = $block->prevents( 'editownusertalk' );
}
- $fields['Reason']['default'] = $block->mReason;
+ // If the username was hidden (ipb_deleted == 1), don't show the reason
+ // unless this user also has rights to hideuser: Bug 35839
+ if ( !$block->mHideName || $this->getUser()->isAllowed( 'hideuser' ) ) {
+ $fields['Reason']['default'] = $block->mReason;
+ } else {
+ $fields['Reason']['default'] = '';
+ }
- if( $this->getRequest()->wasPosted() ){
+ if ( $this->getRequest()->wasPosted() ) {
# Ok, so we got a POST submission asking us to reblock a user. So show the
# confirm checkbox; the user will only see it if they haven't previously
$fields['Confirm']['type'] = 'check';
$fields['Confirm']['default'] = 1;
}
- if( $block->mExpiry == 'infinity' ) {
+ if ( $block->mExpiry == 'infinity' ) {
$fields['Expiry']['default'] = 'infinite';
} else {
$fields['Expiry']['default'] = wfTimestamp( TS_RFC2822, $block->mExpiry );
}
# We always need confirmation to do HideUser
- if( $this->requestedHideUser ){
+ if ( $this->requestedHideUser ) {
$fields['Confirm']['type'] = 'check';
unset( $fields['Confirm']['default'] );
$this->preErrors[] = 'ipb-confirmhideuser';
}
# Or if the user is trying to block themselves
- if( (string)$this->target === $this->getUser()->getName() ){
+ if ( (string)$this->target === $this->getUser()->getName() ) {
$fields['Confirm']['type'] = 'check';
unset( $fields['Confirm']['default'] );
$this->preErrors[] = 'ipb-blockingself';
* Add header elements like block log entries, etc.
* @return String
*/
- protected function preText(){
+ protected function preText() {
$this->getOutput()->addModules( 'mediawiki.special.block' );
$text = $this->msg( 'blockiptext' )->parse();
$otherBlockMessages = array();
- if( $this->target !== null ) {
+ if ( $this->target !== null ) {
# Get other blocks, i.e. from GlobalBlocking or TorBlock extension
wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockMessages, $this->target ) );
- if( count( $otherBlockMessages ) ) {
+ if ( count( $otherBlockMessages ) ) {
$s = Html::rawElement(
'h2',
array(),
$list = '';
- foreach( $otherBlockMessages as $link ) {
+ foreach ( $otherBlockMessages as $link ) {
$list .= Html::rawElement( 'li', array(), $link ) . "\n";
}
* Add footer elements to the form
* @return string
*/
- protected function postText(){
+ protected function postText() {
$links = array();
# Link to the user's contributions, if applicable
- if( $this->target instanceof User ){
+ if ( $this->target instanceof User ) {
$contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() );
$links[] = Linker::link(
$contribsPage,
}
# Link to unblock the specified user, or to a blank unblock form
- if( $this->target instanceof User ) {
+ if ( $this->target instanceof User ) {
$message = $this->msg( 'ipb-unblock-addr', wfEscapeWikiText( $this->target->getName() ) )->parse();
$list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() );
} else {
);
$userTitle = self::getTargetUserTitle( $this->target );
- if( $userTitle ){
+ if ( $userTitle ) {
# Get relevant extracts from the block and suppression logs, if possible
$out = '';
$text .= $out;
# Add suppression block entries if allowed
- if( $user->isAllowed( 'suppressionlog' ) ) {
+ if ( $user->isAllowed( 'suppressionlog' ) ) {
LogEventsList::showLogExtract(
$out,
'suppress',
* @return Title|null
*/
protected static function getTargetUserTitle( $target ) {
- if( $target instanceof User ) {
+ if ( $target instanceof User ) {
return $target->getUserPage();
} elseif ( IP::isIPAddress( $target ) ) {
return Title::makeTitleSafe( NS_USER, $target );
* @param $request WebRequest optionally try and get data from a request too
* @return array( User|string|null, Block::TYPE_ constant|null )
*/
- public static function getTargetAndType( $par, WebRequest $request = null ){
+ public static function getTargetAndType( $par, WebRequest $request = null ) {
$i = 0;
$target = null;
- while( true ){
- switch( $i++ ){
+ while( true ) {
+ switch( $i++ ) {
case 0:
# The HTMLForm will check wpTarget first and only if it doesn't get
# a value use the default, which will be generated from the options
# below; so this has to have a higher precedence here than $par, or
# we could end up with different values in $this->target and the HTMLForm!
- if( $request instanceof WebRequest ){
+ if ( $request instanceof WebRequest ) {
$target = $request->getText( 'wpTarget', null );
}
break;
$target = $par;
break;
case 2:
- if( $request instanceof WebRequest ){
+ if ( $request instanceof WebRequest ) {
$target = $request->getText( 'ip', null );
}
break;
case 3:
# B/C @since 1.18
- if( $request instanceof WebRequest ){
+ if ( $request instanceof WebRequest ) {
$target = $request->getText( 'wpBlockAddress', null );
}
break;
list( $target, $type ) = Block::parseTarget( $target );
- if( $type !== null ){
+ if ( $type !== null ) {
return array( $target, $type );
}
}
list( $target, $type ) = self::getTargetAndType( $value );
- if( $type == Block::TYPE_USER ){
+ if ( $type == Block::TYPE_USER ) {
# TODO: why do we not have a User->exists() method?
- if( !$target->getId() ){
+ if ( !$target->getId() ) {
return $form->msg( 'nosuchusershort',
wfEscapeWikiText( $target->getName() ) );
}
return $form->msg( 'badaccess', $status );
}
- } elseif( $type == Block::TYPE_RANGE ){
+ } elseif ( $type == Block::TYPE_RANGE ) {
list( $ip, $range ) = explode( '/', $target, 2 );
- if( ( IP::isIPv4( $ip ) && $wgBlockCIDRLimit['IPv4'] == 32 )
+ if ( ( IP::isIPv4( $ip ) && $wgBlockCIDRLimit['IPv4'] == 32 )
|| ( IP::isIPv6( $ip ) && $wgBlockCIDRLimit['IPv6'] == 128 ) )
{
# Range block effectively disabled
return $form->msg( 'range_block_disabled' );
}
- if( ( IP::isIPv4( $ip ) && $range > 32 )
+ if ( ( IP::isIPv4( $ip ) && $range > 32 )
|| ( IP::isIPv6( $ip ) && $range > 128 ) )
{
# Dodgy range
return $form->msg( 'ip_range_invalid' );
}
- if( IP::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) {
+ if ( IP::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) {
return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv4'] );
}
- if( IP::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) {
+ if ( IP::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) {
return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv6'] );
}
- } elseif( $type == Block::TYPE_IP ){
+ } elseif ( $type == Block::TYPE_IP ) {
# All is well
} else {
return $form->msg( 'badipaddress' );
* @param $context IContextSource
* @return Bool|String
*/
- public static function processForm( array $data, IContextSource $context ){
+ public static function processForm( array $data, IContextSource $context ) {
global $wgBlockAllowsUTEdit;
$performer = $context->getUser();
$data['Confirm'] = !in_array( $data['Confirm'], array( '', '0', null, false ), true );
list( $target, $type ) = self::getTargetAndType( $data['Target'] );
- if( $type == Block::TYPE_USER ){
+ if ( $type == Block::TYPE_USER ) {
$user = $target;
$target = $user->getName();
$userId = $user->getId();
# since both $data['PreviousTarget'] and $target are normalized
# but $data['target'] gets overriden by (non-normalized) request variable
# from previous request.
- if( $target === $performer->getName() &&
+ if ( $target === $performer->getName() &&
( $data['PreviousTarget'] !== $target || !$data['Confirm'] ) )
{
return array( 'ipb-blockingself' );
}
- } elseif( $type == Block::TYPE_RANGE ){
+ } elseif ( $type == Block::TYPE_RANGE ) {
$userId = 0;
- } elseif( $type == Block::TYPE_IP ){
+ } elseif ( $type == Block::TYPE_IP ) {
$target = $target->getName();
$userId = 0;
} else {
return array( 'badipaddress' );
}
- if( ( strlen( $data['Expiry'] ) == 0) || ( strlen( $data['Expiry'] ) > 50 )
+ if ( ( strlen( $data['Expiry'] ) == 0) || ( strlen( $data['Expiry'] ) > 50 )
|| !self::parseExpiryInput( $data['Expiry'] ) )
{
return array( 'ipb_expiry_invalid' );
}
- if( !isset( $data['DisableEmail'] ) ){
+ if ( !isset( $data['DisableEmail'] ) ) {
$data['DisableEmail'] = false;
}
# If the user has done the form 'properly', they won't even have been given the
# option to suppress-block unless they have the 'hideuser' permission
- if( !isset( $data['HideUser'] ) ){
+ if ( !isset( $data['HideUser'] ) ) {
$data['HideUser'] = false;
}
- if( $data['HideUser'] ) {
- if( !$performer->isAllowed('hideuser') ){
+ if ( $data['HideUser'] ) {
+ if ( !$performer->isAllowed('hideuser') ) {
# this codepath is unreachable except by a malicious user spoofing forms,
# or by race conditions (user has oversight and sysop, loads block form,
# and is de-oversighted before submission); so need to fail completely
}
# Recheck params here...
- if( $type != Block::TYPE_USER ) {
+ if ( $type != Block::TYPE_USER ) {
$data['HideUser'] = false; # IP users should not be hidden
- } elseif( !in_array( $data['Expiry'], array( 'infinite', 'infinity', 'indefinite' ) ) ) {
+ } elseif ( !in_array( $data['Expiry'], array( 'infinite', 'infinity', 'indefinite' ) ) ) {
# Bad expiry.
return array( 'ipb_expiry_temp' );
- } elseif( $user->getEditCount() > self::HIDEUSER_CONTRIBLIMIT ) {
+ } elseif ( $user->getEditCount() > self::HIDEUSER_CONTRIBLIMIT ) {
# Typically, the user should have a handful of edits.
# Disallow hiding users with many edits for performance.
return array( 'ipb_hide_invalid' );
- } elseif( !$data['Confirm'] ){
+ } elseif ( !$data['Confirm'] ) {
return array( 'ipb-confirmhideuser' );
}
}
$block->isAutoblocking( $data['AutoBlock'] );
$block->mHideName = $data['HideUser'];
- if( !wfRunHooks( 'BlockIp', array( &$block, &$performer ) ) ) {
+ if ( !wfRunHooks( 'BlockIp', array( &$block, &$performer ) ) ) {
return array( 'hookaborted' );
}
# Try to insert block. Is there a conflicting block?
$status = $block->insert();
- if( !$status ) {
+ if ( !$status ) {
# Show form unless the user is already aware of this...
- if( !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data )
+ if ( !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data )
&& $data['PreviousTarget'] !== $target ) )
{
return array( array( 'ipb_already_blocked', $block->getTarget() ) );
# be sure the user is blocked by now it should work for our purposes
$currentBlock = Block::newFromTarget( $target );
- if( $block->equals( $currentBlock ) ) {
+ if ( $block->equals( $currentBlock ) ) {
return array( array( 'ipb_already_blocked', $block->getTarget() ) );
}
# If the name was hidden and the blocking user cannot hide
# names, then don't allow any block changes...
- if( $currentBlock->mHideName && !$performer->isAllowed( 'hideuser' ) ) {
+ if ( $currentBlock->mHideName && !$performer->isAllowed( 'hideuser' ) ) {
return array( 'cant-see-hidden-user' );
}
$logaction = 'reblock';
# Unset _deleted fields if requested
- if( $currentBlock->mHideName && !$data['HideUser'] ) {
+ if ( $currentBlock->mHideName && !$data['HideUser'] ) {
RevisionDeleteUser::unsuppressUserName( $target, $userId );
}
# If hiding/unhiding a name, this should go in the private logs
- if( (bool)$currentBlock->mHideName ){
+ if ( (bool)$currentBlock->mHideName ) {
$data['HideUser'] = true;
}
}
wfRunHooks( 'BlockIpComplete', array( $block, $performer ) );
# Set *_deleted fields if requested
- if( $data['HideUser'] ) {
+ if ( $data['HideUser'] ) {
RevisionDeleteUser::suppressUserName( $target, $userId );
}
# Can't watch a rangeblock
- if( $type != Block::TYPE_RANGE && $data['Watch'] ) {
+ if ( $type != Block::TYPE_RANGE && $data['Watch'] ) {
$performer->addWatch( Title::makeTitle( NS_USER, $target ) );
}
* the wiki's content language
* @return Array
*/
- public static function getSuggestedDurations( $lang = null ){
+ public static function getSuggestedDurations( $lang = null ) {
$a = array();
$msg = $lang === null
? wfMessage( 'ipboptions' )->inContentLanguage()->text()
: wfMessage( 'ipboptions' )->inLanguage( $lang )->text();
- if( $msg == '-' ){
+ if ( $msg == '-' ) {
return array();
}
- foreach( explode( ',', $msg ) as $option ) {
- if( strpos( $option, ':' ) === false ){
+ foreach ( explode( ',', $msg ) as $option ) {
+ if ( strpos( $option, ':' ) === false ) {
$option = "$option:$option";
}
*/
public static function parseExpiryInput( $expiry ) {
static $infinity;
- if( $infinity == null ){
+ if ( $infinity == null ) {
$infinity = wfGetDB( DB_SLAVE )->getInfinity();
}
$user = User::newFromName( $user );
}
- if( $performer->isBlocked() ){
- if( $user instanceof User && $user->getId() == $performer->getId() ) {
+ if ( $performer->isBlocked() ) {
+ if ( $user instanceof User && $user->getId() == $performer->getId() ) {
# User is trying to unblock themselves
if ( $performer->isAllowed( 'unblockself' ) ) {
return true;
* reader for this block, to provide more information in the logs
* @param $data Array from HTMLForm data
* @param $type Block::TYPE_ constant (USER, RANGE, or IP)
- * @return array
+ * @return string
*/
protected static function blockLogFlags( array $data, $type ) {
global $wgBlockAllowsUTEdit;
$flags = array();
- # when blocking a user the option 'anononly' is not available/has no effect -> do not write this into log
- if( !$data['HardBlock'] && $type != Block::TYPE_USER ){
+ # when blocking a user the option 'anononly' is not available/has no effect
+ # -> do not write this into log
+ if ( !$data['HardBlock'] && $type != Block::TYPE_USER ) {
// For grepping: message block-log-flags-anononly
$flags[] = 'anononly';
}
- if( $data['CreateAccount'] ){
+ if ( $data['CreateAccount'] ) {
// For grepping: message block-log-flags-nocreate
$flags[] = 'nocreate';
}
# Same as anononly, this is not displayed when blocking an IP address
- if( !$data['AutoBlock'] && $type == Block::TYPE_USER ){
+ if ( !$data['AutoBlock'] && $type == Block::TYPE_USER ) {
// For grepping: message block-log-flags-noautoblock
$flags[] = 'noautoblock';
}
- if( $data['DisableEmail'] ){
+ if ( $data['DisableEmail'] ) {
// For grepping: message block-log-flags-noemail
$flags[] = 'noemail';
}
- if( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ){
+ if ( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ) {
// For grepping: message block-log-flags-nousertalk
$flags[] = 'nousertalk';
}
- if( $data['HideUser'] ){
+ if ( $data['HideUser'] ) {
// For grepping: message block-log-flags-hiddenname
$flags[] = 'hiddenname';
}
* @return string
*/
public static function getDupeWarning( $dupes ) {
- global $wgOut;
- if( $dupes ) {
- $msg = '<gallery>';
- foreach( $dupes as $file ) {
- $title = $file->getTitle();
- $msg .= $title->getPrefixedText() .
- '|' . $title->getText() . "\n";
- }
- $msg .= '</gallery>';
- return '<li>' .
- wfMessage( 'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
- $wgOut->parse( $msg ) . "</li>\n";
- } else {
+ if ( !$dupes ) {
return '';
}
+
+ $gallery = new ImageGallery;
+ $gallery->setShowBytes( false );
+ foreach( $dupes as $file ) {
+ $gallery->add( $file->getTitle() );
+ }
+ return '<li>' .
+ wfMessage( 'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
+ $gallery->toHtml() . "</li>\n";
}
}
# DEFINE
UNIHAN_VER = '5.2.0'
-SF_MIRROR = 'cdnetworks-kr-2'
+SF_MIRROR = 'dfn'
SCIM_TABLES_VER = '0.5.10'
SCIM_PINYIN_VER = '0.5.91'
LIBTABE_VER = '0.2.3'
+ PHPArray( toCN ) \
+ '\n);\n\n$zh2SG = array(\n' \
+ PHPArray( toSG ) \
- + '\n);'
+ + '\n);\n'
f = open( os.path.join( '..', 'ZhConversion.php' ), 'wb', encoding = 'utf8' )
print ('Writing ZhConversion.php ... ')
分布于 分佈於
分布於 分佈於
想象 想像
+無線電視 無綫電視
+无线电视 無綫電視
+無線收費 無綫收費
+无线收费 無綫收費
+無線節目 無綫節目
+无线节目 無綫節目
+無線劇集 無綫劇集
+无线剧集 無綫劇集
+東鐵線 東鐵綫
+东铁线 東鐵綫
+觀塘線 觀塘綫
+观塘线 觀塘綫
+荃灣線 荃灣綫
+荃湾线 荃灣綫
+港島線 港島綫
+港岛线 港島綫
+東涌線 東涌綫
+东涌线 東涌綫
+將軍澳線 將軍澳綫
+将军澳线 將軍澳綫
+西鐵線 西鐵綫
+西铁线 西鐵綫
+馬鞍山線 馬鞍山綫
+马鞍山线 馬鞍山綫
+迪士尼線 迪士尼綫
+迪士尼线 迪士尼綫
+沙田至中環線 沙田至中環綫
+沙田至中环线 沙田至中環綫
+沙中線 沙中綫
+沙中线 沙中綫
+北環線 北環綫
+北环线 北環綫
+機場快線 機場快綫
+机场快线 機場快綫
+505線 505綫
+505线 505綫
+507線 507綫
+507线 507綫
+610線 610綫
+610线 610綫
+614線 614綫
+614线 614綫
+614P線 614P綫
+614P线 614P綫
+615線 615綫
+615线 615綫
+615P線 615P綫
+615P线 615P綫
+705線 705綫
+705线 705綫
+706線 706綫
+706线 706綫
+751線 751綫
+751线 751綫
+751P線 751P綫
+751P线 751P綫
+761P線 761P綫
+761P线 761P綫
$wgHooks['ArticleSaveComplete'][] = $this->mConverter;
}
- /**
- * Work around for right-to-left direction support in kk-arab and kk-cn
- *
- * @return bool
- */
- function isRTL() {
- $variant = $this->getPreferredVariant();
- if ( $variant == 'kk-arab' || $variant == 'kk-cn' ) {
- return true;
- } else {
- return parent::isRTL();
- }
- }
-
/**
* It fixes issue with ucfirst for transforming 'i' to 'İ'
*
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="two">n is 2</pluralRule>
</pluralRules>
+ <pluralRules locales="dsb">
+ <pluralRule count="one">n mod 100 is 1</pluralRule>
+ <pluralRule count="two">n mod 100 is 2</pluralRule>
+ <pluralRule count="few">n mod 100 in 3..4</pluralRule>
+ </pluralRules>
+ <pluralRules locales="cu">
+ <pluralRule count="one">n mod 10 is 1</pluralRule>
+ <pluralRule count="two">n mod 10 is 2</pluralRule>
+ <pluralRule count="few">n mod 10 in 3..4</pluralRule>
+ </pluralRules>
+ <!-- Plural form transformations
+ Based on this discussion: http://translatewiki.net/wiki/Thread:Support/New_plural_rules_for_Scots_Gaelic_(gd)
+ $forms[0] - 1
+ $forms[1] - 2
+ $forms[2] - 11
+ $forms[3] - 12
+ $forms[4] - 3-10, 13-19
+ $forms[5] - 0, 20, rest -->
+ <pluralRules locales="gd">
+ <pluralRule count="one">n is 1</pluralRule>
+ <pluralRule count="two">n is 2</pluralRule>
+ <pluralRule count="elevan">n is 11</pluralRule>
+ <pluralRule count="twelve">n is 12</pluralRule>
+ <pluralRule count="few">n in 3..10 or n in 13..19</pluralRule>
+ </pluralRules>
</plurals>
- <pluralRules locales="dsb">
- <pluralRule count="one">n mod 100 is 1</pluralRule>
- <pluralRule count="two">n mod 100 is 2</pluralRule>
- <pluralRule count="few">n mod 100 in 3..4</pluralRule>
- </pluralRules>
- <pluralRules locales="cu">
- <pluralRule count="one">n mod 10 is 1</pluralRule>
- <pluralRule count="two">n mod 10 is 2</pluralRule>
- <pluralRule count="few">n mod 10 in 3..4</pluralRule>
- </pluralRules>
- <!-- Plural form transformations
- Based on this discussion: http://translatewiki.net/wiki/Thread:Support/New_plural_rules_for_Scots_Gaelic_(gd)
- $forms[0] - 1
- $forms[1] - 2
- $forms[2] - 11
- $forms[3] - 12
- $forms[4] - 3-10, 13-19
- $forms[5] - 0, 20, rest -->
- <pluralRules locales="gd">
- <pluralRule count="one">n is 1</pluralRule>
- <pluralRule count="two">n is 2</pluralRule>
- <pluralRule count="elevan">n is 11</pluralRule>
- <pluralRule count="twelve">n is 12</pluralRule>
- <pluralRule count="few">n in 3..10 or n in 13..19</pluralRule>
- </pluralRules>
</supplementalData>
'newsectionsummary' => '/* $1 */ ܡܢܬܐ ܚܕܬܐ',
'rc-enhanced-expand' => 'ܚܘܝ ܐܪ̈ܝܟܬܐ (ܒܥܐ ܠܟ JavaScript)',
'rc-enhanced-hide' => 'ܛܫܝ ܐܪ̈ܝܟܬܐ',
+'rc-old-title' => 'ܐܬܒܪܝ ܫܪܫܐܝܬ ܐܝܟ "$1"',
# Recent changes linked
'recentchangeslinked' => 'ܫܘܚܠܦ̈ܐ ܕ̈ܡܝܐ',
'mywatchlist' => 'ܪ̈ܗܝܬܝ',
'watchlistfor2' => 'ܕ $1 $2',
'nowatchlist' => 'ܠܝܬ ܠܟ ܡܕܡ ܒܪ̈ܗܝܬܐ ܕܝܠܟ',
+'watchlistanontext' => '$1 ܠܚܙܝܐ ܐܘ ܫܚܠܦܬܐ ܕܦܐܬܬ̈ܐ ܒܪ̈ܗܝܬܟ.',
'watchnologin' => 'ܠܝܬܝܟ ܥܠܝܠܐ',
'watchnologintext' => 'ܐܠܨܐ ܕܬܗܘܐ [[Special:UserLogin|ܥܠܝܠܐ]] ܠܫܚܠܦܬܐ ܕܪ̈ܗܝܬܟ.',
'addwatch' => 'ܐܘܣܦ ܥܠ ܪ̈ܗܝܬܝ',
'createaccount' => 'افتح حساب',
'gotaccount' => "عندك حساب؟ '''$1'''.",
'gotaccountlink' => 'دخول',
+'userlogin-resetlink' => 'نسيت تفاصيل الدخول؟',
'createaccountmail' => 'بـ الايميل',
'createaccountreason' => 'السبب:',
'badretype' => 'كلمتين السر اللى كتبتهم مش زى بعضهم',
افتكر أن ملفات ال.css و ال.js بتستخدم حروف صغيرة فى العنوان ، مثلا {{ns:user}}:Foo/vector.css و مش {{ns:user}}:Foo/Vector.css.",
'updated' => '(متحدثة)',
'note' => "'''ملحوظه:'''",
-'previewnote' => "''' دى بروفه للصفحه بس،
-ولسه ما تسييفتش!'''",
+'previewnote' => "'''دى بروفه للصفحه بس.'''
+ولسه ما تسييفتش! ،",
'previewconflict' => 'البروفة دى بتبينلك فوق إزاى ح يكون شكل النص لو انت دوست على حفظ',
'session_fail_preview' => "'''ما قدرناش نحفظ التعديلات اللى قمت بيها نتيجة لضياع بيانات الجلسه.
الرجاء المحاولة مرة تانيه.
'mergelogpagetext' => 'فى تحت لستة بأحدث عمليات الدمج لتاريخ صفحة فى التانية.',
# Diffs
-'history-title' => 'تاريخ تعديل "$1"',
+'history-title' => ' «$1»: تاريخ التعديل',
'difference-multipage' => '(الفرق بين الصفحتين)',
'lineno' => 'سطر $1:',
'compareselectedversions' => 'قارن بين النسختين المختارتين',
'email' => 'الإيميل',
'prefs-help-realname' => 'الاسم الحقيقى اختيارى.
لو إخترت تكتبه, حيستعمل بس علشان شغلك يتنسب لإسمك.',
-'prefs-help-email' => 'اÙ\84Ø¥Ù\8aÙ\85Ù\8aÙ\84 اختÙ\8aارÙ\89, بس Ù\84ازÙ\85 عÙ\84شاÙ\86 Ù\84Ù\88 Ù\86سÙ\8aت اÙ\84پاسÙ\88Ù\88رد.
-ممكن بردو تختار انك تخلّى اليوزرات تبعتلك إيميل من صفحة اليوزر او المناقشه بتاعتك من غير ما تبقى شخصيتك معروفه.',
+'prefs-help-email' => 'عÙ\86Ù\88اÙ\86 اÙ\84Ù\84Ø¥Ù\8aÙ\85Ù\8aÙ\84 اختÙ\8aارÙ\89 Ø\8c بس Ù\84ازÙ\85 عÙ\84شاÙ\86 Ù\84Ù\88 Ù\86سÙ\8aت اÙ\84پاسÙ\88Ù\88رد..',
+'prefs-help-email-others' => 'ممكن بردو تختار انك تخلّى اليوزرات تبعتلك إيميل من صفحة اليوزر او المناقشه بتاعتك من غير ما تبقى شخصيتك معروفه.',
'prefs-help-email-required' => 'عنوان الإيميل مطلوب.',
'prefs-info' => 'معلومات اساسيه',
'prefs-i18n' => 'التدويل',
# Watchlist
'watchlist' => 'لستة الصفحات اللى باراقبها',
'mywatchlist' => 'لستة الصفح اللى باراقبها',
+'watchlistfor2' => 'لليوزر $1 ($2)',
'nowatchlist' => 'مافيش حاجة فى لستة مراقبتك.',
'watchlistanontext' => 'لو سمحت $1 لعرض أو تعديل الصفحات فى لستة مراقبتك.',
'watchnologin' => 'مش متسجل',
'sp-contributions-newbies-title' => 'مساهمات اليوزر للحسابات الجديدة',
'sp-contributions-blocklog' => 'سجل المنع',
'sp-contributions-deleted' => 'تعديلات اليوزر الممسوحه',
+'sp-contributions-uploads' => 'مرفوعات',
'sp-contributions-logs' => 'السجلات',
'sp-contributions-talk' => 'مناقشه',
'sp-contributions-userrights' => 'ادارة حقوق اليوزر',
آخر عمليه منع في السجل موجوده تحت كمرجع:',
'sp-contributions-search' => 'دور على مساهمات',
'sp-contributions-username' => 'عنوان أيبى أو اسم يوزر:',
+'sp-contributions-toponly' => 'اظهر اختير تعديل بس',
'sp-contributions-submit' => 'تدوير',
# What links here
'tooltip-upload' => 'ابتدى التحميل',
'tooltip-rollback' => "\"'''ترجيع'''\" بيرجع بدوسه واحده التعديل (التعديلات) فى الصفحه دى لاخر واحد عدل الصفحه.",
'tooltip-undo' => '"رجوع" بترجع التعديل دا وبتفتح استمارة التعديل فى شكل البروفة. بتسمح بإضافة سبب فى الملخص.',
+'tooltip-summary' => 'اكتب ملخص قصير',
# Stylesheets
'common.css' => '/* الأنماط المتراصة CSS المعروضة هنا ستؤثر على كل الواجهات */',
إذا كان الملف اتعدل عن حالته الأصلية، فبعض التفاصيل مش ها تعبر عن الملف المعدل.',
'metadata-expand' => 'عرض التفاصيل الاضافيه',
'metadata-collapse' => 'تخبية التفاصيل الاضافيه',
-'metadata-fields' => 'حقول معطيات الميتا EXIF الموجوده فى الرساله دى هاتتعرض فى صفحة الصوره لما يكون جدول معطيات الميتا مضغوط. الحقول التانيه هاتكون مخفيه افتراضيا.
+'metadata-fields' => 'معطيات الميتا الموجوده فى الرساله دى هاتتعرض فى صفحة الصوره لما يكون جدول معطيات الميتا مضغوط.
+المعطيات التانيه هاتكون مخفيه .
* make
* model
* datetimeoriginal
'dberrortext' => 'Възникна синтактична грешка при заявка към базата данни.
Това може да означава грешка в софтуера.
Последната заявка към базата данни беше:
-<blockquote><tt>$1</tt></blockquote>
-при функцията „<tt>$2</tt>“.
-MySQL върна грешка „<tt>$3: $4</tt>“.',
+<blockquote><code>$1</code></blockquote>
+при функцията „<code>$2</code>“.
+Базата от данни върна грешка „<samp>$3: $4</samp>“.',
'dberrortextcl' => 'Възникна синтактична грешка при заявка към базата данни.
Последната заявка към базата данни беше:
„$1“
'rev-deleted-text-permission' => "Тази версия на страницата е била '''изтрита'''.
Допълнителна информация може да се съдържа в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Дневника на изтриванията].",
'rev-deleted-text-unhide' => "Тази версия на страницата е била '''изтрита'''.
-Допълнителна информация може се съдържа в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Дневника на изтриванията].
+Допълнителна информация може се съдържа в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Дневника на изтриванията].
Като администратор на сайта вие можете да [$1 прегледате тази редакция], ако желаете да продължите.",
'rev-suppressed-text-unhide' => "Тази версия на страницата е била '''прикрита'''.
Допълнителна информация може да се съдържа в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Дневника на прикриванията].
ато администратор на сайта, вие можете да [$1 прегледате тази разликова препратка], ако желаете да продължите.",
'rev-deleted-diff-view' => "Една от версиите на тази разлика е била '''изтрита'''.
Можете да видите тази разлика; възможно е да има повече информация в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневника на изтриванията].",
-'rev-suppressed-diff-view' => "Ð\95дна оÑ\82 Ñ\80едакÑ\86ииÑ\82е оÑ\82 Ñ\82ази Ñ\80азлика междÑ\83 веÑ\80Ñ\81ииÑ\82е беÑ\88е '''прикрита'''.
+'rev-suppressed-diff-view' => "Ð\95дна оÑ\82 Ñ\80едакÑ\86ииÑ\82е оÑ\82 Ñ\82ази Ñ\80азлика междÑ\83 веÑ\80Ñ\81ииÑ\82е е била '''прикрита'''.
Като администратор, можете да видите тази разлика; повече подробности има в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} дневника за прикриванията].",
'rev-delundel' => 'показване/скриване',
'rev-showdeleted' => 'показване',
# Suppression log
'suppressionlog' => 'Дневник на прикриванията',
'suppressionlogtext' => 'По-долу е посочен списък на изтривания и блокирания, свързан със съдържание, скрито от администраторите.
-Ð\97а Ñ\82екÑ\83Ñ\89иÑ\82е блокиÑ\80аниÑ\8f и забÑ\80ани, вижÑ\82е [[Special:BlockList|Ñ\81пиÑ\81Ñ\8aка Ñ\81 блокиÑ\80аниÑ\82е IP адÑ\80еÑ\81и]].',
+Ð\97а Ñ\82екÑ\83Ñ\89иÑ\82е блокиÑ\80аниÑ\8f и забÑ\80ани, вижÑ\82е [[Special:BlockList|Ñ\81пиÑ\81Ñ\8aка Ñ\81 блокиÑ\80аниÑ\8fÑ\82а]].',
# History merging
'mergehistory' => 'Сливане на редакционни истории',
'wantedpages' => 'Желани страници',
'wantedpages-badtitle' => 'Невалидно заглавие в резултатното множество: $1',
'wantedfiles' => 'Желани файлове',
+'wantedfiletext-nocat' => 'Следните файлове се използват, но не съществуват. Възможно е да са включени файлове от външни хранилища, въпреки че съществуват. Всички такива случаи на възможна фалшива тревога ще бъдат показвани <del>зачеркнати</del>.',
'wantedtemplates' => 'Желани шаблони',
'mostlinked' => 'Най-препращани страници',
'mostlinkedcategories' => 'Най-препращани категории',
'spambot_username' => 'Спамочистач',
'spam_reverting' => 'Връщане на последната версия, несъдържаща препратки към $1',
'spam_blanking' => 'Всички версии, съдържащи препратки към $1, изчистване',
+'spam_deleting' => 'Всички версии съдържат препратки към $1, изтриване',
# Info page
'pageinfo-title' => 'Информация за "$1"',
'pageinfo-header-edits' => 'Редакции',
'pageinfo-views' => 'Брой прегледи',
'pageinfo-watchers' => 'Брой наблюдабащи',
+'pageinfo-redirects-name' => 'Пренасочвания към тази страница',
'pageinfo-subpages-name' => 'Подстраници на тази страница',
'pageinfo-lastuser' => 'Последeн редактор',
'pageinfo-lasttime' => 'Дата на последнoто редактиране',
'pageinfo-edits' => 'Общ брой редакции',
'pageinfo-authors' => 'Брой на отделни автори',
-'pageinfo-magic-words' => 'Вълшебни думички ($1)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Вълшебна думичка|Вълшебни думички}} ($1)',
# Skin names
'skinname-standard' => 'Класика',
'youhavenewmessages' => "$1 zo ganeoc'h ($2).",
'newmessageslink' => 'Kemennoù nevez',
'newmessagesdifflink' => "Diforc'hioù e-keñver ar stumm kent",
+'youhavenewmessagesfromusers' => '$1 ho peus eus {{PLURAL:$3|un implijer all|$3 implijer}} ($2).',
+'youhavenewmessagesmanyusers' => ' $1 ho peus implijerien a-leizh ($2).',
+'newmessageslinkplural' => "{{PLURAL:$1ur c'hemennad nevez|kemennadoù nevez}}",
+'newmessagesdifflinkplural' => '{{PLURAL:$1|kemennad diwezhañ|kemennadoù diwezhañ}}',
'youhavenewmessagesmulti' => "Kemennoù nevez zo ganeoc'h war $1",
'editsection' => 'kemmañ',
'editold' => 'kemmañ',
'databaseerror' => 'Fazi bank roadennoù',
'dberrortext' => 'C\'hoarvezet ez eus ur fazi ereadur eus ar reked er bank roadennoù, ar pezh a c\'hall talvezout ez eus un draen er meziant.
Setu ar goulenn bet pledet gantañ da ziwezhañ :
-<blockquote><tt>$1</tt></blockquote>
-adal an arc\'hwel "<tt>$2</tt>".
-Adkaset eo bet ar fazi "<tt>$3: $4</tt>" gant ar bank roadennoù.',
+<blockquote><code>$1</code></blockquote>
+adal an arc\'hwel "<code>$2</code>".
+Adkaset eo bet ar fazi "<samp>$3: $4</samp>" gant ar bank roadennoù.',
'dberrortextcl' => 'Ur fazi ereadur zo en ur reked savet ouzh ar bank roadennoù.
Setu ar goulenn bet pledet gantañ da ziwezhañ :
"$1"
'remembermypassword' => "Derc'hel soñj eus ma ger-tremen war an urzhiataer-mañ (evit $1 devezh{{PLURAL:$1||}} d'ar muiañ)",
'securelogin-stick-https' => 'Chom kevreet da HTTPS goude bezañ bet kevreet',
'yourdomainname' => 'Ho tomani',
+'password-change-forbidden' => "Ne c'hallit ket kemmañ ar gerioù-tremen er wiki-mañ.",
'externaldberror' => "Pe ez eus bet ur fazi gwiriekaat diavaez er bank titouroù pe n'oc'h ket aotreet da nevesaat ho kont diavaez.",
'login' => 'Kevreañ',
'nav-login-createaccount' => 'Krouiñ ur gont pe kevreañ',
'noarticletext-nopermission' => 'N\'eus, evit ar mare, tamm testenn ebet war ar bajenn-mañ.
Gallout a rit [[Special:Search/{{PAGENAME}}|klask titl ar bajenn-mañ]] war pajennoù all,
pe <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} klask er marilhoù kar]</span>.',
+'missing-revision' => "C'hoarvezout a ra peurliesañ pa vez heuliet ul liamm istorel dispredet war-zu ur bajenn zo bet dilamet.
+Gallout a reot kavout muioc'h a vunudoù e [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} renabl an dilamadurioù].",
'userpage-userdoesnotexist' => 'N\'eo ket enrollet ar gont "<nowiki>$1</nowiki>". Merkit ma fell deoc\'h krouiñ/kemmañ ar bajenn-mañ.',
'userpage-userdoesnotexist-view' => 'N\'eo ket enrollet ar gont implijer "$1".',
'blocked-notice-logextract' => "Stanket eo an implijer-mañ evit poent.
Dindan emañ merket moned diwezhañ marilh ar stankadennoù, d'ho kelaouiñ :",
'clearyourcache' => "Notenn :''' Goude bezañ enrollet ho pajenn e rankot freskaat krubuilh ho merdeer a-benn gwelet ar c'hemmoù.
-* '''Firefox / Safari: ''' Derc'hel da bouezañ war ''Pennlizherenn'' en ur glikañ war ''Adkargañ'', pe pouezañ war ''Ctrl-F5'' pe ''Ctrl-R'' (''⌘-R'' war ur Mac);
-* '''Google Chrome:''' Pouezañ war ''Ctrl-Pennlizh-R'' (''⌘-Shift-R'' war ur Mac)
+* '''Firefox / Safari:''' Derc'hel da bouezañ war ''Pennlizherenn'' en ur glikañ war ''Adkargañ'', pe pouezañ war ''Ctrl-F5'' pe ''Ctrl-R'' (''⌘-R'' war ur Mac);
+* ''''Google Chrome:''' Pouezañ war ''Ctrl-Pennlizh-R'' (''⌘-Shift-R'' war ur Mac)
* '''Internet Explorer:''' Derc'hel da bouezañ war ''Ctrl'' en ur glikañ war ''Freskaat,'' pe pouezañ war ''Ctrl-F5''
-* '''Konqueror: '''Klikañ war ''Adkargañ'' pe pouezañ war ''F5;''
+* ''''Konqueror: '''Klikañ war ''Adkargañ'' pe pouezañ war ''F5;''
* '''Opera:''' Riñsañ ar grubuilh e ''Ostilhoù → Penndibaboù''",
'usercssyoucanpreview' => "'''Tun :''' Grit gant ar bouton \"{{int:showpreview}}\" evit testiñ ho follenn CSS nevez a-raok enrollañ anezhi.",
'userjsyoucanpreview' => "'''Tun :''' Grit gant ar bouton \"{{int:showpreview}}\" evit testiñ ho follenn JS nevez a-raok enrollañ anezhi.",
'expansion-depth-exceeded-warning' => "Pajenn a ya dreist d'an donder astenn",
'parser-unstrip-loop-warning' => "Detektet ez eus bet ul lagadenn n'haller ket divontañ",
'parser-unstrip-recursion-limit' => "Aet dreist d'ar vevenn rekurziñ n'haller ket divontañ : $1",
+'converter-manual-rule-error' => 'Fazi dinodet er reolenn cheñch yezh dre zorn',
# "Undo" feature
'undo-success' => "Gallout a reer disteurel ar c'hemmoù-mañ. Gwiriit, mar plij, gant ar geñveriadenn a-is evit bezañ sur eo an dra-se a fell deoc'h ober; goude-se enrollit ar c'hemmoù a-is a-benn echuiñ disteurel ar c'hemmoù.",
'editundo' => 'dizober',
'diff-multi' => "({{PLURAL:$1|Ur reizhadenn da c'hortoz|$1 reizhadenn da c'hortoz}} gant {{PLURAL:$2|un implijer|$2 implijer}} kuzhet.)",
'diff-multi-manyusers' => "({{PLURAL:$1|Ur reizhadenn da c'hortoz|$1 reizhadenn da c'hortoz}} gant muioc'h eget $2 {{PLURAL:$2|implijer|implijer}} kuzhet.)",
+'difference-missing-revision' => "C'hoarvezout a ra peurliesañ pa vez heuliet ul liamm disheñvel dispredet war-zu ur bajenn zo bet dilamet.
+Gallout a reot kavout munudoù e [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} renabl an dilamadurioù].",
# Search results
'searchresults' => "Disoc'hoù enklask",
'right-writeapi' => 'Ober gant an API evit kemmañ ar wiki',
'right-delete' => 'Diverkañ pajennoù',
'right-bigdelete' => 'Diverkañ pajennoù dezho un hir a istor',
+'right-deletelogentry' => 'Dilemel hag assevel monedoù dibar eus ar renabl',
'right-deleterevision' => 'Diverkañ ha diziverkañ stummoù zo eus ur pajenn',
'right-deletedhistory' => 'Gwelet anvioù an istorioù diverket hep diskouez an destenn stag outo',
'right-deletedtext' => "Gwelet ar skrid diverket hag an diforc'hioù etre ar stummoù diverket",
'uploadnewversion-linktext' => 'Kargañ ur stumm nevez eus ar restr-mañ',
'shared-repo-from' => 'eus $1',
'shared-repo' => 'ur sanailh rannet',
+'upload-disallowed-here' => "Siwazh, ne c'hallit ket erlec'hiañ ar skeudenn-mañ",
# File reversion
'filerevert' => 'Disteuler $1',
'nbytes' => '$1 {{PLURAL:$1|eizhbit|eizhbit}}',
'ncategories' => '
$1 {{PLURAL:$1|rummad|rummad}}',
+'ninterwikis' => ' {{PLURAL:$1|interwiki|interwikis}}',
'nlinks' => '$1 {{PLURAL:$1|liamm|liamm}}',
'nmembers' => '$1 {{PLURAL:$1|elfenn|elfenn}}',
'nrevisions' => '$1 {{PLURAL:$1|stumm|stumm}}',
ha bezañ merket ur chomlec'h postel reizh en ho [[Special:Preferences|penndibaboù]]
evit gallout kas ur postel d'un implijer all.",
'emailuser' => "Kas ur postel d'an implijer-mañ",
+'emailuser-title-target' => "Kas ur postel d'an {{PLURAL:$1|an implijer-mañ|an implijerez-mañ}}",
+'emailuser-title-notarget' => "Kas ur postel d'un implijer",
'emailpage' => 'Postel implijer',
'emailpagetext' => "Gallout a rit ober gant ar furmskrid a-is a-benn kas ur postel d'an implijer-mañ.
E maezienn \"Kaser\" ho postel e vo merket ar chomlec'h postel resisaet ganeoc'h-c'hwi en ho [[Special:Preferences|Penndibaboù]], d'ar resever da c'hallout respont deoc'h war-eeun ma kar.",
'addedwatchtext' => 'Ouzh ho [[Special:Watchlist|rollad evezhiañ]] eo bet ouzhpennet ar bajenn "[[:$1]]".
Kemmoù da zont ar bajenn-mañ ha re ar bajenn gaozeal stag outi a vo rollet amañ hag e teuio ar bajenn <b>e tev</b> er [[Special:RecentChanges|roll kemmoù diwezhañ]] evit bezañ gwelet aesoc\'h ganeoc\'h.
-Evit tennañ ar bajenn-mañ a-ziwar ho rollad evezhiañ. klikit war "Paouez da evezhiañ" er framm merdeiñ.',
+Evit tennañ ar bajenn-mañ a-ziwar ho rollad evezhiañ, klikit war "Paouez da evezhiañ" er framm merdeiñ.',
'removewatch' => 'Lemel a-ziwar ar roll evezhiañ',
'removedwatchtext' => 'Lamet eo bet ar bajenn "[[:$1]]" a-ziwar ho [[Special:Watchlist|roll evezhiañ]].',
'watch' => 'Evezhiañ',
'import-error-interwiki' => 'Ne vez ket enporzhiet ar bajenn "$1" rak miret eo an anv evit liammoù diavaez (etrewiki).',
'import-error-special' => 'Ne vez ket enporzhiet ar bajenn "$1" rak stag eo ouzh un esaouenn anv dibar na aotre ket pajennoù.',
'import-error-invalid' => 'Ne vez ket enporzhiet ar bajenn "$1" rak direizh eo hec\'h anv.',
+'import-options-wrong' => '{{PLURAL:$2|Dibab fall|Dibaboù fall}}: <nowiki>$1</nowiki>',
# Import log
'importlogpage' => 'Log an enporzhiadennoù',
# Info page
'pageinfo-title' => 'Titouroù evit "$1"',
+'pageinfo-header-basic' => 'Titouroù diazez',
'pageinfo-header-edits' => 'Kemmoù',
+'pageinfo-header-restrictions' => 'Gwarez ar bajenn',
+'pageinfo-header-properties' => 'Perzhioù ar bajenn',
+'pageinfo-display-title' => 'Titl diskwelet',
+'pageinfo-default-sort' => "Alc'hwez rummañ dre ziouer",
+'pageinfo-length' => 'Ment ar bajenn (en oktedoù)',
+'pageinfo-article-id' => 'Niverenn ar bajenn',
+'pageinfo-robot-policy' => 'Statud al lusker klask',
+'pageinfo-robot-index' => "A c'haller menegeriñ",
+'pageinfo-robot-noindex' => "Ne c'haller ket menegeriñ",
'pageinfo-views' => 'Niver a weladennoù',
'pageinfo-watchers' => 'Niver a dud o heuliañ',
+'pageinfo-redirects-name' => 'Adkas war-zu ar bajenn-mañ',
+'pageinfo-subpages-name' => 'Ispajennoù eus ar bajenn-mañ',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|kasadur|kasadurioù}}; $3 {{PLURAL:$3|nann kasaduri|nann kasadurioù}})',
+'pageinfo-firstuser' => 'Krouer ar bajenn',
+'pageinfo-firsttime' => 'Deiziad krouiñ ar bajenn',
+'pageinfo-lastuser' => 'Kontroller diwezhañ',
+'pageinfo-lasttime' => "Deiziad ar c'hemm diwezhañ",
'pageinfo-edits' => 'Niver a gemmoù',
'pageinfo-authors' => 'Niver a aozerien disheñvel',
+'pageinfo-recent-edits' => 'Niver a gemmoù nevez (er $1 diwezhañ)',
+'pageinfo-recent-authors' => "Niver a aozerien nevez a-ziforc'h",
+'pageinfo-restriction' => 'Gwareziñ ar bajenn (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Ger hud |Gerioù hud}} ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Rumm kuzh|Rummoù kuzh}} ($1)',
+'pageinfo-templates' => "{{PLURAL:$1|Patrom endalc'het|Patromoù endalc'het}} ($1)",
# Skin names
'skinname-standard' => 'Standard',
'file-info-size-pages' => '$1 × $2 piksel, ment ar restr : $3, seurt MIME : $4, $5 {{PLURAL:$5|pajenn|pajenn}}',
'file-nohires' => "N'haller ket gwellaat ar pizhder.",
'svg-long-desc' => 'restr SVG file, pizhder $1 × $2 piksel, ment ar restr : $3',
+'svg-long-desc-animated' => 'Restr SVG bev, ment $1 × $2 piksel, ment ar restr: $3',
'show-big-image' => 'Pizhder leun',
'show-big-image-preview' => 'Ment ar rakweled-mañ : $1.',
'show-big-image-other' => '{{PLURAL:$2|pizhder all|pizhderioù all}} : $1.',
'file-info-png-looped' => "e kelc'h",
'file-info-png-repeat' => 'lennet $1 {{PLURAL:$1|wezh|gwezh}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|skeudenn|skeudenn}}',
+'file-no-thumb-animation' => 'Evezhiadenn: En abeg da vevennoù teknikel ne vo ket bevaet skeudennoùigoù ar restr-mañ',
+'file-no-thumb-animation-gif' => 'Evezhiadenn: En abeg da vevennoù teknikel ne vo ket bevaet ar skeudennoù GIF uhel o diarunusted evel homañ.',
# Special:NewFiles
'newimages' => 'Roll ar restroù nevez',
'api-error-file-too-large' => "Ar restr hoc'h eus roet a oa re vras.",
'api-error-filename-tooshort' => 'Re verr eo anv ar restr.',
'api-error-filetype-banned' => 'Difennet eo ar seurt restroù',
-'api-error-filetype-banned-type' => "'''N'eo ket $1 {{PLURAL:$4|ur seurt restr aotreet|seurtoù restroù aotreet}}. $2 eo {{PLURAL:$3|ar seurt restroù|ar seurtoù restroù}} degemeret.",
+'api-error-filetype-banned-type' => "N'eo ket $1{{PLURAL:$4|ur seurt restr aotreet | seurtoù restroù aotreet}}. $2 zo {{PLURAL:$3|ar seurt restroù|ar seurtoù restroù}} degemeret.?",
'api-error-filetype-missing' => "Un astenn a vank d'ar restr.",
'api-error-hookaborted' => "Ar c'hemm hoc'h eus klasket degas zo bet harzet gant ur c'hrog astenn.",
'api-error-http' => "Fazi diabarzh : dibosupl kevreañ d'ar servijer.",
'disclaimerpage' => 'Project:Uslovi korištenja, pravne napomene i odricanje odgovornosti',
'edithelp' => 'Pomoć pri uređivanju stranice',
'edithelppage' => 'Help:Uređivanje',
-'helppage' => 'Pomoć:Sadržaj',
+'helppage' => 'Help:Sadržaj',
'mainpage' => 'Početna strana',
'mainpage-description' => 'Početna strana',
'policy-url' => 'Project:Pravila',
'ns-specialprotected' => 'Specijalne stranice se ne mogu uređivati.',
'titleprotected' => 'Naslov stranice je zaštićen od postavljanja od strane korisnika [[User:$1|$1]].
Iz razloga "\'\'$2\'\'".',
+'exception-nologin' => 'Niste prijavljeni',
# Virus scanner
'virus-badscanner' => "Loša konfiguracija: nepoznati anti-virus program: ''$1''",
# Info page
'pageinfo-title' => 'Informacije za "$1"',
'pageinfo-header-edits' => 'Izmjene',
+'pageinfo-header-restrictions' => 'Zaštita stranice',
+'pageinfo-article-id' => 'ID stranice',
'pageinfo-views' => 'Broj pogleda',
'pageinfo-watchers' => 'Broj onih koji pregledaju',
'pageinfo-edits' => 'Broj izmjena',
'tog-enotifminoredits' => 'بۆ گۆڕانکارییە بچووکەکانی پەڕەکان و پەڕگەکانیش ئیمەیلم بۆ بنێرە',
'tog-enotifrevealaddr' => 'ئەدرەسی ئیمەیلەکەم لە ئیمەیلە ئاگاداریدەرەکان دا نیشان بدە',
'tog-shownumberswatching' => 'ژمارەی بەکارھێنەرە چاودێڕەکان نیشان بدە',
-'tog-oldsig' => 'واژۆی ئێستا:',
-'tog-fancysig' => 'وەک ویکیدەق لەگەڵ واژۆ مامەڵەبکە (بێ بەستەرێکی خۆکار)',
+'tog-oldsig' => 'واژووی ئێستا:',
+'tog-fancysig' => 'وەکوو ویکیدەق واژووەکە لەبەر چاو بگرە (بێ بەستەرێکی خۆگەڕ)',
'tog-externaleditor' => 'دەستکاریکەری دەرەکی بەکاربێنە لە حاڵەتی دیفاڵتدا (تەنھا بۆ شارەزایان، ڕێکخستنی تایبەتی پێویستە لە سەر کۆمپیوتەرەکەت [//www.mediawiki.org/wiki/Manual:External_editors زانیاریی زۆرتر.])',
'tog-externaldiff' => 'لە پرۆگرامێکی دەرەکی بۆ بینینی جیاوازیەکان کەڵک وەرگرە لە دیفاڵتدا (تەنها بۆ شارەزایان، ڕێکخستنی تایبەتی پێویستە لە سەر کۆمپیوتەرەکەت. [//www.mediawiki.org/wiki/Manual:External_editors زانیاریی زۆرتر.])',
'tog-showjumplinks' => 'ڕێگە بدە بۆ بەستەرەکانی «{{int:jumpto}}»',
'index-category' => 'پەڕە پێرستەکراوەکان',
'noindex-category' => 'پەڕە پێرستنەکراوەکان',
'broken-file-category' => 'ئەو پەڕانەی بەستەری پەڕگەکانیان شکاوە',
+'categoryviewer-pagedlinks' => '($1) ($2)',
'about' => 'سەبارەت',
'article' => 'بابەت',
تەماشای [[Special:Version|پەڕەی وەشان]] بکە.',
'ok' => 'باشه',
+'pagetitle' => '$1 - {{SITENAME}}',
+'pagetitle-view-mainpage' => '{{SITENAME}}',
'backlinksubtitle' => '→ $1',
'retrievedfrom' => 'وەرگیراو لە «$1»',
'youhavenewmessages' => '$1ت ھەیە ($2).',
'newmessageslink' => 'پەیامی نوێ',
-'newmessagesdifflink' => 'دوا گۆڕانکارییەکان',
+'newmessagesdifflink' => 'دوایین گۆڕانکاری',
+'youhavenewmessagesfromusers' => '$1ت لە {{PLURAL:$3|بەکارھێنەرێکی تر| $3 بەکارھێنەر}} ھەیە ( $2 ).',
+'youhavenewmessagesmanyusers' => '$1ت لە ژمارەیەک بەکارھێنەر ھەیە ( $2 ).',
+'newmessageslinkplural' => '{{PLURAL:$1|پەیامێکی نوێ|پەیامی نوێ}}',
+'newmessagesdifflinkplural' => 'دوایین {{PLURAL:$1|گۆڕانکاری|گۆڕانکارییەکان}}',
'youhavenewmessagesmulti' => 'لە $1 دا پەیامی نوێت ھەیە',
'editsection' => 'دەستکاری',
'editold' => 'دەستکاری',
'site-atom-feed' => 'فیدی Atom بۆ $1',
'page-rss-feed' => 'فیدی RSS بۆ «$1»',
'page-atom-feed' => 'فیدی Atom بۆ «$1»',
+'feed-atom' => 'ئەتۆم',
'red-link-title' => '$1 (پەڕە بوونی نییە)',
# Short words for each namespace, by default used in the namespace tab in monobook
'yourrealname' => 'ناوی ڕاستی:',
'yourlanguage' => 'زمان',
'yourvariant' => 'شێوەزاری زمانی ناوەرۆک:',
-'yournick' => 'Ù\86ازÙ\86اÙ\88',
+'yournick' => 'Ù\88اÚ\98Ù\88Ù\88Û\8c Ù\86Ù\88Û\8e:',
'prefs-help-signature' => 'بۆچوونەکان لە لاپەڕەکانی وتووێژدا دەبێ بە "<nowiki>~~~~</nowiki>" دیاری بکرێن، کە دواتر خۆکار دەگۆڕێ بە واژۆکەت و مۆری کاتی.',
'badsig' => 'ئیمزاكه ههڵهیه، تهماشای كۆدی HTML بكه',
'badsiglength' => 'واژۆکەت زۆر درێژە.
واژۆ نابێ لە $1 {{PLURAL:$1|نووسە|نووسە}} درێژتر بێت.',
-'yourgender' => 'ڕەگەز:',
+'yourgender' => 'زایەند:',
'gender-unknown' => 'ئاشکرا نەکراو',
'gender-male' => 'پیاو',
'gender-female' => 'ژن',
'prefs-diffs' => 'جیاوازییەکان',
# User rights
-'userrights' => 'بەڕێوەبردنی مافەکانی بەکارهێنەران',
+'userrights' => 'بەڕێوەبردنی مافەکانی بەکارھێنەر',
'userrights-lookup-user' => 'بەڕێوەبردنی گرووپەکانی بەکارهێنەران',
'userrights-user-editname' => 'ناوی بەکارهێنەرێک بنووسە:',
'editusergroup' => 'گرووپەکانی بەکارهێنەر بگۆڕە',
'rcshowhideanons' => 'بەکارھێنەرە نەناسراوەکان $1',
'rcshowhidepatr' => 'گۆرانکارییە کۆنترۆڵکراوەکان $1',
'rcshowhidemine' => 'دەستکارییەکانی من $1',
-'rclinks' => 'دوایین $1 گۆڕانکاریی $2 ڕۆژی ڕابردوو نیشانبدە<br />$3',
+'rclinks' => 'دوایین $1 گۆڕانکاریی $2 ڕۆژی ڕابردوو نیشان بدە<br />$3',
'diff' => 'جیاوازی',
'hist' => 'مێژوو',
'hide' => 'بشارەوە',
'mostimages' => 'ئەو پەڕگانە زۆرترین بەستەریان پێدراوە',
'mostrevisions' => 'ئەو پەڕانە زۆرترین پیاچوونەوەیان ھەیە',
'prefixindex' => 'گشت پەڕەکان بە پێشگرەوە',
+'prefixindex-namespace' => 'هەموو پەڕەکان بەپێشگری (بۆشایی ناوی $1)',
'shortpages' => 'پەڕە کورتەکان',
-'longpages' => 'پەڕە دڕێژەکان',
+'longpages' => 'پەڕە درێژەکان',
'deadendpages' => 'پەڕە بنبەستەکان',
'deadendpagestext' => 'ئەم پەڕانەی خوارەوە پەیوەندییان لەگەڵ پەڕەکانی تری {{SITENAME}} نییە.',
'protectedpages' => 'پەڕە پارێزراوەکان',
'emailpagetext' => 'دەتوانی لەم فۆرمەی خوارەوە کەڵک وەربگریت بۆ ناردنی پەیامێکی ئیمەیل بۆ ئەم بەکارھێنەرە.
ئەو ئەدرەسی ئیمەیلە لە [[Special:Preferences|ھەڵبژاردەکانی بەکارھێنەریتدا]] نووسیوتە، بۆ ئەدرەسی «لەلایەن» (From) لە ئیمەیلدا نیشان دەدرێت، کە وایە بەکارھێنەری وەرگر دەتوانێ ڕاستەوخۆ وەڵامت بداتەوە.',
'defemailsubject' => 'ئیمەیڵی {{SITENAME}} لە بەکارھێنەر «$1»ەوە',
+'usermaildisabled' => 'ئیمەیڵی بەکارهێنەر لەکاردانیە',
'noemailtitle' => 'هیچ ناونیشانێکی ئیمەیل نییە',
'noemailtext' => 'ئەم بەکارهێنەرە ناونێشانێکی بڕوا پێکراوی ئیمەیلی دانەناوە.',
'nowikiemailtitle' => 'ڕێگە بۆ ئیمەیل نەدراوە',
'usermessage-editor' => 'پەیامنێری سیستەم',
# Watchlist
-'watchlist' => 'Ù\84Û\8cستی چاودێرییەکانم',
+'watchlist' => 'Ù¾Û\8eرستی چاودێرییەکانم',
'mywatchlist' => 'پێرستی چاودێرییەکانم',
'watchlistfor2' => 'بۆ $1 $2',
'nowatchlist' => 'لە لیستی چاودێڕییەکانتدا ھیچ نیە.',
'addwatch' => 'بیخە سەر لیستی چاودێری',
'addedwatchtext' => 'پەڕەی «[[:$1]]» خرایە سەر [[Special:Watchlist|لیستی چاودێرییەکەت]].
گۆڕانکارییەکانی داھاتووی ئەم پەڕە و پەڕەی وتووێژەکەی، لەوێدا ڕیزدەکرێ و پەڕەکە لە [[Special:RecentChanges|لیستی دوایین گۆڕانکارییەکاندا]] ئەستوورکراو دەردەکەوێت بۆ ئەوەی ئاسانتر دەستکەوێت.',
+'removewatch' => 'لەلیستی چاودێری لایبە',
'removedwatchtext' => 'پەڕەی «[[:$1]]» لە [[Special:Watchlist|لیستی چاودێریەکەت]] لابرا.',
'watch' => 'چاودێری بکە',
'watchthispage' => 'چاودێریی ئەم پەڕە بکە',
'deletepage' => 'پەڕە بسڕەوە',
'confirm' => 'پشتدار بکەرەوە',
'excontent' => 'ناوەرۆک ئەمە بوو: «$1»',
-'excontentauthor' => 'ناوەرۆک ئەمە بوو: «$1» (و تەنھا بەشداربوو «[[Special:Contributions/$2|$2]]» بوو)',
+'excontentauthor' => 'ناوەرۆک ئەمە بوو: «$1» (و تەنیا بەشداربوو «[[Special:Contributions/$2|$2]]» بوو)',
'exbeforeblank' => 'ناوەرۆک بەر لە بەتاڵ کردنەوە ئەمە بوو: «$1»',
'exblank' => 'پەڕە خاڵی بوو',
'delete-confirm' => 'سڕینەوەی «$1»',
'imagetypemismatch' => 'پاشگری ئەو پەڕگە نوێیە هاوتای جۆری پەڕگەکە نیە.',
'imageinvalidfilename' => 'ناوی پەڕگەی ئامانج گونجاو نیە',
'fix-double-redirects' => 'نوێکەردنەوەی هەموو ڕەوانکەرەکان وا ئاماژە بە سەردێڕە سەرەکیەکە دەکەن',
-'move-leave-redirect' => 'لە پاشەوە ڕەوانکەرێک بە جێ بھێڵە',
+'move-leave-redirect' => 'لە پاشەوە ڕەوانەکەرێک بھێڵەوە',
'protectedpagemovewarning' => "'''ھۆشیار بە: ئەم پەڕە پارێزراوە بۆ ئەوی تەنیا ئەو بەکارھێنەرانە کە مافەکانی بەڕێوەبەرایەتییان ھەیە بتوانن بیگوازنەوە.'''
دوایین لۆگ بۆ ژێدەر لە خوارەوەدا ھاتووە:",
'semiprotectedpagemovewarning' => "'''ئاگاداری:''' ئەم پەڕە پارێزراوە بۆ ئەوی تەنھا بەکارھێنەرە تۆمارکراوەکان بتوانن بیگوازنەوە.
'tooltip-upload' => 'دەستپێکردنی بارکردن',
'tooltip-rollback' => "''گەڕاندنەوە'' بە یەک کلیک گۆڕانکاری (گۆڕانکارییەکانی) ئەم پەڕە ئەباتەوە بۆ ھی دواین بەشدار",
'tooltip-undo' => '«پووچکردنەوە» ئەم گۆڕانکارییە دەگەڕێنێتەوە و فۆرمی دەستکاریکردنەکە لە حاڵەتی پێشبینیندا دەکاتەوە. بەم شێوە دەکرێ ھۆکارێک لە پوختەدا بنووسرێت.',
+'tooltip-preferences-save' => 'هەڵبژاردنەکانت بپارێزە',
'tooltip-summary' => 'پوختەیەکی کورتی تێبخە',
# Metadata
'pageinfo-title' => 'زانیاری بۆ «$1»',
'pageinfo-header-basic' => 'زانیاریی سەرەتایی',
'pageinfo-header-edits' => 'دەستکاریەکان',
+'pageinfo-display-title' => 'ناونیشان نیشانبدە',
+'pageinfo-article-id' => 'زنجیرەی پەڕە',
'pageinfo-views' => 'ژمارەی بینینەکان',
'pageinfo-watchers' => 'ژمارەی چاودێران',
'pageinfo-firstuser' => 'دروستکەری پەڕە',
# Video information, used by Language::formatTimePeriod() to format lengths in the above messages
'video-dims' => '$1، $2 لە $3',
+'seconds-abbrev' => '$1چ',
+'minutes-abbrev' => '$1خ',
+'hours-abbrev' => '$1ک',
+'days-abbrev' => '$1ڕ',
'seconds' => '{{PLURAL:$1|$1 چرکە|$1 چرکە}}',
'minutes' => '{{PLURAL:$1|$1 خولەک|$1 خولەک}}',
'hours' => '{{PLURAL:$1|$1 کاتژمێر|$1 کاتژمێر}}',
'exif-pixelxdimension' => 'بەرزی وێنە',
'exif-usercomment' => 'بۆچوونەکانی بەکارهێنەر',
'exif-relatedsoundfile' => 'فایلی دهنگی لێکچوو',
+'exif-exposuretime-format' => '$1 چرکە ($2)',
'exif-lightsource' => 'سەرچاوەی ڕووناکی',
'exif-flash' => 'فلاش',
'exif-filesource' => 'سەرچاوەی پەڕگە',
'exif-objectname' => 'سەردێری کورت',
'exif-headline' => 'سەردێر',
'exif-source' => 'سەرچاوە',
+'exif-contact' => 'زانیاری پەیوەندیکردن',
+'exif-writer' => 'نووسەر',
+'exif-languagecode' => 'زمان',
+'exif-iimversion' => 'وەشانی IIM',
+'exif-iimcategory' => 'پۆل',
'exif-copyrighted' => 'ڕەوشی مافی لەبەرگرتنەوە',
+# Make & model, can be wikified in order to link to the camera and model name
+'exif-subjectnewscode-value' => '$2 ($1)',
+
# EXIF attributes
'exif-compression-1' => 'نەپەستێنراو',
'exif-dc-date' => 'ڕۆژ(ەکان)',
'exif-dc-publisher' => 'بڵاوکار',
-'exif-dc-relation' => 'Ù¾Û\95Ú\95Ú¯Û\95ی پەیوەندیدار',
+'exif-dc-relation' => 'Ù\85Û\8cدÛ\8cای پەیوەندیدار',
'exif-dc-rights' => 'مافەکان',
-'exif-dc-source' => 'سÛ\95رÚ\86اÙ\88Û\95Û\8c Ù¾Û\95Ú\95Ú¯Û\95',
-'exif-dc-type' => 'جÛ\86رÛ\8c Ù¾Û\95Ú\95Ú¯Û\95',
+'exif-dc-source' => 'سÛ\95رÚ\86اÙ\88Û\95Û\8c Ù\85Û\8cدÛ\8cا',
+'exif-dc-type' => 'جÛ\86رÛ\8c Ù\85Û\8cدÛ\8cا',
'exif-iimcategory-hth' => 'تەندروستی',
+'exif-iimcategory-pol' => 'سیاسەت',
'exif-iimcategory-sci' => 'زانست و تەکنۆلۆژیا',
'exif-iimcategory-soi' => 'بابەتە کۆمەڵایەتییەکان',
'exif-iimcategory-spo' => 'وەرزشەکان',
'size-megabytes' => '$1 مێگابایت',
'size-gigabytes' => '$1 گیگابایت',
'size-terabytes' => '$1 تێرابایت',
+'size-petabytes' => '$1 پێبیبایت',
# Live preview
'livepreview-loading' => 'باركردن...',
'hijri-calendar-m12' => 'زولحەججە',
# Signatures
-'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|وتووێژ]])',
+'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|لێدوان]])',
+'timezone-utc' => 'UTC',
# Core parser functions
'unknown_extension_tag' => 'تاگی درێژکراوەی نەناسراو "$1"',
# New logging system
'logentry-delete-delete' => '$1 پەڕەی $3ی سڕییەوە',
'logentry-delete-restore' => '$1 پەڕەی $3ی ھێنایەوە',
-'logentry-delete-revision' => '$1 دەرکەوتنی {{PLURAL:$5|پێداچوونەوەیکی|$5 پێداچوونەوەی}} پەڕەی $3 گۆڕیی: $4',
+'logentry-delete-revision' => '$1 دەرکەوتنی {{PLURAL:$5|پێداچوونەوەیەکی|$5 پێداچوونەوەی}} پەڕەی $3 گۆڕیی: $4',
'revdelete-content-hid' => 'شاردنەوەی ناوەرۆک',
+'revdelete-uname-hid' => 'ناوی بەکارهێنەری شاراوە',
'revdelete-restricted' => 'ئەو سنووری بەرگریانەی خستراوەتە سەر بەڕێوبەران',
'revdelete-unrestricted' => 'ئەو سنووری بەرگریانەی لابردراوە لە سەر بەڕێوبەران',
'logentry-move-move' => '$1 پەڕەی $3ی گواستەوە بۆ $4',
'feedback-subject' => 'بابەت:',
'feedback-message' => 'پەیام:',
'feedback-cancel' => 'ھەڵیوەشێنەوە',
+'feedback-submit' => 'تێبینییەکان بنێرە',
'feedback-close' => 'ئەنجام درا',
# API errors
'img-auth-nofile' => 'Nid oes ffeil a\'r enw "$1" ar gael.',
'img-auth-isdir' => 'Rydych yn ceisio cyrchu cyfeiriadur o\'r enw "$1".
Dim ond ffeiliau y cewch eu cyrchu.',
-'img-auth-streaming' => 'Wrthi\'n llifo "$1".',
+'img-auth-streaming' => 'Wrthi\'n ffrydio "$1".',
'img-auth-public' => "Gwaith img_auth.php yw allbynnu ffeiliau o wici preifat.
Mae'r wici hwn wedi ei osod yn wici gyhoeddus.
Er mwyn sicrhau'r diogelwch gorau posib, analluogwyd img_auth.php.",
'shared-repo-from' => 'oddi ar $1',
'shared-repo' => 'storfa cyfrannol',
'shared-repo-name-wikimediacommons' => 'Comin Wikimedia',
+'upload-disallowed-here' => "Yn anffodus ni allwch drosysgrifo'r ddelwedd hon.",
# File reversion
'filerevert' => 'Gwrthdroi $1',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|beit|beit|feit|beit|beit|beit}}',
'ncategories' => '$1 {{PLURAL:$1|categori|categori|gategori|chategori|chategori|categori}}',
+'ninterwikis' => '$1 {{PLURAL:$1|cyswllt|cyswllt|gyswllt|chyswllt|chyswllt|cyswllt}}',
'nlinks' => '$1 {{PLURAL:$1|cyswllt|cyswllt|gyswllt|chyswllt|chyswllt|cyswllt}}',
'nmembers' => '$1 {{PLURAL:$1|aelod|aelod|aelod|aelod|aelod|aelod}}',
'nrevisions' => '$1 {{PLURAL:$1|diwygiad|diwygiad|ddiwygiad|diwygiad|diwygiad|diwygiad}}',
'mostlinkedtemplates' => 'Nodiadau yn nhrefn nifer y cysylltiadau iddynt',
'mostcategories' => 'Erthyglau yn nhrefn nifer eu categorïau',
'mostimages' => 'Ffeiliau yn nhrefn nifer y cysylltiadau iddynt',
+'mostinterwikis' => "Tudalennau a'r nifer mwyaf o gysylltau rhyngwici",
'mostrevisions' => 'Tudalennau yn nhrefn nifer y newidiadau iddynt',
'prefixindex' => 'Pob tudalen yn ôl parth',
'prefixindex-namespace' => 'Pob tudalen â rhagddodiad penodol (y parth $1)',
a bod cyfeiriad e-bost dilys yn eich [[Special:Preferences|dewisiadau]]
er mwyn medru anfon e-bost at ddefnyddwyr eraill.',
'emailuser' => 'Anfon e-bost at y defnyddiwr hwn',
+'emailuser-title-target' => "Ebostio'r {{GENDER:$1|defnyddiwr hwn}}",
'emailuser-title-notarget' => 'Anfon e-bost at ddefnyddiwr',
'emailpage' => 'Anfon e-bost at ddefnyddiwr',
'emailpagetext' => "Os yw'r cyfeiriad e-bost sydd yn newisiadau'r defnyddiwr hwn yn un dilys, gellir anfon neges ato o'i ysgrifennu ar y ffurflen isod.
'pageinfo-header-edits' => 'Hanes golygu',
'pageinfo-header-restrictions' => 'Diogelwch y dudalen',
'pageinfo-header-properties' => "Priodweddau'r dudalen",
+'pageinfo-display-title' => 'Teitl y dudalen',
+'pageinfo-default-sort' => 'Allwedd trefnu diofyn',
'pageinfo-length' => 'Hyd y dudalen (beitiau)',
'pageinfo-article-id' => 'ID y dudalen',
+'pageinfo-robot-policy' => 'Statws i beiriannau chwilio',
'pageinfo-views' => 'Nifer yr ymweliadau',
'pageinfo-watchers' => 'Nifer gwylwyr y dudalen',
+'pageinfo-redirects-name' => "Nifer yr ailgyfeiriadau i'r dudalen hon",
+'pageinfo-subpages-name' => "Nifer yr is-dudalennau i'r dudalen hon",
'pageinfo-firstuser' => 'Y defnyddiwr a ddechreuodd y dudalen',
'pageinfo-firsttime' => "Dyddiad dechrau'r dudalen",
'pageinfo-lastuser' => 'Y golygydd diweddaraf',
'pageinfo-lasttime' => 'Dyddiad y golygiad diweddaraf',
'pageinfo-edits' => 'Cyfanswm y golygiadau',
'pageinfo-authors' => 'Cyfanswm yr awduron gwahanol',
+'pageinfo-magic-words' => '{{PLURAL:$1|Gair|Gair|Geiriau}} hud ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Categori|Categori|Categorïau}} cudd ($1)',
# Skin names
'skinname-standard' => 'Safonol',
'redirectedfrom' => '(Omdirigeret fra $1)',
'redirectpagesub' => 'Omdirigering',
'lastmodifiedat' => 'Denne side blev senest ændret $1 kl. $2.',
-'viewcount' => 'Siden er vist i {{PLURAL:$1|en gang|$1 gange}}.',
+'viewcount' => 'Siden er vist {{PLURAL:$1|en gang|$1 gange}}.',
'protectedpage' => 'Beskyttet side',
'jumpto' => 'Skift til:',
'jumptonavigation' => 'Navigation',
* '''Firefox / Safari:''' Hold ''shifttasten'' nede og klik på ''reload'', eller tryk enten ''Ctrl-F5'' eller ''Ctrl-Shift-r'' (''⌘-R'' på en Mac).
* '''Google Chrome:''' Tryk ''Ctrl-Shift-R'' (''⌘-Shift-R'' på en Mac).
* '''Internet Explorer:''' Hold ''controltasten'' nede og klik på ''refresh'' eller tryk på ''Ctrl-F5''.
-* '''Konqueror:''' Klik på ''reload'' eller tryk på ''F5''.
* '''Opera:''' Tøm cachen i ''Tools → Preferences''.",
'usercssyoucanpreview' => "'''Tip:''' Brug \"{{int:showpreview}}\"-knappen for at teste dit nye CSS inden du gemmer.",
'userjsyoucanpreview' => "'''Tip:''' Brug \"{{int:showpreview}}\"-knappen for at teste dit nye JavaScript inden du gemmer.",
'uploadnewversion-linktext' => 'Læg en ny version af denne fil op',
'shared-repo-from' => 'fra $1',
'shared-repo' => 'et delt filarkiv',
+'upload-disallowed-here' => 'Desværre kan du ikke overskrive dette billede.',
# File reversion
'filerevert' => 'Gendan $1',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|byte|bytes}}',
'ncategories' => '$1 {{PLURAL:$1|kategori|kategorier}}',
+'ninterwikis' => '$1 {{PLURAL:$1|interwikilink|interwikilinks}}',
'nlinks' => '{{PLURAL:$1|1 henvisning|$1 henvisninger}}',
'nmembers' => '$1 {{PLURAL:$1|medlem|medlemmer}}',
'nrevisions' => '{{PLURAL:$1|1 ændring|$1 ændringer}}',
'mostlinkedtemplates' => 'Hyppigst brugte skabeloner',
'mostcategories' => 'Mest brugte sider',
'mostimages' => 'Mest brugte filer',
+'mostinterwikis' => 'Sider med flest interwikilinks',
'mostrevisions' => 'Sider med de fleste ændringer',
'prefixindex' => 'Alle sider med præfiks',
'prefixindex-namespace' => 'Alle sider med præfiks (navnerummet $1)',
'mailnologin' => 'Du er ikke logget på',
'mailnologintext' => 'Du skal være [[Special:UserLogin|logget på]] og have en gyldig e-mailadresse sat i dine [[Special:Preferences|indstillinger]] for at sende e-mail til andre brugere.',
'emailuser' => 'E-mail til denne bruger',
+'emailuser-title-target' => 'Send email til denne {{GENDER:$1|bruger}}',
+'emailuser-title-notarget' => 'Send email til en bruger',
'emailpage' => 'E-mail bruger',
'emailpagetext' => 'Du kan bruge formularen nedenfor til at sende en e-mail til denne bruger.
Den e-mail-adresse du har angivet i [[Special:Preferences|dine indstillinger]] vil dukke op i "fra"-feltet på e-mailen, så modtageren kan svare dig.',
'import-error-interwiki' => 'Siden "$1" importeres ikke, da dens navn er reserveret for eksterne henvisninger (interwiki).',
'import-error-special' => 'Siden "$1" importeres ikke, da den tilhører et særligt navnerum, der ikke tillader sider.',
'import-error-invalid' => 'Siden "$1" importeres ikke, da dens navn er ugyldigt.',
+'import-options-wrong' => '{{PLURAL:$2|Ugyldig indstilling|Ugyldige indstillinger}}: <nowiki>$1</nowiki>',
'import-rootpage-invalid' => 'Den rodside der er angivet har en ugyldig titel.',
'import-rootpage-nosubpage' => 'Navnerummet "$1" tillader ikke undersider af rodsiderne.',
# Info page
'pageinfo-title' => 'Information om "$1"',
-'pageinfo-header-edits' => 'Redigeringer',
+'pageinfo-header-basic' => 'Grundlæggende oplysninger',
+'pageinfo-header-edits' => 'Redigeringshistorik',
+'pageinfo-header-restrictions' => 'Sidebeskyttelse',
+'pageinfo-header-properties' => 'Sideegenskaber',
+'pageinfo-default-sort' => 'Standardsorteringsnøgle',
+'pageinfo-length' => 'Sidelængde (i bytes)',
+'pageinfo-article-id' => 'Side-ID',
+'pageinfo-robot-policy' => 'Søgemaskinestatus',
+'pageinfo-robot-index' => 'Indekserbar',
+'pageinfo-robot-noindex' => 'Ikke indekserbar',
'pageinfo-views' => 'Antal visninger',
'pageinfo-watchers' => 'Antal brugere, der overvåger siden',
-'pageinfo-edits' => 'Antal redigeringer',
-'pageinfo-authors' => 'Antal forskellige forfattere',
+'pageinfo-redirects-name' => 'Omdirigeringer til denne side',
+'pageinfo-subpages-name' => 'Undersider til denne side',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|omdirigering|omdirigeringer}}; $3 {{PLURAL:$3|der ikke er en omdirigering|der ikke er omdirigeringer}})',
+'pageinfo-firsttime' => 'Dato for oprettelsen af siden',
+'pageinfo-lasttime' => 'Dato for seneste redigering',
+'pageinfo-edits' => 'Samlet antal redigeringer',
+'pageinfo-authors' => 'Det samlede antal forskellige forfattere',
+'pageinfo-restriction' => 'Sidebeskyttelse (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Magisk|Magiske}} ord ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Skjult kategori|Skjulte kategorier}} ($1)',
+'pageinfo-templates' => '{{PLURAL:$1|Transkluderet skabelon|Transkluderede skabeloner}} ($1)',
# Skin names
'skinname-standard' => 'Klassik',
'file-info-size-pages' => '$1 × $2 punkter, filstørrelse: $3, MIME-type: $4, $5 {{PLURAL:$5|side|sider}}',
'file-nohires' => 'Ingen højere opløsning fundet.',
'svg-long-desc' => 'SVG fil, basisstørrelse $1 × $2 punkters, størrelse: $3',
+'svg-long-desc-animated' => 'Animeret SVG-fil, basisstørrelse $1 × $2 punkter, filstørrelse: $3',
'show-big-image' => 'Version i større opløsning',
'show-big-image-preview' => 'Størrelse af denne forhåndsvisning: $1.',
'show-big-image-other' => '{{PLURAL:$2|Anden opløsning|Andre opløsninger}}: $1.',
'file-info-png-looped' => 'gentaget',
'file-info-png-repeat' => 'afspillede $1 {{PLURAL:$1|gang|gange}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|billede|billeder}}',
+'file-no-thumb-animation' => "'''Bemærk: På grund af tekniske begrænsninger vil miniaturebilleder af denne fil ikke blive animeret.'''",
+'file-no-thumb-animation-gif' => "'''Bemærk: På grund af tekniske begrænsninger vil miniaturebilleder af GIF-filer, der som denne er i høj opløsning, ikke blive animeret.'''",
# Special:NewFiles
'newimages' => 'Galleri med de nyeste billeder',
Vielleicht möchtest du die Beschreibung auf der dortigen [$2 Dateibeschreibungsseite] bearbeiten.',
'sharedupload-desc-create' => 'Diese Datei stammt aus $1 und kann von anderen Projekten verwendet werden.
Vielleicht möchtest du die Beschreibung auf der dortigen [$2 Dateibeschreibungsseite] bearbeiten.',
-'filepage-nofile' => 'Es ist keine Datei dieses namens vorhanden.',
-'filepage-nofile-link' => 'Es ist keine Datei dieses namens vorhanden. Du kannst jedoch [$1 diese Datei hochladen].',
+'filepage-nofile' => 'Es ist keine Datei dieses Namens vorhanden.',
+'filepage-nofile-link' => 'Es ist keine Datei dieses Namens vorhanden. Du kannst jedoch [$1 diese Datei hochladen].',
'uploadnewversion-linktext' => 'Eine neue Version dieser Datei hochladen',
'shared-repo-from' => 'aus $1',
'shared-repo' => 'einem gemeinsam genutzten Medienarchiv',
'ipb-change-block' => 'Sperre mit diesen Sperrparametern erneuern',
'ipb-confirm' => 'Sperrung bestätigen',
'badipaddress' => 'Die IP-Adresse hat ein falsches Format.',
-'blockipsuccesssub' => 'Sperre erfolgreich',
+'blockipsuccesssub' => 'Die Sperrung war erfolgreich.',
'blockipsuccesstext' => 'Der Benutzer / die IP-Adresse [[Special:Contributions/$1|$1]] wurde gesperrt.<br />
Zur Aufhebung der Sperre siehe die [[Special:BlockList|Liste aller aktiven Sperren]].',
'ipb-blockingself' => 'Du bist gerade dabei, dich selbst zu sperren! Möchtest du das wirklich tun?',
'ipb_expiry_invalid' => 'Die eingegebene Dauer ist ungültig.',
'ipb_expiry_temp' => 'Benutzernamens-Sperren mit der Verstecken-Option müssen permanent sein.',
'ipb_hide_invalid' => 'Dieses Konto kann nicht unterdrückt werden, da es zu viele Bearbeitungen aufweist.',
-'ipb_already_blocked' => '„$1“ wurde bereits gesperrt.',
+'ipb_already_blocked' => '„$1“ ist bereits gesperrt',
'ipb-needreblock' => '„$1“ ist bereits gesperrt. Möchtest du die Sperrparameter ändern?',
'ipb-otherblocks-header' => 'Andere {{PLURAL:$1|Sperre|Sperren}}',
'unblock-hideuser' => 'Dieser Benutzer kann nicht entsperrt werden, da dessen Benutzername versteckt wurde.',
'dec' => 'Kan',
# Categories related messages
-'pagecategories' => '{{PLURAL:$1|Kategori|Kategoriy}}',
+'pagecategories' => '{{PLURAL:$1|Kategoriye|Kategoriy}}',
'category_header' => 'Pelê ke kategoriya "$1" derê',
'subcategories' => 'Kategoriyê bınêni',
'category-media-header' => 'Medyawa ke kategoriya "$1" dera',
'talkpage' => 'Ena pele sero werêne',
'talkpagelinktext' => 'Mesac',
'specialpage' => 'Pela xısusiye',
-'personaltools' => 'Hacetê şexsi',
+'personaltools' => 'Haletê şexsi',
'postcomment' => 'Qısımo newe',
'articlepage' => 'Pela zerreki bıvêne',
'talk' => 'Werênayış',
'mwsuggest-disable' => 'Tewsiyay AJAXi bıgê',
'searcheverything-enable' => 'cayê nameyê hemi de bigêre',
'searchrelated' => 'eleqayî',
-'searchall' => 'têdıne',
+'searchall' => 'pêro',
'showingresults' => "Heta {{PLURAL:$1|'''1''' netice|'''$1''' neticeyan}} ke pê #'''$2''' başli beno ey bimocne .",
-'showingresultsnum' => "Heta binê {{PLURAL:$3|'''1''' netice|'''$3''' neticeyan}} ke pê #'''$2''' başli beno ey bimocne .",
+'showingresultsnum' => "'''$2''' netican ra nata {{PLURAL:$3|'''1''' netice|'''$3''' neticeyê}} cêrde liste biyê.",
'showingresultsheader' => "{{PLURAL:$5|Neticeyê '''$1''' of '''$3'''|Neticeyanê '''$1 - $2''' of '''$3'''}} qe '''$4'''",
'nonefound' => "'''Teme''': Teyna tay namecayan cıgeyro beno.
Pe verbendi ''all:'', vaceyê xo bıvurni ki contenti hemi cıgeyro (pelanê mınaqeşe, templatenan, ucb.) ya zi cıgeyro ser namecay ki tı wazeni.",
'listfiles_name' => 'Name',
'listfiles_user' => 'Karber',
'listfiles_size' => 'Gırdiye',
-'listfiles_description' => 'Şınasiyen',
+'listfiles_description' => 'Sılasnayış',
'listfiles_count' => 'Versiyoni',
# File description page
'statistics-header-users' => 'Îstatistiksê karberî',
'statistics-header-hooks' => 'Îstatistiksê binî',
'statistics-articles' => 'Pelanê tedesteyî',
-'statistics-pages' => 'Peli',
+'statistics-pages' => 'Peley',
'statistics-pages-desc' => 'Pelanê hemî ke wîkî de estê, pelanê mineqeşeyî, redireksiyon ucb... dehil o.',
'statistics-files' => 'Dosyayê bar biye',
'statistics-edits' => 'Amarê vurnayîşî ke wextê {{SITENAME}} ronayîşî ra',
# Special:DeletedContributions
'deletedcontributions' => 'İştiraqê karberan de besternayına',
'deletedcontributions-title' => 'Îştirakê karberî wederna',
-'sp-deletedcontributions-contribs' => 'iştıraqi',
+'sp-deletedcontributions-contribs' => 'pêşteni',
# Special:LinkSearch
'linksearch' => 'Gıreyê teberi cı geyrê',
'emailuser' => 'Ena karberi rê mesac bırse',
'emailuser-title-target' => 'Na E-postaya {{GENDER:$1|karberi}}ya',
'emailuser-title-notarget' => 'E-postaya karberi',
-'emailpage' => 'karberi re e-mail bışaw',
+'emailpage' => 'karberi re e-posta bırışê',
'emailpagetext' => 'no/na karberi re e-posta erşawıtışi de şıma pê forma cêrıni eşkeni kar bıkerî.
[[Special:Preferences|tercihanê şıma ye karberi]] de adresa e-posta ya ke şıma dayo, na adres qısmê adresa e-postayi de "From (kam ra)" asena, no sebebi ra gırewtox/e eşkeno/a direk cewab bıdo şıma.',
'usermailererror' => 'xizmetê e-postayi xeta da:',
'enotif_reset' => 'Pela pêro ziyaret kerde deye mor ke',
'enotif_newpagetext' => 'Ena yew pela newî ya.',
'enotif_impersonal_salutation' => '{{SITENAME}} karber',
-'changed' => 'vurniya',
+'changed' => 'vurneya',
'created' => 'viraziya',
'enotif_subject' => 'pelê {{SITENAME}}i $PAGETITLE, hetê/perrê $PAGEEDITOR $CHANGEDORCREATED',
'enotif_lastvisited' => 'ziyareta şıma ye peyini ra nata heme vuryayiş ê ke biyê bıewnê $1i re..',
'blanknamespace' => '(Ser)',
# Contributions
-'contributions' => 'İştirakê karberi',
+'contributions' => 'İştiraqê karberi',
'contributions-title' => '$1 de iştırakê karberi',
-'mycontris' => 'İştıraqi',
+'mycontris' => 'Pêşteni',
'contribsub2' => 'Qandê $1 ($2)',
'nocontribs' => 'Ena kriteriya de vurnayîş çini yo.',
'uctop' => '(ser)',
'blocklink' => 'kılit ke',
'unblocklink' => 'ake',
'change-blocklink' => 'kılit-kerdışi bıvurne',
-'contribslink' => 'iştıraqi',
+'contribslink' => 'pêşteni',
'emaillink' => 'e-poste bırışe',
'autoblocker' => 'Şıma otomatikmen kılit biy, çıke adresa şımawa \'\'IP\'\'y terefê "[[User:$1|$1]]" gureniyena.
Sebebê kılit-biyayışê $1\'i: "$2"o',
'xml-error-string' => '$1 çizgi de $2 col $3 (bit $4): $5',
'import-upload' => 'Dosyayê XML bar bike',
'import-token-mismatch' => "vindibiyayişê ma'lumatê hesabi. kerem kerê newe ra tesel/cereb bıkerê.",
-'import-invalid-interwiki' => 'Eya wîkî ra nieşkenî împort bike.',
+'import-invalid-interwiki' => 'Ena wiki ra azere kerdış nêbeno.',
'import-error-edit' => 'Pela " $1 " qandê vurnayışi aya nêgêrêna çıkı cı rê icazet nêdeyayo.',
'import-error-create' => 'Pela " $1 " qandê vıraştışi aya nêabêna çıkı cı rê icazet nêdeyayo.',
'import-error-interwiki' => 'Pela " $1 " qandê name dayışi aya nêgêrêna çıkı namey cı (interwiki) sero cırê ca abıryayo.',
'exif-ycbcrpositioning-1' => 'Wertekerdış',
'exif-ycbcrpositioning-2' => 'Wayırê-site',
-'exif-dc-contributor' => 'İştırakdari',
+'exif-dc-contributor' => 'Pêşteni',
'exif-dc-coverage' => 'Heruna yana wextin grotışa medya',
'exif-dc-date' => 'Tarix(i)',
'exif-dc-publisher' => 'Hesrekar',
# 'all' in various places, this might be different for inflected languages
'watchlistall2' => 'pêro',
-'namespacesall' => 'têde',
+'namespacesall' => 'pêro',
'monthsall' => 'pêro',
-'limitall' => 'hemi',
+'limitall' => 'pêro',
# E-mail address confirmation
'confirmemail' => 'Adresê e-posta tesdiq ker',
# Table pager
'ascending_abbrev' => 'berz',
'descending_abbrev' => 'nızm',
-'table_pager_next' => 'Pela badê cû',
+'table_pager_next' => 'Pela peyên',
'table_pager_prev' => 'Pela verêne',
'table_pager_first' => 'Pela jûyıne',
'table_pager_last' => 'Pela peyêne',
'specialpages-group-users' => 'Karber u heqqî',
'specialpages-group-highuse' => 'Peleyê ke vêşi karênê',
'specialpages-group-pages' => 'listeyanê pelan',
-'specialpages-group-pagetools' => 'Hacetê pelan',
+'specialpages-group-pagetools' => 'Haletê pelan',
'specialpages-group-wiki' => 'Malumatê wiki u haceti',
'specialpages-group-redirects' => 'Pela xasîyê ke heteneyayê',
-'specialpages-group-spam' => 'hacetê spami',
+'specialpages-group-spam' => 'haletê spami',
# Special:BlankPage
'blankpage' => 'Pela venge',
'youhavenewmessages' => 'Έχετε $1 ($2).',
'newmessageslink' => 'νέα μηνύματα',
'newmessagesdifflink' => 'τελευταία αλλαγή',
+'youhavenewmessagesfromusers' => 'Έχετε $1 από {{PLURAL:$3|ένα άλλο χρήστη|$3 χρήστες}} ($2).',
+'youhavenewmessagesmanyusers' => 'Έχετε $1 από πολλούς χρήστες ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|ένα νέο μήνυμα|νέα μηνύματα}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|τελευταία αλλαγή|τελευταίες αλλαγές}}',
'youhavenewmessagesmulti' => 'Έχετε νέα μηνύματα στο $1',
'editsection' => 'επεξεργασία',
'editold' => 'επεξεργασία',
'filereadonlyerror' => 'Δεν είναι δυνατή η τροποποίηση του αρχείου " $1 " επειδή το αποθετήριο αρχείων " $2 " είναι σε κατάσταση λειτουργίας μόνο για ανάγνωση.
Ο διαχειριστής που το κλείδωσε προσφέρει αυτή την αιτιολόγηση: " $3 ".',
+'exception-nologin' => 'Δεν έχετε συνδεθεί.',
+'exception-nologin-text' => 'Αυτή η σελίδα ή η ενέργεια απαιτεί να είστε {{GENDER:|συνδεμένος|συνδεμένη}} στο wiki.',
# Virus scanner
'virus-badscanner' => "Λάθος ρύθμιση: άγνωστος ανιχνευτής ιών: ''$1''",
μια έγκυρη ηλεκτρονική διεύθυνση στις [[Special:Preferences|Προτιμήσεις]]
για να στείλετε e-mail σε άλλους χρήστες.',
'emailuser' => 'Στείλτε μήνυμα σε αυτό τον χρήστη',
+'emailuser-title-target' => 'Αποστολή e-mail {{GENDER:$1|στο|στη}} χρήστη',
+'emailuser-title-notarget' => 'Αποστολή e-mail σε χρήστη',
'emailpage' => 'Αποστολή μηνύματος ηλεκτρονικού ταχυδρομείο στο χρήστη',
'emailpagetext' => 'Συπληρώνοντας την παρακάτω φόρμα θα στείλετε ένα μήνυμα εφόσον έχετε δηλώσει μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου στις [[Special:Preferences|προτιμήσεις χρήστη]]. Αυτή θα εμφανιστεί ως διεύθυνση αποστολέα του μηνύματος, ούτως ώστε ο παραλήπτης να μπορέσει να σας απαντήσει.',
'usermailererror' => 'Σφάλμα ηλεκτρονικού ταχυδρομείου:',
'rollback' => 'Επαναφορά επεξεργασιών',
'rollback_short' => 'Επαναφορά',
'rollbacklink' => 'Επαναφορά στην προηγούμενη',
+'rollbacklinkcount' => 'Επαναφορά $1 {{PLURAL:$1|επεξεργασίας|επεξεργασιών}}',
+'rollbacklinkcount-morethan' => 'επαναφορά περισσότερων από $1 {{PLURAL:$1|επεξεργασία|επεξεργασίες}}',
'rollbackfailed' => 'Η επαναφορά απέτυχε.',
'cantrollback' => 'Δεν είναι δυνατή η αναίρεση αυτής της αλλαγής, πρόκειται για την αρχική ενέργεια δημιουργίας της σελίδας.',
'alreadyrolled' => 'Αδύνατον να αναιρεθεί η τελευταία αλλαγή της σελίδας [[:$1]] από το χρήστη ([[User:$2|$2]] ([[User talk:$2|Συζήτηση]]){{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]), διότι κάποιος έχει ήδη αναιρέσει την αλλαγή ή έχει αλλάξει εκ νέου τη σελίδα.
# Info page
'pageinfo-title' => 'Πληροφορίες για "$1"',
-'pageinfo-header-edits' => 'Επεξεργασίες',
+'pageinfo-header-basic' => 'Βασικές πληροφορίες',
+'pageinfo-header-edits' => 'Ιστορικό επεξεργασίας',
+'pageinfo-header-restrictions' => 'Προστασία σελίδας',
+'pageinfo-header-properties' => 'Ιδιότητες σελίδας',
+'pageinfo-display-title' => 'Εμφάνιση τίτλου',
+'pageinfo-default-sort' => 'Προεπιλεγμένο κλειδί ταξινόμησης',
+'pageinfo-length' => 'Μήκος σελίδας (σε bytes)',
+'pageinfo-article-id' => 'Αναγνωριστικό σελίδας',
'pageinfo-views' => 'Αριθμός προβολών',
'pageinfo-watchers' => 'Αριθμός παρατηρητών',
'pageinfo-edits' => 'Αριθμός επεξεργασιών',
'spam_deleting' => 'All revisions contained links to $1, deleting',
# Info page
+'pageinfo-header' => '-', # do not translate or duplicate this message to other languages
'pageinfo-title' => 'Information for "$1"',
'pageinfo-header-basic' => 'Basic information',
'pageinfo-header-edits' => 'Edit history',
'pageinfo-magic-words' => 'Magic {{PLURAL:$1|word|words}} ($1)',
'pageinfo-hidden-categories' => 'Hidden {{PLURAL:$1|category|categories}} ($1)',
'pageinfo-templates' => 'Transcluded {{PLURAL:$1|template|templates}} ($1)',
+'pageinfo-footer' => '-', # do not translate or duplicate this message to other languages
# Skin names
'skinname-standard' => 'Classic', # only translate this message to other languages if you have to change it
'tog-externaldiff' => 'Utilizar diff externo por defecto (sólo para expertos, pues necesitas ajustes especiales en tu ordenador; [//www.mediawiki.org/wiki/Manual:External_editors más información])',
'tog-showjumplinks' => 'Habilitar enlaces de accesibilidad «saltar a»',
'tog-uselivepreview' => 'Usar live preview (JavaScript) (Experimental)',
-'tog-forceeditsummary' => 'Alertar al grabar sin resumen de edición.',
+'tog-forceeditsummary' => 'Avisar cuando grabe la página sin introducir un resumen de edición',
'tog-watchlisthideown' => 'Ocultar mis ediciones en la lista de seguimiento',
'tog-watchlisthidebots' => 'Ocultar ediciones de bots en la lista de seguimiento',
'tog-watchlisthideminor' => 'Ocultar ediciones menores en la lista de seguimiento',
'categorypage' => 'Ver página de categoría',
'viewtalkpage' => 'Ver discusión',
'otherlanguages' => 'Otros idiomas',
-'redirectedfrom' => '(Redirigido desde $1)',
+'redirectedfrom' => '(Redirigido desde «$1»)',
'redirectpagesub' => 'Página redirigida',
'lastmodifiedat' => 'Esta página fue modificada por última vez el $1, a las $2.',
'viewcount' => 'Esta página ha sido visitada {{PLURAL:$1|una vez|$1 veces}}.',
'privacypage' => 'Project:Política de protección de datos',
'badaccess' => 'Error de permisos',
-'badaccess-group0' => 'No tienes autorización para ejecutar la acción que ha solicitado.',
+'badaccess-group0' => 'No estás autorizado a ejecutar la acción solicitada.',
'badaccess-groups' => 'La acción que has solicitado está restringida a los usuarios {{PLURAL:$2|del grupo|de uno de estos $2 grupos}}: $1.',
'versionrequired' => 'La versión $1 de MediaWiki es necesaria para utilizar esta página',
'noarticletext-nopermission' => 'Actualmente no hay texto en esta página.
Puedes [[Special:Search/{{PAGENAME}}|buscar este título de página]] en otras páginas,
o <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar en los registros relacionados]</span>.',
-'missing-revision' => 'La revisión # $1 de la página denominada "{{PAGENAME}}" no existe.
-!¡ N!Esto es generalmente causado al seguir un enlace de historia obsoleto a una página que se ha borrado.!¡ N!Los detalles pueden encontrarse en el [{{fullurl: {{#Special:Log}} / delete|page = {{FULLPAGENAMEE}}}} registro de borrado].',
+'missing-revision' => 'La revisión #$1 de la página «{{PAGENAME}}» no existe.
+
+Esto suele deberse a seguir un enlace obsoleto hacia el historial de una página que ya ha sido borrada.
+Los detalles pueden encontrarse en el [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de borrado].',
'userpage-userdoesnotexist' => 'La cuenta de usuario «<nowiki>$1</nowiki>» no está registrada. Por favor comprueba si quieres crear o editar esta página.',
'userpage-userdoesnotexist-view' => 'La cuenta de usuario «$1» no está registrada.',
'blocked-notice-logextract' => 'Este usuario está actualmente bloqueado.
'editundo' => 'deshacer',
'diff-multi' => '(No se {{PLURAL:$1|muestra una edición intermedia realizada|muestran $1 ediciones intermedias realizadas}} por {{PLURAL:$2|un usuario|$2 usuarios}})',
'diff-multi-manyusers' => '(No se {{PLURAL:$1|muestra una edición intermedia|muestran $1 ediciones intermedias}} de {{PLURAL:$2|un usuario|$2 usuarios}})',
-'difference-missing-revision' => '{{PLURAL:$2|Un revisión| $2 revisiones}} de esta diferencia ( $1 ) no {{PLURAL:$2| ha siado encontrada|han sido encontradas}}.
-!¡ N!Esto es generalmente causado por seguir un enlace de diffs obsoletas a una página que ha sido borrada.!¡ N!Los detalles pueden encontrarse en el [{{fullurl:{{#Special:log}} / delete|page = {{FULLPAGENAMEE}}}} registro de borrado].',
+'difference-missing-revision' => 'No {{PLURAL:$2|se ha encontrado|se han encontrado}} {{PLURAL:$2|una revisión|$2 revisiones}} de esta diferencia ($1).
+
+Esto suele deberse a seguir un enlace obsoleto hacia una página que ya ha sido borrada.
+Los detalles pueden encontrarse en el [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de borrado].',
# Search results
'searchresults' => 'Resultados de la búsqueda',
$messages = array(
# User preference toggles
-'tog-underline' => 'Lingid alla kriipsutada',
+'tog-underline' => 'Linkide allakriipsutus:',
'tog-justify' => 'Lõikude rööpjoondus',
'tog-hideminor' => 'Peida pisiparandused viimastes muudatustes',
-'tog-hidepatrolled' => 'Peida viimaste muudatuste loetelus jälgimisloendis esitatavad muudatused',
+'tog-hidepatrolled' => 'Peida kontrollitud redaktsioonid viimastes muudatustes',
'tog-newpageshidepatrolled' => 'Peida uute lehtede loendis kontrollitud leheküljed',
'tog-extendwatchlist' => 'Laienda jälgimisloendit, et näha kõiki muudatusi, mitte vaid kõige värskemaid',
'tog-usenewrc' => 'Rühmita viimased muudatused ja muudatused jälgimisloendis lehekülje järgi (vaja JavaScripti)',
'tog-numberheadings' => 'Pealkirjade automaatnummerdus',
-'tog-showtoolbar' => 'Redigeerimise tööriistariba näitamine',
-'tog-editondblclick' => 'Artiklite redigeerimine topeltklõpsu peale (JavaScript)',
+'tog-showtoolbar' => 'Näita redigeerimise tööriistariba (vaja JavaScripti)',
+'tog-editondblclick' => 'Redigeeri lehekülgi topeltklõpsu peale (vaja JavaScripti)',
'tog-editsection' => 'Näita alaosade redigeerimise linke',
'tog-editsectiononrightclick' => 'Alusta alaosa redigeerimist paremklõpsuga alaosa pealkirjal (vaja JavaScripti)',
'tog-showtoc' => 'Näita sisukorda (lehtedel, millel on rohkem kui 3 pealkirja)',
'talk' => 'Arutelu',
'views' => 'vaatamisi',
'toolbox' => 'Tööriistad',
-'userpage' => 'Kasutajalehekülg',
+'userpage' => 'Vaata kasutajalehekülge',
'projectpage' => 'Vaata projektilehekülge',
'imagepage' => 'Vaata faililehekülge',
'mediawikipage' => 'Vaata sõnumi lehekülge',
-'templatepage' => 'Mallilehekülg',
+'templatepage' => 'Vaata malli lehekülge',
'viewhelppage' => 'Vaata abilehekülge',
-'categorypage' => 'Kategoorialehekülg',
-'viewtalkpage' => 'Arutelulehekülg',
+'categorypage' => 'Vaata kategooria lehekülge',
+'viewtalkpage' => 'Vaata arutelulehekülge',
'otherlanguages' => 'Teistes keeltes',
'redirectedfrom' => '(Ümber suunatud leheküljelt $1)',
'redirectpagesub' => 'Ümbersuunamisleht',
'viewhelppage' => 'نمایش صفحهٔ راهنما',
'categorypage' => 'نمایش صفحهٔ رده',
'viewtalkpage' => 'نمایش صفحهٔ بحث',
-'otherlanguages' => 'زبانهای دیگر',
+'otherlanguages' => 'بÙ\87 زباÙ\86â\80\8cÙ\87اÛ\8c دÛ\8cگر',
'redirectedfrom' => '(تغییرمسیر از $1)',
'redirectpagesub' => 'صفحهٔ تغییرمسیر',
'lastmodifiedat' => 'این صفحه آخرینبار در $1 ساعت $2 تغییر یافتهاست.',
'youhavenewmessages' => '$1 دارید ($2).',
'newmessageslink' => 'پیامهای جدید',
'newmessagesdifflink' => 'آخرین تغییر',
+'youhavenewmessagesfromusers' => 'شما $1 از {{PLURAL:$3| کاربر دیگر| $3 کاربر}} دارید ( $2 ).',
+'youhavenewmessagesmanyusers' => 'شما $1 از تعدادی کاربر دارید ( $2 ).',
+'newmessageslinkplural' => '{{PLURAL:$1|پیام جدید |پیام جدید}}',
+'newmessagesdifflinkplural' => '{{formatnum:$1}} {{PLURAL:$1|تغییر|تغییرات}} اخیر',
'youhavenewmessagesmulti' => 'پیامهای جدیدی در $1 دارید.',
'editsection' => 'ویرایش',
'editold' => 'ویرایش',
'dberrortext' => 'اشکال نحوی در درخواست فرستاده شده به پایگاه داده رخ داد.
دلیل این مشکل میتواند ایرادی در نرمافزار باشد.
آخرین درخواست که برای پایگاه داده فرستاد شد این بود:
-<blockquote style="direction:ltr;"><tt>$1</tt></blockquote>
-این درخواست از درون عملگر «<span class="ltr"><tt>$2</tt></span>» فرستاده شد.
+<blockquote style="direction:ltr;"><code>$1</code></blockquote>
+این درخواست از درون عملگر «<span class="ltr"><code>$2</code></span>» فرستاده شد.
پایگاه داده این خطا را بازگرداند:
-<div class="ltr"><tt>$3: $4</tt></div>',
+<div class="ltr"><samp>$3: $4</samp></div>',
'dberrortextcl' => 'اشکال نحوی در درخواست فرستاده شده به پایگاه داده رخ داد.
آخرین درخواستی که برای پایگاه داده فرستاد شد این بود:
<div class="ltr">$1</div>
'noarticletext-nopermission' => 'این صفحه هماکنون متنی ندارد.
شما میتوانید در دیگر صفحهها [[Special:Search/{{PAGENAME}}|این عنوان را جستجو کنید]]،
یا <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} سیاهههای مرتبط را بگردید]</span>.',
+'missing-revision' => 'ویرایش #$1 از صفحهٔ "{{PAGENAME}}" موجود نیست.
+
+معمولاً در اثر پیوند به تاریخچهٔ بهروز نشدهٔ صفحهٔ حذف شده است.
+میتوانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.',
'userpage-userdoesnotexist' => 'حساب کاربر «<nowiki>$1</nowiki>» ثبت نشدهاست.
لطفاً مطمئن شوید که میخواهید این صفحه را ایجاد یا ویرایش کنید.',
'userpage-userdoesnotexist-view' => 'حساب کاربری «$1» ثبت نشدهاست.',
'blocked-notice-logextract' => 'دسترسی این کاربر در حال حاضر بسته است.
آخرین مورد سیاهه قطع دسترسی در زیر آمدهاست:',
-'clearyourcache' => "'''نکته:''' پس از ذخیرهکردن ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.
+'clearyourcache' => "''نکته:''' پس از ذخیرهکردن ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.
*'''فایرفاکس / سافاری:''' کلید ''Shift'' را نگه دارید و روی دکمهٔ ''Reload'' کلیک کنید، یا کلیدهای ''Ctrl-F5'' یا ''Ctrl-R'' را با هم فشار دهید (در رایانههای اپل مکینتاش کلیدهای ''⌘-R'')
*'''گوگل کروم:'''کلیدهای ''Ctrl+Shift+R'' را با هم فشار دهید. (در رایانههای اپل مکینتاش کلیدهای ''⌘-Shift-R'')
*'''اینترنت اکسپلورر:''' کلید ''Ctrl'' را نگهدارید و روی دکمهٔ ''Refresh'' کلیک کنید، یا کلیدهای ''Ctrl-F5'' را با هم فشار دهید
-*'''کانکوئرر:''' روی دکمهٔ ''Reload'' کلیک کنید و یا کلید ''F5'' را فشار دهید
*'''اپرا:''' حافظهٔ نهانی مرورگر را از طریق منوی ''Tools → Preferences'' پاک کنید",
'usercssyoucanpreview' => "'''نکته:''' پیش از ذخیهکردن فایل CSS یا JS خود، با دکمهٔ '''{{int:showpreview}}''' آن را آزمایش کنید.",
'userjsyoucanpreview' => "'''نکته:''' پیش از ذخیرهکردن فایل CSS یا JS خود، با دکمهٔ '''{{int:showpreview}}''' آن را آزمایش کنید.",
'expansion-depth-exceeded-warning' => 'صفحه حداکثر عمق بسط دادن تجاوز کرد',
'parser-unstrip-loop-warning' => 'حلقه در دستور unstrip پیدا شد',
'parser-unstrip-recursion-limit' => 'از حداکثر ارجاع در دستور unstrip تجاوز شد ($1)',
+'converter-manual-rule-error' => 'خطا در ساختار کتابچهٔ مبدل زبان',
# "Undo" feature
'undo-success' => 'این ویرایش را میتوان خنثی کرد.
'editundo' => 'خنثیسازی',
'diff-multi' => '({{PLURAL:$1|یک|$1}} ویرایش میانی توسط {{PLURAL:$2|یک|$2}} کاربر نشان داده نشدهاست)',
'diff-multi-manyusers' => '({{PLURAL:$1|یک|$1}} ویرایش میانی توسط بیش از {{PLURAL:$2|یک|$2}} کاربر نشان داده نشدهاست)',
+'difference-missing-revision' => '{{PLURAL:$2|یک ویرایش|$2 ویرایش}} از تفاوت نسخهها ($1) {{PLURAL:$2|یافت|یافت}} نشد.
+
+معمولاً در اثر پیوند به تاریخچهٔ بهروز نشدهٔ صفحهٔ حذف شده است.
+میتوانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.',
# Search results
'searchresults' => 'نتایج جستجو',
'shared-repo-from' => 'از $1',
'shared-repo' => 'یک مخزن مشترک',
'shared-repo-name-wikimediacommons' => 'ویکیانبار',
+'upload-disallowed-here' => 'متاسفانه شما نمی توانید این نگاره را بازنویس کنید.',
# File reversion
'filerevert' => 'واگردانی $1',
'disambiguations' => 'صفحههای دارای پیوند به صفحههای ابهامزدایی',
'disambiguationspage' => 'Template:ابهامزدایی',
-'disambiguations-text' => "صفحههای زیر پیوندی به یک '''صفحهٔ ابهامزدایی''' هستند.
-اÛ\8cÙ\86 صÙ\81ØÙ\87â\80\8cÙ\87ا باید در عوض به موضوعات مرتبط پیوند داده شوند.<br />
+'disambiguations-text' => "صفحههای زیر حاوی حداقل یک پیوند به یک '''صفحهٔ ابهامزدایی''' هستند.
+اÛ\8cÙ\86 صÙ\81ØÙ\87â\80\8cÙ\87ا Ø´اید در عوض به موضوعات مرتبط پیوند داده شوند.<br />
یک صفحه هنگامی صفحهٔ ابهامزدایی در نظر گرفته میشود که در آن از الگویی که به [[MediaWiki:Disambiguationspage]] پیوند دارد استفاده شده باشد.",
'doubleredirects' => 'تغییرمسیرهای دوتایی',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|بایت|بایت}}',
'ncategories' => '$1 {{PLURAL:$1|رده|رده}}',
+'ninterwikis' => '$1 {{PLURAL:$1|میانویکی|میانویکی}}',
'nlinks' => '$1 {{PLURAL:$1|پیوند|پیوند}}',
'nmembers' => '$1 {{PLURAL:$1|عضو|عضو}}',
'nrevisions' => '$1 {{PLURAL:$1|نسخه|نسخه}}',
'mostlinkedtemplates' => 'الگوهایی که بیشتر از همه به آنها پیوند داده شدهاست',
'mostcategories' => 'صفحههای دارای بیشترین رده',
'mostimages' => 'پروندههایی که بیشتر از همه به آنها پیوند داده شدهاست',
+'mostinterwikis' => 'صفحههای دارای بیشترین میانویکی',
'mostrevisions' => 'صفحههای دارای بیشترین نسخه',
'prefixindex' => 'تمام صفحهها با پیشوند',
'prefixindex-namespace' => 'همهٔ صفحههای دارای پیشوند (فضاینام $1)',
'mailnologin' => 'نشانیای از فرستنده موجود نیست',
'mailnologintext' => 'برای فرستادن رایانامه به کاربران دیگر باید [[Special:UserLogin|به سامانه وارد شوید]] و نشانی رایانامهٔ معتبری در [[Special:Preferences|ترجیحات]] خود داشته باشید.',
'emailuser' => 'فرستادن نامه به این کاربر',
+'emailuser-title-target' => 'ایمیل این {{GENDER:$1| کاربر}}',
+'emailuser-title-notarget' => 'رایانامه به کاربر',
'emailpage' => 'رایانامه به کاربر',
'emailpagetext' => 'شما میتوانید از فرم زیر برای ارسال یک رایانامه به این کاربر استفاده کنید.
نشانی رایانامهای که در [[Special:Preferences|ترجیحات کاربریتان]] وارد کردهاید در نشانی فرستنده (From) نامه خواهد آمد، تا گیرنده بتواند پاسخ دهد.',
'import-interwiki-templates' => 'تمام الگوها را شامل شود',
'import-interwiki-submit' => 'درونریزی شود',
'import-interwiki-namespace' => 'فضای نام مقصد:',
+'import-interwiki-rootpage' => 'مقصد صفحه ٔ مبنا (اختیاری):',
'import-upload-filename' => 'نام پرونده:',
'import-comment' => 'توضیح:',
'importtext' => 'لطفاً پرونده را از ویکی منبع با کمک [[Special:Export|ابزار برونبری]] دریافت کنید.
'import-error-interwiki' => 'صفحه «$1» وارد نشد. چون نام آن برای پیوند خارجی (interwiki) رزرو شدهاست.',
'import-error-special' => 'صفحه «$1» درونریزی نشد، چرا که متعلق به فضای نام غیرمجاز است.',
'import-error-invalid' => 'صفحه "$1" به دلیل نامعتبر بودن نامش وارد نمیشود.',
+'import-options-wrong' => '{{PLURAL:$2|جزئیات|جزئیات}} اشتباه: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'با توجه به ریشه صفحه عنوان نامعتبر است.',
+'import-rootpage-nosubpage' => 'فضای نام "$1" صفحهٔ مبنا اجازهٔ زیرصفحه نمیدهد.',
# Import log
'importlogpage' => 'سیاههٔ درونریزیها',
# Info page
'pageinfo-title' => 'اطلاعات در مورد «$1»',
-'pageinfo-header-edits' => 'ویرایش',
+'pageinfo-header-basic' => 'اطلاعات اولیه',
+'pageinfo-header-edits' => 'ویرایش تاریخچه',
+'pageinfo-header-restrictions' => 'حفاظت از صفحه',
+'pageinfo-header-properties' => 'ويژگيهای صفحه',
+'pageinfo-display-title' => 'نمایش عنوان',
+'pageinfo-default-sort' => 'کلید مرتبسازی پیشفرض',
+'pageinfo-length' => 'حجم صفحه (بایت)',
+'pageinfo-article-id' => 'شناسهٔ صفحه',
+'pageinfo-robot-policy' => 'وضعیت موتور جستجو',
+'pageinfo-robot-index' => 'فهرستپذیر',
+'pageinfo-robot-noindex' => 'عدم فهرستپذیری',
'pageinfo-views' => 'شمار بازدیدها',
-'pageinfo-watchers' => 'شمار پیگیریکنندگان',
-'pageinfo-edits' => 'شمار ویرایشها',
-'pageinfo-authors' => 'شمار نویسندگان یکتا',
+'pageinfo-watchers' => 'شمار پیگیریکنندگان صفحه',
+'pageinfo-redirects-name' => 'تغییرمسیرها به این صفحه',
+'pageinfo-subpages-name' => 'زیرصفحههای این صفحه',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|تغییرمسیر|تغییرمسیر}}; $3 {{PLURAL:$3|غیرتغییرمسیر|غیرتغییرمسیر}})',
+'pageinfo-firstuser' => 'بهوجود آورندهٔ صفحه',
+'pageinfo-firsttime' => 'زمان ایجاد صفحه',
+'pageinfo-lastuser' => 'آخرین ویرایشگر',
+'pageinfo-lasttime' => 'تاریخ آخرین ویرایش',
+'pageinfo-edits' => 'شمار کلی ویرایشها',
+'pageinfo-authors' => 'تعداد کلی نویسندگان یکتا',
+'pageinfo-recent-edits' => 'شماره ویرایشهای اخیر (در $1 گذشته)',
+'pageinfo-recent-authors' => 'تعداد نویسندگان یکتای اخیر',
+'pageinfo-restriction' => 'محافظت صفحه ( <code>{{lcfirst:$1}}</code> )',
+'pageinfo-magic-words' => '{{PLURAL:$1|حرف|حروف}} جادویی ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1| ردهٔ|ردهٔ}} پنهان ( $1 )',
+'pageinfo-templates' => '{{PLURAL:$1|الگو|الگو}} استفادهشده ($1)',
# Skin names
'skinname-standard' => 'کلاسیک',
'file-info-size-pages' => '<span style="direction:ltr">$1 × $2</span> نقطه، حجم پرونده: $3، نوع MIME پرونده: $4، $5 صفحه',
'file-nohires' => 'تفکیکپذیری بالاتری در دسترس نیست.',
'svg-long-desc' => 'پروندهٔ اسویجی، با ابعاد <span dir="ltr">$1 × $2</span> پیکسل، اندازهٔ پرونده: $3',
+'svg-long-desc-animated' => 'پروندهٔ اسویجی متحرک، با ابعاد <span dir="ltr">$1 × $2</span> پیکسل، اندازهٔ پرونده: $3',
'show-big-image' => 'تصویر با تفکیکپذیری بالاتر',
'show-big-image-preview' => 'اندازهٔ این پیشنمایش: $1.',
'show-big-image-other' => '{{PLURAL:$2|کیفیت|کیفیتهای}} دیگر: $1.',
'file-info-png-looped' => 'چرخشدار',
'file-info-png-repeat' => '$1 {{PLURAL:$1|بار|بار}} پخش شد',
'file-info-png-frames' => '$1 {{PLURAL:$1|قاب|قاب}}',
+'file-no-thumb-animation' => "'''توجه: به علت مسائل فنی پیشنمایش پرونده به صورت متحرک نمایش داده نمیشود.'''",
+'file-no-thumb-animation-gif' => "'''توجه:به علت مسائل فنی پیشنمایش پروندههای GIF مانند این پرونده، به صورت متحرک نمایش داده نمیشود.'''",
# Special:NewFiles
'newimages' => 'نگارخانهٔ پروندههای جدید',
پیوندهایی بعدی در همان سطر استثنا در نظر گرفته میشوند.',
# Metadata
-'metadata' => 'Ù\85تاداده',
+'metadata' => 'Ù\81راداده',
'metadata-help' => 'این پرونده حاوی اطلاعات اضافهایاست که احتمالاً دوربین دیجیتال یا پویشگری که در ایجاد یا دیجیتالیکردن آن به کار رفته آن را افزودهاست. اگر پرونده از وضعیت ابتداییاش تغییر داده شده باشد آنگاه ممکن است شرح و تفصیلات موجود اطلاعات تصویر را تماماً بازتاب ندهد.',
'metadata-expand' => 'نمایش جزئیات تفصیلی',
'metadata-collapse' => 'نهفتن جزئیات تفصیلی',
'tagline' => '{{SITENAME}}',
'help' => 'Ohje',
'search' => 'Haku',
-'searchbutton' => 'Etsi',
+'searchbutton' => 'Hae',
'go' => 'Siirry',
'searcharticle' => 'Siirry',
'history' => 'Historia',
'faqpage' => 'Project:Quèstions sovent posâyes',
# Vector skin
-'vector-action-addsection' => 'Apondre un sujèt',
+'vector-action-addsection' => 'Apondre na chousa',
'vector-action-delete' => 'Suprimar',
'vector-action-move' => 'Renomar',
'vector-action-protect' => 'Protègiér',
'laggedslavemode' => "'''Atencion :''' cela pâge pôt pas contegnir tôs los dèrriérs changements fêts.",
'readonly' => 'Bâsa de donâs vèrrolyêye',
'enterlockreason' => 'Balyéd la rêson du vèrroly et pués n’èstimacion de la sina durâ',
-'readonlytext' => 'Ora la bâsa de donâs est vèrrolyêye por les entrâs novèles et los ôtros changements, probâblament por pèrmetre la sina mantegnence, dês cen tot tornerat en ôrdre.
+'readonlytext' => 'Ora la bâsa de donâs est vèrrolyêye por les entrâs novèles et los ôtros changements, de sûr por pèrmetre la sina mantegnence, dês cen tot tornerat en ôrdre.
L’administrator que l’at vèrrolyê at balyê cet’èxplicacion : $1',
'missing-article' => 'La bâsa de donâs at pas trovâ lo tèxto d’una pâge qu’el arêt diu trovar, avouéc lo titro « $1 » $2.
'password-login-forbidden' => 'L’usâjo de cél nom d’utilisator et de cél contresegno est étâ dèfendu.',
'mailmypassword' => 'Recêvre un contresegno novél per mèssageria èlèctronica',
'passwordremindertitle' => 'Contresegno temporèro novél por {{SITENAME}}',
-'passwordremindertext' => 'Quârqu’un (probâblament vos, avouéc l’adrèce IP $1) at demandâ un contresegno
+'passwordremindertext' => 'Quârqu’un (probâblament vos, dês l’adrèce IP $1) at demandâ un contresegno
novél por {{SITENAME}} ($4). Un contresegno temporèro est étâ fêt por
l’utilisator « $2 » et est « $3 ». S’o ére voutra entencion, vos vos devréd
branchiér et pués chouèsir un contresegno novél.
-Voutron contresegno temporèro èxpirerat dens $5 jorn{{PLURAL:$5||s}}.
+Voutron contresegno temporèro èxpirerat dens {{PLURAL:$5|yon jorn|$5 jorns}}.
-Se cela demanda vint pas de vos ou ben se vos vos rapelâd ora
-de voutron contresegno et que vos souhètâd pas més nen changiér, vos
+Se cela demanda vint pas de vos ou ben que vos vos éte rapelâ
+de voutron contresegno et que vos souhètâd pas més lo changiér, vos
pouede ignorar ceti mèssâjo et continuar a empleyér voutron viely contresegno.',
'noemail' => 'Niona adrèce èlèctronica est étâye encartâye por l’utilisator « $1 ».',
'noemailcreate' => 'Vos dête balyér n’adrèce èlèctronica valida',
'passwordreset-text' => 'Rempléd ceti formulèro por recêvre un mèssâjo de sovegnence des dètalys de voutron compto.',
'passwordreset-legend' => 'Tornar inicialisar lo contresegno',
'passwordreset-disabled' => 'La remisa a zérô des contresegnos est étâye dèsactivâye sur ceti vouiqui.',
-'passwordreset-pretext' => '{{PLURAL:$1||Buchiéd yon des bocons de balyês ce-desot}}',
-'passwordreset-username' => 'Nom d’usanciér :',
+'passwordreset-pretext' => '{{PLURAL:$1||Buchiéd yona de les piéces de donâs ce-desot}}',
+'passwordreset-username' => 'Nom d’utilisator :',
'passwordreset-domain' => 'Domêno :',
'passwordreset-capture' => 'Vêre lo mèssâjo que rèsulte ?',
-'passwordreset-capture-help' => 'Se vos pouentâd cela câsa, lo mèssâjo (avouéc lo contresegno temporèro) vos serat montrâ en mémo temps que serat mandâ a l’usanciér.',
+'passwordreset-capture-help' => 'Se vos pouentâd cela câsa, lo mèssâjo (avouéc lo contresegno temporèro) vos serat fêt vêre quand serat mandâ a l’utilisator.',
'passwordreset-email' => 'Adrèce èlèctronica :',
'passwordreset-emailtitle' => 'Dètalys du compto dessus {{SITENAME}}',
-'passwordreset-emailtext-ip' => 'Quârqu’un (probâblament vos, avouéc l’adrèce IP $1) at demandâ un rapèl des dètalys
-de voutron compto por {{SITENAME}} ($4). {{PLURAL:$3|Ceti compto usanciér est associyê|Cetos comptos usanciérs sont associyês}}
-a cela adrèce èlèctronica :
+'passwordreset-emailtext-ip' => 'Quârqu’un (probâblament vos, dês l’adrèce IP $1) at demandâ na sovegnence des dètalys
+de voutron compto por {{SITENAME}} ($4). {{PLURAL:$3|Ceti compto utilisator est associyê|Cetos comptos utilisators sont associyês}}
+a cel’adrèce èlèctronica :
$2
-{{PLURAL:$3|Cél contresegno temporèro èxpirerat|Celos contresegnos temporèros èxpireront}} dens $5 jorn{{PLURAL:$5||s}}.
-Ora, vos vos dête branchiér et pués chouèsir un contresegno novél. Se cela demanda vint pas de vos,
-ou ben se vos vos rapelâd ora de voutron contresegno originâl et que vos souhètâd pas més nen changiér,
-vos pouede ignorar ceti mèssâjo et continuar a utilisar voutron viely contresegno.',
-'passwordreset-emailtext-user' => 'L’usanciér $1 dessus {{SITENAME}} at demandâ un rapèl des dètalys
-de voutron compto por {{SITENAME}} ($4). {{PLURAL:$3|Ceti compto usanciér est associyê|Cetos comptos usanciérs sont associyês}}
-a cela adrèce èlèctronica :
+{{PLURAL:$3|Cél contresegno temporèro èxpirerat|Celos contresegnos temporèros èxpireront}} dens {{PLURAL:$5|yon jorn|$5 jorns}}.
+Ora vos vos dête branchiér et pués chouèsir un contresegno novél. Se cela demanda vint pas de vos
+ou ben que vos vos éte rapelâ de voutron contresegno originâl et que vos souhètâd pas més lo changiér,
+vos pouede ignorar ceti mèssâjo et continuar a empleyér voutron viely contresegno.',
+'passwordreset-emailtext-user' => 'L’utilisator $1 dessus {{SITENAME}} at demandâ na sovegnence des dètalys
+de voutron compto por {{SITENAME}} ($4). {{PLURAL:$3|Ceti compto utilisator est associyê|Cetos comptos utilisators sont associyês}}
+a cel’adrèce èlèctronica :
$2
-{{PLURAL:$3|Cél contresegno temporèro èxpirerat|Celos contresegnos temporèros èxpireront}} dens $5 jorn{{PLURAL:$5||s}}.
-Ora, vos vos dête branchiér et pués chouèsir un contresegno novél. Se cela demanda vint pas de vos,
-ou ben se vos vos rapelâd ora de voutron contresegno originâl et que vos souhètâd pas més nen changiér,
-vos pouede ignorar ceti mèssâjo et continuar a utilisar voutron viely contresegno.',
-'passwordreset-emailelement' => 'Nom d’usanciér : $1
+{{PLURAL:$3|Cél contresegno temporèro èxpirerat|Celos contresegnos temporèros èxpireront}} dens {{PLURAL:$5|yon jorn|$5 jorns}}.
+Ora vos vos dête branchiér et pués chouèsir un contresegno novél. Se cela demanda vint pas de vos
+ou ben que vos vos éte rapelâ de voutron contresegno originâl et que vos souhètâd pas més lo changiér,
+vos pouede ignorar ceti mèssâjo et continuar a empleyér voutron viely contresegno.',
+'passwordreset-emailelement' => 'Nom d’utilisator : $1
Contresegno temporèro : $2',
-'passwordreset-emailsent' => 'Un mèssâjo de rapèl at étâ mandâ.',
-'passwordreset-emailsent-capture' => 'Un mèssâjo de rapèl at étâ mandâ, qu’est montrâ ce-desot.',
-'passwordreset-emailerror-capture' => 'Un mèssâjo de rapèl at étâ fêt, qu’est montrâ ce-desot, mas l’èxpèdicion a l’usanciér at pas reussia : $1',
+'passwordreset-emailsent' => 'Un mèssâjo de sovegnence est étâ mandâ.',
+'passwordreset-emailsent-capture' => 'Un mèssâjo de sovegnence est étâ mandâ, qu’est fêt vêre ce-desot.',
+'passwordreset-emailerror-capture' => 'Un mèssâjo de sovegnence est étâ fêt, qu’est fêt vêre ce-desot, mas l’èxpèdicion a l’utilisator at pas reussi : $1',
# Special:ChangeEmail
'changeemail' => 'Changiér l’adrèce èlèctronica',
-'changeemail-header' => 'Changiér l’adrèce èlèctronica',
-'changeemail-text' => 'Rempléd ceti formulèro por changiér voutra adrèce èlèctronica. Vos devréd buchiér voutron contresegno por confirmar cél changement.',
-'changeemail-no-info' => 'Vos dête étre branchiê por avêr accès a cela pâge.',
+'changeemail-header' => 'Changiér l’adrèce èlèctronica du compto',
+'changeemail-text' => 'Rempléd ceti formulèro por changiér voutron adrèce èlèctronica. Vos devréd buchiér voutron contresegno por confirmar cél changement.',
+'changeemail-no-info' => 'Vos dête étre branchiê por arrevar tot drêt a cela pâge.',
'changeemail-oldemail' => 'Adrèce èlèctronica d’ora :',
'changeemail-newemail' => 'Novèla adrèce èlèctronica :',
'changeemail-none' => '(niona)',
'changeemail-cancel' => 'Anular',
# Edit page toolbar
-'bold_sample' => 'Tèxto en grâs',
-'bold_tip' => 'Tèxto en grâs',
-'italic_sample' => 'Tèxto en étalico',
-'italic_tip' => 'Tèxto en étalico',
+'bold_sample' => 'Tèxto grâs',
+'bold_tip' => 'Tèxto grâs',
+'italic_sample' => 'Tèxto étalico',
+'italic_tip' => 'Tèxto étalico',
'link_sample' => 'Titro du lim',
'link_tip' => 'Lim de dedens',
'extlink_sample' => 'http://www.example.com titro du lim',
'extlink_tip' => 'Lim de defôr (oubliâd pas lo prèfixo http://)',
-'headline_sample' => 'Tèxto de sot-titro',
+'headline_sample' => 'Tèxto du titro',
'headline_tip' => 'Sot-titro nivél 2',
'nowiki_sample' => 'Buchiéd lo tèxto pas formatâ ique',
'nowiki_tip' => 'Ignorar lo formatâjo vouiqui',
'image_sample' => 'Ègzemplo.jpg',
-'image_tip' => 'Fichiér entrebetâ',
+'image_tip' => 'Fichiér apondu',
'media_sample' => 'Ègzemplo.ogg',
'media_tip' => 'Lim de vers un fichiér',
-'sig_tip' => 'Voutra signatura avouéc la dâta',
+'sig_tip' => 'Voutra signatura avouéc la dâta et hora',
'hr_tip' => 'Legne plana (pas nen abusar)',
# Edit pages
'summary' => 'Rèsumâ :',
-'subject' => 'Sujèt / titro :',
+'subject' => 'Chousa / titro :',
'minoredit' => 'Petiôt changement',
'watchthis' => 'Siuvre ceta pâge',
'savearticle' => 'Sôvar la pâge',
'template-protected' => '(air a dhìon)',
'template-semiprotected' => '(air a leth-dhìon)',
'hiddencategories' => "Tha an duilleag seo 'na ball de {{PLURAL:$1|1 roinn-seòrsa fhalaichte|$1 roinn-seòrsa fhalaichte|1 roinn-seòrsa fhalaichte|$1 roinn-seòrsa fhalaichte|$1 roinnean-seòrsa falaichte|$1 roinn-seòrsa fhalaichte}}:",
+'nocreatetitle' => 'Tha cruthachadh dhuilleagan cuingichte',
+'nocreatetext' => "Chuir {{SITENAME}} bacadh air cruthachadh de dhuilleagan ùra.
+'S urrainn dhut tilleadh is duilleag a tha ann mu thràth a dheasachadh no [[Special:UserLogin|clàradh a-steach no cunntas a chruthachadh]].",
+'nocreate-loggedin' => 'Chan eil cead agad duilleagan ùra a chruthachadh.',
+'sectioneditnotsupported-title' => 'Chan eil taic ri deasachadh earrannan',
+'sectioneditnotsupported-text' => 'Chan eil taic ri deasachadh earrannan air an duilleag seo.',
+'permissionserrors' => "Meareachd leis a' chead",
+'permissionserrorstext' => 'Chan eil cead agad sin a dhèanamh air sgàth {{PLURAL:$1|an adhbhair|nan adhbharan|an adhbhair|nan adhbharan|nan adhbharan}} a leanas:',
'permissionserrorstext-withaction' => 'Chan eil cead agad airson "$2" air sgàth {{PLURAL:$1|an adhbhair|nan adhbharan|an adhbhair|nan adhbharan|nan adhbharan}} a leanas:',
'recreate-moveddeleted-warn' => "'''Rabhadh: Tha thu gu bhith ath-chruthachadh duilleag a chaidh a sguabadh às roimhe.'''
Seo dhut loga an sguabaidh às agus a' ghluasaid mar fhiosrachadh dhut:",
'moveddeleted-notice' => "Chaidh an duilleag seo a sguabadh às.
Chì thu loga an sguabaidh às agus a' ghluasaid gu h-ìosal mar fhiosrachadh dhut.",
+'log-fulllog' => 'Seall an loga slàn',
+'edit-hook-aborted' => 'Sguireadh dhen deasachadh ri linn dubhan.
+Cha deach adhbhar a thoirt seachad.',
+'edit-gone-missing' => "Cha b' urrainn dhuinn an duilleag ath-nuadhachadh.
+Tha coltas gun deach a sguabadh às.",
+'edit-conflict' => 'Còmhstri deasachaidh.',
+'edit-no-change' => "Chaidh an obair-dheasachaidh agad a leigeil seachad a chionn 's nach do dh'atharraich thu dad.",
+'edit-already-exists' => "Cha b' urrainn dhuinn an duilleag ùr a chruthachadh.
+Tha e ann mu thràth.",
# Parser/template warnings
+'expensive-parserfunction-warning' => "'''Rabhadh:''' Tha cus expensive parser function calls san duilleag seo.
+
+Bu chòir nas lugha na $2 {{PLURAL:$2|call|calls}} a bhith ann ach tha {{PLURAL:$1|$1 call|$1 calls}} ann.",
+'expensive-parserfunction-category' => 'Duilleagan le cus expensive parser function calls',
'post-expand-template-inclusion-warning' => "'''Rabhadh:''' Tha meud na teamplaide ro mhòr.
Cha dèid cuid dhith a ghabhail a-steach.",
'post-expand-template-inclusion-category' => "Duilleagan far a bheil meud nan teamplaidean a' dol thairis air na tha ceadaichte",
'post-expand-template-argument-warning' => "'''Rabhadh:''' Tha aon argamaid teamplaid air a' char as lugha air an duilleag seo aig a bheil meud leudachaidh ro mhòr.
Chaidh na h-argamaidean sinn a leigeil seachad.",
'post-expand-template-argument-category' => 'Duilleagan air an deach argamaidean teamplaidean fhàgail às',
+'parser-template-loop-warning' => 'Mhothaicheadh do lùb teamplaid: [[$1]]',
+
+# Account creation failure
+'cantcreateaccounttitle' => 'Cha ghabh an cunntas a chruthachadh',
# History pages
'viewpagelogs' => 'Seall logaichean na duilleige seo',
'history-show-deleted' => 'Na chaidh sguabadh às a-mhàin',
'histfirst' => 'As sine',
'histlast' => 'As ùire',
+'historyempty' => '(falamh)',
# Revision feed
+'history-feed-title' => 'Eachdraidh nam mùthaidhean',
+'history-feed-description' => 'Eachdraidh nam mùthaidhean airson na duilleige seo air an uici',
'history-feed-item-nocomment' => '$1 $2',
+'history-feed-empty' => "Chan eil an duilleag a dh'iarr thu ann.
+Dh'fhaoidte gun deach a sguabadh às an uici no gun deach ainm ùr a chur air.
+Feuch is [[Special:Search|lorg duilleagan ùra iomachaidh air an uici]]",
# Revision deletion
+'rev-deleted-comment' => '(chaidh gearr-chunntas an deasachaidh a thoirt air falbh)',
+'rev-deleted-user' => '(chaidh an t-ainm-cleachdaiche a thoirt air falbh)',
+'rev-deleted-event' => '(chaidh gnìomh an loga a thoirt air falbh)',
'rev-delundel' => 'seall/falaich',
+'rev-showdeleted' => 'seall',
+'revdelete-hide-user' => 'Falaich ainm-cleachdaiche/seòladh IP an deasaiche',
'revdel-restore' => 'mùth follaiseachd',
'revdel-restore-deleted' => 'mùthaidhean a chaidh a sguabadh às',
'revdel-restore-visible' => 'mùthaidhean faicsinneach',
+# History merging
+'mergehistory-from' => 'An duilleag thùsail:',
+'mergehistory-reason' => 'Adhbhar:',
+
# Merge log
'revertmerge' => 'Dì-aontaich',
'search-interwiki-more' => '(barrachd)',
'search-mwsuggest-enabled' => 'le molaidhean',
'search-mwsuggest-disabled' => 'gun mholaidhean',
+'search-relatedarticle' => 'Co-cheangailte',
'searchrelated' => 'co-cheangailte',
'searchall' => 'a h-uile',
'showingresults' => "A' nochdadh suas gu $1 {{PLURAL:$1|toradh|thoradh|toradh|thoradh|toraidhean|toradh}} gu h-ìosal a' tòiseachadh le #'''$2'''.",
'powersearch-redir' => 'Seall ath-sheòlaidhean',
'powersearch-field' => 'Lorg',
+# Quickbar
+'qbsettings-none' => 'Chan eil gin',
+
# Preferences page
'preferences' => 'Roghainnean',
'mypreferences' => 'Mo roghainnean',
'prefs-skin' => 'Bian',
'skin-preview' => 'Ro-shealladh',
'prefs-beta' => 'Feartan Beta',
+'prefs-datetime' => 'Ceann-là is àm',
'prefs-labs' => 'Feartan nan deuchainn-lannan',
'prefs-personal' => "Pròifil a' chleachdaiche",
+'prefs-rc' => 'Mùthaidhean ùra',
+'prefs-watchlist' => 'An clàr-faire',
+'prefs-resetpass' => 'Atharraich am facal-faire',
+'prefs-changeemail' => 'Atharraich am post-d',
+'prefs-setemail' => 'Suidhich seòladh puist-d',
+'prefs-email' => "Roghainnean a' phuist-d",
+'prefs-rendering' => 'Coltas',
'saveprefs' => 'Sàbhail',
'resetprefs' => 'Falamhaich atharrachaidhean nach deach a shàbhaladh fhathast',
+'restoreprefs' => 'Aisig na roghainnean bunaiteach uile',
+'prefs-editing' => "A' deasachadh",
+'prefs-edit-boxsize' => 'Meud uinneag an deasachaidh.',
'rows' => 'Sreathan',
'columns' => 'Colbhan',
+'searchresultshead' => 'Lorg',
+'stub-threshold-disabled' => 'À comas',
'savedprefs' => 'Tha na roghainnean agad air an sàbhaladh.',
+'timezonelegend' => 'Roinn-tìde:',
+'localtime' => 'An t-àm ionadail:',
+'servertime' => 'Àm an fhrithealaichte:',
+'timezoneregion-africa' => 'Afraga',
+'timezoneregion-america' => 'Aimeireaga',
+'timezoneregion-antarctica' => 'An Antartaig',
+'timezoneregion-arctic' => 'An Arctaig',
+'timezoneregion-asia' => 'Àisia',
+'timezoneregion-atlantic' => 'An Cuan Siar',
+'timezoneregion-australia' => 'Astràilia',
+'timezoneregion-europe' => 'An Roinn-Eòrpa',
+'timezoneregion-indian' => 'An Cuan Innseanach',
+'timezoneregion-pacific' => 'An Cuan Sèimh',
'default' => 'an roghainn bhunaiteach',
+'prefs-custom-css' => 'CSS gnàthaichte',
'youremail' => 'Post-dealain:',
'username' => 'Ainm-cleachdaiche:',
'yourrealname' => "An dearbh ainm a th' ort:",
'yourlanguage' => 'Cànan:',
'yournick' => 'Earr-sgrìobhadh ùr:',
+'yourgender' => 'Gnè:',
+'gender-unknown' => 'Gun innse',
+'gender-male' => 'Fireann',
+'gender-female' => 'Boireann',
+'email' => 'Post-d:',
'prefs-help-email' => "Chan leig thu leas post-dealain a chur ann ach bidh feum air ma dhìochuimhnicheas tu am facal-faire agad 's ma dh'iarras tu fear ùr.",
'prefs-help-email-others' => "'S urrainn dhut leigeil le daoine eile post-dealain a chur thugad tro cheangal air an duilleag agad.
Chan fhaicear an seòladh fhèin nuair a chuireas cuideigin post-dealain thugad.",
+'prefs-advancedediting' => 'Roghainnean adhartach',
+'prefs-advancedrc' => 'Roghainnean adhartach',
+'prefs-advancedrendering' => 'Roghainnean adhartach',
+'prefs-advancedsearchoptions' => 'Roghainnean adhartach',
+'prefs-advancedwatchlist' => 'Roghainnean adhartach',
# User rights
'userrights-changeable-col' => 'Buidhnean as urrainn dhut atharrachadh',
# Groups
'group-sysop' => 'Rianadairean',
+'group-user-member' => '{{GENDER:$1|cleachdaiche}}',
+'group-bot-member' => '{{GENDER:$1|bot}}',
+'group-sysop-member' => '{{GENDER:$1|rianaire}}',
+'group-bureaucrat-member' => '{{GENDER:$1|biùrocrat}}',
+
+'grouppage-user' => '{{ns:project}}:Cleachdaichean',
'grouppage-sysop' => '{{ns:project}}:Rianadairean',
# User rights log
'rightslog' => "Loga còraichean a' chleachdaiche",
+'rightsnone' => '(chan eil gin)',
# Associated actions - in the sentence "You do not have permission to X"
'action-edit' => 'deasaich an duilleag seo',
# Upload
'upload' => 'Luchdaich suas faidhle',
+'uploadbtn' => 'Luchdaich suas faidhle',
'uploadlogpage' => 'Loga an luchdaidh suas',
'filename' => 'Ainm-faidhle',
'filedesc' => 'Gearr-chunntas',
+'fileuploadsummary' => 'Gearr-chunntas:',
'filestatus' => 'Cor dlighe-sgrìobhaidh:',
'ignorewarning' => 'Leig seachad an rabhadh agus sàbhail am faidhle co-dhiù',
'badfilename' => 'Ainm ìomhaigh air atharrachadh ri "$1".',
'htmlform-float-invalid' => 'Vrijednost koju ste naveli nije broj.',
'htmlform-int-toolow' => 'Vrijednost koju ste naveli je ispod minimuma od $1',
'htmlform-int-toohigh' => 'Vrijednost koju ste naveli je iznad maksimuma od $1',
-'htmlform-required' => 'Ova vrijednost je potrebna',
+'htmlform-required' => 'Ova je vrijednost potrebna',
'htmlform-submit' => 'Pošalji',
'htmlform-reset' => 'Poništi izmjene',
'htmlform-selectorother-other' => 'Drugi',
'youhavenewmessages' => 'Դուք ունեք $1 ($2)։',
'newmessageslink' => 'նոր ուղերձներ',
'newmessagesdifflink' => 'վերջին փոփոխությունը',
+'newmessageslinkplural' => '{{PLURAL:$1|նոր հաղորդագրություն|նոր հաղորդագրություններ}}',
+'newmessagesdifflinkplural' => '$1 {{PLURAL:$1|փոփոխում|փոփոխումներ}}',
'youhavenewmessagesmulti' => 'Դուք նոր ուղերձներ եք ստացել $1 վրա',
'editsection' => 'խմբագրել',
'editold' => 'խմբագրել',
'youhavenewmessages' => 'Addaanka ti $1 ($2).',
'newmessageslink' => 'dagiti baro a mensahe',
'newmessagesdifflink' => 'naudi a sinukatan',
+'youhavenewmessagesfromusers' => 'Adda $1 manipud {{PLURAL:$3|ti sabali nga agar-aramat|$3 kadagiti sabsabali nga agar-aramat}} ($2).',
+'youhavenewmessagesmanyusers' => 'Adda $1 fmanipud kadagiti adu nga agar-aramat ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|baro a mensahem|dagiti baro a mensahem}}',
+'newmessagesdifflinkplural' => 'kinaudi {{PLURAL:$1|a sinukatan|a sinuksukatan}}',
'youhavenewmessagesmulti' => 'Adda dagiti baro a mensahem iti $1',
'editsection' => 'urnosen',
'editold' => 'urnosen',
# General errors
'error' => 'Biddut',
'databaseerror' => 'Biddut iti database',
-'dberrortext' => 'Adda biddut ti database ti gramatika na a panagsapul.
+'dberrortext' => 'Adda napasamak a biddut ti nakaibatayan ti datos a panagsapul ti gramatika.
Adda ngata kiteb iti software.
-Ti kinaudia a panagpadas ti panagsapul ti database ket:
-<blockquote><tt>$1</tt></blockquote>
-naggapu ti uneg ti pamay-an "<tt>$2</tt>".
-Ti database ket nangipatulod ti biddut "<tt>$3: $4</tt>".',
+Ti kinaudi a panagpadas ti panagsapul ti nakaibatayan ti datos ket:
+<blockquote><code>$1</code></blockquote>
+naggapu ti uneg ti pamay-an "<code>$2</code>".
+Ti nakaibatayan ti datos ket nangipatulod ti biddut "<samp>$3: $4</samp>".',
'dberrortextcl' => 'Adda biddut ti database ti gramatika a panagsapul.
Ti kinaudi a panagsapul ti database ket:
"$1"
'remembermypassword' => 'Laglagipem ti iseserrekko iti daytoy a pagbasabasa (para iti kapaut iti $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}})',
'securelogin-stick-https' => 'Agyan ka a nakasilpo iti HTTPS no nakastrekka',
'yourdomainname' => 'Ti bukodmo a pagturayan:',
+'password-change-forbidden' => 'Saanmo a mabalin ti mangbaliw kadagiti kontrasenias iti daytoy a wiki.',
'externaldberror' => 'Adda biddut idi ti panakapasingked ti database wenno saanmo a mabalin ti agpabaro ti bukodmo a ruar a pakabilangan.',
'login' => 'Sumrek',
'nav-login-createaccount' => 'Sumrek / agaramid ti pakabilangan',
Mabalinmo ti [[Special:Search/{{PAGENAME}}|agsapul iti kastoy a titulo ti panid]] iti sabsabali a pampanid,
<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} agbirukka],
wenno <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} agbiruk ka kadagiti maikabagian a listaan]</span>.',
+'missing-revision' => 'Ti panagbalbaliw ti #$1 tipanid a nanaganan ti "{{PAGENAME}}" ket awan.
+
+Daytoy ket kadawyan agapuanan babaen ti samaganad a panilpo ti baak a pakasaritaan iti maysa a panid a naikkaten.
+Dagiti salaysay ket mabalin a mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].',
'userpage-userdoesnotexist' => 'Ti pakabilangan ti agar-aramat "$1" ket saan a nakarehistro.
Pangngaasi a kitaem no kayatmo ti agaramid/urnosen daytoy a panid.',
'userpage-userdoesnotexist-view' => 'Ti pakabilangan ni agar-aramat "$1" ket saan a nakarehistro.',
'blocked-notice-logextract' => 'Agdama a naserraan daytoy nga agar-aramat.
Ti naudi a listaan ti panaka-serra ket adda dita baba tapno mausar a reperensia:',
-'clearyourcache' => "'''Pakaammo:''' No nalpas ka nga agidulin, kuma ket masapul nga ipalabas ti cahe ti pinagbasabasam tapno makita dagiti sinukatam.
+'clearyourcache' => "'''Pakaammo:''' No nalpaskan nga agiduldulin, kuma ket masapul nga ipalabas ti cahe ti pinagbasabasam tapno makita dagiti sinukatam.
* '''Firefox / Safari:''' Tenglen ti ''Sukatan'' bayat nga agtakla ti ''Ikarga manen'', wenno itakla ti ''Ctrl-F5'' wenno''Ctrl-R'' (''⌘-R'' Mac)
* '''Google Chrome:''' Itakla ti ''Ctrl-Shift-R'' (''⌘-Shift-R'' iti Mac)
* '''Internet Explorer:''' Tenglen ti ''Ctrl'' bayat nga agtakla ti ''Ipasaradiwa'', wenno itakla ti ''Ctrl-F5''
-* '''Konqueror:''' Itakla ti ''Ikarga manen'' wenno itakla ti ''F5''
* '''Opera:''' Dalusan ti cache iti ''Ramramit → Kakaykayatan''",
'usercssyoucanpreview' => "'''Paammo:''' Usaren ti \"{{int:showpreview}}\" buton ti panagsubok ti baro a CSS sakbay nga idulinmo.",
'userjsyoucanpreview' => "'''Paammo:''' Usaren ti \"{{int:showpreview}}\" buton ti panagsubok ti baro a JavaScript sakbay nga idulinmo.",
'expansion-depth-exceeded-warning' => 'Ti panid ket nasurokanna ti kauneg ti panagpadakkel',
'parser-unstrip-loop-warning' => 'Adda nakita a di-naukisan a silo',
'parser-unstrip-recursion-limit' => 'Ti di-naukisan a panagsumro manen a patingga ket nasurokan ($1)',
+'converter-manual-rule-error' => 'Adda biddut a naduktalan idiay manual nga alagaden ti panagbalbaliw ti pagsasao',
# "Undo" feature
'undo-success' => 'Ti panag-urnos ket saan a maisubli.
'editundo' => 'ibabawi',
'diff-multi' => '({{PLURAL:$1|Maysa nga agtengnga a panangbalbaliw|Dagiti $1 nga agtennga a panangbalbaliw}} babaen {{PLURAL:$2|ti agararamat|dagiti $2 nga agararamat}} ti saan a naipakita)',
'diff-multi-manyusers' => '({{PLURAL:$1|Maysa nga agtengnga a panangbalbaliw|Dagiti $1 nga agtengnga a panangbalbaliw}} babaen ti ad-adu ngem $2 {{PLURAL:$2|nga agar-aramat|kadagiti agar-aramat}} a saan a naipakita)',
+'difference-missing-revision' => '{{PLURAL:$2|Maysa a panagbalbaliw|$2 kadagiti panagbalbaliw}} iti daytoy a paggiddiatan ($1) {{PLURAL:$2|ket ti|ket dagiti}} saan a naburikan.
+
+Daytoy ket kadawyan a gapuanan babaen ti sumaganad a nabaak a panilpo tipaggiddiatan ti maysa a panid a naikkaten.
+Dagiti salaysay ket mabalin a mabirukan idiay [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} listaan ti panagikkat].',
# Search results
'searchresults' => 'Dagiti nagbanagan ti panagbiruk',
'right-writeapi' => 'Panagusar ti panagsurat nga API',
'right-delete' => 'Ikkaten dagiti panid',
'right-bigdelete' => 'Ikkaten dagiti panid nga adda dagiti dakkel a pakasaritaanna',
+'right-deletelogentry' => 'Ikkaten ken isubli ti panagikkat dagiti naisangsangayan a naikabil ti listaan',
'right-deleterevision' => 'Ikkaten ken ipasubli dagiti nainagan a pinagbaliwan ti panid',
'right-deletedhistory' => 'Kitaen dagiti naikabil a pakasaritaan, nga awan kaniada kadagiti nairaman a testo',
'right-deletedtext' => 'Kitaen dagiti naikkat a testo ken dagiti nasukatan a nagbaetan dagiti binaliwan',
'uploadnewversion-linktext' => 'Mangipan ti kabarbaro a bersion iti daytoy a papeles',
'shared-repo-from' => 'Naggapo iti $1',
'shared-repo' => 'iti pagbingbingayan a nagikabilan',
+'upload-disallowed-here' => 'Daksanggasat a saanmo a mabalin a suratan manen daytoy nga imahen.',
# File reversion
'filerevert' => 'Isubli ti $1',
'disambiguations' => 'Dagiti panid a nakasilpo kadagiti panangilawlawag',
'disambiguationspage' => 'Template:Panangilawlawag',
-'disambiguations-text' => "Dagiti sumaganad a panid ket nakasilpo iti '''panangilawlawag a panid'''.
-Ngem agpasilpo da kuma ti husto a topiko.<br />
-Ti panid ket matrato a kas panangilawlawag a panid no agusar ti plantilia a nakasilpo idiay [[MediaWiki:Disambiguationspage]]",
+'disambiguations-text' => "Dagiti sumaganad a panid ket aglaon ti saan a basbasit ngem maysa a panilpo iti '''panangilawlawag a panid'''.
+Dagitoy ket mabalinno a nasken nga isilpo kadagiti embes a nasaysayaat a panid.<br />
+Ti panid ket matrato a kas panangilawlawag a panid no agusar ti plantilia a nakasilpo idiay
+ [[MediaWiki:Disambiguationspage]]",
'doubleredirects' => 'Dagiti namindua a naibaw-ing',
'doubleredirectstext' => 'Daytoy a panid ket ilistana dagiti panid nga agbaw-ing kadagiti sabsabali a baw-ing a pampanid.
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|a byte|kadagiti byte}}',
'ncategories' => '$1 {{PLURAL:$1|a kategoria|kadagiti kategoria}}',
+'ninterwikis' => '$1 {{PLURAL:$1|interwiki|dagiti interwiki}}',
'nlinks' => '$1 {{PLURAL:$1|a panilpo|kadagiti panilpo}}',
'nmembers' => '$1 {{PLURAL:$1|a kameng|kadagiti kameng}}',
'nrevisions' => '$1 {{PLURAL:$1|a panagbalbaliw|kadagiti panagbalbaliw}}',
'mostlinkedtemplates' => 'Dagiti plantilia a kaaduan iti nakasilpo',
'mostcategories' => 'Dagiti panid a kaaduan kadagiti kategoria',
'mostimages' => 'Dagiti papeles a kaaduan iti nakasilpo',
+'mostinterwikis' => 'Dagiti panid a kaaduan kadagiti interwiki',
'mostrevisions' => 'Dagiti artikulo a kaaduan ti pannakabalbaliwna',
'prefixindex' => 'Dagiti amin a panid nga adda ti pasaruno na',
'prefixindex-namespace' => 'Amin a panid nga addaan ti pasaruno ($1 nagan ti luglugar)',
'mailnologin' => 'Awan ti pagipatulodan a pagtaengan',
'mailnologintext' => 'Masapul a [[Special:UserLogin|nakastrekka]] ken adda umisu nga e-surat a pagtaengan idiay [[Special:Preferences|kaykayatmo]] ti agipatulod ti e-surat kadagiti sabsabali nga agar-aramat.',
'emailuser' => 'E-suratan daytoy nga agar-aramat',
+'emailuser-title-target' => 'E-suratam daytoy nga {{GENDER:$1|agar-aramat}}',
+'emailuser-title-notarget' => 'E-suratan ti agar-aramat',
'emailpage' => 'E-suratan ti agar-aramat',
'emailpagetext' => 'Mabalinmo nga usaren ti kinabuklan dita baba nga agipatulod ti e-surat a mensahe daytoy nga agar-aramat.
Ti e-surat nga inkabilmo idiay [[Special:Preferences|kakaykayatam]] ket agparang a kas "Naggapu" a pagtaengan ti e-surat, tapno ti nagipatulodam ket makasungbat kenka.',
'rollback' => 'Isubli dagiti panag-urnos',
'rollback_short' => 'Isubli',
'rollbacklink' => 'isubli',
+'rollbacklinkcount' => 'agisubli ti $1 {{PLURAL:$1|nga inurnos|nga inururnos}}',
+'rollbacklinkcount-morethan' => 'agisubli ti ad-adu ngem $1 {{PLURAL:$1|nga inurnos|nga inururnos}}',
'rollbackfailed' => 'Napaay ti panangisubli',
'cantrollback' => 'Saan a maisubli ti panagurnos;
ti naudi a nakaaramid ket iti laeng nagsurat daytoy a panid..',
'import-interwiki-templates' => 'Ikabil amin dagiti plantilia',
'import-interwiki-submit' => 'Agala',
'import-interwiki-namespace' => 'Pangipanan ti nagan ti lugar:',
+'import-interwiki-rootpage' => 'Papanan a ramut ti panid (mapili):',
'import-upload-filename' => 'Nagan ti papeles:',
'import-comment' => 'Komentario:',
'importtext' => 'Pangngaasi nga ipanmo ti papeles a naggapu iti nagtaudan a wiki nga agusar ti [[Special:Export|agipan]].',
'import-error-interwiki' => 'Ti panid ti "$1" ket saan a naala ngamin ket ti nagan ket nailasin para iti ruar a panagsilpo (interwiki).',
'import-error-special' => 'Ti panid ti "$1" ket saan a naala ngamin ket bukod ti espesial a nagan a lugar a saan nga agpalubos ti pampanid.',
'import-error-invalid' => 'Ti panid ti "$1" ket saan a naala ngamin ket ti nagan ket imbalido.',
+'import-options-wrong' => 'Saan nga husto {{PLURAL:$2|a pagpilian|a pagpilpilian}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'Ti naited a ramut ti panid ket imbalido a titulo.',
+'import-rootpage-nosubpage' => 'Ti nagan ti lugar ti "$1" iti ramut ti panid ket saan amangpalubos kadagiti apo ti panid.',
# Import log
'importlogpage' => 'Alaen ti listaan',
# Info page
'pageinfo-title' => 'Pakaammo para iti "$1"',
-'pageinfo-header-edits' => 'Dagiti inurnos',
+'pageinfo-header-basic' => 'Kangrunaan a pakaammuan',
+'pageinfo-header-edits' => 'Pakasaritaan ti inurnos',
+'pageinfo-header-restrictions' => 'Panagsalaknib ti panid',
+'pageinfo-header-properties' => 'Tagtagikua ti panid',
+'pageinfo-display-title' => 'Iparang ti titulo',
+'pageinfo-default-sort' => 'Kasisigud a kangrunaan a panagilasin',
+'pageinfo-length' => 'Kaatiddog ti panid (kadagiti bytes)',
+'pageinfo-article-id' => 'ID ti panid',
+'pageinfo-robot-policy' => 'Kasasaad ti panagbiruk a makina',
+'pageinfo-robot-index' => 'Mabalin a maipasurotan',
+'pageinfo-robot-noindex' => 'Saan a mabalin a maipasurotan',
'pageinfo-views' => 'Bilang dagiti panagkita',
-'pageinfo-watchers' => 'Bilang dagiti agbuybuya',
-'pageinfo-edits' => 'Bilang dagiti inurnos:',
-'pageinfo-authors' => 'Ti bilang dagiti sabsabali a mannurat',
+'pageinfo-watchers' => 'Bilang dagiti agbuybuya ti panid',
+'pageinfo-redirects-name' => 'Maibaw-ing ti daytoy a panid',
+'pageinfo-subpages-name' => 'Apo dagiti panid ti daytoy a panid',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|baw-ing|bawbaw-ing}}; $3 {{PLURAL:$3|saan a baw-ing|saan a bawbaw-ing}})',
+'pageinfo-firstuser' => 'Nagpartuat ti panid',
+'pageinfo-firsttime' => 'Petsa a panakapartuat ti panid',
+'pageinfo-lastuser' => 'Kinaudi a nagurnos',
+'pageinfo-lasttime' => 'Petsa ti kinaudi a panag-urnos',
+'pageinfo-edits' => 'Dagup a bilang dagiti inurnos',
+'pageinfo-authors' => 'Dagup a bilang dagiti naisangsangayn a mannurat',
+'pageinfo-recent-edits' => 'Itay nabiit a bilang dagiti inurnos (ti uneg ti napalabas ti $1)',
+'pageinfo-recent-authors' => 'Itay nabiit a bilang dagiti naisangsangayan a mannurat',
+'pageinfo-restriction' => 'Panagsalaknib ti panid (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => 'Salamangka {{PLURAL:$1|a balikas|a balbalikas}} ($1)',
+'pageinfo-hidden-categories' => 'Nailemmeng {{PLURAL:$1|a kategoria|a katkategoria}} ($1)',
+'pageinfo-templates' => 'Nailak-am {{PLURAL:$1|a plantilia|a planplantilia}} ($1)',
# Patrolling
'markaspatrolleddiff' => 'Markaan a kas napatruliaan',
'file-info-size-pages' => '$1 × $2 dagiti piksel, kadakkel ti papeles: $3, kita ti MIME: $4, $5 {{PLURAL:$5|panid|pampanid}}',
'file-nohires' => 'Awan ti mabalin a nangatngato a resolusion.',
'svg-long-desc' => 'SVG a papeles, babassit ngem $1 × $2 pixels, kadakkel ti papeles: $3',
+'svg-long-desc-animated' => 'Naanimado nga SVG a papeles, babassit ngem $1 × $2 pixels, kadakkel ti papeles: $3',
'show-big-image' => 'Sibubukel a resolusion',
'show-big-image-preview' => 'Kadakkel na daytoy a pagpadas: $1.',
'show-big-image-other' => 'Sabali {{PLURAL:$2|a resolusion|kadagiti resolusion}}: $1.',
'file-info-png-looped' => 'nasiluan',
'file-info-png-repeat' => 'pinaayayam ti $1 {{PLURAL:$1|a beses|a beses}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|a kuadro| kadagiti kuadro}}',
+'file-no-thumb-animation' => "'''Paammo: Gapu kadagiti teknikal a panakaipatingga, dagiti bassit a ladawan ti daytoy a papeles ket saanto a maanimado.'''",
+'file-no-thumb-animation-gif' => "'''Paammo: Gapu kadagiti teknikal a panakaipatingga, dagiti bassit a ladawan ti nangato a resolusion dagiti GIF nga imahen a kas daytoy ket saanto a maanimado.'''",
# Special:NewFiles
'newimages' => 'Galeria dagiti kabarbaro a papeles',
* <span class="mw-specialpagecached">Cached nga espesial a pampanid (baka nagpaso).</span>',
'specialpages-group-maintenance' => 'Dagiti pagsimpa a padamag',
'specialpages-group-other' => 'Sabsabali pay nga espesial a pampanid',
-'specialpages-group-login' => 'Sumrek / agrehistro',
+'specialpages-group-login' => 'Sumrek / agaramid ti pakabilangan',
'specialpages-group-changes' => 'Kaudian a sinukatan ken listaan',
'specialpages-group-media' => 'Dagiti padamag ti media ken panag-ipan',
'specialpages-group-users' => 'Dagiti agar-aramat ken karkarbengan',
'api-error-file-too-large' => 'Ti papeles nga intedmo ket dakkel unay.',
'api-error-filename-tooshort' => 'Ti nagan daytoy a papeles ket bassit unay.',
'api-error-filetype-banned' => 'Ti kita daytoy a papeles ket maiparit.',
-'api-error-filetype-banned-type' => 'Ti $1 {{PLURAL:$4|ket saan a mapalubusan a kita ti papeles|ket dagiti saan a mapalubusan a kita ti papeles}}. Ti mapalubusan{{PLURAL:$3|a kita ti papeles ket|kadagiti kita ti papeles ket}} $2.',
+'api-error-filetype-banned-type' => 'Ti $1 {{PLURAL:$4|ket saan a mapalubusan a kita ti papeles|ket dagiti saan a mapalubusan a kita ti papeles}}. Ti mapalubusan {{PLURAL:$3|a kita ti papeles ket|kadagiti kita ti papeles ket}} $2.',
'api-error-filetype-missing' => 'Ti papeles ket agkurang ti pagpa-atiddog.',
'api-error-hookaborted' => 'Ti panagbabaro a pinadasmo ket napasardeng iti pangpa-atiddog a kawit.',
'api-error-http' => 'Kinauneg a biddut: Saan a makaikabit idiay server.',
'fewestrevisions' => 'Greinar með fæstar breytingar',
# Miscellaneous special pages
-'nbytes' => '$1 {{PLURAL:$1|bæt|bæt}}',
+'nbytes' => '$1 {{PLURAL:$1|bæt|bæti}}',
'ncategories' => '$1 {{PLURAL:$1|flokkur|flokkar}}',
'nlinks' => '$1 {{PLURAL:$1|tengill|tenglar}}',
'nmembers' => '$1 {{PLURAL:$1|meðlimur|meðlimir}}',
L'ultimo elemento del registro dei blocchi è riportato di seguito per informazione:",
'clearyourcache' => "'''Nota:''' dopo aver salvato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti.
*'''Firefox / Safari''': tenere premuto il tasto delle maiuscole e fare clic su ''Ricarica'', oppure premere ''Ctrl-F5'' o ''Ctrl-R'' (''⌘-R'' su Mac)
-*'''Google Chrome''': fare clic su ''Ricarica'', oppure premere ''Ctrl-R'' o ''Ctrl-Shift-R'' (''⌘-Shift-R'' su un Mac)
+*'''Google Chrome''': premere ''Ctrl-Shift-R'' (''⌘-Shift-R'' su un Mac)
*'''Internet Explorer''': tenere premuto il tasto ''Ctrl'' mentre si fa clic su ''Refresh'', oppure premere ''Ctrl-F5''
*'''Opera''': svuotare completamente la cache dal menu ''Strumenti → Preferenze''",
'usercssyoucanpreview' => "'''Suggerimento:''' usa il pulsante 'Visualizza anteprima' per provare il tuo nuovo CSS prima di salvarlo.",
$messages = array(
# User preference toggles
-'tog-underline' => 'リンクの下線:',
+'tog-underline' => 'リンクの下線:',
'tog-justify' => '段落に均等割り付けを設定',
'tog-hideminor' => '最近の更新に細部の編集を表示しない',
'tog-hidepatrolled' => '最近の更新に巡回済みの編集を表示しない',
'tog-enotifminoredits' => 'ページやファイルへの細部の編集でもメールを受け取る',
'tog-enotifrevealaddr' => '通知メールで自分のメールアドレスを明示',
'tog-shownumberswatching' => 'ページをウォッチしている利用者数を表示',
-'tog-oldsig' => '既存の署名:',
-'tog-fancysig' => '署名をウィキ文として扱う(自動リンクなし)',
+'tog-oldsig' => '既存の署名:',
+'tog-fancysig' => '署名をウィキ文として扱う (自動リンクなし)',
'tog-externaleditor' => '既定で編集に外部アプリケーションを使用(上級者向け、コンピューターに特殊な設定が必要。[//www.mediawiki.org/wiki/Manual:External_editors 詳細])',
'tog-externaldiff' => '差分表示に外部アプリケーションを使用(上級者向け、コンピューターに特殊な設定が必要。[//www.mediawiki.org/wiki/Manual:External_editors 詳細])',
'tog-showjumplinks' => '利用しやすさ向上のための「{{int:jumpto}}」リンクを有効にする',
'tog-watchlisthideown' => 'ウォッチリストに自分の編集を表示しない',
'tog-watchlisthidebots' => 'ウォッチリストにボットによる編集を表示しない',
'tog-watchlisthideminor' => 'ウォッチリストに細部の編集を表示しない',
-'tog-watchlisthideliu' => 'ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«ã\83ã\82°ã\82¤ã\83³å\88©ç\94¨è\80\85ã\81®編集を表示しない',
-'tog-watchlisthideanons' => 'ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«å\8c¿å\90\8då\88©ç\94¨è\80\85ã\81®編集を表示しない',
+'tog-watchlisthideliu' => 'ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«ã\83ã\82°ã\82¤ã\83³å\88©ç\94¨è\80\85ã\81«ã\82\88ã\82\8b編集を表示しない',
+'tog-watchlisthideanons' => 'ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«å\8c¿å\90\8då\88©ç\94¨è\80\85ã\81«ã\82\88ã\82\8b編集を表示しない',
'tog-watchlisthidepatrolled' => 'ウォッチリストに巡回済みの編集を表示しない',
'tog-ccmeonemails' => '他の利用者に送信したメールの控えを自分にも送信',
'tog-diffonly' => '差分の下にページ内容を表示しない',
'welcomecreation' => '== ようこそ、$1 さん! ==
アカウントが作成されました。
[[Special:Preferences|{{SITENAME}}の個人設定]]の変更も忘れないようにしてください。',
-'yourname' => '利用者名:',
-'yourpassword' => 'パスワード:',
-'yourpasswordagain' => 'パスワード再入力:',
+'yourname' => '利用者名:',
+'yourpassword' => 'パスワード:',
+'yourpasswordagain' => 'パスワード再入力:',
'remembermypassword' => 'このブラウザーにログイン情報を保存 (最長 $1 {{PLURAL:$1|日|日間}})',
'securelogin-stick-https' => 'ログイン後にHTTPS接続を維持',
-'yourdomainname' => 'ドメイン:',
+'yourdomainname' => 'ドメイン:',
'password-change-forbidden' => 'このウィキではパスワードを変更できません。',
'externaldberror' => '外部の認証データベースでエラーが発生したか、または外部アカウント情報の更新が許可されていません。',
'login' => 'ログイン',
'resetpass-submit-cancel' => '中止',
'resetpass-wrong-oldpass' => '仮パスワードまたは現在のパスワードが正しくありません。
パスワードを既に変更した、または新しい仮パスワードを依頼した可能性があります。',
-'resetpass-temp-password' => '仮パスワード:',
+'resetpass-temp-password' => '仮パスワード:',
# Special:PasswordReset
'passwordreset' => 'パスワードの再設定',
'passwordreset-legend' => 'パスワードの再設定',
'passwordreset-disabled' => 'パスワードの再設定は、このウィキでは無効になっています。',
'passwordreset-pretext' => '{{PLURAL:$1||下記のデータのいずれか 1 つを入力してください}}',
-'passwordreset-username' => '利用者名:',
-'passwordreset-domain' => 'ドメイン:',
+'passwordreset-username' => '利用者名:',
+'passwordreset-domain' => 'ドメイン:',
'passwordreset-capture' => '送信されるメールの内容を表示しますか?',
'passwordreset-capture-help' => 'このボックスにチェックを入れると、利用者に送信されるメールの内容(仮パスワードを含む)をあなたも閲覧できます。',
-'passwordreset-email' => 'メールアドレス:',
+'passwordreset-email' => 'メールアドレス:',
'passwordreset-emailtitle' => '{{SITENAME}}上のアカウントの詳細',
'passwordreset-emailtext-ip' => 'どなたか(おそらくあなた、IP アドレス $1)が {{SITENAME}} ($4) での
あなたのアカウントの詳細情報を送信するよう申請しました。
'recreate-moveddeleted-warn' => "'''警告:以前削除されたページを再作成しようとしています。'''
このページの編集を続行するのが適切かどうかご確認ください。
-å\8f\82è\80\83ã\81®ã\81\9fã\82\81以ä¸\8bã\81«ã\81\93ã\81®ã\83\9aã\83¼ã\82¸ã\81®å\89\8aé\99¤ã\81¨ç§»å\8b\95ã\81®è¨\98é\8c²ã\82\92表示します:",
+å\8f\82è\80\83ã\81¾ã\81§ã\81«ã\80\81ã\81\93ã\81®ã\83\9aã\83¼ã\82¸ã\81®å\89\8aé\99¤ã\81¨ç§»å\8b\95ã\81®è¨\98é\8c²ã\82\92以ä¸\8bã\81«示します:",
'moveddeleted-notice' => 'このページは削除されています。
参考のため、このページの削除と移動の記録を以下に表示します。',
'log-fulllog' => '完全な記録を閲覧',
現在操作できる追放とブロックの一覧については[[Special:BlockList|ブロックの一覧]]を参照してください。',
# History merging
-'mergehistory' => 'ページ履歴の統合',
+'mergehistory' => 'ページの履歴の統合',
'mergehistory-header' => 'このページでは、ある元ページの履歴を新しいページに統合できます。
この変更を行ってもページの履歴の連続性が確実に保たれるようにしてください。',
'mergehistory-box' => '2ページの過去の版を統合する:',
# Preferences page
'preferences' => '個人設定',
'mypreferences' => '個人設定',
-'prefs-edits' => '編集回数:',
+'prefs-edits' => '編集回数:',
'prefsnologin' => 'ログインしていません',
'prefsnologintext' => '個人設定を変更するためには<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ログイン]</span>する必要があります。',
'changepassword' => 'パスワードの変更',
'prefs-personal' => '利用者情報',
'prefs-rc' => '最近の更新',
'prefs-watchlist' => 'ウォッチリスト',
-'prefs-watchlist-days' => 'ウォッチリストの表示日数:',
+'prefs-watchlist-days' => 'ウォッチリストの表示日数:',
'prefs-watchlist-days-max' => '最大 $1 {{PLURAL:$1|日間}}',
-'prefs-watchlist-edits' => '拡張ウォッチリストの表示件数:',
+'prefs-watchlist-edits' => '拡張ウォッチリストの表示件数:',
'prefs-watchlist-edits-max' => '最大数:1000',
-'prefs-watchlist-token' => 'ウォッチリストのトークン:',
+'prefs-watchlist-token' => 'ウォッチリストのトークン:',
'prefs-misc' => 'その他',
'prefs-resetpass' => 'パスワードの変更',
'prefs-changeemail' => 'メールアドレスを変更',
'restoreprefs' => '初期設定に戻す',
'prefs-editing' => '編集',
'prefs-edit-boxsize' => '編集ウィンドウのサイズ。',
-'rows' => '行数:',
-'columns' => '列数:',
+'rows' => '行数:',
+'columns' => '列数:',
'searchresultshead' => '検索',
'resultsperpage' => '1ページあたりの表示件数:',
'stub-threshold' => '<a href="#" class="stub">スタブリンク</a>として表示する閾値 (バイト):',
'stub-threshold-disabled' => '無効',
-'recentchangesdays' => '最近の更新に表示する日数:',
-'recentchangesdays-max' => '(最大 $1 {{PLURAL:$1|日間}})',
-'recentchangescount' => '既定で表示する件数:',
+'recentchangesdays' => '最近の更新に表示する日数:',
+'recentchangesdays-max' => '(最大 $1 {{PLURAL:$1|日|日間}})',
+'recentchangescount' => '既定で表示する件数:',
'prefs-help-recentchangescount' => 'この設定は最近の更新、ページの履歴、および記録に適用されます。',
'prefs-help-watchlist-token' => 'この欄に秘密鍵を入力すると、あなたのウォッチリストのRSSフィードが生成されます。
この欄に入力されている鍵を知っている人は誰でもこのウォッチリストを閲覧できるようになるため、他人に分からない値を選んでください。
乱数によって生成された次の値を使うこともできます:$1',
'savedprefs' => '個人設定を保存しました。',
-'timezonelegend' => 'タイムゾーン:',
-'localtime' => 'ローカルの時刻:',
+'timezonelegend' => 'タイムゾーン:',
+'localtime' => 'ローカルの時刻:',
'timezoneuseserverdefault' => 'ウィキの既定を使用 ($1)',
'timezoneuseoffset' => 'その他(時差を指定)',
'timezoneoffset' => '時差¹:',
-'servertime' => 'サーバーの時刻:',
+'servertime' => 'サーバーの時刻:',
'guesstimezone' => 'ブラウザーの設定から入力',
'timezoneregion-africa' => 'アフリカ',
'timezoneregion-america' => 'アメリカ',
'allowemail' => '他の利用者からのメールを受け取る',
'prefs-searchoptions' => '検索設定',
'prefs-namespaces' => '名前空間',
-'defaultns' => 'または次の名前空間のみを検索:',
+'defaultns' => '指定した名前空間のみを検索:',
'default' => '既定',
'prefs-files' => 'ファイル',
'prefs-custom-css' => 'カスタムCSS',
'prefs-custom-js' => 'カスタムJS',
-'prefs-common-css-js' => '全外装に共通のCSSとJavaScript:',
+'prefs-common-css-js' => 'すべての外装に共通のCSSとJavaScript:',
'prefs-reset-intro' => 'このページを使用すると、自分の個人設定をこのサイトの初期設定に戻せます。
この操作は取り消せません。',
-'prefs-emailconfirm-label' => 'メール確認:',
+'prefs-emailconfirm-label' => 'メールアドレスの確認:',
'prefs-textboxsize' => '編集画面の大きさ',
-'youremail' => 'メールアドレス:',
-'username' => '利用者名:',
-'uid' => '利用者ID:',
-'prefs-memberingroups' => '所属する{{PLURAL:$1|グループ}}:',
-'prefs-registration' => '登録日時:',
-'yourrealname' => '本名:',
-'yourlanguage' => '使用言語:',
-'yourvariant' => 'コンテンツ言語変種:',
+'youremail' => 'メールアドレス:',
+'username' => '利用者名:',
+'uid' => '利用者 ID:',
+'prefs-memberingroups' => '所属{{PLURAL:$1|グループ}}:',
+'prefs-registration' => '登録日時:',
+'yourrealname' => '本名:',
+'yourlanguage' => '使用言語:',
+'yourvariant' => 'コンテンツ言語変種:',
'prefs-help-variant' => 'このウィキのコンテンツに表示に使用したい言語変種または正書法。',
-'yournick' => '新しい署名:',
+'yournick' => '新しい署名:',
'prefs-help-signature' => 'トークページ上での発言には「<nowiki>~~~~</nowiki>」と付けて署名すべきです。これは自分の署名に時刻印を付けたものに変換されます。',
'badsig' => '署名用のソースが正しくありません。
HTMLタグを見直してください。',
'badsiglength' => '署名が長すぎます。
$1 {{PLURAL:$1|文字}}以下である必要があります。',
-'yourgender' => '性別:',
+'yourgender' => '性別:',
'gender-unknown' => '未指定',
'gender-male' => '男',
'gender-female' => '女',
'right-createtalk' => '議論ページを作成',
'right-createaccount' => '新しい利用者アカウントを作成',
'right-minoredit' => '細部の編集の印を付ける',
-'right-move' => 'ã\83\9aã\83¼ã\82¸ã\81®移動',
+'right-move' => 'ã\83\9aã\83¼ã\82¸ã\82\92移動',
'right-move-subpages' => '下位ページを含めてページを移動',
'right-move-rootuserpages' => '利用者ページ本体を移動',
-'right-movefile' => 'ã\83\95ã\82¡ã\82¤ã\83«ã\81®移動',
+'right-movefile' => 'ã\83\95ã\82¡ã\82¤ã\83«ã\82\92移動',
'right-suppressredirect' => 'リダイレクトを残さずにページを移動',
'right-upload' => 'ファイルをアップロード',
'right-reupload' => '既存のファイルに上書き',
'right-reupload-own' => '自分自身がアップロードした既存のファイルに上書き',
'right-reupload-shared' => '共有メディアリポジトリ上のファイルにローカルで上書き',
'right-upload_by_url' => 'URL からファイルをアップロード',
-'right-purge' => '確èª\8dã\82\92ç\9c\81ç\95¥ã\81\97ã\81¦サイトのキャッシュを破棄',
+'right-purge' => '確èª\8dã\81ªã\81\97ã\81§サイトのキャッシュを破棄',
'right-autoconfirmed' => '半保護されたページを編集',
'right-bot' => '自動処理と認識させる',
'right-nominornewtalk' => '議論ページの細部の編集をした際に、新着メッセージとして通知しない',
'right-apihighlimits' => 'API要求でより高い制限値を使用',
'right-writeapi' => '書き込みAPIを使用',
-'right-delete' => 'ã\83\9aã\83¼ã\82¸ã\81®削除',
+'right-delete' => 'ã\83\9aã\83¼ã\82¸ã\82\92削除',
'right-bigdelete' => '大きな履歴があるページを削除',
'right-deletelogentry' => '特定の記録項目を削除/復帰',
'right-deleterevision' => 'ページの特定の版を削除/復帰',
'right-autopatrol' => '自分の編集を自動的に巡回済みにする',
'right-patrolmarks' => '最近の更新で巡回済み印を閲覧',
'right-unwatchedpages' => 'ウォッチされていないページ一覧を閲覧',
-'right-mergehistory' => 'ページ履歴の統合',
+'right-mergehistory' => 'ページの履歴を統合',
'right-userrights' => '全利用者権限を編集',
'right-userrights-interwiki' => '他のウィキの利用者の利用者権限を編集',
'right-siteadmin' => 'データベースをロックおよびロック解除',
# User rights log
'rightslog' => '利用者権限変更記録',
'rightslogtext' => '以下は利用者権限の変更記録です。',
-'rightslogentry' => '$1の所属グループを$2から$3へ変更しました',
-'rightslogentry-autopromote' => '$2 から $3 に自動的に昇格',
+'rightslogentry' => '$1の所属グループを $2 から $3 に変更しました',
+'rightslogentry-autopromote' => '$2 から $3 に自動的に昇格しました',
'rightsnone' => '(なし)',
# Associated actions - in the sentence "You do not have permission to X"
'recentchangeslinked-toolbox' => '関連ページの更新状況',
'recentchangeslinked-title' => '「$1」と関連する変更',
'recentchangeslinked-noresult' => '指定期間中に指定ページのリンク先に変更はありませんでした。',
-'recentchangeslinked-summary' => "これはã\80\81æ\8c\87å®\9aã\81\97ã\81\9fã\83\9aã\83¼ã\82¸ã\81\8bã\82\89ã\83ªã\83³ã\82¯ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bï¼\88ã\81¾ã\81\9fã\81¯æ\8c\87å®\9aã\81\97ã\81\9fã\82«ã\83\86ã\82´ã\83ªã\81«å\90«ã\81¾ã\82\8cã\81¦ã\81\84ã\82\8bï¼\89ã\83\9aã\83¼ã\82¸ã\81¸ã\81®æ\9c\80è¿\91ã\81®å¤\89æ\9b´ã\81®ä¸\80覧ã\81§ã\81\99ã\80\82
-[[Special:Watchlist|è\87ªå\88\86ã\81®ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«ã\81\82ã\82\8bã\83\9aã\83¼ã\82¸ã\81¯'''太å\97'''ã\81«ã\81ªã\82\8aます。",
+'recentchangeslinked-summary' => "これはæ\8c\87å®\9aã\81\97ã\81\9fã\83\9aã\83¼ã\82¸ã\81\8bã\82\89ã\83ªã\83³ã\82¯ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bï¼\88ã\81¾ã\81\9fã\81¯æ\8c\87å®\9aã\81\97ã\81\9fã\82«ã\83\86ã\82´ã\83ªã\81«å\90«ã\81¾ã\82\8cã\81¦ã\81\84ã\82\8bï¼\89ã\83\9aã\83¼ã\82¸ã\81®æ\9c\80è¿\91ã\81®å¤\89æ\9b´ã\81®ä¸\80覧ã\81§ã\81\99ã\80\82
+[[Special:Watchlist|è\87ªå\88\86ã\81®ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«ã\81\82ã\82\8bã\83\9aã\83¼ã\82¸ã\81¯'''太å\97'''ã\81§è¡¨ç¤ºã\81\95ã\82\8cます。",
'recentchangeslinked-page' => 'ページ名:',
-'recentchangeslinked-to' => '代わりに、指定したページへのリンク元での変更を表示',
+'recentchangeslinked-to' => '指定したページの「リンク元」ページの変更を表示',
# Upload
'upload' => 'ファイルをアップロード',
* '''<code><nowiki>[[</nowiki>{{ns:file}}:<nowiki>File.jpg]]</nowiki></code>'''とすると、ファイルが完全なままで使用されます
* '''<code><nowiki>[[</nowiki>{{ns:file}}:<nowiki>File.png|200px|thumb|left|代替文]]</nowiki></code>'''とすると、200ピクセルの幅に修正された状態で、左寄せの枠内に、「代替文」が説明として使用されます。
* '''<code><nowiki>[[</nowiki>{{ns:media}}:<nowiki>File.ogg]]</nowiki></code>'''とするとファイルを表示せずに直接ファイルへリンクします",
-'upload-permitted' => '許可されているファイル形式:$1。',
-'upload-preferred' => '推奨されているファイル形式:$1。',
-'upload-prohibited' => '禁止されているファイル形式:$1。',
+'upload-permitted' => '許可されているファイル形式: $1。',
+'upload-preferred' => '推奨されているファイル形式: $1。',
+'upload-prohibited' => '禁止されているファイル形式: $1。',
'uploadlog' => 'アップロード記録',
'uploadlogpage' => 'アップロード記録',
'uploadlogpagetext' => '以下はファイルアップロードの最近の記録です。
画像付きで見るには[[Special:NewFiles|新規ファイルの一覧]]をご覧ください。',
'filename' => 'ファイル名',
'filedesc' => '概要',
-'fileuploadsummary' => '概要:',
-'filereuploadsummary' => 'ファイルの変更:',
-'filestatus' => '著作権情報:',
-'filesource' => '出典:',
+'fileuploadsummary' => '概要:',
+'filereuploadsummary' => 'ファイルの変更:',
+'filestatus' => '著作権情報:',
+'filesource' => '出典:',
'uploadedfiles' => 'アップロードされたファイル',
'ignorewarning' => '警告を無視してファイルを保存',
'ignorewarnings' => '警告を無視',
'uploadjava' => 'このファイルは、Javaの.classファイルを含むZIPファイルです。
セキュリティの制限を回避されるおそれがあるため、Javaファイルのアップロードは許可されていません。',
'upload-source' => 'アップロード元ファイル',
-'sourcefilename' => 'アップロード元のファイル名:',
-'sourceurl' => 'アップロード元のURL:',
-'destfilename' => '登録するファイル名:',
-'upload-maxfilesize' => 'ファイルの最大サイズ:$1',
-'upload-description' => 'ファイル説明',
+'sourcefilename' => 'アップロード元のファイル名:',
+'sourceurl' => 'アップロード元の URL:',
+'destfilename' => '登録するファイル名:',
+'upload-maxfilesize' => 'ファイルの最大サイズ: $1',
+'upload-description' => 'ファイルの説明',
'upload-options' => 'アップロードのオプション',
'watchthisupload' => 'このファイルをウォッチ',
'filewasdeleted' => 'この名前のファイルは一度アップロードされ、その後削除されています。
ウェブサイトが現在稼働していることを確認し、しばらく待ってからもう一度お試しください。
混雑していない時間帯に試すことをおすすめします。',
-'license' => 'ライセンス:',
+'license' => 'ライセンス:',
'license-header' => 'ライセンス',
'nolicense' => '選択なし',
'license-nopreview' => '(プレビューはありません)',
$3
もしアカウントの登録をした覚えがない場合は、
-次のURLをブラウザーで開いて、メール確認を中止してください:
+次のURLをブラウザーで開いて、メールアドレスの確認を中止してください:
$5
# action=purge
'confirm_purge_button' => 'OK',
'confirm-purge-top' => 'このページのキャッシュを破棄しますか?',
-'confirm-purge-bottom' => 'ページをパージすると、キャッシュが破棄され、強制的に最新の版が表示されます。',
+'confirm-purge-bottom' => 'ページをパージすると、キャッシュが破棄され、強制的に最新版が表示されます。',
# action=watch/unwatch
'confirm-watch-button' => 'OK',
'youhavenewmessages' => 'თქვენ გაქვთ $1 ($2).',
'newmessageslink' => 'ახალი შეტყობინებები',
'newmessagesdifflink' => 'განსხვავება წინა ვერსიასთან',
+'youhavenewmessagesfromusers' => 'თქვენ გაქვთ $1 {{PLURAL:$3|სხვა მომხმარებლისგან|$3 მომხმარებლებისგან}} ($2).',
+'youhavenewmessagesmanyusers' => 'თქვენ გაქვთ $1 ბევრი მომხმარებლისგან ($2).',
'newmessageslinkplural' => '{{PLURAL:$1|ახალი შეტყობინება|ახალი შეტყობინება}}',
'newmessagesdifflinkplural' => 'ბოლო {{PLURAL:$1|ცვლილება|ცვლილება}}',
'youhavenewmessagesmulti' => 'თქვენ გაქვთ ახალი შეტყობინება $1-ზე',
'rollback' => 'რცვლილებების გაუქმება',
'rollback_short' => 'სწრაფი გაუქმება',
'rollbacklink' => 'სწრაფი გაუქმება',
-'rollbacklinkcount' => '$1 {{PLURAL:$1|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡}} á\83\93á\83\90á\83\91á\83 á\83£á\83\9cება',
-'rollbacklinkcount-morethan' => '$1-á\83\96á\83\94 á\83\9bá\83\94á\83¢á\83\98 {{PLURAL:$1|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡}} á\83\93á\83\90á\83\91á\83 á\83£á\83\9cება',
+'rollbacklinkcount' => '$1 {{PLURAL:$1|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡}} á\83\92á\83\90á\83£á\83¥á\83\9bება',
+'rollbacklinkcount-morethan' => '$1-á\83\96á\83\94 á\83\9bá\83\94á\83¢á\83\98 {{PLURAL:$1|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡|á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡}} á\83\92á\83\90á\83£á\83¥á\83\9bება',
'rollbackfailed' => 'შეცდომა გაუქმებისას',
'cantrollback' => 'შეუძლებელია უწინდელი რედაქციის აღდგენა; ის, ვინც უკანასკნელი ცვლილებები შეიტანა, ამ სტატიის ერთადერთი ავტორია.',
'alreadyrolled' => 'შეუძლებელია ბოლო ცვლილების გაუქმება [[:$1]], გაკეებული [[User:$2|$2]] ([[User talk:$2|განხილვა]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);
თქვენ შეგიძლიათ ამ გვერდის დაცვის დონე შეცვალოთ, თუმცა ეს კასკადურ დაცვაზე გავლენას არ იქონიებს.',
'protect-default' => 'ყველა მომხმარებელი',
'protect-fallback' => 'საჭიროა „$1-ის“ უფლება',
-'protect-level-autoconfirmed' => 'ახალი და არარეგისტრირებული მომხმარებლების დაბლოკვა',
+'protect-level-autoconfirmed' => 'ახალი და არარეგისტრირებული მომხმარებლებისაგან დაცვა',
'protect-level-sysop' => 'მხოლოდ ადმინისტრატორები',
'protect-summary-cascade' => 'იერარქიული',
'protect-expiring' => 'ვადა გასდის: $1 (UTC)',
'undelete-no-results' => 'არ არის ნაპოვნი შესაბამისი გვერდები წაშლათა არქივში.',
'undelete-filename-mismatch' => 'შეუძლებელია წაშლილი ფაილის აღდგენა $1-ში – განსხვავებები წაშლამდე.',
'undelete-bad-store-key' => 'შეუძლებელია წაშლილი ფაილის აღდგენა $1-ში – იგი არ არსებობდა წაშლამდე.',
-'undelete-cleanup-error' => 'გამოუყენებელი სარქივო ფაილის «$1» წაშლის შეცდომა:',
+'undelete-cleanup-error' => 'გამოუყენებელი სარქივო ფაილის „$1“ წაშლის შეცდომა:',
'undelete-missing-filearchive' => 'შეუძლებელია ფაილის აღდგენა არქივის იდენტიფიკატორით $1, რადგანაც ის არ არის მონაცემთა ბაზაში. შესაძლებელია ფაილი უკვე აღდგენილია.',
'undelete-error' => 'შეცდომა გვერდის აღდგენისას',
'undelete-error-short' => 'შეცდომა ფაილის წაშლის გაუქმებაში: $1',
# What links here
'whatlinkshere' => 'ბმული გვერდზე',
-'whatlinkshere-title' => 'გვერდები, რომლებიც შეიცავენ ბმულებს "$1"-ზე',
+'whatlinkshere-title' => 'გვერდები, რომლებიც შეიცავენ ბმულებს „$1“-ზე',
'whatlinkshere-page' => 'გვერდი:',
'linkshere' => "მომდევნო გვერდები შეიცავენ ბმულებს '''[[:$1]]'''-ზე:",
'nolinkshere' => "'''[[:$1]]'''-ზე ბმული არ არის.",
'ipb_expiry_invalid' => 'მოქმედების მიუღებელი პერიოდი',
'ipb_expiry_temp' => 'ბლოკირება მომხმარებლის სახელის დამალვით უვადო უნდა იყოს',
'ipb_hide_invalid' => 'შეუძლებელია მოხემული ანგარიშის დამალვა, სავარაუდოდ მის მიერ განხორციელებულია ძალიან ბევრი შესწორება',
-'ipb_already_blocked' => '"$1" უკვე ბლოკირებულია',
+'ipb_already_blocked' => '„$1“ უკვე ბლოკირებულია',
'ipb-needreblock' => 'მომხმარებელი $1 უკვე დაიბლოკა. გსურთ დაბლოკვის პარამეტრების შესწორება?',
'ipb-otherblocks-header' => 'სხვა {{PLURAL:$1|დაბლოკვა|დაბლოკვები}}',
'unblock-hideuser' => 'თქვენ არ შეგიძლიათ მოხსნათ ბლოკი ამ მომხმარებელს, რადგან მისი მომხმარებლის სახელი დამალულია.',
'delete_and_move' => 'წაშლა და გადატანა',
'delete_and_move_text' => '==საჭიროა წაშლა==
-სტატია დასახელებით "[[:$1]]" უკვე არსებობს. გსურთ მისი წაშლა გადატანისთვის ადგილის დასათმობად?',
+სტატია დასახელებით „[[:$1]]“ უკვე არსებობს. გსურთ მისი წაშლა გადატანისთვის ადგილის დასათმობად?',
'delete_and_move_confirm' => 'დიახ, წაშალეთ ეს გვერდი',
-'delete_and_move_reason' => 'წაშლილია "[[$1]]"-á\83\93á\83\90á\83\9c á\83\92á\83\90á\83\93á\83\90á\83¢á\83\90á\83\9cá\83\98á\83¡á\83\97á\83\95á\83\98á\83¡ á\83\90á\83\93á\83\92á\83\98á\83\9aá\83\98á\83¡ á\83\93á\83\90á\83¡á\83\90á\83\97á\83\9bá\83\9dá\83\91á\83\90á\83\93',
+'delete_and_move_reason' => 'წაშლილია â\80\9e[[$1]]-á\83\93á\83\90á\83\9câ\80\9c á\83\92á\83\90á\83\93á\83\90á\83¢á\83\90á\83\9cá\83\98á\83¡á\83\97á\83\95á\83\98á\83¡ á\83\90á\83\93á\83\92á\83\98á\83\9aá\83\98á\83¡ á\83\93á\83\90á\83¡á\83\90á\83\97á\83\9bá\83\9dá\83\91á\83\90á\83\93',
'selfmove' => 'წყარო და დანიშნულების სათაურები მსგავსია; შეუძლებელია გვერდის საკუთარ თავზე გადატანა.',
-'immobile-source-namespace' => 'შეუძლებელია სახელის გადარქმევა «$1» სახელთა სივრცეში',
-'immobile-target-namespace' => 'შეუძლებელია გვერდის გადატანა «$1» სახელთა სივრცეში',
+'immobile-source-namespace' => 'შეუძლებელია სახელის გადარქმევა „$1“ სახელთა სივრცეში',
+'immobile-target-namespace' => 'შეუძლებელია გვერდის გადატანა „$1“ სახელთა სივრცეში',
'immobile-target-namespace-iw' => 'ინტერვიკის ბმული შეუძლებელია გამოყენებული იქნას გადარქმევისთვის.',
'immobile-source-page' => 'ამ გვეერდის გადატანა შეუძლებელია.',
'immobile-target-page' => 'შეუძლებელია მოცემულ სახელზე გადატანა.',
'import-upload' => 'XML მონაცემების ატვირთვა',
'import-token-mismatch' => 'სეანსის მონაცემები დაიკარგა. კიდევ ერთხელ სცადეთ!',
'import-invalid-interwiki' => 'შეუძლებელია იმპორტირება მოცემული ვიკიდან.',
-'import-error-edit' => 'გვერდი "$1" იმპორტირება არ მოხდა, რადგან თქვენ არ გაქვთ მისი რედაქტირების უფლება.',
-'import-error-create' => 'გვერდი "$1" იმპორტირება არ მოხდა, რადგან თქვენ არ გაქვთ მისი შექმნის უფლება.',
-'import-error-interwiki' => 'გვერდი "$1" არ იქნა იმპორტირებული, რადგანაც მისი სახელი დარეგისტრირებულია გარე ბმულებისათვის (interwiki).',
-'import-error-special' => 'გვერდი "$1" არ იქნა იმპორტირებული, რადგანაც ის განეკუთვნება განსაკუთრებულ სახელთა სივრცეს, რომელიც კრძალავს გვერდების შექმნას.',
+'import-error-edit' => 'გვერდი „$1“ იმპორტირება არ მოხდა, რადგან თქვენ არ გაქვთ მისი რედაქტირების უფლება.',
+'import-error-create' => 'გვერდი „$1“ იმპორტირება არ მოხდა, რადგან თქვენ არ გაქვთ მისი შექმნის უფლება.',
+'import-error-interwiki' => 'გვერდი „$1“ არ იქნა იმპორტირებული, რადგანაც მისი სახელი დარეგისტრირებულია გარე ბმულებისათვის (interwiki).',
+'import-error-special' => 'გვერდი „$1“ არ იქნა იმპორტირებული, რადგანაც ის განეკუთვნება განსაკუთრებულ სახელთა სივრცეს, რომელიც კრძალავს გვერდების შექმნას.',
'import-error-invalid' => 'გვერდი "$1" იმპორტირება არ მოხდა მიუღებელი სახელის გამო.',
'import-options-wrong' => 'არასწორი {{PLURAL:$2|პარამეტრი|პარამეტრი}}: <nowiki>$1</nowiki>',
'import-rootpage-invalid' => 'ძირეული გვერდის მითითებული სახელი არასწორია.',
# Import log
'importlogpage' => 'იმპორტის ჟურნალი',
'importlogpagetext' => 'ადმინისტრატორთა მიერ გვერდების იმპორტირება ცვლილებების ჩათვლით სხვა ვიკიდან.',
-'import-logentry-upload' => '«[[$1]]» — ფაილის იმპორტი',
+'import-logentry-upload' => '„[[$1]]“ — ფაილის იმპორტი',
'import-logentry-upload-detail' => '$1 ცვლილება',
-'import-logentry-interwiki' => '«$1» — ტრანსვიკი იმპორტი',
+'import-logentry-interwiki' => '„$1“ — ტრანსვიკი იმპორტი',
'import-logentry-interwiki-detail' => '$1 ცვლილება $2-დან',
# JavaScriptTest
'javascripttest-disabled' => 'ეს ფუნქცია ამ ვიკიში არ ჩართულა.',
'javascripttest-title' => 'მიმდინარეობს $1-ის ტესტირება',
'javascripttest-pagetext-noframework' => 'ეს გვერდი დარეგისტრირებულია JavaScript-ის ტესტების გასაშვებად.',
-'javascripttest-pagetext-unknownframework' => '"$1"-ის ტესტირების უცნობი გარემო.',
+'javascripttest-pagetext-unknownframework' => '„$1-ის“ ტესტირების უცნობი გარემო.',
'javascripttest-pagetext-frameworks' => 'გთხოვთ, აირჩიეთ ტესტირების ერთ-ერთი შემდეგი გარემო: $1',
'javascripttest-pagetext-skins' => 'ტესტების გასაშვებად აირჩიეთ გაფორმების თემა:',
'javascripttest-qunit-intro' => 'იხილეთ [$1 ტესტირების დოკუმენტები] mediawiki.org-ზე.',
'revdelete-uname-unhid' => 'მომხმარებლის სახელი გახსნილია',
'revdelete-restricted' => 'შეზღუდვა ადმინისტრატორთათვის',
'revdelete-unrestricted' => 'ადმინისტრატორთათვის შეზღუდვები მოხსნილია',
-'logentry-move-move' => '$1 á\83\92á\83\90á\83\93á\83\90á\83\98á\83¢á\83\90á\83\9cá\83\90 á\83\92á\83\95á\83\94á\83 á\83\93á\83\98 $3 â\86\92 $4-á\83\96á\83\94',
-'logentry-move-move-noredirect' => '$1 á\83\92á\83\90á\83\93á\83\90á\83\98á\83¢á\83\90á\83\9cá\83\90 á\83\92á\83\95á\83\94á\83 á\83\93á\83\98 $3 $4-á\83¨á\83\98 გადამისამართების დატოვების გარეშე',
-'logentry-move-move_redir' => '$1 á\83\92á\83\90á\83\93á\83\90á\83\98á\83¢á\83\90á\83\9cá\83\90 á\83\92á\83\95á\83\94á\83 á\83\93á\83\98 $3 $4-á\83¨á\83\98 გადამისამართებაზე',
+'logentry-move-move' => '$1 á\83\92á\83\95á\83\94á\83 á\83\93á\83\98 â\80\9e$3â\80\9c á\83\92á\83\90á\83\93á\83\90á\83\98á\83¢á\83\90á\83\9cá\83\90 á\83\92á\83\95á\83\94á\83 á\83\93á\83\96á\83\94 â\80\9e$4â\80\9c',
+'logentry-move-move-noredirect' => '$1 á\83\92á\83\95á\83\94á\83 á\83\93á\83\98 â\80\9e$3â\80\9c á\83\92á\83\90á\83\93á\83\90á\83\98á\83¢á\83\90á\83\9cá\83\90 á\83\92á\83\95á\83\94á\83 á\83\93á\83\96á\83\94 â\80\9e$4â\80\9c გადამისამართების დატოვების გარეშე',
+'logentry-move-move_redir' => '$1 á\83\92á\83\95á\83\94á\83 á\83\93á\83\98 â\80\9e$3â\80\9c á\83\92á\83\90á\83\93á\83\90á\83\98á\83¢á\83\90á\83\9cá\83\90 á\83\92á\83\95á\83\94á\83 á\83\93á\83\96á\83\94 â\80\9e$4â\80\9c გადამისამართებაზე',
'logentry-move-move_redir-noredirect' => '$1 გადაიტანა გვერდი $3 $4-ში გადამისამართების დატოვების გარეშე',
-'logentry-patrol-patrol' => '$1 გააკეთა გვერდი $3-ის $4 ვერსიის პატრულირება',
-'logentry-patrol-patrol-auto' => '$1 ავტომატურად გააკეთა გვერდი $3-ის $4 ვერსიის პატრულირება',
+'logentry-patrol-patrol' => '$1 გააკეთა გვერდის „$3“ $4 ვერსიის პატრულირება',
+'logentry-patrol-patrol-auto' => '$1 ავტომატურად გააკეთა გვერდის „$3“ $4 ვერსიის პატრულირება',
'logentry-newusers-newusers' => '$1 შექმნა მომხმარებლის ანგარიში',
'logentry-newusers-create' => '$1 შექმნა მომხმარებლის ანგარიში',
'logentry-newusers-create2' => '$1 შექმნა მომხმარებელ $3 ანგარიში',
'youhavenewmessages' => '다른 사용자가 $1란에 글을 남겼습니다. ($2)',
'newmessageslink' => '사용자 토론',
'newmessagesdifflink' => '바뀐 내용 비교',
-'youhavenewmessagesfromusers' => '{{PLURAL:$3|다른 사용자|$3 사용자}}가 $1란에 글을 남겼습니다. ($2)',
+'youhavenewmessagesfromusers' => '{{PLURAL:$3|다른 사용자가|사용자 $3명이}} $1란에 글을 남겼습니다. ($2)',
'youhavenewmessagesmanyusers' => '여러 사용자가 $1란에 글을 남겼습니다. ($2)',
-'newmessageslinkplural' => '{{PLURAL:$1|ì\83\88 ë©\94ì\8b\9cì§\80}}',
+'newmessageslinkplural' => '{{PLURAL:$1|ì\82¬ì\9a©ì\9e\90 í\86 ë¡ }}',
'newmessagesdifflinkplural' => '최근 {{PLURAL:$1|바뀜}}',
'youhavenewmessagesmulti' => '다른 사용자가 $1란에 글을 남겼습니다.',
'editsection' => '편집',
'mergelogpagetext' => '다음은 한 문서의 역사를 다른 문서의 역사와 합친 최근 기록입니다.',
# Diffs
-'history-title' => '"$1" 문서의 바뀜 내역',
+'history-title' => '"$1" 문서의 바뀜 내역',
'difference-title' => '"$1"의 두 판 사이의 차이',
'difference-title-multipage' => '문서 "$1"(와)과 "$2" 사이의 차이',
'difference-multipage' => '(문서 사이의 차이)',
'search-result-score' => '유사도: $1%',
'search-redirect' => '($1에서 넘어옴)',
'search-section' => '($1 문단)',
-'search-suggest' => '$1 문서를 찾고 있나요?',
+'search-suggest' => '$1 문서를 찾고 있으신가요?',
'search-interwiki-caption' => '자매 프로젝트',
'search-interwiki-default' => '$1 결과:',
'search-interwiki-more' => '(더 보기)',
# Preferences page
'preferences' => '사용자 환경 설정',
-'mypreferences' => '내 사용자 환경 설정',
+'mypreferences' => '사용자 환경 설정',
'prefs-edits' => '편집 횟수:',
'prefsnologin' => '로그인하지 않음',
'prefsnologintext' => '사용자 환경 설정을 바꾸려면 먼저 <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 로그인]</span>해야 합니다.',
'prefs-files' => '파일',
'prefs-custom-css' => '사용자 CSS',
'prefs-custom-js' => '사용자 자바스크립트',
-'prefs-common-css-js' => '모든 스킨에 대한 공통 CSS/JavaScript:',
+'prefs-common-css-js' => '모든 스킨에 대한 공통 CSS/자바스크립트:',
'prefs-reset-intro' => '이 사이트의 기본값으로 환경 설정을 되돌릴 수 있습니다.
복구할 수 없습니다.',
'prefs-emailconfirm-label' => '이메일 인증:',
'tooltip-pt-anonuserpage' => '현재 사용하는 IP의 사용자 문서',
'tooltip-pt-mytalk' => '내 토론 문서',
'tooltip-pt-anontalk' => '현재 사용하는 IP를 위한 사용자 토론 문서',
-'tooltip-pt-preferences' => '내 사용자 환경 설정',
+'tooltip-pt-preferences' => '사용자 환경 설정',
'tooltip-pt-watchlist' => '주시문서에 대한 바뀜 목록',
'tooltip-pt-mycontris' => '내가 편집한 글',
'tooltip-pt-login' => '꼭 로그인해야 하는 것은 아니지만, 로그인을 권장합니다.',
'youhavenewmessages' => 'Habes $1 ($2).',
'newmessageslink' => 'nuntia nova',
'newmessagesdifflink' => 'dissimilia post mutationem ultimam',
+'youhavenewmessagesfromusers' => 'Habes $1 ab {{PLURAL:$3|uno usore alio|usoribus $3}} ($2).',
+'youhavenewmessagesmanyusers' => 'Habes $1 a multis usoribus ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|nuntium novum|nuntia nova}}',
+'newmessagesdifflinkplural' => 'dissimilitudo post mutationem ultimam',
'youhavenewmessagesmulti' => 'Habes nuntia nova in $1',
'editsection' => 'recensere',
'editold' => 'recensere',
'youhavenewmessages' => 'Jūs turite $1 ($2).',
'newmessageslink' => 'naujų žinučių',
'newmessagesdifflink' => 'paskutinis pakeitimas',
-'youhavenewmessagesfromusers' => 'Jūs turite $1 nuo {{PLURAL:$3|kito vartotojo|$3 vartotojų}} ($2).',
+'youhavenewmessagesfromusers' => 'Jūs gavote $1 nuo {{PLURAL:$3|kito vartotojo|$3 vartotojų}} ($2).',
'youhavenewmessagesmanyusers' => 'Jūs turite $1 iš daugelio vartotojų ( $2 ) .',
-'newmessageslinkplural' => '{{PLURAL:$1|nauja žinutė|naujos žinutės}}',
+'newmessageslinkplural' => '{{PLURAL:$1|naują žinutę|naujų žinučių}}',
'newmessagesdifflinkplural' => 'paskutinis {{PLURAL:$1|pakeitimas|pakeitimai}}',
'youhavenewmessagesmulti' => 'Turite naujų žinučių $1',
'editsection' => 'redaguoti',
'group-autoconfirmed' => 'Mpikambana voamarina',
'group-bot' => 'Mpikambana rôbô',
'group-sysop' => 'Mpandrindra',
-'group-bureaucrat' => 'Borōkraty',
+'group-bureaucrat' => 'Borôkraty',
'group-suppress' => 'Mpitondra',
'group-all' => '(izy rehetra)',
'grouppage-autoconfirmed' => '{{ns:project}}:Mpikambana Voamafy',
'grouppage-bot' => '{{ns:project}}:Mpikambana rôbô',
'grouppage-sysop' => '{{ns:project}}:Mpandrindra',
-'grouppage-bureaucrat' => '{{ns:project}}:Borōkraty',
+'grouppage-bureaucrat' => '{{ns:project}}:Borôkraty',
'grouppage-suppress' => '{{ns:project}}:Oversight',
# Rights
* Anaran-drakitra ho ampidirina : <strong>[[:$1]]</strong>
* Anaran-drakitra misy : <strong>[[:$2]]</strong>
Misafidia anarana hafa.',
-'fileexists-thumbnail-yes' => "
-Hoatry ny saritapaka ''(vignette)'' ilay sary. [[$1|thumb]]
-Marino ilay rakitra <strong>[[:$1]]</strong>.
+'fileexists-thumbnail-yes' => "Ohatry ny sary nakelezina ilay rakitra. [[$1|thumb]]
+Mba marino ilay rakitra <strong>[[:$1]]</strong>.
Raha mitovy amin'ny sary voalohany ny sarin'ilay rakitra marinina, tsy ilaina ny mampiditra santiôna nakelezina.",
'file-thumbnail-no' => "Manomboka amin'ny <strong>$1</strong> ny anaran'ilay rakitra.
Mety saritapaka ''(vignette)'' io sary io.
'listusers-blocked' => '(voasakana)',
# Special:ActiveUsers
-'activeusers' => 'lisitra ny mpikambana miasa',
-'activeusers-intro' => "Ity ny lisitra ny mpikambana niasa teto tanatin'ny $1 andro farany {{PLURAL:}}",
+'activeusers' => 'Lisitry ny mpikambana mavitrika',
+'activeusers-intro' => 'Ity ny lisitry ny mpikambana izay nanao zavatra iray nandritry ny andro $1 farany. {{PLURAL:}}',
'activeusers-count' => "Nanova in-$1 tao anatin'ny $3 andro{{PLURAL:}}",
'activeusers-from' => 'Aseho ny mpikambana hatry ny :',
'activeusers-hidebots' => 'Asitriho ny robo',
'listgrouprights-group' => 'Vondrona/Gropy',
'listgrouprights-rights' => 'Fahefana miaraka aminy',
'listgrouprights-helppage' => "Help:Fahefan'ny vondrona",
-'listgrouprights-members' => '(lisitra ny mpikambana)',
+'listgrouprights-members' => '(lisitry ny mpikambana)',
'listgrouprights-addgroup' => '{{PLURAL:$2}}Manampy ny mpikambana : $1',
'listgrouprights-removegroup' => "Manala ny mpikambana {{PLURAL:$2}}amin'ny gropy : $1",
'listgrouprights-addgroup-all' => 'Manampy mpikambana anaty vondrona rehetra',
'unprotectthispage' => 'Bukak palindungan laman iko',
'newpage' => 'Laman baru',
'talkpage' => 'Musyawarahkan laman ko',
-'talkpagelinktext' => 'Kecek',
+'talkpagelinktext' => 'Maota',
'specialpage' => 'Laman istimewa',
'personaltools' => 'Peralatan pribadi',
'postcomment' => 'Bagian baru',
'articlepage' => 'Liek isi laman',
-'talk' => 'Pembicaraan',
+'talk' => 'Ota',
'views' => 'Tampilan',
'toolbox' => 'Kotak pakakeh',
'userpage' => 'Liek laman pangguno',
'site-atom-feed' => '$1 umpan Atom',
'page-rss-feed' => 'Umpan RSS "$1"',
'page-atom-feed' => '"$1" umpan Atom',
-'red-link-title' => '$1 (laman alun tasadio)',
+'red-link-title' => '$1 (halaman alun babuek)',
'sort-descending' => 'Urutkan manurun',
'sort-ascending' => 'Urutkan manaik',
# Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'Laman',
+'nstab-main' => 'Halaman',
'nstab-user' => 'Laman pangguno',
'nstab-media' => 'Laman Media',
'nstab-special' => 'Laman istimewa',
# Search results
'searchresults' => 'Hasil pencarian',
-'searchresults-title' => 'Hasil pencarian untuak "$1"',
+'searchresults-title' => 'Hasil pancarian untuak "$1"',
'searchresulttext' => 'Untuak informasi lanjut tentang pencarian {{SITENAME}}, lihek [[{{MediaWiki:Helppage}}|{{int:help}}]].',
'searchsubtitle' => 'Awak mancari \'\'\'[[:$1]]\'\'\' ([[Special:Prefixindex/$1|sado laman yang dimulai jo "$1"]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|sado laman nan tapauik ka "$1"]])',
'searchsubtitleinvalid' => "Awak mancari '''$1'''",
'tooltip-ca-unwatch' => 'Kaluaan laman ko dari senarai pantauan awak',
'tooltip-search' => 'Cari {{SITENAME}}',
'tooltip-search-go' => 'Cari suatu laman dengan namo yang samo jiko tasadio',
-'tooltip-search-fulltext' => 'Cari laman yang ado teks ko',
+'tooltip-search-fulltext' => 'Cari halaman nan mamuek teks ko',
'tooltip-p-logo' => '↓ Kunjungi laman utamo',
'tooltip-n-mainpage' => 'Kunjungi Halaman Utamo',
'tooltip-n-mainpage-description' => 'Kunjungi halaman utamo',
'tooltip-n-portal' => 'Tentang proyek, apo yang dapek awak lakukan, di mano mancari sasuatu',
'tooltip-n-currentevents' => 'Temukan informasi latar dari peristiwa kini ko',
-'tooltip-n-recentchanges' => 'Senarai parubahan baru dalam wiki',
+'tooltip-n-recentchanges' => 'Daftar panyuntiangan baru dalam wiki',
'tooltip-n-randompage' => 'Tampilkan sembarang halaman',
'tooltip-n-help' => 'Tampek mancari bantuan',
'tooltip-t-whatlinkshere' => 'Senarai sado halaman wiki yang punyo pranala ka halaman ko',
'tooltip-t-contributions' => 'Lihek senarai jariah pangguno ko',
'tooltip-t-emailuser' => 'Kirimkan e-mail ka pangguno ko',
'tooltip-t-upload' => 'Unggah berkas',
-'tooltip-t-specialpages' => 'Senarai semua halaman istimewa',
+'tooltip-t-specialpages' => 'Sadoalah halaman istimewa',
'tooltip-t-print' => 'Versi cetak halaman ko',
'tooltip-t-permalink' => 'Pranala permanen untuak revisi laman ko',
'tooltip-ca-nstab-main' => 'Lihek isi laman',
'upload-source' => 'Sors tal-fajl',
'sourcefilename' => 'L-isem tal-fajl tal-oriġini:',
'sourceurl' => 'Sors tal-URL:',
-'destfilename' => 'L-Isem tal-fajl tad-destinazzjoni:',
+'destfilename' => "Isem tal-fajl ta' destinazzjoni:",
'upload-maxfilesize' => 'Daqs massimu tal-fajl: $1',
'upload-description' => 'Deskrizzjoni tal-fajl',
'upload-options' => 'Opzjonijiet għat-tlugħ tal-fajl',
'tog-hidepatrolled' => 'Motlàtìs tlapîpialli tlayèktlàlilistli ìpan welok tlapảtlalistli',
'tog-newpageshidepatrolled' => 'Mokintlàtis tlapîpialtlaìxtlapaltìn ìwikpa ìtlapòpòwaltekpànal in yâyankuik tlaìxtlapaltìn',
'tog-extendwatchlist' => 'Mìxmảnas in tlapòpòwaltekpàntlachialli ìka mỏtas nochi in tlapảtlalistli, âmò in san okachi yankuik.',
-'tog-usenewrc' => 'Okachi kualli yankuik tlapảtlalistli (ìpan kineki JavaScript)',
+'tog-usenewrc' => 'Colōloāz in tlapatlaiztli īca yancuīc tlapatlaliztli īhuān in tlachiyaliztli tlapōhualāmatl (monequi JavaScript)',
'tog-showtoolbar' => 'Tiquittāz in tlein motequitiltia tlapatlaliztechcopa (JavaScript)',
'tog-editondblclick' => 'Tiquimpatlāz zāzaniltin ōme clicca (JavaScript)',
'tog-showtoc' => 'Tiquittāz in tlein cah zāzotlahcuilōlco',
'tog-rememberpassword' => 'Ticpiyāz moMotlatequitiltilīltōca īhuān motlahtōlichtacāyo inīn chīuhpōhualhuazco (īxquich {{PLURAL:$1|tōnalli|tōnalli}})',
-'tog-watchcreations' => 'Tiquintlachiyāz zāzaniltin tiquinchīhua',
-'tog-watchdefault' => 'Tiquintlachiyāz zāzaniltin tiquimpatla',
-'tog-watchmoves' => 'Tiquintlachiyāz zāzaniltin tiquinzaca',
-'tog-watchdeletion' => 'Tiquintlachiyāz zāzaniltin tiquimpoloa',
+'tog-watchcreations' => 'Moaquiāz in āmatl mā niquinyōcoya īhuān in tlahcuilōlli mā niquinquetza īpan notlachiyaliz',
+'tog-watchdefault' => 'Moaquiāz āmatl īhuān tlahcuilōlli mā niquinpatla in notlachiyaliz',
+'tog-watchmoves' => 'Moaquiāz āmatl īhuān tlahcuilōlli mā niquinzaca in notlachiyaliz',
+'tog-watchdeletion' => 'Moaquiāz āmatl īhuān tlahcuilōlli mā niquimpolo in notlachiyaliz',
'tog-minordefault' => 'Ticmachiyōtīz mochīntīn tlapatlalitzintli ic default',
'tog-previewontop' => 'Tiquittāz achtochīhualiztli achtopa tlapatlaliztli caxitl',
'tog-previewonfirst' => 'Xiquitta achtochīhualiztli inic cē tlapatlalizpan',
'sep' => 'ic chiucnāuh',
'oct' => 'ic mahtlāc',
'nov' => 'ic mahtlāctli oncē',
-'dec' => 'ic mahtlāctli onōme',
+'dec' => 'ic mahtlāctli omōme',
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Tlaìxmatkàtlàlilòtl|Tlaìxmatkàtlàlilòmë}}',
'qbpageinfo' => 'Tlahcuilōltechcopa',
'qbmyoptions' => 'Nozāzanil',
'qbspecialpages' => 'Nònkuâkìskàtlaìxtlapaltìn',
-'faq' => 'FAQ',
+'faq' => 'Zan īc tētlatlanīliztli',
'faqpage' => 'Project:FAQ',
# Vector skin
'badaccess-groups' => 'Inōn tiquiēlēhuia zan quichīhuah tlatequitiltilīlli {{PLURAL:$2|oncān|oncān}}: $1.',
'ok' => 'Nopan iti',
-'retrievedfrom' => 'Īhuīcpa "$1"',
+'retrievedfrom' => 'Ōquīzqui ītech "$1"',
'youhavenewmessages' => 'Tiquimpiya $1 ($2).',
'newmessageslink' => 'yancuīc tlahcuilōltzintli',
'newmessagesdifflink' => 'achto tlapatlaliztli',
'italic_sample' => 'Cōliuhqui tlahcuilōliztli',
'italic_tip' => 'Cōliuhqui tlahcuilōliztli',
'link_sample' => 'Tzonhuiliztli ītōcā',
-'link_tip' => 'Tzonhuiliztli tlahtic',
-'extlink_sample' => 'http://www.example.com Tōcāitl',
-'extlink_tip' => 'Tzonhuilizcallān (xitequitiltia http://)',
+'link_tip' => 'Tlahtic tzonhuiliztli',
+'extlink_sample' => 'http://www.machiyōtl.com Tzonhuiliztōcāitl',
+'extlink_tip' => 'Calān tzonhuiliztli (xiquilnamiqui ticaquiāz in http://)',
'headline_sample' => 'Cuātlahcuilōlli',
'headline_tip' => 'Iuhcāyōtl 2 tōcāyōtl',
'image_sample' => 'Machiyōtl.jpg',
# Edit pages
'summary' => 'Mopatlaliz:',
'subject' => 'Tōcāitl/Āmoxmachiyōtl:',
-'minoredit' => 'Inīn cah tlapatlalitzintli',
+'minoredit' => 'Inīn tlapatlaliztli tepitōn',
'watchthis' => 'Tictlachiyāz inīn zāzanilli',
'savearticle' => 'Ticpiyāz',
'preview' => 'Xiquitta achtochīhualiztli',
'''¡Ahmo ōmochīuh nozan!'''",
'updated' => '(Ōmoyancuīli)',
'note' => "'''Tlahtōlcaquiliztilōni:'''",
-'previewnote' => "'''¡Ca inīn moachtochīhualiz, auh mopatlaliz ahmō cateh ōmochīhuah nozan!'''",
+'previewnote' => "'''Xiquilnamiqui tein inīn zan tlaachtopaittaliztli.'''
+¡Motlapatlaliz ayamo ōquinpix!",
'editing' => 'Ticpatlacah $1',
'editingsection' => 'Ticpatlacah $1 (tlahtōltzintli)',
'editingcomment' => 'Ticpatlacah $1 (tlahtōltzintli)',
'revertmerge' => 'Tiquīxipehuaz',
# Diffs
-'history-title' => '"$1" ītlachiyaliz tlahcuilōlloh',
+'history-title' => '«$1» tlahcuilōlloh ītlaihittaliz',
'lineno' => 'Pāntli $1:',
'editundo' => 'Tichuelōz',
'diff-multi' => '({{PLURAL:$1|Cē tlapatlaliztli nepantlah ahmo motta in ōquichīuh|$1 Tlapatlaliztli nepantlah ahmo mottah in ōquinchīuh}} {{PLURAL:$2|cē tlatequitiltilīlli|$2 tlatequitiltilīltin}})',
'search-result-size' => '$1 ({{PLURAL:$2|1 tlahtōl|$2 tlahtōltin}})',
'search-redirect' => '(tlacuepaliztli $1)',
'search-section' => '(tlahtōltzintli $1)',
-'search-suggest' => 'Mohtoa ahnozo: $1',
+'search-suggest' => 'Ahnōceh tiquihtōznequiya: $1',
'search-interwiki-caption' => 'Tlachīhualiztli īcnīhuān',
'search-interwiki-more' => '(huehca ōmpa)',
'search-relatedarticle' => 'Ītechcopa',
'filehist-dimensions' => 'Octacayōtl',
'filehist-comment' => 'TlahtōIcaquiliztīlōni',
'imagelinks' => 'Tlahcuilōlli tlanemītīliztli',
-'linkstoimage' => 'Inīn {{PLURAL:$1|zāzanilli tzonhuilia|$1 zāzaniltin tzonhuiliah}} inīn tlahcuilōlhuīc:',
+'linkstoimage' => 'Inīn {{PLURAL:$1|zāzanilli motzonhuilia|$1 zāzanilli motzonhuiliah}} inīn tlahcuilōlhuīc:',
'nolinkstoimage' => 'Ahmo cateh zāzaniltin tlein tzonhuiliah inīn tlahcuilōlhuīc.',
'morelinkstoimage' => 'Tiquinttāz [[Special:WhatLinksHere/$1|achi tzonhuiliztli]] inīn tlahcuilōlhuīc.',
'duplicatesoffile' => 'Inōn {{PLURAL:$1|tlahcuilōlli cah|$1 tlahcuilōlli cateh}} ōntiah inīn zāzanilli ([[Special:FileDuplicateSearch/$2|ocahci]]):',
'undelete-show-file-submit' => 'Quemah',
# Namespace form on various pages
-'namespace' => 'Tōcātzin:',
+'namespace' => 'Tōcātlacāuhtli:',
'invert' => 'Tlacuepāz motlahtōl',
-'blanknamespace' => '(Huēyi)',
+'blanknamespace' => '(Tāchcāuh)',
# Contributions
'contributions' => 'Ītlahcuilōl',
'ipbreasonotherlist' => 'Occē īxtlamatiliztli',
'ipbsubmit' => 'Tiquitzacuilīz inīn tlatequitiltilīlli',
'ipbother' => 'Occē cāuhpan:',
-'ipboptions' => '2 yēmpōhualminutl:2 hours,1 tōnalli:1 day,3 tōnaltin:3 days,7 tōnaltin:1 week,14 tōnaltin:2 weeks,1 mētztli:1 month,3 mētztli:3 months,6 mētztli:6 months,1 xihuitl:1 year,Mochipa:infinite',
+'ipboptions' => '2 cāhuitl:2 hours,1 tōnalli:1 day,3 tōnaltin:3 days,1 chicuēyilhuitl:1 week,2 chicuēyilhuitl:2 weeks,1 mētztli:1 month,3 mētztli:3 months,6 mētztli:6 months,1 xihuitl:1 year,mochipa:infinite',
'ipbotheroption' => 'occē',
'ipbotherreason' => 'Occē īxtlamatiliztli:',
'ipbwatchuser' => 'Tiquinchiyāz inīn tlatequitiltilīlli in ītlatequitiltilīlzāzanil auh in ītēixnāmiquiliz',
'tooltip-search' => 'Tlatēmōz īpan {{SITENAME}}',
'tooltip-search-go' => 'Tiyaz in zāzanilhuīc īca inīn huel melāhuac tōcaitl intlā yez',
'tooltip-p-logo' => 'Calīxatl',
-'tooltip-n-mainpage' => 'Tictlahpolōz in Calīxatl',
+'tooltip-n-mainpage' => 'Tiquittaz in calīxatl',
'tooltip-n-mainpage-description' => 'Tiquittaz in calīxatl',
'tooltip-n-portal' => 'Tlachīhualiztechcopa, inōn tihuelīti titlachīhua, tlatēmoyān',
'tooltip-n-recentchanges' => 'Yancuīc tlapatlaliztli huiquipan',
'tooltip-ca-nstab-category' => 'Mà mỏta ìtlaìxtlapal in tlaìxmatkàtlàlilòtl',
'tooltip-minoredit' => 'Ticmachiyōz quemeh tlapatlalitzintli',
'tooltip-save' => 'Ticpiyāz mopatlaliz',
-'tooltip-preview' => 'Xiquitta achtopa mopatlaliz, ¡timitztlātlauhtiah quitēquitiltilia achto ticpiya!',
+'tooltip-preview' => 'Xachtopaitta mopatlaliz ¡Timitztlahtlauhtiliah, xicchīhua yēppa mā tiquimpiya!',
'tooltip-diff' => 'Xiquitta in tlein ōticpatlāz tlahcuilōlco.',
'tooltip-compareselectedversions' => 'Tiquinttāz ahneneuhquiliztli ōme zāzanilli tlapatlaliznepantlah.',
'tooltip-watch' => 'Ticcēntilīz inīn zāzanilli motlachiyalizhuīc',
'uploadnewversion-linktext' => 'Last opp en ny versjon av denne filen',
'shared-repo-from' => 'fra $1',
'shared-repo' => 'et delt fillager',
+'upload-disallowed-here' => 'Beklageligvis kan du ikke overskrive dette bildet.',
# File reversion
'filerevert' => 'Tilbakestill $1',
'pageinfo-authors' => 'Totalt antall forskjellige forfattere',
'pageinfo-recent-edits' => 'Antall nylige redigeringer (innen siste $1)',
'pageinfo-recent-authors' => 'Antall nylige forfattere',
-'pageinfo-restriction' => 'Sidebeskyttelse (<code>$1</code>)',
+'pageinfo-restriction' => 'Sidebeskyttelse (<code>{{lcfirst:$1}}</code>)',
'pageinfo-magic-words' => '{{PLURAL:$1|Magisk|Magiske}} ord ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Skjult kategori|Skjulte kategorier}} ($1)',
'pageinfo-templates' => 'Transkludert {{PLURAL:$1|mal|maler}} ($1)',
'file-info-size' => '$1 × $2 piksler, filstørrelse: $3, MIME-type: $4',
'file-info-size-pages' => '$1 × $2 piksler, filstørrelse: $3, MIME-type: $4, $5 {{PLURAL:$5|side|sider}}',
'file-nohires' => 'Ingen høyere oppløsning tilgjengelig.',
-'svg-long-desc' => 'SVG-fil, standardoppløsning $1 × $2 piksler, filstørrelse: $3',
+'svg-long-desc' => 'SVG-fil, standardstørrelse $1 × $2 piksler, filstørrelse: $3',
+'svg-long-desc-animated' => 'Animert SVG-fil, standardstørrelse $1 × $2 piksler, filstørrelse: $3',
'show-big-image' => 'Full oppløsning',
'show-big-image-preview' => 'Størrelse på denne forhåndsvisningen: $1.',
'show-big-image-other' => '{{PLURAL:$2|Annen oppløsning|Andre oppløsninger}}: $1.',
'file-info-png-looped' => 'loopet',
'file-info-png-repeat' => 'avspilt $1 {{PLURAL:$1|gang|ganger}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|bilde|bilder}}',
+'file-no-thumb-animation' => "'''Merk: På grunn av tekniske begrensninger vil ikke miniatyrbilder av denne filen bli animert.'''",
+'file-no-thumb-animation-gif' => "'''Merk: På grunn av tekniske begrensninger vil ikke miniatyrbilder av høyoppløselige GIF-bilder, slik som denne, bli animert.'''",
# Special:NewFiles
'newimages' => 'Galleri over nye filer',
'ipblocklist-empty' => 'De blokkeerlijst is leeg.',
'ipblocklist-no-results' => 'Dit IP-adres of deze gebruikersnaam is niet geblokkeerd.',
'blocklink' => 'blokkeren',
-'unblocklink' => 'deblokkeren',
+'unblocklink' => 'blokkade opheffen',
'change-blocklink' => 'blokkade wijzigen',
'contribslink' => 'bijdragen',
'emaillink' => 'e-mail verzenden',
'summary' => 'Samandrag:',
'subject' => 'Emne/overskrift:',
'minoredit' => 'Småplukk',
-'watchthis' => 'Overvak denne sida',
+'watchthis' => 'Overvak sida',
'savearticle' => 'Lagre',
'preview' => 'Førehandsvising',
'showpreview' => 'Førehandsvis',
'removewatch' => 'Fjerna frå overvakingslista',
'removedwatchtext' => 'Sida «[[:$1]]» er fjerna frå [[Special:Watchlist|overvakingslista di]].',
'watch' => 'Overvak',
-'watchthispage' => 'Overvak denne sida',
+'watchthispage' => 'Overvak sida',
'unwatch' => 'Fjern overvaking',
'unwatchthispage' => 'Fjern overvaking',
'notanarticle' => 'Ikkje innhaldsside',
'cant-move-user-page' => 'Du har ikkje løyve til å flytte brukarsider (bortsett frå undersider).',
'cant-move-to-user-page' => 'Du har ikkje løyve til å flytte brukarsider (bortsett frå undersider).',
'newtitle' => 'Til ny tittel:',
-'move-watch' => 'Overvak denne sida',
+'move-watch' => 'Overvak sida',
'movepagebtn' => 'Flytt side',
'pagemovedsub' => 'Flyttinga er gjennomførd',
'movepage-moved' => "'''«$1» er flytt til «$2»'''",
'fri' => 'ଶୁକ୍ରବାର',
'sat' => 'ଶନିବାର',
'january' => 'ଜାନୁଆରୀ',
-'february' => 'ଫà\87ବà\83ଆରୀ',
+'february' => 'ଫà\87ବà\8dରà\81ଆରୀ',
'march' => 'ମାର୍ଚ୍ଚ',
'april' => 'ଅପ୍ରେଲ',
'may_long' => 'ମଇ',
'november' => 'ନଭେମ୍ବର',
'december' => 'ଡିସେମ୍ବର',
'january-gen' => 'ଜାନୁଆରୀ',
-'february-gen' => 'ଫà\87ବà\83ଆରୀ',
+'february-gen' => 'ଫà\87ବà\8dରà\81ଆରୀ',
'march-gen' => 'ମାର୍ଚ୍ଚ',
'april-gen' => 'ଅପ୍ରେଲ',
'may-gen' => 'ମଇ',
'november-gen' => 'ନଭେମ୍ବର',
'december-gen' => 'ଡିସେମ୍ବର',
'jan' => 'ଜାନୁଆରୀ',
-'feb' => 'ଫà\87ବà\83ଆରୀ',
+'feb' => 'ଫà\87ବà\8dରà\81ଆରୀ',
'mar' => 'ମାର୍ଚ୍ଚ',
'apr' => 'ଅପ୍ରେଲ',
'may' => 'ମଇ',
'prefs-beta' => 'ଆଗ ବିଶେଷତାମାନ',
'prefs-datetime' => 'ତାରିଖ ଓ ସମୟ',
'prefs-labs' => 'ପରଖଶାଳା ସୁବିଧାସବୁ',
+'prefs-user-pages' => 'ବ୍ୟବହାରକାରୀଙ୍କର ପୃଷ୍ଠାଗୁଡିକ',
'prefs-personal' => 'ସଭ୍ୟ ପ୍ରଫାଇଲ',
'prefs-rc' => 'ନଗଦ ବଦଳ',
'prefs-watchlist' => 'ଦେଖଣା ତାଲିକା',
'allpagesbadtitle' => 'ଆପଣ ଅନୁରୋଧ କରିଥିବା ପୃଷ୍ଠାଟି ଭୁଲ, ଅଲଗା ଭାଷାର ବ୍ୟବହାର କରାଯାଇଛି ବା ଭୁଲ ଇଣ୍ଟର ଉଇକି ଉପସର୍ଗ ଦିଆଯାଇଛି ।
ଏଥିରେ ଥିବା ଗୋଟିଏ ବା ଦୁଇଟି ଅକ୍ଷର ଶିରୋନାମା ଭାବରେ ବ୍ୟବହାର କରାଯାଇ ପାରିବ ନାହିଁ ।',
'allpages-bad-ns' => '{{SITENAME}}ରେ "$1" ନେମସ୍ପେସଟିଏ ନାହିଁ ।',
+'allpages-hide-redirects' => 'ପୁନଃପ୍ରେରଣସମୂହକୁ ଲୁଚାଇବେ',
# SpecialCachedPage
'cachedspecial-refresh-now' => 'ନୂତନତମ ଦେଖନ୍ତୁ ।',
'mailnologin' => 'ଗୋଟିଏ ବି ପଠାଇବା ଠିକଣା ନାହିଁ',
'mailnologintext' => 'ଆପଣ ନିଜ [[Special:Preferences|ପସନ୍ଦସବୁ]]ରେ [[Special:UserLogin|ଲଗ ଇନ]] କରିଥିଲେ ଓ ନିଜର ଏକ ସଚଳ ଇ-ମେଲ ଠିକଣା ଥିଲେ ଯାଇ ବାକି ସବୁ ସଭ୍ୟଙ୍କୁ ଇ-ମେଲ ପଠାଇପାରିବେ ।',
'emailuser' => 'ଏହି ସଭ୍ୟଙ୍କୁ ଇମେଲ କରିବେ',
+'emailuser-title-notarget' => 'ବ୍ୟବହାରକାରୀ କୁ ଇ-ମେଲ',
'emailpage' => 'ଇ-ମେଲ ବ୍ୟବହାରକାରୀ',
'emailpagetext' => 'ତଳେ ଥିବା ଫର୍ମ ବ୍ୟବହାର କରି ଆପଣ ଏହି ସଭ୍ୟଙ୍କୁ ଇ-ମେଲ କରିପାରିବେ ।
[[Special:Preferences|ଆପଣଙ୍କ ପସନ୍ଦ]]ରେ ଥିବା ଇ-ମେଲ ଠିକଣା ପ୍ରେରକ ଭାବରେ ଦେଖାଯିବ, ତେଣୁ ଚିଠି ପାଇଥିବା ସଭ୍ୟ ଆପଣଙ୍କୁ ସିଧା ସଳଖ ଉତ୍ତର ଦେଇପାରିବ ।',
# Info page
'pageinfo-title' => '"$1"ର ବିବରଣୀ',
'pageinfo-header-edits' => 'ବଦଳସବୁ',
+'pageinfo-article-id' => 'ପୃଷ୍ଠା ଆଇଡ଼ି',
'pageinfo-views' => 'ଦେଖଣା ସଂଖ୍ୟା',
'pageinfo-watchers' => 'ଦେଖଣାହାରି ସଂଖ୍ୟା',
'pageinfo-edits' => 'ସମ୍ପାଦନା ସଂଖ୍ୟା:',
'api-error-verification-error' => 'ଏହି ଫାଇଲଟି ବୋଧ ହୁଏ ନଷ୍ଟ ହୋଇଯାଇଅଛି କିମ୍ବା ଭୁଲ ଏକ୍ସଟେନସନ ଦିଆଯାଇଅଛି ।',
# Durations
+'duration-seconds' => '$1 {{PLURAL:$1|ସେକଣ୍ଡ|ସେକେଣ୍ଡ}}',
+'duration-minutes' => '$1 {{PLURAL:$1|ମିନିଟ|ମିନିଟ}}',
+'duration-hours' => '$1 {{PLURAL:$1|ଘଣ୍ଟା|ଘଣ୍ଟା}}',
+'duration-days' => '$1 {{PLURAL:$1|ଦିନ|ଦିନଗୁଡିକ}}',
+'duration-weeks' => '$1 {{PLURAL: $1|ସପ୍ତାହ|ସପ୍ତାହଗୁଡିକ}}',
'duration-years' => '$1 {{PLURAL:$1|year|years}}',
'duration-decades' => '$1 {{PLURAL:$1|decade|decades}',
'duration-centuries' => '$1 {{PLURAL:$1|century|centuries}}',
'tog-hidepatrolled' => 'ਮੌਨਜੁਦਾ ਬਦਲਾਬ ਮੈ ਸੈ ਸਹੀਤਕ ਬਦਲਾਬ ਕੌ ਛੁਪਾ ਕਰ ਰਖੇ.',
'tog-newpageshidepatrolled' => 'ਨਵੀ ਸੁਚੀ ਮੈ ਸੈ ਗਸ਼ਤ ਪਰਚੇ ਕੌ ਛੁਪਾਏ.',
'tog-extendwatchlist' => 'ਸਾਰੀ ਨਵੀ ਤਬਦੀਲੀਆ ਹੀ ਨਹੀ ,ਪੂਰਾਣੀ ਤਬਦੀਲੀਆ ਨੂੰ ਵੀ ਨਵੀ ਸੂਚੀ ਵਿਚ ਵਧਾ ਕੈ ਸ਼ਾਮੀਲ ਕਰੌ.',
-'tog-usenewrc' => 'ਤਾਜ਼ਾ ਤਬਦੀਲੀਆਂ ਅਤੇ ਨਿਗਰਾਨੀ ਲਿਸਟ ਵਿਚ ਤਬਦੀਲੀਆਂ ਸਫ਼ੇ ਮੁਤਾਬਕ (ਜਾਵਾ ਸਕ੍ਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)',
+'tog-usenewrc' => 'ਤਾਜ਼ਾ ਤਬਦੀਲੀਆਂ ਅਤੇ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚ ਸਫ਼ੇ ਮੁਤਾਬਕ ਤਬਦੀਲੀਆਂ ਦੇ ਗਰੁੱਪ ਬਣਾਓ (ਜਾਵਾ ਸਕ੍ਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)',
'tog-numberheadings' => 'ਆਟੋ-ਨੰਬਰ ਹੈਡਿੰਗ',
'tog-showtoolbar' => 'ਐਡਿਟ ਟੂਲਬਾਰ ਵੇਖੋ (JavaScript)',
-'tog-editondblclick' => 'ਦà©\8bਹਰà©\87 à¨\95ਲਿੱà¨\95 ਨਾਲ਼ ਸਫ਼ਾ ਸੋਧੋ (ਜਾਵਾ ਸਕ੍ਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)',
-'tog-editsection' => '[ਸà©\8bਧà©\8b] ਲਿੰà¨\95ਾà¨\82 à¨\9c਼ਰà©\80à¨\8f ਸà©\88à¨\95ਸ਼ਨ ਸà©\8bਧ ਯà©\8bà¨\97 ਕਰੋ',
+'tog-editondblclick' => 'ਦà©\82ਹਰà©\87 à¨\95ਲਿੱà¨\95 ਨਾਲ਼ ਸਫ਼à©\87 ਸੋਧੋ (ਜਾਵਾ ਸਕ੍ਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)',
+'tog-editsection' => '[ਸà©\8bਧà©\8b] ਲਿੰà¨\95ਾà¨\82 à¨\9c਼ਰà©\80à¨\8f ਸà©\88à¨\95ਸ਼ਨ ਸà©\8bਧ à¨\9aਾਲà©\82 ਕਰੋ',
'tog-editsectiononrightclick' => 'ਸੈਕਸ਼ਨ ਸਿਰਲੇਖਾਂ ਤੇ ਸੱਜੀ ਕਲਿੱਕ ਦੁਆਰਾ ਸੋਧ ਯੋਗ ਕਰੋ (ਜਾਵਾ ਸਕ੍ਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)',
'tog-showtoc' => 'ਟੇਬਲ ਆਫ਼ ਕੰਨਟੈੱਟ ਵੇਖਾਓ (for pages with more than 3 headings)',
'tog-rememberpassword' => 'ਇਸ ਬਰਾਊਜ਼ਰ ਉੱਤੇ ਮੇਰਾ ਲਾਗਇਨ ਯਾਦ ਰੱਖੋ ($1 {{PLURAL:$1|ਦਿਨ|ਦਿਨਾਂ}} ਲਈ ਵੱਧ ਤੋਂ ਵੱਧ)',
'tog-watchdefault' => 'ਮੇਰੇ ਵੱਲੋਂ ਸੋਧੇ ਸਫ਼ੇ ਅਤੇ ਫ਼ਾਈਲਾਂ ਮੇਰੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿੱਚ ਪਾਓ',
'tog-watchmoves' => 'ਮੇਰੇ ਵੱਲੋਂ ਬਦਲੇ ਸਿਰਲੇਖਾਂ ਵਾਲ਼ੇ ਸਫ਼ੇ ਅਤੇ ਫ਼ਾਈਲਾਂ ਮੇਰੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿੱਚ ਪਾਓ',
'tog-watchdeletion' => 'ਮੇਰੇ ਵਲੋਂ ਹਟਾਏ ਗਏ ਸਫ਼ੇ ਮੇਰੀ ਵਾਚ-ਲਿਸਟ ਵਿੱਚ ਪਾਓ',
-'tog-minordefault' => 'ਸਾਰà©\80à¨\86à¨\82 ਸà©\8bਧਾà¨\82 ਤੇ ਮੂਲ ਰੂਪ ਵਿਚ ਛੋਟੀਆਂ ਹੋਣ ਦਾ ਨਿਸ਼ਾਨ ਲਾਓ',
+'tog-minordefault' => 'ਸਾਰà©\87 ਫà©\87ਰ-ਬਦਲਾà¨\82 â\80\99ਤੇ ਮੂਲ ਰੂਪ ਵਿਚ ਛੋਟੀਆਂ ਹੋਣ ਦਾ ਨਿਸ਼ਾਨ ਲਾਓ',
'tog-previewontop' => 'ਐਡਿਟ ਬਕਸੇ ਤੋਂ ਪਹਿਲਾਂ ਝਲਕ ਵੇਖਾਓ',
'tog-previewonfirst' => 'ਪਹਿਲੇ ਐਡਿਟ ਉੱਤੇ ਝਲਕ ਵੇਖਾਓ',
'tog-nocache' => 'ਬਰਾਊਜ਼ਰ ਸਫ਼ਾ ਕੈਸ਼ ਕਰਨਾ ਬੰਦ ਕਰੋ',
'tog-enotifwatchlistpages' => 'ਜਦੋਂ ਮੇਰੀ ਵਾਚ-ਲਿਸਟ ਵਿਚ ਦਰਜ ਕੋਈ ਸਫ਼ਾ ਬਦਲਿਆ ਜਾਵੇ ਯਾ ਮਿਸਲ ਬਦਲੀ ਜਾਵੇ ਤਾਂ ਮੈਨੂੰ ਈਮੇਲ ਭੇਜੋ',
'tog-enotifusertalkpages' => 'ਜਦੋਂ ਮੇਰਾ ਗੱਲ-ਬਾਤ ਸਫ਼ਾ ਬਦਲਿਆ ਜਾਵੇ ਤਾਂ ਮੈਨੂੰ ਈ-ਮੇਲ ਭੇਜੋ',
'tog-enotifminoredits' => 'ਸਫ਼ਿਆਂ ਅਤੇ ਫ਼ਾਈਲਾਂ ਦੀਆਂ ਛੋਟੀਆਂ ਤਬਦੀਲੀਆਂ ਲਈ ਵੀ ਮੈਨੂੰ ਈ-ਮੇਲ ਭੇਜੋ',
-'tog-enotifrevealaddr' => 'à¨\9cਾਣà©\82 à¨\95ਰਵਾà¨\89ਣ ਵਾਲ਼ੀਆਂ ਈ-ਮੇਲਾਂ ਵਿਚ ਮੇਰਾ ਈ-ਮੇਲ ਪਤਾ ਜ਼ਾਹਰ ਕਰੋ',
+'tog-enotifrevealaddr' => 'à¨\87ਤਲਾਹ ਦà©\87ਣ ਵਾਲ਼ੀਆਂ ਈ-ਮੇਲਾਂ ਵਿਚ ਮੇਰਾ ਈ-ਮੇਲ ਪਤਾ ਜ਼ਾਹਰ ਕਰੋ',
'tog-shownumberswatching' => 'ਨਜ਼ਰ ਰੱਖ ਰਹੇ ਮੈਂਬਰਾਂ ਦੀ ਗਿਣਤੀ ਵਖਾਓ',
'tog-oldsig' => 'ਮੌਜੂਦਾ ਦਸਤਖਤ:',
-'tog-fancysig' => 'ਦਸਤà¨\96਼ਤ ਨà©\82à©° ਵਿà¨\95à©\80ਲਿà¨\96ਤ ਦà©\87 ਤà©\8cਰ ਤà©\87 ਵਰਤੋ (ਬਿਨਾਂ ਆਟੋਮੈਟਿਕ ਲਿੰਕ)',
+'tog-fancysig' => 'ਦਸਤà¨\96਼ਤ ਨà©\82à©° ਬਤà©\8cਰ ਵਿà¨\95à©\80ਲਿà¨\96ਤ ਵਰਤੋ (ਬਿਨਾਂ ਆਟੋਮੈਟਿਕ ਲਿੰਕ)',
'tog-externaleditor' => 'ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਬਾਹਰੀ ਸੋਧਕ ਵਰਤੋ (ਸਿਰਫ਼ ਮਾਹਿਰਾਂ ਲਈ ਹੈ, ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਤੇ ਖ਼ਾਸ ਸੈਟਿੰਗਾਂ ਲੋੜੀਂਦੀਆਂ ਹਨ। [//
www.mediawiki.org/wiki/
Manual:External_editors More
ਮਾਹਿਰਾਂ ਲਈ ਹੈ, ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਤੇ ਖ਼ਾਸ
ਸੈਟਿੰਗਾਂ ਲੋੜੀਂਦੀਆਂ ਹਨ। [//
www.mediawiki.org/wiki/
-Manual:External_editors More
-information.])',
+Manual:External_editors ਹੋਰ ਜਾਣਕਾਰੀ।])',
'tog-showjumplinks' => '"ਇਸ ਤੇ ਜਾਓ" ਦੇ ਲਿੰਕ ਦਿਖਾਣਾ ਸਮਰੱਥ ਕਰੋ',
'tog-uselivepreview' => 'ਸਿੱਧੀ ਝਲਕ ਵਰਤੋ (ਜਾਵਾਸਕ੍ਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ) (ਤਜਰਬੇਕਾਰੀ)',
'tog-forceeditsummary' => 'ਜਦੋਂ ਮੈਂ ਖ਼ਾਲੀ ਸੋਧ ਸਾਰ ਦਾਖ਼ਲ ਕਰਾਂ ਤਾਂ ਮੈਨੂੰ ਖ਼ਬਰਦਾਰ ਕਰੋ',
'tog-watchlisthideown' => 'ਮੇਰੀ ਵਾਚ-ਲਿਸਟ ਵਿੱਚੋਂ ਮੇਰੀਆਂ ਸੋਧਾਂ ਹਟਾਓ',
'tog-watchlisthidebots' => 'ਮੇਰੀ ਵਾਚ-ਲਿਸਟ ਵਿੱਚੋਂ ਰੋਬਾਟ ਦਿਆਂ ਸੋਧਾਂ ਹਟਾਓ',
'tog-watchlisthideminor' => 'ਛੋਟੇ ਸੋਧ ਵਾਚ-ਲਿਸਟ ਤੋਂ ਓਹਲੇ ਰੱਖੋ',
-'tog-watchlisthideliu' => 'ਨਿà¨\97ਰਾਨà©\80-ਲਿਸà¨\9f ਵਿà¨\9aà©\8bà¨\82 ਲਾà¨\97 à¨\87ਨ à¨\95à©\80ਤà©\87 ਮà©\88à¨\82ਬਰਾà¨\82 ਦà©\80à¨\86à¨\82 ਸà©\8bਧਾà¨\82 ਲੁਕਾਓ',
-'tog-watchlisthideanons' => 'ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚ ਗੁਮਨਾਮ ਮੈਂਬਰਾਂ ਦੀਆਂ ਕੀਤੀਆਂ ਸੋਧਾਂ ਲੁਕਾਓ',
+'tog-watchlisthideliu' => 'ਨਿà¨\97ਰਾਨà©\80-ਲਿਸà¨\9f ਵਿà¨\9aà©\8bà¨\82 ਲਾà¨\97 à¨\87ਨ ਮà©\88à¨\82ਬਰਾà¨\82 ਦà©\87 à¨\95à©\80ਤà©\87 ਫà©\87ਰ-ਬਦਲ ਲੁਕਾਓ',
+'tog-watchlisthideanons' => 'ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚੋਂ ਗੁਮਨਾਮ ਮੈਂਬਰਾਂ ਦੇ ਕੀਤੇ ਫੇਰ-ਬਦਲ ਲੁਕਾਓ',
'tog-watchlisthidepatrolled' => 'ਵੇਖੀਆਂ ਜਾ ਚੁੱਕੀਆਂ ਸੋਧਾਂ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚੋਂ ਲੁਕਾਓ',
'tog-ccmeonemails' => 'ਜੋ ਈ-ਮੇਲਾਂ ਮੈਂ ਦੂਜੇ ਮੈਂਬਰਾਂ ਨੂੰ ਭੇਜਦਾ ਹਾਂ ਓਹਨਾਂ ਦੀਆਂ ਨਕਲਾਂ ਮੈਨੂੰ ਭੇਜੋ',
'tog-diffonly' => 'ਫ਼ਰਕਾਂ ਤੋਂ ਹੇਠ ਸਫ਼ੇ ਦੀ ਸਮੱਗਰੀ ਨਾ ਵਖਾਓ',
-'tog-showhiddencats' => 'ਲà©\81à¨\95à©\80à¨\86à¨\82 ਸ਼à©\8dਰà©\87ਣੀਆਂ ਵਖਾਓ',
+'tog-showhiddencats' => 'ਲà©\81à¨\95à©\80à¨\86à¨\82 à¨\95à©\88à¨\9fà©\87à¨\97ਰੀਆਂ ਵਖਾਓ',
'tog-norollbackdiff' => '"ਵਾਪਸ ਮੋੜੌ"ਅਮਲ ਵਿਚ ਲਿਆਣ ਬਾਦ ਫ਼ਰਕ ਨਾ ਦਿਖਾਓ',
'underline-always' => 'ਹਮੇਸ਼ਾਂ',
'pagecategories' => '{{PLURAL:$1|ਕੈਟਾਗਰੀ|ਕੈਟਾਗਰੀਆਂ}}',
'category_header' => 'ਕੈਟਾਗਰੀ "$1" ਵਿੱਚ ਲੇਖ',
'subcategories' => 'ਸਬ-ਕੈਟਾਗਰੀਆਂ',
-'category-media-header' => 'à¨\95à©\88à¨\9fਾਗਰੀ "$1" ਵਿੱਚ ਮੀਡੀਆ',
-'category-empty' => "''à¨\87ਸ à¨\95à©\88à¨\9fਾà¨\97ਰà©\80 ਵਿੱà¨\9a à¨\87ਸ ਵà©\87ਲ਼à©\87 à¨\95à©\8bà¨\88 ਵà©\80 ਲà©\87à¨\96 ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ ਹੈ।''",
+'category-media-header' => 'à¨\95à©\88à¨\9fà©\87ਗਰੀ "$1" ਵਿੱਚ ਮੀਡੀਆ',
+'category-empty' => "''à¨\87ਸ à¨\95à©\88à¨\9fà©\87à¨\97ਰà©\80 ਵਿੱà¨\9a à¨\87ਸ ਵà©\87ਲ਼à©\87 à¨\95à©\8bà¨\88 ਵà©\80 ਸਫ਼ਾ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ ਹੈ।''",
'hidden-categories' => '{{PLURAL:$1|ਲੁਕੀਵੀਂ ਸ਼੍ਰੇਣੀ|ਲੁਕਵੀਂਆਂ ਸ਼੍ਰੇਣੀਆਂ}}',
-'hidden-category-category' => 'ਲà©\81à¨\95à©\80à¨\86à¨\82 ਸ਼à©\8dਰà©\87ਣੀਆਂ',
+'hidden-category-category' => 'ਲà©\81à¨\95à©\80à¨\86à¨\82 à¨\95à©\88à¨\9fà©\87à¨\97ਰੀਆਂ',
'category-subcat-count' => '{{ਕੁੱਲ $2 ਸ਼੍ਰੇਣੀਆਂ ਵਿਚੋਂ, PLURAL:$2|ਇਸ ਸ਼੍ਰੇਣੀ ਵਿਚ ਸਿਰਫ਼ ਹੇਠ ਲਿਖੀ ਸ਼੍ਰੇਣੀ ਹੈ| ਇਸ ਸ਼੍ਰੇਣੀ ਵਿਚ {{PLURAL:$1|ਉਪ ਸ਼੍ਰੇਣੀ ਹੈ|$1 ਉਪ-ਸ਼੍ਰੇਣੀਆਂ ਹਨ}}}}',
'category-subcat-count-limited' => 'ਇਸ ਸ਼੍ਰੇਣੀ ਵਿਚ {{PLURAL:$1|ਉਪ-ਸ਼੍ਰੇਣੀ ਹੈ।|$1 ਉਪ-ਸ਼੍ਰੇਣੀਆਂ ਹਨ।}}',
'category-article-count' => '{{PLURAL:$2|ਇਸ ਸ਼੍ਰੇਣੀ ਵਿਚ ਸਿਰਫ਼ ਇਹ ਸਫ਼ਾ ਹੈ|ਇਸ ਸ਼੍ਰੇਣੀ ਵਿਚ, ਕੁੱਲ $2 ਵਿਚੋਂ, ਇਹ {{PLURAL:$1|ਸਫ਼ਾ ਹੈ|$1 ਸਫ਼ੇ}} ਹਨ}}',
'vector-action-addsection' => 'ਮਜ਼ਮੂਨ ਜੋੜੋ',
'vector-action-delete' => 'ਮਿਟਾਓ',
'vector-action-move' => 'ਭੇਜੋ',
-'vector-action-protect' => 'ਸà©\81ਰੱà¨\96ਿà¨\85ਤ ਬਣਾà¨\93',
+'vector-action-protect' => 'ਸà©\81ਰੱà¨\96ਿà¨\85ਤ à¨\95ਰà©\8b',
'vector-action-undelete' => 'ਹਟਾਉਣਾ ਵਾਪਸ',
'vector-action-unprotect' => 'ਸੁਰੱਖਿਆ ਬਦਲੋ',
'vector-simplesearch-preference' => 'ਵਾਧੂ ਖੋਜ ਸਲਾਹਾਂ ਯੋਗ ਕਰੋ (ਸਿਰਫ਼ ਵਿਕਟਰ ਸਕਿੰਨ ਵਿਚ)',
'login' => 'ਲਾਗ ਇਨ',
'nav-login-createaccount' => 'ਲਾਗ ਇਨ/ਖਾਤਾ ਬਣਾਓ',
'loginprompt' => 'ਤੁਹਾਨੂੰ {{SITENAME}} ’ਤੇ ਲਾਗਇਨ ਕਰਨ ਲਈ ਕੂਕੀਜ਼ ਯੋਗ ਕਰਨੇ ਜ਼ਰੂਰੀ ਹਨ।',
-'userlogin' => 'ਲਾà¨\97 à¨\87ਨ/à¨\96ਾਤਾ à¨\96à©\8bਲà©\8dਹà©\8b',
+'userlogin' => 'ਲਾà¨\97 à¨\87ਨ/à¨\96ਾਤਾ ਬਣਾà¨\93',
'userloginnocreate' => 'ਲਾਗ ਇਨ',
'logout' => 'ਲਾਗ ਆਉਟ',
'userlogout' => 'ਲਾਗ ਆਉਟ',
'nologin' => 'ਖਾਤਾ ਨਹੀਂ ਹੈ? $1।',
'nologinlink' => 'ਖਾਤਾ ਬਣਾਓ',
'createaccount' => 'ਖਾਤਾ ਬਣਾਓ',
-'gotaccount' => "ਖਾਤਾ ਹੈ? '''$1'''।",
+'gotaccount' => 'ਖਾਤਾ ਹੈ? $1।',
'gotaccountlink' => 'ਲਾਗ ਇਨ',
'userlogin-resetlink' => 'ਆਪਣੀ ਲਾਗਇਨ ਜਾਣਕਾਰੀ ਭੁੱਲ ਗਏ ਹੋ?',
'createaccountmail' => 'ਈਮੇਲ ਨਾਲ',
'accmailtitle' => 'ਪਾਸਵਰਡ ਭੇਜਿਆ।',
'accmailtext' => '"$1" ਲਈ ਪਾਸਵਰਡ $2 ਨੂੰ ਭੇਜਿਆ ਗਿਆ।',
'newarticle' => '(ਨਵਾਂ)',
-'newarticletext' => "ਤà©\81ਸà©\80à¨\82 à¨\95ਿਸà©\87 à¨\90ਸà©\87 ਲਿੰà¨\95 ਰਾਹà©\80à¨\82 à¨\87ਸ ਸਫ਼à©\87 â\80\99ਤà©\87 ਪà©\81ੱà¨\9cੇ ਹੋ ਜੋ ਹਾਲੇ ਬਣਾਇਆ ਨਹੀਂ ਗਿਆ।
-ਸਫ਼ਾ ਬਣਾਉਣ ਲਈ ਹੇਠ ਦਿੱਤੇ ਖ਼ਾਨੇ ਵਿਚ ਲਿਖਣਾ ਸ਼ੁਰੂ ਕਰੋ। (ਹੋਰ ਮਦਦ ਲਈ [[{{MediaWiki:Helppage}}|ਮਦਦ ਸਫ਼ਾ]] ਵੇਖੋ)
-à¨\9cà©\87 ਤà©\81ਸà©\80à¨\82 à¨\97਼ਲਤà©\80 ਨਾਲ਼ à¨\87ੱਥà©\87 à¨\86à¨\8f ਹà©\8b ਤਾà¨\82 à¨\86ਪਣà©\87 ਬਰਾà¨\8aà¨\9c਼ਰ ਦà©\87 ''ਪਿੱà¨\9bà©\87'' (back) ਬਟਨ ’ਤੇ ਕਲਿੱਕ ਕਰੋ।",
+'newarticletext' => "ਤà©\81ਸà©\80à¨\82 à¨\95ਿਸà©\87 à¨\90ਸà©\87 ਸਫ਼à©\87 ਦà©\87 ਲਿੰà¨\95 â\80\99ਤੇ ਹੋ ਜੋ ਹਾਲੇ ਬਣਾਇਆ ਨਹੀਂ ਗਿਆ।
+ਸਫ਼ਾ ਬਣਾਉਣ ਲਈ ਹੇਠ ਦਿੱਤੇ ਖ਼ਾਨੇ ਵਿਚ ਲਿਖਣਾ ਸ਼ੁਰੂ ਕਰੋ। (ਹੋਰ ਮਦਦ ਲਈ [[{{MediaWiki:Helppage}}|ਮਦਦ ਸਫ਼ਾ]] ਵੇਖੋ।)
+à¨\9cà©\87 ਤà©\81ਸà©\80à¨\82 à¨\97਼ਲਤà©\80 ਨਾਲ਼ à¨\87ੱਥà©\87 à¨\86à¨\8f ਹà©\8b ਤਾà¨\82 à¨\86ਪਣà©\87 ਬà©\8dਰਾà¨\8aà¨\9c਼ਰ ਦà©\87 '''ਪਿੱà¨\9bà©\87''' ਬਟਨ ’ਤੇ ਕਲਿੱਕ ਕਰੋ।",
'anontalkpagetext' => "----''ਇਹ ਇਕ ਗੁਮਨਾਮ ਮੈਂਬਰ ਲਈ ਇਕ ਚਰਚਾ ਸਫ਼ਾ ਹੈ ਜਿਸਨੇ ਹਾਲੇ ਖਾਤਾ ਨਹੀ ਬਣਾਇਆ ਜਾਂ ਉਸਨੂੰ ਵਰਤ ਨਹੀਂ ਰਿਹਾ।
ਇਸ ਵਾਸਤੇ ਸਾਡੇ ਕੋਲ ਉਸਨੂੰ ਪਛਾਨਣ ਲਈ IP ਪਤਾ ਹੈ।
ਇਕ IP ਪਤਾ ਕਈ ਵਰਤਣ ਵਾਲ਼ਿਆਂ ਦੁਆਰਾ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।
'''ਇਹ ਹਾਲੇ ਸਾਂਭੀ ਨਹੀਂ ਗਈ ਹੈ!'''",
'updated' => '(ਅੱਪਡੇਟ)',
'note' => "'''ਨੋਟ:'''",
-'previewnote' => 'ਯਾਦ ਰੱਖੋ ਇਹ ਸਿਰਫ਼ ਇੱਕ ਝਲਕ ਹੈ; ਤੁਹਾਡੀਆਂ ਤਬਦੀਲੀਆਂ ਹਾਲੇ ਸਾਂਭੀਆਂ ਨਹੀਂ ਗਈਆਂ!',
+'previewnote' => "'''ਯਾਦ ਰੱਖੋ ਇਹ ਸਿਰਫ਼ ਇਕ ਝਲਕ ਹੈ।''' ਤੁਹਾਡੀਆਂ ਤਬਦੀਲੀਆਂ ਹਾਲੇ ਸਾਂਭੀਆਂ ਨਹੀਂ ਗਈਆਂ!",
'continue-editing' => 'ਸੋਧਣਾ ਜਾਰੀ ਰੱਖੋ',
'previewconflict' => 'ਇਹ ਝਲਕ ਲਿਖਤ ਦਾ ਓਹ ਅਕਸ ਪੇਸ਼ ਕਰਦੀ ਹੈ ਜਿਵੇਂ ਓਹ ਤੁਹਾਡੇ ਸਾਂਭੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਦਿੱਸੇਗਾ।',
'editing' => '$1 ਸੋਧਿਆ ਜਾ ਰਿਹਾ ਹੈ',
'templatesusedsection' => 'ਇਹ ਸ਼ੈਕਸ਼ਨ ਵਿੱਚ ਟੈਪਲੇਟ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ:',
'template-protected' => '(ਸੁਰੱਖਿਅਤ)',
'template-semiprotected' => '(ਨੀਮ-ਸੁਰੱਖਿਅਤ)',
-'hiddencategories' => 'ਇਹ ਸਫ਼ਾ {{PLURAL:$1|1 ਲੁਕਵੀਂ ਸ਼੍ਰੇਣੀ|
-$1 ਲà©\81à¨\95ਵà©\80à¨\86à¨\82 ਸ਼à©\8dਰà©\87ਣੀਆਂ}} ਦਾ ਮੈਂਬਰ ਹੈ:',
+'hiddencategories' => 'ਇਹ ਸਫ਼ਾ {{PLURAL:$1|੧ ਲੁਕਵੀਂ ਕੈਟੇਗਰੀ|
+$1 ਲà©\81à¨\95ਵà©\80à¨\86à¨\82 à¨\95à©\88à¨\9fà©\87à¨\97ਰੀਆਂ}} ਦਾ ਮੈਂਬਰ ਹੈ:',
'nocreatetitle' => 'ਸਫ਼ਾ ਬਣਾਉਣ ਦੀ ਹੱਦ ਹੈ',
'nocreatetext' => '{{SITENAME}} ਨੇ ਨਵੇਂ ਸਫ਼ੇ ਬਣਾਉਣ ਤੇ ਰੋਕ ਲਾਈ ਹੋਈ ਹੈ।
ਤੁਸੀਂ ਵਾਪਸ ਜਾ ਕੇ ਮੌਜੂਦਾ ਸਫ਼ੇ ਸੋਧ ਸਕਦੇ ਹੋ ਜਾਂ [[Special:UserLogin|ਲਾਗਇਨ ਜਾਂ ਖਾਤਾ ਬਣਾ]] ਸਕਦੇ ਹੋ।',
'''({{int:cur}})''' = ਨਵੇਂ ਰੀਵਿਜ਼ਨ ਨਾਲ਼ੋਂ ਫ਼ਰਕ, '''({{int:last}})''' = ਆਖ਼ਰੀ ਰੀਵਿਜ਼ਨ ਨਾਲ਼ੋਂ ਫ਼ਰਕ, '''({{int:minoreditletter}})''' = ਛੋਟੀ ਸੋਧ।",
'history-fieldset-title' => 'ਅਤੀਤ ’ਤੇ ਨਜ਼ਰ ਮਾਰੋ',
'history-show-deleted' => 'ਸਿਰਫ਼ ਮਿਟਾਏ ਗਏ',
-'histfirst' => 'ਸਭ ਤੋਂ ਪਹਿਲਾ',
+'histfirst' => 'ਸਭ ਤੋਂ ਪਹਿਲਾਂ ਦੇ',
'histlast' => 'ਸਭ ਤੋਂ ਨਵਾਂ',
'historysize' => '($1 ਬਾਈਟ)',
'historyempty' => '(ਖਾਲੀ)',
'mergelogpagetext' => 'ਹੇਠਾਂ ਇੱਕ ਸਫ਼ੇ ਦੇ ਅਤੀਤ ਨੂੰ ਦੂਜੇ ਦੇ ਅਤੀਤ ਵਿਚ ਰਲ਼ਾਉਣ ਦੀ ਸਭ ਤੋਂ ਤਾਜ਼ਾ ਲਿਸਟ ਹੈ।',
# Diffs
-'history-title' => '"$1" ਦà©\87 ਰà©\80ਵਿà¨\9c਼ਨ ਦਾ à¨\85ਤà©\80ਤ',
+'history-title' => '"$1" ਦà©\87 à¨\85ਤà©\80ਤ ਰà©\80ਵਿà¨\9c਼ਨ',
'difference-title' => '"$1" ਦੇ ਰੀਵਿਜ਼ਨਾਂ ਵਿਚ ਫ਼ਰਕ',
'difference-title-multipage' => 'ਸਫ਼ਿਆਂ "$1" ਅਤੇ "$2" ਵਿਚ ਫ਼ਰਕ',
'difference-multipage' => '(ਦੋ ਸਫ਼ਿਆਂ ਵਿਚਕਾਰ ਫ਼ਰਕ)',
'searchprofile-everything-tooltip' => 'ਸਭ ਚੀਜ਼ਾਂ ਖੋਜੋ (ਗੱਲਬਾਤ ਸਫ਼ਿਆਂ ਸਮੇਤ)',
'searchprofile-advanced-tooltip' => 'ਆਪਣੇ ਬਣਾਏ ਨਾਮ-ਥਾਂਵਾਂ ਵਿਚ ਖੋਜੋ',
'search-result-size' => '$1 ({{PLURAL:$2|੧ ਸ਼ਬਦ|$2 ਸ਼ਬਦ}})',
+'search-result-category-size' => '{{PLURAL:$1|੧ ਮੈਂਬਰ|$1 ਮੈਂਬਰ}} ({{PLURAL:$2|੧ ਸਬ-ਕੈਟੇਗਰੀ|$2 ਸਬ-ਕੈਟੇਗਰੀਆਂ}}, {{PLURAL:$3|੧ ਫ਼ਾਈਲ|$3 ਫ਼ਾਈਲਾਂ}})',
'search-redirect' => '($1 ਰੀ-ਡਿਰੈਕਟ)',
'search-section' => '(ਭਾਗ $1)',
'search-suggest' => 'ਕੀ ਤੁਹਾਡਾ ਮਤਲਬ ਸੀ: $1',
# Associated actions - in the sentence "You do not have permission to X"
'action-read' => 'ਇਹ ਸਫ਼ਾ ਪੜ੍ਹਨ',
-'action-edit' => 'à¨\87ਹ ਸਫ਼ਾ ਸà©\8bਧੋ',
+'action-edit' => 'à¨\87ਹ ਸਫ਼à©\87 â\80\99à¨\9a ਫà©\87ਰ-ਬਦਲ à¨\95ਰੋ',
'action-createpage' => 'ਸਫ਼ੇ ਬਣਾਉਣ',
'action-createtalk' => 'ਚਰਚਾ ਸਫ਼ੇ ਬਣਾਉਣ',
'action-createaccount' => 'ਮੈਂਬਰ ਖਾਤਾ ਬਣਾਉਣ',
'upload-recreate-warning' => "'''ਖ਼ਬਰਦਾਰ: ਇਸ ਨਾਮ ਦੀ ਫ਼ਾਈਲ ਮਿਟਾਈ ਜਾਂ ਹੋਰ ਨਾਮ ਤੇ ਭੇਜੀ ਜਾ ਚੁੱਕੀ ਹੈ।'''
ਮਿਟਾਉਣ ਅਤੇ ਭੇਜੇ ਜਾਣ ਦਾ ਚਿੱਠਾ ਸਹੂਲਤ ਲਈ ਇੱਥੇ ਦਿੱਤਾ ਗਿਆ ਹੈ:",
'uploadlog' => 'ਅੱਪਲੋਡ ਲਾਗ',
-'uploadlogpage' => 'ਅੱਪਲੋਡ ਦਾ ਚਿੱਠਾ',
+'uploadlogpage' => 'ਅੱਪਲੋਡਾਂ ਦਾ ਚਿੱਠਾ',
'filename' => 'ਫਾਇਲ ਨਾਂ',
'filedesc' => 'ਸਾਰ',
'fileuploadsummary' => 'ਸੰਖੇਪ:',
'upload-curl-error28' => 'ਅੱਪਲੋਡ ਟਾਈਮ-ਆਉਟ',
'license' => 'ਲਾਈਸੈਂਸਿੰਗ:',
-'license-header' => 'ਲਾà¨\88ਸੰਸ',
+'license-header' => 'ਲਾà¨\88ਸà©\88à¨\82ਸ',
'nolicense' => 'ਕੁਝ ਵੀ ਚੁਣਿਆ',
'license-nopreview' => '(ਝਲਕ ਉਪਲੱਬਧ ਨਹੀਂ)',
'upload_source_file' => ' (ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਉੱਤੇ ਇੱਕ ਫਾਇਲ)',
'statistics-users-active-desc' => 'ਮੈਂਬਰ, ਜਿੰਨ੍ਹਾ ਨੇ ਆਖ਼ਰੀ {{PLURAL:$1|ਦਿਨ|$1 ਦਿਨਾਂ}} ਵਿਚ ਕੋਈ ਕੰਮ ਕੀਤਾ ਹੈ।',
'statistics-mostpopular' => 'ਸਭ ਤੋਂ ਵੱਧ ਵੇਖੇ ਪੇਜ',
+'disambiguationspage' => 'ਗੁੰਝਲ ਖੋਲ੍ਹ',
+
'doubleredirects' => 'ਦੋਹਰੇ ਰੀਡਿਰੈਕਟ',
'brokenredirectstext' => 'ਇਹ ਰਿਡਿਰੈਕਟ ਨਾ-ਮੌਜੂਦ ਸਫ਼ਿਆਂ ’ਤੇ ਜੋੜਦੇ ਹਨ:',
'prefixindex' => 'ਇਸ ਅਗੇਤਰ ਵਾਲ਼ੇ ਸਾਰੇ ਸਫ਼ੇ',
'shortpages' => 'ਛੋਟੇ ਪੇਜ',
'listusers' => 'ਯੂਜ਼ਰ ਲਿਸਟ',
-'usercreated' => '$1 ਨà©\82à©° $2 â\80\99ਤà©\87 {{GENDER:$3|ਰà¨\9aਿਆ}}',
+'usercreated' => '$1 ਨà©\82à©° $2 â\80\99ਤà©\87 {{GENDER:$3|ਬਣਾà¨\87ਆ}}',
'newpages' => 'ਨਵੇਂ ਸਫ਼ੇ',
'newpages-username' => 'ਯੂਜ਼ਰ ਨਾਂ:',
'ancientpages' => 'ਸਭ ਤੋਂ ਪੁਰਾਣੇ ਪੇਜ',
'actionfailed' => 'ਕਾਰਵਾਈ ਨਾਕਾਮ',
'deletedtext' => '"$1" ਮਿਟਾਇਆ ਜਾ ਚੁੱਕਾ ਹੈ।
ਤਾਜ਼ੀਆਂ ਮਿਟਾਉਣਾਂ ਦੇ ਰਿਕਾਰਡ ਲਈ $2 ਵੇਖੋ।',
-'dellogpage' => 'ਮਿਟਾਉਣ ਦਾ ਚਿੱਠਾ',
+'dellogpage' => 'ਮਿਟਾਉਣਾਂ ਦਾ ਚਿੱਠਾ',
'dellogpagetext' => 'ਹੇਠਾਂ ਸਭ ਤੋਂ ਤਾਜ਼ਾ ਮਿਟਾਉਣਾਂ ਦੀ ਲਿਸਟ ਹੈ।',
'deletionlog' => 'ਮਿਟਾਉਣਾਂ ਦਾ ਚਿੱਠਾ',
'deletecomment' => 'ਕਾਰਨ:',
'sp-contributions-blocked-notice-anon' => 'ਇਹ IP ਪਤਾ ਇਸ ਵੇਲ਼ੇ ਪਾਬੰਦੀਸ਼ੁਦਾ ਹੈ।
ਪਾਬੰਦੀ ਚਿੱਠੇ ਦਾ ਤਾਜ਼ਾ ਦਾਖ਼ਲਾ ਹਵਾਲੇ ਲਈ ਹੇਠਾਂ ਦਿੱਤਾ ਗਿਆ ਹੈ:',
'sp-contributions-search' => 'ਯੋਗਦਾਨ ਖੋਜੋ',
-'sp-contributions-username' => 'IP ਪਤਾ à¨\9cਾà¨\82 ਯà©\82à¨\9c਼ਰ ਨਾà¨\82:',
+'sp-contributions-username' => 'IP ਪਤਾ à¨\9cਾà¨\82 ਯà©\82à¨\9c਼ਰ ਨਾਮ:',
'sp-contributions-toponly' => 'ਸਿਰਫ਼ ਉਹੀ ਸੋਧਾਂ ਵਖਾਓ ਜੋ ਸਭ ਤੋਂ ਨਵੀਂਆਂ ਹਨ',
'sp-contributions-submit' => 'ਖੋਜੋ',
# What links here
'whatlinkshere' => 'ਕਿਹੜੇ (ਸਫ਼ੇ) ਇੱਥੇ ਜੋੜਦੇ ਹਨ',
-'whatlinkshere-title' => '$1 ਨਾਲ਼ à¨\9cà©\8bà©\9cਦੇ ਸਫ਼ੇ',
+'whatlinkshere-title' => '$1 ਨਾਲ਼ à¨\9cà©\8bà©\9cਨ ਵਾਲ਼ੇ ਸਫ਼ੇ',
'whatlinkshere-page' => 'ਸਫਾ:',
'linkshere' => "ਇਹ ਸਫ਼ੇ '''[[:$1]]''' ਨਾਲ਼ ਜੋੜਦੇ ਹਨ:",
'nolinkshere' => "ਕੋਈ ਵੀ ਸਫ਼ਾ '''[[:$1]]''' ਨਾਲ਼ ਨਹੀਂ ਜੋੜਦਾ।",
-'isredirect' => 'ਰੀ-ਡਿਰੈਕਟ ਸਫ਼ਾ',
+'isredirect' => 'ਰੀਡਿਰੈਕਟ ਸਫ਼ਾ',
'istemplate' => 'ਟਾਕਰਾ ਕਰੋ',
'isimage' => 'ਫ਼ਾਈਲ ਦਾ ਲਿੰਕ',
'whatlinkshere-prev' => '{{PLURAL:$1|ਪਿਛਲਾ|ਪਿਛਲੇ $1}}',
ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਕੋਈ ਹੋਰ ਨਾਮ ਚੁਣੋ।',
'movedto' => 'ਮੂਵ ਕੀਤਾ',
'movepage-page-moved' => 'ਸਫ਼ਾ $1 ਨੂੰ $2 ’ਤੇ ਭੇਜਿਆ ਜਾ ਚੁੱਕਾ ਹੈ।',
-'movelogpage' => 'à¨à©\87à¨\9cà©\87 à¨\9cਾਣ ਦਾ ਚਿੱਠਾ',
+'movelogpage' => 'ਸਿਰਲà©\87à¨\96 ਬਦਲà©\80 ਦਾ ਚਿੱਠਾ',
'movereason' => 'ਕਾਰਨ:',
'revertmove' => 'ਰੱਦ ਕਰੋ',
'delete_and_move' => 'ਹਟਾਓ ਅਤੇ ਮੂਵ ਕਰੋ',
'tooltip-ca-nstab-template' => 'ਸਾਂਚਾ ਵੇਖੋ',
'tooltip-ca-nstab-help' => 'ਮੱਦਦ ਪੇਜ ਵੇਖੋ',
'tooltip-ca-nstab-category' => 'ਕੈਟਾਗਰੀ ਸਫ਼ਾ ਵੇਖੋ',
-'tooltip-minoredit' => 'à¨\87ਸ â\80\99ਤà©\87 à¨\9bà©\8bà¨\9fà©\80 ਤਬਦਲà©\80 ਦà©\87 ਤà©\8cਰ â\80\99ਤà©\87 ਨਿਸ਼ਾਨ ਲਾਓ',
+'tooltip-minoredit' => 'à¨\87ਸ â\80\99ਤà©\87 ਬਤà©\8cਰ à¨\9bà©\8bà¨\9fà©\80 ਤਬਦà©\80ਲà©\80 ਨਿਸ਼ਾਨ ਲਾਓ',
'tooltip-save' => 'ਆਪਣੀਆਂ ਤਬਦੀਲੀਆਂ ਸਾਂਭੋ',
'tooltip-preview' => 'ਆਪਣੀ ਤਬਦੀਲੀ ਦੀ ਝਲਕ ਵੇਖੋ, ਸਾਂਭਣ ਤੋਂ ਪਹਿਲਾਂ ਇਹ ਵਰਤੋਂ!',
'tooltip-diff' => 'ਤੁਹਾਡੇ ਦੁਆਰਾ ਲਿਖਤ ਵਿਚ ਕੀਤੀਆਂ ਤਬਦੀਲੀਆਂ ਵਖਾਉਂਦਾ ਹੈ',
'username' => 'Nazwa użytkownika',
'uid' => 'ID użytkownika',
'prefs-memberingroups' => 'Należy do {{PLURAL:$1|grupy|grup}}',
-'prefs-registration' => 'Moment rejestracji',
+'prefs-registration' => 'Data rejestracji',
'yourrealname' => 'Imię i nazwisko',
'yourlanguage' => 'Język interfejsu',
'yourvariant' => 'Wariant języka treści',
'uploadnewversion-linktext' => 'Załaduj nowszą wersję tego pliku',
'shared-repo-from' => 'z $1',
'shared-repo' => 'współdzielone zasoby',
+'upload-disallowed-here' => 'Niestety, nie możesz nadpisać tego pliku.',
# File reversion
'filerevert' => 'Przywracanie $1',
'pageinfo-authors' => 'Całkowita liczba autorów',
'pageinfo-recent-edits' => 'Liczba ostatnich edycji (w przeciągu $1)',
'pageinfo-recent-authors' => 'Liczba ostatnich autorów',
-'pageinfo-restriction' => 'Zabezpieczenie strony (<code>$1</code>)',
+'pageinfo-restriction' => 'Zabezpieczenie strony (<code>{{lcfirst:$1}}</code>)',
'pageinfo-magic-words' => 'Magiczne {{PLURAL:$1|słowo|słowa|słowa}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Ukryta kategoria|Ukryte kategorie|Ukryte kategorie}} ($1)',
'pageinfo-templates' => 'Transkludowan{{PLURAL:$1|y szablon|e szablony}} ($1)',
'file-info-size-pages' => '$1 × $2 pikseli, rozmiar pliku: $3, typ MIME: $4, $5 {{PLURAL:$5|strona|strony|stron}}',
'file-nohires' => 'Grafika w wyższej rozdzielczości nie jest dostępna.',
'svg-long-desc' => 'Plik SVG, nominalnie $1 × $2 pikseli, rozmiar pliku: $3',
+'svg-long-desc-animated' => 'Animowany plik SVG, nominalnie $1 × $2 pikseli, rozmiar pliku: $3',
'show-big-image' => 'Pełna rozdzielczość',
'show-big-image-preview' => 'Rozmiar podglądu – $1.',
'show-big-image-other' => '{{PLURAL:$2|Inna rozdzielczość|Inne rozdzielczości}}: $1.',
'file-info-png-looped' => 'zapętlony',
'file-info-png-repeat' => 'powtarzany $1 {{PLURAL:$1|raz|razy}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|klatka|klatki|klatek}}',
+'file-no-thumb-animation' => "'''Uwaga: z powodu ograniczeń technicznych miniaturki tego pliku nie bedą animowane.'''",
+'file-no-thumb-animation-gif' => "'''Uwaga: z powodu ograniczeń technicznych miniaturki plików GIF o wysokiej rozdzielczości – takich jak ten – nie bedą animowane.'''",
# Special:NewFiles
'newimages' => 'Najnowsze pliki',
# General errors
'error' => 'Eror',
'databaseerror' => 'Eror ant la base dat',
-'dberrortext' => 'A l\'é capitaje n\'eror ëd sintassi ant la domanda mandà a la base dat.
-Sòn a peul vorèj dì n\'eror ant ël programa.
-L\'ùltima domanda mandà a la base dat a l\'é stàita:
+'dberrortext' => "A l'é capitaje n'eror ëd sintassi ant la domanda mandà a la base dij dat.
+Sòn a peul vorèj dì n'eror ant ël programa.
+L'ùltima arcesta mandà a la base dij dat a l'é stàita:
<blockquote><tt>$1</tt></blockquote>
-da \'nt la funsion "<tt>$2</tt>".
-La base dat a l\'ha dane andré n\'eror "<tt>$3: $4</tt>".',
+da 'nt la funsion «<tt>$2</tt>».
+La base dij dat a l'ha dàit n'eror «<tt>$3: $4</tt>».",
'dberrortextcl' => 'A-i é staje n\'eror ant la sintassi d\'anterogassion dla base dat.
L\'ùltima anterogassion a l\'é stàita:
"$1"
'shared-repo-from' => 'da $1',
'shared-repo' => "n'archivi condivis",
'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
-'upload-disallowed-here' => 'Për maleur it peule pa dzorscrive sta figura.',
+'upload-disallowed-here' => 'Për maleur a peul pa rampiassé sta figura.',
# File reversion
'filerevert' => "Buté torna $1 tanme ch'a l'era",
'mostlinkedtemplates' => 'Stamp pì dovrà',
'mostcategories' => 'Artìcoj che a son marcà an pì categorìe',
'mostimages' => 'Figure pì dovrà',
-'mostinterwikis' => 'Pagine con pi antërwiki',
+'mostinterwikis' => "Pàgine con pi 'd liure antërwiki",
'mostrevisions' => 'Artìcoj pì modificà',
'prefixindex' => "Tute le pàgine ch'a ancamin-o con",
'prefixindex-namespace' => 'Tute le pàgine con prefiss ($1 spassi nominal)',
'mailnologintext' => "A dev [[Special:UserLogin|rintré ant ël sistema]]
e avèj registrà n'adrëssa ëd pòsta eletrònica vàlida ant ij [[Special:Preferences|sò gust]] për podèj mandé dij mëssagi ëd pòsta eletrònica a j'àutri Utent.",
'emailuser' => "Mandeje un mëssagi eletrònich a st'utent-sì",
-'emailuser-title-target' => 'Manda e-mail a sto {{GENDER:$1|utent}}',
+'emailuser-title-target' => 'Mandé un mëssagi ëd pòsta eletrònica a cost {{GENDER:$1|utent}}',
'emailuser-title-notarget' => "Mandeje un mëssagi ëd pòsta eletrònica a st'utent-sì",
'emailpage' => "Mandeje un mëssagi ëd pòsta eletrònica a st'utent-sì",
'emailpagetext' => "A peule dovré ël formolari sì-sota për mandé un mëssagi ëd pòsta eletrònica a st'utent-sì.
'tooltip-ca-nstab-main' => 'Vardé la pàgina ëd contnù.',
'tooltip-ca-nstab-user' => 'Vardé la pàgina Utent.',
'tooltip-ca-nstab-media' => 'Vardé la pàgina dël mojen',
-'tooltip-ca-nstab-special' => 'Costa a l',
+'tooltip-ca-nstab-special' => "Costa a l'é na pàgina special, a peul nen modifichela.",
'tooltip-ca-nstab-project' => 'Vardé la pàgina proteta.',
-'tooltip-ca-nstab-image' => 'Vardé la pàgina dl',
-'tooltip-ca-nstab-mediawiki' => 'Vardé ël messagi ëd sistema.',
+'tooltip-ca-nstab-image' => "Vardé la pàgina dl'archivi",
+'tooltip-ca-nstab-mediawiki' => 'Vardé ël mëssagi ëd sistema.',
'tooltip-ca-nstab-template' => 'Vardé lë stamp.',
-'tooltip-ca-nstab-help' => 'Vardé la pàgina d',
+'tooltip-ca-nstab-help' => "Vardé la pàgina d'agiut",
'tooltip-ca-nstab-category' => 'Vardé la pàgina dla categorìa.',
-'tooltip-minoredit' => 'Marca sossì coma modìfica cita',
-'tooltip-save' => 'Salva le modìfiche',
+'tooltip-minoredit' => 'Marché sòn coma modìfica cita',
+'tooltip-save' => 'Salvé le modìfiche',
'tooltip-preview' => 'Preuva dle modìfiche (mej sempe fela, prima che fé che salvé!)',
-'tooltip-diff' => "Fame vëdde che modìfiche che i l'hai faje al test.",
-'tooltip-compareselectedversions' => 'Fame ël paragon dle diferense antra le version selessionà.',
-'tooltip-watch' => 'Gionta sta pàgina-sì a la lista dle ròbe che im ten-o sot euj',
+'tooltip-diff' => "A fa vëdde le modìfiche che a l'ha faje al test",
+'tooltip-compareselectedversions' => 'Fé ël paragon dle diferense antra le version selessionà.',
+'tooltip-watch' => 'Gionté sta pàgina-sì a la lista dle ròbe che im ten-o sot euj',
'tooltip-watchlistedit-normal-submit' => 'Gavé via ij tìtoj',
-'tooltip-watchlistedit-raw-submit' => 'Agiorné la Lista',
-'tooltip-recreate' => 'Creé torna la pàgina contut che a la sia staita scancelà',
+'tooltip-watchlistedit-raw-submit' => "Agiorné la lista dle ròbe ch'as ten-o sot-euj",
+'tooltip-recreate' => 'Creé torna la pàgina contut che a la sia stàita scancelà',
'tooltip-upload' => 'Anandiesse a carié',
-'tooltip-rollback' => '"Rollback" a scansela con un clich le modìfiche fàite a costa pagina da l\'ùltim contribudor',
-'tooltip-undo' => '"Undo" a scansela costa modìfica e a deurb la fnestra ëd modìfica an manera ëd vardé prima.
-At lassa gionté na spiegassion ëd la modìfica.',
+'tooltip-rollback' => "«Tiré andré» a gava con un colp ëd rat le modìfiche fàite a costa pàgina da l'ùltim contributor",
+'tooltip-undo' => "«Buté 'me ch'a l'era» a scancela costa modìfica e a deurb la fnestra ëd modìfica an manera ëd preuva.
+A lassa gionté na spiegassion ant ël resumé.",
'tooltip-preferences-save' => 'Salvé ij sò gust',
'tooltip-summary' => 'Anserì un curt resumé',
'monobook.js' => "/* Ës messagi-sì as dovrìa pa pì dovrelo; a sò pòst ch'a dòvra [[MediaWiki:common.js]] */",
# Metadata
-'notacceptable' => 'Ël server dla wiki a-i la fa pa a provëdde dij dat ant na forma che sò programa local a peula lese.',
+'notacceptable' => 'Ës servent ëd la wiki a-i la fa pa a fornì dij dat ant na forma che sò programa local a peula lese.',
# Attribution
'anonymous' => '{{PLURAL:$1|Utent|Utent}} anònim ëd {{SITENAME}}',
'siteuser' => '$1, utent ëd {{SITENAME}}',
-'anonuser' => '{{SITENAME}} utent anònim $1',
-'lastmodifiedatby' => "Sta pàgina-sì a l'é staita modificà l'ùltima vira al $2, $1 da $3.",
+'anonuser' => "l'utent anònim $1 ëd {{SITENAME}}",
+'lastmodifiedatby' => "Costa pàgina-sì a l'é staita modificà l'ùltima vira a $2, $1 da $3.",
'othercontribs' => 'Basà ant sëj travaj ëd $1.',
'others' => 'àutri',
'siteusers' => '$1, {{PLURAL:$2|utent|utent}} ëd {{SITENAME}}',
'anonusers' => '{{SITENAME}} {{PLURAL:$2|utent|utent}} anònim $1',
-'creditspage' => 'Credit dla pàgina',
-'nocredits' => 'A-i é pa gnun crédit për sta pagina-sì.',
+'creditspage' => 'Paternità dla pàgina',
+'nocredits' => "A-i é gnun-a anformassion d'atribussion disponìbil për costa pàgina.",
# Spam protection
'spamprotectiontitle' => 'Filtror dla rumenta',
'pageinfo-title' => 'Anformassion për "$1"',
'pageinfo-header-basic' => 'Anformassion ëd base',
'pageinfo-header-edits' => 'Modìfiche',
-'pageinfo-header-restrictions' => 'Protession ëd pagina',
-'pageinfo-header-properties' => 'Proprietà ëd pagina',
-'pageinfo-display-title' => 'Visualisa tìtol',
+'pageinfo-header-restrictions' => 'Protession ëd la pàgina',
+'pageinfo-header-properties' => 'Proprietà ëd la pàgina',
+'pageinfo-display-title' => 'Tìtol visualisà',
'pageinfo-default-sort' => "ciav d'ordinament për sòlit",
-'pageinfo-length' => 'Lunghëssa ëd pagina (an byte)',
+'pageinfo-length' => 'Longheur ëd la pàgina (an byte)',
'pageinfo-article-id' => 'Identificativ ëd la pàgina',
'pageinfo-robot-policy' => "Stat dël motor d'arserca",
-'pageinfo-robot-index' => 'Andicisàbil',
-'pageinfo-robot-noindex' => 'Pa andicisàbil',
+'pageinfo-robot-index' => 'Indesàbil',
+'pageinfo-robot-noindex' => 'Nen indesàbil',
'pageinfo-views' => 'Nùmer ëd vìsite',
'pageinfo-watchers' => "Vàire ch'a ten-o sot-euj la pàgina",
-'pageinfo-redirects-name' => 'Rediression a sta pagina-sì',
-'pageinfo-subpages-name' => 'Sotpagine dë sta pagina',
-'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|rediression|rediression}}; $3 {{PLURAL:$3|non-rediression|non-rediression}})',
-'pageinfo-firstuser' => 'Creator ëd la pagina',
-'pageinfo-firsttime' => 'Data ëd creassion ëd la pagina',
-'pageinfo-lastuser' => 'Ultim editor',
+'pageinfo-redirects-name' => 'Ridiression a sta pàgina-sì',
+'pageinfo-subpages-name' => 'Sot-pàgine ëd costa pàgina',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|ridiression|ridiression}}; $3 {{PLURAL:$3|nen ridiression|nen ridiression}})',
+'pageinfo-firstuser' => 'Creator ëd la pàgina',
+'pageinfo-firsttime' => 'Data ëd creassion ëd la pàgina',
+'pageinfo-lastuser' => 'Ùltim contributor',
'pageinfo-lasttime' => "Data ëd l'ùltima modìfica",
'pageinfo-edits' => 'Nùmer ëd modìfiche',
'pageinfo-authors' => "Nùmer d'autor diferent",
-'pageinfo-recent-edits' => "Nùmer ëd modìfiche recente (an drinta a j'ùltim $1)",
-'pageinfo-recent-authors' => "Nùmer recent d'autor diferent",
-'pageinfo-restriction' => 'Protession ëd pagina (<code>{{lcfirst:$1}}</code>)',
-'pageinfo-magic-words' => '{{PLURAL:$1|Paròla màgic|Paròle màgiche}} ($1)',
+'pageinfo-recent-edits' => "Nùmer ëd modìfiche recente (ant j'ùltim $1)",
+'pageinfo-recent-authors' => "Nùmer d'autor diferent recent",
+'pageinfo-restriction' => 'Protession ëd la pàgina (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Paròla màgica|Paròle màgiche}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Categorìa|Categorìe}} stërmà ($1)',
-'pageinfo-templates' => 'Trascludù {{PLURAL:$1|stamp|stamp}} ($1)',
+'pageinfo-templates' => '{{PLURAL:$1|stamp contnù|stamp contnù}} ($1)',
# Patrolling
'markaspatrolleddiff' => 'Marca coma verificà',
'file-info-size-pages' => "$1 × $2 pontin, dimension ëd l'archivi: $3, sòrt MIME: $4, $5 {{PLURAL:$5|pàgina|pàgine}}",
'file-nohires' => 'Gnun-a risolussion pì bela disponìbil.',
'svg-long-desc' => "archivi an forma SVG, amzure nominaj $1 × $2 pixel, amzura dl'archivi: $3",
-'svg-long-desc-animated' => "Archivi SVG animà, nominalment $1 × $2 pixel, amzura dl'archivi: $3",
+'svg-long-desc-animated' => "Archivi SVG animà, dimension $1 × $2 pontin, amzura dl'archivi: $3",
'show-big-image' => 'Version a amzura pijn-a',
'show-big-image-preview' => 'Amzure dë sta preuva: $1.',
'show-big-image-other' => '{{PLURAL:$2|Àutra arzolussion|Àutre arzolussion}}: $1.',
'file-info-png-looped' => 'an sìrcol',
'file-info-png-repeat' => 'sonà $1 {{PLURAL:$1|vira|vire}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|quàder|quàder}}',
-'file-no-thumb-animation' => "'''Nòta: Për limitassion técniche, le miniadure dë sto archivi a saran pa animà.'''",
+'file-no-thumb-animation' => "'''Nòta: Për dle limitassion técniche, le miniadure ëd s'archivi a saran pa animà.'''",
'file-no-thumb-animation-gif' => "'''Nòta: Për limitassion técniche, le miniadure ëd figure GIF a àuta arzolussion com costa a saran pa animà.'''",
# Special:NewFiles
'mycontris' => 'زما ونډې',
'contribsub2' => 'د $1 لپاره ($2)',
'uctop' => '(سرپاڼه)',
-'month' => 'Ù\84Ù\87 ټاکÙ\84Û\90 Ù\85Ù\8aاشتÛ\90 Ù\86Ù\87 راپدÛ\90Ø®Ù\88ا (اÙ\88 تر دÛ\90 پخواني):',
-'year' => 'له ټاکلي کال نه راپدېخوا (او تر دې پخواني):',
+'month' => 'Ù\84Ù\87 Ù\85Ù\8aاشتÛ\90 د (اÙ\88 پخواني):',
+'year' => 'له کال د (او پخواني):',
'sp-contributions-newbies' => 'د نوو ګڼونونو ونډې ښکاره کول',
'sp-contributions-newbies-sub' => 'د نوو ګڼونونو لپاره',
'uploadnewversion-linktext' => 'Carregar uma nova versão deste ficheiro',
'shared-repo-from' => 'de $1',
'shared-repo' => 'um repositório partilhado',
+'upload-disallowed-here' => 'Infelizmente você não pode substituir essa imagem.',
# File reversion
'filerevert' => 'Reverter $1',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|byte|bytes}}',
'ncategories' => '$1 {{PLURAL:$1|categoria|categorias}}',
+'ninterwikis' => '$1 {{PLURAL:$1|interwiki|interwikis}}',
'nlinks' => '$1 {{PLURAL:$1|link|links}}',
'nmembers' => '$1 {{PLURAL:$1|membro|membros}}',
'nrevisions' => '$1 {{PLURAL:$1|edição|edições}}',
'mostlinkedtemplates' => 'Predefinições com mais afluentes',
'mostcategories' => 'Páginas com mais categorias',
'mostimages' => 'Ficheiros com mais afluentes',
+'mostinterwikis' => 'Páginas com mais interwikis',
'mostrevisions' => 'Páginas com mais revisões',
'prefixindex' => 'Todas as páginas iniciadas por',
'prefixindex-namespace' => 'Todas as páginas com prefixo (domínio $1)',
'tog-editsectiononrightclick' => 'Habilitar edição de seção por clique com o botão direito no título da seção (JavaScript)',
'tog-showtoc' => 'Mostrar Tabela de Conteúdos (para páginas com mais de três cabeçalhos)',
'tog-rememberpassword' => 'Recordar os meus dados neste navegador (por no máximo $1 {{PLURAL:$1|dia|dias}})',
-'tog-watchcreations' => 'Adicionar páginas criadas por mim à minha lista de páginas vigiadas',
+'tog-watchcreations' => 'Adicionar as páginas e arquivos que eu criar às minhas páginas vigiadas',
'tog-watchdefault' => 'Adicionar páginas editadas por mim à minha lista de páginas vigiadas',
'tog-watchmoves' => 'Adicionar páginas movidas por mim à minha lista de páginas vigiadas',
'tog-watchdeletion' => 'Adicionar páginas eliminadas por mim à minha lista de páginas vigiadas',
'youhavenewmessages' => 'Você tem $1 ($2).',
'newmessageslink' => 'novas mensagens',
'newmessagesdifflink' => 'última alteração',
+'youhavenewmessagesfromusers' => 'Você tem $1 de {{PLURAL:$3|outro usuário|outros usuários}} ($2)',
+'youhavenewmessagesmanyusers' => 'Você tem $1 de muitos usuários ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|uma mensagem nova|mensagens novas}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|última alteração|últimas alterações}}',
'youhavenewmessagesmulti' => 'Você tem novas mensagens em $1',
'editsection' => 'editar',
'editold' => 'editar',
'cannotdelete' => 'Não foi possível eliminar a página ou arquivo $1.
É possível que ele já tenha sido eliminado por outra pessoa.',
'cannotdelete-title' => 'Não é possível excluir a página " $1 "',
+'delete-hook-aborted' => 'A eliminação foi cancelada por um "hook".
+Não foi dada nenhuma explicação.',
'badtitle' => 'Título inválido',
'badtitletext' => 'O título de página solicitado era inválido, vazio, ou um link interlínguas ou interwikis incorreto.
Talvez contenha um ou mais caracteres que não podem ser usados em títulos.',
'remembermypassword' => 'Lembrar meu login neste navegador (por no máximo $1 {{PLURAL:$1|dia|dias}})',
'securelogin-stick-https' => 'Permanecer conectado ao HTTPS após a autenticação',
'yourdomainname' => 'Seu domínio:',
+'password-change-forbidden' => 'Você não pode alterar senhas nessa wiki.',
'externaldberror' => 'Ocorreu ou um erro no banco de dados durante a autenticação ou não lhe é permitido atualizar a sua conta externa.',
'login' => 'Autenticar-se',
'nav-login-createaccount' => 'Entrar / criar conta',
'noarticletext-nopermission' => 'No momento, não há conteúdo nesta página
Você pode [[Special:Search/{{PAGENAME}}|pesquisar pelo título desta página]] em outras páginas,
ou <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar por registros relacionados] </span>.',
+'missing-revision' => 'A revisão #$1 da página denominada "{{PAGENAME}}" não existe.
+
+Isto é geralmente causado por seguir um link de histórico desatualizado para uma página que foi eliminada.
+Os detalhes podem ser encontrados no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminação].',
'userpage-userdoesnotexist' => 'A conta "<nowiki>$1</nowiki>" não se encontra registrada.
Verifique se deseja mesmo criar/editar esta página.',
'userpage-userdoesnotexist-view' => 'A conta de usuário "$1" não está registrada.',
'blocked-notice-logextract' => 'Este usuário está atualmente bloqueado.
O registro de bloqueio mais recente é fornecido abaixo, para referência:',
-'clearyourcache' => "'''Nota:''' Depois de salvar, você terá de limpar o ''cache'' do seu navegador para ver as alterações.
+'clearyourcache' => "Nota:''' Depois de salvar, você terá de limpar o ''cache'' do seu navegador para ver as alterações.
* '''Firefox / Safari:''' pressione ''Shift'' enquanto clica em ''Recarregar'', ou pressione ''Ctrl-F5'' ou ''Ctrl-R'' (''Command-R'' para Mac);
* '''Google Chrome:''' pressione ''Ctrl-Shift-R'' (''Command-Shift-R'' em um Mac)
* '''Internet Explorer:''' pressione ''Ctrl'' enquanto clica em ''Recarregar'' ou pressione ''Ctrl-F5'';
-* '''Konqueror:''' clique no botão ''Recarregar'' ou pressione ''F5'';
* '''Opera:''' limpe o ''cache'' em ''Ferramentas → Preferências'' (''Tools → Preferences'')",
'usercssyoucanpreview' => "'''Dica:''' Utilize o botão \"{{int:showpreview}}\" para testar seu novo CSS antes de salvar.",
'userjsyoucanpreview' => "'''Dica:''' Utilize o botão \"{{int:showpreview}}\" para testar seu novo JavaScript antes de salvar.",
'parser-template-loop-warning' => 'Ciclo de predefinições detectado: [[$1]]',
'parser-template-recursion-depth-warning' => 'O limite de profundidade de recursividade de predefinição foi ultrapassado ($1)',
'language-converter-depth-warning' => 'O limite de profundidade do conversor de línguas excedeu a ($1)',
+'node-count-exceeded-category' => 'Páginas em que o total de nós é excedido',
+'node-count-exceeded-warning' => 'A página excedeu o total de nós',
+'expansion-depth-exceeded-category' => 'Páginas em que a profundidade de expansão é excedida',
+'expansion-depth-exceeded-warning' => 'A página excedeu a profundidade de expansão',
+'parser-unstrip-loop-warning' => 'Foi detectado um ciclo infinito unstrip',
+'parser-unstrip-recursion-limit' => 'Limite de recursão do unstrip excedido ($1)',
+'converter-manual-rule-error' => 'Erro detectado na regra de conversão de língua manual',
# "Undo" feature
'undo-success' => 'A edição pôde ser desfeita. Por gentileza, verifique o comparativo a seguir para se certificar de que é isto que deseja fazer, salvando as alterações após ter terminado de revisá-las.',
'editundo' => 'desfazer',
'diff-multi' => '({{PLURAL:$1|Uma edição intermediária|$1 edições intermediárias}} de {{PLURAL:$2|um usuário|$2 usuários}} {{PLURAL:$1|não apresentada|não apresentadas}})',
'diff-multi-manyusers' => '({{PLURAL:$1|Uma edição intermediária|$1 edições intermediárias}} de mais de {{PLURAL:$2|um usuário|$2 usuário}} não {{PLURAL:$1|apresentada|apresentadas}})',
+'difference-missing-revision' => '{{PLURAL:$2|Uma revisão|$2 revisões}} desta diferença ($1) não {{PLURAL:$2|foi encontrada|foram encontradas}}.
+
+Isto é geralmente causado por seguir um link de histórico desatualizado para uma página que foi eliminada.
+Os detalhes podem ser encontrados no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminação].',
# Search results
'searchresults' => 'Resultados da pesquisa',
'right-writeapi' => 'Uso da API de escrita',
'right-delete' => 'Eliminar páginas',
'right-bigdelete' => 'Eliminar páginas com histórico grande',
+'right-deletelogentry' => 'Eliminar e restaurar entradas específicas de registos',
'right-deleterevision' => 'Eliminar e restaurar revisões específicas de páginas',
'right-deletedhistory' => 'Ver entradas de histórico eliminadas, sem o texto associado',
'right-deletedtext' => 'Ver texto removido e alterado entre revisões removidas',
'backend-fail-internal' => 'Ocorreu um erro desconhecido no servidor de armazenamento "$1".',
'backend-fail-contenttype' => 'Não foi possível determinar o tipo de conteúdo do arquivo para armazenar em "$1".',
'backend-fail-batchsize' => 'O servidor de armazenamento retornou um conjunto de $1 {{PLURAL:$1|operação|operações}} de arquivo, enquanto seu limite é de $2 {{PLURAL:$1|operação|operações}}.',
+'backend-fail-usable' => 'Não foi possível salvar o arquivo $1 devido a permissões insuficientes a diretórios ou repositórios inexistentes.',
# File journal errors
'filejournal-fail-dbconnect' => 'Não foi possível se conectar ao banco de dados de registros do sistema de armazenamento "$1".',
'lockmanager-fail-releaselock' => 'Não foi possível liberar o bloqueio para "$1".',
'lockmanager-fail-db-bucket' => 'Não foi possível contatar suficientemente bloqueio das bases de dados no bucket $1 .',
'lockmanager-fail-db-release' => 'Não foi possível liberar os bloqueios para "$1".',
+'lockmanager-fail-svr-acquire' => 'Não foi possível obter bloqueios no servidor $1.',
'lockmanager-fail-svr-release' => 'Não foi possível liberar os bloqueios do servidor "$1".',
# ZipDirectoryReader
'uploadstash-badtoken' => 'Não foi possível executar essa operação, talvez porque as suas credenciais de edição expiraram. Tente novamente.',
'uploadstash-errclear' => 'Não foi possível apagar os arquivos.',
'uploadstash-refresh' => 'Atualizar a lista de arquivos',
+'invalid-chunk-offset' => 'Deslocamento de fragmento inválido',
# img_auth script messages
'img-auth-accessdenied' => 'Acesso negado',
'uploadnewversion-linktext' => 'Enviar uma nova versão deste arquivo',
'shared-repo-from' => 'de $1',
'shared-repo' => 'um repositório compartilhado',
+'upload-disallowed-here' => 'Infelizmente você não pode substituir essa imagem.',
# File reversion
'filerevert' => 'Reverter $1',
# Info page
'pageinfo-title' => 'Informações sobre "$1"',
-'pageinfo-header-edits' => 'Edições',
+'pageinfo-header-edits' => 'Histórico de edições',
'pageinfo-views' => 'Número de visitas',
'pageinfo-watchers' => 'Número de pessoas vigiando',
'pageinfo-edits' => 'Número de edições',
* <span class="mw-specialpagerestricted">Páginas especiais restritas.</span>',
'specialpages-group-maintenance' => 'Relatórios de manutenção',
'specialpages-group-other' => 'Outras páginas especiais',
-'specialpages-group-login' => 'Entrar / registrar-se',
+'specialpages-group-login' => 'Entrar / Criar conta',
'specialpages-group-changes' => 'Mudanças e registros recentes',
'specialpages-group-media' => 'Relatórios de mídias e uploads',
'specialpages-group-users' => 'Usuários e privilégios',
This link text appears on the recent changes page to users who have the "rollback" right. It is also effectively a submit button; when clicked it performs the rollback without going to a dialog box first.
This message has a tooltip {{msg-mw|tooltip-rollback}}',
'rollbacklinkcount' => 'Text of the rollback link showing the number of edits to be rolled back. This link is also effectively a submit button; when clicked it performs the rollback without going to a dialog box first. See also {{msg-mw|rollbacklink}}.
-* $1: the number of edits that will be rollbacked. If $1 is over the value of $wgShowRollbackEditCount (default: 10) {{msg-mw|rollbacklinkcount-morethan}} is used.',
+* $1: the number of edits that will be rollbacked. If $1 is over the value of $wgShowRollbackEditCount (default: 10) {{msg-mw|rollbacklinkcount-morethan}} is used.
+
+The rollback link is displayed with a tooltip {{msg-mw|Tooltip-rollback}}',
'rollbacklinkcount-morethan' => 'Text of the rollback link when a greater number of edits is to be rolled back. See also {{msg-mw|rollbacklink}}.
When the number of edits rolled back is smaller than [[mw:Manual:$wgShowRollbackEditCount|$wgShowRollbackEditCount]], {{msg-mw|rollbacklinkcount}} is used instead.',
'tooltip-watch' => '{{Identical|Add this page to your watchlist}}',
'tooltip-watchlistedit-normal-submit' => 'Tooltip for {{msg|watchlistedit-normal-submit}} (used as button on [[Special:EditWatchlist]]).',
'tooltip-watchlistedit-raw-submit' => 'Tooltip for {{msg|watchlistedit-raw-submit}} (used as button on [[Special:EditWatchlist/raw]]).',
-'tooltip-rollback' => 'Tooltip of the rollback link on the history page and the diff view {{msg-mw|rollbacklink}}
+'tooltip-rollback' => 'Tooltip of the rollback link on the history page and the diff view {{msg-mw|rollbacklinkcount}}
{{Identical|Rollback}}
{{Identical|Revert}}',
'tooltip-undo' => 'Tooltip of the undo link on the history page and the diff view {{msg-mw|editundo}}
'shared-repo' => "'nu condenitore de cose condivise",
'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
'filepage.css' => "/* 'U CSS ca se iacchie aqquà jè ingluse sus 'a pàgene de descrizione d'u file, pure ingluse pe le client de le Uicchi furastire */",
+'upload-disallowed-here' => "Sfortunatamende non ge puè sovrascrivere st'immaggine.",
# File reversion
'filerevert' => "'Nvirte $1",
'pageinfo-title' => '\'Mbormaziune pe "$1"',
'pageinfo-header-basic' => "'Mbormaziune 'nderra-'nderre",
'pageinfo-header-edits' => 'Cunde de le cangiaminde',
+'pageinfo-header-restrictions' => "Protezione d'a pàgene",
'pageinfo-header-properties' => "Probbietà d'a pàgene",
'pageinfo-display-title' => "Fà vedè 'u titole",
+'pageinfo-default-sort' => 'Chiave de ordenamende de base',
+'pageinfo-length' => "Lunghezze d'a pàgene (in byte)",
'pageinfo-article-id' => "ID d'a pàgene",
'pageinfo-robot-policy' => "State d'u motore de ricerche",
'pageinfo-robot-index' => 'Indicizzabbele',
'pageinfo-lasttime' => "Darte de l'urteme cangiamende",
'pageinfo-edits' => 'Numere totale de cangiaminde',
'pageinfo-authors' => 'Numere Totale de autore diverse',
+'pageinfo-recent-edits' => "Numere de le urteme cangiaminde ('mbonde a $1)",
+'pageinfo-recent-authors' => 'Numere de le urteme autore diverse',
'pageinfo-magic-words' => '{{PLURAL:$1|Parole|Parole}} maggiche ($1)',
# Skin names
'file-info-size-pages' => "$1 × $2 pixel, dimenzione d'u file: $3, tipe de MIME: $4, $5 {{PLURAL:$5|pàgene|pàggene}}",
'file-nohires' => "Manghe 'a risoluzione ierta.",
'svg-long-desc' => "Fail SVG, nominalmende sonde $1 × $2 pixel, dimenzione d'u fail: $3",
+'svg-long-desc-animated' => "File SVG animate, nominalmende sonde $1 × $2 pixel, dimenzione d'u file: $3",
'show-big-image' => 'Risoluzione chiena chiena',
'show-big-image-preview' => 'Dimenziune de sta andeprime: $1.',
'show-big-image-other' => 'Otre {{PLURAL:$2|resoluzione|resoluziune}}: $1.',
$messages = array(
# User preference toggles
-'tog-underline' => 'Підчарковати одказы:',
+'tog-underline' => 'Підкреслёвати одказы:',
'tog-justify' => 'Зарівнати текст до блоку',
'tog-hideminor' => 'Сховати малы едітованя в списку послїднїх змін',
'tog-hidepatrolled' => 'Сховати патролёваны едітованя в списку послїднїх змін',
'tog-enotifminoredits' => 'Послати електронічну пошту і про меншы едітованя сторінок і файлів',
'tog-enotifrevealaddr' => 'Прозрадити мою поштову адресу в поштї увідомлїня',
'tog-shownumberswatching' => 'Вказати кілько хоснователїв придало сторінку до свого списку слїдованых',
-'tog-oldsig' => 'Ð\95кзÑ\96Ñ\81Ñ\82уючій підпис:',
+'tog-oldsig' => 'Ð\86Ñ\81нуючій підпис:',
'tog-fancysig' => 'Хосновати про підпис вікітекст (без автоматічного одказу)',
'tog-externaleditor' => 'Імпліцітно хосновати екстерный едітор (лем про скусеных, выжадує шпеціалне наштелёваня компютера; [//www.mediawiki.org/wiki/Manual:External_editors далшы інформації])',
'tog-externaldiff' => 'Імпліцітно хосновати проґрам про порівнаваня (лем про скусеных, выжадує шпеціалне наштелёваня компютера; [//www.mediawiki.org/wiki/Manual:External_editors далшы інформації])',
'tog-watchlisthideown' => 'Сховати мої едітованя на списку слїдованых сторінок',
'tog-watchlisthidebots' => 'Сховати едітованя ботів у списку слїдованых сторінок',
'tog-watchlisthideminor' => 'Сховати малы едітованя зо списку слїдованых сторінок',
-'tog-watchlisthideliu' => 'У Ñ\81пиÑ\81кÑ\83 Ñ\81лÑ\97дованÑ\8bÑ\85 Ñ\81Ñ\82оÑ\80Ñ\96нок Ñ\81Ñ\85оваÑ\82и едÑ\96Ñ\82аÑ\86Ñ\96Ñ\97 приголошеных хоснователїв',
-'tog-watchlisthideanons' => 'У Ñ\81пиÑ\81кÑ\83 Ñ\81лÑ\97дованÑ\8bÑ\85 Ñ\81Ñ\82оÑ\80Ñ\96нок Ñ\81Ñ\85оваÑ\82и едÑ\96Ñ\82аÑ\86Ñ\96Ñ\97 анонімів',
-'tog-watchlisthidepatrolled' => 'СÑ\85оваÑ\82и паÑ\82Ñ\80олÑ\91ванÑ\8b едÑ\96Ñ\82аÑ\86Ñ\96Ñ\97 Ñ\83 слїдованых сторінках',
-'tog-ccmeonemails' => 'Ð\9fоÑ\81Ñ\8bлаÑ\82и мÑ\96 копÑ\96Ñ\97 поÑ\88Ñ\82Ñ\8b, коÑ\82Ñ\80Ñ\83 поÑ\88лÑ\8e іншым хоснователям',
+'tog-watchlisthideliu' => 'Ð\92 Ñ\81пиÑ\81кÑ\83 Ñ\81лÑ\97дованÑ\8bÑ\85 Ñ\81Ñ\82оÑ\80Ñ\96нок Ñ\81Ñ\85оваÑ\82и едÑ\96Ñ\82ованÑ\8f приголошеных хоснователїв',
+'tog-watchlisthideanons' => 'Ð\92 Ñ\81пиÑ\81кÑ\83 Ñ\81лÑ\97дованÑ\8bÑ\85 Ñ\81Ñ\82оÑ\80Ñ\96нок Ñ\81Ñ\85оваÑ\82и едÑ\96Ñ\82ованÑ\8f анонімів',
+'tog-watchlisthidepatrolled' => 'СÑ\85оваÑ\82и паÑ\82Ñ\80олÑ\91ванÑ\8b едÑ\96Ñ\82ованÑ\8f в слїдованых сторінках',
+'tog-ccmeonemails' => 'Ð\9fоÑ\81Ñ\8bлаÑ\82и мÑ\96 копÑ\96Ñ\97 поÑ\88Ñ\82Ñ\8b, коÑ\82Ñ\80Ñ\83 заженÑ\83 іншым хоснователям',
'tog-diffonly' => 'Не вказовати обсяг сторінкы під роздїлом верзій',
'tog-showhiddencats' => 'Вказати схованы катеґорії',
'tog-norollbackdiff' => 'По вернутю зміны не вказовати порівнаня роздїлів',
'category_header' => 'Сторінкы в катеґорії «$1»',
'subcategories' => 'Підкатеґорії',
'category-media-header' => 'Файлы в катеґорії «$1»',
-'category-empty' => "''ТоÑ\82а катеґорія порожня.''",
+'category-empty' => "''Ð\93евÑ\81Ñ\8f катеґорія порожня.''",
'hidden-categories' => '{{PLURAL:$1|Скрыта катеґорія|Скрыты катеґорії}}',
'hidden-category-category' => 'Схованы катеґорії',
'category-subcat-count' => '{{PLURAL:$2|Тота катеґорія має лем таку підкатеґорію.|{{PLURAL:$1|Указана $1 підкатеґорія|Указаны $1 підкатеґорії|Указаных $1 підкатеґорій}} із $2.}}',
'listingcontinuesabbrev' => '(дале)',
'index-category' => 'Індексованы сторінкы',
'noindex-category' => 'Неіндексованы сторінкы',
-'broken-file-category' => 'Сторінкы, што ся одказують на неекзістуючі файлы',
+'broken-file-category' => 'Сторінкы, што ся одказують на неіснуючі файлы',
'about' => 'О',
'article' => 'Обсягова сторінка',
'searcharticle' => 'Перейти',
'history' => 'Історія сторінкы',
'history_short' => 'Історія',
-'updatedmarker' => 'змÑ\96нено од поÑ\81лÑ\97днÑ\8bй навщівы',
+'updatedmarker' => 'обновлено од поÑ\81лÑ\97днÑ\91й навщівы',
'printableversion' => 'Верзія до друку',
'permalink' => 'Перманентный одказ',
'print' => 'Друк',
'jumpto' => 'Перейти до:',
'jumptonavigation' => 'навіґація',
'jumptosearch' => 'Найти',
-'view-pool-error' => 'Перебачте, серверы суть теперь перетяжены.
-Тоту сторінку сі теперь перезерать много хоснователїв.
+'view-pool-error' => 'Перебачте, серверы суть теперь переладованы.
+Тоту сторінку сі теперь пoзерать много хоснователїв.
Просиме Вас, почекайте і спробуйте доступность пізнїше.
$1',
'badaccess' => 'Брак прав приступу',
'badaccess-group0' => 'Вам не є дозволено выконавати тоту дїю.',
-'badaccess-groups' => 'Дїя, яку сьте хотїли зробити, дозволена лем хоснователям із {{PLURAL:$2|ґрупы|ґруп}}: $1.',
+'badaccess-groups' => 'Дїя, яку сьте хотїли зробити, дозволена лем хоснователям з {{PLURAL:$2|ґрупы|ґруп}}: $1.',
'versionrequired' => 'Потрібна MediaWiki верзії $1',
'versionrequiredtext' => 'Про роботу з тов сторінков потрібна MediaWiki верзії $1. Відь [[Special:Version|сторінку верзії]].',
'dberrortext' => 'Найджена сінтактічна хыба в запросї до датабазы.
Тото може вказовати на хыбу в проґрамовім забеспечіню.
Послїднїй запрос до датабазы:
-<blockquote><tt>$1</tt></blockquote>
-з функції "<tt>$2</tt>".
-Датабаза вернула хыбу "<tt>$3: $4</tt>".',
+<blockquote><code>$1</code></blockquote>
+з функції "<code>$2</code>".
+Датабаза вернула хыбу "<samp>$3: $4</samp>".',
'dberrortextcl' => 'Найджена сінтактічна хыба в запросї до датабазы.
Послїднїй запрос до датабазы:
«$1»
'filecopyerror' => 'Не было можне копіровати файл «$1» на «$2».',
'filerenameerror' => 'Не было можне переменовати файл «$1» на «$2».',
'filedeleteerror' => 'Не было можне змазаты файл «$1».',
-'directorycreateerror' => 'Не є можне вытворити адресарь «$1».',
+'directorycreateerror' => 'Не мож вытворити адресарь «$1».',
'filenotfound' => 'Не было можне найти файл «$1».',
'fileexistserror' => 'Не дасть ся записати до файлу «$1»: файл екзістує.',
'unexpected' => 'Неочекавана годнота: «$1»=«$2».',
'viewsource' => 'Видїти код',
'viewsource-title' => 'Видїти жрідло сторінкы $1',
'actionthrottled' => 'Акція была придушена',
-'actionthrottledtext' => 'Ð\92зглÑ\8fдом кÑ\83 пÑ\80оÑ\82иÑ\81памовÑ\8bм опаÑ\82Ñ\80Ñ\97нÑ\8fм не можете жадану акцію провести барз часто в короткім часї. Спробуйте то знову о пару мінут.',
+'actionthrottledtext' => 'Ð\92зглÑ\8fдом кÑ\83 пÑ\80оÑ\82иÑ\81памовÑ\8bм кÑ\80окам не можете жадану акцію провести барз часто в короткім часї. Спробуйте то знову о пару мінут.',
'protectedpagetext' => 'Тота сторінка была замкнута, также ся не дасть едітовати',
'viewsourcetext' => 'Можете видїти і копіровати код той сторінкы:',
'viewyourtext' => "Можете собі посмотрити і скопіровати жрідловый текст '''вашых змін''' той сторінкы:",
'previewconflict' => 'Тот нагляд зображує текст так, як буде вызерати по уложіню сторінкы.',
'session_fail_preview' => "'''Вашу пожадавку ся не удало спрацовати, бо были страчены дата сеансу.
Просиме, спробуйте то зясь.
-Ð\9aÑ\96дÑ\8c Ñ\81Ñ\8f Ñ\82оÑ\82 пÑ\80облем бÑ\83де опаковати, спробуйте ся [[Special:UserLogout|одголосити]] і знову приголосити до сістемы.'''",
+Ð\9aÑ\96дÑ\8c Ñ\81Ñ\8f Ñ\82оÑ\82 пÑ\80облем бÑ\83де повÑ\82оÑ\80ити, спробуйте ся [[Special:UserLogout|одголосити]] і знову приголосити до сістемы.'''",
'session_fail_preview_html' => "'''Вашу пожадавку ся не удало спрацовати, бо были страчены дата сеансу..'''
''Зато же {{SITENAME}} має запнуте хоснованя чістого HTML, нагляд ся про превенцію проти атакам JavaScript-ом не зображує.''
'editingcomment' => 'Едітованя $1 (нова секція)',
'editconflict' => 'Конфлікт едітованя: $1',
'explainconflict' => "Дахто змінив сторінку по започатю вашой едітації.
-Выше видите актуалный текст сторінкы.
+Ð\92Ñ\8bÑ\81Ñ\88е видиÑ\82е акÑ\82Ñ\83алнÑ\8bй Ñ\82екÑ\81Ñ\82 Ñ\81Ñ\82оÑ\80Ñ\96нкÑ\8b.
Вашы зміны суть вказаны долов.
-Ð\9cÑ\83Ñ\81иÑ\82е злÑ\83Ñ\87Ñ\96Ñ\82и Ñ\81воÑ\97 змÑ\96нÑ\8b з Ñ\94Ñ\81Ñ\82вуючім текстом.
-'''Ð\9bем''' вÑ\8bÑ\88е вказанÑ\8bй Ñ\82екÑ\81Ñ\82 зÑ\96Ñ\81Ñ\82ане Ñ\83Ñ\85ованый по кликнутю на „{{int:savearticle}}“.",
+Ð\9cÑ\83Ñ\81иÑ\82е злÑ\83Ñ\87Ñ\96Ñ\82и Ñ\81воÑ\97 змÑ\96нÑ\8b з Ñ\96Ñ\81нуючім текстом.
+'''Ð\9bем''' вÑ\8bÑ\81Ñ\88е вказанÑ\8bй Ñ\82екÑ\81Ñ\82 зÑ\96Ñ\81Ñ\82ане вÑ\81окоÑ\87еный по кликнутю на „{{int:savearticle}}“.",
'yourtext' => 'Ваш текст',
'storedversion' => 'Уложена верзія',
'nonunicodebrowser' => "'''Увага: Ваш переглядач не є способный працовати із знаками Unicode. Абы сьте могли тоту сторінку беспечно едітовати: вшыткы знакы мімо ASCII суть зображены в гексадецімалных кодах.'''",
'nocreate-loggedin' => 'Не маєте права створёвати новы сторінкы.',
'sectioneditnotsupported-title' => 'Едітованя секцій не є підпороване',
'sectioneditnotsupported-text' => 'На тій сторінцї не є підпороване едітованя єдной секції.',
-'permissionserrors' => 'Ð¥Ñ\8bба опÑ\80авнÑ\97нÑ\8f',
+'permissionserrors' => 'Ð¥Ñ\8bба пÑ\80ав',
'permissionserrorstext' => 'Не маєте поволїня той операції з {{PLURAL:$1|такой причіны|такых причін}}:',
'permissionserrorstext-withaction' => 'Не маєте дозволїня на $2 з {{PLURAL:$1|такой прічіны|такых прічін}}:',
'recreate-moveddeleted-warn' => "'''Увага: Пробуєте знову створити сторінку, котра была в минулости змазана.'''
Асі была змазана.',
'edit-conflict' => 'Конфлікт едітованя.',
'edit-no-change' => 'Ваша едітація была іґнорована, бо ся не зробила жадна зміна тексту.',
-'edit-already-exists' => 'Не вдало ся створити нову сторінку, бо она уж екзістує.',
+'edit-already-exists' => 'Не вдало ся створити нову сторінку, бо она уж існує.',
'defaultmessagetext' => 'Преднаставленый текст повідомлїня',
# Parser/template warnings
'converter-manual-rule-error' => 'Найджена хыба в ручнім правилї конверзії языка',
# "Undo" feature
-'undo-success' => 'Ð\95дÑ\96Ñ\82ованÑ\8f може бÑ\8bÑ\82и зÑ\80Ñ\83Ñ\87ене.
-Просиме Вас перевірте порівнаня ниже, жебы сьте ся упевнили в тім, што хочете зробити а потім уложте зміны долов, жебы сьте закінчіли зрушіня едітованя.',
+'undo-success' => 'Ð\95дÑ\96Ñ\82ованÑ\8f може бÑ\8bÑ\82и зÑ\80Ñ\83Ñ\88ене.
+Ð\9fÑ\80оÑ\81име Ð\92аÑ\81 пеÑ\80евÑ\96Ñ\80Ñ\8cÑ\82е поÑ\80Ñ\96внанÑ\8f ниже, жебÑ\8b Ñ\81Ñ\8cÑ\82е Ñ\81Ñ\8f Ñ\83певнили в Ñ\82Ñ\96м, Ñ\88Ñ\82о Ñ\85оÑ\87еÑ\82е зÑ\80обиÑ\82и а поÑ\82Ñ\96м Ñ\83ложÑ\82е змÑ\96нÑ\8b долов, жебÑ\8b Ñ\81Ñ\8cÑ\82е закÑ\96нÑ\87Ñ\96ли зÑ\80Ñ\83Ñ\88Ñ\96нÑ\8f едÑ\96Ñ\82ованÑ\8f.',
'undo-failure' => 'Едітованя не могло быти зрушене про конфлікт міджілеглых змін.',
'undo-norev' => 'Тото едітованя не можете вернути назад, бо не екзістує або было змазане.',
'undo-summary' => 'Зрушена верзія $1 од хоснователя [[Special:Contributions/$2|$2]] ([[User talk:$2|діскузія]])',
'history-feed-title' => 'Історія едітовань',
'history-feed-description' => 'Історія едітовань той сторінкы на вікі',
'history-feed-item-nocomment' => '$1 в $2',
-'history-feed-empty' => 'Такой сторінкы не екзістує.
+'history-feed-empty' => 'Такой сторінкы нїт.
Могли єй вымазати ці переменовати.
-СпÑ\80обÑ\83йÑ\82е [[Special:Search|найÑ\82и во вікі]] подобны сторінкы.',
+СпÑ\80обÑ\83йÑ\82е [[Special:Search|найÑ\82и на вікі]] подобны сторінкы.',
# Revision deletion
'rev-deleted-comment' => '(згорнутя едітованя вымазане)',
-'rev-deleted-user' => '(мено автора стерто)',
+'rev-deleted-user' => '(імя автора стерто)',
'rev-deleted-event' => '(лоґ одстраненый)',
'rev-deleted-user-contribs' => '[мено хоснователя або IP адреса одстранене – едітованя є в приспевках сховане]',
-'rev-deleted-text-permission' => "ТоÑ\82а Ñ\80евÑ\96зÑ\96Ñ\8f бÑ\8bла '''змазана'''.
-Ð\94еÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 змазаных сторінок].",
-'rev-deleted-text-unhide' => "ТоÑ\82а Ñ\80евÑ\96зÑ\96Ñ\8f бÑ\8bла '''змазана'''.
-Ð\94еÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 змазаных сторінок].
+'rev-deleted-text-permission' => "ТоÑ\82а Ñ\80евÑ\96зÑ\96Ñ\8f бÑ\8bла '''вÑ\8bлÑ\83Ñ\87ена''.
+Ð\94еÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 вÑ\8bлÑ\83Ñ\87еных сторінок].",
+'rev-deleted-text-unhide' => "ТоÑ\82а Ñ\80евÑ\96зÑ\96Ñ\8f бÑ\8bла '''вÑ\8bлÑ\83Ñ\87ена'''.
+Ð\94еÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 вÑ\8bлÑ\83Ñ\87еных сторінок].
Можете сі все [$1 тоту ревізію посмотрити], кідь хочете.",
'rev-suppressed-text-unhide' => "Тота ревізія была '''затаєна'''.
Детайлы можуть быти уведены в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} записї утаїня].
Можете сі [$1 тоту ревізію посмотрити], кідь хочете.",
-'rev-deleted-text-view' => "ТоÑ\82а Ñ\80евÑ\96зÑ\96Ñ\8f бÑ\8bла '''змазана'''.
-Ð\9cожеÑ\82е Ñ\81Ñ\96 Ñ\94й поÑ\81моÑ\82Ñ\80иÑ\82и; деÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 змазаных сторінок].",
+'rev-deleted-text-view' => "ТоÑ\82а Ñ\80евÑ\96зÑ\96Ñ\8f бÑ\8bла '''вÑ\8bлÑ\83Ñ\87ена'''.
+Ð\9cожеÑ\82е Ñ\81Ñ\96 Ñ\94й поÑ\81моÑ\82Ñ\80иÑ\82и; деÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 вÑ\8bлÑ\83Ñ\87еных сторінок].",
'rev-suppressed-text-view' => "Тота верзія была '''затаєна'''.
Можете сі єй посмотрити; детайлы можуть быти зазначены в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} записї затаїня].",
'rev-deleted-no-diff' => "Тот розділ сі не можете помострити, бо єдна з ревізій была '''змазана'''.
Детайлы можуть быти зазначены в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзї змазаных сторінок].",
'rev-suppressed-no-diff' => "Тот роздїл сі не можете посмотрити, бо єдна з ревізій была '''змазана'''.",
-'rev-deleted-unhide-diff' => "Ð\84дна з Ñ\80евÑ\96зÑ\96й пÑ\80о Ñ\82оÑ\82о поÑ\80Ñ\96внанÑ\8f бÑ\8bла '''змазана'''.
+'rev-deleted-unhide-diff' => "Ð\84дна з Ñ\80евÑ\96зÑ\96й пÑ\80о Ñ\82оÑ\82о поÑ\80Ñ\96внанÑ\8f бÑ\8bла '''вÑ\8bлÑ\83Ñ\87ена'''.
Можете сі але [$1 тоту ревізію посмотрити], кідь хочете.",
'rev-suppressed-unhide-diff' => "Єдна з ревізій про тото порівнаня была '''затаєна'''.
Детайлы можуть быти уведены в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} записї утаїня].
Можете сі але [$1 тоту ревізію посмотрити], кідь хочете.",
-'rev-deleted-diff-view' => "Ð\84дна з Ñ\80евÑ\96зÑ\96й пÑ\80о Ñ\82оÑ\82о поÑ\80Ñ\96внанÑ\8f бÑ\8bла '''змазана'''.
-Ð\9cожеÑ\82е Ñ\81Ñ\96 Ñ\94й поÑ\81моÑ\82Ñ\80иÑ\82и; деÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 змазаных сторінок].",
+'rev-deleted-diff-view' => "Ð\84дна з Ñ\80евÑ\96зÑ\96й пÑ\80о Ñ\82оÑ\82о поÑ\80Ñ\96внанÑ\8f бÑ\8bла '''вÑ\8bлÑ\83Ñ\87ена'''.
+Ð\9cожеÑ\82е Ñ\81Ñ\96 Ñ\94й поÑ\81моÑ\82Ñ\80иÑ\82и; деÑ\82айлÑ\8b можÑ\83Ñ\82Ñ\8c бÑ\8bÑ\82и зазнаÑ\87енÑ\8b в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} книзÑ\97 вÑ\8bлÑ\83Ñ\87еных сторінок].",
'rev-suppressed-diff-view' => "Єдна з ревізій про тото порівнаня была '''затаєна'''.
Можете сі єй посмотрити; детайлы можуть быти зазначены в [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} записї затаїня].",
'rev-delundel' => 'вказати/сховати',
'rev-showdeleted' => 'вказати',
-'revisiondelete' => 'Ð\97мазати/обновити ревізії',
+'revisiondelete' => 'Ð\92Ñ\8bлÑ\83Ñ\87Ñ\96ти/обновити ревізії',
'revdelete-nooldid-title' => 'Хыбна цілёва ревізія',
'revdelete-nooldid-text' => 'Не зволили сьте ревізії, на котрых хочете тоту функцію выконати.',
'revdelete-nologtype-title' => 'Нестановленый тіп запису',
'revdelete-nologid-title' => 'Неплатный протоколовачій запис',
'revdelete-nologid-text' => 'Будь сьте не зазначіли цілёвый запис в протоколї або даный запис не екзістує.',
'revdelete-no-file' => 'Зазначеный файл не єствує.',
-'revdelete-show-file-confirm' => 'Ð\9dа певно Ñ\81обÑ\96 Ñ\85оÑ\87еÑ\82е поÑ\81моÑ\82Ñ\80иÑ\82и змазану ревізію файлу „<nowiki>$1</nowiki>“ з $2, $3?',
+'revdelete-show-file-confirm' => 'Ð\9dа певно Ñ\81обÑ\96 Ñ\85оÑ\87еÑ\82е поÑ\81моÑ\82Ñ\80иÑ\82и вÑ\8bлÑ\83Ñ\87ену ревізію файлу „<nowiki>$1</nowiki>“ з $2, $3?',
'revdelete-show-file-submit' => 'Гей',
'revdelete-selected' => "'''{{PLURAL:$2|Выбрана ревізія|Выбраны ревізії}} з [[:$1]]:'''",
'logdelete-selected' => "'''{{PLURAL:$1|Выбрана протоколована подїя|Выбраны протоколованы подїї}}:'''",
'logdelete-failure' => "'''Не вдало ся наставити видимость протоколу.'''
$1",
'revdel-restore' => 'Змінити видимость',
-'revdel-restore-deleted' => 'вÑ\8bмазаны ревізії',
+'revdel-restore-deleted' => 'вÑ\8bлÑ\83Ñ\87ены ревізії',
'revdel-restore-visible' => 'видительны ревізії',
'pagehist' => 'Історія сторінкы',
'deletedhist' => 'Вымазана історія',
'mergehistory-header' => 'Тота сторінка Вам дозволить злучіти історію єдной жрідловой сторінкы з новшов сторінков.
Пересвіджте ся, же тота зміна утриме повязаность і поступность історії сторінкы.',
'mergehistory-box' => 'Злучіти ревізії двох сторінок:',
-'mergehistory-from' => 'Ð\97дÑ\80оÑ\91ва сторінка:',
+'mergehistory-from' => 'Ð\96Ñ\80Ñ\96длова сторінка:',
'mergehistory-into' => 'Цілёва сторінка:',
'mergehistory-list' => 'Історія злучітельных сторінок',
'mergehistory-merge' => 'Наслїдуючі верзії сторінкы [[:$1|$1]] можуть быти злучены в [[:$2]]. Перепиначом выберте верзію, котра урчіть, же лем тота і старшы едітації будуть злучены. Рахуйте з тым, же хоснованём навіґачных одказів будуть дата страчены.',
'mergehistory-empty' => 'Не дають ся споїти жадны ревізії.',
'mergehistory-success' => '$3 {{PLURAL:$3|ревізія|ревізії|ревізійí}} сторінкы [[:$1]] {{PLURAL:$3|была успішно злучена|были успішно злучены|было успішно злуґено}} до сторінкы [[:$2]].',
'mergehistory-fail' => 'Злучіня історій ся не дасть зробити. Перевірте заданы сторінкы і їх історії',
-'mergehistory-no-source' => 'Ð\97дÑ\80оÑ\91ва Ñ\81Ñ\82оÑ\80Ñ\96нка $1 не екзÑ\96Ñ\81Ñ\82ує.',
+'mergehistory-no-source' => 'Ð\96Ñ\80Ñ\96длова Ñ\81Ñ\82оÑ\80Ñ\96нка $1 не Ñ\96Ñ\81нує.',
'mergehistory-no-destination' => 'Цілёва сторінка «$1» не екзістує.',
-'mergehistory-invalid-source' => 'Ð\97дÑ\80ойова сторінка мусить мати правилну назву.',
+'mergehistory-invalid-source' => 'Ð\96Ñ\80Ñ\96длова сторінка мусить мати правилну назву.',
'mergehistory-invalid-destination' => 'Цілёва сторінка мусить мати правилну назву.',
'mergehistory-autocomment' => 'Злучена сторінка [[:$1]] до сторінкы [[:$2]]',
'mergehistory-comment' => 'Злучена сторінка [[:$1]] до сторінкы [[:$2]]: $3',
'restriction-level-all' => 'хоцьяка рівень',
# Undelete
-'undelete' => 'Ð\97мазаны сторінкы',
+'undelete' => 'Ð\92Ñ\8bлÑ\83Ñ\87ены сторінкы',
'undeletepage' => 'Посмотрити собі і обновити змазану сторінку',
'undeletepagetitle' => "'''Ниже суть змазаны верзії сторінкы [[:$1]]'''.",
'viewdeletedpage' => 'Зобразити змазаны сторінкы',
'blocklist-addressblocks' => 'Сховати блокованя єдной IP адресы',
'blocklist-rangeblocks' => 'Скрыти блокованя россягів',
'blocklist-timestamp' => 'Часова значка',
-'blocklist-target' => 'ЦÑ\96ль',
+'blocklist-target' => 'ЦÑ\97ль',
'blocklist-expiry' => 'Кінчіть',
'blocklist-by' => 'Блокуючій адмін',
'blocklist-params' => 'Параметры блокованя',
# General errors
'error' => 'दोषः',
'databaseerror' => 'दत्ताधारे दोषः',
-'dberrortext' => 'समंकाधार पृच्छायां वाक्यरचना त्रुटिरेका अभवत्।
+'dberrortext' => 'समंकाधार पृच्छायां वाक्यरचनात्रुटिरेका अभवत्।
अनेन अस्माकं तन्त्रांशे त्रुटिरपि निर्दिष्टा स्यात्।
अन्तिमा चेष्टिता समंकाधार-पृच्छा आसीत्:
-<blockquote><tt>$1</tt></blockquote>
- "<tt>$2</tt>" इत्यस्मात् फलनात्।
-समंकाधारे त्रुटिरासीत्: "<tt>$3: $4</tt>" इति।',
+<blockquote><code>$1</code></blockquote>
+ "<code>$2</code>" इत्यस्मात् फलनात्।
+समंकाधारे त्रुटिरासीत्: "<samp>$3: $4</samp>" इति।',
'dberrortextcl' => 'समंकाधार पृच्छायां वाक्यरचना त्रुटिरेका अभवत्।
अन्तिमा चेष्टिता समंकाधार पृच्छा आसीत् :
"$1"
'userpage-userdoesnotexist-view' => '"$1" इति प्रयोक्तृलेखा पञ्जीकृता नास्ति।',
'blocked-notice-logextract' => 'अयं प्रयोक्ता सम्प्रति अवरुद्धः वर्तते।
नूतनतमा अवरोधाभिलेख-प्रविष्टिः सन्दर्भार्थम् अधस्तात् प्रदत्ताऽस्ति:',
-'clearyourcache' => "'''सूचनाः'''",
+'clearyourcache' => "'''सूचनाः:''' संरक्षणानन्तरं परिवर्तनानां दर्शनाय जालगवेशकस्य पुनर्चालनम् अवश्यं भवेत् ।
+* '''Firefox / Safari:''' गृह्यताम् ''Shift'' नोदनावसरे ''Reload'', अथवा एतयोः अन्यतरं नुद्यताम् ''Ctrl-F5'' अथवा ''Ctrl-R'' (''⌘-R'' on a Mac)
+* '''Google Chrome:''' नुद्यताम् ''Ctrl-Shift-R'' (''⌘-Shift-R'' on a Mac)
+* '''Internet Explorer:''' गृह्यताम् ''Ctrl'' नोदनावसरे ''Refresh'', अथवा नुद्यताम् ''Ctrl-F5''
+* '''Opera:''' पुनर्चाल्यताम् ''Tools → Preferences''",
'usercssyoucanpreview' => "'''सूचना :''' रक्षणात्पूर्वं स्वकीयं जावास्क्रिप्ट् इति लिपिं परीक्षितुं \"{{int:showpreview}}\" इति गण्डं प्रयोजयतु।",
'userjsyoucanpreview' => "'''सूचना :''' रक्षणात्पूर्वं स्वकीयं जावास्क्रिप्ट् इति लिपिं परीक्षितुं \"{{int:showpreview}}\" इति गण्डं प्रयोजयतु।",
'usercsspreview' => "'''मनसि धारयतु यद्भवान् केवलं प्राग्दृश्यं पश्यति स्वकीयस्य प्रयोक्तृ-सीएसएस् इत्येतस्य'''
'uploadnewversion-linktext' => 'अस्य पृष्ठस्य नूतनाम् आवृत्तिं उद्भारयतु',
'shared-repo-from' => '$1 इत्यस्मात् ।',
'shared-repo' => 'विभक्तः कोशः ।',
+'upload-disallowed-here' => 'दुरदृष्टवशात् अस्य चित्रस्य उपरि पुनर्लेखनम् अशक्यम् ।',
# File reversion
'filerevert' => '$1 अनुवर्तताम् ।',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|बैट्|बैट्स्}}',
'ncategories' => '{{PLURAL:$1|वर्गः|वर्गाः }}',
+'ninterwikis' => '$1 {{PLURAL:$1|अन्तार्विकी|अन्तार्विक्यः}}',
'nlinks' => '$1 {{PLURAL:$1|अनुबन्धः|अनुबन्धाः}}',
'nmembers' => '$1 {{PLURAL:$1|सदस्यः|सदस्याः}}',
'nrevisions' => '$1 {{PLURAL:$1|पुनरावृत्तिः}}',
'mostlinkedtemplates' => 'प्राकृतिभिः अत्यनुबद्धाः ।',
'mostcategories' => 'बहुवर्गयुक्तपुटानि ।',
'mostimages' => 'अत्यनुबद्धानि पुटानि ।',
+'mostinterwikis' => 'अधिकान्तार्विकियुक्ताः पृष्ठाः',
'mostrevisions' => 'सर्वाधिकपुनरावृत्तियुक्तानि पुटानि ।',
'prefixindex' => 'उपसर्गयुक्तानि सर्वाणि पृष्ठानि',
'prefixindex-namespace' => 'उपसर्गैः युक्तानि सर्वपुटानि । ($1 नामस्थानम्)',
'mailnologin' => 'सम्प्रेषणस्य सङ्केतः नास्ति ।',
'mailnologintext' => 'अस्य योजकेभ्यः विद्युन्मानपत्रप्रेषणार्थम् [[Special:UserLogin|नामाभिलेखनम्]] आवश्यकम् [[Special:Preferences|आद्यता]]यां प्रेषयितुं विद्युन्मानपत्रसङ्केतः आवश्यकः ।',
'emailuser' => 'एतस्मै योजकाय ईपत्रं प्रेष्यताम्',
+'emailuser-title-target' => 'ईपत्र प्रेष्यताम् {{GENDER:$1|योजकः}}',
+'emailuser-title-notarget' => 'ईपत्र योजकः',
'emailpage' => 'ई-मेल योजक',
'emailpagetext' => 'अस्मै योजकाय विद्युन्मानपत्रं प्रेषयितुम् अधो दत्तप्रपत्रम् उपयोक्तुं शक्नोति ।
[[Special:Preferences|your user preferences]] अत्र भवता विनिवेशितः वि-पत्रसङ्केतः सकाशात् इति स्थाने प्रतिभाति । अनेन स्वीकर्ता साक्षात् प्रत्युत्तरं दातुं प्रभविष्यति ।',
# Info page
'pageinfo-title' => '"$1" कृते सूचनाः ।',
-'pageinfo-header-edits' => 'सम्पादयति',
+'pageinfo-header-basic' => 'मूलसूचनाः ।',
+'pageinfo-header-edits' => 'इतिहासः सम्पाद्यताम्',
+'pageinfo-header-restrictions' => 'पृष्ठसंरक्षणम्',
+'pageinfo-header-properties' => 'पृष्ठस्य गुणधर्मः',
+'pageinfo-display-title' => 'शीर्षकं दर्श्यताम्',
+'pageinfo-default-sort' => 'संविभागकीलकं पूर्वनिर्दिष्टं क्रियताम्',
+'pageinfo-length' => 'पृष्ठदैर्घ्यम् (बैट्स्द्वारा)',
+'pageinfo-article-id' => 'पृष्ठाभिज्ञापकम्',
+'pageinfo-robot-policy' => 'चालकयन्त्रस्थितिः अन्विष्यताम्',
+'pageinfo-robot-index' => 'अङ्कनयोग्यम्',
+'pageinfo-robot-noindex' => 'अङ्कनायोग्यम्',
'pageinfo-views' => 'अवलोकनानां सङ्ख्या ।',
-'pageinfo-watchers' => 'अवलोकनानां सङ्ख्या ।',
-'pageinfo-edits' => 'सम्पादननां सङ्ख्या ।',
-'pageinfo-authors' => 'स्पष्टानां कर्तॄणां सङ्ख्या ।',
+'pageinfo-watchers' => 'पृष्ठावलोककानां सङ्ख्या ।',
+'pageinfo-redirects-name' => 'एतत् पृष्ठं प्रति पुनर्निर्दिश्यते',
+'pageinfo-subpages-name' => 'अस्य पृष्ठस्य उपपृष्ठानि',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|पुनर्निर्देशः|पुनर्निर्देशाः}}; $3 {{PLURAL:$3|न पुनर्निर्देशः|न-पुनर्निर्देशाः}})',
+'pageinfo-firstuser' => 'पृष्ठनिर्माता',
+'pageinfo-firsttime' => 'पृष्ठनिर्माणस्य दिनम्',
+'pageinfo-lastuser' => 'अन्तिमः सम्पादकः',
+'pageinfo-lasttime' => 'अन्तिमसम्पादनस्य दिनाङ्कः',
+'pageinfo-edits' => 'समग्रसम्पादनानां सङ्ख्या ।',
+'pageinfo-authors' => 'प्रत्येककर्तॄणां समग्रा सङ्ख्या ।',
+'pageinfo-recent-edits' => 'सद्योजातसम्पादनानां सङ्ख्या (गतेषु $1 दिनेषु)',
+'pageinfo-recent-authors' => 'प्रत्येककर्तॄणां सद्यःकालीना सङ्ख्या ।',
+'pageinfo-restriction' => 'पृष्ठसंरक्षणम् (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => 'मान्त्रिक{{PLURAL:$1|शब्दः|शब्दाः}} ($1)',
+'pageinfo-hidden-categories' => 'गोपित{{PLURAL:$1|वर्गः|वर्गाः}} ($1)',
+'pageinfo-templates' => 'समायोजित{{PLURAL:$1|फलकम्|फलकानि}} ($1)',
# Skin names
'skinname-standard' => 'पूर्व',
'file-info-size-pages' => '$1 × $2 पिक्सेल्, सञ्चिकायाः आकारः : $3 , MIME प्रकारः : $4 , $5 {{PLURAL:$5|पुटम्|पुटानि}}',
'file-nohires' => 'उच्चतरं विभेदनं नोपलब्धम्',
'svg-long-desc' => 'SVG संचिका, साधारणतया $1 × $2 पिक्सेलानि, संचिकायाः आकारः : $3',
+'svg-long-desc-animated' => 'आश्वसिता SVG संचिका, साधारणतया $1 × $2 पिक्सेलानि, संचिकायाः आकारः : $3',
'show-big-image' => 'पूर्णं विभेदनम्',
'show-big-image-preview' => 'अस्य पूर्वावलोकनस्य आकारः : $1',
'show-big-image-other' => 'अन्याः {{PLURAL:$2| प्रस्तवः|प्रस्तावाः}}: $1 ।',
'file-info-png-looped' => 'चक्रितम्',
'file-info-png-repeat' => 'विलसितम् $1 {{PLURAL:$1|समयः|समयाः}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|पृष्ठम्|पृष्ठानि}}',
+'file-no-thumb-animation' => "'''सूचना: तान्त्रिकपरिमितेः कारणतः अस्याः सञ्चिकायाः लघ्वाकृतिः आश्वसितुम् अशक्या ।'''",
+'file-no-thumb-animation-gif' => "'''सूचना: तान्त्रिकपरिमितेः कारणतः अस्याः सञ्चिकासदृशस्य अधिकप्रगल्भतायुक्तस्य GIF चित्रस्य लघ्वाकृतिः आश्वसितुम् अशक्या ।'''",
# Special:NewFiles
'newimages' => 'नूतन-संचिकानां वीथिका',
'retrievedfrom' => 'Преузето из „$1“',
'youhavenewmessages' => 'Имате $1 ($2).',
'newmessageslink' => 'нових порука',
-'newmessagesdifflink' => 'последњу измену',
+'newmessagesdifflink' => 'последња измена',
'youhavenewmessagesfromusers' => 'Имате $1 од {{PLURAL:$3|другог корисника|$3 корисника|$3 корисника}} ($2).',
'youhavenewmessagesmanyusers' => 'Имате $1 од много корисника ($2).',
'newmessageslinkplural' => '{{PLURAL:$1|нову поруку|нове поруке}}',
'pageinfo-header-properties' => 'Својства странице',
'pageinfo-display-title' => 'Наслов за приказ',
'pageinfo-default-sort' => 'Подразумевани кључ сортирања',
+'pageinfo-length' => 'Дужина странице (у бајтовима)',
+'pageinfo-article-id' => 'ИД странице',
+'pageinfo-robot-policy' => 'Статус претраживача',
+'pageinfo-robot-index' => 'Може да се попише',
+'pageinfo-robot-noindex' => 'Не може да се попише',
'pageinfo-views' => 'Број прегледа',
'pageinfo-watchers' => 'Број надгледача страница',
+'pageinfo-redirects-name' => 'Преусмеравања на страницу',
+'pageinfo-subpages-name' => 'Подстранице ове странице',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|преусмерење|преусмерења|преусмерења}}; $3 {{PLURAL:$3|непреусмерење|непреусмерења|непреусмерења}})',
+'pageinfo-firstuser' => 'Аутор странице',
+'pageinfo-firsttime' => 'Датум стварања странице',
+'pageinfo-lastuser' => 'Последњи уредник',
+'pageinfo-lasttime' => 'Датум последње измене',
'pageinfo-edits' => 'Број измена',
'pageinfo-authors' => 'Број засебних аутора',
+'pageinfo-recent-edits' => 'Број скорашњих измена (у последњих $1)',
+'pageinfo-recent-authors' => 'Број скорашњих засебних аутора',
+'pageinfo-restriction' => 'Заштита странице (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Магична реч|Магичне речи}} ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Сакривена категорија|Сакривене категорије}} ($1)',
+'pageinfo-templates' => '{{PLURAL:$1|Укључени шаблон|Укључени шаблони}} ($1)',
# Skin names
'skinname-standard' => 'Класично',
'file-info-size-pages' => '$1 × $2 пиксела, величина: $3, MIME врста: $4, $5 {{PLURAL:$5|страница|странице|страница}}',
'file-nohires' => 'Већа резолуција није доступна.',
'svg-long-desc' => 'SVG датотека, номинално $1 × $2 пиксела, величина: $3',
+'svg-long-desc-animated' => 'Анимирана SVG датотека, номинално: $1 × $2 пиксела, величина: $3',
'show-big-image' => 'Пуна величина',
'show-big-image-preview' => 'Величина овог приказа: $1.',
'show-big-image-other' => '{{PLURAL:$2|Друга резолуција|Друге резолуције}}: $1.',
'file-info-png-looped' => 'петља',
'file-info-png-repeat' => 'поновљено $1 {{PLURAL:$1|пут|пута|пута}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|кадар|кадра|кадрова}}',
+'file-no-thumb-animation' => "'''Напомена: због техничких ограничења, минијатуре ове датотеке се неће анимирати.'''",
+'file-no-thumb-animation-gif' => "'''Напомена: због техничких ограничења, минијатуре GIF слика високе резолуције као што је ова неће се анимирати.'''",
# Special:NewFiles
'newimages' => 'Галерија нових датотека',
'sectioneditnotsupported-text' => 'Uređivanje odeljka nije podržano na ovoj stranici.',
'permissionserrors' => 'Greške u dozvolama',
'permissionserrorstext' => 'Nemate ovlašćenje za tu radnju iz {{PLURAL:$1|sledećeg|sledećih}} razloga:',
-'permissionserrorstext-withaction' => 'Nemate ovlašćenja za $2 zbog {{PLURAL:$1|sledećeg|sledećih}} razloga:',
+'permissionserrorstext-withaction' => 'Nemate dozvolu da $2 iz {{PLURAL:$1|sledećeg|sledećih}} razloga:',
'recreate-moveddeleted-warn' => "'''Upozorenje: ponovo pravite stranicu koja je prethodno obrisana.'''
Razmotrite da li je prikladno da nastavite s uređivanjem ove stranice.
'shared-repo' => 'zajedničko skladište',
'shared-repo-name-wikimediacommons' => 'Vikimedijina ostava',
'filepage.css' => '/* CSS koji je postavljen ovde se nalazi na stranicama za opis datoteka, kao i na stranim vikijima */',
+'upload-disallowed-here' => 'Nažalost, ne možete da zamenite ovu sliku.',
# File reversion
'filerevert' => 'Vrati $1',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|bajt|bajta|bajtova}}',
'ncategories' => '$1 {{PLURAL:$1|kategorija|kategorije|kategorija}}',
+'ninterwikis' => '$1 {{PLURAL:$1|međuviki|međuvikija|međuvikija}}',
'nlinks' => '$1 {{PLURAL:$1|veza|veze|veza}}',
'nmembers' => '$1 {{PLURAL:$1|član|člana|članova}}',
'nrevisions' => '$1 {{PLURAL:$1|izmena|izmene|izmena}}',
'mostlinkedtemplates' => 'Šabloni s najviše veza',
'mostcategories' => 'Članci s najviše kategorija',
'mostimages' => 'Datoteke s najviše veza',
+'mostinterwikis' => 'Stranice sa najviše međuvikija',
'mostrevisions' => 'Stranice s najviše izmena',
'prefixindex' => 'Sve stranice s prefiksom',
'prefixindex-namespace' => 'Sve stranice s predmetkom (imenski prostor $1)',
'mailnologin' => 'Nema adrese za slanje',
'mailnologintext' => 'Morate biti [[Special:UserLogin|prijavljeni]] i imati ispravnu e-adresu u [[Special:Preferences|podešavanjima]] da biste slali e-poruke drugim korisnicima.',
'emailuser' => 'Pošalji e-poruku',
+'emailuser-title-target' => 'Slanje e-poruke {{GENDER:$1|korisniku|korisnici|korisniku}}',
+'emailuser-title-notarget' => 'Slanje e-poruke korisniku',
'emailpage' => 'Slanje e-poruka',
'emailpagetext' => 'Koristite ovaj obrazac da pošaljete e-poruku ovom korisniku.
E-adresa koju ste uneli u [[Special:Preferences|podešavanjima]] će biti prikazana kao adresa pošiljaoca, tako da će primalac poruke moći da vam odgovori.',
# Info page
'pageinfo-title' => 'Podaci o „$1“',
+'pageinfo-header-basic' => 'Osnovni podaci',
'pageinfo-header-edits' => 'Istorija izmena',
+'pageinfo-header-restrictions' => 'Zaštita stranice',
+'pageinfo-header-properties' => 'Svojstva stranice',
+'pageinfo-display-title' => 'Naslov za prikaz',
+'pageinfo-default-sort' => 'Podrazumevani ključ sortiranja',
+'pageinfo-length' => 'Dužina stranice (u bajtovima)',
+'pageinfo-article-id' => 'ID stranice',
+'pageinfo-robot-policy' => 'Status pretraživača',
+'pageinfo-robot-index' => 'Može da se popiše',
+'pageinfo-robot-noindex' => 'Ne može da se popiše',
'pageinfo-views' => 'Broj pregleda',
'pageinfo-watchers' => 'Broj nadgledača stranica',
+'pageinfo-redirects-name' => 'Preusmeravanja na stranicu',
+'pageinfo-subpages-name' => 'Podstranice ove stranice',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|preusmerenje|preusmerenja|preusmerenja}}; $3 {{PLURAL:$3|nepreusmerenje|nepreusmerenja|nepreusmerenja}})',
+'pageinfo-firstuser' => 'Autor stranice',
+'pageinfo-firsttime' => 'Datum stvaranja stranice',
+'pageinfo-lastuser' => 'Poslednji urednik',
+'pageinfo-lasttime' => 'Datum poslednje izmene',
'pageinfo-edits' => 'Broj izmena',
'pageinfo-authors' => 'Broj zasebnih autora',
+'pageinfo-recent-edits' => 'Broj skorašnjih izmena (u poslednjih $1)',
+'pageinfo-recent-authors' => 'Broj skorašnjih zasebnih autora',
+'pageinfo-restriction' => 'Zaštita stranice (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Magična reč|Magične reči}} ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}} ($1)',
+'pageinfo-templates' => '{{PLURAL:$1|Uključeni šablon|Uključeni šabloni}} ($1)',
# Skin names
'skinname-standard' => 'Klasično',
'file-info-size-pages' => '$1 × $2 piksela, veličina: $3, MIME vrsta: $4, $5 {{PLURAL:$5|stranica|stranice|stranica}}',
'file-nohires' => 'Veća rezolucija nije dostupna.',
'svg-long-desc' => 'SVG datoteka, nominalno $1 × $2 piksela, veličina: $3',
+'svg-long-desc-animated' => 'Animirana SVG datoteka, nominalno: $1 × $2 piksela, veličina: $3',
'show-big-image' => 'Puna veličina',
'show-big-image-preview' => 'Veličina ovog prikaza: $1.',
'show-big-image-other' => '{{PLURAL:$2|Druga rezolucija|Druge rezolucije}}: $1.',
'file-info-png-looped' => 'petlja',
'file-info-png-repeat' => 'ponovljeno $1 {{PLURAL:$1|put|puta|puta}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|kadar|kadra|kadrova}}',
+'file-no-thumb-animation' => "'''Napomena: zbog tehničkih ograničenja, minijature ove datoteke se neće animirati.'''",
+'file-no-thumb-animation-gif' => "'''Napomena: zbog tehničkih ograničenja, minijature GIF slika visoke rezolucije kao što je ova neće se animirati.'''",
# Special:NewFiles
'newimages' => 'Galerija novih datoteka',
* @author Petter Strandmark
* @author Poxnar
* @author Purodha
+ * @author Rotsee
* @author S.Örvarr.S
* @author Sannab
* @author Sertion
'error' => 'Fel',
'databaseerror' => 'Databasfel',
'dberrortext' => 'Ett syntaxfel i databasfrågan har uppstått.
-Detta kan indikera en bug i mjukvaran.
+Detta kan indikera en bugg i mjukvaran.
Den senaste databasfrågan att köras var:
<blockquote><tt>$1</tt></blockquote>
från funktionen "<tt>$2</tt>".
'userpage-userdoesnotexist-view' => 'Kontot "$1" är inte registrerat.',
'blocked-notice-logextract' => 'Användaren är blockerad.
Orsaken till senaste blockeringen kan ses nedan:',
-'clearyourcache' => "'''OBS:''' Sedan du sparat sidan kan du behöva tömma din webbläsares cache för att se ändringarna.
+'clearyourcache' => "'''OBS:''' Efter du sparat sidan kan du behöva tömma din webbläsares cache för att se ändringarna.
*'''Firefox / Safari:''' Håll ned ''Skift'' och klicka på ''Uppdatera sidan'' eller tryck antingen ''Ctrl-F5'' eller ''Ctrl-R'' (''⌘-R'' på Mac)
*'''Google Chrome:''' Tryck ''Ctrl-Skift-R'' (''⌘-Shift-R'' på Mac)
*'''Internet Explorer:''' Håll ned ''Ctrl'' och klicka på ''Uppdatera'' eller tryck ''Ctrl-F5''
-*'''Konqueror:''' Klicka på ''Reload'' eller tryck på ''F5''
*'''Opera:''' Rensa cachen i ''Verktyg → Inställningar''",
'usercssyoucanpreview' => "'''Tips:''' Använd \"{{int:showpreview}}\"-knappen för att testa din nya css innan du sparar.",
'userjsyoucanpreview' => "'''Tips:''' Använd \"{{int:showpreview}}\"-knappen för att testa din nya JavaScript innan du sparar.",
'editundo' => 'gör ogjord',
'diff-multi' => '({{PLURAL:$1|En mellanliggande version|$1 mellanliggande versioner}} av {{PLURAL:$2|en användare|$2 användare}} visas inte)',
'diff-multi-manyusers' => '({{PLURAL:$1|En mellanliggande version|$1 mellanliggande versioner}} av mer än $2 användare visas inte)',
+'difference-missing-revision' => '{{PLURAL:$2|En revision|$2 revisioner}} av denna skillnad ($1) kunde inte hittas.
+
+Detta orsakas vanligtvis av att följa en utgången difflänk till en sida som har raderats.
+Detaljer kan hittas i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} raderingsloggen].',
# Search results
'searchresults' => 'Sökresultat',
'shared-repo-from' => 'från $1',
'shared-repo' => 'en gemensam filförvaring',
'filepage.css' => '/* CSS som skrivs här inkluderas på filbeskrivningssidan, även på utländska klientwikis */',
+'upload-disallowed-here' => 'Du kan inte skriva över denna bild.',
# File reversion
'filerevert' => 'Återställ $1',
'disambiguations' => 'Sidor som länkar till förgreningssidor',
'disambiguationspage' => 'Template:Förgrening',
-'disambiguations-text' => "Följande sidor länkar till ''förgreningssidor''.
-Länkarna bör troligtvis ändras så att de länkar till en artikel istället.<br />
+'disambiguations-text' => "Följande sidorna innehåller minst en länk till en '''förgreningssida'''.
+De bör troligtvis ändras så att de länkar till en mer passande sida istället.<br />
En sida anses vara en förgreningssida om den inkluderar en mall som länkas till från [[MediaWiki:Disambiguationspage]].",
'doubleredirects' => 'Dubbla omdirigeringar',
'import-interwiki-templates' => 'Inkludera alla mallar',
'import-interwiki-submit' => 'Importera',
'import-interwiki-namespace' => 'Målnamnrymd:',
+'import-interwiki-rootpage' => 'Destinationens grundsida (valfri):',
'import-upload-filename' => 'Filnamn:',
'import-comment' => 'Kommentar:',
'importtext' => 'Var god exportera filen från ursprungs-wikin med hjälp av [[Special:Export|exporteringsverktyget]].
'import-error-special' => 'Sidan "$1" är inte importerad eftersom den tillhör en särskild namnrymd som inte tillåter sidor.',
'import-error-invalid' => 'Sidan "$1" är inte importerad eftersom dess namn är ogiltigt.',
'import-options-wrong' => 'Fel {{PLURAL:$2|alternativ|alternativ}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'Angiven grundsida är en ogiltig titel.',
'import-rootpage-nosubpage' => 'Namnrymden "$1" till grundsidan tillåter inte undersidor.',
# Import log
'pageinfo-length' => 'Sidlängd (i byte)',
'pageinfo-article-id' => 'Sid-ID',
'pageinfo-robot-policy' => 'Sökmotorns status',
+'pageinfo-robot-index' => 'Indexerbar',
+'pageinfo-robot-noindex' => 'Inte indexerbar',
'pageinfo-views' => 'Antal visningar',
'pageinfo-watchers' => 'Antal användare som bevakar sidan',
'pageinfo-redirects-name' => 'Omdirigeringar till denna sida',
'pageinfo-subpages-name' => 'Undersidor till denna sida',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|omdirigering|omdirigeringar}}; $3 {{PLURAL:$3|icke-omdirigering|icke-omdirigeringar}})',
+'pageinfo-firstuser' => 'Sidskapare',
+'pageinfo-firsttime' => 'Datum när sidan skapades',
+'pageinfo-lastuser' => 'Senaste redigeraren',
'pageinfo-lasttime' => 'Datum för senaste redigeringen',
'pageinfo-edits' => 'Totalt antal redigeringar',
'pageinfo-authors' => 'Totalt antal olika författare',
+'pageinfo-recent-edits' => 'Antal nyliga redigeringar (inom de senaste $1)',
+'pageinfo-recent-authors' => 'Antal nyliga olika författare',
+'pageinfo-restriction' => 'Sidskydd (<code>{{lcfirst:$1}}</code>)',
'pageinfo-magic-words' => '{{PLURAL:$1|Magiskt|Magiska}} ord ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Dold kategori|Dolda kategorier}} ($1)',
'file-info-png-looped' => 'upprepad',
'file-info-png-repeat' => 'spelad $1 {{PLURAL:$1|gång|gånger}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|bild|bilder}}',
+'file-no-thumb-animation' => "'''OBS: På grund av tekniska begränsningar kommer inte miniatyrer av denna fil animeras.'''",
+'file-no-thumb-animation-gif' => "'''OBS: På grund av tekniska begränsningar kommer inte miniatyrer av GIF-bilder med hög upplösning som denna animeras.'''",
# Special:NewFiles
'newimages' => 'Galleri över nya filer',
# img_auth script messages
'img-auth-accessdenied' => 'Ruksa imekataliwa',
+'img-auth-nologinnWL' => '',
'img-auth-nofile' => 'Hakuna faili la "$1".',
+'img-auth-isdir' => '',
'img-auth-noread' => 'Mtumiaji hana fursa ya kusoma "$1".',
# HTTP errors
'protect-unchain-permissions' => 'Fungua chaguzi zingine za ulindaji',
'protect-text' => "Unaweza kutazama na kubadilisha kiwango cha ulindaji hapa kwa ukurasa '''$1'''.",
'protect-locked-dblock' => "Viwango vya ulindaji haviwezi kubadilishwa kwa sababu hifadhidata imefungwa.
-Hapo panaandikwa viwango vya ulindaji wa ukurasa '''$1''':",
+Hii hapa ni mipangilio iliyopo kwa ajili ya ukurasa '''$1''':",
'protect-locked-access' => "Akaunti yako hairuhusiwi kubadilisha viwango vya ulindaji.
Hivi ni vipimo kwa ukurasa '''$1''':",
'protect-cascadeon' => 'Ukurasa huu umelindwa kwa sababu umezingatiwa katika {{PLURAL:$1|ukurasa $1 unaolinda kurasa chini yake|kurasa $1 zinazolinda kurasa chini yake}}. Unaweza kubadilisha kiwango cha ulindaji wa ukurasa huu, lakini hutaathirika ulindaji kutoka kurasa juu yake.',
'protect-level-sysop' => 'Wakabidhi tu',
'protect-summary-cascade' => 'ulindaji kwa kurasa chini yake',
'protect-expiring' => 'itakwisha $1 (UTC)',
-'protect-expiring-local' => 'inaishia saa $1',
+'protect-expiring-local' => 'inaisha $1',
'protect-expiry-indefinite' => 'bila mwisho',
'protect-cascade' => 'Linda kurasa zinazozingatiwa chini ya ukurasa huu',
'protect-cantedit' => 'Huwezi kubadilisha kiwango cha ulindaji wa ukurasa huu, kwa sababu huruhusiwi kuuhariri.',
'protect-othertime' => 'Kipindi kingine:',
'protect-othertime-op' => 'kipindi kingine',
-'protect-existing-expiry' => 'Kipindi cha ulindaji uliowekwa unaishia: $3, $2',
+'protect-existing-expiry' => 'Muda wa kwisha uliopo: $3, $2',
'protect-otherreason' => 'Sababu nyingine:',
'protect-otherreason-op' => 'Sababu nyingine',
'protect-dropdown' => '*Sababu za kawaida za ulindaji
'protect-expiry-options' => 'saa 1:1 hour,siku 1:1 day,wiki 1:1 week,wiki 2:2 weeks,mwezi 1:1 month,miezi 3:3 months,miezi 6:6 months,mwaka 1:1 year,milele:infinite',
'restriction-type' => 'Ruhusa:',
'restriction-level' => 'Kiwango cha kizuia:',
-'minimum-size' => 'Saizi ndogo mno',
-'maximum-size' => 'Saizi kubwa mno:',
+'minimum-size' => 'Saizi ndogo',
+'maximum-size' => 'Saizi kubwa:',
'pagesize' => '(baiti)',
# Restrictions (nouns)
# Restriction levels
'restriction-level-sysop' => 'umelindwa kabisa',
-'restriction-level-autoconfirmed' => 'umelindwa kwa kiasi',
-'restriction-level-all' => 'chochote',
+'restriction-level-autoconfirmed' => 'umelindwa kiasi',
+'restriction-level-all' => 'kiasi chochote',
# Undelete
'undelete' => 'Kuzitazama kurasa zilizofutwa',
'pageinfo-title' => 'Taarifa juu ya "$1"',
'pageinfo-header-edits' => 'Maharirio',
'pageinfo-watchers' => 'Idadi ya wanaofuatilia',
-'pageinfo-edits' => 'Idadi ya haririo',
+'pageinfo-edits' => 'Idadi ya maharirio',
# Image deletion
'deletedrevision' => 'Pitio la awali lililofutwa $1',
# Special:ChangeEmail
'changeemail' => 'ఈ-మెయిలు చిరునామా మార్పు',
'changeemail-header' => 'ఖాతా ఈ-మెయిల్ చిరునామాని మార్చండి',
-'changeemail-text' => 'à°®à±\80 à°\88à°®à±\86యిలà±\8d à°\9aà°¿à°°à±\81నామా మారà±\8dà°\9aà±\81à°\9fà°\95à±\81 à°\88 ఫారమà±\81 నిà°\82à°ªà°\82à°¡à°¿. à°\88 మారà±\8dà°ªà±\81ని à°\96à°\9aà±\8dà°\9aితపరà°\9aà±\81à°\9fà°\95à±\81 à°®à±\80 à°¸à°\82à°\95à±\87తపదà°\82 à°ªà±\8dà°°à°µà±\87శపà±\86à°\9fà±\8dà°\9fాలి.',
+'changeemail-text' => 'à°®à±\80 à°\88à°®à±\86యిలà±\81 à°\9aà°¿à°°à±\81నామాని మారà±\8dà°\9aà±\81à°\95à±\8bడానిà°\95à°¿ à°\88 ఫారానà±\8dని నిà°\82à°ªà°\82à°¡à°¿. à°\88 మారà±\8dà°ªà±\81ని నిరà±\8dధారిà°\82à°\9aడానిà°\95à°¿ à°®à±\80 à°¸à°\82à°\95à±\87తపదానà±\8dని à°\87à°µà±\8dవాలà±\8dసివసà±\8dà°¤à±\81à°\82à°¦ి.',
'changeemail-no-info' => 'ఈ పేజీని నేరుగా చూడటానికి మీరు లోనికి ప్రవేశించివుండాలి.',
'changeemail-oldemail' => 'ప్రస్తుత ఈ-మెయిలు చిరునామా:',
'changeemail-newemail' => 'కొత్త ఈ-మెయిలు చిరునామా:',
'tog-enotifminoredits' => 'แม้ว่าการแก้ไขจะเป็นการแก้ไขเล็กน้อย',
'tog-enotifrevealaddr' => 'เผยที่อยู่อีเมลในอีเมลที่ชี้แจง',
'tog-shownumberswatching' => 'แสดงจำนวนผู้ใช้ที่เฝ้าดูหน้านี้',
-'tog-oldsig' => 'ลายà¹\80à¸\8bà¹\87à¸\99à¸\95à¹\8cà¹\80à¸\94ิมà¸\97ีà¹\88à¹\83à¸\8aà¹\89à¸à¸¢à¸¹à¹\88:',
+'tog-oldsig' => 'ลายเซ็นที่ใช้อยู่:',
'tog-fancysig' => 'ใช้คำสั่งวิกิที่ปรากฏในลายเซ็นนี้ (ไม่มีการสร้างลิงก์อัตโนมัติ)',
'tog-externaleditor' => 'ใช้โปรแกรมแก้ไขภายนอกโดยปริยาย (สำหรับผู้เชี่ยวชาญเท่านั้น ต้องการการตั้งค่าพิเศษบนคอมพิวเตอร์ของคุณ [//www.mediawiki.org/wiki/Manual:External_editors ข้อมูลเพิ่มเติม])',
'tog-externaldiff' => 'ใช้โปรแกรมเปรียบเทียบภายนอกโดยปริยาย (สำหรับผู้เชี่ยวชาญเท่านั้น ต้องการการตั้งค่าพิเศษบนคอมพิวเตอร์ของคุณ [//www.mediawiki.org/wiki/Manual:External_editors ข้อมูลเพิ่มเติม])',
'tog-showjumplinks' => 'เปิดใช้งาน "กระโดด" อัตโนมัติไปตามลิงก์',
'tog-uselivepreview' => 'แสดงตัวอย่างการแก้ไขแบบทันที (จาวาสคริปต์) (ทดลอง)',
-'tog-forceeditsummary' => 'à¹\80à¸\95ืà¸à¸\99à¹\80มืà¹\88à¸à¸\8aà¹\88à¸à¸\87สรุà¸\9bà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82ว่าง',
+'tog-forceeditsummary' => 'à¹\80à¸\95ืà¸à¸\99à¹\80มืà¹\88à¸à¸\8aà¹\88à¸à¸\87à¸\84ำà¸à¸\98ิà¸\9aายà¸à¸¢à¹\88าà¸\87ยà¹\88à¸ว่าง',
'tog-watchlisthideown' => 'ไม่แสดงการแก้ไขของตนเองจากรายการเฝ้าดูของตนเอง',
'tog-watchlisthidebots' => 'ไม่แสดงการแก้ไขของบอตจากรายการเฝ้าดูของตนเอง',
'tog-watchlisthideminor' => 'ไม่แสดงการแก้ไขเล็กน้อยจากรายการเฝ้าดูของตนเอง',
# Font style option in Special:Preferences
'editfont-style' => 'รูปแบบของแบบตัวอักษรในกล่องแก้ไข:',
-'editfont-default' => 'ค่าตั้งต้นของ browser',
+'editfont-default' => 'ค่าตั้งต้นของเบราว์เซอร์',
'editfont-monospace' => 'ชุดอักษรแบบความกว้างคงที่',
'editfont-sansserif' => 'ชุดอักษรแบบไม่มีเชิง',
'editfont-serif' => 'ชุดอักษรแบบมีเชิง',
'specialpage' => 'หน้าพิเศษ',
'personaltools' => 'เครื่องมือส่วนตัว',
'postcomment' => 'หัวข้อใหม่',
-'articlepage' => 'à¹\81สà¸\94à¸\87à¹\80à¸\99ืà¹\89à¸à¸«à¸²à¸\82à¸à¸\87หà¸\99à¹\89า',
+'articlepage' => 'à¹\81สà¸\94à¸\87หà¸\99à¹\89าà¹\80à¸\99ืà¹\89à¸à¸«า',
'talk' => 'อภิปราย',
'views' => 'ดู',
'toolbox' => 'เครื่องมือเพิ่ม',
'imagepage' => 'ดูหน้ารายละเอียดไฟล์',
'mediawikipage' => 'ดูหน้าข้อความ',
'templatepage' => 'ดูหน้าแม่แบบ',
-'viewhelppage' => 'à¸\94ูหà¸\99à¹\89าà¸\84ำà¸à¸\98ิà¸\9aาย',
+'viewhelppage' => 'à¸\94ูหà¸\99à¹\89าวิà¸\98ีà¹\83à¸\8aà¹\89',
'categorypage' => 'ดูหน้าหมวดหมู่',
'viewtalkpage' => 'ดูการพูดคุย',
'otherlanguages' => 'ในภาษาอื่น',
'jumpto' => 'ข้ามไปที่:',
'jumptonavigation' => 'นำทาง',
'jumptosearch' => 'สืบค้น',
-'view-pool-error' => 'à¸\82à¸à¸à¸ ัย à¸\82à¸\93ะà¸\99ีà¹\89มีà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\87าà¸\99à¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วà¸à¸£à¹\8cมาà¸\81à¹\80à¸\81ิà¸\99à¸\97ีà¹\88à¸\88ะรัà¸\9aà¹\84à¸\94à¹\89
-à¸\9cูà¹\89à¸\97ีà¹\88à¸\9eยายามà¹\80à¸\82à¹\89าà¸\94ูหà¸\99à¹\89าà¸\99ีà¹\89มีà¸\88ำà¸\99วà¸\99มาà¸\81à¸\88à¸\99เกินไป
+'view-pool-error' => 'à¸\82à¸à¸à¸ ัย à¸\82à¸\93ะà¸\99ีà¹\89à¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วà¸à¸£à¹\8cมีภาระà¹\80à¸\81ิà¸\99
+à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\9eยายามà¹\80à¸\82à¹\89าà¸\94ูหà¸\99à¹\89าà¸\99ีà¹\89มาà¸\81เกินไป
กรุณารอสักครู่ก่อนที่จะเข้าดูหน้านี้อีกครั้งหนึ่ง
$1',
# All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage) and the disambiguation template definition (see disambiguations).
'aboutsite' => 'เกี่ยวกับ {{SITENAME}}',
'aboutpage' => 'Project:เกี่ยวกับเว็บไซต์',
-'copyright' => 'à¹\80à¸\99ืà¹\89à¸à¸«à¸²à¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¸à¸¢à¸¹à¹\88ภายà¹\83à¸\95à¹\89ลิà¸\82สิà¸\97à¸\98ิà¹\8cà¹\81à¸\9aà¸\9a $1',
+'copyright' => 'à¹\80à¸\99ืà¹\89à¸à¸«à¸²à¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\80à¸\9cยà¹\81à¸\9eรà¹\88ภายà¹\83à¸\95à¹\89 $1',
'copyrightpage' => '{{ns:project}}:ลิขสิทธิ์',
'currentevents' => 'เหตุการณ์ปัจจุบัน',
'currentevents-url' => 'Project:เหตุการณ์ปัจจุบัน',
'retrievedfrom' => 'รับข้อมูลจาก "$1"',
'youhavenewmessages' => 'คุณมี $1 ($2)',
'newmessageslink' => 'ข้อความใหม่',
-'newmessagesdifflink' => 'à¸\82à¹\89à¸à¸\84วามà¹\80à¸\82à¹\89ามาà¹\83หมà¹\88',
+'newmessagesdifflink' => 'à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87ลà¹\88าสุà¸\94',
'youhavenewmessagesmulti' => 'คุณมีข้อความใหม่ที่ $1',
'editsection' => 'แก้ไข',
'editold' => 'แก้ไข',
'nstab-image' => 'ไฟล์',
'nstab-mediawiki' => 'ข้อความ',
'nstab-template' => 'แม่แบบ',
-'nstab-help' => 'หà¸\99à¹\89าà¸\84ำà¸à¸\98ิà¸\9aาย',
+'nstab-help' => 'หà¸\99à¹\89าวิà¸\98ีà¹\83à¸\8aà¹\89',
'nstab-category' => 'หมวดหมู่',
# Main script and global functions
'nosuchaction' => 'ไม่มีการกระทำดังกล่าว',
'nosuchactiontext' => 'การกระทำที่กำหนดผ่านยูอาร์แอลดังกล่าวไม่สามารถใช้ได้
-คุณอาจกรอกยูอาร์แอลผิด หรือ มาตามลิงก์ที่ไม่ถูกต้อง
-หรืà¸à¸à¸²à¸\88à¸\88ะà¹\80à¸\81ิà¸\94à¸\88าà¸\81à¸\82à¹\89à¸à¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¹\82à¸\9bรà¹\81à¸\81รมซึ่ง {{SITENAME}} ใช้อยู่',
+คุณอาจกรอกยูอาร์แอลผิด หรือมาตามลิงก์ที่ไม่ถูกต้อง
+หรืà¸à¸à¸²à¸\88à¹\80à¸\81ิà¸\94à¸\88าà¸\81à¸\82à¹\89à¸à¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\8bà¸à¸\9fà¸\95à¹\8cà¹\81วรà¹\8cซึ่ง {{SITENAME}} ใช้อยู่',
'nosuchspecialpage' => 'ไม่มีหน้าพิเศษดังกล่าว',
'nospecialpagetext' => '
<strong>คุณร้องขอหน้าพิเศษไม่ถูกต้อง</strong>
'filenotfound' => 'ไม่พบไฟล์ "$1"',
'fileexistserror' => 'ไม่สามารถเขียนไฟล์ "$1" ได้ เนื่องจากมีไฟล์อยู่แล้ว',
'unexpected' => 'ผลที่ไม่คาดคิด: "$1"="$2"',
-'formerror' => 'à¸\9cิà¸\94à¸\9eลาà¸\94: à¹\84มà¹\88สามารà¸\96สà¹\88à¸\87à¸\9fà¸à¸£à¹\8cมได้',
+'formerror' => 'à¸\9cิà¸\94à¸\9eลาà¸\94: à¹\84มà¹\88สามารà¸\96สà¹\88à¸\87à¹\81à¸\9aà¸\9aได้',
'badarticleerror' => 'การกระทำนี้ไม่สามารถดำเนินการในหน้านี้ได้',
'cannotdelete' => 'ไม่สามารถลบหน้าหรือไฟล์ "$1"
อาจมีผู้อื่นลบไปแล้ว',
'createaccountmail' => 'ผ่านทางอีเมล',
'createaccountreason' => 'เหตุผล:',
'badretype' => 'รหัสผ่านที่ใส่ไม่ถูกต้อง',
-'userexists' => 'à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81รà¸à¸\81à¸\96ูà¸\81à¹\83à¸\8aà¹\89à¹\84à¸\9bà¹\81ลà¹\89ว. กรุณาเลือกชื่ออื่น',
+'userexists' => 'à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88à¸\81รà¸à¸\81มีà¸\9cูà¹\89à¸à¸·à¹\88à¸\99à¹\83à¸\8aà¹\89à¹\84à¸\9bà¹\81ลà¹\89ว กรุณาเลือกชื่ออื่น',
'loginerror' => 'ล็อกอินผิดพลาด',
'createaccounterror' => 'ไม่สามารถสร้างบัญชีผู้ใช้: $1',
'nocookiesnew' => 'ชื่อบัญชีผู้ใช้ได้ถูกสร้างขึ้นแล้ว แต่ยังไม่ได้ล็อกอินเข้าสู่ {{SITENAME}} เนื่องจากว่าไม่ได้เปิดใช้คุกกี้ ถ้าต้องการล็อกอินให้เปิดใช้งานคุกกี้และทำการล็อกอินโดยใส่ชื่อผู้ใช้พร้อมรหัสผ่าน',
'createaccount-text' => 'มีใครบางคนสร้างบัญชีผู้ใช้สำหรับที่อยู่อีเมลของคุณไว้บน {{SITENAME}} ($4) โดยใช้ชื่อบัญชีผู้ใช้ "$2" และรหัสผ่าน "$3" คุณควรล็อกอินเพื่อเปลี่ยนรหัสผ่านโดยทันที
ข้อความนี้อาจจะไม่สำคัญสำหรับคุณ หากการสร้างบัญชีผู้ใช้นี้เกิดจากความผิดพลาด',
-'usernamehasherror' => 'à¹\84มà¹\88สามารà¸\96มีà¸\95ัวà¸à¸±à¸\81ษร "#" à¹\83à¸\99à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89',
+'usernamehasherror' => 'à¹\83à¸\99à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\95à¹\89à¸à¸\87à¹\84มà¹\88มีà¸\95ัวà¸à¸±à¸\81ษร "#"',
'login-throttled' => 'คุณได้พยายามล็อกอินมากครั้งเกินไป
กรุณารอสักครู่แล้วลองใหม่อีกครั้ง',
'login-abort-generic' => 'การเข้าสู่ระบบของคุณไม่ประสบความสำเร็จ - ล้มเลิกแล้ว',
'newpassword' => 'รหัสผ่านใหม่:',
'retypenew' => 'พิมพ์รหัสผ่านใหม่อีกครั้ง:',
'resetpass_submit' => 'ตั้งรหัสผ่านและล็อกอิน',
-'resetpass_success' => 'รหัสà¸\9cà¹\88าà¸\99à¹\84à¸\94à¹\89à¸\96ูà¸\81à¹\80à¸\9bลีà¹\88ยà¸\99เรียบร้อย ขณะนี้กำลังล็อกอินให้คุณ...',
+'resetpass_success' => 'à¹\80à¸\9bลีà¹\88ยà¸\99รหัสà¸\9cà¹\88าà¸\99à¸\82à¸à¸\87à¸\84ุà¸\93เรียบร้อย ขณะนี้กำลังล็อกอินให้คุณ...',
'resetpass_forbidden' => 'ไม่สามารถเปลี่ยนรหัสผ่านได้',
'resetpass-no-info' => 'คุณต้องล็อกอินเพื่อที่จะเข้าถึงหน้านี้โดยตรง',
'resetpass-submit-loggedin' => 'เปลี่ยนรหัสผ่าน',
# Special:ChangeEmail
'changeemail' => 'เปลี่ยนที่อยู่อีเมล',
'changeemail-header' => 'เปลี่ยนที่อยู่อีเมลของบัญชีผู้ใช้',
-'changeemail-no-info' => 'à¸\84ุà¸\93à¸\88ำà¹\80à¸\9bà¹\87à¸\99à¸\95à¹\89à¸à¸\87à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9aà¹\80à¸\9eืà¹\88à¸à¹\80à¸\82à¹\89าà¸\96ึà¸\87หà¸\99à¹\89าà¹\80à¸à¸\81สารà¸\99ีà¹\89à¹\84à¸\94้โดยตรง',
+'changeemail-no-info' => 'à¸\84ุà¸\93à¸\88ำà¹\80à¸\9bà¹\87à¸\99à¸\95à¹\89à¸à¸\87à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9aà¹\80à¸\9eืà¹\88à¸à¹\80à¸\82à¹\89าà¸\96ึà¸\87หà¸\99à¹\89าà¸\99ี้โดยตรง',
'changeemail-oldemail' => 'ที่อยู่อีเมลปัจจุบัน:',
'changeemail-newemail' => 'ที่อยู่อีเมลใหม่:',
'changeemail-none' => '(ไม่มี)',
'token_suffix_mismatch' => "'''การแก้ไขของคุณได้ถูกปฏิเสธ เนื่องจากเครื่องลูกข่ายที่คุณใช้อยู่ได้ทำลายรูปแบบเครื่องหมายวรรคตอนในตราสารประจำการแก้ไข (edit token)'''
ระบบไม่รับการแก้ไขของคุณเพื่อป้องกันความผิดพลาดของข้อมูล
ในบางครั้งปัญหานี้จะเกิดขึ้นถ้าคุณใช้บริการเว็บพร็อกซีนิรนามที่มีบั๊ก",
-'edit_form_incomplete' => "'''à¸\9aาà¸\87สà¹\88วà¸\99à¸\82à¸à¸\87à¹\81à¸\9aà¸\9aà¸\9fà¸à¸£à¹\8cมà¹\81à¸\81à¹\89à¹\84à¸\82à¹\84มà¹\88à¹\84à¸\94à¹\89à¸\95ิà¸\94à¸\95à¹\88à¸à¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วà¸à¸£à¹\8c à¸\95รวà¸\88สà¸à¸\9aà¸à¸µà¸\81à¸\84รัà¹\89à¸\87วà¹\88าà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93ยัà¸\87à¸\84à¸\87à¸à¸¢à¸¹à¹\88à¹\81ละลà¸à¸\87à¹\83หมà¹\88อีกครั้ง'''",
+'edit_form_incomplete' => "'''à¸\9aาà¸\87สà¹\88วà¸\99à¸\82à¸à¸\87à¹\81à¸\9aà¸\9aà¹\81à¸\81à¹\89à¹\84à¸\82à¹\84à¸\9bà¹\84มà¹\88à¸\96ึà¸\87à¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วà¸à¸£à¹\8c à¸\95รวà¸\88สà¸à¸\9aà¸à¸µà¸\81à¸\84รัà¹\89à¸\87วà¹\88าà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93ยัà¸\87à¸\84à¸\87à¸à¸¢à¸¹à¹\88à¹\81ละลà¸à¸\87อีกครั้ง'''",
'editing' => 'กำลังแก้ไข $1',
'creating' => 'สร้างหน้า $1',
'editingsection' => 'กำลังแก้ไข $1 (เฉพาะส่วน)',
'readonlywarning' => "'''คำเตือน: ขณะนี้ฐานข้อมูลถูกล็อกเพื่อบำรุงรักษา จึงไม่สามารถบันทึกข้อมูลที่แก้ไขได้ แนะนำให้คัดลอกไปเก็บไว้ที่อื่นก่อนแล้วนำมาบันทึกในเว็บไซต์นี้ภายหลัง'''
ผู้ดูแลระบบที่ล็อกฐานข้อมูลได้ให้คำอธิบายดังนี้: $1",
-'protectedpagewarning' => "'''คำเตือน: หน้านี้ถูกล็อก และแก้ไขได้เฉพาะผู้ดูแลระบบเท่านั้น'''
-à¸\9aัà¸\99à¸\97ึà¸\81à¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99ลà¹\88าสุà¸\94à¸\96ูà¸\81à¹\81สà¸\94à¸\87à¹\84วà¹\89à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9eืà¹\88à¸à¸\81ารà¸à¹\89าà¸\87à¸à¸´à¸\87",
+'protectedpagewarning' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99: หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81 à¹\81ละà¹\81à¸\81à¹\89à¹\84à¸\82à¹\84à¸\94à¹\89à¹\80à¸\89à¸\9eาะà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88มีสิà¸\97à¸\98ิà¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9aà¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99'''
+à¸\9bูมลà¹\88าสุà¸\94à¸\96ูà¸\81à¹\81สà¸\94à¸\87à¹\84วà¹\89à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9eืà¹\88à¸à¸\81ารà¸à¹\89าà¸\87à¸à¸´à¸\87:",
'semiprotectedpagewarning' => "'''หมายเหตุ:''' หน้านี้ถูกล็อก และแก้ไขได้เฉพาะผู้ใช้ที่ลงทะเบียนเท่านั้น
รายการแก้ไขล่าสุดได้ถูกแสดงไว้ด้านล่างนี้เพื่อการอ้างอิง",
-'cascadeprotectedwarning' => "'''คำเตือน:''' หน้านี้ถูกล็อก และแก้ไขได้เฉพาะผู้ดูแลระบบเท่านั้น เนื่องจากหน้านี้สืบทอดการล็อกมาจาก{{PLURAL:$1|หน้า|หน้า}}ต่อไปนี้:",
+'cascadeprotectedwarning' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99:''' หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81 à¹\81ละà¹\81à¸\81à¹\89à¹\84à¸\82à¹\84à¸\94à¹\89à¹\80à¸\89à¸\9eาะà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88มีสิà¸\97à¸\98ิà¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9aà¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81หà¸\99à¹\89าà¸\99ีà¹\89สืà¸\9aà¸\97à¸à¸\94à¸\81ารลà¹\87à¸à¸\81มาà¸\88าà¸\81{{PLURAL:$1|หà¸\99à¹\89า|หà¸\99à¹\89า}}à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89:",
'titleprotectedwarning' => "'''คำเตือน: หน้านี้ได้รับการป้องกันไว้ให้สร้างได้โดย[[Special:ListGroupRights|ผู้ใช้ที่ได้รับสิทธิ]]เท่านั้น'''
รายการแก้ไขล่าสุดได้ถูกแสดงไว้ด้านล่างนี้เพื่อการอ้างอิง",
'templatesused' => '{{PLURAL:$1|แม่แบบ}}ที่ใช้ในหน้านี้:',
'hiddencategories' => 'หน้านี้มี {{PLURAL:$1|1 หมวดหมู่ที่ซ่อนอยู่|$1 หมวดหมู่ที่ซ่อนอยู่}} :',
'edittools' => '<!-- ข้อความนี้จะแสดงผลด้านใต้การแก้ไขและฟอร์มสำหรับอัปโหลด -->',
'nocreatetitle' => 'จำกัดการสร้างหน้าใหม่',
-'nocreatetext' => 'เว็บไซต์นี้จำกัดการสร้างหน้าเว็บเพจใหม่
-à¸\84ุà¸\93สามารà¸\96à¸\97ำà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\97ีà¹\88สรà¹\89าà¸\87à¹\84วà¹\89à¹\81ลà¹\89ว หรืภ[[Special:UserLogin|ล็อกอินหรือสร้างบัญชีผู้ใช้]]',
-'nocreate-loggedin' => 'คุณไม่ได้รับอนุญาตให้สร้างหน้าใหม่ได้',
+'nocreatetext' => '{{SITENAME}} จำกัดการสร้างหน้าใหม่
+à¸\84ุà¸\93สามารà¸\96ยà¹\89à¸à¸\99à¸\81ลัà¸\9aà¹\84à¸\9bà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\97ีà¹\88มีà¸à¸¢à¸¹à¹\88à¹\80à¸\94ิม หรืà¸[[Special:UserLogin|ล็อกอินหรือสร้างบัญชีผู้ใช้]]',
+'nocreate-loggedin' => 'คุณไม่ได้รับอนุญาตให้สร้างหน้าใหม่',
'sectioneditnotsupported-title' => 'ไม่สนับสนุนการแก้ไขหัวข้อย่อย',
'sectioneditnotsupported-text' => 'ไม่สนับสนุนการแก้ไขหัวข้อย่อยในหน้านี้',
'permissionserrors' => 'ข้อผิดพลาดในการใช้สิทธิ',
'permissionserrorstext' => 'คุณไม่ได้รับสิทธิในการทำสิ่งนี้ เนื่องจาก{{PLURAL:$1|เหตุผล|เหตุผล}}ต่อไปนี้:',
'permissionserrorstext-withaction' => 'คุณไม่มีสิทธิ$2 ด้วย{{PLURAL:$1|เหตุผล|เหตุผล}}ต่อไปนี้:',
-'recreate-moveddeleted-warn' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99: à¸\84ุà¸\93à¸\81ำลัà¸\87à¸\88ะสรà¹\89าà¸\87หà¸\99à¹\89าà¹\83หมà¹\88à¸\8bึà¹\88à¸\87à¹\84à¸\94à¹\89à¸\96ูà¸\81ลà¸\9aà¹\84à¸\9bà¸\81à¹\88à¸à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¹\81ลà¹\89ว'''
+'recreate-moveddeleted-warn' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99: à¸\84ุà¸\93à¸\81ำลัà¸\87สรà¹\89าà¸\87หà¸\99à¹\89าà¸\8bึà¹\88à¸\87à¹\84à¸\94à¹\89à¸\96ูà¸\81ลà¸\9aà¹\84à¸\9bà¸\81à¹\88à¸à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¹\81ลà¹\89วà¸à¸µà¸\81à¸\84รัà¹\89à¸\87'''
-คุณควรพิจารณาว่าการแก้ไขหน้านี้เหมาะสมหรือไม่
+à¸\84ุà¸\93à¸\84วรà¸\9eิà¸\88ารà¸\93าวà¹\88าà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\99ีà¹\89à¸\95à¹\88à¸à¹\84à¸\9bà¹\80หมาะสมหรืà¸à¹\84มà¹\88
ปูมการลบและเปลี่ยนชื่อหน้านี้ได้แสดงไว้ด้านล่างเพื่อความสะดวก:",
'moveddeleted-notice' => 'หน้านี้ถูกลบ
ปูมการลบและเปลี่ยนชื่อของหน้านี้ได้แสดงไว้ด้านล่างเพื่ออ้างอิง',
'log-fulllog' => 'ดูปูมแบบเต็ม',
'edit-hook-aborted' => 'การแก้ไขถูกยกเลิก
ไม่มีคำอธิบายสำหรับการยกเลิกนี้',
-'edit-gone-missing' => 'à¹\84มà¹\88สามารà¸\96à¸\9bรัà¸\9aà¹\81à¸\81à¹\89หน้าดังกล่าวได้
+'edit-gone-missing' => 'à¹\84มà¹\88สามารà¸\96à¸à¸±à¸\9bà¹\80à¸\94à¸\95หน้าดังกล่าวได้
เนื่องจากหน้านี้ถูกลบไปแล้ว',
'edit-conflict' => 'แก้ชนกัน',
-'edit-no-change' => 'à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¹\80à¸\9eิà¸\81à¹\80à¸\89ย à¹\80à¸\9eราะà¸\82à¹\89à¸à¸\84วามà¹\84มà¹\88à¸\96ูà¸\81à¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¹\83à¸\94 à¹\86 à¸\97ัà¹\89à¸\87สิà¹\89à¸\99',
-'edit-already-exists' => 'à¹\84มà¹\88สามารà¸\96สรà¹\89าà¸\87หà¸\99à¹\89าà¹\83หมà¹\88à¸\99ีà¹\89à¹\84à¸\94à¹\89
-à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81มีหน้านี้แล้ว',
+'edit-no-change' => 'à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¹\80à¸\9eิà¸\81à¹\80à¸\89ย à¹\80à¸\9eราะà¹\84มà¹\88มีà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¹\83à¸\94 à¹\86',
+'edit-already-exists' => 'ไม่สามารถสร้างหน้าใหม่ได้
+à¹\80à¸\9eราะมีหน้านี้แล้ว',
# Parser/template warnings
'expensive-parserfunction-warning' => 'คำเตือน: หน้านี้มีการเรียกใช้ฟังก์ชันแจงส่วนมากเกินไป
'history-feed-title' => 'ประวัติการปรับปรุง',
'history-feed-description' => 'ประวัติการปรับปรุงของหน้านี้ในวิกิ',
'history-feed-item-nocomment' => '$1 เมื่อ $2',
-'history-feed-empty' => 'หà¸\99à¹\89าà¸\97ีà¹\88à¸\95à¹\89à¸à¸\87à¸\81ารà¹\84มà¹\88มี มันอาจถูกลบหรือถูกเปลี่ยนชื่อไปแล้ว ให้ลอง
-[[Special:Search|à¸\84à¹\89à¸\99หาà¹\83à¸\99วิà¸\81ิà¸\99ีà¹\89]] สำหรัà¸\9aหà¸\99à¹\89าà¸à¸·à¹\88à¸\99à¸\97ีà¹\88à¸à¸²à¸\88à¹\80à¸\81ีà¹\88ยวà¸\82à¹\89à¸à¸\87',
+'history-feed-empty' => 'à¹\84มà¹\88มีหà¸\99à¹\89าà¸\97ีà¹\88à¸\95à¹\89à¸à¸\87à¸\81าร มันอาจถูกลบหรือถูกเปลี่ยนชื่อไปแล้ว ให้ลอง
+[[Special:Search|à¸\84à¹\89à¸\99หาà¹\83à¸\99วิà¸\81ิà¸\99ีà¹\89]] สำหรัà¸\9aหà¸\99à¹\89าà¹\83หมà¹\88à¸\97ีà¹\88à¹\80à¸\81ีà¹\88ยวà¸\82à¹\89à¸à¸\87',
# Revision deletion
'rev-deleted-comment' => '(คำอธิบายอย่างย่อถูกลบออก)',
ผู้ดูแลระบบคนอื่นบน {{SITENAME}} จะยังคงสามารถเข้าถึงเนื้อหาที่ถูกซ่อน และสามารถกู้คืนขึ้นมาอีกครั้งในลักษณะเดิมเช่นนี้ เว้นแต่จะมีการตั้งค่าการควบคุมเพิ่มเติม",
'revdelete-confirm' => 'กรุณายืนยันว่าคุณตั้งใจที่จะลบจริง และเข้าใจผลกระทบหลังจากนี้ที่จะเกิดขึ้น และกระทำกายภายใต้[[{{MediaWiki:Policy-url}}|นโยบาย]]',
'revdelete-suppress-text' => "การระงับควรใช้ '''เฉพาะ''' กรณีต่อไปนี้:
+* ข้อมูลที่อาจหมิ่นประมาท
* ข้อมูลส่วนบุคคลที่ไม่เหมาะสม
-*: ''à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\81ละหมายà¹\80ลà¸\82à¹\82à¸\97รศัà¸\9eà¸\97à¹\8cà¸\88าà¸\81บ้าน, หมายเลขประกันสังคม, ฯลฯ''",
+*: ''à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸\9aà¹\89าà¸\99à¹\81ละหมายà¹\80ลà¸\82à¹\82à¸\97รศัà¸\9eà¸\97à¹\8cบ้าน, หมายเลขประกันสังคม, ฯลฯ''",
'revdelete-legend' => 'ระบุการควบคุม:',
'revdelete-hide-text' => 'ซ่อนข้อความรุ่นที่ปรับปรุง',
'revdelete-hide-image' => 'ซ่อนเนื้อหาไฟล์',
'revdelete-concurrent-change' => 'เกิดความผิดพลาดในการแก้ไขฉบับปรับปรุงในวันที่ $2 เวลา $1: สถานะของฉบับปรับปรุงได้ถูกเปลี่ยนโดยใครบางคนในขณะที่คุณพยายามแก้ไขอยู่
กรุณาตรวจสอบประวัติการแก้ไข',
'revdelete-only-restricted' => 'เกิดความผิดพลาดในการซ่อนฉบับปรับปรุงในวันที่ $2 เวลา $1: คุณไม่สามารถยับยั้งผู้ดูแลระบบจากการดูฉบับปรับปรุงนี้โดยที่ไม่ได้เลือกตัวเลือกการให้ดูอื่นๆ',
-'revdelete-reason-dropdown' => '*à¹\80หà¸\95ุà¸\9cลà¹\82à¸\94ยà¸\97ัà¹\88วà¹\84à¸\9bà¹\83à¸\99à¸\81ารลà¸\9a
+'revdelete-reason-dropdown' => '*à¹\80หà¸\95ุà¸\9cลà¸\81ารลà¸\9aà¸\97ัà¹\88วà¹\84à¸\9b
** ละเมิดลิขสิทธิ์
** มีข้อมูลส่วนบุคคลที่ไม่เหมาะสม
-** มีà¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\97ีà¹\88à¸à¸²à¸\88สรà¹\89าà¸\87à¸\84วามà¹\80สียหาย',
+** มีà¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\97ีà¹\88à¸à¸²à¸\88หมิà¹\88à¸\99à¸\9bระมาà¸\97',
'revdelete-otherreason' => 'เหตุผลอื่นหรือเหตุผลเพิ่มเติม:',
'revdelete-reasonotherlist' => 'เหตุผลอื่น',
-'revdelete-edit-reasonlist' => 'à¹\81à¸\81à¹\89à¹\84à¸\82รายà¸\8aืà¹\88à¸à¹\80หà¸\95ุà¸\9cลà¹\83à¸\99การลบ',
+'revdelete-edit-reasonlist' => 'à¹\81à¸\81à¹\89à¹\84à¸\82à¹\80หà¸\95ุà¸\9cลการลบ',
'revdelete-offender' => 'ผู้เขียนของรุ่น:',
# Suppression log
'searchmenu-legend' => 'ตัวเลือกการค้นหา',
'searchmenu-exists' => "'''มีหน้าชื่อ \"[[:\$1]]\" บนวิกินี้'''",
'searchmenu-new' => "'''สร้างหน้า \"[[:\$1]]\" บนวิกินี้'''",
-'searchhelp-url' => 'Help:วิà¸\98ีà¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99',
+'searchhelp-url' => 'Help:สารà¸\9aัà¸\8d',
'searchmenu-prefix' => '[[Special:PrefixIndex/$1|สืบค้นหน้าที่มีคำขึ้นต้นเหล่านี้]]',
'searchprofile-articles' => 'หน้าบทความ',
'searchprofile-project' => 'วิธีใช้และหน้าโครงการ',
'mypreferences' => 'ตั้งค่าส่วนตัว',
'prefs-edits' => 'จำนวนการแก้ไข:',
'prefsnologin' => 'ไม่ได้ล็อกอิน',
-'prefsnologintext' => 'คุณต้อง<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ล็อกอิน]</span> ก่อนเพื่อที่จะตั้งค่าส่วนตัวได้',
+'prefsnologintext' => 'คุณต้อง<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ล็อกอิน]</span>ก่อนเพื่อตั้งค่าส่วนตัว',
'changepassword' => 'เปลี่ยนรหัสผ่าน',
'prefs-skin' => 'หน้าตา',
'skin-preview' => 'แสดงตัวอย่าง',
'recentchangesdays' => 'จำนวนวันที่แสดงในปรับปรุงล่าสุด:',
'recentchangesdays-max' => '(สูงสุด $1 {{PLURAL:$1|วัน|วัน}})',
'recentchangescount' => 'จำนวนการแก้ไขที่แสดงโดยปริยาย:',
-'prefs-help-recentchangescount' => 'นี่รวมไปถึงการแก้ไขล่าสุด, ประวิติของหน้า, และรายการแก้ไขอื่นๆ',
+'prefs-help-recentchangescount' => 'นี่รวมไปถึงการแก้ไขล่าสุด, ประวิติของหน้า, และรายการแก้ไขอื่น ๆ',
'prefs-help-watchlist-token' => 'การเติมช่องนี้ด้วยรหัสลับจะสร้าง RSS feed สำหรับรายการเฝ้าดูของคุณ
ผู้ใดที่รู้รหัสในช่องนี้จะสามารถดูรายการเฝ้าดูของคุณได้ ดังนั้นเลือกรหัสที่ปลอดภัย
นี่คือรหัสที่สุ่มเลือกขึ้นมาที่คุณสามารถใช้ได้: $1',
'yourlanguage' => 'ภาษา:',
'yourvariant' => 'อักษรต่างรูปของเนื้อหา:',
'yournick' => 'ลายเซ็น:',
-'prefs-help-signature' => 'à¸\84à¸à¸¡à¹\80มà¸\99à¸\95à¹\8cà¹\83à¸\99หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\84วรà¸\88ะเซ็นด้วย "<nowiki>~~~~</nowiki>" ซึ่งจะถูกแปลงเป็นลายเซ็นและลงวันที่เขียน',
+'prefs-help-signature' => 'à¸\84วามà¹\80หà¹\87à¸\99à¹\83à¸\99หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\84วรà¸\88ะลà¸\87ลายเซ็นด้วย "<nowiki>~~~~</nowiki>" ซึ่งจะถูกแปลงเป็นลายเซ็นและลงวันที่เขียน',
'badsig' => 'ลายเซ็นที่ใช้ผิดพลาด กรุณาตรวจสอบคำสั่งเอชทีเอ็มแอล',
'badsiglength' => 'ลายเซ็นของคุณยาวเกินไป ต้องมีความยาวไม่เกิน $1 {{PLURAL:$1|ตัวอักษร|ตัวอักษร}}',
'yourgender' => 'เพศ:',
'gender-unknown' => 'ไม่ระบุ',
'gender-male' => 'ชาย',
'gender-female' => 'หญิง',
-'prefs-help-gender' => 'à¹\80à¸\9bà¹\87à¸\99à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\80สริม: à¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¸\8bà¸à¸\9fà¸\95à¹\8cà¹\81วรà¹\8cสามารà¸\96à¹\81ยà¸\81à¹\81ยะà¹\80à¸\9eศà¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89 ข้อมูลนี้จะเป็นที่เปิดเผย',
+'prefs-help-gender' => 'à¹\80à¸\9bà¹\87à¸\99à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\80สริม: à¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¸\8bà¸à¸\9fà¸\95à¹\8cà¹\81วรà¹\8cà¹\81ยà¸\81à¹\81ยะà¹\80à¸\9eศà¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89 ข้อมูลนี้จะเป็นที่เปิดเผย',
'email' => 'อีเมล',
'prefs-help-realname' => 'ไม่จำเป็นต้องใส่ชื่อจริง โดยชื่อที่ใส่นั้นจะถูกใช้เพียงแค่แสดงผลงานที่คุณได้ร่วมสร้างไว้',
'prefs-help-email' => 'ที่อยู่อีเมลไม่จำเป็นต้องใส่ แต่จำเป็นสำหรับการตั้งรหัสผ่านใหม่เมื่อคุณลืมรหัสผ่านของคุณ',
'delete-warning-toobig' => 'หน้านี้มีประวัติการแก้ไขมากเกินกว่า $1 {{PLURAL:$1|รุ่น|รุ่น}} ซึ่งถือว่าเยอะมาก การลบหน้านี้อาจทำให้ {{SITENAME}} ได้รับความเสียหายอย่างที่ไม่เคยคาดคิดมาก่อน จึงได้เตือนไว้ ก่อนที่จะกระทำสิ่งนี้',
# Rollback
-'rollback' => 'à¸\96à¸à¸¢การแก้ไขกลับฉุกเฉิน',
-'rollback_short' => 'à¸\96à¸à¸¢กลับฉุกเฉิน',
+'rollback' => 'ยà¹\89à¸à¸\99การแก้ไขกลับฉุกเฉิน',
+'rollback_short' => 'ยà¹\89à¸à¸\99กลับฉุกเฉิน',
'rollbacklink' => 'ย้อนกลับฉุกเฉิน',
'rollbackfailed' => 'ย้อนไม่สำเร็จ',
'cantrollback' => 'ไม่สามารถย้อนการแก้ไขได้ เนื่องจากหน้านี้ไม่มีผู้แก้ไขรายอื่นอีก',
'unblocklink' => 'เลิกบล็อก',
'change-blocklink' => 'เปลี่ยนการบล็อก',
'contribslink' => 'เรื่องที่เขียน',
-'emaillink' => 'ส่งอีเมล์',
+'emaillink' => 'ส่งอีเมล',
'autoblocker' => 'ถูกบล็อกอัตโนมัติเนื่องจากหมายเลขไอพีของคุณตรงกับ "[[User:$1|$1]]" ถูกบล็อกกล่อนหน้านี้เนื่องจากสาเหตุ: "$2"',
'blocklogpage' => 'ปูมการบล็อก',
'blocklog-showlog' => 'ผู้ใช้นี้ถูกสกัดกั้นมาก่อน
<b>คำเตือน!</b>
การเปลี่ยนชื่อจะมีผลอย่างมากกับสถิติของหน้านิยมที่มีคนเข้าดูมาก ให้แน่ใจว่าต้องการเปลี่ยนชื่อในครั้งนี้",
-'movepagetext-noredirectfixer' => "à¸\81ารà¹\83à¸\8aà¹\89à¹\81à¸\9aà¸\9aà¸\9fà¸à¸£à¹\8cมà¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\99ีà¹\89จะเปลี่ยนชื่อหน้า ซึ่งจะทำให้ประวัติทั้งหมดย้ายไปยังชื่อใหม่
+'movepagetext-noredirectfixer' => "à¸\81ารà¹\83à¸\8aà¹\89à¹\81à¸\9aà¸\9aà¸\94à¹\89าà¸\99ลà¹\88าà¸\87จะเปลี่ยนชื่อหน้า ซึ่งจะทำให้ประวัติทั้งหมดย้ายไปยังชื่อใหม่
ชื่อเรื่องเก่าจะกลายเป็นหน้าเปลี่ยนทางไปยังชื่อเรื่องใหม่
-à¸à¸¢à¹\88าลืมตรวจสอบ[[Special:DoubleRedirects|หน้าเปลี่ยนทางซ้ำซ้อน]]หรือ[[Special:BrokenRedirects|หน้าเปลี่ยนทางที่เสีย]]
-à¸\84ุà¸\93à¸\88ะà¹\80à¸\9bà¹\87à¸\99à¸\9cูà¹\89รัà¸\9aà¸\9cิà¸\94à¸\8aà¸à¸\9aà¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¸\95à¹\88าà¸\87 à¹\86 à¸\8aีà¹\89à¹\84à¸\9bยัà¸\87à¸\97ีà¹\88à¸\97ีà¹\88à¸\9eวà¸\81มัà¸\99à¸\84วรà¸\88ะà¹\84à¸\9b
+à¹\83หà¹\89à¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88า ตรวจสอบ[[Special:DoubleRedirects|หน้าเปลี่ยนทางซ้ำซ้อน]]หรือ[[Special:BrokenRedirects|หน้าเปลี่ยนทางที่เสีย]]
+à¸\84ุà¸\93à¸\88ะà¹\80à¸\9bà¹\87à¸\99à¸\9cูà¹\89รัà¸\9aà¸\9cิà¸\94à¸\8aà¸à¸\9aà¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าลิà¸\87à¸\81à¹\8cà¸\95à¹\88าà¸\87 à¹\86 ยัà¸\87à¸\8aีà¹\89à¹\84à¸\9bยัà¸\87à¸\97ีà¹\88à¸\97ีà¹\88สมà¸\84วร
โปรดทราบว่าหน้าดังกล่าวจะ'''ไม่'''ถูกย้าย ถ้ามีหน้าที่ใช้ชื่อเรื่องใหม่อยู่แล้ว เว้นแต่เป็นหน้าว่างหรือหน้าเปลี่ยนทาง และไม่มีประวัติการแก้ไขในอดีต
-à¸\8bึà¹\88à¸\87หมายà¸\84วามวà¹\88า à¸\84ุà¸\93สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¸«à¸\99à¹\89าà¸\81ลัà¸\9aà¹\84à¸\9bà¹\80à¸\9bà¹\87à¸\99à¸\8aืà¹\88à¸à¹\80à¸\94ิมหากคุณทำผิดพลาด และคุณไม่สามารถเขียนทับหน้าที่มีอยู่แล้วได้
+à¸\8bึà¹\88à¸\87หมายà¸\84วามวà¹\88า à¸\84ุà¸\93สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¸«à¸\99à¹\89าà¸\81ลัà¸\9aà¹\80à¸\9bà¹\87à¸\99à¸\8aืà¹\88à¸à¹\80à¸\94ิมà¹\84à¸\94à¹\89หากคุณทำผิดพลาด และคุณไม่สามารถเขียนทับหน้าที่มีอยู่แล้วได้
'''คำเตือน!'''
สิ่งนี้อาจเป็นการเปลี่ยนแปลงที่รุนแรงและไม่คาดคิดสำหรับหน้าที่เป็นที่นิยม
-à¹\82à¸\9bรà¸\94à¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าà¸\84ุà¸\93à¹\80à¸\82à¹\89าà¹\83à¸\88à¹\83à¸\99à¸\9cลà¸\82à¸à¸\87à¸\81ารà¸\81ระà¸\97ำนี้ก่อนที่จะดำเนินการต่อไป",
+à¹\82à¸\9bรà¸\94à¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าà¸\84ุà¸\93à¹\80à¸\82à¹\89าà¹\83à¸\88à¸\96ึà¸\87à¸\9cลลัà¸\9eà¸\98à¹\8cนี้ก่อนที่จะดำเนินการต่อไป",
'movepagetalktext' => "หน้าพูดคุยของหน้านี้จะถูกเปลี่ยนชื่อตามไปด้วย '''เว้นเสียแต่:'''
-*หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¹\84มà¹\88วà¹\88าà¸\87มีà¹\81ลà¹\89วà¸\97ีà¹\88ชื่อใหม่ หรือ
-*à¹\84à¸\94à¹\89เลือกไม่ต้องการเปลี่ยนชื่อด้านล่าง
+*มีหà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\97ีà¹\88à¹\84มà¹\88วà¹\88าà¸\87à¸à¸¢à¸¹à¹\88à¹\81ลà¹\89วภายà¹\83à¸\95à¹\89ชื่อใหม่ หรือ
+*à¸\84ุà¸\93เลือกไม่ต้องการเปลี่ยนชื่อด้านล่าง
-ในกรณีนั้นให้เปลี่ยนชื่อหน้าเอง",
+ในกรณีนั้น คุณจำต้องย้ายหรือรวมหน้าเองหากต้องการ",
'movearticle' => 'เปลี่ยนชื่อ',
-'moveuserpage-warning' => "'''คำเตือน''' คุณกำลังจะย้ายหน้าผู้ใช้ โปรดทราบว่าหน้าผู้ใช้เท่านั้นที่จะถูกเปลี่ยนชื่อ แต่ผู้ใช้จะ'''ไม่ได้ถูกเปลี่ยนชื่อแต่อย่างใด'''",
+'moveuserpage-warning' => "'''คำเตือน''' คุณกำลังจะย้ายหน้าผู้ใช้ โปรดทราบว่าหน้าผู้ใช้เท่านั้นที่จะถูกเปลี่ยนชื่อ แต่ผู้ใช้จะ'''ไม่'''ถูกเปลี่ยนชื่อ",
'movenologin' => 'ไม่ได้ล็อกอิน',
'movenologintext' => 'ถ้าต้องการเปลี่ยนชื่อหน้านี้ ต้องลงทะเบียนและให้ทำการ[[Special:UserLogin|ล็อกอิน]]',
'movenotallowed' => 'คุณไม่ได้รับอนุญาตให้ทำการย้ายหน้าต่าง ๆ',
-'movenotallowedfile' => 'à¸\84ุà¸\93à¹\84มà¹\88มีสิà¸\97à¸\98ิà¹\8cà¸\97ีà¹\88à¸\88ะยà¹\89ายà¹\84à¸\9fลà¹\8c',
+'movenotallowedfile' => 'คุณไม่มีสิทธิที่จะย้ายไฟล์',
'cant-move-user-page' => 'คุณไม่มีสิทธิในการย้ายหน้าผู้ใช้ (แยกจากหน้าย่อย)',
'cant-move-to-user-page' => 'คุณไม่มีสิทธิในการย้ายหน้าใด ๆ ไปเป็นหน้าผู้ใช้ (ยกเว้นหน้าย่อยของผู้ใช้)',
'newtitle' => 'ชื่อใหม่',
'movepage-moved-noredirect' => 'หน้าเปลี่ยนทางไม่ได้ถูกสร้าง',
'articleexists' => 'หน้าที่ต้องการมีอยู่แล้ว หรือชื่อที่เลือกไม่ถูกต้อง กรุณาเลือกชื่อใหม่',
'cantmove-titleprotected' => 'คุณไม่สามารถเปลี่ยนชื่อหน้าเป็นชื่อนี้ได้ เนื่องจากชื่อใหม่นี้ได้รับการป้องกันไม่ให้สร้างใหม่',
-'talkexists' => "'''หà¸\99à¹\89าà¹\84à¸\94à¹\89à¸\96ูà¸\81à¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¹\80รียà¸\9aรà¹\89à¸à¸¢ à¹\81à¸\95à¹\88หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¹\84มà¹\88à¹\84à¸\94à¹\89à¸\96ูà¸\81à¹\80à¸\9bลีà¹\88ยà¸\99à¸\95ามà¹\84à¸\9bà¸\94à¹\89วยà¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81มีหà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\8bà¹\89ำà¹\81ลà¹\89ว à¹\83หà¹\89à¸\95รวà¸\88สà¸à¸\9aà¹\81ละย้ายเองอีกครั้ง'''",
+'talkexists' => "'''à¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¸«à¸\99à¹\89าสำà¹\80รà¹\87à¸\88 à¹\81à¸\95à¹\88หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¹\84มà¹\88สามารà¸\96à¸\96ูà¸\81à¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¸\84à¹\88à¸\97à¹\84à¸\94à¹\80 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81มีหà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¹\83à¸\99à¸\8aืà¹\88à¸à¹\83หมà¹\88à¹\81ลà¹\89ว à¹\82à¸\9bรà¸\94ย้ายเองอีกครั้ง'''",
'movedto' => 'เปลี่ยนชื่อเป็น',
'movetalk' => 'เปลี่ยนชื่อหน้าพูดคุยพร้อมกัน',
'move-subpages' => 'ย้ายหน้าย่อยทั้งหมด (มากถึง $1 หน้า)',
'imageinvalidfilename' => 'ชื่อไฟล์เป้าหมายไม่ถูกต้อง',
'fix-double-redirects' => 'อัปเดตหน้าเปลี่ยนทางทุกหน้าที่โอนไปยังชื่อเดิม',
'move-leave-redirect' => 'สร้างหน้าเปลี่ยนทางตามมา',
-'protectedpagemovewarning' => "'''คำเตือน: หน้านี้ถูกล็อก และแก้ไขได้เฉพาะผู้ดูแลระบบเท่านั้น'''
-บันทึกการป้องกันล่าสุดถูกแสดงไว้ด้านล่างเพื่อการอ้างอิง",
-'semiprotectedpagemovewarning' => "'''หมายà¹\80หà¸\95ุ:''' หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81 à¹\81ละà¹\81à¸\81à¹\89à¹\84à¸\82à¹\84à¸\94à¹\89à¹\80à¸\89à¸\9eาะà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88ลà¸\87à¸\97ะà¹\80à¸\9aียà¸\99à¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99
-รายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82ลà¹\88าสุà¸\94à¹\84à¸\94à¹\89à¸\96ูà¸\81à¹\81สà¸\94à¸\87à¹\84วà¹\89à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\99ีà¹\89à¹\80à¸\9eืà¹\88à¸à¸\81ารà¸à¹\89าà¸\87à¸à¸´à¸\87",
+'protectedpagemovewarning' => "'''คำเตือน:''' หน้านี้ถูกล็อก และเฉพาะผู้ใช้ที่มีสิทธิผู้ดูแลระบบเท่านั้นที่ย้ายได้
+บันทึกการป้องกันล่าสุดถูกแสดงไว้ด้านล่างเพื่อการอ้างอิง:",
+'semiprotectedpagemovewarning' => "'''หมายà¹\80หà¸\95ุ:''' หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81 à¹\81ละà¹\80à¸\89à¸\9eาะà¸\9cูà¹\89à¹\83à¸\8aà¹\89ลà¸\87à¸\97ะà¹\80à¸\9aียà¸\99à¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99à¸\97ีà¹\88ยà¹\89ายà¹\84à¸\94à¹\89
+รายà¸\81ารà¸\9bูมลà¹\88าสุà¸\94à¹\84à¸\94à¹\89à¸\96ูà¸\81à¹\81สà¸\94à¸\87à¹\84วà¹\89à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\99ีà¹\89à¹\80à¸\9eืà¹\88à¸à¸\81ารà¸à¹\89าà¸\87à¸à¸´à¸\87:",
'move-over-sharedrepo' => '== มีไฟล์เดิมปรากฏ ==
ไฟล์ [[:$1]] มีปรากฏเดิมอยู่แล้วในคลังเก็บภาพส่วนกลาง การย้ายไฟล์ที่มีชื่อเรื่องนี้อาจจะเป็นการเขียนทับไฟล์เดิมในคลังเก็บได้',
'file-exists-sharedrepo' => 'ชื่อไฟล์นี้มีปรากฏเดิมอยู่แล้วในคลังเก็บภาพส่วนกลาง
'tooltip-pt-anonlogin' => 'ไม่จำเป็นต้องล็อกอินในการแก้ไข แต่แนะนำอย่างยิ่งให้ล็อกอิน',
'tooltip-pt-logout' => 'ล็อกเอาต์',
'tooltip-ca-talk' => 'พูดคุยเกี่ยวกับเนื้อหา',
-'tooltip-ca-edit' => 'หà¸\99à¹\89าà¸\99ีà¹\89à¹\81à¸\81à¹\89à¹\84à¸\82à¹\84à¸\94à¹\89 à¸\81à¹\88à¸à¸\99à¸\97ำà¸\81ารà¸\9aัà¸\99à¸\97ึà¸\81à¹\83หà¹\89à¸\81รุà¸\93าà¸\81à¸\94à¸\9bุà¹\88มà¸\94ูà¸\95ัวà¸à¸¢à¹\88าà¸\87à¸\81à¹\88à¸à¸\99 à¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าà¹\84à¸\94à¹\89à¸\95ามà¸\97ีà¹\88à¸\95à¹\89à¸à¸\87à¸\81าร',
+'tooltip-ca-edit' => 'à¸\84ุà¸\93สามารà¸\96à¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\99ีà¹\89à¹\84à¸\94à¹\89 à¹\82à¸\9bรà¸\94à¹\83à¸\8aà¹\89à¸\9bุà¹\88มà¸\94ูà¸\95ัวà¸à¸¢à¹\88าà¸\87à¸\81à¹\88à¸à¸\99à¸\9aัà¸\99à¸\97ึà¸\81',
'tooltip-ca-addsection' => 'เริ่มหัวข้อย่อยใหม่',
'tooltip-ca-viewsource' => 'หน้านี้ถูกล็อก แต่ยังดูโค้ดได้',
'tooltip-ca-history' => 'รุ่นที่แล้วของหน้านี้',
'tooltip-search-go' => 'ตรงไปยังหน้าที่ตรงกับชื่อนี้ (ถ้ามี)',
'tooltip-search-fulltext' => 'ค้นหาหน้าที่มีข้อความนี้',
'tooltip-p-logo' => 'หน้าหลัก',
-'tooltip-n-mainpage' => 'à¹\81วะหน้าหลัก',
+'tooltip-n-mainpage' => 'à¹\80à¸\82à¹\89าสูà¹\88หน้าหลัก',
'tooltip-n-mainpage-description' => 'เข้าสู่หน้าหลัก',
'tooltip-n-portal' => 'เกี่ยวกับโครงการ สิ่งที่คุณทำได้ วิธีการค้นหา',
'tooltip-n-currentevents' => 'ค้นหาเหตุการณ์ปัจจุบัน',
'tooltip-t-upload' => 'อัปโหลดภาพหรือไฟล์',
'tooltip-t-specialpages' => 'แสดงรายการหน้าพิเศษ',
'tooltip-t-print' => 'หน้าที่แสดงผลพร้อมสำหรับพิมพ์ออกมา',
-'tooltip-t-permalink' => 'ลิà¸\87à¸\81à¹\8cà¸\96าวรมาà¸\97ีà¹\88à¹\80à¸\89à¸\9eาะรุà¹\88à¸\99à¸\99ีà¹\89à¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89',
+'tooltip-t-permalink' => 'ลิà¸\87à¸\81à¹\8cà¸\96าวรมาà¸\97ีà¹\88à¹\80à¸\89à¸\9eาะรุà¹\88à¸\99à¸\99ีà¹\89à¸\82à¸à¸\87หà¸\99à¹\89า',
'tooltip-ca-nstab-main' => 'ดูหน้าเนื้อหา',
'tooltip-ca-nstab-user' => 'ดูหน้าผู้ใช้',
'tooltip-ca-nstab-media' => 'ดูหน้าสื่อ ภาพ เพลง',
'tooltip-ca-nstab-image' => 'ดูหน้าภาพ',
'tooltip-ca-nstab-mediawiki' => 'ดูข้อความระบบ',
'tooltip-ca-nstab-template' => 'ดูหน้าแม่แบบ',
-'tooltip-ca-nstab-help' => 'à¸\94ูหà¸\99à¹\89าà¸\84ำà¸à¸\98ิà¸\9aาย',
+'tooltip-ca-nstab-help' => 'à¸\94ูหà¸\99à¹\89าวิà¸\98ีà¹\83à¸\8aà¹\89',
'tooltip-ca-nstab-category' => 'ดูหน้าหมวดหมู่',
'tooltip-minoredit' => 'กำหนดเป็นการแก้ไขเล็กน้อย',
'tooltip-save' => 'บันทึกการแก้ไข',
'exif-gpsareainformation' => 'ชื่อของพื้นที่จีพีเอส',
'exif-gpsdatestamp' => 'วันที่จีพีเอส',
'exif-gpsdifferential' => 'การปรับแค่ข้อแตกต่างจีพีเอส',
-'exif-keywords' => 'à¸\84ียà¹\8cà¹\80วิรà¹\8cà¸\94',
+'exif-keywords' => 'à¸\84ำสำà¸\84ัà¸\8d',
'exif-objectname' => 'ชื่อเรื่องสั้น',
'exif-headline' => 'พาดหัวข่าว',
'exif-contact' => 'ข้อมูลสำหรับติดต่อ',
'specialpages-group-spam' => 'เครื่องมือเกี่ยวกับสแปม',
# Special:BlankPage
-'blankpage' => 'หน้าว่างเปล่า',
+'blankpage' => 'หน้าว่าง',
'intentionallyblankpage' => 'หน้านี้ถูกทิ้งว่างโดยเจตนา',
# External image whitelist
'htmlform-required' => 'จำเป็นต้องกรอกข้อมูลนี้',
'htmlform-submit' => 'ส่งข้อมูล',
'htmlform-reset' => 'ยกเลิกการเปลื่ยนแปลง',
-'htmlform-selectorother-other' => 'อื่นๆ',
+'htmlform-selectorother-other' => 'อื่น ๆ',
# SQLite database support
'sqlite-has-fts' => 'รุ่น $1 พร้อมการสนับสนุนการค้นหาข้อความแบบเต็ม',
'feedback-close' => 'เสร็จสิ้น',
# API errors
-'api-error-mustbeloggedin' => 'à¸\81รุà¸\93าลà¸\87à¸\8aืà¹\88à¸à¹\80à¸\82à¹\89าà¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88à¸à¸\97ำà¸\81ารà¸à¸±à¸\9eโหลดไฟล์',
+'api-error-mustbeloggedin' => 'à¸\81รุà¸\93าลà¸\87à¸\8aืà¹\88à¸à¹\80à¸\82à¹\89าà¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88à¸à¸à¸±à¸\9bโหลดไฟล์',
);
'youhavenewmessages' => 'Ви отримали $1 ($2).',
'newmessageslink' => 'нові повідомлення',
'newmessagesdifflink' => 'остання зміна',
+'newmessageslinkplural' => '{{PLURAL:$1|нове повідомлення|нові повідомлення|нових повідомлень}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|остання зміна|останні зміни|останніх змін}}',
'youhavenewmessagesmulti' => 'Ви отримали нові повідомлення на $1',
'editsection' => 'ред.',
'editsection-brackets' => '[$1]',
'userpage-userdoesnotexist-view' => 'Обліковий запис користувача „$1“ не зареєстровано.',
'blocked-notice-logextract' => 'Цей користувач наразі заблокований.
Останній запис у журналі блокувань такий:',
-'clearyourcache' => "'''Увага:''' Ð\9fÑ\96Ñ\81лÑ\8f збеÑ\80еженнÑ\8f Ñ\81лÑ\96д оÑ\87иÑ\81Ñ\82иÑ\82и кеÑ\88 бÑ\80аÑ\83зеÑ\80а, щоб побачити зміни.
+'clearyourcache' => "'''Увага:''' Ð\9fÑ\96Ñ\81лÑ\8f збеÑ\80еженнÑ\8f Ñ\81лÑ\96д оÑ\87иÑ\81Ñ\82иÑ\82и кеÑ\88 оглÑ\8fдаÑ\87а, щоб побачити зміни.
* '''Firefox / Safari:''' тримайте ''Shift'', коли натискаєте ''Оновити'', або натисніть ''Ctrl-F5'' чи ''Ctrl-Shift-R'' (''⌘-R'' на Apple Mac)
* '''Google Chrome:''' натисніть ''Ctrl-Shift-R'' (''⌘-Shift-R'' на Apple Mac)
* '''Internet Explorer:''' тримайте ''Ctrl'', коли натискаєте ''Оновити'', або натисніть ''Ctrl-F5''
'tooltip-ca-move' => 'Перейменувати цю сторінку',
'tooltip-ca-watch' => 'Додати цю сторінку до вашого списку спостереження',
'tooltip-ca-unwatch' => 'Вилучити цю сторінку з вашого списку спостереження',
-'tooltip-search' => 'Шукати у {{GRAMMAR:locative|{{SITENAME}}}}',
+'tooltip-search' => 'Шукати',
'tooltip-search-go' => 'Перейти до сторінки, що має точно таку назву (якщо вона існує)',
'tooltip-search-fulltext' => 'Знайти сторінки, що містять зазначений текст',
'tooltip-p-logo' => 'Головна сторінка',
# Info page
'pageinfo-title' => 'Інформація про " $1 "',
-'pageinfo-header-edits' => 'РедагÑ\83ваннÑ\8f',
+'pageinfo-header-edits' => 'Ð\86Ñ\81Ñ\82оÑ\80Ñ\96Ñ\8f Ñ\80едагÑ\83ванÑ\8c',
'pageinfo-views' => 'Кількість переглядів',
'pageinfo-watchers' => 'Кількість спостерігачів',
-'pageinfo-edits' => 'Ð\9aількість редагувань',
-'pageinfo-authors' => 'Ð\9aількість унікальних авторів',
+'pageinfo-edits' => 'Ð\97агалÑ\8cна кількість редагувань',
+'pageinfo-authors' => 'Ð\97агалÑ\8cна кількість унікальних авторів',
# Skin names
'skinname-standard' => 'Стандартне',
<?php
/**
- * Replication-safe online upgrade script for log_id/log_deleted
+ * Replication-safe online upgrade for log_id/log_deleted fields.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
require( __DIR__ . '/../commandLine.inc' );
+/**
+ * Maintenance script that upgrade for log_id/log_deleted fields in a
+ * replication-safe way.
+ *
+ * @ingroup Maintenance
+ */
class UpdateLogging {
/**
-- action field, but only the type controls categorization.
log_type varbinary(10) NOT NULL default '',
log_action varbinary(10) NOT NULL default '',
-
+
-- Timestamp. Duh.
log_timestamp binary(14) NOT NULL default '19700101000000',
-
+
-- The user who performed this action; key to user_id
log_user int unsigned NOT NULL default 0,
-
+
-- Key to the page affected. Where a user is the target,
-- this will point to the user page.
log_namespace int NOT NULL default 0,
log_title varchar(255) binary NOT NULL default '',
-
+
-- Freeform text. Interpreted as edit history comments.
log_comment varchar(255) NOT NULL default '',
-
+
-- LF separated list of miscellaneous parameters
log_params blob NOT NULL,
$minTs = $this->dbw->selectField( $srcTable, 'MIN(log_timestamp)', false, __METHOD__ );
$minTsUnix = wfTimestamp( TS_UNIX, $minTs );
$numRowsCopied = 0;
-
+
while ( true ) {
$maxTs = $this->dbw->selectField( $srcTable, 'MAX(log_timestamp)', false, __METHOD__ );
$copyPos = $this->dbw->selectField( $dstTable, 'MAX(log_timestamp)', false, __METHOD__ );
$percent = ( $copyPosUnix - $minTsUnix ) / ( $maxTsUnix - $minTsUnix ) * 100;
}
printf( "%s %.2f%%\n", $copyPos, $percent );
-
+
# Handle all entries with timestamp equal to $copyPos
if ( $copyPos !== null ) {
$numRowsCopied += $this->copyExactMatch( $srcTable, $dstTable, $copyPos );
$dbr = wfGetDB( DB_SLAVE );
}
$this->maxCount = $dbr->selectField( $table, "MAX($field)", '', __METHOD__ );
- $this->startTime = wfTime();
+ $this->startTime = microtime( true );
$this->lastTime = $this->startTime;
$this->ID = getmypid();
}
function showReport() {
if ( $this->reporting ) {
$now = wfTimestamp( TS_DB );
- $nowts = wfTime();
- $deltaAll = wfTime() - $this->startTime;
- $deltaPart = wfTime() - $this->lastTime;
+ $nowts = microtime( true );
+ $deltaAll = $nowts - $this->startTime;
+ $deltaPart = $nowts - $this->lastTime;
$this->pageCountPart = $this->pageCount - $this->pageCountLast;
$this->revCountPart = $this->revCount - $this->revCountLast;
if ( $this->reporting ) {
$now = wfTimestamp( TS_DB );
- $nowts = wfTime();
- $deltaAll = wfTime() - $this->startTime;
- $deltaPart = wfTime() - $this->lastTime;
+ $nowts = microtime( true );
+ $deltaAll = $nowts - $this->startTime;
+ $deltaPart = $nowts - $this->lastTime;
$this->pageCountPart = $this->pageCount - $this->pageCountLast;
$this->revCountPart = $this->revCount - $this->revCountLast;
*/
/**
- * Create a doxygen subgroup of Maintenance for benchmarks
+ * Base code for benchmark scripts.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
require_once( __DIR__ . '/../Maintenance.php' );
+
+/**
+ * Base class for benchmark scripts.
+ *
+ * @ingroup Benchmark
+ */
abstract class Benchmarker extends Maintenance {
private $results;
$this->results[$bench_number] = array(
'function' => $bench['function'],
- 'arguments' => $bench['args'],
+ 'arguments' => $bench['args'],
'count' => $count,
'delta' => $delta,
'average' => $delta / $count,
<?php
/**
- * This come from r75429 message
+ * Benchmark HTTP request vs HTTPS request.
+ *
+ * This come from r75429 message.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
require_once( __DIR__ . '/Benchmarker.php' );
+
+/**
+ * Maintenance script that benchmarks HTTP request vs HTTPS request.
+ *
+ * @ingroup Benchmark
+ */
class bench_HTTP_HTTPS extends Benchmarker {
public function __construct() {
<?php
/**
+ * Benchmark SQL DELETE vs SQL TRUNCATE.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Benchmark
*/
require_once( __DIR__ . '/Benchmarker.php' );
+/**
+ * Maintenance script that benchmarks SQL DELETE vs SQL TRUNCATE.
+ *
+ * @ingroup Benchmark
+ */
class BenchmarkDeleteTruncate extends Benchmarker {
public function __construct() {
<?php
/**
+ * Benchmark if elseif... versus switch case.
+ *
* This come from r75429 message
*
* This program is free software; you can redistribute it and/or modify
*/
require_once( __DIR__ . '/Benchmarker.php' );
+
+/**
+ * Maintenance script that benchmark if elseif... versus switch case.
+ *
+ * @ingroup Maintenance
+ */
class bench_if_switch extends Benchmarker {
public function __construct() {
<?php
/**
+ * Benchmark for strtr() vs str_replace().
+ *
+ * This come from r75429 message.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Benchmark
*/
return str_replace( '_', ' ', $str );
}
+/**
+ * Maintenance script that benchmarks for strtr() vs str_replace().
+ *
+ * @ingroup Benchmark
+ */
class bench_strtr_str_replace extends Benchmarker {
public function __construct() {
<?php
/**
+ * Benchmark for using a regexp vs. mb_check_encoding to check for UTF-8 encoding.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup Benchmark
*/
require_once( __DIR__ . '/Benchmarker.php' );
/**
- * This little benchmark executes the regexp used in Language->checkTitleEncoding() and compares its execution time
- * against that of mb_check_encoding, if available.
+ * This little benchmark executes the regexp used in Language->checkTitleEncoding()
+ * and compares its execution time against that of mb_check_encoding, if available.
+ *
+ * @ingroup Benchmark
*/
class bench_utf8_title_check extends Benchmarker {
<?php
/**
- * This come from r75429 message
+ * Benchmark for wfIsWindows().
+ *
+ * This come from r75429 message.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
require_once( __DIR__ . '/Benchmarker.php' );
+
+/**
+ * Maintenance script that benchmarks wfIsWindows().
+ *
+ * @ingroup Benchmark
+ */
class bench_wfIsWindows extends Benchmarker {
public function __construct() {
<?php
/**
+ * Benchmark %MediaWiki hooks.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
require_once( __DIR__ . '/Benchmarker.php' );
+/**
+ * Maintenance script that benchmarks %MediaWiki hooks.
+ *
+ * @ingroup Benchmark
+ */
class BenchmarkHooks extends Benchmarker {
public function __construct() {
<?php
/**
- * Squid purge benchmark script
+ * Benchmark for Squid purge.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
require_once( __DIR__ . '/Benchmarker.php' );
+/**
+ * Maintenance script that benchmarks Squid purge.
+ *
+ * @ingroup Benchmark
+ */
class BenchmarkPurge extends Benchmarker {
public function __construct() {
$this->processed = 0;
$this->updated = 0;
$this->count = $count;
- $this->startTime = wfTime();
+ $this->startTime = microtime( true );
$this->table = $table;
}
$portion = $this->processed / $this->count;
$updateRate = $this->updated / $this->processed;
- $now = wfTime();
+ $now = microtime( true );
$delta = $now - $this->startTime;
$estimatedTotalTime = $delta / $portion;
$eta = $this->startTime + $estimatedTotalTime;
return;
}
- $this->startTime = wfTime();
+ $this->startTime = microtime( true );
if ( $this->getOption('dump') == '-' ) {
$source = new ImportStreamSource( $this->getStdin() );
$this->conclusions();
- $delta = wfTime() - $this->startTime;
+ $delta = microtime( true ) - $this->startTime;
$this->error( "Done {$this->count} revisions in " . round($delta, 2) . " seconds " );
if ($delta > 0)
$this->error( round($this->count / $delta, 2) . " pages/sec" );
function showReport() {
if ( !$this->mQuiet ) {
- $delta = wfTime() - $this->startTime;
+ $delta = microtime( true ) - $this->startTime;
if ( $delta ) {
$rate = sprintf( "%.2f", $this->pageCount / $delta );
$revrate = sprintf( "%.2f", $this->revCount / $delta );
}
function importFromHandle( $handle ) {
- $this->startTime = wfTime();
+ $this->startTime = microtime( true );
$source = new ImportStreamSource( $handle );
$importer = new WikiImporter( $source );
'version-entrypoints-api-php',
'version-entrypoints-load-php',
'ipb-default-expiry',
+ 'pageinfo-header',
+ 'pageinfo-footer',
);
/** Optional messages, which may be translated only if changed in the target language. */
'spam_deleting',
),
'info' => array(
+ 'pageinfo-header',
'pageinfo-title',
'pageinfo-header-basic',
'pageinfo-header-edits',
'pageinfo-magic-words',
'pageinfo-hidden-categories',
'pageinfo-templates',
+ 'pageinfo-footer',
),
'skin' => array(
'skinname-standard',
$dbw->update( 'user_groups',
array( 'ug_group' => $newGroup ),
array( 'ug_group' => $oldGroup,
- "ug_user BETWEEN $blockStart AND $blockEnd" )
+ "ug_user BETWEEN $blockStart AND $blockEnd" ),
+ __METHOD__,
+ array( 'IGNORE' )
+ );
+ $count += $dbw->affectedRows();
+ $dbw->delete( 'user_groups',
+ array( 'ug_group' => $oldGroup,
+ "ug_user BETWEEN $blockStart AND $blockEnd" ),
+ __METHOD__
);
$count += $dbw->affectedRows();
$dbw->commit( __METHOD__ );
$this->processed = 0;
$this->updated = 0;
$this->count = $count;
- $this->startTime = wfTime();
+ $this->startTime = microtime( true );
$this->table = $table;
}
$portion = $this->processed / $this->count;
$updateRate = $this->updated / $this->processed;
- $now = wfTime();
+ $now = microtime( true );
$delta = $now - $this->startTime;
$estimatedTotalTime = $delta / $portion;
$eta = $this->startTime + $estimatedTotalTime;
public function execute() {
$this->outputDirectory = $this->getOption( 'output-dir' );
$this->prefix = $this->getOption( 'prefix', 'wiki' );
- $this->startTime = wfTime();
+ $this->startTime = microtime( true );
if ( $this->hasOption( 'parser' ) ) {
global $wgParserConf;
$importer->doImport();
- $delta = wfTime() - $this->startTime;
+ $delta = microtime( true ) - $this->startTime;
$this->error( "Rendered {$this->count} pages in " . round($delta, 2) . " seconds " );
if ($delta > 0)
$this->error( round($this->count / $delta, 2) . " pages/sec" );
<?php
/**
- * Based on runJobs.php
- *
* Report number of jobs currently waiting in master database.
*
+ * Based on runJobs.php
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @file
* @ingroup Maintenance
* @author Tim Starling
* @author Antoine Musso
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script that reports the number of jobs currently waiting
+ * in master database.
+ *
+ * @ingroup Maintenance
+ */
class ShowJobs extends Maintenance {
public function __construct() {
parent::__construct();
<?php
/**
- * Maintenance script to show the cached statistics.
+ * Show the cached statistics.
* Give out the same output as [[Special:Statistics]]
*
* This program is free software; you can redistribute it and/or modify
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @file
* @ingroup Maintenance
* @author Antoine Musso <hashar at free dot fr>
* Based on initStats.php by:
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script to show the cached statistics.
+ *
+ * @ingroup Maintenance
+ */
class ShowStats extends Maintenance {
public function __construct() {
parent::__construct();
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @file
* @ingroup Maintenance
*/
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script that sends SQL queries from the specified file to the database.
+ *
+ * @ingroup Maintenance
+ */
class MwSql extends Maintenance {
public function __construct() {
parent::__construct();
/**
* This class contains code common to different SQLite-related maintenance scripts
+ *
+ * @ingroup Maintenance
*/
class Sqlite {
$db->close();
return true;
}
- };
\ No newline at end of file
+ };
<?php
/**
- * Performs some operations specific to SQLite database backend
+ * Performs some operations specific to SQLite database backend.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @file
* @ingroup Maintenance
*/
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script that performs some operations specific to SQLite database backend.
+ *
+ * @ingroup Maintenance
+ */
class SqliteMaintenance extends Maintenance {
public function __construct() {
parent::__construct();
<?php
/**
- * Show statistics from the cache
+ * Show statistics from the cache.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @file
* @ingroup Maintenance
*/
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script that shows statistics from the cache.
+ *
+ * @ingroup Maintenance
+ */
class CacheStats extends Maintenance {
public function __construct() {
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @file
* @ingroup Maintenance
*/
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script that syncs one file backend to another based on
+ * the journal of later.
+ *
+ * @ingroup Maintenance
+ */
class SyncFileBackend extends Maintenance {
public function __construct() {
parent::__construct();
$wgUseMasterForMaintenance = true;
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script to run database schema updates.
+ *
+ * @ingroup Maintenance
+ */
class UpdateMediaWiki extends Maintenance {
function __construct() {
<?php
/**
- * Maintenance script to provide a better count of the number of articles
- * and update the site statistics table, if desired
+ * Provide a better count of the number of articles
+ * and update the site statistics table, if desired.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script to provide a better count of the number of articles
+ * and update the site statistics table, if desired.
+ *
+ * @ingroup Maintenance
+ */
class UpdateArticleCount extends Maintenance {
public function __construct() {
<?php
/**
- * Script will find all rows in the categorylinks table whose collation is
- * out-of-date (cl_collation != $wgCategoryCollation) and repopulate cl_sortkey
+ * Find all rows in the categorylinks table whose collation is out-of-date
+ * (cl_collation != $wgCategoryCollation) and repopulate cl_sortkey
* using the page title and cl_sortkey_prefix.
*
* This program is free software; you can redistribute it and/or modify
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script that will find all rows in the categorylinks table
+ * whose collation is out-of-date.
+ *
+ * @ingroup Maintenance
+ */
class UpdateCollation extends Maintenance {
const BATCH_SIZE = 50; // Number of rows to process in one batch
const SYNC_INTERVAL = 20; // Wait for slaves after this many batches
'collation, though, so it may miss out-of-date rows with a different, ' .
'even older collation.', false, true );
$this->addOption( 'target-collation', 'Set this to the new collation type to ' .
- 'use instead of $wgCategoryCollation. Usually you should not use this, ' .
- 'you should just update $wgCategoryCollation in LocalSettings.php.',
+ 'use instead of $wgCategoryCollation. Usually you should not use this, ' .
+ 'you should just update $wgCategoryCollation in LocalSettings.php.',
false, true );
$this->addOption( 'dry-run', 'Don\'t actually change the collations, just ' .
'compile statistics.' );
<?php
/**
- * Script to normalize double-byte latin UTF-8 characters
+ * Normalize double-byte latin UTF-8 characters
*
* Usage: php updateDoubleWidthSearch.php
*
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script to normalize double-byte latin UTF-8 characters.
+ *
+ * @ingroup Maintenance
+ */
class UpdateDoubleWidthSearch extends Maintenance {
public function __construct() {
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script that updates page_restrictions table from
+ * old page_restriction column.
+ *
+ * @ingroup Maintenance
+ */
class UpdateRestrictions extends Maintenance {
public function __construct() {
parent::__construct();
<?php
/**
- * Script for periodic off-peak updating of the search index
+ * Periodic off-peak updating of the search index.
*
* Usage: php updateSearchIndex.php [-s START] [-e END] [-p POSFILE] [-l LOCKTIME] [-q]
* Where START is the starting timestamp
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script for periodic off-peak updating of the search index.
+ *
+ * @ingroup Maintenance
+ */
class UpdateSearchIndex extends Maintenance {
public function __construct() {
<?php
/**
- * Run this script periodically if you have miser mode enabled, to refresh the
- * caches
+ * Update for cached special pages.
+ * Run this script periodically if you have miser mode enabled.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script to update cached special pages.
+ *
+ * @ingroup Maintenance
+ */
class UpdateSpecialPages extends Maintenance {
public function __construct() {
parent::__construct();
$this->chunkSize = $chunksize;
$this->chunkFinal = $final;
$this->chunkCount = 0;
- $this->chunkStartTime = wfTime();
+ $this->chunkStartTime = microtime( true );
$this->chunkOptions = array( 'IGNORE' );
$this->chunkTable = $table;
$this->chunkFunction = $fname;
$this->insertChunk( $chunk );
$this->chunkCount += count( $chunk );
- $now = wfTime();
+ $now = microtime( true );
$delta = $now - $this->chunkStartTime;
$rate = $this->chunkCount / $delta;
<?php
/**
- * Script to change users skins on the fly.
- * This is for at least MediaWiki 1.10alpha (r19611) and have not been
- * tested with previous versions. It should probably work with 1.7+.
+ * Script to change users preferences on the fly.
*
* Made on an original idea by Fooey (freenode)
*
<?php
/**
- * Script to wait until slave lag goes under a certain value.
+ * Wait until slave lag goes under a certain value.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
require_once( __DIR__ . '/Maintenance.php' );
+/**
+ * Maintenance script to wait until slave lag goes under a certain value.
+ *
+ * @ingroup Maintenance
+ */
class WaitForSlave extends Maintenance {
public function __construct() {
$this->addArg( 'maxlag', 'How long to wait for the slaves, default 10 seconds', false );
),
'jquery.highlightText' => array(
'scripts' => 'resources/jquery/jquery.highlightText.js',
+ 'dependencies' => 'jquery.mwExtension',
),
'jquery.hoverIntent' => array(
'scripts' => 'resources/jquery/jquery.hoverIntent.js',
'styles' => 'resources/jquery/jquery.makeCollapsible.css',
'messages' => array( 'collapsible-expand', 'collapsible-collapse' ),
),
- 'jquery.messageBox' => array(
- 'scripts' => 'resources/jquery/jquery.messageBox.js',
- 'styles' => 'resources/jquery/jquery.messageBox.css',
- ),
'jquery.mockjax' => array(
'scripts' => 'resources/jquery/jquery.mockjax.js',
),
'scripts' => 'resources/jquery/jquery.tablesorter.js',
'styles' => 'resources/jquery/jquery.tablesorter.css',
'messages' => array( 'sort-descending', 'sort-ascending' ),
+ 'dependencies' => 'jquery.mwExtension',
),
'jquery.textSelection' => array(
'scripts' => 'resources/jquery/jquery.textSelection.js',
'mediawiki.htmlform' => array(
'scripts' => 'resources/mediawiki/mediawiki.htmlform.js',
),
+ 'mediawiki.notification' => array(
+ 'styles' => 'resources/mediawiki/mediawiki.notification.css',
+ 'scripts' => 'resources/mediawiki/mediawiki.notification.js',
+ 'dependencies' => array(
+ 'mediawiki.page.startup',
+ ),
+ ),
+ 'mediawiki.notify' => array(
+ 'scripts' => 'resources/mediawiki/mediawiki.notify.js',
+ ),
'mediawiki.Title' => array(
'scripts' => 'resources/mediawiki/mediawiki.Title.js',
'dependencies' => 'mediawiki.util',
'dependencies' => array(
'jquery.client',
'jquery.cookie',
- 'jquery.messageBox',
'jquery.mwExtension',
+ 'mediawiki.notify',
),
'messages' => array( 'showtoc', 'hidetoc' ),
'position' => 'top', // For $wgPreloadJavaScriptMwUtil
'dependencies' => array(
'mediawiki.page.startup',
'mediawiki.api.watch',
- 'mediawiki.util'
+ 'mediawiki.util',
+ 'mediawiki.notify',
+ 'jquery.mwExtension',
),
'messages' => array(
'watch',
'scripts' => 'common/preview.js',
'remoteBasePath' => $GLOBALS['wgStylePath'],
'localBasePath' => $GLOBALS['wgStyleDirectory'],
- 'dependencies' => 'mediawiki.legacy.wikibits',
+ 'dependencies' => array(
+ 'mediawiki.legacy.wikibits',
+ 'jquery.form',
+ )
),
'mediawiki.legacy.protect' => array(
'scripts' => 'common/protect.js',
/*!
- * jQuery UI Effects Blind 1.8.22
+ * jQuery UI Effects Blind 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Bounce 1.8.22
+ * jQuery UI Effects Bounce 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Clip 1.8.22
+ * jQuery UI Effects Clip 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects 1.8.22
+ * jQuery UI Effects 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/******************************************************************************/
$.extend($.effects, {
- version: "1.8.22",
+ version: "1.8.23",
// Saves a set of properties in a data storage
save: function(element, set) {
/*********************************** EASING ***********************************/
/******************************************************************************/
-/*
- * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
- *
- * Uses the built in easing capabilities added In jQuery 1.1
- * to offer multiple easing options
- *
- * TERMS OF USE - jQuery Easing
- *
- * Open source under the BSD License.
- *
- * Copyright 2008 George McGinley Smith
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * Neither the name of the author nor the names of contributors may be used to endorse
- * or promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
-*/
+// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
-// t: current time, b: begInnIng value, c: change In value, d: duration
-$.easing.jswing = $.easing.swing;
+var baseEasings = {};
-$.extend($.easing,
-{
- def: 'easeOutQuad',
- swing: function (x, t, b, c, d) {
- //alert($.easing.default);
- return $.easing[$.easing.def](x, t, b, c, d);
- },
- easeInQuad: function (x, t, b, c, d) {
- return c*(t/=d)*t + b;
- },
- easeOutQuad: function (x, t, b, c, d) {
- return -c *(t/=d)*(t-2) + b;
- },
- easeInOutQuad: function (x, t, b, c, d) {
- if ((t/=d/2) < 1) return c/2*t*t + b;
- return -c/2 * ((--t)*(t-2) - 1) + b;
- },
- easeInCubic: function (x, t, b, c, d) {
- return c*(t/=d)*t*t + b;
- },
- easeOutCubic: function (x, t, b, c, d) {
- return c*((t=t/d-1)*t*t + 1) + b;
- },
- easeInOutCubic: function (x, t, b, c, d) {
- if ((t/=d/2) < 1) return c/2*t*t*t + b;
- return c/2*((t-=2)*t*t + 2) + b;
- },
- easeInQuart: function (x, t, b, c, d) {
- return c*(t/=d)*t*t*t + b;
- },
- easeOutQuart: function (x, t, b, c, d) {
- return -c * ((t=t/d-1)*t*t*t - 1) + b;
- },
- easeInOutQuart: function (x, t, b, c, d) {
- if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
- return -c/2 * ((t-=2)*t*t*t - 2) + b;
- },
- easeInQuint: function (x, t, b, c, d) {
- return c*(t/=d)*t*t*t*t + b;
- },
- easeOutQuint: function (x, t, b, c, d) {
- return c*((t=t/d-1)*t*t*t*t + 1) + b;
- },
- easeInOutQuint: function (x, t, b, c, d) {
- if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
- return c/2*((t-=2)*t*t*t*t + 2) + b;
- },
- easeInSine: function (x, t, b, c, d) {
- return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
- },
- easeOutSine: function (x, t, b, c, d) {
- return c * Math.sin(t/d * (Math.PI/2)) + b;
- },
- easeInOutSine: function (x, t, b, c, d) {
- return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
- },
- easeInExpo: function (x, t, b, c, d) {
- return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
- },
- easeOutExpo: function (x, t, b, c, d) {
- return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
- },
- easeInOutExpo: function (x, t, b, c, d) {
- if (t==0) return b;
- if (t==d) return b+c;
- if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
- return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
- },
- easeInCirc: function (x, t, b, c, d) {
- return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
- },
- easeOutCirc: function (x, t, b, c, d) {
- return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
- },
- easeInOutCirc: function (x, t, b, c, d) {
- if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
- return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
- },
- easeInElastic: function (x, t, b, c, d) {
- var s=1.70158;var p=0;var a=c;
- if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
- if (a < Math.abs(c)) { a=c; var s=p/4; }
- else var s = p/(2*Math.PI) * Math.asin (c/a);
- return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
- },
- easeOutElastic: function (x, t, b, c, d) {
- var s=1.70158;var p=0;var a=c;
- if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
- if (a < Math.abs(c)) { a=c; var s=p/4; }
- else var s = p/(2*Math.PI) * Math.asin (c/a);
- return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
- },
- easeInOutElastic: function (x, t, b, c, d) {
- var s=1.70158;var p=0;var a=c;
- if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
- if (a < Math.abs(c)) { a=c; var s=p/4; }
- else var s = p/(2*Math.PI) * Math.asin (c/a);
- if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
- return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
- },
- easeInBack: function (x, t, b, c, d, s) {
- if (s == undefined) s = 1.70158;
- return c*(t/=d)*t*((s+1)*t - s) + b;
- },
- easeOutBack: function (x, t, b, c, d, s) {
- if (s == undefined) s = 1.70158;
- return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
+ baseEasings[ name ] = function( p ) {
+ return Math.pow( p, i + 2 );
+ };
+});
+
+$.extend( baseEasings, {
+ Sine: function ( p ) {
+ return 1 - Math.cos( p * Math.PI / 2 );
},
- easeInOutBack: function (x, t, b, c, d, s) {
- if (s == undefined) s = 1.70158;
- if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
- return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+ Circ: function ( p ) {
+ return 1 - Math.sqrt( 1 - p * p );
},
- easeInBounce: function (x, t, b, c, d) {
- return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
+ Elastic: function( p ) {
+ return p === 0 || p === 1 ? p :
+ -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
},
- easeOutBounce: function (x, t, b, c, d) {
- if ((t/=d) < (1/2.75)) {
- return c*(7.5625*t*t) + b;
- } else if (t < (2/2.75)) {
- return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
- } else if (t < (2.5/2.75)) {
- return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
- } else {
- return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
- }
+ Back: function( p ) {
+ return p * p * ( 3 * p - 2 );
},
- easeInOutBounce: function (x, t, b, c, d) {
- if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
- return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
+ Bounce: function ( p ) {
+ var pow2,
+ bounce = 4;
+
+ while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
+ return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
}
});
-/*
- *
- * TERMS OF USE - EASING EQUATIONS
- *
- * Open source under the BSD License.
- *
- * Copyright 2001 Robert Penner
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * Neither the name of the author nor the names of contributors may be used to endorse
- * or promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
+$.each( baseEasings, function( name, easeIn ) {
+ $.easing[ "easeIn" + name ] = easeIn;
+ $.easing[ "easeOut" + name ] = function( p ) {
+ return 1 - easeIn( 1 - p );
+ };
+ $.easing[ "easeInOut" + name ] = function( p ) {
+ return p < .5 ?
+ easeIn( p * 2 ) / 2 :
+ easeIn( p * -2 + 2 ) / -2 + 1;
+ };
+});
})(jQuery);
/*!
- * jQuery UI Effects Drop 1.8.22
+ * jQuery UI Effects Drop 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Explode 1.8.22
+ * jQuery UI Effects Explode 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Fade 1.8.22
+ * jQuery UI Effects Fade 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Fold 1.8.22
+ * jQuery UI Effects Fold 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Highlight 1.8.22
+ * jQuery UI Effects Highlight 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Pulsate 1.8.22
+ * jQuery UI Effects Pulsate 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Scale 1.8.22
+ * jQuery UI Effects Scale 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Shake 1.8.22
+ * jQuery UI Effects Shake 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Slide 1.8.22
+ * jQuery UI Effects Slide 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Transfer 1.8.22
+ * jQuery UI Effects Transfer 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Accordion 1.8.22
+ * jQuery UI Accordion 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.accordion, {
- version: "1.8.22",
+ version: "1.8.23",
animations: {
slide: function( options, additions ) {
options = $.extend({
/*!
- * jQuery UI Autocomplete 1.8.22
+ * jQuery UI Autocomplete 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Button 1.8.22
+ * jQuery UI Button 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI 1.8.22
+ * jQuery UI 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
}
$.extend( $.ui, {
- version: "1.8.22",
+ version: "1.8.23",
keyCode: {
ALT: 18,
/*!
- * jQuery UI Datepicker 1.8.22
+ * jQuery UI Datepicker 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
*/
(function( $, undefined ) {
-$.extend($.ui, { datepicker: { version: "1.8.22" } });
+$.extend($.ui, { datepicker: { version: "1.8.23" } });
var PROP_NAME = 'datepicker';
var dpuuid = new Date().getTime();
*/
_attachHandlers: function(inst) {
var stepMonths = this._get(inst, 'stepMonths');
- var id = '#' + inst.id;
+ var id = '#' + inst.id.replace( /\\\\/g, "\\" );
inst.dpDiv.find('[data-handler]').map(function () {
var handler = {
prev: function () {
$.datepicker = new Datepicker(); // singleton instance
$.datepicker.initialized = false;
$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "1.8.22";
+$.datepicker.version = "1.8.23";
// Workaround for #4055
// Add another global to avoid noConflict issues with inline event handlers
/*!
- * jQuery UI Dialog 1.8.22
+ * jQuery UI Dialog 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
maxWidth: true,
minHeight: true,
minWidth: true
- },
- // support for jQuery 1.3.2 - handle common attrFn methods for dialog
- attrFn = $.attrFn || {
- val: true,
- css: true,
- html: true,
- text: true,
- data: true,
- width: true,
- height: true,
- offset: true,
- click: true
};
$.widget("ui.dialog", {
if ( key === "click" ) {
return;
}
- if ( key in attrFn ) {
+ if ( key in button ) {
button[ key ]( value );
} else {
button.attr( key, value );
});
$.extend($.ui.dialog, {
- version: "1.8.22",
+ version: "1.8.23",
uuid: 0,
maxZ: 0,
/*!
- * jQuery UI Draggable 1.8.22
+ * jQuery UI Draggable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.draggable, {
- version: "1.8.22"
+ version: "1.8.23"
});
$.ui.plugin.add("draggable", "connectToSortable", {
/*!
- * jQuery UI Droppable 1.8.22
+ * jQuery UI Droppable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.droppable, {
- version: "1.8.22"
+ version: "1.8.23"
});
$.ui.intersect = function(draggable, droppable, toleranceMode) {
/*!
- * jQuery UI Mouse 1.8.22
+ * jQuery UI Mouse 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
// other instances of mouse
_mouseDestroy: function() {
this.element.unbind('.'+this.widgetName);
- $(document)
- .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
- .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+ if ( this._mouseMoveDelegate ) {
+ $(document)
+ .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+ }
},
_mouseDown: function(event) {
/*!
- * jQuery UI Position 1.8.22
+ * jQuery UI Position 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
};
}
+// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
+if ( !$.curCSS ) {
+ $.curCSS = $.css;
+}
+
// fraction support test (older versions of jQuery don't support fractions)
(function () {
var body = document.getElementsByTagName( "body" )[ 0 ],
/*!
- * jQuery UI Progressbar 1.8.22
+ * jQuery UI Progressbar 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.progressbar, {
- version: "1.8.22"
+ version: "1.8.23"
});
})( jQuery );
/*!
- * jQuery UI Resizable 1.8.22
+ * jQuery UI Resizable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.resizable, {
- version: "1.8.22"
+ version: "1.8.23"
});
/*
/*!
- * jQuery UI Selectable 1.8.22
+ * jQuery UI Selectable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.selectable, {
- version: "1.8.22"
+ version: "1.8.23"
});
})(jQuery);
/*!
- * jQuery UI Slider 1.8.22
+ * jQuery UI Slider 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.slider, {
- version: "1.8.22"
+ version: "1.8.23"
});
}(jQuery));
/*!
- * jQuery UI Sortable 1.8.22
+ * jQuery UI Sortable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.sortable, {
- version: "1.8.22"
+ version: "1.8.23"
});
})(jQuery);
/*!
- * jQuery UI Tabs 1.8.22
+ * jQuery UI Tabs 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.tabs, {
- version: "1.8.22"
+ version: "1.8.23"
});
/*
/*!
- * jQuery UI Widget 1.8.22
+ * jQuery UI Widget 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Accordion 1.8.22
+ * jQuery UI Accordion 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Autocomplete 1.8.22
+ * jQuery UI Autocomplete 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/*
- * jQuery UI Menu 1.8.22
+ * jQuery UI Menu 1.8.23
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Button 1.8.22
+ * jQuery UI Button 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI CSS Framework 1.8.22
+ * jQuery UI CSS Framework 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Datepicker 1.8.22
+ * jQuery UI Datepicker 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Dialog 1.8.22
+ * jQuery UI Dialog 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Progressbar 1.8.22
+ * jQuery UI Progressbar 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Resizable 1.8.22
+ * jQuery UI Resizable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Selectable 1.8.22
+ * jQuery UI Selectable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Slider 1.8.22
+ * jQuery UI Slider 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Tabs 1.8.22
+ * jQuery UI Tabs 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI CSS Framework 1.8.22
+ * jQuery UI CSS Framework 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* </script>
*
*/
-
( function ( $ ) {
$.fn.arrowSteps = function () {
+ var $steps, width, arrowWidth;
this.addClass( 'arrowSteps' );
- var $steps = this.find( 'li' );
+ $steps = this.find( 'li' );
- var width = parseInt( 100 / $steps.length, 10 );
+ width = parseInt( 100 / $steps.length, 10 );
$steps.css( 'width', width + '%' );
// every step except the last one has an arrow at the right hand side. Also add in the padding
// for the calculated arrow width.
- var arrowWidth = parseInt( this.outerHeight(), 10 );
+ arrowWidth = parseInt( this.outerHeight(), 10 );
$steps.filter( ':not(:last-child)' ).addClass( 'arrow' )
.find( 'div' ).css( 'padding-right', arrowWidth.toString() + 'px' );
};
$.fn.arrowStepsHighlight = function ( selector ) {
- var $steps = this.data( 'arrowSteps' );
- var $previous;
+ var $previous,
+ $steps = this.data( 'arrowSteps' );
$.each( $steps, function ( i, step ) {
var $step = $( step );
if ( $step.is( selector ) ) {
*/
( function ( $ ) {
-// Cache ellipsed substrings for every string-width-position combination
-var cache = { };
-// Use a separate cache when match highlighting is enabled
-var matchTextCache = { };
+var
+ // Cache ellipsed substrings for every string-width-position combination
+ cache = { },
+
+ // Use a separate cache when match highlighting is enabled
+ matchTextCache = { };
$.fn.autoEllipsis = function ( options ) {
options = $.extend( {
$(this).each( function () {
var $container, $trimmableText,
text, trimmableText, w, pw,
- l, r, i, side,
+ l, r, i, side, m,
$el = $(this);
if ( options.restoreText ) {
if ( !$el.data( 'autoEllipsis.originalText' ) ) {
l = 0;
r = trimmableText.length;
do {
- var m = Math.ceil( ( l + r ) / 2 );
+ m = Math.ceil( ( l + r ) / 2 );
$trimmableText.text( trimmableText.substr( 0, m ) + '...' );
if ( $trimmableText.width() + pw > w ) {
// Text is too long
min-width: 8px;
height: 14px;
border: 1px solid white;
- border-radius: 8px;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
- box-shadow: 0px 1px 4px #ccc;
+ border-radius: 8px;
-moz-box-shadow: 0px 1px 4px #ccc;
-webkit-box-shadow: 0px 1px 4px #ccc;
+ box-shadow: 0px 1px 4px #ccc;
background-color: #b60a00;
- background-image: linear-gradient(bottom, #a70802 0%, #cf0e00 100%);
background-image: -o-linear-gradient(bottom, #a70802 0%, #cf0e00 100%);
background-image: -moz-linear-gradient(bottom, #a70802 0%, #cf0e00 100%);
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #a70802), color-stop(1, #cf0e00));
background-image: -webkit-linear-gradient(bottom, #a70802 0%, #cf0e00 100%);
background-image: -ms-linear-gradient(bottom, #a70802 0%, #cf0e00 100%);
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #a70802), color-stop(1, #cf0e00));
+ background-image: linear-gradient(bottom, #a70802 0%, #cf0e00 100%);
padding: 0 3px;
text-align: center;
}
-// Badger v1.0 by Daniel Raftery
-// http://thrivingkings.com/badger
-// http://twitter.com/ThrivingKings
-// Modified by Ryan Kaldari <rkaldari@wikimedia.org>
+/**
+ * jQuery Badge plugin
+ *
+ * Based on Badger plugin by Daniel Raftery (http://thrivingkings.com/badger).
+ *
+ * @license MIT
+ */
/**
+ * @author Ryan Kaldari <rkaldari@wikimedia.org>, 2012
+ * @author Andrew Garrett <agarrett@wikimedia.org>, 2012
+ * @author Marius Hoch <hoo@online.de>, 2012
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
*
* This program is distributed WITHOUT ANY WARRANTY.
*/
+( function ( $ ) {
-(function( $ ) {
- $.fn.badge = function( badge, options ) {
- var existingBadge = this.find( '.mw-badge' );
- options = $.extend( {}, options );
+ /**
+ * Allows you to put a numeric "badge" on an item on the page.
+ * See mediawiki.org/wiki/ResourceLoader/Default_modules#jQuery.badge
+ *
+ * @param {string|number} badgeCount An explicit number, or "+n"/ "-n"
+ * to modify the existing value. If the new value is equal or lower than 0,
+ * any existing badge will be removed. The badge container will be appended
+ * to the selected element(s).
+ * @param {Object} options Optional parameters specified below
+ * type: 'inline' or 'overlay' (default)
+ * callback: will be called with the number now shown on the badge as a parameter
+ */
+ $.fn.badge = function ( badgeCount, options ) {
+ var $badge,
+ oldBadgeCount,
+ newBadgeCount,
+ $existingBadge = this.find( '.mw-badge' );
- badge = String(badge);
- if ( badge.charAt(0) === '+' ) {
- if ( existingBadge.length > 0 ) {
- oldBadge = existingBadge.text();
- badge = Math.round( Number( oldBadge ) + Number( badge.substr(1) ) );
- } else {
- badge = badge.substr(1);
- }
- } else if ( badge.charAt(0) === '-' ) {
- if ( existingBadge.length > 0 ) {
- oldBadge = existingBadge.text();
- badge = Math.round( Number( oldBadge ) - Number( badge.substr(1) ) );
+ options = $.extend( { type : 'overlay' }, options );
+
+ // If there is no existing badge, this will give an empty string
+ oldBadgeCount = Number( $existingBadge.text() );
+ if ( isNaN( oldBadgeCount ) ) {
+ oldBadgeCount = 0;
+ }
+
+ // If badgeCount is a number, use that as the new badge
+ if ( typeof badgeCount === 'number' ) {
+ newBadgeCount = badgeCount;
+ } else if ( typeof badgeCount === 'string' ) {
+ // If badgeCount is "+x", add x to the old badge
+ if ( badgeCount.charAt(0) === '+' ) {
+ newBadgeCount = oldBadgeCount + Number( badgeCount.substr(1) );
+ // If badgeCount is "-x", subtract x from the old badge
+ } else if ( badgeCount.charAt(0) === '-' ) {
+ newBadgeCount = oldBadgeCount - Number( badgeCount.substr(1) );
+ // If badgeCount can be converted into a number, convert it
+ } else if ( !isNaN( Number( badgeCount ) ) ) {
+ newBadgeCount = Number( badgeCount );
} else {
- badge = 0;
+ newBadgeCount = 0;
}
+ // Other types are not supported, fall back to 0.
+ } else {
+ newBadgeCount = 0;
}
- if ( Number(badge) <= 0 ) {
- // Clear any existing badge
- existingBadge.remove();
+ // Badge count must be a whole number
+ newBadgeCount = Math.round( newBadgeCount );
+
+ if ( newBadgeCount <= 0 ) {
+ // Badges should only exist for values > 0.
+ $existingBadge.remove();
} else {
// Don't add duplicates
- var $badge = existingBadge;
- if ( existingBadge.length > 0 ) {
- this.find( '.mw-badge-content' ).text( badge );
+ if ( $existingBadge.length ) {
+ $badge = $existingBadge;
+ // Insert the new count into the badge
+ this.find( '.mw-badge-content' ).text( newBadgeCount );
} else {
- $badge = $('<div/>')
- .addClass('mw-badge')
- .addClass('mw-badge-overlay')
+ // Contruct a new badge with the count
+ $badge = $( '<div>' )
+ .addClass( 'mw-badge' )
.append(
- $('<span/>')
- .addClass('mw-badge-content')
- .text(badge)
+ $( '<span>' )
+ .addClass( 'mw-badge-content' )
+ .text( newBadgeCount )
);
- this.append($badge);
+ this.append( $badge );
}
- if ( options.type ) {
- if ( options.type == 'inline' ) {
- $badge.removeClass('mw-badge-overlay')
- .addClass('mw-badge-inline');
- } else if ( options.type == 'overlay' ) {
- $badge.removeClass('mw-badge-inline')
- .addClass('mw-badge-overlay');
- }
+ if ( options.type === 'inline' ) {
+ $badge
+ .removeClass( 'mw-badge-overlay' )
+ .addClass( 'mw-badge-inline' );
+ // Default: overlay
+ } else {
+ $badge
+ .removeClass( 'mw-badge-inline' )
+ .addClass( 'mw-badge-overlay' );
+
}
- // If a callback was specified, call it with the badge number
- if ( options.callback ) {
- options.callback( badge );
+ // If a callback was specified, call it with the badge count
+ if ( $.isFunction( options.callback ) ) {
+ options.callback( newBadgeCount );
}
}
};
-} ) ( jQuery );
+}( jQuery ) );
* @author Krinkle <krinklemail@gmail.com>
* @license GPL v2
*/
-( function( $ ) {
+( function ( $ ) {
$.fn.checkboxShiftClick = function ( text ) {
- var prevCheckbox = null;
- var $box = this;
+ var prevCheckbox = null, $box = this;
// When our boxes are clicked..
$box.click( function ( e ) {
// And one has been clicked before...
$box.slice(
Math.min( $box.index( prevCheckbox ), $box.index( e.target ) ),
Math.max( $box.index( prevCheckbox ), $box.index( e.target ) ) + 1
- ).prop( 'checked', e.target.checked ? true : false );
+ ).prop( 'checked', !!e.target.checked );
}
// Either way, update the prevCheckbox variable to the one clicked now
prevCheckbox = e.target;
* }
*/
profile: function ( nav ) {
- /*jshint boss:true */
+ /*jshint boss: true */
if ( nav === undefined ) {
nav = window.navigator;
$.fn.expandableField = function () {
// Multi-context fields
- var returnValue;
- var args = arguments;
+ var returnValue,
+ args = arguments;
$( this ).each( function () {
- var key;
+ var key, context;
/* Construction / Loading */
- var context = $( this ).data( 'expandableField-context' );
+ context = $( this ).data( 'expandableField-context' );
// TODO: Do we need to check both null and undefined?
if ( context === undefined || context === null ) {
// Split our pattern string at spaces and run our highlight function on the results
splitAndHighlight: function ( node, pat ) {
- var patArray = pat.split( ' ' );
- for ( var i = 0; i < patArray.length; i++ ) {
+ var i,
+ patArray = pat.split( ' ' );
+ for ( i = 0; i < patArray.length; i++ ) {
if ( patArray[i].length === 0 ) {
continue;
}
// scans a node looking for the pattern and wraps a span around each match
innerHighlight: function ( node, pat ) {
+ var i, match, pos, spannode, middlebit, middleclone;
// if this is a text node
if ( node.nodeType === 3 ) {
// TODO - need to be smarter about the character matching here.
// non latin characters can make regex think a new word has begun: do not use \b
// http://stackoverflow.com/questions/3787072/regex-wordwrap-with-utf8-characters-in-js
// look for an occurrence of our pattern and store the starting position
- var match = node.data.match( new RegExp( "(^|\\s)" + $.escapeRE( pat ), "i" ) );
+ match = node.data.match( new RegExp( "(^|\\s)" + $.escapeRE( pat ), "i" ) );
if ( match ) {
- var pos = match.index + match[1].length; // include length of any matched spaces
+ pos = match.index + match[1].length; // include length of any matched spaces
// create the span wrapper for the matched text
- var spannode = document.createElement( 'span' );
+ spannode = document.createElement( 'span' );
spannode.className = 'highlight';
// shave off the characters preceding the matched text
- var middlebit = node.splitText( pos );
+ middlebit = node.splitText( pos );
// shave off any unmatched text off the end
middlebit.splitText( pat.length );
// clone for appending to our span
- var middleclone = middlebit.cloneNode( true );
+ middleclone = middlebit.cloneNode( true );
// append the matched text node to the span
spannode.appendChild( middleclone );
// replace the matched node, with our span-wrapped clone of the matched node
// if this is an element with childnodes, and not a script, style or an element we created
} else if ( node.nodeType === 1 && node.childNodes && !/(script|style)/i.test( node.tagName )
&& !( node.tagName.toLowerCase() === 'span' && node.className.match( /\bhighlight/ ) ) ) {
- for ( var i = 0; i < node.childNodes.length; ++i ) {
+ for ( i = 0; i < node.childNodes.length; ++i ) {
// call the highlight function for each child node
$.highlightText.innerHighlight( node.childNodes[i], pat );
}
/*!
- * jQuery JavaScript Library v1.8.0
+ * jQuery JavaScript Library v1.7.2
* http://jquery.com/
*
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
* Includes Sizzle.js
* http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
*
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: Thu Aug 09 2012 16:24:48 GMT-0400 (Eastern Daylight Time)
+ * Date: Wed Mar 21 12:46:34 2012 -0700
*/
(function( window, undefined ) {
-var
- // A central reference to the root jQuery(document)
- rootjQuery,
-
- // The deferred used on DOM ready
- readyList,
-
- // Use the correct document accordingly with window argument (sandbox)
- document = window.document,
- location = window.location,
- navigator = window.navigator,
-
- // Map over jQuery in case of overwrite
- _jQuery = window.jQuery,
-
- // Map over the $ in case of overwrite
- _$ = window.$,
-
- // Save a reference to some core methods
- core_push = Array.prototype.push,
- core_slice = Array.prototype.slice,
- core_indexOf = Array.prototype.indexOf,
- core_toString = Object.prototype.toString,
- core_hasOwn = Object.prototype.hasOwnProperty,
- core_trim = String.prototype.trim,
-
- // Define a local copy of jQuery
- jQuery = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- return new jQuery.fn.init( selector, context, rootjQuery );
- },
-
- // Used for matching numbers
- core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
-
- // Used for detecting and trimming whitespace
- core_rnotwhite = /\S/,
- core_rspace = /\s+/,
-
- // IE doesn't match non-breaking spaces with \s
- rtrim = core_rnotwhite.test("\xA0") ? (/^[\s\xA0]+|[\s\xA0]+$/g) : /^\s+|\s+$/g,
-
- // A simple way to check for HTML strings
- // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
- rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
-
- // Match a standalone tag
- rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
-
- // JSON RegExp
- rvalidchars = /^[\],:{}\s]*$/,
- rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
- rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
- rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
-
- // Matches dashed string for camelizing
- rmsPrefix = /^-ms-/,
- rdashAlpha = /-([\da-z])/gi,
-
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return ( letter + "" ).toUpperCase();
- },
-
- // The ready event handler and self cleanup method
- DOMContentLoaded = function() {
- if ( document.addEventListener ) {
- document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
- jQuery.ready();
- } else if ( document.readyState === "complete" ) {
- // we're here because readyState === "complete" in oldIE
- // which is good enough for us to call the dom ready!
- document.detachEvent( "onreadystatechange", DOMContentLoaded );
- jQuery.ready();
- }
- },
- // [[Class]] -> type pairs
- class2type = {};
+// Use the correct document accordingly with window argument (sandbox)
+ var document = window.document,
+ navigator = window.navigator,
+ location = window.location;
+ var jQuery = (function() {
-jQuery.fn = jQuery.prototype = {
- constructor: jQuery,
- init: function( selector, context, rootjQuery ) {
- var match, elem, ret, doc;
+// Define a local copy of jQuery
+ var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
- // Handle $(""), $(null), $(undefined), $(false)
- if ( !selector ) {
- return this;
- }
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
- // Handle $(DOMElement)
- if ( selector.nodeType ) {
- this.context = this[0] = selector;
- this.length = 1;
- return this;
- }
+ // Map over the $ in case of overwrite
+ _$ = window.$,
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
+ // A central reference to the root jQuery(document)
+ rootjQuery,
- } else {
- match = rquickExpr.exec( selector );
- }
+ // A simple way to check for HTML strings or ID strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
- // Match html or make sure no context is specified for #id
- if ( match && (match[1] || !context) ) {
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
- // HANDLE: $(html) -> $(array)
- if ( match[1] ) {
- context = context instanceof jQuery ? context[0] : context;
- doc = ( context && context.nodeType ? context.ownerDocument || context : document );
+ // Used for trimming whitespace
+ trimLeft = /^\s+/,
+ trimRight = /\s+$/,
- // scripts is true for back-compat
- selector = jQuery.parseHTML( match[1], doc, true );
- if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
- this.attr.call( selector, context, true );
- }
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
- return jQuery.merge( this, selector );
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
- // HANDLE: $(#id)
- } else {
- elem = document.getElementById( match[2] );
-
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- if ( elem && elem.parentNode ) {
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem.id !== match[2] ) {
- return rootjQuery.find( selector );
- }
+ // Useragent RegExp
+ rwebkit = /(webkit)[ \/]([\w.]+)/,
+ ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+ rmsie = /(msie) ([\w.]+)/,
+ rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
- // Otherwise, we inject the element directly into the jQuery object
- this.length = 1;
- this[0] = elem;
- }
+ // Matches dashed string for camelizing
+ rdashAlpha = /-([a-z]|[0-9])/ig,
+ rmsPrefix = /^-ms-/,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return ( letter + "" ).toUpperCase();
+ },
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // The deferred used on DOM ready
+ readyList,
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwn = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ trim = String.prototype.trim,
+ indexOf = Array.prototype.indexOf,
+
+ // [[Class]] -> type pairs
+ class2type = {};
+
+ jQuery.fn = jQuery.prototype = {
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context && document.body ) {
this.context = document;
+ this[0] = document.body;
this.selector = selector;
+ this.length = 1;
return this;
}
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || rootjQuery ).find( selector );
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
+ } else {
+ match = quickExpr.exec( selector );
+ }
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
- return rootjQuery.ready( selector );
- }
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
- if ( selector.selector !== undefined ) {
- this.selector = selector.selector;
- this.context = selector.context;
- }
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+ doc = ( context ? context.ownerDocument || context : document );
- return jQuery.makeArray( selector, this );
- },
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
- // Start with an empty selector
- selector: "",
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
- // The current version of jQuery being used
- jquery: "1.8.0",
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
- // The default length of a jQuery object is 0
- length: 0,
+ } else {
+ ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+ selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+ }
- // The number of elements contained in the matched element set
- size: function() {
- return this.length;
- },
+ return jQuery.merge( this, selector );
- toArray: function() {
- return core_slice.call( this );
- },
+ // HANDLE: $("#id")
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num == null ?
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
- // Return a 'clean' array
- this.toArray() :
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
- // Return just the object
- ( num < 0 ? this[ this.length + num ] : this[ num ] );
- },
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems, name, selector ) {
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
- // Build a new jQuery matched element set
- var ret = jQuery.merge( this.constructor(), elems );
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
- ret.context = this.context;
+ return jQuery.makeArray( selector, this );
+ },
- if ( name === "find" ) {
- ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
- } else if ( name ) {
- ret.selector = this.selector + "." + name + "(" + selector + ")";
- }
+ // Start with an empty selector
+ selector: "",
- // Return the newly-formed element set
- return ret;
- },
-
- // Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
- },
-
- ready: function( fn ) {
- // Add the callback
- jQuery.ready.promise().done( fn );
-
- return this;
- },
-
- eq: function( i ) {
- i = +i;
- return i === -1 ?
- this.slice( i ) :
- this.slice( i, i + 1 );
- },
-
- first: function() {
- return this.eq( 0 );
- },
-
- last: function() {
- return this.eq( -1 );
- },
-
- slice: function() {
- return this.pushStack( core_slice.apply( this, arguments ),
- "slice", core_slice.call(arguments).join(",") );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function( elem, i ) {
- return callback.call( elem, i, elem );
- }));
- },
-
- end: function() {
- return this.prevObject || this.constructor(null);
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: core_push,
- sort: [].sort,
- splice: [].splice
-};
+ // The current version of jQuery being used
+ jquery: "1.7.2",
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-jQuery.extend = jQuery.fn.extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
- }
+ // The default length of a jQuery object is 0
+ length: 0,
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
- target = {};
- }
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
- // extend jQuery itself if only one argument is passed
- if ( length === i ) {
- target = this;
- --i;
- }
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
+ // Return a 'clean' array
+ this.toArray() :
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && jQuery.isArray(src) ? src : [];
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
- } else {
- clone = src && jQuery.isPlainObject(src) ? src : {};
- }
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = this.constructor();
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
+ } else {
+ jQuery.merge( ret, elems );
}
- }
- }
- }
- // Return the modified object
- return target;
-};
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
-jQuery.extend({
- noConflict: function( deep ) {
- if ( window.$ === jQuery ) {
- window.$ = _$;
- }
+ ret.context = this.context;
- if ( deep && window.jQuery === jQuery ) {
- window.jQuery = _jQuery;
- }
+ if ( name === "find" ) {
+ ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
- return jQuery;
- },
+ // Return the newly-formed element set
+ return ret;
+ },
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
- // Hold (or release) the ready event
- holdReady: function( hold ) {
- if ( hold ) {
- jQuery.readyWait++;
- } else {
- jQuery.ready( true );
- }
- },
+ // Add the callback
+ readyList.add( fn );
- // Handle when the DOM is ready
- ready: function( wait ) {
+ return this;
+ },
- // Abort if there are pending holds or we're already ready
- if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
- return;
- }
+ eq: function( i ) {
+ i = +i;
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, i + 1 );
+ },
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( !document.body ) {
- return setTimeout( jQuery.ready, 1 );
- }
+ first: function() {
+ return this.eq( 0 );
+ },
- // Remember that the DOM is ready
- jQuery.isReady = true;
+ last: function() {
+ return this.eq( -1 );
+ },
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
+ },
- // If there are functions bound, to execute
- readyList.resolveWith( document, [ jQuery ] );
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
- // Trigger any bound ready events
- if ( jQuery.fn.trigger ) {
- jQuery( document ).trigger("ready").off("ready");
- }
- },
-
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
- isFunction: function( obj ) {
- return jQuery.type(obj) === "function";
- },
-
- isArray: Array.isArray || function( obj ) {
- return jQuery.type(obj) === "array";
- },
-
- isWindow: function( obj ) {
- return obj != null && obj == obj.window;
- },
-
- isNumeric: function( obj ) {
- return !isNaN( parseFloat(obj) ) && isFinite( obj );
- },
-
- type: function( obj ) {
- return obj == null ?
- String( obj ) :
- class2type[ core_toString.call(obj) ] || "object";
- },
-
- isPlainObject: function( obj ) {
- // Must be an Object.
- // Because of IE, we also have to check the presence of the constructor property.
- // Make sure that DOM nodes and window objects don't pass through, as well
- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
- return false;
- }
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
- try {
- // Not own constructor property must be Object
- if ( obj.constructor &&
- !core_hasOwn.call(obj, "constructor") &&
- !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
- return false;
- }
- } catch ( e ) {
- // IE8,9 Will throw exceptions on certain host objects #9897
- return false;
- }
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+ };
- // Own properties are enumerated firstly, so to speed up,
- // if last one is own, then all properties are own.
+// Give the init function the jQuery prototype for later instantiation
+ jQuery.fn.init.prototype = jQuery.fn;
- var key;
- for ( key in obj ) {}
+ jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
- return key === undefined || core_hasOwn.call( obj, key );
- },
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
- isEmptyObject: function( obj ) {
- var name;
- for ( name in obj ) {
- return false;
- }
- return true;
- },
-
- error: function( msg ) {
- throw new Error( msg );
- },
-
- // data: string of html
- // context (optional): If specified, the fragment will be created in this context, defaults to document
- // scripts (optional): If true, will include scripts passed in the html string
- parseHTML: function( data, context, scripts ) {
- var parsed;
- if ( !data || typeof data !== "string" ) {
- return null;
- }
- if ( typeof context === "boolean" ) {
- scripts = context;
- context = 0;
- }
- context = context || document;
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
- // Single tag
- if ( (parsed = rsingleTag.exec( data )) ) {
- return [ context.createElement( parsed[1] ) ];
- }
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
- parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
- return jQuery.merge( [],
- (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
- },
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
- parseJSON: function( data ) {
- if ( !data || typeof data !== "string") {
- return null;
- }
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
- // Make sure leading/trailing whitespace is removed (IE can't handle it)
- data = jQuery.trim( data );
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
- // Attempt to parse using the native JSON parser first
- if ( window.JSON && window.JSON.parse ) {
- return window.JSON.parse( data );
- }
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
- // Make sure the incoming data is actual JSON
- // Logic borrowed from http://json.org/json2.js
- if ( rvalidchars.test( data.replace( rvalidescape, "@" )
- .replace( rvalidtokens, "]" )
- .replace( rvalidbraces, "")) ) {
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
- return ( new Function( "return " + data ) )();
+ // Return the modified object
+ return target;
+ };
- }
- jQuery.error( "Invalid JSON: " + data );
- },
+ jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
- // Cross-browser xml parsing
- parseXML: function( data ) {
- var xml, tmp;
- if ( !data || typeof data !== "string" ) {
- return null;
- }
- try {
- if ( window.DOMParser ) { // Standard
- tmp = new DOMParser();
- xml = tmp.parseFromString( data , "text/xml" );
- } else { // IE
- xml = new ActiveXObject( "Microsoft.XMLDOM" );
- xml.async = "false";
- xml.loadXML( data );
- }
- } catch( e ) {
- xml = undefined;
- }
- if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
- jQuery.error( "Invalid XML: " + data );
- }
- return xml;
- },
-
- noop: function() {},
-
- // Evaluates a script in a global context
- // Workarounds based on findings by Jim Driscoll
- // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
- globalEval: function( data ) {
- if ( data && core_rnotwhite.test( data ) ) {
- // We use execScript on Internet Explorer
- // We use an anonymous function so that context is window
- // rather than jQuery in Firefox
- ( window.execScript || function( data ) {
- window[ "eval" ].call( window, data );
- } )( data );
- }
- },
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
- // Convert dashed to camelCase; used by the css and data modules
- // Microsoft forgot to hump their vendor prefix (#9572)
- camelCase: function( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
- },
+ return jQuery;
+ },
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
- },
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
- // args is for internal usage only
- each: function( obj, callback, args ) {
- var name,
- i = 0,
- length = obj.length,
- isObj = length === undefined || jQuery.isFunction( obj );
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
- if ( args ) {
- if ( isObj ) {
- for ( name in obj ) {
- if ( callback.apply( obj[ name ], args ) === false ) {
- break;
- }
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
}
- } else {
- for ( ; i < length; ) {
- if ( callback.apply( obj[ i++ ], args ) === false ) {
- break;
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+ // Either a released hold or an DOMready/load event and not yet ready
+ if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 1 );
}
- }
- }
- // A special, fast, case for the most common use of each
- } else {
- if ( isObj ) {
- for ( name in obj ) {
- if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
- break;
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
}
- }
- } else {
- for ( ; i < length; ) {
- if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
- break;
+
+ // If there are functions bound, to execute
+ readyList.fireWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger( "ready" ).off( "ready" );
}
}
- }
- }
+ },
- return obj;
- },
-
- // Use native String.trim function wherever possible
- trim: core_trim ?
- function( text ) {
- return text == null ?
- "" :
- core_trim.call( text );
- } :
+ bindReady: function() {
+ if ( readyList ) {
+ return;
+ }
- // Otherwise use our own trimming functionality
- function( text ) {
- return text == null ?
- "" :
- text.toString().replace( rtrim, "" );
- },
+ readyList = jQuery.Callbacks( "once memory" );
- // results is for internal usage only
- makeArray: function( arr, results ) {
- var type,
- ret = results || [];
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ return setTimeout( jQuery.ready, 1 );
+ }
- if ( arr != null ) {
- // The window, strings (and functions) also have 'length'
- // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
- type = jQuery.type( arr );
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
- if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
- core_push.call( ret, arr );
- } else {
- jQuery.merge( ret, arr );
- }
- }
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
- return ret;
- },
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
- inArray: function( elem, arr, i ) {
- var len;
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
- if ( arr ) {
- if ( core_indexOf ) {
- return core_indexOf.call( arr, elem, i );
- }
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
- len = arr.length;
- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
- for ( ; i < len; i++ ) {
- // Skip accessing in sparse arrays
- if ( i in arr && arr[ i ] === elem ) {
- return i;
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
}
- }
- }
+ },
- return -1;
- },
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
- merge: function( first, second ) {
- var l = second.length,
- i = first.length,
- j = 0;
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
- if ( typeof l === "number" ) {
- for ( ; j < l; j++ ) {
- first[ i++ ] = second[ j ];
- }
+ isWindow: function( obj ) {
+ return obj != null && obj == obj.window;
+ },
- } else {
- while ( second[j] !== undefined ) {
- first[ i++ ] = second[ j++ ];
- }
- }
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
- first.length = i;
+ type: function( obj ) {
+ return obj == null ?
+ String( obj ) :
+ class2type[ toString.call(obj) ] || "object";
+ },
- return first;
- },
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
- grep: function( elems, callback, inv ) {
- var retVal,
- ret = [],
- i = 0,
- length = elems.length;
- inv = !!inv;
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
- // Go through the array, only saving the items
- // that pass the validator function
- for ( ; i < length; i++ ) {
- retVal = !!callback( elems[ i ], i );
- if ( inv !== retVal ) {
- ret.push( elems[ i ] );
- }
- }
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
- return ret;
- },
+ var key;
+ for ( key in obj ) {}
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var value, key,
- ret = [],
- i = 0,
- length = elems.length,
- // jquery objects are treated as arrays
- isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+ return key === undefined || hasOwn.call( obj, key );
+ },
- // Go through the array, translating each of the items to their
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
- if ( value != null ) {
- ret[ ret.length ] = value;
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
}
- }
- // Go through every key on the object,
- } else {
- for ( key in elems ) {
- value = callback( elems[ key ], key, arg );
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
- if ( value != null ) {
- ret[ ret.length ] = value;
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
}
- }
- }
- // Flatten any nested arrays
- return ret.concat.apply( [], ret );
- },
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
- // A global GUID counter for objects
- guid: 1,
+ return ( new Function( "return " + data ) )();
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- var tmp, args, proxy;
+ }
+ jQuery.error( "Invalid JSON: " + data );
+ },
- if ( typeof context === "string" ) {
- tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+ var xml, tmp;
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
- // Simulated bind
- args = core_slice.call( arguments, 2 );
- proxy = function() {
- return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
- };
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
- return proxy;
- },
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction( object );
- // Multifunctional method to get and set values of a collection
- // The value/s can optionally be executed if it's a function
- access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
- var exec,
- bulk = key == null,
- i = 0,
- length = elems.length;
-
- // Sets many values
- if ( key && typeof key === "object" ) {
- for ( i in key ) {
- jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
- }
- chainable = 1;
-
- // Sets one value
- } else if ( value !== undefined ) {
- // Optionally, function values get executed if exec is true
- exec = pass === undefined && jQuery.isFunction( value );
-
- if ( bulk ) {
- // Bulk operations only iterate when executing function values
- if ( exec ) {
- exec = fn;
- fn = function( elem, key, value ) {
- return exec.call( jQuery( elem ), value );
- };
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
- // Otherwise they run against the entire set
+ // A special, fast, case for the most common use of each
} else {
- fn.call( elems, value );
- fn = null;
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+ break;
+ }
+ }
+ }
}
- }
- if ( fn ) {
- for (; i < length; i++ ) {
- fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
- }
- }
+ return object;
+ },
- chainable = 1;
- }
+ // Use native String.trim function wherever possible
+ trim: trim ?
+ function( text ) {
+ return text == null ?
+ "" :
+ trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+ },
- return chainable ?
- elems :
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
- // Gets
- bulk ?
- fn.call( elems ) :
- length ? fn( elems[0], key ) : emptyGet;
- },
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+ var type = jQuery.type( array );
- now: function() {
- return ( new Date() ).getTime();
- }
-});
+ if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
-jQuery.ready.promise = function( obj ) {
- if ( !readyList ) {
+ return ret;
+ },
- readyList = jQuery.Deferred();
+ inArray: function( elem, array, i ) {
+ var len;
- // Catch cases where $(document).ready() is called after the
- // browser event has already occurred.
- if ( document.readyState === "complete" || ( document.readyState !== "loading" && document.addEventListener ) ) {
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- setTimeout( jQuery.ready, 1 );
+ if ( array ) {
+ if ( indexOf ) {
+ return indexOf.call( array, elem, i );
+ }
- // Standards-based browsers support DOMContentLoaded
- } else if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ len = array.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", jQuery.ready, false );
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in array && array[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
- // If IE event model is used
- } else {
- // Ensure firing before onload, maybe late but safe also for iframes
- document.attachEvent( "onreadystatechange", DOMContentLoaded );
+ return -1;
+ },
- // A fallback to window.onload, that will always work
- window.attachEvent( "onload", jQuery.ready );
+ merge: function( first, second ) {
+ var i = first.length,
+ j = 0;
- // If IE and not a frame
- // continually check to see if the document is ready
- var top = false;
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
- try {
- top = window.frameElement == null && document.documentElement;
- } catch(e) {}
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [], retVal;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value, key, ret = [],
+ i = 0,
+ length = elems.length,
+ // jquery objects are treated as arrays
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( key in elems ) {
+ value = callback( elems[ key ], key, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ if ( typeof context === "string" ) {
+ var tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ var args = slice.call( arguments, 2 ),
+ proxy = function() {
+ return fn.apply( context, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Mutifunctional method to get and set values to a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
+ var exec,
+ bulk = key == null,
+ i = 0,
+ length = elems.length;
+
+ // Sets many values
+ if ( key && typeof key === "object" ) {
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
+ }
+ chainable = 1;
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = pass === undefined && jQuery.isFunction( value );
+
+ if ( bulk ) {
+ // Bulk operations only iterate when executing function values
+ if ( exec ) {
+ exec = fn;
+ fn = function( elem, key, value ) {
+ return exec.call( jQuery( elem ), value );
+ };
+
+ // Otherwise they run against the entire set
+ } else {
+ fn.call( elems, value );
+ fn = null;
+ }
+ }
+
+ if ( fn ) {
+ for (; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+ }
+
+ chainable = 1;
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ },
+
+ // Use of jQuery.browser is frowned upon.
+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = rwebkit.exec( ua ) ||
+ ropera.exec( ua ) ||
+ rmsie.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+ [];
+
+ return { browser: match[1] || "", version: match[2] || "0" };
+ },
+
+ sub: function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ return jQuerySub;
+ },
+
+ browser: {}
+ });
+
+// Populate the class2type map
+ jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+ });
+
+ browserMatch = jQuery.uaMatch( userAgent );
+ if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+ }
+
+// Deprecated, use jQuery.browser.webkit instead
+ if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+ }
+
+// IE doesn't match non-breaking spaces with \s
+ if ( rnotwhite.test( "\xA0" ) ) {
+ trimLeft = /^[\s\xA0]+/;
+ trimRight = /[\s\xA0]+$/;
+ }
+
+// All jQuery objects should point back to these
+ rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+ if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+ } else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ };
+ }
+
+// The DOM ready check for Internet Explorer
+ function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch(e) {
+ setTimeout( doScrollCheck, 1 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+
+ return jQuery;
+
+ })();
+
+
+// String to Object flags format cache
+ var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+ function createFlags( flags ) {
+ var object = flagsCache[ flags ] = {},
+ i, length;
+ flags = flags.split( /\s+/ );
+ for ( i = 0, length = flags.length; i < length; i++ ) {
+ object[ flags[i] ] = true;
+ }
+ return object;
+ }
+
+ /*
+ * Create a callback list using the following parameters:
+ *
+ * flags: an optional list of space-separated flags that will change how
+ * the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+ jQuery.Callbacks = function( flags ) {
+
+ // Convert flags from String-formatted to Object-formatted
+ // (we check in cache first)
+ flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+ var // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = [],
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Add one or several callbacks to the list
+ add = function( args ) {
+ var i,
+ length,
+ elem,
+ type,
+ actual;
+ for ( i = 0, length = args.length; i < length; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ // Inspect recursively
+ add( elem );
+ } else if ( type === "function" ) {
+ // Add if not in unique mode and callback is not in
+ if ( !flags.unique || !self.has( elem ) ) {
+ list.push( elem );
+ }
+ }
+ }
+ },
+ // Fire callbacks
+ fire = function( context, args ) {
+ args = args || [];
+ memory = !flags.memory || [ context, args ];
+ fired = true;
+ firing = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+ memory = true; // Mark as halted
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( !flags.once ) {
+ if ( stack && stack.length ) {
+ memory = stack.shift();
+ self.fireWith( memory[ 0 ], memory[ 1 ] );
+ }
+ } else if ( memory === true ) {
+ self.disable();
+ } else {
+ list = [];
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ var length = list.length;
+ add( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away, unless previous
+ // firing was halted (stopOnFalse)
+ } else if ( memory && memory !== true ) {
+ firingStart = length;
+ fire( memory[ 0 ], memory[ 1 ] );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ var args = arguments,
+ argIndex = 0,
+ argLength = args.length;
+ for ( ; argIndex < argLength ; argIndex++ ) {
+ for ( var i = 0; i < list.length; i++ ) {
+ if ( args[ argIndex ] === list[ i ] ) {
+ // Handle firingIndex and firingLength
+ if ( firing ) {
+ if ( i <= firingLength ) {
+ firingLength--;
+ if ( i <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ // Remove the element
+ list.splice( i--, 1 );
+ // If we have some unicity property then
+ // we only need to do this once
+ if ( flags.unique ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return this;
+ },
+ // Control if a given callback is in the list
+ has: function( fn ) {
+ if ( list ) {
+ var i = 0,
+ length = list.length;
+ for ( ; i < length; i++ ) {
+ if ( fn === list[ i ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory || memory === true ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( stack ) {
+ if ( firing ) {
+ if ( !flags.once ) {
+ stack.push( [ context, args ] );
+ }
+ } else if ( !( flags.once && memory ) ) {
+ fire( context, args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+ };
+
+
+
+
+ var // Static reference to slice
+ sliceDeferred = [].slice;
+
+ jQuery.extend({
+
+ Deferred: function( func ) {
+ var doneList = jQuery.Callbacks( "once memory" ),
+ failList = jQuery.Callbacks( "once memory" ),
+ progressList = jQuery.Callbacks( "memory" ),
+ state = "pending",
+ lists = {
+ resolve: doneList,
+ reject: failList,
+ notify: progressList
+ },
+ promise = {
+ done: doneList.add,
+ fail: failList.add,
+ progress: progressList.add,
+
+ state: function() {
+ return state;
+ },
+
+ // Deprecated
+ isResolved: doneList.fired,
+ isRejected: failList.fired,
+
+ then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+ deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+ return this;
+ },
+ always: function() {
+ deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+ return this;
+ },
+ pipe: function( fnDone, fnFail, fnProgress ) {
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( {
+ done: [ fnDone, "resolve" ],
+ fail: [ fnFail, "reject" ],
+ progress: [ fnProgress, "notify" ]
+ }, function( handler, data ) {
+ var fn = data[ 0 ],
+ action = data[ 1 ],
+ returned;
+ if ( jQuery.isFunction( fn ) ) {
+ deferred[ handler ](function() {
+ returned = fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+ }
+ });
+ } else {
+ deferred[ handler ]( newDefer[ action ] );
+ }
+ });
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ if ( obj == null ) {
+ obj = promise;
+ } else {
+ for ( var key in promise ) {
+ obj[ key ] = promise[ key ];
+ }
+ }
+ return obj;
+ }
+ },
+ deferred = promise.promise({}),
+ key;
+
+ for ( key in lists ) {
+ deferred[ key ] = lists[ key ].fire;
+ deferred[ key + "With" ] = lists[ key ].fireWith;
+ }
+
+ // Handle state
+ deferred.done( function() {
+ state = "resolved";
+ }, failList.disable, progressList.lock ).fail( function() {
+ state = "rejected";
+ }, doneList.disable, progressList.lock );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( firstParam ) {
+ var args = sliceDeferred.call( arguments, 0 ),
+ i = 0,
+ length = args.length,
+ pValues = new Array( length ),
+ count = length,
+ pCount = length,
+ deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+ firstParam :
+ jQuery.Deferred(),
+ promise = deferred.promise();
+ function resolveFunc( i ) {
+ return function( value ) {
+ args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ if ( !( --count ) ) {
+ deferred.resolveWith( deferred, args );
+ }
+ };
+ }
+ function progressFunc( i ) {
+ return function( value ) {
+ pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ deferred.notifyWith( promise, pValues );
+ };
+ }
+ if ( length > 1 ) {
+ for ( ; i < length; i++ ) {
+ if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+ args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+ } else {
+ --count;
+ }
+ }
+ if ( !count ) {
+ deferred.resolveWith( deferred, args );
+ }
+ } else if ( deferred !== firstParam ) {
+ deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+ }
+ return promise;
+ }
+ });
+
+
+
+
+ jQuery.support = (function() {
+
+ var support,
+ all,
+ a,
+ select,
+ opt,
+ input,
+ fragment,
+ tds,
+ events,
+ eventName,
+ i,
+ isSupported,
+ div = document.createElement( "div" ),
+ documentElement = document.documentElement;
+
+ // Preliminary tests
+ div.setAttribute("className", "t");
+ div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+ all = div.getElementsByTagName( "*" );
+ a = div.getElementsByTagName( "a" )[ 0 ];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return {};
+ }
+
+ // First batch of supports tests
+ select = document.createElement( "select" );
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName( "input" )[ 0 ];
+
+ support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: ( input.value === "on" ),
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // Tests for enctype support on a form(#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+ // Will be defined later
+ submitBubbles: true,
+ changeBubbles: true,
+ focusinBubbles: false,
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true,
+ pixelMargin: true
+ };
+
+ // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead
+ jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat");
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+ div.attachEvent( "onclick", function() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ support.noCloneEvent = false;
+ });
+ div.cloneNode( true ).fireEvent( "onclick" );
+ }
+
+ // Check if a radio maintains its value
+ // after being appended to the DOM
+ input = document.createElement("input");
+ input.value = "t";
+ input.setAttribute("type", "radio");
+ support.radioValue = input.value === "t";
+
+ input.setAttribute("checked", "checked");
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( div.lastChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ fragment.removeChild( input );
+ fragment.appendChild( div );
+
+ // Technique from Juriy Zaytsev
+ // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+ // We only care about the case where non-standard event systems
+ // are used, namely in IE. Short-circuiting here helps us to
+ // avoid an eval call (in setAttribute) which can cause CSP
+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+ if ( div.attachEvent ) {
+ for ( i in {
+ submit: 1,
+ change: 1,
+ focusin: 1
+ }) {
+ eventName = "on" + i;
+ isSupported = ( eventName in div );
+ if ( !isSupported ) {
+ div.setAttribute( eventName, "return;" );
+ isSupported = ( typeof div[ eventName ] === "function" );
+ }
+ support[ i + "Bubbles" ] = isSupported;
+ }
+ }
+
+ fragment.removeChild( div );
+
+ // Null elements to avoid leaks in IE
+ fragment = select = opt = div = input = null;
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, outer, inner, table, td, offsetSupport,
+ marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,
+ paddingMarginBorderVisibility, paddingMarginBorder,
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ conMarginTop = 1;
+ paddingMarginBorder = "padding:0;margin:0;border:";
+ positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;";
+ paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;";
+ style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;";
+ html = "<div " + style + "display:block;'><div style='" + paddingMarginBorder + "0;display:block;overflow:hidden;'></div></div>" +
+ "<table " + style + "' cellpadding='0' cellspacing='0'>" +
+ "<tr><td></td></tr></table>";
+
+ container = document.createElement("div");
+ container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+ body.insertBefore( container, body.firstChild );
+
+ // Construct the test element
+ div = document.createElement("div");
+ container.appendChild( div );
+
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ // (only IE 8 fails this test)
+ div.innerHTML = "<table><tr><td style='" + paddingMarginBorder + "0;display:none'></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName( "td" );
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Check if empty table cells still have offsetWidth/Height
+ // (IE <= 8 fail this test)
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. For more
+ // info see bug #3333
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ if ( window.getComputedStyle ) {
+ div.innerHTML = "";
+ marginDiv = document.createElement( "div" );
+ marginDiv.style.width = "0";
+ marginDiv.style.marginRight = "0";
+ div.style.width = "2px";
+ div.appendChild( marginDiv );
+ support.reliableMarginRight =
+ ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+ }
+
+ if ( typeof div.style.zoom !== "undefined" ) {
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ // (IE < 8 does this)
+ div.innerHTML = "";
+ div.style.width = div.style.padding = "1px";
+ div.style.border = 0;
+ div.style.overflow = "hidden";
+ div.style.display = "inline";
+ div.style.zoom = 1;
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+ // Check if elements with layout shrink-wrap their children
+ // (IE 6 does this)
+ div.style.display = "block";
+ div.style.overflow = "visible";
+ div.innerHTML = "<div style='width:5px;'></div>";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+ }
+
+ div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;
+ div.innerHTML = html;
+
+ outer = div.firstChild;
+ inner = outer.firstChild;
+ td = outer.nextSibling.firstChild.firstChild;
+
+ offsetSupport = {
+ doesNotAddBorder: ( inner.offsetTop !== 5 ),
+ doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+ };
+
+ inner.style.position = "fixed";
+ inner.style.top = "20px";
+
+ // safari subtracts parent border width here which is 5px
+ offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+ inner.style.position = inner.style.top = "";
+
+ outer.style.overflow = "hidden";
+ outer.style.position = "relative";
+
+ offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+ offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+ if ( window.getComputedStyle ) {
+ div.style.marginTop = "1%";
+ support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%";
+ }
+
+ if ( typeof container.style.zoom !== "undefined" ) {
+ container.style.zoom = 1;
+ }
+
+ body.removeChild( container );
+ marginDiv = div = container = null;
+
+ jQuery.extend( support, offsetSupport );
+ });
+
+ return support;
+ })();
+
+
+
+
+ var rbrace = /^(?:\{.*\}|\[.*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+ jQuery.extend({
+ cache: {},
+
+ // Please use with caution
+ uuid: 0,
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var privateCache, thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
+ isEvents = name === "events";
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = ++jQuery.uuid;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ privateCache = thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Users should not attempt to inspect the internal events object using jQuery.data,
+ // it is undocumented and subject to change. But does anyone listen? No.
+ if ( isEvents && !thisCache[ name ] ) {
+ return privateCache.events;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+ },
+
+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i, l,
+
+ // Reference to internal data cache key
+ internalKey = jQuery.expando,
+
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+
+ // See jQuery.data for more information
+ id = isNode ? elem[ internalKey ] : internalKey;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split( " " );
+ }
+ }
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject(cache[ id ]) ) {
+ return;
+ }
+ }
+
+ // Browsers that fail expando deletion also refuse to delete expandos on
+ // the window, but it will allow it on all other JS objects; other browsers
+ // don't care
+ // Ensure that `cache` is not a window object #10080
+ if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+ delete cache[ id ];
+ } else {
+ cache[ id ] = null;
+ }
+
+ // We destroyed the cache and need to eliminate the expando on the node to avoid
+ // false lookups in the cache for entries that no longer exist
+ if ( isNode ) {
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( jQuery.support.deleteExpando ) {
+ delete elem[ internalKey ];
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( internalKey );
+ } else {
+ elem[ internalKey ] = null;
+ }
+ }
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return jQuery.data( elem, name, data, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ if ( elem.nodeName ) {
+ var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ if ( match ) {
+ return !(match === true || elem.getAttribute("classid") !== match);
+ }
+ }
+
+ return true;
+ }
+ });
+
+ jQuery.fn.extend({
+ data: function( key, value ) {
+ var parts, part, attr, name, l,
+ elem = this[0],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ attr = elem.attributes;
+ for ( l = attr.length; i < l; i++ ) {
+ name = attr[i].name;
+
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.substring(5) );
+
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ parts = key.split( ".", 2 );
+ parts[1] = parts[1] ? "." + parts[1] : "";
+ part = parts[1] + "!";
+
+ return jQuery.access( this, function( value ) {
+
+ if ( value === undefined ) {
+ data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+
+ // Try to fetch any internally stored data first
+ if ( data === undefined && elem ) {
+ data = jQuery.data( elem, key );
+ data = dataAttr( elem, key, data );
+ }
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ }
+
+ parts[1] = value;
+ this.each(function() {
+ var self = jQuery( this );
+
+ self.triggerHandler( "setData" + part, parts );
+ jQuery.data( this, key, value );
+ self.triggerHandler( "changeData" + part, parts );
+ });
+ }, null, value, arguments.length > 1, null, false );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+ });
+
+ function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ jQuery.isNumeric( data ) ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+ }
+
+// checks a cache object for emptiness
+ function isEmptyDataObject( obj ) {
+ for ( var name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+
+
+ function handleQueueMarkDefer( elem, type, src ) {
+ var deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ defer = jQuery._data( elem, deferDataKey );
+ if ( defer &&
+ ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+ ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+ // Give room for hard-coded callbacks to fire first
+ // and eventually mark/queue something else on the element
+ setTimeout( function() {
+ if ( !jQuery._data( elem, queueDataKey ) &&
+ !jQuery._data( elem, markDataKey ) ) {
+ jQuery.removeData( elem, deferDataKey, true );
+ defer.fire();
+ }
+ }, 0 );
+ }
+ }
+
+ jQuery.extend({
+
+ _mark: function( elem, type ) {
+ if ( elem ) {
+ type = ( type || "fx" ) + "mark";
+ jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+ }
+ },
+
+ _unmark: function( force, elem, type ) {
+ if ( force !== true ) {
+ type = elem;
+ elem = force;
+ force = false;
+ }
+ if ( elem ) {
+ type = type || "fx";
+ var key = type + "mark",
+ count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+ if ( count ) {
+ jQuery._data( elem, key, count );
+ } else {
+ jQuery.removeData( elem, key, true );
+ handleQueueMarkDefer( elem, type, "mark" );
+ }
+ }
+ },
+
+ queue: function( elem, type, data ) {
+ var q;
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ q = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ q.push( data );
+ }
+ }
+ return q || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift(),
+ hooks = {};
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
+
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ jQuery._data( elem, type + ".run", hooks );
+ fn.call( elem, function() {
+ jQuery.dequeue( elem, type );
+ }, hooks );
+ }
+
+ if ( !queue.length ) {
+ jQuery.removeData( elem, type + "queue " + type + ".run", true );
+ handleQueueMarkDefer( elem, type, "queue" );
+ }
+ }
+ });
+
+ jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, object ) {
+ if ( typeof type !== "string" ) {
+ object = type;
+ type = undefined;
+ }
+ type = type || "fx";
+ var defer = jQuery.Deferred(),
+ elements = this,
+ i = elements.length,
+ count = 1,
+ deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ tmp;
+ function resolve() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ }
+ while( i-- ) {
+ if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+ ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+ jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+ jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+ count++;
+ tmp.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( object );
+ }
+ });
+
+
+
+
+ var rclass = /[\n\t\r]/g,
+ rspace = /\s+/,
+ rreturn = /\r/g,
+ rtype = /^(?:button|input)$/i,
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
+ rclickable = /^a(?:rea)?$/i,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ nodeHook, boolHook, fixSpecified;
+
+ jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classNames, i, l, elem,
+ setClass, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ classNames = value.split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className && classNames.length === 1 ) {
+ elem.className = value;
+
+ } else {
+ setClass = " " + elem.className + " ";
+
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+ setClass += classNames[ c ] + " ";
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classNames, i, l, elem, className, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( (value && typeof value === "string") || value === undefined ) {
+ classNames = ( value || "" ).split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ className = (" " + elem.className + " ").replace( rclass, " " );
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[ c ] + " ", " ");
+ }
+ elem.className = jQuery.trim( className );
+
+ } else {
+ elem.className = "";
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.split( rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var self = jQuery(this), val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+ });
+
+ jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, i, max, option,
+ index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ i = one ? index : 0;
+ max = one ? index + 1 : options.length;
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Don't return options that are disabled or in a disabled optgroup
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+ if ( one && !values.length && options.length ) {
+ return jQuery( options[ index ] ).val();
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
+ },
+
+ attr: function( elem, name, value, pass ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery( elem )[ name ]( value );
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+
+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, "" + value );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ ret = elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret === null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var propName, attrNames, name, l, isBool,
+ i = 0;
+
+ if ( value && elem.nodeType === 1 ) {
+ attrNames = value.toLowerCase().split( rspace );
+ l = attrNames.length;
+
+ for ( ; i < l; i++ ) {
+ name = attrNames[ i ];
+
+ if ( name ) {
+ propName = jQuery.propFix[ name ] || name;
+ isBool = rboolean.test( name );
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ // Do not do this for boolean attributes (see #10870)
+ if ( !isBool ) {
+ jQuery.attr( elem, name, "" );
+ }
+ elem.removeAttribute( getSetAttribute ? name : propName );
+
+ // Set corresponding property to false for boolean attributes
+ if ( isBool && propName in elem ) {
+ elem[ propName ] = false;
+ }
+ }
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to it's default in case type is set after value
+ // This is for element creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ },
+ // Use the value property for back compat
+ // Use the nodeHook for button elements in IE6/7 (#1954)
+ value: {
+ get: function( elem, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.get( elem, name );
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.set( elem, value, name );
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+ });
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+ jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+ boolHook = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+ };
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+ if ( !getSetAttribute ) {
+
+ fixSpecified = {
+ name: true,
+ id: true,
+ coords: true
+ };
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret;
+ ret = elem.getAttributeNode( name );
+ return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+ ret.nodeValue :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ ret = document.createAttribute( name );
+ elem.setAttributeNode( ret );
+ }
+ return ( ret.nodeValue = value + "" );
+ }
+ };
+
+ // Apply the nodeHook to tabindex
+ jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ if ( value === "" ) {
+ value = "false";
+ }
+ nodeHook.set( elem, value, name );
+ }
+ };
+ }
+
+
+// Some attributes require a special call on IE
+ if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret === null ? undefined : ret;
+ }
+ });
+ });
+ }
+
+ if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Normalize to lowercase since IE uppercases css property names
+ return elem.style.cssText.toLowerCase() || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = "" + value );
+ }
+ };
+ }
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+ if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+// IE6/7 call enctype encoding
+ if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+ }
+
+// Radios and checkboxes getter/setter
+ if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+ }
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+ });
+
+
+
+
+ var rformElems = /^(?:textarea|input|select)$/i,
+ rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+ rhoverHack = /(?:^|\s)hover(\.\S+)?\b/,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+ quickParse = function( selector ) {
+ var quick = rquickIs.exec( selector );
+ if ( quick ) {
+ // 0 1 2 3
+ // [ _, tag, id, class ]
+ quick[1] = ( quick[1] || "" ).toLowerCase();
+ quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+ }
+ return quick;
+ },
+ quickIs = function( elem, m ) {
+ var attrs = elem.attributes || {};
+ return (
+ (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+ (!m[2] || (attrs.id || {}).value === m[2]) &&
+ (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
+ );
+ },
+ hoverHack = function( events ) {
+ return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+ /*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+ jQuery.event = {
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var elemData, eventHandle, events,
+ t, tns, type, namespaces, handleObj,
+ handleObjIn, quick, handlers, special;
+
+ // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+ if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ events = elemData.events;
+ if ( !events ) {
+ elemData.events = events = {};
+ }
+ eventHandle = elemData.handle;
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = jQuery.trim( hoverHack(types) ).split( " " );
+ for ( t = 0; t < types.length; t++ ) {
+
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = tns[1];
+ namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: tns[1],
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ quick: selector && quickParse( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ handlers = events[ type ];
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+ t, tns, type, origType, namespaces, origCount,
+ j, events, special, handle, eventType, handleObj;
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+ for ( t = 0; t < types.length; t++ ) {
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tns[1];
+ namespaces = tns[2];
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector? special.delegateType : special.bindType ) || type;
+ eventType = events[ type ] || [];
+ origCount = eventType.length;
+ namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+ // Remove matching events
+ for ( j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ eventType.splice( j--, 1 );
+
+ if ( handleObj.selector ) {
+ eventType.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( eventType.length === 0 && origCount !== eventType.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery.removeData( elem, [ "events", "handle" ], true );
+ }
+ },
+
+ // Events that are safe to short-circuit if no handlers are attached.
+ // Native DOM events should not be added, they may have inline handlers.
+ customEvent: {
+ "getData": true,
+ "setData": true,
+ "changeData": true
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ // Don't do events on text and comment nodes
+ if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+ return;
+ }
+
+ // Event object or event type
+ var type = event.type || event,
+ namespaces = [],
+ cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "!" ) >= 0 ) {
+ // Exclusive events trigger only for the exact event (no namespaces)
+ type = type.slice(0, -1);
+ exclusive = true;
+ }
+
+ if ( type.indexOf( "." ) >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+
+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+ // No jQuery handlers for this event type, and it can't have inline handlers
+ return;
+ }
+
+ // Caller can pass in an Event, Object, or just an event type string
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[ jQuery.expando ] ? event :
+ // Object literal
+ new jQuery.Event( type, event ) :
+ // Just the event type (string)
+ new jQuery.Event( type );
+
+ event.type = type;
+ event.isTrigger = true;
+ event.exclusive = exclusive;
+ event.namespace = namespaces.join( "." );
+ event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+ ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+ // Handle a global trigger
+ if ( !elem ) {
+
+ // TODO: Stop taunting the data cache; remove global events and always attach to document
+ cache = jQuery.cache;
+ for ( i in cache ) {
+ if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+ jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+ }
+ }
+ return;
+ }
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data != null ? jQuery.makeArray( data ) : [];
+ data.unshift( event );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ eventPath = [[ elem, special.bindType || type ]];
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+ old = null;
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push([ cur, bubbleType ]);
+ old = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( old && old === elem.ownerDocument ) {
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+ }
+ }
+
+ // Fire handlers on the event path
+ for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+ cur = eventPath[i][0];
+ event.type = eventPath[i][1];
+
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+ // Note that this is a bare JS function and not a jQuery handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ // IE<9 dies on focus/blur to hidden element (#1486)
+ if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ old = elem[ ontype ];
+
+ if ( old ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( old ) {
+ elem[ ontype ] = old;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event || window.event );
+
+ var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+ delegateCount = handlers.delegateCount,
+ args = [].slice.call( arguments, 0 ),
+ run_all = !event.exclusive && !event.namespace,
+ special = jQuery.event.special[ event.type ] || {},
+ handlerQueue = [],
+ i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers that should run if there are delegated events
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && !(event.button && event.type === "click") ) {
+
+ // Pregenerate a single jQuery object for reuse with .is()
+ jqcur = jQuery(this);
+ jqcur.context = this.ownerDocument || this;
+
+ for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+
+ // Don't process events on disabled elements (#6911, #8165)
+ if ( cur.disabled !== true ) {
+ selMatch = {};
+ matches = [];
+ jqcur[0] = cur;
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+ sel = handleObj.selector;
+
+ if ( selMatch[ sel ] === undefined ) {
+ selMatch[ sel ] = (
+ handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
+ );
+ }
+ if ( selMatch[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, matches: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( handlers.length > delegateCount ) {
+ handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+ }
+
+ // Run delegates first; they may want to stop propagation beneath us
+ for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+ matched = handlerQueue[ i ];
+ event.currentTarget = matched.elem;
+
+ for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+ handleObj = matched.matches[ j ];
+
+ // Triggered event must either 1) be non-exclusive and have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+ props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop,
+ originalEvent = event,
+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = jQuery.Event( originalEvent );
+
+ for ( i = copy.length; i; ) {
+ prop = copy[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Target should not be a text node (#504, Safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
+ if ( event.metaKey === undefined ) {
+ event.metaKey = event.ctrlKey;
+ }
+
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady
+ },
+
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+
+ focus: {
+ delegateType: "focusin"
+ },
+ blur: {
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( jQuery.isWindow( this ) ) {
+ this.onbeforeunload = eventHandle;
+ }
+ },
+
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+ };
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+ jQuery.event.handle = jQuery.event.dispatch;
+
+ jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ if ( elem.detachEvent ) {
+ elem.detachEvent( "on" + type, handle );
+ }
+ };
+
+ jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+ };
+
+ function returnFalse() {
+ return false;
+ }
+ function returnTrue() {
+ return true;
+ }
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+ jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // otherwise set the returnValue property of the original event to false (IE)
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+ };
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+ jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+ }, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj,
+ selector = handleObj.selector,
+ ret;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+ });
+
+// IE submit delegation
+ if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !form._submit_attached ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ form._submit_attached = true;
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+ }
+
+// IE change delegation and checkbox/radio fix
+ if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ jQuery.event.simulate( "change", this, event, true );
+ }
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ elem._change_attached = true;
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return rformElems.test( this.nodeName );
+ }
+ };
+ }
+
+// Create "bubbling" focus and blur events
+ if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+ }
+
+ jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) { // && selector != null
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ var handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( var type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ live: function( types, data, fn ) {
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+ },
+ die: function( types, fn ) {
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ return jQuery.event.trigger( type, data, this[0], true );
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+ });
+
+ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ if ( fn == null ) {
+ fn = data;
+ data = null;
+ }
+
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+
+ if ( rkeyEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+ }
+
+ if ( rmouseEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+ }
+ });
+
+
+
+ /*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+ (function(){
+
+ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ expando = "sizcache" + (Math.random() + '').replace('.', ''),
+ done = 0,
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true,
+ rBackslash = /\\/g,
+ rReturn = /\r\n/g,
+ rNonWord = /\W/;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+ [0, 0].sort(function() {
+ baseHasDuplicate = false;
+ return 0;
+ });
+
+ var Sizzle = function( selector, context, results, seed ) {
+ results = results || [];
+ context = context || document;
+
+ var origContext = context;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var m, set, checkSet, extra, ret, cur, pop, i,
+ prune = true,
+ contextXML = Sizzle.isXML( context ),
+ parts = [],
+ soFar = selector;
+
+ // Reset the position of the chunker regexp (start from head)
+ do {
+ chunker.exec( "" );
+ m = chunker.exec( soFar );
+
+ if ( m ) {
+ soFar = m[3];
+
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = m[3];
+ break;
+ }
+ }
+ } while ( m );
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context, seed );
+
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
- if ( top && top.doScroll ) {
- (function doScrollCheck() {
- if ( !jQuery.isReady ) {
+ while ( parts.length ) {
+ selector = parts.shift();
- try {
- // Use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- top.doScroll("left");
- } catch(e) {
- return setTimeout( doScrollCheck, 50 );
+ if ( Expr.relative[ selector ] ) {
+ selector += parts.shift();
}
- // and execute any waiting functions
- jQuery.ready();
+ set = posProcess( selector, set, seed );
}
- })();
- }
- }
- }
- return readyList.promise( obj );
-};
+ }
-// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
+ } else {
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+ ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set )[0] :
+ ret.set[0];
+ }
-// All jQuery objects should point back to these
-rootjQuery = jQuery(document);
-// String to Object options format cache
-var optionsCache = {};
-
-// Convert String-formatted options into Object-formatted ones and store in cache
-function createOptions( options ) {
- var object = optionsCache[ options ] = {};
- jQuery.each( options.split( core_rspace ), function( _, flag ) {
- object[ flag ] = true;
- });
- return object;
-}
+ if ( context ) {
+ ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
-/*
- * Create a callback list using the following parameters:
- *
- * options: an optional list of space-separated options that will change how
- * the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
+ set = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set ) :
+ ret.set;
- // Convert options from String-formatted to Object-formatted if needed
- // (we check in cache first)
- options = typeof options === "string" ?
- ( optionsCache[ options ] || createOptions( options ) ) :
- jQuery.extend( {}, options );
+ if ( parts.length > 0 ) {
+ checkSet = makeArray( set );
- var // Last fire value (for non-forgettable lists)
- memory,
- // Flag to know if list was already fired
- fired,
- // Flag to know if list is currently firing
- firing,
- // First callback to fire (used internally by add and fireWith)
- firingStart,
- // End of the loop when firing
- firingLength,
- // Index of currently firing callback (modified by remove if needed)
- firingIndex,
- // Actual callback list
- list = [],
- // Stack of fire calls for repeatable lists
- stack = !options.once && [],
- // Fire callbacks
- fire = function( data ) {
- memory = options.memory && data;
- fired = true;
- firingIndex = firingStart || 0;
- firingStart = 0;
- firingLength = list.length;
- firing = true;
- for ( ; list && firingIndex < firingLength; firingIndex++ ) {
- if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
- memory = false; // To prevent further calls using add
- break;
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ cur = parts.pop();
+ pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+
+ } else {
+ checkSet = parts = [];
}
}
- firing = false;
- if ( list ) {
- if ( stack ) {
- if ( stack.length ) {
- fire( stack.shift() );
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ Sizzle.error( cur || selector );
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+
+ } else if ( context && context.nodeType === 1 ) {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
}
- } else if ( memory ) {
- list = [];
+
} else {
- self.disable();
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
}
+
+ } else {
+ makeArray( checkSet, results );
}
- },
- // Actual Callbacks object
- self = {
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
- // First, we save the current length
- var start = list.length;
- (function add( args ) {
- jQuery.each( args, function( _, arg ) {
- if ( jQuery.isFunction( arg ) && ( !options.unique || !self.has( arg ) ) ) {
- list.push( arg );
- } else if ( arg && arg.length ) {
- // Inspect recursively
- add( arg );
- }
- });
- })( arguments );
- // Do we need to add the callbacks to the
- // current firing batch?
- if ( firing ) {
- firingLength = list.length;
- // With memory, if we're not firing then
- // we should call right away
- } else if ( memory ) {
- firingStart = start;
- fire( memory );
+
+ if ( extra ) {
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
+
+ return results;
+ };
+
+ Sizzle.uniqueSort = function( results ) {
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[ i - 1 ] ) {
+ results.splice( i--, 1 );
+ }
}
}
- return this;
- },
- // Remove a callback from the list
- remove: function() {
- if ( list ) {
- jQuery.each( arguments, function( _, arg ) {
- var index;
- while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
- list.splice( index, 1 );
- // Handle firing indexes
- if ( firing ) {
- if ( index <= firingLength ) {
- firingLength--;
- }
- if ( index <= firingIndex ) {
- firingIndex--;
- }
- }
+ }
+
+ return results;
+ };
+
+ Sizzle.matches = function( expr, set ) {
+ return Sizzle( expr, null, null, set );
+ };
+
+ Sizzle.matchesSelector = function( node, expr ) {
+ return Sizzle( expr, null, null, [node] ).length > 0;
+ };
+
+ Sizzle.find = function( expr, context, isXML ) {
+ var set, i, len, match, type, left;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( i = 0, len = Expr.order.length; i < len; i++ ) {
+ type = Expr.order[i];
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ left = match[1];
+ match.splice( 1, 1 );
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace( rBackslash, "" );
+ set = Expr.find[ type ]( match, context, isXML );
+
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
}
- });
- }
- return this;
- },
- // Control if a given callback is in the list
- has: function( fn ) {
- return jQuery.inArray( fn, list ) > -1;
- },
- // Remove all callbacks from the list
- empty: function() {
- list = [];
- return this;
- },
- // Have the list do nothing anymore
- disable: function() {
- list = stack = memory = undefined;
- return this;
- },
- // Is it disabled?
- disabled: function() {
- return !list;
- },
- // Lock the list in its current state
- lock: function() {
- stack = undefined;
- if ( !memory ) {
- self.disable();
- }
- return this;
- },
- // Is it locked?
- locked: function() {
- return !stack;
- },
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- args = args || [];
- args = [ context, args.slice ? args.slice() : args ];
- if ( list && ( !fired || stack ) ) {
- if ( firing ) {
- stack.push( args );
- } else {
- fire( args );
}
}
- return this;
- },
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!fired;
}
+
+ if ( !set ) {
+ set = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( "*" ) :
+ [];
+ }
+
+ return { set: set, expr: expr };
};
- return self;
-};
-jQuery.extend({
-
- Deferred: function( func ) {
- var tuples = [
- // action, add listener, listener list, final state
- [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
- [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
- [ "notify", "progress", jQuery.Callbacks("memory") ]
- ],
- state = "pending",
- promise = {
- state: function() {
- return state;
- },
- always: function() {
- deferred.done( arguments ).fail( arguments );
- return this;
- },
- then: function( /* fnDone, fnFail, fnProgress */ ) {
- var fns = arguments;
- return jQuery.Deferred(function( newDefer ) {
- jQuery.each( tuples, function( i, tuple ) {
- var action = tuple[ 0 ],
- fn = fns[ i ];
- // deferred[ done | fail | progress ] for forwarding actions to newDefer
- deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
- function() {
- var returned = fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
- returned.promise()
- .done( newDefer.resolve )
- .fail( newDefer.reject )
- .progress( newDefer.notify );
- } else {
- newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
- }
- } :
- newDefer[ action ]
- );
- });
- fns = null;
- }).promise();
- },
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- return typeof obj === "object" ? jQuery.extend( obj, promise ) : promise;
- }
- },
- deferred = {};
+ Sizzle.filter = function( expr, set, inplace, not ) {
+ var match, anyFound,
+ type, found, item, filter, left,
+ i, pass,
+ old = expr,
+ result = [],
+ curLoop = set,
+ isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
- // Keep pipe for back-compat
- promise.pipe = promise.then;
+ while ( expr && set.length ) {
+ for ( type in Expr.filter ) {
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ filter = Expr.filter[ type ];
+ left = match[1];
- // Add list-specific methods
- jQuery.each( tuples, function( i, tuple ) {
- var list = tuple[ 2 ],
- stateString = tuple[ 3 ];
+ anyFound = false;
- // promise[ done | fail | progress ] = list.add
- promise[ tuple[1] ] = list.add;
+ match.splice(1,1);
- // Handle state
- if ( stateString ) {
- list.add(function() {
- // state = [ resolved | rejected ]
- state = stateString;
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
- // [ reject_list | resolve_list ].disable; progress_list.lock
- }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
- }
+ if ( curLoop === result ) {
+ result = [];
+ }
- // deferred[ resolve | reject | notify ] = list.fire
- deferred[ tuple[0] ] = list.fire;
- deferred[ tuple[0] + "With" ] = list.fireWith;
- });
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
- // Make the deferred a promise
- promise.promise( deferred );
+ if ( !match ) {
+ anyFound = found = true;
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ pass = not ^ found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
- // All done!
- return deferred;
- },
+ } else {
+ curLoop[i] = false;
+ }
- // Deferred helper
- when: function( subordinate /* , ..., subordinateN */ ) {
- var i = 0,
- resolveValues = core_slice.call( arguments ),
- length = resolveValues.length,
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
- // the count of uncompleted subordinates
- remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
- // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
- deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+ expr = expr.replace( Expr.match[ type ], "" );
- // Update function for both resolve and progress values
- updateFunc = function( i, contexts, values ) {
- return function( value ) {
- contexts[ i ] = this;
- values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
- if( values === progressValues ) {
- deferred.notifyWith( contexts, values );
- } else if ( !( --remaining ) ) {
- deferred.resolveWith( contexts, values );
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
}
- };
- },
+ }
- progressValues, progressContexts, resolveContexts;
+ // Improper expression
+ if ( expr === old ) {
+ if ( anyFound == null ) {
+ Sizzle.error( expr );
- // add listeners to Deferred subordinates; treat others as resolved
- if ( length > 1 ) {
- progressValues = new Array( length );
- progressContexts = new Array( length );
- resolveContexts = new Array( length );
- for ( ; i < length; i++ ) {
- if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
- resolveValues[ i ].promise()
- .done( updateFunc( i, resolveContexts, resolveValues ) )
- .fail( deferred.reject )
- .progress( updateFunc( i, progressContexts, progressValues ) );
- } else {
- --remaining;
+ } else {
+ break;
+ }
}
+
+ old = expr;
}
- }
- // if we're not waiting on anything, resolve the master
- if ( !remaining ) {
- deferred.resolveWith( resolveContexts, resolveValues );
- }
+ return curLoop;
+ };
- return deferred.promise();
- }
-});
-jQuery.support = (function() {
-
- var support,
- all,
- a,
- select,
- opt,
- input,
- fragment,
- eventName,
- i,
- isSupported,
- clickFn,
- div = document.createElement("div");
-
- // Preliminary tests
- div.setAttribute( "className", "t" );
- div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
-
- all = div.getElementsByTagName("*");
- a = div.getElementsByTagName("a")[ 0 ];
- a.style.cssText = "top:1px;float:left;opacity:.5";
-
- // Can't get basic test support
- if ( !all || !all.length || !a ) {
- return {};
- }
+ Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+ };
- // First batch of supports tests
- select = document.createElement("select");
- opt = select.appendChild( document.createElement("option") );
- input = div.getElementsByTagName("input")[ 0 ];
-
- support = {
- // IE strips leading whitespace when .innerHTML is used
- leadingWhitespace: ( div.firstChild.nodeType === 3 ),
-
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- tbody: !div.getElementsByTagName("tbody").length,
-
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- htmlSerialize: !!div.getElementsByTagName("link").length,
-
- // Get the style information from getAttribute
- // (IE uses .cssText instead)
- style: /top/.test( a.getAttribute("style") ),
-
- // Make sure that URLs aren't manipulated
- // (IE normalizes it by default)
- hrefNormalized: ( a.getAttribute("href") === "/a" ),
-
- // Make sure that element opacity exists
- // (IE uses filter instead)
- // Use a regex to work around a WebKit issue. See #5145
- opacity: /^0.5/.test( a.style.opacity ),
-
- // Verify style float existence
- // (IE uses styleFloat instead of cssFloat)
- cssFloat: !!a.style.cssFloat,
-
- // Make sure that if no value is specified for a checkbox
- // that it defaults to "on".
- // (WebKit defaults to "" instead)
- checkOn: ( input.value === "on" ),
-
- // Make sure that a selected-by-default option has a working selected property.
- // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
- optSelected: opt.selected,
-
- // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
- getSetAttribute: div.className !== "t",
-
- // Tests for enctype support on a form(#6743)
- enctype: !!document.createElement("form").enctype,
-
- // Makes sure cloning an html5 element does not cause problems
- // Where outerHTML is undefined, this still works
- html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
-
- // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
- boxModel: ( document.compatMode === "CSS1Compat" ),
-
- // Will be defined later
- submitBubbles: true,
- changeBubbles: true,
- focusinBubbles: false,
- deleteExpando: true,
- noCloneEvent: true,
- inlineBlockNeedsLayout: false,
- shrinkWrapBlocks: false,
- reliableMarginRight: true,
- boxSizingReliable: true,
- pixelPosition: false
- };
+ /**
+ * Utility function for retreiving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+ var getText = Sizzle.getText = function( elem ) {
+ var i, node,
+ nodeType = elem.nodeType,
+ ret = "";
+
+ if ( nodeType ) {
+ if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent || innerText for elements
+ if ( typeof elem.textContent === 'string' ) {
+ return elem.textContent;
+ } else if ( typeof elem.innerText === 'string' ) {
+ // Replace IE's carriage returns
+ return elem.innerText.replace( rReturn, '' );
+ } else {
+ // Traverse it's children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ } else {
- // Make sure checked status is properly cloned
- input.checked = true;
- support.noCloneChecked = input.cloneNode( true ).checked;
+ // If no nodeType, this is expected to be an array
+ for ( i = 0; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ if ( node.nodeType !== 8 ) {
+ ret += getText( node );
+ }
+ }
+ }
+ return ret;
+ };
- // Make sure that the options inside disabled selects aren't marked as disabled
- // (WebKit marks them as disabled)
- select.disabled = true;
- support.optDisabled = !opt.disabled;
+ var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+ },
- // Test to see if it's possible to delete an expando from an element
- // Fails in Internet Explorer
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
+ leftMatch: {},
- if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
- div.attachEvent( "onclick", clickFn = function() {
- // Cloning a node shouldn't copy over any
- // bound event handlers (IE does this)
- support.noCloneEvent = false;
- });
- div.cloneNode( true ).fireEvent("onclick");
- div.detachEvent( "onclick", clickFn );
- }
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
- // Check if a radio maintains its value
- // after being appended to the DOM
- input = document.createElement("input");
- input.value = "t";
- input.setAttribute( "type", "radio" );
- support.radioValue = input.value === "t";
-
- input.setAttribute( "checked", "checked" );
-
- // #11217 - WebKit loses check when the name is after the checked attribute
- input.setAttribute( "name", "t" );
-
- div.appendChild( input );
- fragment = document.createDocumentFragment();
- fragment.appendChild( div.lastChild );
-
- // WebKit doesn't clone checked state correctly in fragments
- support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
- // Check if a disconnected checkbox will retain its checked
- // value of true after appended to the DOM (IE6/7)
- support.appendChecked = input.checked;
-
- fragment.removeChild( input );
- fragment.appendChild( div );
-
- // Technique from Juriy Zaytsev
- // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
- // We only care about the case where non-standard event systems
- // are used, namely in IE. Short-circuiting here helps us to
- // avoid an eval call (in setAttribute) which can cause CSP
- // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
- if ( div.attachEvent ) {
- for ( i in {
- submit: true,
- change: true,
- focusin: true
- }) {
- eventName = "on" + i;
- isSupported = ( eventName in div );
- if ( !isSupported ) {
- div.setAttribute( eventName, "return;" );
- isSupported = ( typeof div[ eventName ] === "function" );
- }
- support[ i + "Bubbles" ] = isSupported;
- }
- }
+ attrHandle: {
+ href: function( elem ) {
+ return elem.getAttribute( "href" );
+ },
+ type: function( elem ) {
+ return elem.getAttribute( "type" );
+ }
+ },
- // Run tests that need a body at doc ready
- jQuery(function() {
- var container, div, tds, marginDiv,
- divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
- body = document.getElementsByTagName("body")[0];
+ relative: {
+ "+": function(checkSet, part){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !rNonWord.test( part ),
+ isPartStrNotTag = isPartStr && !isTag;
- if ( !body ) {
- // Return for frameset docs that don't have a body
- return;
- }
+ if ( isTag ) {
+ part = part.toLowerCase();
+ }
- container = document.createElement("div");
- container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
- body.insertBefore( container, body.firstChild );
-
- // Construct the test element
- div = document.createElement("div");
- container.appendChild( div );
-
- // Check if table cells still have offsetWidth/Height when they are set
- // to display:none and there are still other visible table cells in a
- // table row; if so, offsetWidth/Height are not reliable for use when
- // determining if an element has been hidden directly using
- // display:none (it is still safe to use offsets if a parent element is
- // hidden; don safety goggles and see bug #4512 for more information).
- // (only IE 8 fails this test)
- div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
- tds = div.getElementsByTagName("td");
- tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
- isSupported = ( tds[ 0 ].offsetHeight === 0 );
-
- tds[ 0 ].style.display = "";
- tds[ 1 ].style.display = "none";
-
- // Check if empty table cells still have offsetWidth/Height
- // (IE <= 8 fail this test)
- support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
-
- // Check box-sizing and margin behavior
- div.innerHTML = "";
- div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
- support.boxSizing = ( div.offsetWidth === 4 );
- support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
-
- // NOTE: To any future maintainer, window.getComputedStyle was used here
- // instead of getComputedStyle because it gave a better gzip size.
- // The difference between window.getComputedStyle and getComputedStyle is
- // 7 bytes
- if ( window.getComputedStyle ) {
- support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
- support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
- // Check if div with explicit width and no margin-right incorrectly
- // gets computed margin-right based on width of container. For more
- // info see bug #3333
- // Fails in WebKit before Feb 2011 nightlies
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
- marginDiv = document.createElement("div");
- marginDiv.style.cssText = div.style.cssText = divReset;
- marginDiv.style.marginRight = marginDiv.style.width = "0";
- div.style.width = "1px";
- div.appendChild( marginDiv );
- support.reliableMarginRight =
- !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
- }
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+ elem || false :
+ elem === part;
+ }
+ }
- if ( typeof div.style.zoom !== "undefined" ) {
- // Check if natively block-level elements act like inline-block
- // elements when setting their display to 'inline' and giving
- // them layout
- // (IE < 8 does this)
- div.innerHTML = "";
- div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
- support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
-
- // Check if elements with layout shrink-wrap their children
- // (IE 6 does this)
- div.style.display = "block";
- div.style.overflow = "visible";
- div.innerHTML = "<div></div>";
- div.firstChild.style.width = "5px";
- support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
-
- container.style.zoom = 1;
- }
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
- // Null elements to avoid leaks in IE
- body.removeChild( container );
- container = div = tds = marginDiv = null;
- });
+ ">": function( checkSet, part ) {
+ var elem,
+ isPartStr = typeof part === "string",
+ i = 0,
+ l = checkSet.length;
- // Null elements to avoid leaks in IE
- fragment.removeChild( div );
- all = a = select = opt = input = fragment = div = null;
+ if ( isPartStr && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
- return support;
-})();
-var rbrace = /^(?:\{.*\}|\[.*\])$/,
- rmultiDash = /([A-Z])/g;
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
-jQuery.extend({
- cache: {},
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+ }
+ }
- deletedIds: [],
+ } else {
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
- // Please use with caution
- uuid: 0,
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
- // Unique for each copy of jQuery on the page
- // Non-digits removed to match rinlinejQuery
- expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
- // The following elements throw uncatchable exceptions if you
- // attempt to add expando properties to them.
- noData: {
- "embed": true,
- // Ban all objects except for Flash (which handle expandos)
- "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
- "applet": true
- },
+ "": function(checkSet, part, isXML){
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
- hasData: function( elem ) {
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
- return !!elem && !isEmptyDataObject( elem );
- },
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
- data: function( elem, name, data, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
+ checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+ },
- var thisCache, ret,
- internalKey = jQuery.expando,
- getByName = typeof name === "string",
+ "~": function( checkSet, part, isXML ) {
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
- // We have to handle DOM nodes and JS objects differently because IE6-7
- // can't GC object references properly across the DOM-JS boundary
- isNode = elem.nodeType,
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
- // Only DOM nodes need the global jQuery cache; JS object data is
- // attached directly to the object so GC can occur automatically
- cache = isNode ? jQuery.cache : elem,
+ checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+ }
+ },
- // Only defining an ID for JS objects if its cache already exists allows
- // the code to shortcut on the same path as a DOM node with no cache
- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+ find: {
+ ID: function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ },
- // Avoid doing any more work than we need to when trying to get data on an
- // object that has no data at all
- if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
- return;
- }
+ NAME: function( match, context ) {
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [],
+ results = context.getElementsByName( match[1] );
- if ( !id ) {
- // Only DOM nodes need a new unique ID for each element since their data
- // ends up in the global cache
- if ( isNode ) {
- elem[ internalKey ] = id = jQuery.deletedIds.pop() || ++jQuery.uuid;
- } else {
- id = internalKey;
- }
- }
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
- if ( !cache[ id ] ) {
- cache[ id ] = {};
+ return ret.length === 0 ? null : ret;
+ }
+ },
- // Avoids exposing jQuery metadata on plain JS objects when the object
- // is serialized using JSON.stringify
- if ( !isNode ) {
- cache[ id ].toJSON = jQuery.noop;
- }
- }
+ TAG: function( match, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( match[1] );
+ }
+ }
+ },
+ preFilter: {
+ CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+ match = " " + match[1].replace( rBackslash, "" ) + " ";
- // An object can be passed to jQuery.data instead of a key/value pair; this gets
- // shallow copied over onto the existing cache
- if ( typeof name === "object" || typeof name === "function" ) {
- if ( pvt ) {
- cache[ id ] = jQuery.extend( cache[ id ], name );
- } else {
- cache[ id ].data = jQuery.extend( cache[ id ].data, name );
- }
- }
+ if ( isXML ) {
+ return match;
+ }
- thisCache = cache[ id ];
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
+ result.push( elem );
+ }
- // jQuery data() is stored in a separate object inside the object's internal data
- // cache in order to avoid key collisions between internal data and user-defined
- // data.
- if ( !pvt ) {
- if ( !thisCache.data ) {
- thisCache.data = {};
- }
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
- thisCache = thisCache.data;
- }
+ return false;
+ },
+
+ ID: function( match ) {
+ return match[1].replace( rBackslash, "" );
+ },
+
+ TAG: function( match, curLoop ) {
+ return match[1].replace( rBackslash, "" ).toLowerCase();
+ },
+
+ CHILD: function( match ) {
+ if ( match[1] === "nth" ) {
+ if ( !match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ match[2] = match[2].replace(/^\+|\s*/g, '');
+
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+ else if ( match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
- if ( data !== undefined ) {
- thisCache[ jQuery.camelCase( name ) ] = data;
- }
+ ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+ var name = match[1] = match[1].replace( rBackslash, "" );
- // Check for both converted-to-camel and non-converted data property names
- // If a data property was specified
- if ( getByName ) {
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
- // First Try to find as-is property data
- ret = thisCache[ name ];
+ // Handle if an un-quoted value was used
+ match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
- // Test for null|undefined property data
- if ( ret == null ) {
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
- // Try to find the camelCased property
- ret = thisCache[ jQuery.camelCase( name ) ];
- }
- } else {
- ret = thisCache;
- }
+ return match;
+ },
- return ret;
- },
+ PSEUDO: function( match, curLoop, inplace, result, not ) {
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
- removeData: function( elem, name, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
- var thisCache, i, l,
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
- isNode = elem.nodeType,
+ return false;
+ }
- // See jQuery.data for more information
- cache = isNode ? jQuery.cache : elem,
- id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
- // If there is already no cache entry for this object, there is no
- // purpose in continuing
- if ( !cache[ id ] ) {
- return;
- }
+ return match;
+ },
- if ( name ) {
+ POS: function( match ) {
+ match.unshift( true );
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
+ return match;
+ }
+ },
- if ( thisCache ) {
+ filters: {
+ enabled: function( elem ) {
+ return elem.disabled === false && elem.type !== "hidden";
+ },
- // Support array or space separated string names for data keys
- if ( !jQuery.isArray( name ) ) {
+ disabled: function( elem ) {
+ return elem.disabled === true;
+ },
- // try the string as a key before any manipulation
- if ( name in thisCache ) {
- name = [ name ];
- } else {
+ checked: function( elem ) {
+ return elem.checked === true;
+ },
- // split the camel cased version by spaces unless a key with the spaces exists
- name = jQuery.camelCase( name );
- if ( name in thisCache ) {
- name = [ name ];
- } else {
- name = name.split(" ");
- }
+ selected: function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
}
- }
- for ( i = 0, l = name.length; i < l; i++ ) {
- delete thisCache[ name[i] ];
- }
+ return elem.selected === true;
+ },
- // If there is no data left in the cache, we want to continue
- // and let the cache object itself get destroyed
- if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
- return;
- }
- }
- }
+ parent: function( elem ) {
+ return !!elem.firstChild;
+ },
- // See jQuery.data for more information
- if ( !pvt ) {
- delete cache[ id ].data;
+ empty: function( elem ) {
+ return !elem.firstChild;
+ },
- // Don't destroy the parent cache unless the internal data object
- // had been the only thing left in it
- if ( !isEmptyDataObject( cache[ id ] ) ) {
- return;
- }
- }
+ has: function( elem, i, match ) {
+ return !!Sizzle( match[3], elem ).length;
+ },
+
+ header: function( elem ) {
+ return (/h\d/i).test( elem.nodeName );
+ },
- // Destroy the cache
- if ( isNode ) {
- jQuery.cleanData( [ elem ], true );
+ text: function( elem ) {
+ var attr = elem.getAttribute( "type" ), type = elem.type;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
+ },
- // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
- } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
- delete cache[ id ];
+ radio: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
+ },
- // When all else fails, null
- } else {
- cache[ id ] = null;
- }
- },
+ checkbox: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
+ },
- // For internal use only.
- _data: function( elem, name, data ) {
- return jQuery.data( elem, name, data, true );
- },
+ file: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
+ },
- // A method for determining if a DOM node can handle the data expando
- acceptData: function( elem ) {
- var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+ password: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
+ },
- // nodes accept data unless otherwise specified; rejection can be conditional
- return !noData || noData !== true && elem.getAttribute("classid") === noData;
- }
-});
+ submit: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "submit" === elem.type;
+ },
-jQuery.fn.extend({
- data: function( key, value ) {
- var parts, part, attr, name, l,
- elem = this[0],
- i = 0,
- data = null;
+ image: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
+ },
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = jQuery.data( elem );
+ reset: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "reset" === elem.type;
+ },
- if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
- attr = elem.attributes;
- for ( l = attr.length; i < l; i++ ) {
- name = attr[i].name;
+ button: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && "button" === elem.type || name === "button";
+ },
- if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.substring(5) );
+ input: function( elem ) {
+ return (/input|select|textarea|button/i).test( elem.nodeName );
+ },
- dataAttr( elem, name, data[ name ] );
- }
- }
- jQuery._data( elem, "parsedAttrs", true );
+ focus: function( elem ) {
+ return elem === elem.ownerDocument.activeElement;
}
- }
+ },
+ setFilters: {
+ first: function( elem, i ) {
+ return i === 0;
+ },
- return data;
- }
+ last: function( elem, i, match, array ) {
+ return i === array.length - 1;
+ },
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each(function() {
- jQuery.data( this, key );
- });
- }
+ even: function( elem, i ) {
+ return i % 2 === 0;
+ },
+
+ odd: function( elem, i ) {
+ return i % 2 === 1;
+ },
- parts = key.split( ".", 2 );
- parts[1] = parts[1] ? "." + parts[1] : "";
- part = parts[1] + "!";
+ lt: function( elem, i, match ) {
+ return i < match[3] - 0;
+ },
- return jQuery.access( this, function( value ) {
+ gt: function( elem, i, match ) {
+ return i > match[3] - 0;
+ },
- if ( value === undefined ) {
- data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+ nth: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ },
- // Try to fetch any internally stored data first
- if ( data === undefined && elem ) {
- data = jQuery.data( elem, key );
- data = dataAttr( elem, key, data );
+ eq: function( elem, i, match ) {
+ return match[3] - 0 === i;
}
+ },
+ filter: {
+ PSEUDO: function( elem, match, i, array ) {
+ var name = match[1],
+ filter = Expr.filters[ name ];
- return data === undefined && parts[1] ?
- this.data( parts[0] ) :
- data;
- }
-
- parts[1] = value;
- this.each(function() {
- var self = jQuery( this );
+ if ( filter ) {
+ return filter( elem, i, match, array );
- self.triggerHandler( "setData" + part, parts );
- jQuery.data( this, key, value );
- self.triggerHandler( "changeData" + part, parts );
- });
- }, null, value, arguments.length > 1, null, false );
- },
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
- removeData: function( key ) {
- return this.each(function() {
- jQuery.removeData( this, key );
- });
- }
-});
+ } else if ( name === "not" ) {
+ var not = match[3];
-function dataAttr( elem, key, data ) {
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
+ for ( var j = 0, l = not.length; j < l; j++ ) {
+ if ( not[j] === elem ) {
+ return false;
+ }
+ }
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+ return true;
- data = elem.getAttribute( name );
+ } else {
+ Sizzle.error( name );
+ }
+ },
- if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- // Only convert to a number if it doesn't change the string
- +data + "" === data ? +data :
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
- data;
- } catch( e ) {}
-
- // Make sure we set the data so it isn't changed later
- jQuery.data( elem, key, data );
+ CHILD: function( elem, match ) {
+ var first, last,
+ doneName, parent, cache,
+ count, diff,
+ type = match[1],
+ node = elem;
+
+ switch ( type ) {
+ case "only":
+ case "first":
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
- } else {
- data = undefined;
- }
- }
+ if ( type === "first" ) {
+ return true;
+ }
- return data;
-}
+ node = elem;
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
- var name;
- for ( name in obj ) {
+ /* falls through */
+ case "last":
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
- // if the public data object is empty, the private is still empty
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
- continue;
- }
- if ( name !== "toJSON" ) {
- return false;
- }
- }
+ return true;
- return true;
-}
-jQuery.extend({
- queue: function( elem, type, data ) {
- var queue;
+ case "nth":
+ first = match[2];
+ last = match[3];
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- queue = jQuery._data( elem, type );
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !queue || jQuery.isArray(data) ) {
- queue = jQuery._data( elem, type, jQuery.makeArray(data) );
- } else {
- queue.push( data );
- }
- }
- return queue || [];
- }
- },
+ doneName = match[0];
+ parent = elem.parentNode;
- dequeue: function( elem, type ) {
- type = type || "fx";
+ if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
+ count = 0;
- var queue = jQuery.queue( elem, type ),
- fn = queue.shift(),
- hooks = jQuery._queueHooks( elem, type ),
- next = function() {
- jQuery.dequeue( elem, type );
- };
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- }
+ parent[ expando ] = doneName;
+ }
- if ( fn ) {
+ diff = elem.nodeIndex - last;
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
+ if ( first === 0 ) {
+ return diff === 0;
- // clear up the last queue stop function
- delete hooks.stop;
- fn.call( elem, next, hooks );
- }
- if ( !queue.length && hooks ) {
- hooks.empty.fire();
- }
- },
-
- // not intended for public consumption - generates a queueHooks object, or returns the current one
- _queueHooks: function( elem, type ) {
- var key = type + "queueHooks";
- return jQuery._data( elem, key ) || jQuery._data( elem, key, {
- empty: jQuery.Callbacks("once memory").add(function() {
- jQuery.removeData( elem, type + "queue", true );
- jQuery.removeData( elem, key, true );
- })
- });
- }
-});
+ } else {
+ return ( diff % first === 0 && diff / first >= 0 );
+ }
+ }
+ },
-jQuery.fn.extend({
- queue: function( type, data ) {
- var setter = 2;
+ ID: function( elem, match ) {
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
+ TAG: function( elem, match ) {
+ return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
+ },
- if ( arguments.length < setter ) {
- return jQuery.queue( this[0], type );
- }
+ CLASS: function( elem, match ) {
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
- return data === undefined ?
- this :
- this.each(function() {
- var queue = jQuery.queue( this, type, data );
+ ATTR: function( elem, match ) {
+ var name = match[1],
+ result = Sizzle.attr ?
+ Sizzle.attr( elem, name ) :
+ Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ !type && Sizzle.attr ?
+ result != null :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value !== check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
- // ensure a hooks for this queue
- jQuery._queueHooks( this, type );
+ POS: function( elem, match, i, array ) {
+ var name = match[2],
+ filter = Expr.setFilters[ name ];
- if ( type === "fx" && queue[0] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- });
- },
- dequeue: function( type ) {
- return this.each(function() {
- jQuery.dequeue( this, type );
- });
- },
- // Based off of the plugin by Clint Helfers, with permission.
- // http://blindsignals.com/index.php/2009/07/jquery-delay/
- delay: function( time, type ) {
- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
- type = type || "fx";
-
- return this.queue( type, function( next, hooks ) {
- var timeout = setTimeout( next, time );
- hooks.stop = function() {
- clearTimeout( timeout );
- };
- });
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, obj ) {
- var tmp,
- count = 1,
- defer = jQuery.Deferred(),
- elements = this,
- i = this.length,
- resolve = function() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
}
- };
+ }
+ };
- if ( typeof type !== "string" ) {
- obj = type;
- type = undefined;
- }
- type = type || "fx";
+ var origPOS = Expr.match.POS,
+ fescape = function(all, num){
+ return "\\" + (num - 0 + 1);
+ };
- while( i-- ) {
- if ( (tmp = jQuery._data( elements[ i ], type + "queueHooks" )) && tmp.empty ) {
- count++;
- tmp.empty.add( resolve );
- }
+ for ( var type in Expr.match ) {
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}
- resolve();
- return defer.promise( obj );
- }
-});
-var nodeHook, boolHook, fixSpecified,
- rclass = /[\t\r\n]/g,
- rreturn = /\r/g,
- rtype = /^(?:button|input)$/i,
- rfocusable = /^(?:button|input|object|select|textarea)$/i,
- rclickable = /^a(?:rea|)$/i,
- rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
- getSetAttribute = jQuery.support.getSetAttribute;
-
-jQuery.fn.extend({
- attr: function( name, value ) {
- return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
- },
-
- removeAttr: function( name ) {
- return this.each(function() {
- jQuery.removeAttr( this, name );
- });
- },
+// Expose origPOS
+// "global" as in regardless of relation to brackets/parens
+ Expr.match.globalPOS = origPOS;
- prop: function( name, value ) {
- return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
- },
+ var makeArray = function( array, results ) {
+ array = Array.prototype.slice.call( array, 0 );
- removeProp: function( name ) {
- name = jQuery.propFix[ name ] || name;
- return this.each(function() {
- // try/catch handles cases where IE balks (such as removing a property on window)
- try {
- this[ name ] = undefined;
- delete this[ name ];
- } catch( e ) {}
- });
- },
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
- addClass: function( value ) {
- var classNames, i, l, elem,
- setClass, c, cl;
+ return array;
+ };
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).addClass( value.call(this, j, this.className) );
- });
- }
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+ try {
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
- if ( value && typeof value === "string" ) {
- classNames = value.split( core_rspace );
+// Provide a fallback method if it does not work
+ } catch( e ) {
+ makeArray = function( array, results ) {
+ var i = 0,
+ ret = results || [];
- for ( i = 0, l = this.length; i < l; i++ ) {
- elem = this[ i ];
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
- if ( elem.nodeType === 1 ) {
- if ( !elem.className && classNames.length === 1 ) {
- elem.className = value;
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
} else {
- setClass = " " + elem.className + " ";
-
- for ( c = 0, cl = classNames.length; c < cl; c++ ) {
- if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
- setClass += classNames[ c ] + " ";
- }
+ for ( ; array[i]; i++ ) {
+ ret.push( array[i] );
}
- elem.className = jQuery.trim( setClass );
}
}
- }
- }
-
- return this;
- },
- removeClass: function( value ) {
- var removes, className, elem, c, cl, i, l;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).removeClass( value.call(this, j, this.className) );
- });
+ return ret;
+ };
}
- if ( (value && typeof value === "string") || value === undefined ) {
- removes = ( value || "" ).split( core_rspace );
- for ( i = 0, l = this.length; i < l; i++ ) {
- elem = this[ i ];
- if ( elem.nodeType === 1 && elem.className ) {
+ var sortOrder, siblingCheck;
- className = (" " + elem.className + " ").replace( rclass, " " );
+ if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
- // loop over each item in the removal list
- for ( c = 0, cl = removes.length; c < cl; c++ ) {
- // Remove until there is nothing to remove,
- while ( className.indexOf(" " + removes[ c ] + " ") > -1 ) {
- className = className.replace( " " + removes[ c ] + " " , " " );
- }
- }
- elem.className = value ? jQuery.trim( className ) : "";
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ return a.compareDocumentPosition ? -1 : 1;
}
- }
- }
- return this;
- },
+ return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+ };
- toggleClass: function( value, stateVal ) {
- var type = typeof value,
- isBool = typeof stateVal === "boolean";
+ } else {
+ sortOrder = function( a, b ) {
+ // The nodes are identical, we can exit early
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
+ } else if ( a.sourceIndex && b.sourceIndex ) {
+ return a.sourceIndex - b.sourceIndex;
+ }
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( i ) {
- jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
- });
- }
+ var al, bl,
+ ap = [],
+ bp = [],
+ aup = a.parentNode,
+ bup = b.parentNode,
+ cur = aup;
- return this.each(function() {
- if ( type === "string" ) {
- // toggle individual class names
- var className,
- i = 0,
- self = jQuery( this ),
- state = stateVal,
- classNames = value.split( core_rspace );
+ // If the nodes are siblings (or identical) we can do a quick check
+ if ( aup === bup ) {
+ return siblingCheck( a, b );
+
+ // If no parents were found then the nodes are disconnected
+ } else if ( !aup ) {
+ return -1;
- while ( (className = classNames[ i++ ]) ) {
- // check each className given, space separated list
- state = isBool ? state : !self.hasClass( className );
- self[ state ? "addClass" : "removeClass" ]( className );
+ } else if ( !bup ) {
+ return 1;
}
- } else if ( type === "undefined" || type === "boolean" ) {
- if ( this.className ) {
- // store className if set
- jQuery._data( this, "__className__", this.className );
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while ( cur ) {
+ ap.unshift( cur );
+ cur = cur.parentNode;
}
- // toggle whole className
- this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
- }
- });
- },
+ cur = bup;
- hasClass: function( selector ) {
- var className = " " + selector + " ",
- i = 0,
- l = this.length;
- for ( ; i < l; i++ ) {
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
- return true;
- }
- }
+ while ( cur ) {
+ bp.unshift( cur );
+ cur = cur.parentNode;
+ }
- return false;
- },
+ al = ap.length;
+ bl = bp.length;
- val: function( value ) {
- var hooks, ret, isFunction,
- elem = this[0];
+ // Start walking down the tree looking for a discrepancy
+ for ( var i = 0; i < al && i < bl; i++ ) {
+ if ( ap[i] !== bp[i] ) {
+ return siblingCheck( ap[i], bp[i] );
+ }
+ }
- if ( !arguments.length ) {
- if ( elem ) {
- hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+ // We ended someplace up the tree so do a sibling check
+ return i === al ?
+ siblingCheck( a, bp[i], -1 ) :
+ siblingCheck( ap[i], b, 1 );
+ };
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ siblingCheck = function( a, b, ret ) {
+ if ( a === b ) {
return ret;
}
- ret = elem.value;
+ var cur = a.nextSibling;
- return typeof ret === "string" ?
- // handle most common string cases
- ret.replace(rreturn, "") :
- // handle cases where value is null/undef or number
- ret == null ? "" : ret;
- }
+ while ( cur ) {
+ if ( cur === b ) {
+ return -1;
+ }
- return;
+ cur = cur.nextSibling;
+ }
+
+ return 1;
+ };
}
- isFunction = jQuery.isFunction( value );
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+ (function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("div"),
+ id = "script" + (new Date()).getTime(),
+ root = document.documentElement;
- return this.each(function( i ) {
- var val,
- self = jQuery(this);
+ form.innerHTML = "<a name='" + id + "'/>";
- if ( this.nodeType !== 1 ) {
- return;
- }
+ // Inject it into the root element, check its status, and remove it quickly
+ root.insertBefore( form, root.firstChild );
- if ( isFunction ) {
- val = value.call( this, i, self.val() );
- } else {
- val = value;
- }
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( document.getElementById( id ) ) {
+ Expr.find.ID = function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
- // Treat null/undefined as ""; convert numbers to string
- if ( val == null ) {
- val = "";
- } else if ( typeof val === "number" ) {
- val += "";
- } else if ( jQuery.isArray( val ) ) {
- val = jQuery.map(val, function ( value ) {
- return value == null ? "" : value + "";
- });
- }
+ return m ?
+ m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
- hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+ Expr.filter.ID = function( elem, match ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
- // If set returns undefined, fall back to normal setting
- if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
- this.value = val;
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
}
- });
- }
-});
-jQuery.extend({
- valHooks: {
- option: {
- get: function( elem ) {
- // attributes.value is undefined in Blackberry 4.7 but
- // uses .value. See #6932
- var val = elem.attributes.value;
- return !val || val.specified ? elem.value : elem.text;
- }
- },
- select: {
- get: function( elem ) {
- var value, i, max, option,
- index = elem.selectedIndex,
- values = [],
- options = elem.options,
- one = elem.type === "select-one";
-
- // Nothing was selected
- if ( index < 0 ) {
- return null;
- }
+ root.removeChild( form );
- // Loop through all the selected options
- i = one ? index : 0;
- max = one ? index + 1 : options.length;
- for ( ; i < max; i++ ) {
- option = options[ i ];
+ // release memory in IE
+ root = form = null;
+ })();
- // Don't return options that are disabled or in a disabled optgroup
- if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
- (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+ (function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function( match, context ) {
+ var results = context.getElementsByTagName( match[1] );
- // Get the specific value for the option
- value = jQuery( option ).val();
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
- // We don't need an array for one selects
- if ( one ) {
- return value;
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
}
- // Multi-Selects return an array
- values.push( value );
+ results = tmp;
}
- }
-
- // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
- if ( one && !values.length && options.length ) {
- return jQuery( options[ index ] ).val();
- }
- return values;
- },
+ return results;
+ };
+ }
- set: function( elem, value ) {
- var values = jQuery.makeArray( value );
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
- jQuery(elem).find("option").each(function() {
- this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
- });
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
- if ( !values.length ) {
- elem.selectedIndex = -1;
- }
- return values;
+ Expr.attrHandle.href = function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ };
}
- }
- },
- // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
- attrFn: {},
+ // release memory in IE
+ div = null;
+ })();
- attr: function( elem, name, value, pass ) {
- var ret, hooks, notxml,
- nType = elem.nodeType;
+ if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle,
+ div = document.createElement("div"),
+ id = "__sizzle__";
- // don't get/set attributes on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
+ div.innerHTML = "<p class='TEST'></p>";
- if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
- return jQuery( elem )[ name ]( value );
- }
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
- // Fallback to prop when attributes are not supported
- if ( typeof elem.getAttribute === "undefined" ) {
- return jQuery.prop( elem, name, value );
- }
+ Sizzle = function( query, context, extra, seed ) {
+ context = context || document;
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && !Sizzle.isXML(context) ) {
+ // See if we find a selector to speed up
+ var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
- // All attributes are lowercase
- // Grab necessary hook if one is defined
- if ( notxml ) {
- name = name.toLowerCase();
- hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
- }
+ if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
+ // Speed-up: Sizzle("TAG")
+ if ( match[1] ) {
+ return makeArray( context.getElementsByTagName( query ), extra );
- if ( value !== undefined ) {
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
+ return makeArray( context.getElementsByClassName( match[2] ), extra );
+ }
+ }
- if ( value === null ) {
- jQuery.removeAttr( elem, name );
- return;
+ if ( context.nodeType === 9 ) {
+ // Speed-up: Sizzle("body")
+ // The body element only exists once, optimize finding it
+ if ( query === "body" && context.body ) {
+ return makeArray( [ context.body ], extra );
+
+ // Speed-up: Sizzle("#ID")
+ } else if ( match && match[3] ) {
+ var elem = context.getElementById( match[3] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id === match[3] ) {
+ return makeArray( [ elem ], extra );
+ }
- } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
- return ret;
+ } else {
+ return makeArray( [], extra );
+ }
+ }
- } else {
- elem.setAttribute( name, "" + value );
- return value;
- }
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(qsaError) {}
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ var oldContext = context,
+ old = context.getAttribute( "id" ),
+ nid = old || id,
+ hasParent = context.parentNode,
+ relativeHierarchySelector = /^\s*[+~]/.test( query );
+
+ if ( !old ) {
+ context.setAttribute( "id", nid );
+ } else {
+ nid = nid.replace( /'/g, "\\$&" );
+ }
+ if ( relativeHierarchySelector && hasParent ) {
+ context = context.parentNode;
+ }
- } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
+ try {
+ if ( !relativeHierarchySelector || hasParent ) {
+ return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+ }
+
+ } catch(pseudoError) {
+ } finally {
+ if ( !old ) {
+ oldContext.removeAttribute( "id" );
+ }
+ }
+ }
+ }
- } else {
+ return oldSizzle(query, context, extra, seed);
+ };
- ret = elem.getAttribute( name );
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
- // Non-existent attributes return null, we normalize to undefined
- return ret === null ?
- undefined :
- ret;
+ // release memory in IE
+ div = null;
+ })();
}
- },
-
- removeAttr: function( elem, value ) {
- var propName, attrNames, name, isBool,
- i = 0;
- if ( value && elem.nodeType === 1 ) {
+ (function(){
+ var html = document.documentElement,
+ matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
- attrNames = value.split( core_rspace );
+ if ( matches ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9 fails this)
+ var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
+ pseudoWorks = false;
- for ( ; i < attrNames.length; i++ ) {
- name = attrNames[ i ];
+ try {
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( document.documentElement, "[test!='']:sizzle" );
- if ( name ) {
- propName = jQuery.propFix[ name ] || name;
- isBool = rboolean.test( name );
+ } catch( pseudoError ) {
+ pseudoWorks = true;
+ }
- // See #9699 for explanation of this approach (setting first, then removal)
- // Do not do this for boolean attributes (see #10870)
- if ( !isBool ) {
- jQuery.attr( elem, name, "" );
- }
- elem.removeAttribute( getSetAttribute ? name : propName );
+ Sizzle.matchesSelector = function( node, expr ) {
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
- // Set corresponding property to false for boolean attributes
- if ( isBool && propName in elem ) {
- elem[ propName ] = false;
+ if ( !Sizzle.isXML( node ) ) {
+ try {
+ if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+ var ret = matches.call( node, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || !disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9, so check for that
+ node.document && node.document.nodeType !== 11 ) {
+ return ret;
+ }
+ }
+ } catch(e) {}
}
- }
- }
- }
- },
- attrHooks: {
- type: {
- set: function( elem, value ) {
- // We can't allow the type property to be changed (since it causes problems in IE)
- if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
- jQuery.error( "type property can't be changed" );
- } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
- // Setting the type on a radio button after the value resets the value in IE6-9
- // Reset value to it's default in case type is set after value
- // This is for element creation
- var val = elem.value;
- elem.setAttribute( "type", value );
- if ( val ) {
- elem.value = val;
- }
- return value;
- }
- }
- },
- // Use the value property for back compat
- // Use the nodeHook for button elements in IE6/7 (#1954)
- value: {
- get: function( elem, name ) {
- if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
- return nodeHook.get( elem, name );
- }
- return name in elem ?
- elem.value :
- null;
- },
- set: function( elem, value, name ) {
- if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
- return nodeHook.set( elem, value, name );
- }
- // Does not return so that setAttribute is also used
- elem.value = value;
+ return Sizzle(expr, null, null, [node]).length > 0;
+ };
}
- }
- },
-
- propFix: {
- tabindex: "tabIndex",
- readonly: "readOnly",
- "for": "htmlFor",
- "class": "className",
- maxlength: "maxLength",
- cellspacing: "cellSpacing",
- cellpadding: "cellPadding",
- rowspan: "rowSpan",
- colspan: "colSpan",
- usemap: "useMap",
- frameborder: "frameBorder",
- contenteditable: "contentEditable"
- },
-
- prop: function( elem, name, value ) {
- var ret, hooks, notxml,
- nType = elem.nodeType;
-
- // don't get/set properties on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
+ })();
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+ (function(){
+ var div = document.createElement("div");
- if ( notxml ) {
- // Fix name and attach hooks
- name = jQuery.propFix[ name ] || name;
- hooks = jQuery.propHooks[ name ];
- }
-
- if ( value !== undefined ) {
- if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
- return ret;
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
- } else {
- return ( elem[ name ] = value );
+ // Opera can't find a second classname (in 9.6)
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+ return;
}
- } else {
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
- } else {
- return elem[ name ];
+ if ( div.getElementsByClassName("e").length === 1 ) {
+ return;
}
- }
- },
- propHooks: {
- tabIndex: {
- get: function( elem ) {
- // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
- // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
- var attributeNode = elem.getAttributeNode("tabindex");
-
- return attributeNode && attributeNode.specified ?
- parseInt( attributeNode.value, 10 ) :
- rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
- 0 :
- undefined;
- }
- }
- }
-});
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function( match, context, isXML ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
-// Hook for boolean attributes
-boolHook = {
- get: function( elem, name ) {
- // Align boolean attributes with corresponding properties
- // Fall back to attribute presence where some booleans are not supported
- var attrNode,
- property = jQuery.prop( elem, name );
- return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
- name.toLowerCase() :
- undefined;
- },
- set: function( elem, value, name ) {
- var propName;
- if ( value === false ) {
- // Remove boolean attributes when set to false
- jQuery.removeAttr( elem, name );
- } else {
- // value is true since we know at this point it's type boolean and not false
- // Set boolean attributes to the same name and set the DOM property
- propName = jQuery.propFix[ name ] || name;
- if ( propName in elem ) {
- // Only set the IDL specifically if it already exists on the element
- elem[ propName ] = true;
- }
+ // release memory in IE
+ div = null;
+ })();
- elem.setAttribute( name, name.toLowerCase() );
- }
- return name;
- }
-};
+ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !getSetAttribute ) {
+ if ( elem ) {
+ var match = false;
- fixSpecified = {
- name: true,
- id: true,
- coords: true
- };
+ elem = elem[dir];
- // Use this for any attribute in IE6/7
- // This fixes almost every IE6/7 issue
- nodeHook = jQuery.valHooks.button = {
- get: function( elem, name ) {
- var ret;
- ret = elem.getAttributeNode( name );
- return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
- ret.value :
- undefined;
- },
- set: function( elem, value, name ) {
- // Set the existing or create a new attribute node
- var ret = elem.getAttributeNode( name );
- if ( !ret ) {
- ret = document.createAttribute( name );
- elem.setAttributeNode( ret );
- }
- return ( ret.value = value + "" );
- }
- };
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
- // Set width and height to auto instead of 0 on empty string( Bug #8150 )
- // This is for removals
- jQuery.each([ "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
- set: function( elem, value ) {
- if ( value === "" ) {
- elem.setAttribute( name, "auto" );
- return value;
- }
- }
- });
- });
+ if ( elem.nodeType === 1 && !isXML ){
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
- // Set contenteditable to false on removals(#10429)
- // Setting to empty string throws an error as an invalid value
- jQuery.attrHooks.contenteditable = {
- get: nodeHook.get,
- set: function( elem, value, name ) {
- if ( value === "" ) {
- value = "false";
- }
- nodeHook.set( elem, value, name );
- }
- };
-}
+ if ( elem.nodeName.toLowerCase() === cur ) {
+ match = elem;
+ break;
+ }
+ elem = elem[dir];
+ }
-// Some attributes require a special call on IE
-if ( !jQuery.support.hrefNormalized ) {
- jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
- get: function( elem ) {
- var ret = elem.getAttribute( name, 2 );
- return ret === null ? undefined : ret;
+ checkSet[i] = match;
+ }
}
- });
- });
-}
-
-if ( !jQuery.support.style ) {
- jQuery.attrHooks.style = {
- get: function( elem ) {
- // Return undefined in the case of empty string
- // Normalize to lowercase since IE uppercases css property names
- return elem.style.cssText.toLowerCase() || undefined;
- },
- set: function( elem, value ) {
- return ( elem.style.cssText = "" + value );
}
- };
-}
-// Safari mis-reports the default selected property of an option
-// Accessing the parent's selectedIndex property fixes it
-if ( !jQuery.support.optSelected ) {
- jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
- get: function( elem ) {
- var parent = elem.parentNode;
+ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
- if ( parent ) {
- parent.selectedIndex;
+ if ( elem ) {
+ var match = false;
- // Make sure that it also works with optgroups, see #5701
- if ( parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- }
- return null;
- }
- });
-}
+ elem = elem[dir];
-// IE6/7 call enctype encoding
-if ( !jQuery.support.enctype ) {
- jQuery.propFix.enctype = "encoding";
-}
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
-// Radios and checkboxes getter/setter
-if ( !jQuery.support.checkOn ) {
- jQuery.each([ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = {
- get: function( elem ) {
- // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
- return elem.getAttribute("value") === null ? "on" : elem.value;
- }
- };
- });
-}
-jQuery.each([ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
- set: function( elem, value ) {
- if ( jQuery.isArray( value ) ) {
- return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
- }
- }
- });
-});
-var rformElems = /^(?:textarea|input|select)$/i,
- rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
- rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|contextmenu)|click/,
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
- hoverHack = function( events ) {
- return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
- };
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
- add: function( elem, types, handler, data, selector ) {
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
- var elemData, eventHandle, events,
- t, tns, type, namespaces, handleObj,
- handleObjIn, handlers, special;
+ elem = elem[dir];
+ }
- // Don't attach events to noData or text/comment nodes (allow plain objects tho)
- if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
- return;
+ checkSet[i] = match;
+ }
+ }
}
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
+ if ( document.documentElement.contains ) {
+ Sizzle.contains = function( a, b ) {
+ return a !== b && (a.contains ? a.contains(b) : true);
+ };
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
+ } else if ( document.documentElement.compareDocumentPosition ) {
+ Sizzle.contains = function( a, b ) {
+ return !!(a.compareDocumentPosition(b) & 16);
+ };
- // Init the element's event structure and main handler, if this is the first
- events = elemData.events;
- if ( !events ) {
- elemData.events = events = {};
- }
- eventHandle = elemData.handle;
- if ( !eventHandle ) {
- elemData.handle = eventHandle = function( e ) {
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
- undefined;
+ } else {
+ Sizzle.contains = function() {
+ return false;
};
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
- eventHandle.elem = elem;
}
- // Handle multiple events separated by a space
- // jQuery(...).bind("mouseover mouseout", fn);
- types = jQuery.trim( hoverHack(types) ).split( " " );
- for ( t = 0; t < types.length; t++ ) {
+ Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
- tns = rtypenamespace.exec( types[t] ) || [];
- type = tns[1];
- namespaces = ( tns[2] || "" ).split( "." ).sort();
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+ };
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
+ var posProcess = function( selector, context, seed ) {
+ var match,
+ tmpSet = [],
+ later = "",
+ root = context.nodeType ? [context] : context;
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
+ selector = Expr.relative[selector] ? selector + "*" : selector;
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend({
- type: type,
- origType: tns[1],
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- namespace: namespaces.join(".")
- }, handleObjIn );
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet, seed );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+ };
- // Init the event handler queue if we're the first
- handlers = events[ type ];
- if ( !handlers ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
+// EXPOSE
+// Override sizzle attribute retrieval
+ Sizzle.attr = jQuery.attr;
+ Sizzle.selectors.attrMap = {};
+ jQuery.find = Sizzle;
+ jQuery.expr = Sizzle.selectors;
+ jQuery.expr[":"] = jQuery.expr.filters;
+ jQuery.unique = Sizzle.uniqueSort;
+ jQuery.text = Sizzle.getText;
+ jQuery.isXMLDoc = Sizzle.isXML;
+ jQuery.contains = Sizzle.contains;
+
+
+ })();
+
+
+ var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ slice = Array.prototype.slice,
+ POS = jQuery.expr.match.globalPOS,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
- // Only use addEventListener/attachEvent if the special events handler returns false
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- // Bind the global event handler to the element
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle, false );
+ jQuery.fn.extend({
+ find: function( selector ) {
+ var self = this,
+ i, l;
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, eventHandle );
+ if ( typeof selector !== "string" ) {
+ return jQuery( selector ).filter(function() {
+ for ( i = 0, l = self.length; i < l; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
}
- }
+ });
}
- if ( special.add ) {
- special.add.call( elem, handleObj );
+ var ret = this.pushStack( "", "find", selector ),
+ length, n, r;
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( n = length; n < ret.length; n++ ) {
+ for ( r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
}
}
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
+ return ret;
+ },
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
- global: {},
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ POS.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
+ closest: function( selectors, context ) {
+ var ret = [], i, l, cur = this[0];
- var t, tns, type, origType, namespaces, origCount,
- j, events, special, eventType, handleObj,
- elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+ // Array (deprecated as of jQuery 1.7)
+ if ( jQuery.isArray( selectors ) ) {
+ var level = 1;
- if ( !elemData || !(events = elemData.events) ) {
- return;
- }
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( i = 0; i < selectors.length; i++ ) {
- // Once for each type.namespace in types; type may be omitted
- types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
- for ( t = 0; t < types.length; t++ ) {
- tns = rtypenamespace.exec( types[t] ) || [];
- type = origType = tns[1];
- namespaces = tns[2];
+ if ( jQuery( cur ).is( selectors[ i ] ) ) {
+ ret.push({ selector: selectors[ i ], elem: cur, level: level });
+ }
+ }
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ cur = cur.parentNode;
+ level++;
}
- continue;
+
+ return ret;
}
- special = jQuery.event.special[ type ] || {};
- type = ( selector? special.delegateType : special.bindType ) || type;
- eventType = events[ type ] || [];
- origCount = eventType.length;
- namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
+ // String
+ var pos = POS.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
- // Remove matching events
- for ( j = 0; j < eventType.length; j++ ) {
- handleObj = eventType[ j ];
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ cur = this[i];
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
- eventType.splice( j--, 1 );
+ while ( cur ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
- if ( handleObj.selector ) {
- eventType.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
+ } else {
+ cur = cur.parentNode;
+ if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
+ break;
+ }
}
}
}
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( eventType.length === 0 && origCount !== eventType.length ) {
- if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- delete elemData.handle;
-
- // removeData also checks for emptiness and clears the expando if empty
- // so use it instead of delete
- jQuery.removeData( elem, "events", true );
- }
- },
-
- // Events that are safe to short-circuit if no handlers are attached.
- // Native DOM events should not be added, they may have inline handlers.
- customEvent: {
- "getData": true,
- "setData": true,
- "changeData": true
- },
-
- trigger: function( event, data, elem, onlyHandlers ) {
- // Don't do events on text and comment nodes
- if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
- return;
- }
-
- // Event object or event type
- var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
- type = event.type || event,
- namespaces = [];
+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
-
- if ( type.indexOf( "!" ) >= 0 ) {
- // Exclusive events trigger only for the exact event (no namespaces)
- type = type.slice(0, -1);
- exclusive = true;
- }
+ return this.pushStack( ret, "closest", selectors );
+ },
- if ( type.indexOf( "." ) >= 0 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split(".");
- type = namespaces.shift();
- namespaces.sort();
- }
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
- if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
- // No jQuery handlers for this event type, and it can't have inline handlers
- return;
- }
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+ }
- // Caller can pass in an Event, Object, or just an event type string
- event = typeof event === "object" ?
- // jQuery.Event object
- event[ jQuery.expando ] ? event :
- // Object literal
- new jQuery.Event( type, event ) :
- // Just the event type (string)
- new jQuery.Event( type );
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
- event.type = type;
- event.isTrigger = true;
- event.exclusive = exclusive;
- event.namespace = namespaces.join( "." );
- event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
- ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
- // Handle a global trigger
- if ( !elem ) {
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
- // TODO: Stop taunting the data cache; remove global events and always attach to document
- cache = jQuery.cache;
- for ( i in cache ) {
- if ( cache[ i ].events && cache[ i ].events[ type ] ) {
- jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
- }
- }
- return;
- }
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
+ andSelf: function() {
+ return this.add( this.prevObject );
}
+ });
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data != null ? jQuery.makeArray( data ) : [];
- data.unshift( event );
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+ function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+ }
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
+ jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
}
+ }, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- eventPath = [[ elem, special.bindType || type ]];
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
- bubbleType = special.delegateType || type;
- cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
- for ( old = elem; cur; cur = cur.parentNode ) {
- eventPath.push([ cur, bubbleType ]);
- old = cur;
+ if ( !runtil.test( name ) ) {
+ selector = until;
}
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( old === (elem.ownerDocument || document) ) {
- eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
}
- }
-
- // Fire handlers on the event path
- for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
- cur = eventPath[i][0];
- event.type = eventPath[i][1];
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
- // Note that this is a bare JS function and not a jQuery handler
- handle = ontype && cur[ ontype ];
- if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
- event.preventDefault();
+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
}
- }
- event.type = type;
-
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
- if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
- !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
-
- // Call a native DOM method on the target with the same name name as the event.
- // Can't use an .isFunction() check here because IE6/7 fails that test.
- // Don't do default actions on window, that's where global variables be (#6170)
- // IE<9 dies on focus/blur to hidden element (#1486)
- if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+ return this.pushStack( ret, name, slice.call( arguments ).join(",") );
+ };
+ });
- // Don't re-trigger an onFOO event when we call its FOO() method
- old = elem[ ontype ];
+ jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
- if ( old ) {
- elem[ ontype ] = null;
- }
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- elem[ type ]();
- jQuery.event.triggered = undefined;
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
- if ( old ) {
- elem[ ontype ] = old;
- }
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
}
+ cur = cur[dir];
}
- }
+ return matched;
+ },
- return event.result;
- },
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
- dispatch: function( event ) {
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
- // Make a writable jQuery.Event from the native event object
- event = jQuery.event.fix( event || window.event );
+ return cur;
+ },
- var i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related,
- handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
- delegateCount = handlers.delegateCount,
- args = [].slice.call( arguments ),
- run_all = !event.exclusive && !event.namespace,
- special = jQuery.event.special[ event.type ] || {},
- handlerQueue = [];
+ sibling: function( n, elem ) {
+ var r = [];
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[0] = event;
- event.delegateTarget = this;
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
+ return r;
}
+ });
- // Determine handlers that should run if there are delegated events
- // Avoid non-left-click bubbling in Firefox (#3861)
- if ( delegateCount && !(event.button && event.type === "click") ) {
+// Implement the identical functionality for filter and not
+ function winnow( elements, qualifier, keep ) {
- // Pregenerate a single jQuery object for reuse with .is()
- jqcur = jQuery(this);
- jqcur.context = this;
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
- for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
- // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #xxxx)
- if ( cur.disabled !== true || event.type !== "click" ) {
- selMatch = {};
- matches = [];
- jqcur[0] = cur;
- for ( i = 0; i < delegateCount; i++ ) {
- handleObj = handlers[ i ];
- sel = handleObj.selector;
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( elem === qualifier ) === keep;
+ });
- if ( selMatch[ sel ] === undefined ) {
- selMatch[ sel ] = jqcur.is( sel );
- }
- if ( selMatch[ sel ] ) {
- matches.push( handleObj );
- }
- }
- if ( matches.length ) {
- handlerQueue.push({ elem: cur, matches: matches });
- }
- }
- }
- }
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
- // Add the remaining (directly-bound) handlers
- if ( handlers.length > delegateCount ) {
- handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
}
- // Run delegates first; they may want to stop propagation beneath us
- for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
- matched = handlerQueue[ i ];
- event.currentTarget = matched.elem;
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+ }
- for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
- handleObj = matched.matches[ j ];
- // Triggered event must either 1) be non-exclusive and have no namespace, or
- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
- if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
- event.data = handleObj.data;
- event.handleObj = handleObj;
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
- .apply( matched.elem, args );
+ function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
- if ( ret !== undefined ) {
- event.result = ret;
- if ( ret === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
}
}
+ return safeFrag;
+ }
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
-
- return event.result;
- },
+ var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style)/i,
+ rnocache = /<(?:script|object|embed|option|style)/i,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /\/(java|ecma)script/i,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ area: [ 1, "<map>", "</map>" ],
+ _default: [ 0, "", "" ]
+ },
+ safeFragment = createSafeFragment( document );
- // Includes some event props shared by KeyEvent and MouseEvent
- // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
- props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+ wrapMap.optgroup = wrapMap.option;
+ wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+ wrapMap.th = wrapMap.td;
- fixHooks: {},
+// IE can't serialize <link> and <script> tags normally
+ if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+ }
- keyHooks: {
- props: "char charCode key keyCode".split(" "),
- filter: function( event, original ) {
+ jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
- // Add which for key events
- if ( event.which == null ) {
- event.which = original.charCode != null ? original.charCode : original.keyCode;
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
}
- return event;
- }
- },
-
- mouseHooks: {
- props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
- filter: function( event, original ) {
- var eventDoc, doc, body,
- button = original.button,
- fromElement = original.fromElement;
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && original.clientX != null ) {
- eventDoc = event.target.ownerDocument || document;
- doc = eventDoc.documentElement;
- body = eventDoc.body;
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
- event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
- event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
- }
+ wrap.map(function() {
+ var elem = this;
- // Add relatedTarget, if necessary
- if ( !event.relatedTarget && fromElement ) {
- event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
- }
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
- // Add which for click: 1 === left; 2 === middle; 3 === right
- // Note: button is not normalized, so don't use it
- if ( !event.which && button !== undefined ) {
- event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ return elem;
+ }).append( this );
}
- return event;
- }
- },
-
- fix: function( event ) {
- if ( event[ jQuery.expando ] ) {
- return event;
- }
+ return this;
+ },
- // Create a writable copy of the event object and normalize some properties
- var i, prop,
- originalEvent = event,
- fixHook = jQuery.event.fixHooks[ event.type ] || {},
- copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
- event = jQuery.Event( originalEvent );
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
- for ( i = copy.length; i; ) {
- prop = copy[ --i ];
- event[ prop ] = originalEvent[ prop ];
- }
+ if ( contents.length ) {
+ contents.wrapAll( html );
- // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
- if ( !event.target ) {
- event.target = originalEvent.srcElement || document;
- }
+ } else {
+ self.append( html );
+ }
+ });
+ },
- // Target should not be a text node (#504, Safari)
- if ( event.target.nodeType === 3 ) {
- event.target = event.target.parentNode;
- }
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
- // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
- event.metaKey = !!event.metaKey;
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
- return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
- },
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
- special: {
- ready: {
- // Make sure the ready event is setup
- setup: jQuery.bindReady
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
},
- load: {
- // Prevent triggered image.load events from bubbling to window.load
- noBubble: true
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
},
- focus: {
- delegateType: "focusin"
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery.clean( arguments );
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
+ }
},
- blur: {
- delegateType: "focusout"
+
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery.clean(arguments) );
+ return set;
+ }
},
- beforeunload: {
- setup: function( data, namespaces, eventHandle ) {
- // We only want to do this special case on windows
- if ( jQuery.isWindow( this ) ) {
- this.onbeforeunload = eventHandle;
- }
- },
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
- teardown: function( namespaces, eventHandle ) {
- if ( this.onbeforeunload === eventHandle ) {
- this.onbeforeunload = null;
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
}
}
- }
- },
-
- simulate: function( type, elem, event, bubble ) {
- // Piggyback on a donor event to simulate a different one.
- // Fake originalEvent to avoid donor's stopPropagation, but if the
- // simulated event prevents default then we do the same on the donor.
- var e = jQuery.extend(
- new jQuery.Event(),
- event,
- { type: type,
- isSimulated: true,
- originalEvent: {}
- }
- );
- if ( bubble ) {
- jQuery.event.trigger( e, null, elem );
- } else {
- jQuery.event.dispatch.call( elem, e );
- }
- if ( e.isDefaultPrevented() ) {
- event.preventDefault();
- }
- }
-};
-
-// Some plugins are using, but it's undocumented/deprecated and will be removed.
-// The 1.7 special event interface should provide all the hooks needed now.
-jQuery.event.handle = jQuery.event.dispatch;
-jQuery.removeEvent = document.removeEventListener ?
- function( elem, type, handle ) {
- if ( elem.removeEventListener ) {
- elem.removeEventListener( type, handle, false );
- }
- } :
- function( elem, type, handle ) {
- var name = "on" + type;
+ return this;
+ },
- if ( elem.detachEvent ) {
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
- // #8545, #7054, preventing memory leaks for custom events in IE6-8 –
- // detachEvent needed property on element, by name of that event, to properly expose it to GC
- if ( typeof elem[ name ] === "undefined" ) {
- elem[ name ] = null;
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
}
- elem.detachEvent( name, handle );
- }
- };
+ return this;
+ },
-jQuery.Event = function( src, props ) {
- // Allow instantiation without the 'new' keyword
- if ( !(this instanceof jQuery.Event) ) {
- return new jQuery.Event( src, props );
- }
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
- // Event object
- if ( src && src.type ) {
- this.originalEvent = src;
- this.type = src.type;
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
- // Events bubbling up the document may have been marked as prevented
- // by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
- src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[0] || {},
+ i = 0,
+ l = this.length;
- // Event type
- } else {
- this.type = src;
- }
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ null;
+ }
- // Put explicitly provided properties onto the event object
- if ( props ) {
- jQuery.extend( this, props );
- }
- // Create a timestamp if incoming event doesn't have one
- this.timeStamp = src && src.timeStamp || jQuery.now();
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
- // Mark it as fixed
- this[ jQuery.expando ] = true;
-};
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
-function returnFalse() {
- return false;
-}
-function returnTrue() {
- return true;
-}
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName( "*" ) );
+ elem.innerHTML = value;
+ }
+ }
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
- preventDefault: function() {
- this.isDefaultPrevented = returnTrue;
+ elem = 0;
- var e = this.originalEvent;
- if ( !e ) {
- return;
- }
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
- // if preventDefault exists run it on the original event
- if ( e.preventDefault ) {
- e.preventDefault();
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
- // otherwise set the returnValue property of the original event to false (IE)
- } else {
- e.returnValue = false;
- }
- },
- stopPropagation: function() {
- this.isPropagationStopped = returnTrue;
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
- var e = this.originalEvent;
- if ( !e ) {
- return;
- }
- // if stopPropagation exists run it on the original event
- if ( e.stopPropagation ) {
- e.stopPropagation();
- }
- // otherwise set the cancelBubble property of the original event to true (IE)
- e.cancelBubble = true;
- },
- stopImmediatePropagation: function() {
- this.isImmediatePropagationStopped = returnTrue;
- this.stopPropagation();
- },
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse
-};
+ if ( typeof value !== "string" ) {
+ value = jQuery( value ).detach();
+ }
-// Create mouseenter/leave events using mouseover/out and event-time checks
-jQuery.each({
- mouseenter: "mouseover",
- mouseleave: "mouseout"
-}, function( orig, fix ) {
- jQuery.event.special[ orig ] = {
- delegateType: fix,
- bindType: fix,
-
- handle: function( event ) {
- var ret,
- target = this,
- related = event.relatedTarget,
- handleObj = event.handleObj,
- selector = handleObj.selector;
-
- // For mousenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
- event.type = handleObj.origType;
- ret = handleObj.handler.apply( this, arguments );
- event.type = fix;
- }
- return ret;
- }
- };
-});
+ return this.each(function() {
+ var next = this.nextSibling,
+ parent = this.parentNode;
-// IE submit delegation
-if ( !jQuery.support.submitBubbles ) {
+ jQuery( this ).remove();
- jQuery.event.special.submit = {
- setup: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.length ?
+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+ this;
}
+ },
- // Lazy-add a submit handler when a descendant form may potentially be submitted
- jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
- // Node name check avoids a VML-related crash in IE (#9807)
- var elem = e.target,
- form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
- if ( form && !jQuery._data( form, "_submit_attached" ) ) {
- jQuery.event.add( form, "submit._submit", function( event ) {
- event._submit_bubble = true;
- });
- jQuery._data( form, "_submit_attached", true );
- }
- });
- // return undefined since we don't need an event listener
+ detach: function( selector ) {
+ return this.remove( selector, true );
},
- postDispatch: function( event ) {
- // If form was submitted by the user, bubble the event up the tree
- if ( event._submit_bubble ) {
- delete event._submit_bubble;
- if ( this.parentNode && !event.isTrigger ) {
- jQuery.event.simulate( "submit", this.parentNode, event, true );
- }
+ domManip: function( args, table, callback ) {
+ var results, first, fragment, parent,
+ value = args[0],
+ scripts = [];
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
}
- },
- teardown: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
}
- // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
- jQuery.event.remove( this, "._submit" );
- }
- };
-}
+ if ( this[0] ) {
+ parent = value && value.parentNode;
-// IE change delegation and checkbox/radio fix
-if ( !jQuery.support.changeBubbles ) {
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
- jQuery.event.special.change = {
+ } else {
+ results = jQuery.buildFragment( args, this, scripts );
+ }
- setup: function() {
+ fragment = results.fragment;
- if ( rformElems.test( this.nodeName ) ) {
- // IE doesn't fire change on a check/radio until blur; trigger it on click
- // after a propertychange. Eat the blur-change in special.change.handle.
- // This still fires onchange a second time for check/radio after blur.
- if ( this.type === "checkbox" || this.type === "radio" ) {
- jQuery.event.add( this, "propertychange._change", function( event ) {
- if ( event.originalEvent.propertyName === "checked" ) {
- this._just_changed = true;
- }
- });
- jQuery.event.add( this, "click._change", function( event ) {
- if ( this._just_changed && !event.isTrigger ) {
- this._just_changed = false;
- }
- // Allow triggered, simulated change events (#11500)
- jQuery.event.simulate( "change", this, event, true );
- });
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
}
- return false;
- }
- // Delegated event; lazy-add a change handler on descendant inputs
- jQuery.event.add( this, "beforeactivate._change", function( e ) {
- var elem = e.target;
- if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) {
- jQuery.event.add( elem, "change._change", function( event ) {
- if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
- jQuery.event.simulate( "change", this.parentNode, event, true );
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ // Make sure that we do not leak memory by inadvertently discarding
+ // the original fragment (which might have attached data) instead of
+ // using it; in addition, use the original fragment object for the last
+ // item instead of first because it can end up being emptied incorrectly
+ // in certain situations (Bug #8070).
+ // Fragments from the fragment cache must always be cloned and never used
+ // in place.
+ results.cacheable || ( l > 1 && i < lastIndex ) ?
+ jQuery.clone( fragment, true, true ) :
+ fragment
+ );
+ }
+ }
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, function( i, elem ) {
+ if ( elem.src ) {
+ jQuery.ajax({
+ type: "GET",
+ global: false,
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ } else {
+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
}
});
- jQuery._data( elem, "_change_attached", true );
}
- });
- },
+ }
- handle: function( event ) {
- var elem = event.target;
+ return this;
+ }
+ });
- // Swallow native change events from checkbox/radio, we already triggered them above
- if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
- return event.handleObj.handler.apply( this, arguments );
- }
- },
+ function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+ }
- teardown: function() {
- jQuery.event.remove( this, "._change" );
+ function cloneCopyEvent( src, dest ) {
- return rformElems.test( this.nodeName );
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
}
- };
-}
-// Create "bubbling" focus and blur events
-if ( !jQuery.support.focusinBubbles ) {
- jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
- // Attach a single capturing handler while someone wants focusin/focusout
- var attaches = 0,
- handler = function( event ) {
- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
- };
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
- jQuery.event.special[ fix ] = {
- setup: function() {
- if ( attaches++ === 0 ) {
- document.addEventListener( orig, handler, true );
- }
- },
- teardown: function() {
- if ( --attaches === 0 ) {
- document.removeEventListener( orig, handler, true );
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
}
}
- };
- });
-}
+ }
-jQuery.fn.extend({
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+ }
- on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
- var origFn, type;
+ function cloneFixAttributes( src, dest ) {
+ var nodeName;
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) { // && selector != null
- // ( types-Object, data )
- data = data || selector;
- selector = undefined;
- }
- for ( type in types ) {
- this.on( type, selector, data, types[ type ], one );
- }
- return this;
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
}
- if ( data == null && fn == null ) {
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return this;
+ // clearAttributes removes the attributes, which we don't want,
+ // but also removes the attachEvent events, which we *do* want
+ if ( dest.clearAttributes ) {
+ dest.clearAttributes();
}
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return this.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- });
- },
- one: function( types, selector, data, fn ) {
- return this.on( types, selector, data, fn, 1 );
- },
- off: function( types, selector, fn ) {
- var handleObj, type;
- if ( types && types.preventDefault && types.handleObj ) {
- // ( event ) dispatched jQuery.Event
- handleObj = types.handleObj;
- jQuery( types.delegateTarget ).off(
- handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
- handleObj.selector,
- handleObj.handler
- );
- return this;
- }
- if ( typeof types === "object" ) {
- // ( types-object [, selector] )
- for ( type in types ) {
- this.off( type, selector, types[ type ] );
- }
- return this;
- }
- if ( selector === false || typeof selector === "function" ) {
- // ( types [, fn] )
- fn = selector;
- selector = undefined;
- }
- if ( fn === false ) {
- fn = returnFalse;
+ // mergeAttributes, in contrast, only merges back on the
+ // original attributes, not the events
+ if ( dest.mergeAttributes ) {
+ dest.mergeAttributes( src );
}
- return this.each(function() {
- jQuery.event.remove( this, types, fn, selector );
- });
- },
-
- bind: function( types, data, fn ) {
- return this.on( types, null, data, fn );
- },
- unbind: function( types, fn ) {
- return this.off( types, null, fn );
- },
-
- live: function( types, data, fn ) {
- jQuery( this.context ).on( types, this.selector, data, fn );
- return this;
- },
- die: function( types, fn ) {
- jQuery( this.context ).off( types, this.selector || "**", fn );
- return this;
- },
-
- delegate: function( selector, types, data, fn ) {
- return this.on( types, selector, data, fn );
- },
- undelegate: function( selector, types, fn ) {
- // ( namespace ) or ( selector, types [, fn] )
- return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
- },
-
- trigger: function( type, data ) {
- return this.each(function() {
- jQuery.event.trigger( type, data, this );
- });
- },
- triggerHandler: function( type, data ) {
- if ( this[0] ) {
- return jQuery.event.trigger( type, data, this[0], true );
- }
- },
-
- toggle: function( fn ) {
- // Save reference to arguments for access in closure
- var args = arguments,
- guid = fn.guid || jQuery.guid++,
- i = 0,
- toggler = function( event ) {
- // Figure out which function to execute
- var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
- jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
- // Make sure that clicks stop
- event.preventDefault();
+ nodeName = dest.nodeName.toLowerCase();
- // and execute the function
- return args[ lastToggle ].apply( this, arguments ) || false;
- };
+ // IE6-8 fail to clone children inside object elements that use
+ // the proprietary classid attribute value (rather than the type
+ // attribute) to identify the type of content to display
+ if ( nodeName === "object" ) {
+ dest.outerHTML = src.outerHTML;
- // link all the functions, so any of them can unbind this click handler
- toggler.guid = guid;
- while ( i < args.length ) {
- args[ i++ ].guid = guid;
- }
+ } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+ if ( src.checked ) {
+ dest.defaultChecked = dest.checked = src.checked;
+ }
- return this.click( toggler );
- },
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
- hover: function( fnOver, fnOut ) {
- return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
- }
-});
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.selected = src.defaultSelected;
-jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
- "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
- "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
- // Handle event binding
- jQuery.fn[ name ] = function( data, fn ) {
- if ( fn == null ) {
- fn = data;
- data = null;
+ // IE blanks contents when cloning scripts
+ } else if ( nodeName === "script" && dest.text !== src.text ) {
+ dest.text = src.text;
}
- return arguments.length > 0 ?
- this.on( name, null, data, fn ) :
- this.trigger( name );
- };
+ // Event data gets referenced instead of copied if the expando
+ // gets copied too
+ dest.removeAttribute( jQuery.expando );
- if ( rkeyEvent.test( name ) ) {
- jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+ // Clear flags for bubbling special change/submit events, they must
+ // be reattached when the newly cloned events are first activated
+ dest.removeAttribute( "_submit_attached" );
+ dest.removeAttribute( "_change_attached" );
}
- if ( rmouseEvent.test( name ) ) {
- jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
- }
-});
-/*!\r
- * Sizzle CSS Selector Engine\r
- * Copyright 2012 jQuery Foundation and other contributors\r
- * Released under the MIT license\r
- * http://sizzlejs.com/\r
- */\r
-(function( window, undefined ) {\r
-\r
-var cachedruns,\r
- dirruns,\r
- sortOrder,\r
- siblingCheck,\r
- assertGetIdNotName,\r
-\r
- document = window.document,\r
- docElem = document.documentElement,\r
-\r
- strundefined = "undefined",\r
- hasDuplicate = false,\r
- baseHasDuplicate = true,\r
- done = 0,\r
- slice = [].slice,\r
- push = [].push,\r
-\r
- expando = ( "sizcache" + Math.random() ).replace( ".", "" ),\r
-\r
- // Regex\r
-\r
- // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\r
- whitespace = "[\\x20\\t\\r\\n\\f]",\r
- // http://www.w3.org/TR/css3-syntax/#characters\r
- characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",\r
-\r
- // Loosely modeled on CSS identifier characters\r
- // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)\r
- // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\r
- identifier = characterEncoding.replace( "w", "w#" ),\r
-\r
- // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\r
- operators = "([*^$|!~]?=)",\r
- attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +\r
- "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",\r
- pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)",\r
- pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)",\r
- combinators = whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*",\r
- groups = "(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|" + attributes + "|" + pseudos.replace( 2, 7 ) + "|[^\\\\(),])+",\r
-\r
- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\r
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),\r
-\r
- rcombinators = new RegExp( "^" + combinators ),\r
-\r
- // All simple (non-comma) selectors, excluding insignifant trailing whitespace\r
- rgroups = new RegExp( groups + "?(?=" + whitespace + "*,|$)", "g" ),\r
-\r
- // A selector, or everything after leading whitespace\r
- // Optionally followed in either case by a ")" for terminating sub-selectors\r
- rselector = new RegExp( "^(?:(?!,)(?:(?:^|,)" + whitespace + "*" + groups + ")*?|" + whitespace + "*(.*?))(\\)|$)" ),\r
-\r
- // All combinators and selector components (attribute test, tag, pseudo, etc.), the latter appearing together when consecutive\r
- rtokens = new RegExp( groups.slice( 19, -6 ) + "\\x20\\t\\r\\n\\f>+~])+|" + combinators, "g" ),\r
-\r
- // Easily-parseable/retrievable ID or TAG or CLASS selectors\r
- rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,\r
-\r
- rsibling = /[\x20\t\r\n\f]*[+~]/,\r
- rendsWithNot = /:not\($/,\r
-\r
- rheader = /h\d/i,\r
- rinputs = /input|select|textarea|button/i,\r
-\r
- rbackslash = /\\(?!\\)/g,\r
-\r
- matchExpr = {\r
- "ID": new RegExp( "^#(" + characterEncoding + ")" ),\r
- "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),\r
- "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),\r
- "TAG": new RegExp( "^(" + characterEncoding.replace( "[-", "[-\\*" ) + ")" ),\r
- "ATTR": new RegExp( "^" + attributes ),\r
- "PSEUDO": new RegExp( "^" + pseudos ),\r
- "CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace +\r
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +\r
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),\r
- "POS": new RegExp( pos, "ig" ),\r
- // For use in libraries implementing .is()\r
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )\r
- },\r
-\r
- classCache = {},\r
- cachedClasses = [],\r
- compilerCache = {},\r
- cachedSelectors = [],\r
-\r
- // Mark a function for use in filtering\r
- markFunction = function( fn ) {\r
- fn.sizzleFilter = true;\r
- return fn;\r
- },\r
-\r
- // Returns a function to use in pseudos for input types\r
- createInputFunction = function( type ) {\r
- return function( elem ) {\r
- // Check the input's nodeName and type\r
- return elem.nodeName.toLowerCase() === "input" && elem.type === type;\r
- };\r
- },\r
-\r
- // Returns a function to use in pseudos for buttons\r
- createButtonFunction = function( type ) {\r
- return function( elem ) {\r
- var name = elem.nodeName.toLowerCase();\r
- return (name === "input" || name === "button") && elem.type === type;\r
- };\r
- },\r
-\r
- // Used for testing something on an element\r
- assert = function( fn ) {\r
- var pass = false,\r
- div = document.createElement("div");\r
- try {\r
- pass = fn( div );\r
- } catch (e) {}\r
- // release memory in IE\r
- div = null;\r
- return pass;\r
- },\r
-\r
- // Check if attributes should be retrieved by attribute nodes\r
- assertAttributes = assert(function( div ) {\r
- div.innerHTML = "<select></select>";\r
- var type = typeof div.lastChild.getAttribute("multiple");\r
- // IE8 returns a string for some attributes even when not present\r
- return type !== "boolean" && type !== "string";\r
- }),\r
-\r
- // Check if getElementById returns elements by name\r
- // Check if getElementsByName privileges form controls or returns elements by ID\r
- assertUsableName = assert(function( div ) {\r
- // Inject content\r
- div.id = expando + 0;\r
- div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";\r
- docElem.insertBefore( div, docElem.firstChild );\r
-\r
- // Test\r
- var pass = document.getElementsByName &&\r
- // buggy browsers will return fewer than the correct 2\r
- document.getElementsByName( expando ).length ===\r
- // buggy browsers will return more than the correct 0\r
- 2 + document.getElementsByName( expando + 0 ).length;\r
- assertGetIdNotName = !document.getElementById( expando );\r
-\r
- // Cleanup\r
- docElem.removeChild( div );\r
-\r
- return pass;\r
- }),\r
-\r
- // Check if the browser returns only elements\r
- // when doing getElementsByTagName("*")\r
- assertTagNameNoComments = assert(function( div ) {\r
- div.appendChild( document.createComment("") );\r
- return div.getElementsByTagName("*").length === 0;\r
- }),\r
-\r
- // Check if getAttribute returns normalized href attributes\r
- assertHrefNotNormalized = assert(function( div ) {\r
- div.innerHTML = "<a href='#'></a>";\r
- return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\r
- div.firstChild.getAttribute("href") === "#";\r
- }),\r
-\r
- // Check if getElementsByClassName can be trusted\r
- assertUsableClassName = assert(function( div ) {\r
- // Opera can't find a second classname (in 9.6)\r
- div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";\r
- if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {\r
- return false;\r
- }\r
-\r
- // Safari caches class attributes, doesn't catch changes (in 3.2)\r
- div.lastChild.className = "e";\r
- return div.getElementsByClassName("e").length !== 1;\r
- });\r
-\r
-var Sizzle = function( selector, context, results, seed ) {\r
- results = results || [];\r
- context = context || document;\r
- var match, elem, xml, m,\r
- nodeType = context.nodeType;\r
-\r
- if ( nodeType !== 1 && nodeType !== 9 ) {\r
- return [];\r
- }\r
-\r
- if ( !selector || typeof selector !== "string" ) {\r
- return results;\r
- }\r
-\r
- xml = isXML( context );\r
-\r
- if ( !xml && !seed ) {\r
- if ( (match = rquickExpr.exec( selector )) ) {\r
- // Speed-up: Sizzle("#ID")\r
- if ( (m = match[1]) ) {\r
- if ( nodeType === 9 ) {\r
- elem = context.getElementById( m );\r
- // Check parentNode to catch when Blackberry 4.6 returns\r
- // nodes that are no longer in the document #6963\r
- if ( elem && elem.parentNode ) {\r
- // Handle the case where IE, Opera, and Webkit return items\r
- // by name instead of ID\r
- if ( elem.id === m ) {\r
- results.push( elem );\r
- return results;\r
- }\r
- } else {\r
- return results;\r
- }\r
- } else {\r
- // Context is not a document\r
- if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\r
- contains( context, elem ) && elem.id === m ) {\r
- results.push( elem );\r
- return results;\r
- }\r
- }\r
-\r
- // Speed-up: Sizzle("TAG")\r
- } else if ( match[2] ) {\r
- push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\r
- return results;\r
-\r
- // Speed-up: Sizzle(".CLASS")\r
- } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {\r
- push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\r
- return results;\r
- }\r
- }\r
- }\r
-\r
- // All others\r
- return select( selector, context, results, seed, xml );\r
-};\r
-\r
-var Expr = Sizzle.selectors = {\r
-\r
- // Can be adjusted by the user\r
- cacheLength: 50,\r
-\r
- match: matchExpr,\r
-\r
- order: [ "ID", "TAG" ],\r
-\r
- attrHandle: {},\r
-\r
- createPseudo: markFunction,\r
-\r
- find: {\r
- "ID": assertGetIdNotName ?\r
- function( id, context, xml ) {\r
- if ( typeof context.getElementById !== strundefined && !xml ) {\r
- var m = context.getElementById( id );\r
- // Check parentNode to catch when Blackberry 4.6 returns\r
- // nodes that are no longer in the document #6963\r
- return m && m.parentNode ? [m] : [];\r
- }\r
- } :\r
- function( id, context, xml ) {\r
- if ( typeof context.getElementById !== strundefined && !xml ) {\r
- var m = context.getElementById( id );\r
-\r
- return m ?\r
- m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?\r
- [m] :\r
- undefined :\r
- [];\r
- }\r
- },\r
-\r
- "TAG": assertTagNameNoComments ?\r
- function( tag, context ) {\r
- if ( typeof context.getElementsByTagName !== strundefined ) {\r
- return context.getElementsByTagName( tag );\r
- }\r
- } :\r
- function( tag, context ) {\r
- var results = context.getElementsByTagName( tag );\r
-\r
- // Filter out possible comments\r
- if ( tag === "*" ) {\r
- var elem,\r
- tmp = [],\r
- i = 0;\r
-\r
- for ( ; (elem = results[i]); i++ ) {\r
- if ( elem.nodeType === 1 ) {\r
- tmp.push( elem );\r
- }\r
- }\r
-\r
- return tmp;\r
- }\r
- return results;\r
- }\r
- },\r
-\r
- relative: {\r
- ">": { dir: "parentNode", first: true },\r
- " ": { dir: "parentNode" },\r
- "+": { dir: "previousSibling", first: true },\r
- "~": { dir: "previousSibling" }\r
- },\r
-\r
- preFilter: {\r
- "ATTR": function( match ) {\r
- match[1] = match[1].replace( rbackslash, "" );\r
-\r
- // Move the given value to match[3] whether quoted or unquoted\r
- match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );\r
-\r
- if ( match[2] === "~=" ) {\r
- match[3] = " " + match[3] + " ";\r
- }\r
-\r
- return match.slice( 0, 4 );\r
- },\r
-\r
- "CHILD": function( match ) {\r
- /* matches from matchExpr.CHILD\r
- 1 type (only|nth|...)\r
- 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)\r
- 3 xn-component of xn+y argument ([+-]?\d*n|)\r
- 4 sign of xn-component\r
- 5 x of xn-component\r
- 6 sign of y-component\r
- 7 y of y-component\r
- */\r
- match[1] = match[1].toLowerCase();\r
-\r
- if ( match[1] === "nth" ) {\r
- // nth-child requires argument\r
- if ( !match[2] ) {\r
- Sizzle.error( match[0] );\r
- }\r
-\r
- // numeric x and y parameters for Expr.filter.CHILD\r
- // remember that false/true cast respectively to 0/1\r
- match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );\r
- match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );\r
-\r
- // other types prohibit arguments\r
- } else if ( match[2] ) {\r
- Sizzle.error( match[0] );\r
- }\r
-\r
- return match;\r
- },\r
-\r
- "PSEUDO": function( match ) {\r
- var argument,\r
- unquoted = match[4];\r
-\r
- if ( matchExpr["CHILD"].test( match[0] ) ) {\r
- return null;\r
- }\r
-\r
- // Relinquish our claim on characters in `unquoted` from a closing parenthesis on\r
- if ( unquoted && (argument = rselector.exec( unquoted )) && argument.pop() ) {\r
-\r
- match[0] = match[0].slice( 0, argument[0].length - unquoted.length - 1 );\r
- unquoted = argument[0].slice( 0, -1 );\r
- }\r
-\r
- // Quoted or unquoted, we have the full argument\r
- // Return only captures needed by the pseudo filter method (type and argument)\r
- match.splice( 2, 3, unquoted || match[3] );\r
- return match;\r
- }\r
- },\r
-\r
- filter: {\r
- "ID": assertGetIdNotName ?\r
- function( id ) {\r
- id = id.replace( rbackslash, "" );\r
- return function( elem ) {\r
- return elem.getAttribute("id") === id;\r
- };\r
- } :\r
- function( id ) {\r
- id = id.replace( rbackslash, "" );\r
- return function( elem ) {\r
- var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");\r
- return node && node.value === id;\r
- };\r
- },\r
-\r
- "TAG": function( nodeName ) {\r
- if ( nodeName === "*" ) {\r
- return function() { return true; };\r
- }\r
- nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();\r
-\r
- return function( elem ) {\r
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\r
- };\r
- },\r
-\r
- "CLASS": function( className ) {\r
- var pattern = classCache[ className ];\r
- if ( !pattern ) {\r
- pattern = classCache[ className ] = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" );\r
- cachedClasses.push( className );\r
- // Avoid too large of a cache\r
- if ( cachedClasses.length > Expr.cacheLength ) {\r
- delete classCache[ cachedClasses.shift() ];\r
- }\r
- }\r
- return function( elem ) {\r
- return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );\r
- };\r
- },\r
-\r
- "ATTR": function( name, operator, check ) {\r
- if ( !operator ) {\r
- return function( elem ) {\r
- return Sizzle.attr( elem, name ) != null;\r
- };\r
- }\r
-\r
- return function( elem ) {\r
- var result = Sizzle.attr( elem, name ),\r
- value = result + "";\r
-\r
- if ( result == null ) {\r
- return operator === "!=";\r
- }\r
-\r
- switch ( operator ) {\r
- case "=":\r
- return value === check;\r
- case "!=":\r
- return value !== check;\r
- case "^=":\r
- return check && value.indexOf( check ) === 0;\r
- case "*=":\r
- return check && value.indexOf( check ) > -1;\r
- case "$=":\r
- return check && value.substr( value.length - check.length ) === check;\r
- case "~=":\r
- return ( " " + value + " " ).indexOf( check ) > -1;\r
- case "|=":\r
- return value === check || value.substr( 0, check.length + 1 ) === check + "-";\r
- }\r
- };\r
- },\r
-\r
- "CHILD": function( type, argument, first, last ) {\r
-\r
- if ( type === "nth" ) {\r
- var doneName = done++;\r
-\r
- return function( elem ) {\r
- var parent, diff,\r
- count = 0,\r
- node = elem;\r
-\r
- if ( first === 1 && last === 0 ) {\r
- return true;\r
- }\r
-\r
- parent = elem.parentNode;\r
-\r
- if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) {\r
- for ( node = parent.firstChild; node; node = node.nextSibling ) {\r
- if ( node.nodeType === 1 ) {\r
- node.sizset = ++count;\r
- if ( node === elem ) {\r
- break;\r
- }\r
- }\r
- }\r
-\r
- parent[ expando ] = doneName;\r
- }\r
-\r
- diff = elem.sizset - last;\r
-\r
- if ( first === 0 ) {\r
- return diff === 0;\r
-\r
- } else {\r
- return ( diff % first === 0 && diff / first >= 0 );\r
- }\r
- };\r
- }\r
-\r
- return function( elem ) {\r
- var node = elem;\r
-\r
- switch ( type ) {\r
- case "only":\r
- case "first":\r
- while ( (node = node.previousSibling) ) {\r
- if ( node.nodeType === 1 ) {\r
- return false;\r
- }\r
- }\r
-\r
- if ( type === "first" ) {\r
- return true;\r
- }\r
-\r
- node = elem;\r
-\r
- /* falls through */\r
- case "last":\r
- while ( (node = node.nextSibling) ) {\r
- if ( node.nodeType === 1 ) {\r
- return false;\r
- }\r
- }\r
-\r
- return true;\r
- }\r
- };\r
- },\r
-\r
- "PSEUDO": function( pseudo, argument, context, xml ) {\r
- // pseudo-class names are case-insensitive\r
- // http://www.w3.org/TR/selectors/#pseudo-classes\r
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\r
- var fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ];\r
-\r
- if ( !fn ) {\r
- Sizzle.error( "unsupported pseudo: " + pseudo );\r
- }\r
-\r
- // The user may set fn.sizzleFilter to indicate\r
- // that arguments are needed to create the filter function\r
- // just as Sizzle does\r
- if ( !fn.sizzleFilter ) {\r
- return fn;\r
- }\r
-\r
- return fn( argument, context, xml );\r
- }\r
- },\r
-\r
- pseudos: {\r
- "not": markFunction(function( selector, context, xml ) {\r
- // Trim the selector passed to compile\r
- // to avoid treating leading and trailing\r
- // spaces as combinators\r
- var matcher = compile( selector.replace( rtrim, "$1" ), context, xml );\r
- return function( elem ) {\r
- return !matcher( elem );\r
- };\r
- }),\r
-\r
- "enabled": function( elem ) {\r
- return elem.disabled === false;\r
- },\r
-\r
- "disabled": function( elem ) {\r
- return elem.disabled === true;\r
- },\r
-\r
- "checked": function( elem ) {\r
- // In CSS3, :checked should return both checked and selected elements\r
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\r
- var nodeName = elem.nodeName.toLowerCase();\r
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);\r
- },\r
-\r
- "selected": function( elem ) {\r
- // Accessing this property makes selected-by-default\r
- // options in Safari work properly\r
- if ( elem.parentNode ) {\r
- elem.parentNode.selectedIndex;\r
- }\r
-\r
- return elem.selected === true;\r
- },\r
-\r
- "parent": function( elem ) {\r
- return !Expr.pseudos["empty"]( elem );\r
- },\r
-\r
- "empty": function( elem ) {\r
- // http://www.w3.org/TR/selectors/#empty-pseudo\r
- // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\r
- // not comment, processing instructions, or others\r
- // Thanks to Diego Perini for the nodeName shortcut\r
- // Greater than "@" means alpha characters (specifically not starting with "#" or "?")\r
- var nodeType;\r
- elem = elem.firstChild;\r
- while ( elem ) {\r
- if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {\r
- return false;\r
- }\r
- elem = elem.nextSibling;\r
- }\r
- return true;\r
- },\r
-\r
- "contains": markFunction(function( text ) {\r
- return function( elem ) {\r
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\r
- };\r
- }),\r
-\r
- "has": markFunction(function( selector ) {\r
- return function( elem ) {\r
- return Sizzle( selector, elem ).length > 0;\r
- };\r
- }),\r
-\r
- "header": function( elem ) {\r
- return rheader.test( elem.nodeName );\r
- },\r
-\r
- "text": function( elem ) {\r
- var type, attr;\r
- // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\r
- // use getAttribute instead to test this case\r
- return elem.nodeName.toLowerCase() === "input" &&\r
- (type = elem.type) === "text" &&\r
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );\r
- },\r
-\r
- // Input types\r
- "radio": createInputFunction("radio"),\r
- "checkbox": createInputFunction("checkbox"),\r
- "file": createInputFunction("file"),\r
- "password": createInputFunction("password"),\r
- "image": createInputFunction("image"),\r
-\r
- "submit": createButtonFunction("submit"),\r
- "reset": createButtonFunction("reset"),\r
-\r
- "button": function( elem ) {\r
- var name = elem.nodeName.toLowerCase();\r
- return name === "input" && elem.type === "button" || name === "button";\r
- },\r
-\r
- "input": function( elem ) {\r
- return rinputs.test( elem.nodeName );\r
- },\r
-\r
- "focus": function( elem ) {\r
- var doc = elem.ownerDocument;\r
- return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);\r
- },\r
-\r
- "active": function( elem ) {\r
- return elem === elem.ownerDocument.activeElement;\r
- }\r
- },\r
-\r
- setFilters: {\r
- "first": function( elements, argument, not ) {\r
- return not ? elements.slice( 1 ) : [ elements[0] ];\r
- },\r
-\r
- "last": function( elements, argument, not ) {\r
- var elem = elements.pop();\r
- return not ? elements : [ elem ];\r
- },\r
-\r
- "even": function( elements, argument, not ) {\r
- var results = [],\r
- i = not ? 1 : 0,\r
- len = elements.length;\r
- for ( ; i < len; i = i + 2 ) {\r
- results.push( elements[i] );\r
- }\r
- return results;\r
- },\r
-\r
- "odd": function( elements, argument, not ) {\r
- var results = [],\r
- i = not ? 0 : 1,\r
- len = elements.length;\r
- for ( ; i < len; i = i + 2 ) {\r
- results.push( elements[i] );\r
- }\r
- return results;\r
- },\r
-\r
- "lt": function( elements, argument, not ) {\r
- return not ? elements.slice( +argument ) : elements.slice( 0, +argument );\r
- },\r
-\r
- "gt": function( elements, argument, not ) {\r
- return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 );\r
- },\r
-\r
- "eq": function( elements, argument, not ) {\r
- var elem = elements.splice( +argument, 1 );\r
- return not ? elements : elem;\r
- }\r
- }\r
-};\r
-\r
-// Deprecated\r
-Expr.setFilters["nth"] = Expr.setFilters["eq"];\r
-\r
-// Back-compat\r
-Expr.filters = Expr.pseudos;\r
-\r
-// IE6/7 return a modified href\r
-if ( !assertHrefNotNormalized ) {\r
- Expr.attrHandle = {\r
- "href": function( elem ) {\r
- return elem.getAttribute( "href", 2 );\r
- },\r
- "type": function( elem ) {\r
- return elem.getAttribute("type");\r
- }\r
- };\r
-}\r
-\r
-// Add getElementsByName if usable\r
-if ( assertUsableName ) {\r
- Expr.order.push("NAME");\r
- Expr.find["NAME"] = function( name, context ) {\r
- if ( typeof context.getElementsByName !== strundefined ) {\r
- return context.getElementsByName( name );\r
- }\r
- };\r
-}\r
-\r
-// Add getElementsByClassName if usable\r
-if ( assertUsableClassName ) {\r
- Expr.order.splice( 1, 0, "CLASS" );\r
- Expr.find["CLASS"] = function( className, context, xml ) {\r
- if ( typeof context.getElementsByClassName !== strundefined && !xml ) {\r
- return context.getElementsByClassName( className );\r
- }\r
- };\r
-}\r
-\r
-// If slice is not available, provide a backup\r
-try {\r
- slice.call( docElem.childNodes, 0 )[0].nodeType;\r
-} catch ( e ) {\r
- slice = function( i ) {\r
- var elem, results = [];\r
- for ( ; (elem = this[i]); i++ ) {\r
- results.push( elem );\r
- }\r
- return results;\r
- };\r
-}\r
-\r
-var isXML = Sizzle.isXML = function( elem ) {\r
- // documentElement is verified for cases where it doesn't yet exist\r
- // (such as loading iframes in IE - #4833)\r
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;\r
- return documentElement ? documentElement.nodeName !== "HTML" : false;\r
-};\r
-\r
-// Element contains another\r
-var contains = Sizzle.contains = docElem.compareDocumentPosition ?\r
- function( a, b ) {\r
- return !!( a.compareDocumentPosition( b ) & 16 );\r
- } :\r
- docElem.contains ?\r
- function( a, b ) {\r
- var adown = a.nodeType === 9 ? a.documentElement : a,\r
- bup = b.parentNode;\r
- return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );\r
- } :\r
- function( a, b ) {\r
- while ( (b = b.parentNode) ) {\r
- if ( b === a ) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- };\r
-\r
-/**\r
- * Utility function for retrieving the text value of an array of DOM nodes\r
- * @param {Array|Element} elem\r
- */\r
-var getText = Sizzle.getText = function( elem ) {\r
- var node,\r
- ret = "",\r
- i = 0,\r
- nodeType = elem.nodeType;\r
-\r
- if ( nodeType ) {\r
- if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\r
- // Use textContent for elements\r
- // innerText usage removed for consistency of new lines (see #11153)\r
- if ( typeof elem.textContent === "string" ) {\r
- return elem.textContent;\r
- } else {\r
- // Traverse its children\r
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\r
- ret += getText( elem );\r
- }\r
- }\r
- } else if ( nodeType === 3 || nodeType === 4 ) {\r
- return elem.nodeValue;\r
- }\r
- // Do not include comment or processing instruction nodes\r
- } else {\r
-\r
- // If no nodeType, this is expected to be an array\r
- for ( ; (node = elem[i]); i++ ) {\r
- // Do not traverse comment nodes\r
- ret += getText( node );\r
- }\r
- }\r
- return ret;\r
-};\r
-\r
-Sizzle.attr = function( elem, name ) {\r
- var attr,\r
- xml = isXML( elem );\r
-\r
- if ( !xml ) {\r
- name = name.toLowerCase();\r
- }\r
- if ( Expr.attrHandle[ name ] ) {\r
- return Expr.attrHandle[ name ]( elem );\r
- }\r
- if ( assertAttributes || xml ) {\r
- return elem.getAttribute( name );\r
- }\r
- attr = elem.getAttributeNode( name );\r
- return attr ?\r
- typeof elem[ name ] === "boolean" ?\r
- elem[ name ] ? name : null :\r
- attr.specified ? attr.value : null :\r
- null;\r
-};\r
-\r
-Sizzle.error = function( msg ) {\r
- throw new Error( "Syntax error, unrecognized expression: " + msg );\r
-};\r
-\r
-// Check if the JavaScript engine is using some sort of\r
-// optimization where it does not always call our comparision\r
-// function. If that is the case, discard the hasDuplicate value.\r
-// Thus far that includes Google Chrome.\r
-[0, 0].sort(function() {\r
- return (baseHasDuplicate = 0);\r
-});\r
-\r
-\r
-if ( docElem.compareDocumentPosition ) {\r
- sortOrder = function( a, b ) {\r
- if ( a === b ) {\r
- hasDuplicate = true;\r
- return 0;\r
- }\r
-\r
- return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?\r
- a.compareDocumentPosition :\r
- a.compareDocumentPosition(b) & 4\r
- ) ? -1 : 1;\r
- };\r
-\r
-} else {\r
- sortOrder = function( a, b ) {\r
- // The nodes are identical, we can exit early\r
- if ( a === b ) {\r
- hasDuplicate = true;\r
- return 0;\r
-\r
- // Fallback to using sourceIndex (in IE) if it's available on both nodes\r
- } else if ( a.sourceIndex && b.sourceIndex ) {\r
- return a.sourceIndex - b.sourceIndex;\r
- }\r
-\r
- var al, bl,\r
- ap = [],\r
- bp = [],\r
- aup = a.parentNode,\r
- bup = b.parentNode,\r
- cur = aup;\r
-\r
- // If the nodes are siblings (or identical) we can do a quick check\r
- if ( aup === bup ) {\r
- return siblingCheck( a, b );\r
-\r
- // If no parents were found then the nodes are disconnected\r
- } else if ( !aup ) {\r
- return -1;\r
-\r
- } else if ( !bup ) {\r
- return 1;\r
- }\r
-\r
- // Otherwise they're somewhere else in the tree so we need\r
- // to build up a full list of the parentNodes for comparison\r
- while ( cur ) {\r
- ap.unshift( cur );\r
- cur = cur.parentNode;\r
- }\r
-\r
- cur = bup;\r
-\r
- while ( cur ) {\r
- bp.unshift( cur );\r
- cur = cur.parentNode;\r
- }\r
-\r
- al = ap.length;\r
- bl = bp.length;\r
-\r
- // Start walking down the tree looking for a discrepancy\r
- for ( var i = 0; i < al && i < bl; i++ ) {\r
- if ( ap[i] !== bp[i] ) {\r
- return siblingCheck( ap[i], bp[i] );\r
- }\r
- }\r
-\r
- // We ended someplace up the tree so do a sibling check\r
- return i === al ?\r
- siblingCheck( a, bp[i], -1 ) :\r
- siblingCheck( ap[i], b, 1 );\r
- };\r
-\r
- siblingCheck = function( a, b, ret ) {\r
- if ( a === b ) {\r
- return ret;\r
- }\r
-\r
- var cur = a.nextSibling;\r
-\r
- while ( cur ) {\r
- if ( cur === b ) {\r
- return -1;\r
- }\r
-\r
- cur = cur.nextSibling;\r
- }\r
-\r
- return 1;\r
- };\r
-}\r
-\r
-// Document sorting and removing duplicates\r
-Sizzle.uniqueSort = function( results ) {\r
- var elem,\r
- i = 1;\r
-\r
- if ( sortOrder ) {\r
- hasDuplicate = baseHasDuplicate;\r
- results.sort( sortOrder );\r
-\r
- if ( hasDuplicate ) {\r
- for ( ; (elem = results[i]); i++ ) {\r
- if ( elem === results[ i - 1 ] ) {\r
- results.splice( i--, 1 );\r
- }\r
- }\r
- }\r
- }\r
-\r
- return results;\r
-};\r
-\r
-function multipleContexts( selector, contexts, results, seed ) {\r
- var i = 0,\r
- len = contexts.length;\r
- for ( ; i < len; i++ ) {\r
- Sizzle( selector, contexts[i], results, seed );\r
- }\r
-}\r
-\r
-function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) {\r
- var results,\r
- fn = Expr.setFilters[ posfilter.toLowerCase() ];\r
-\r
- if ( !fn ) {\r
- Sizzle.error( posfilter );\r
- }\r
-\r
- if ( selector || !(results = seed) ) {\r
- multipleContexts( selector || "*", contexts, (results = []), seed );\r
- }\r
-\r
- return results.length > 0 ? fn( results, argument, not ) : [];\r
-}\r
-\r
-function handlePOS( selector, context, results, seed, groups ) {\r
- var match, not, anchor, ret, elements, currentContexts, part, lastIndex,\r
- i = 0,\r
- len = groups.length,\r
- rpos = matchExpr["POS"],\r
- // This is generated here in case matchExpr["POS"] is extended\r
- rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ),\r
- // This is for making sure non-participating\r
- // matching groups are represented cross-browser (IE6-8)\r
- setUndefined = function() {\r
- var i = 1,\r
- len = arguments.length - 2;\r
- for ( ; i < len; i++ ) {\r
- if ( arguments[i] === undefined ) {\r
- match[i] = undefined;\r
- }\r
- }\r
- };\r
-\r
- for ( ; i < len; i++ ) {\r
- // Reset regex index to 0\r
- rpos.exec("");\r
- selector = groups[i];\r
- ret = [];\r
- anchor = 0;\r
- elements = seed;\r
- while ( (match = rpos.exec( selector )) ) {\r
- lastIndex = rpos.lastIndex = match.index + match[0].length;\r
- if ( lastIndex > anchor ) {\r
- part = selector.slice( anchor, match.index );\r
- anchor = lastIndex;\r
- currentContexts = [ context ];\r
-\r
- if ( rcombinators.test(part) ) {\r
- if ( elements ) {\r
- currentContexts = elements;\r
- }\r
- elements = seed;\r
- }\r
-\r
- if ( (not = rendsWithNot.test( part )) ) {\r
- part = part.slice( 0, -5 ).replace( rcombinators, "$&*" );\r
- }\r
-\r
- if ( match.length > 1 ) {\r
- match[0].replace( rposgroups, setUndefined );\r
- }\r
- elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not );\r
- }\r
- }\r
-\r
- if ( elements ) {\r
- ret = ret.concat( elements );\r
-\r
- if ( (part = selector.slice( anchor )) && part !== ")" ) {\r
- if ( rcombinators.test(part) ) {\r
- multipleContexts( part, ret, results, seed );\r
- } else {\r
- Sizzle( part, context, results, seed ? seed.concat(elements) : elements );\r
- }\r
- } else {\r
- push.apply( results, ret );\r
- }\r
- } else {\r
- Sizzle( selector, context, results, seed );\r
- }\r
- }\r
-\r
- // Do not sort if this is a single filter\r
- return len === 1 ? results : Sizzle.uniqueSort( results );\r
-}\r
-\r
-function tokenize( selector, context, xml ) {\r
- var tokens, soFar, type,\r
- groups = [],\r
- i = 0,\r
-\r
- // Catch obvious selector issues: terminal ")"; nonempty fallback match\r
- // rselector never fails to match *something*\r
- match = rselector.exec( selector ),\r
- matched = !match.pop() && !match.pop(),\r
- selectorGroups = matched && selector.match( rgroups ) || [""],\r
-\r
- preFilters = Expr.preFilter,\r
- filters = Expr.filter,\r
- checkContext = !xml && context !== document;\r
-\r
- for ( ; (soFar = selectorGroups[i]) != null && matched; i++ ) {\r
- groups.push( tokens = [] );\r
-\r
- // Need to make sure we're within a narrower context if necessary\r
- // Adding a descendant combinator will generate what is needed\r
- if ( checkContext ) {\r
- soFar = " " + soFar;\r
- }\r
-\r
- while ( soFar ) {\r
- matched = false;\r
-\r
- // Combinators\r
- if ( (match = rcombinators.exec( soFar )) ) {\r
- soFar = soFar.slice( match[0].length );\r
-\r
- // Cast descendant combinators to space\r
- matched = tokens.push({ part: match.pop().replace( rtrim, " " ), captures: match });\r
- }\r
-\r
- // Filters\r
- for ( type in filters ) {\r
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\r
- (match = preFilters[ type ]( match, context, xml )) ) ) {\r
-\r
- soFar = soFar.slice( match.shift().length );\r
- matched = tokens.push({ part: type, captures: match });\r
- }\r
- }\r
-\r
- if ( !matched ) {\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if ( !matched ) {\r
- Sizzle.error( selector );\r
- }\r
-\r
- return groups;\r
-}\r
-\r
-function addCombinator( matcher, combinator, context ) {\r
- var dir = combinator.dir,\r
- doneName = done++;\r
-\r
- if ( !matcher ) {\r
- // If there is no matcher to check, check against the context\r
- matcher = function( elem ) {\r
- return elem === context;\r
- };\r
- }\r
- return combinator.first ?\r
- function( elem, context ) {\r
- while ( (elem = elem[ dir ]) ) {\r
- if ( elem.nodeType === 1 ) {\r
- return matcher( elem, context ) && elem;\r
- }\r
- }\r
- } :\r
- function( elem, context ) {\r
- var cache,\r
- dirkey = doneName + "." + dirruns,\r
- cachedkey = dirkey + "." + cachedruns;\r
- while ( (elem = elem[ dir ]) ) {\r
- if ( elem.nodeType === 1 ) {\r
- if ( (cache = elem[ expando ]) === cachedkey ) {\r
- return elem.sizset;\r
- } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {\r
- if ( elem.sizset ) {\r
- return elem;\r
- }\r
- } else {\r
- elem[ expando ] = cachedkey;\r
- if ( matcher( elem, context ) ) {\r
- elem.sizset = true;\r
- return elem;\r
- }\r
- elem.sizset = false;\r
- }\r
- }\r
- }\r
- };\r
-}\r
-\r
-function addMatcher( higher, deeper ) {\r
- return higher ?\r
- function( elem, context ) {\r
- var result = deeper( elem, context );\r
- return result && higher( result === true ? elem : result, context );\r
- } :\r
- deeper;\r
-}\r
-\r
-// ["TAG", ">", "ID", " ", "CLASS"]\r
-function matcherFromTokens( tokens, context, xml ) {\r
- var token, matcher,\r
- i = 0;\r
-\r
- for ( ; (token = tokens[i]); i++ ) {\r
- if ( Expr.relative[ token.part ] ) {\r
- matcher = addCombinator( matcher, Expr.relative[ token.part ], context );\r
- } else {\r
- token.captures.push( context, xml );\r
- matcher = addMatcher( matcher, Expr.filter[ token.part ].apply( null, token.captures ) );\r
- }\r
- }\r
-\r
- return matcher;\r
-}\r
-\r
-function matcherFromGroupMatchers( matchers ) {\r
- return function( elem, context ) {\r
- var matcher,\r
- j = 0;\r
- for ( ; (matcher = matchers[j]); j++ ) {\r
- if ( matcher(elem, context) ) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- };\r
-}\r
-\r
-var compile = Sizzle.compile = function( selector, context, xml ) {\r
- var tokens, group, i,\r
- cached = compilerCache[ selector ];\r
-\r
- // Return a cached group function if already generated (context dependent)\r
- if ( cached && cached.context === context ) {\r
- return cached;\r
- }\r
-\r
- // Generate a function of recursive functions that can be used to check each element\r
- group = tokenize( selector, context, xml );\r
- for ( i = 0; (tokens = group[i]); i++ ) {\r
- group[i] = matcherFromTokens( tokens, context, xml );\r
- }\r
-\r
- // Cache the compiled function\r
- cached = compilerCache[ selector ] = matcherFromGroupMatchers( group );\r
- cached.context = context;\r
- cached.runs = cached.dirruns = 0;\r
- cachedSelectors.push( selector );\r
- // Ensure only the most recent are cached\r
- if ( cachedSelectors.length > Expr.cacheLength ) {\r
- delete compilerCache[ cachedSelectors.shift() ];\r
- }\r
- return cached;\r
-};\r
-\r
-Sizzle.matches = function( expr, elements ) {\r
- return Sizzle( expr, null, null, elements );\r
-};\r
-\r
-Sizzle.matchesSelector = function( elem, expr ) {\r
- return Sizzle( expr, null, null, [ elem ] ).length > 0;\r
-};\r
-\r
-var select = function( selector, context, results, seed, xml ) {\r
- // Remove excessive whitespace\r
- selector = selector.replace( rtrim, "$1" );\r
- var elements, matcher, i, len, elem, token,\r
- type, findContext, notTokens,\r
- match = selector.match( rgroups ),\r
- tokens = selector.match( rtokens ),\r
- contextNodeType = context.nodeType;\r
-\r
- // POS handling\r
- if ( matchExpr["POS"].test(selector) ) {\r
- return handlePOS( selector, context, results, seed, match );\r
- }\r
-\r
- if ( seed ) {\r
- elements = slice.call( seed, 0 );\r
-\r
- // To maintain document order, only narrow the\r
- // set if there is one group\r
- } else if ( match && match.length === 1 ) {\r
-\r
- // Take a shortcut and set the context if the root selector is an ID\r
- if ( tokens.length > 1 && contextNodeType === 9 && !xml &&\r
- (match = matchExpr["ID"].exec( tokens[0] )) ) {\r
-\r
- context = Expr.find["ID"]( match[1], context, xml )[0];\r
- if ( !context ) {\r
- return results;\r
- }\r
-\r
- selector = selector.slice( tokens.shift().length );\r
- }\r
-\r
- findContext = ( (match = rsibling.exec( tokens[0] )) && !match.index && context.parentNode ) || context;\r
-\r
- // Get the last token, excluding :not\r
- notTokens = tokens.pop();\r
- token = notTokens.split(":not")[0];\r
-\r
- for ( i = 0, len = Expr.order.length; i < len; i++ ) {\r
- type = Expr.order[i];\r
-\r
- if ( (match = matchExpr[ type ].exec( token )) ) {\r
- elements = Expr.find[ type ]( (match[1] || "").replace( rbackslash, "" ), findContext, xml );\r
-\r
- if ( elements == null ) {\r
- continue;\r
- }\r
-\r
- if ( token === notTokens ) {\r
- selector = selector.slice( 0, selector.length - notTokens.length ) +\r
- token.replace( matchExpr[ type ], "" );\r
-\r
- if ( !selector ) {\r
- push.apply( results, slice.call(elements, 0) );\r
- }\r
- }\r
- break;\r
- }\r
- }\r
- }\r
-\r
- // Only loop over the given elements once\r
- // If selector is empty, we're already done\r
- if ( selector ) {\r
- matcher = compile( selector, context, xml );\r
- dirruns = matcher.dirruns++;\r
-\r
- if ( elements == null ) {\r
- elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context );\r
- }\r
- for ( i = 0; (elem = elements[i]); i++ ) {\r
- cachedruns = matcher.runs++;\r
- if ( matcher(elem, context) ) {\r
- results.push( elem );\r
- }\r
- }\r
- }\r
-\r
- return results;\r
-};\r
-\r
-if ( document.querySelectorAll ) {\r
- (function() {\r
- var disconnectedMatch,\r
- oldSelect = select,\r
- rescape = /'|\\/g,\r
- rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,\r
- rbuggyQSA = [],\r
- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\r
- // A support test would require too much code (would include document ready)\r
- // just skip matchesSelector for :active\r
- rbuggyMatches = [":active"],\r
- matches = docElem.matchesSelector ||\r
- docElem.mozMatchesSelector ||\r
- docElem.webkitMatchesSelector ||\r
- docElem.oMatchesSelector ||\r
- docElem.msMatchesSelector;\r
-\r
- // Build QSA regex\r
- // Regex strategy adopted from Diego Perini\r
- assert(function( div ) {\r
- div.innerHTML = "<select><option selected></option></select>";\r
-\r
- // IE8 - Some boolean attributes are not treated correctly\r
- if ( !div.querySelectorAll("[selected]").length ) {\r
- rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );\r
- }\r
-\r
- // Webkit/Opera - :checked should return selected option elements\r
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\r
- // IE8 throws error here (do not put tests after this one)\r
- if ( !div.querySelectorAll(":checked").length ) {\r
- rbuggyQSA.push(":checked");\r
- }\r
- });\r
-\r
- assert(function( div ) {\r
-\r
- // Opera 10-12/IE9 - ^= $= *= and empty values\r
- // Should not select anything\r
- div.innerHTML = "<p test=''></p>";\r
- if ( div.querySelectorAll("[test^='']").length ) {\r
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );\r
- }\r
-\r
- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\r
- // IE8 throws error here (do not put tests after this one)\r
- div.innerHTML = "<input type='hidden'>";\r
- if ( !div.querySelectorAll(":enabled").length ) {\r
- rbuggyQSA.push(":enabled", ":disabled");\r
- }\r
- });\r
-\r
- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );\r
-\r
- select = function( selector, context, results, seed, xml ) {\r
- // Only use querySelectorAll when not filtering,\r
- // when this is not xml,\r
- // and when no QSA bugs apply\r
- if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\r
- if ( context.nodeType === 9 ) {\r
- try {\r
- push.apply( results, slice.call(context.querySelectorAll( selector ), 0) );\r
- return results;\r
- } catch(qsaError) {}\r
- // qSA works strangely on Element-rooted queries\r
- // We can work around this by specifying an extra ID on the root\r
- // and working up from there (Thanks to Andrew Dupont for the technique)\r
- // IE 8 doesn't work on object elements\r
- } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {\r
- var old = context.getAttribute("id"),\r
- nid = old || expando,\r
- newContext = rsibling.test( selector ) && context.parentNode || context;\r
-\r
- if ( old ) {\r
- nid = nid.replace( rescape, "\\$&" );\r
- } else {\r
- context.setAttribute( "id", nid );\r
- }\r
-\r
- try {\r
- push.apply( results, slice.call( newContext.querySelectorAll(\r
- selector.replace( rgroups, "[id='" + nid + "'] $&" )\r
- ), 0 ) );\r
- return results;\r
- } catch(qsaError) {\r
- } finally {\r
- if ( !old ) {\r
- context.removeAttribute("id");\r
- }\r
- }\r
- }\r
- }\r
-\r
- return oldSelect( selector, context, results, seed, xml );\r
- };\r
-\r
- if ( matches ) {\r
- assert(function( div ) {\r
- // Check to see if it's possible to do matchesSelector\r
- // on a disconnected node (IE 9)\r
- disconnectedMatch = matches.call( div, "div" );\r
-\r
- // This should fail with an exception\r
- // Gecko does not error, returns false instead\r
- try {\r
- matches.call( div, "[test!='']:sizzle" );\r
- rbuggyMatches.push( Expr.match.PSEUDO );\r
- } catch ( e ) {}\r
- });\r
-\r
- // rbuggyMatches always contains :active, so no need for a length check\r
- rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );\r
-\r
- Sizzle.matchesSelector = function( elem, expr ) {\r
- // Make sure that attribute selectors are quoted\r
- expr = expr.replace( rattributeQuotes, "='$1']" );\r
-\r
- // rbuggyMatches always contains :active, so no need for an existence check\r
- if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {\r
- try {\r
- var ret = matches.call( elem, expr );\r
-\r
- // IE 9's matchesSelector returns false on disconnected nodes\r
- if ( ret || disconnectedMatch ||\r
- // As well, disconnected nodes are said to be in a document\r
- // fragment in IE 9\r
- elem.document && elem.document.nodeType !== 11 ) {\r
- return ret;\r
- }\r
- } catch(e) {}\r
- }\r
-\r
- return Sizzle( expr, null, null, [ elem ] ).length > 0;\r
- };\r
- }\r
- })();\r
-}\r
-\r
-// Override sizzle attribute retrieval
-Sizzle.attr = jQuery.attr;
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.pseudos;
-jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-\r
-\r
-})( window );\r
-var runtil = /Until$/,
- rparentsprev = /^(?:parents|prev(?:Until|All))/,
- isSimple = /^.[^:#\[\.,]*$/,
- rneedsContext = jQuery.expr.match.needsContext,
- // methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
+ jQuery.buildFragment = function( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults, doc,
+ first = args[ 0 ];
-jQuery.fn.extend({
- find: function( selector ) {
- var i, l, length, n, r, ret,
- self = this;
+ // nodes may contain either an explicit document object,
+ // a jQuery collection or context object.
+ // If nodes[0] contains a valid object to assign to doc
+ if ( nodes && nodes[0] ) {
+ doc = nodes[0].ownerDocument || nodes[0];
+ }
- if ( typeof selector !== "string" ) {
- return jQuery( selector ).filter(function() {
- for ( i = 0, l = self.length; i < l; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- });
+ // Ensure that an attr object doesn't incorrectly stand in as a document object
+ // Chrome and Firefox seem to allow this to occur and will throw exception
+ // Fixes #8950
+ if ( !doc.createDocumentFragment ) {
+ doc = document;
}
- ret = this.pushStack( "", "find", selector );
+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+ if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
+ first.charAt(0) === "<" && !rnocache.test( first ) &&
+ (jQuery.support.checkClone || !rchecked.test( first )) &&
+ (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
- for ( i = 0, l = this.length; i < l; i++ ) {
- length = ret.length;
- jQuery.find( selector, this[i], ret );
+ cacheable = true;
- if ( i > 0 ) {
- // Make sure that the results are unique
- for ( n = length; n < ret.length; n++ ) {
- for ( r = 0; r < length; r++ ) {
- if ( ret[r] === ret[n] ) {
- ret.splice(n--, 1);
- break;
- }
- }
- }
+ cacheresults = jQuery.fragments[ first ];
+ if ( cacheresults && cacheresults !== 1 ) {
+ fragment = cacheresults;
}
}
- return ret;
- },
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
- has: function( target ) {
- var i,
- targets = jQuery( target, this ),
- len = targets.length;
+ if ( cacheable ) {
+ jQuery.fragments[ first ] = cacheresults ? fragment : 1;
+ }
- return this.filter(function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( this, targets[i] ) ) {
- return true;
- }
- }
- });
- },
-
- not: function( selector ) {
- return this.pushStack( winnow(this, selector, false), "not", selector);
- },
-
- filter: function( selector ) {
- return this.pushStack( winnow(this, selector, true), "filter", selector );
- },
-
- is: function( selector ) {
- return !!selector && (
- typeof selector === "string" ?
- // If this is a positional/relative selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- rneedsContext.test( selector ) ?
- jQuery( selector, this.context ).index( this[0] ) >= 0 :
- jQuery.filter( selector, this ).length > 0 :
- this.filter( selector ).length > 0 );
- },
-
- closest: function( selectors, context ) {
- var cur,
- i = 0,
- l = this.length,
- ret = [],
- pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
- jQuery( selectors, context || this.context ) :
- 0;
+ return { fragment: fragment, cacheable: cacheable };
+ };
- for ( ; i < l; i++ ) {
- cur = this[i];
+ jQuery.fragments = {};
+
+ jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+ }, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [],
+ insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
- while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
- if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
- ret.push( cur );
- break;
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = ( i > 0 ? this.clone(true) : this ).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
}
- cur = cur.parentNode;
- }
- }
- ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
-
- return this.pushStack( ret, "closest", selectors );
- },
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+ });
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
+ function getAll( elem ) {
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ return elem.getElementsByTagName( "*" );
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
- }
+ } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+ return elem.querySelectorAll( "*" );
- // index in selector
- if ( typeof elem === "string" ) {
- return jQuery.inArray( this[0], jQuery( elem ) );
+ } else {
+ return [];
}
-
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[0] : elem, this );
- },
-
- add: function( selector, context ) {
- var set = typeof selector === "string" ?
- jQuery( selector, context ) :
- jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
- all = jQuery.merge( this.get(), set );
-
- return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
- all :
- jQuery.unique( all ) );
- },
-
- addBack: function( selector ) {
- return this.add( selector == null ?
- this.prevObject : this.prevObject.filter(selector)
- );
- }
-});
-
-jQuery.fn.andSelf = jQuery.fn.addBack;
-
-// A painfully simple check to see if an element is disconnected
-// from a document (should be improved, where feasible).
-function isDisconnected( node ) {
- return !node || !node.parentNode || node.parentNode.nodeType === 11;
-}
-
-function sibling( cur, dir ) {
- do {
- cur = cur[ dir ];
- } while ( cur && cur.nodeType !== 1 );
-
- return cur;
-}
-
-jQuery.each({
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return jQuery.dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return sibling( elem, "nextSibling" );
- },
- prev: function( elem ) {
- return sibling( elem, "previousSibling" );
- },
- nextAll: function( elem ) {
- return jQuery.dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return jQuery.dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
- },
- children: function( elem ) {
- return jQuery.sibling( elem.firstChild );
- },
- contents: function( elem ) {
- return jQuery.nodeName( elem, "iframe" ) ?
- elem.contentDocument || elem.contentWindow.document :
- jQuery.merge( [], elem.childNodes );
}
-}, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var ret = jQuery.map( this, fn, until );
-
- if ( !runtil.test( name ) ) {
- selector = until;
- }
- if ( selector && typeof selector === "string" ) {
- ret = jQuery.filter( selector, ret );
+// Used in clean, fixes the defaultChecked property
+ function fixDefaultChecked( elem ) {
+ if ( elem.type === "checkbox" || elem.type === "radio" ) {
+ elem.defaultChecked = elem.checked;
}
-
- ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
-
- if ( this.length > 1 && rparentsprev.test( name ) ) {
- ret = ret.reverse();
+ }
+// Finds all inputs and passes them to fixDefaultChecked
+ function findInputs( elem ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "input" ) {
+ fixDefaultChecked( elem );
+ // Skip scripts, get other children
+ } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
}
+ }
- return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
- };
-});
+// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
+ function shimCloneNode( elem ) {
+ var div = document.createElement( "div" );
+ safeFragment.appendChild( div );
-jQuery.extend({
- filter: function( expr, elems, not ) {
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
+ div.innerHTML = elem.outerHTML;
+ return div.firstChild;
+ }
- return elems.length === 1 ?
- jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
- jQuery.find.matches(expr, elems);
- },
+ jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var srcElements,
+ destElements,
+ i,
+ // IE<=8 does not properly clone detached, unknown element nodes
+ clone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ?
+ elem.cloneNode( true ) :
+ shimCloneNode( elem );
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+ // IE copies events bound via attachEvent when using cloneNode.
+ // Calling detachEvent on the clone will also remove the events
+ // from the original. In order to get around this, we use some
+ // proprietary methods to clear the events. Thanks to MooTools
+ // guys for this hotness.
+
+ cloneFixAttributes( elem, clone );
- dir: function( elem, dir, until ) {
- var matched = [],
- cur = elem[ dir ];
+ // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
- if ( cur.nodeType === 1 ) {
- matched.push( cur );
+ // Weird iteration because IE will replace the length property
+ // with an element if you are cloning the body and one of the
+ // elements on the page has a name or id of "length"
+ for ( i = 0; srcElements[i]; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ cloneFixAttributes( srcElements[i], destElements[i] );
+ }
+ }
}
- cur = cur[dir];
- }
- return matched;
- },
- sibling: function( n, elem ) {
- var r = [];
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ cloneCopyEvent( elem, clone );
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- r.push( n );
+ if ( deepDataAndEvents ) {
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ for ( i = 0; srcElements[i]; ++i ) {
+ cloneCopyEvent( srcElements[i], destElements[i] );
+ }
+ }
}
- }
- return r;
- }
-});
+ srcElements = destElements = null;
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, keep ) {
+ // Return the cloned set
+ return clone;
+ },
- // Can't pass null or undefined to indexOf in Firefox 4
- // Set to 0 to skip string check
- qualifier = qualifier || 0;
+ clean: function( elems, context, fragment, scripts ) {
+ var checkScriptType, script, j,
+ ret = [];
- if ( jQuery.isFunction( qualifier ) ) {
- return jQuery.grep(elements, function( elem, i ) {
- var retVal = !!qualifier.call( elem, i, elem );
- return retVal === keep;
- });
+ context = context || document;
- } else if ( qualifier.nodeType ) {
- return jQuery.grep(elements, function( elem, i ) {
- return ( elem === qualifier ) === keep;
- });
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ }
- } else if ( typeof qualifier === "string" ) {
- var filtered = jQuery.grep(elements, function( elem ) {
- return elem.nodeType === 1;
- });
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
- if ( isSimple.test( qualifier ) ) {
- return jQuery.filter(qualifier, filtered, !keep);
- } else {
- qualifier = jQuery.filter( qualifier, filtered );
- }
- }
+ if ( !elem ) {
+ continue;
+ }
- return jQuery.grep(elements, function( elem, i ) {
- return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
- });
-}
-function createSafeFragment( document ) {
- var list = nodeNames.split( "|" ),
- safeFrag = document.createDocumentFragment();
-
- if ( safeFrag.createElement ) {
- while ( list.length ) {
- safeFrag.createElement(
- list.pop()
- );
- }
- }
- return safeFrag;
-}
-
-var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
- "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
- rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
- rleadingWhitespace = /^\s+/,
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
- rtagName = /<([\w:]+)/,
- rtbody = /<tbody/i,
- rhtml = /<|&#?\w+;/,
- rnoInnerhtml = /<(?:script|style|link)/i,
- rnocache = /<(?:script|object|embed|option|style)/i,
- rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
- rcheckableType = /^(?:checkbox|radio)$/,
- // checked="checked" or checked
- rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
- rscriptType = /\/(java|ecma)script/i,
- rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,
- wrapMap = {
- option: [ 1, "<select multiple='multiple'>", "</select>" ],
- legend: [ 1, "<fieldset>", "</fieldset>" ],
- thead: [ 1, "<table>", "</table>" ],
- tr: [ 2, "<table><tbody>", "</tbody></table>" ],
- td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
- col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
- area: [ 1, "<map>", "</map>" ],
- _default: [ 0, "", "" ]
- },
- safeFragment = createSafeFragment( document ),
- fragmentDiv = safeFragment.appendChild( document.createElement("div") );
-
-wrapMap.optgroup = wrapMap.option;
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
-
-// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
-// unless wrapped in a div with non-breaking characters in front of it.
-if ( !jQuery.support.htmlSerialize ) {
- wrapMap._default = [ 1, "X<div>", "</div>" ];
-}
-
-jQuery.fn.extend({
- text: function( value ) {
- return jQuery.access( this, function( value ) {
- return value === undefined ?
- jQuery.text( this ) :
- this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
- }, null, value, arguments.length );
- },
-
- wrapAll: function( html ) {
- if ( jQuery.isFunction( html ) ) {
- return this.each(function(i) {
- jQuery(this).wrapAll( html.call(this, i) );
- });
- }
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ if ( !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+ } else {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div"),
+ safeChildNodes = safeFragment.childNodes,
+ remove;
+
+ // Append wrapper element to unknown element safe doc fragment
+ if ( context === document ) {
+ // Use the fragment we've already created for this document
+ safeFragment.appendChild( div );
+ } else {
+ // Use a fragment created with the owner document
+ createSafeFragment( context ).appendChild( div );
+ }
- if ( this[0] ) {
- // The elements to wrap the target around
- var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
- if ( this[0].parentNode ) {
- wrap.insertBefore( this[0] );
- }
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
- wrap.map(function() {
- var elem = this;
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
- while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
- elem = elem.firstChild;
- }
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
- return elem;
- }).append( this );
- }
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
- return this;
- },
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+ }
- wrapInner: function( html ) {
- if ( jQuery.isFunction( html ) ) {
- return this.each(function(i) {
- jQuery(this).wrapInner( html.call(this, i) );
- });
- }
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
- return this.each(function() {
- var self = jQuery( this ),
- contents = self.contents();
+ elem = div.childNodes;
- if ( contents.length ) {
- contents.wrapAll( html );
+ // Clear elements from DocumentFragment (safeFragment or otherwise)
+ // to avoid hoarding elements. Fixes #11356
+ if ( div ) {
+ div.parentNode.removeChild( div );
- } else {
- self.append( html );
- }
- });
- },
+ // Guard against -1 index exceptions in FF3.6
+ if ( safeChildNodes.length > 0 ) {
+ remove = safeChildNodes[ safeChildNodes.length - 1 ];
- wrap: function( html ) {
- var isFunction = jQuery.isFunction( html );
+ if ( remove && remove.parentNode ) {
+ remove.parentNode.removeChild( remove );
+ }
+ }
+ }
+ }
+ }
- return this.each(function(i) {
- jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
- });
- },
+ // Resets defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ var len;
+ if ( !jQuery.support.appendChecked ) {
+ if ( elem[0] && typeof (len = elem.length) === "number" ) {
+ for ( j = 0; j < len; j++ ) {
+ findInputs( elem[j] );
+ }
+ } else {
+ findInputs( elem );
+ }
+ }
- unwrap: function() {
- return this.parent().each(function() {
- if ( !jQuery.nodeName( this, "body" ) ) {
- jQuery( this ).replaceWith( this.childNodes );
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
}
- }).end();
- },
- append: function() {
- return this.domManip(arguments, true, function( elem ) {
- if ( this.nodeType === 1 || this.nodeType === 11 ) {
- this.appendChild( elem );
- }
- });
- },
+ if ( fragment ) {
+ checkScriptType = function( elem ) {
+ return !elem.type || rscriptType.test( elem.type );
+ };
+ for ( i = 0; ret[i]; i++ ) {
+ script = ret[i];
+ if ( scripts && jQuery.nodeName( script, "script" ) && (!script.type || rscriptType.test( script.type )) ) {
+ scripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );
+
+ } else {
+ if ( script.nodeType === 1 ) {
+ var jsTags = jQuery.grep( script.getElementsByTagName( "script" ), checkScriptType );
- prepend: function() {
- return this.domManip(arguments, true, function( elem ) {
- if ( this.nodeType === 1 || this.nodeType === 11 ) {
- this.insertBefore( elem, this.firstChild );
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ }
+ fragment.appendChild( script );
+ }
+ }
}
- });
- },
- before: function() {
- if ( !isDisconnected( this[0] ) ) {
- return this.domManip(arguments, false, function( elem ) {
- this.parentNode.insertBefore( elem, this );
- });
- }
+ return ret;
+ },
- if ( arguments.length ) {
- var set = jQuery.clean( arguments );
- return this.pushStack( jQuery.merge( set, this ), "before", this.selector );
- }
- },
+ cleanData: function( elems ) {
+ var data, id,
+ cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
- after: function() {
- if ( !isDisconnected( this[0] ) ) {
- return this.domManip(arguments, false, function( elem ) {
- this.parentNode.insertBefore( elem, this.nextSibling );
- });
- }
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ continue;
+ }
- if ( arguments.length ) {
- var set = jQuery.clean( arguments );
- return this.pushStack( jQuery.merge( this, set ), "after", this.selector );
- }
- },
+ id = elem[ jQuery.expando ];
- // keepData is for internal use only--do not document
- remove: function( selector, keepData ) {
- var elem,
- i = 0;
+ if ( id ) {
+ data = cache[ id ];
- for ( ; (elem = this[i]) != null; i++ ) {
- if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
- if ( !keepData && elem.nodeType === 1 ) {
- jQuery.cleanData( elem.getElementsByTagName("*") );
- jQuery.cleanData( [ elem ] );
- }
+ if ( data && data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
- if ( elem.parentNode ) {
- elem.parentNode.removeChild( elem );
- }
- }
- }
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
- return this;
- },
+ // Null the DOM reference to avoid IE6/7/8 leak (#7054)
+ if ( data.handle ) {
+ data.handle.elem = null;
+ }
+ }
- empty: function() {
- var elem,
- i = 0;
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
- for ( ; (elem = this[i]) != null; i++ ) {
- // Remove element nodes and prevent memory leaks
- if ( elem.nodeType === 1 ) {
- jQuery.cleanData( elem.getElementsByTagName("*") );
- }
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
- // Remove any remaining nodes
- while ( elem.firstChild ) {
- elem.removeChild( elem.firstChild );
+ delete cache[ id ];
+ }
}
}
+ });
- return this;
- },
- clone: function( dataAndEvents, deepDataAndEvents ) {
- dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
- deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
- return this.map( function () {
- return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
- });
- },
- html: function( value ) {
- return jQuery.access( this, function( value ) {
- var elem = this[0] || {},
- i = 0,
- l = this.length;
+ var ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity=([^)]*)/,
+ // fixed for IE9, see #8346
+ rupper = /([A-Z]|^ms)/g,
+ rnum = /^[\-+]?(?:\d*\.)?\d+$/i,
+ rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,
+ rrelNum = /^([\-+])=([\-+.\de]+)/,
+ rmargin = /^margin/,
- if ( value === undefined ) {
- return elem.nodeType === 1 ?
- elem.innerHTML.replace( rinlinejQuery, "" ) :
- undefined;
- }
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
- // See if we can take a shortcut and just use innerHTML
- if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
- ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
- ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
- !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+ // order is important!
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
- value = value.replace( rxhtmlTag, "<$1></$2>" );
+ curCSS,
- try {
- for (; i < l; i++ ) {
- // Remove element nodes and prevent memory leaks
- elem = this[i] || {};
- if ( elem.nodeType === 1 ) {
- jQuery.cleanData( elem.getElementsByTagName( "*" ) );
- elem.innerHTML = value;
- }
- }
+ getComputedStyle,
+ currentStyle;
- elem = 0;
+ jQuery.fn.css = function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ };
- // If using innerHTML throws an exception, use the fallback method
- } catch(e) {}
- }
+ jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
- if ( elem ) {
- this.empty().append( value );
+ } else {
+ return elem.style.opacity;
+ }
+ }
}
- }, null, value, arguments.length );
- },
+ },
- replaceWith: function( value ) {
- if ( !isDisconnected( this[0] ) ) {
- // Make sure that the elements are removed from the DOM before they are inserted
- // this can help fix replacing a parent with child elements
- if ( jQuery.isFunction( value ) ) {
- return this.each(function(i) {
- var self = jQuery(this), old = self.html();
- self.replaceWith( value.call( this, i, old ) );
- });
- }
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
- if ( typeof value !== "string" ) {
- value = jQuery( value ).detach();
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
}
- return this.each(function() {
- var next = this.nextSibling,
- parent = this.parentNode;
+ // Make sure that we're working with the right name
+ var ret, type, origName = jQuery.camelCase( name ),
+ style = elem.style, hooks = jQuery.cssHooks[ origName ];
- jQuery( this ).remove();
+ name = jQuery.cssProps[ origName ] || origName;
- if ( next ) {
- jQuery(next).before( value );
- } else {
- jQuery(parent).append( value );
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
}
- });
- }
- return this.length ?
- this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
- this;
- },
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
- detach: function( selector ) {
- return this.remove( selector, true );
- },
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
- domManip: function( args, table, callback ) {
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
- // Flatten any nested arrays
- args = [].concat.apply( [], args );
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
- var results, first, fragment, iNoClone,
- i = 0,
- value = args[0],
- scripts = [],
- l = this.length;
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
- // We can't cloneNode fragments that contain checked, in WebKit
- if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) {
- return this.each(function() {
- jQuery(this).domManip( args, table, callback );
- });
- }
+ css: function( elem, name, extra ) {
+ var ret, hooks;
- if ( jQuery.isFunction(value) ) {
- return this.each(function(i) {
- var self = jQuery(this);
- args[0] = value.call( this, i, table ? self.html() : undefined );
- self.domManip( args, table, callback );
- });
- }
+ // Make sure that we're working with the right name
+ name = jQuery.camelCase( name );
+ hooks = jQuery.cssHooks[ name ];
+ name = jQuery.cssProps[ name ] || name;
- if ( this[0] ) {
- results = jQuery.buildFragment( args, this, scripts );
- fragment = results.fragment;
- first = fragment.firstChild;
-
- if ( fragment.childNodes.length === 1 ) {
- fragment = first;
- }
-
- if ( first ) {
- table = table && jQuery.nodeName( first, "tr" );
-
- // Use the original fragment for the last item instead of the first because it can end up
- // being emptied incorrectly in certain situations (#8070).
- // Fragments from the fragment cache must always be cloned and never used in place.
- for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {
- callback.call(
- table && jQuery.nodeName( this[i], "table" ) ?
- findOrAppend( this[i], "tbody" ) :
- this[i],
- i === iNoClone ?
- fragment :
- jQuery.clone( fragment, true, true )
- );
- }
+ // cssFloat needs a special treatment
+ if ( name === "cssFloat" ) {
+ name = "float";
}
- // Fix #11809: Avoid leaking memory
- fragment = first = null;
-
- if ( scripts.length ) {
- jQuery.each( scripts, function( i, elem ) {
- if ( elem.src ) {
- if ( jQuery.ajax ) {
- jQuery.ajax({
- url: elem.src,
- type: "GET",
- dataType: "script",
- async: false,
- global: false,
- "throws": true
- });
- } else {
- jQuery.error("no ajax");
- }
- } else {
- jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) );
- }
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+ return ret;
- if ( elem.parentNode ) {
- elem.parentNode.removeChild( elem );
- }
- });
+ // Otherwise, if a way to get the computed value exists, use that
+ } else if ( curCSS ) {
+ return curCSS( elem, name );
}
- }
+ },
- return this;
- }
-});
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {},
+ ret, name;
-function findOrAppend( elem, tag ) {
- return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
-}
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
-function cloneCopyEvent( src, dest ) {
+ ret = callback.call( elem );
- if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
- return;
- }
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
- var type, i, l,
- oldData = jQuery._data( src ),
- curData = jQuery._data( dest, oldData ),
- events = oldData.events;
+ return ret;
+ }
+ });
- if ( events ) {
- delete curData.handle;
- curData.events = {};
+// DEPRECATED in 1.3, Use jQuery.css() instead
+ jQuery.curCSS = jQuery.css;
- for ( type in events ) {
- for ( i = 0, l = events[ type ].length; i < l; i++ ) {
- jQuery.event.add( dest, type, events[ type ][ i ] );
- }
- }
- }
+ if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ getComputedStyle = function( elem, name ) {
+ var ret, defaultView, computedStyle, width,
+ style = elem.style;
- // make the cloned public data object a copy from the original
- if ( curData.data ) {
- curData.data = jQuery.extend( {}, curData.data );
- }
-}
+ name = name.replace( rupper, "-$1" ).toLowerCase();
-function cloneFixAttributes( src, dest ) {
- var nodeName;
+ if ( (defaultView = elem.ownerDocument.defaultView) &&
+ (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
- // We do not need to do anything for non-Elements
- if ( dest.nodeType !== 1 ) {
- return;
- }
+ ret = computedStyle.getPropertyValue( name );
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+ }
- // clearAttributes removes the attributes, which we don't want,
- // but also removes the attachEvent events, which we *do* want
- if ( dest.clearAttributes ) {
- dest.clearAttributes();
- }
+ // A tribute to the "awesome hack by Dean Edwards"
+ // WebKit uses "computed value (percentage if specified)" instead of "used value" for margins
+ // which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {
+ width = style.width;
+ style.width = ret;
+ ret = computedStyle.width;
+ style.width = width;
+ }
- // mergeAttributes, in contrast, only merges back on the
- // original attributes, not the events
- if ( dest.mergeAttributes ) {
- dest.mergeAttributes( src );
+ return ret;
+ };
}
- nodeName = dest.nodeName.toLowerCase();
-
- if ( nodeName === "object" ) {
- // IE6-10 improperly clones children of object elements using classid.
- // IE10 throws NoModificationAllowedError if parent is null, #12132.
- if ( dest.parentNode ) {
- dest.outerHTML = src.outerHTML;
- }
+ if ( document.documentElement.currentStyle ) {
+ currentStyle = function( elem, name ) {
+ var left, rsLeft, uncomputed,
+ ret = elem.currentStyle && elem.currentStyle[ name ],
+ style = elem.style;
- // This path appears unavoidable for IE9. When cloning an object
- // element in IE9, the outerHTML strategy above is not sufficient.
- // If the src has innerHTML and the destination does not,
- // copy the src.innerHTML into the dest.innerHTML. #10324
- if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {
- dest.innerHTML = src.innerHTML;
- }
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && (uncomputed = style[ name ]) ) {
+ ret = uncomputed;
+ }
- } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
- // IE6-8 fails to persist the checked state of a cloned checkbox
- // or radio button. Worse, IE6-7 fail to give the cloned element
- // a checked appearance if the defaultChecked value isn't also set
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
- dest.defaultChecked = dest.checked = src.checked;
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( rnumnonpx.test( ret ) ) {
- // IE6-7 get confused and end up setting the value of a cloned
- // checkbox/radio button to an empty string instead of "on"
- if ( dest.value !== src.value ) {
- dest.value = src.value;
- }
+ // Remember the original values
+ left = style.left;
+ rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
- // IE6-8 fails to return the selected option to the default selected
- // state when cloning options
- } else if ( nodeName === "option" ) {
- dest.selected = src.defaultSelected;
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
- // IE6-8 fails to set the defaultValue to the correct value when
- // cloning other types of input fields
- } else if ( nodeName === "input" || nodeName === "textarea" ) {
- dest.defaultValue = src.defaultValue;
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
- // IE blanks contents when cloning scripts
- } else if ( nodeName === "script" && dest.text !== src.text ) {
- dest.text = src.text;
+ return ret === "" ? "auto" : ret;
+ };
}
- // Event data gets referenced instead of copied if the expando
- // gets copied too
- dest.removeAttribute( jQuery.expando );
-}
+ curCSS = getComputedStyle || currentStyle;
-jQuery.buildFragment = function( args, context, scripts ) {
- var fragment, cacheable, cachehit,
- first = args[ 0 ];
+ function getWidthOrHeight( elem, name, extra ) {
- // Set context from what may come in as undefined or a jQuery collection or a node
- context = context || document;
- context = (context[0] || context).ownerDocument || context[0] || context;
+ // Start with offset property
+ var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ i = name === "width" ? 1 : 0,
+ len = 4;
- // Ensure that an attr object doesn't incorrectly stand in as a document object
- // Chrome and Firefox seem to allow this to occur and will throw exception
- // Fixes #8950
- if ( typeof context.createDocumentFragment === "undefined" ) {
- context = document;
- }
+ if ( val > 0 ) {
+ if ( extra !== "border" ) {
+ for ( ; i < len; i += 2 ) {
+ if ( !extra ) {
+ val -= parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;
+ } else {
+ val -= parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ }
+ }
+ }
- // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
- // Cloning options loses the selected state, so don't cache them
- // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
- // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
- // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
- if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document &&
- first.charAt(0) === "<" && !rnocache.test( first ) &&
- (jQuery.support.checkClone || !rchecked.test( first )) &&
- (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
-
- // Mark cacheable and look for a hit
- cacheable = true;
- fragment = jQuery.fragments[ first ];
- cachehit = fragment !== undefined;
- }
+ return val + "px";
+ }
- if ( !fragment ) {
- fragment = context.createDocumentFragment();
- jQuery.clean( args, context, fragment, scripts );
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
- // Update the cache, but only store false
- // unless this is a second parsing of the same content
- if ( cacheable ) {
- jQuery.fragments[ first ] = cachehit && fragment;
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
}
- }
- return { fragment: fragment, cacheable: cacheable };
-};
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
-jQuery.fragments = {};
+ // Add padding, border, margin
+ if ( extra ) {
+ for ( ; i < len; i += 2 ) {
+ val += parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
+ if ( extra !== "padding" ) {
+ val += parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;
+ }
+ }
+ }
-jQuery.each({
- appendTo: "append",
- prependTo: "prepend",
- insertBefore: "before",
- insertAfter: "after",
- replaceAll: "replaceWith"
-}, function( name, original ) {
- jQuery.fn[ name ] = function( selector ) {
- var elems,
- i = 0,
- ret = [],
- insert = jQuery( selector ),
- l = insert.length,
- parent = this.length === 1 && this[0].parentNode;
+ return val + "px";
+ }
- if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {
- insert[ original ]( this[0] );
- return this;
- } else {
- for ( ; i < l; i++ ) {
- elems = ( i > 0 ? this.clone(true) : this ).get();
- jQuery( insert[i] )[ original ]( elems );
- ret = ret.concat( elems );
+ jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ if ( elem.offsetWidth !== 0 ) {
+ return getWidthOrHeight( elem, name, extra );
+ } else {
+ return jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ });
+ }
+ }
+ },
+
+ set: function( elem, value ) {
+ return rnum.test( value ) ?
+ value + "px" :
+ value;
}
+ };
+ });
- return this.pushStack( ret, name, insert.selector );
- }
- };
-});
+ if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( parseFloat( RegExp.$1 ) / 100 ) + "" :
+ computed ? "1" : "";
+ },
-function getAll( elem ) {
- if ( typeof elem.getElementsByTagName !== "undefined" ) {
- return elem.getElementsByTagName( "*" );
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
- } else if ( typeof elem.querySelectorAll !== "undefined" ) {
- return elem.querySelectorAll( "*" );
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
- } else {
- return [];
- }
-}
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
-// Used in clean, fixes the defaultChecked property
-function fixDefaultChecked( elem ) {
- if ( rcheckableType.test( elem.type ) ) {
- elem.defaultChecked = elem.checked;
- }
-}
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
-jQuery.extend({
- clone: function( elem, dataAndEvents, deepDataAndEvents ) {
- var srcElements,
- destElements,
- i,
- clone;
+ // if there there is no filter style applied in a css rule, we are done
+ if ( currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
- if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
- clone = elem.cloneNode( true );
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+ }
- // IE<=8 does not properly clone detached, unknown element nodes
- } else {
- fragmentDiv.innerHTML = elem.outerHTML;
- fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ jQuery(function() {
+ // This hook cannot be added until DOM ready because the support test
+ // for it is not run until after DOM ready
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" }, function() {
+ if ( computed ) {
+ return curCSS( elem, "margin-right" );
+ } else {
+ return elem.style.marginRight;
+ }
+ });
+ }
+ };
}
+ });
- if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
- (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
- // IE copies events bound via attachEvent when using cloneNode.
- // Calling detachEvent on the clone will also remove the events
- // from the original. In order to get around this, we use some
- // proprietary methods to clear the events. Thanks to MooTools
- // guys for this hotness.
+ if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth,
+ height = elem.offsetHeight;
- cloneFixAttributes( elem, clone );
+ return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
- // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
- srcElements = getAll( elem );
- destElements = getAll( clone );
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+ }
- // Weird iteration because IE will replace the length property
- // with an element if you are cloning the body and one of the
- // elements on the page has a name or id of "length"
- for ( i = 0; srcElements[i]; ++i ) {
- // Ensure that the destination node is not null; Fixes #9587
- if ( destElements[i] ) {
- cloneFixAttributes( srcElements[i], destElements[i] );
- }
- }
- }
+// These hooks are used by animate to expand properties
+ jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+ }, function( prefix, suffix ) {
- // Copy the events from the original to the clone
- if ( dataAndEvents ) {
- cloneCopyEvent( elem, clone );
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i,
- if ( deepDataAndEvents ) {
- srcElements = getAll( elem );
- destElements = getAll( clone );
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ],
+ expanded = {};
- for ( i = 0; srcElements[i]; ++i ) {
- cloneCopyEvent( srcElements[i], destElements[i] );
+ for ( i = 0; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
}
- }
- }
- srcElements = destElements = null;
+ return expanded;
+ }
+ };
+ });
- // Return the cloned set
- return clone;
- },
- clean: function( elems, context, fragment, scripts ) {
- var j, safe, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
- i = 0,
- ret = [];
- // Ensure that context is a document
- if ( !context || typeof context.createDocumentFragment === "undefined" ) {
- context = document;
- }
- // Use the already-created safe fragment if context permits
- for ( safe = context === document && safeFragment; (elem = elems[i]) != null; i++ ) {
- if ( typeof elem === "number" ) {
- elem += "";
- }
+ var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rhash = /#.*$/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rquery = /\?/,
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ rselectTextarea = /^(?:select|textarea)/i,
+ rspacesAjax = /\s+/,
+ rts = /([?&])_=[^&]*/,
+ rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
- if ( !elem ) {
- continue;
- }
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
- // Convert html string into DOM nodes
- if ( typeof elem === "string" ) {
- if ( !rhtml.test( elem ) ) {
- elem = context.createTextNode( elem );
- } else {
- // Ensure a safe container in which to render the html
- safe = safe || createSafeFragment( context );
- div = div || safe.appendChild( context.createElement("div") );
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
- // Fix "XHTML"-style tags in all browsers
- elem = elem.replace(rxhtmlTag, "<$1></$2>");
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
- // Go to html and back, then peel off extra wrappers
- tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
- wrap = wrapMap[ tag ] || wrapMap._default;
- depth = wrap[0];
- div.innerHTML = wrap[1] + elem + wrap[2];
+ // Document location
+ ajaxLocation,
- // Move to the right depth
- while ( depth-- ) {
- div = div.lastChild;
- }
+ // Document location segments
+ ajaxLocParts,
- // Remove IE's autoinserted <tbody> from table fragments
- if ( !jQuery.support.tbody ) {
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = ["*/"] + ["*"];
- // String was a <table>, *may* have spurious <tbody>
- hasBody = rtbody.test(elem);
- tbody = tag === "table" && !hasBody ?
- div.firstChild && div.firstChild.childNodes :
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+ try {
+ ajaxLocation = location.href;
+ } catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+ }
- // String was a bare <thead> or <tfoot>
- wrap[1] === "<table>" && !hasBody ?
- div.childNodes :
- [];
+// Segment location into parts
+ ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
- for ( j = tbody.length - 1; j >= 0 ; --j ) {
- if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
- tbody[ j ].parentNode.removeChild( tbody[ j ] );
- }
- }
- }
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+ function addToPrefiltersOrTransports( structure ) {
- // IE completely kills leading whitespace when innerHTML is used
- if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
- div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
- }
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
- elem = div.childNodes;
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
- // Remember the top-level container for proper cleanup
- div = safe.lastChild;
+ if ( jQuery.isFunction( func ) ) {
+ var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
+ i = 0,
+ length = dataTypes.length,
+ dataType,
+ list,
+ placeBefore;
+
+ // For each dataType in the dataTypeExpression
+ for ( ; i < length; i++ ) {
+ dataType = dataTypes[ i ];
+ // We control if we're asked to add before
+ // any existing element
+ placeBefore = /^\+/.test( dataType );
+ if ( placeBefore ) {
+ dataType = dataType.substr( 1 ) || "*";
+ }
+ list = structure[ dataType ] = structure[ dataType ] || [];
+ // then we add to the structure accordingly
+ list[ placeBefore ? "unshift" : "push" ]( func );
}
}
+ };
+ }
- if ( elem.nodeType ) {
- ret.push( elem );
- } else {
- ret = jQuery.merge( ret, elem );
- }
- }
+// Base inspection function for prefilters and transports
+ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+ dataType /* internal */, inspected /* internal */ ) {
- // Fix #11356: Clear elements from safeFragment
- if ( div ) {
- safe.removeChild( div );
- elem = div = safe = null;
- }
+ dataType = dataType || options.dataTypes[ 0 ];
+ inspected = inspected || {};
- // Reset defaultChecked for any radios and checkboxes
- // about to be appended to the DOM in IE 6/7 (#8060)
- if ( !jQuery.support.appendChecked ) {
- for ( i = 0; (elem = ret[i]) != null; i++ ) {
- if ( jQuery.nodeName( elem, "input" ) ) {
- fixDefaultChecked( elem );
- } else if ( typeof elem.getElementsByTagName !== "undefined" ) {
- jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+ inspected[ dataType ] = true;
+
+ var list = structure[ dataType ],
+ i = 0,
+ length = list ? list.length : 0,
+ executeOnly = ( structure === prefilters ),
+ selection;
+
+ for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+ selection = list[ i ]( options, originalOptions, jqXHR );
+ // If we got redirected to another dataType
+ // we try there if executing only and not done already
+ if ( typeof selection === "string" ) {
+ if ( !executeOnly || inspected[ selection ] ) {
+ selection = undefined;
+ } else {
+ options.dataTypes.unshift( selection );
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, selection, inspected );
}
}
}
+ // If we're only executing or nothing was selected
+ // we try the catchall dataType if not done already
+ if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, "*", inspected );
+ }
+ // unnecessary when only executing (prefilters)
+ // but it'll be ignored by the caller in that case
+ return selection;
+ }
- // Append elements to a provided document fragment
- if ( fragment ) {
- // Special handling of each script element
- handleScript = function( elem ) {
- // Check if we consider it executable
- if ( !elem.type || rscriptType.test( elem.type ) ) {
- // Detach the script and store it in the scripts array (if provided) or the fragment
- // Return truthy to indicate that it has been handled
- return scripts ?
- scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
- fragment.appendChild( elem );
- }
- };
-
- for ( i = 0; (elem = ret[i]) != null; i++ ) {
- // Check if we're done after handling an executable script
- if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
- // Append to fragment and handle embedded scripts
- fragment.appendChild( elem );
- if ( typeof elem.getElementsByTagName !== "undefined" ) {
- // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
- jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
-
- // Splice the scripts into ret after their former ancestor and advance our index beyond them
- ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
- i += jsTags.length;
- }
- }
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+ function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
}
}
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+ }
- return ret;
- },
-
- cleanData: function( elems, /* internal */ acceptData ) {
- var data, id, elem, type,
- i = 0,
- internalKey = jQuery.expando,
- cache = jQuery.cache,
- deleteExpando = jQuery.support.deleteExpando,
- special = jQuery.event.special;
-
- for ( ; (elem = elems[i]) != null; i++ ) {
-
- if ( acceptData || jQuery.acceptData( elem ) ) {
-
- id = elem[ internalKey ];
- data = id && cache[ id ];
+ jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
- if ( data ) {
- if ( data.events ) {
- for ( type in data.events ) {
- if ( special[ type ] ) {
- jQuery.event.remove( elem, type );
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
- // This is a shortcut to avoid jQuery.event.remove's overhead
- } else {
- jQuery.removeEvent( elem, type, data.handle );
- }
- }
- }
+ var off = url.indexOf( " " );
+ if ( off >= 0 ) {
+ var selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
- // Remove cache only if it was not already removed by jQuery.event.remove
- if ( cache[ id ] ) {
+ // Default to a GET request
+ var type = "GET";
- delete cache[ id ];
+ // If the second parameter was provided
+ if ( params ) {
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
- // IE does not allow us to delete expando properties from nodes,
- // nor does it have a removeAttribute function on Document nodes;
- // we must handle all of these cases
- if ( deleteExpando ) {
- delete elem[ internalKey ];
+ // Otherwise, build a param string
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+ type = "POST";
+ }
+ }
- } else if ( elem.removeAttribute ) {
- elem.removeAttribute( internalKey );
+ var self = this;
- } else {
- elem[ internalKey ] = null;
- }
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ // Complete callback (responseText is used internally)
+ complete: function( jqXHR, status, responseText ) {
+ // Store the response as specified by the jqXHR object
+ responseText = jqXHR.responseText;
+ // If successful, inject the HTML into all the matched elements
+ if ( jqXHR.isResolved() ) {
+ // #4825: Get the actual response in case
+ // a dataFilter is present in ajaxSettings
+ jqXHR.done(function( r ) {
+ responseText = r;
+ });
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(responseText.replace(rscript, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ responseText );
+ }
- jQuery.deletedIds.push( id );
+ if ( callback ) {
+ self.each( callback, [ responseText, status, jqXHR ] );
}
}
- }
- }
- }
-});
-// Limit scope pollution from any deprecated API
-(function() {
-
-var matched, browser;
-
-// Use of jQuery.browser is frowned upon.
-// More details: http://api.jquery.com/jQuery.browser
-// jQuery.uaMatch maintained for back-compat
-jQuery.uaMatch = function( ua ) {
- ua = ua.toLowerCase();
-
- var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
- /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
- /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
- /(msie) ([\w.]+)/.exec( ua ) ||
- ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
- [];
-
- return {
- browser: match[ 1 ] || "",
- version: match[ 2 ] || "0"
- };
-};
-
-matched = jQuery.uaMatch( navigator.userAgent );
-browser = {};
-
-if ( matched.browser ) {
- browser[ matched.browser ] = true;
- browser.version = matched.version;
-}
+ });
-// Deprecated, use jQuery.browser.webkit instead
-// Maintained for back-compat only
-if ( browser.webkit ) {
- browser.safari = true;
-}
+ return this;
+ },
-jQuery.browser = browser;
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
-jQuery.sub = function() {
- function jQuerySub( selector, context ) {
- return new jQuerySub.fn.init( selector, context );
- }
- jQuery.extend( true, jQuerySub, this );
- jQuerySub.superclass = this;
- jQuerySub.fn = jQuerySub.prototype = this();
- jQuerySub.fn.constructor = jQuerySub;
- jQuerySub.sub = this.sub;
- jQuerySub.fn.init = function init( selector, context ) {
- if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
- context = jQuerySub( context );
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray( this.elements ) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
+ rinput.test( this.type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val, i ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
}
+ });
- return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
- };
- jQuerySub.fn.init.prototype = jQuerySub.fn;
- var rootjQuerySub = jQuerySub(document);
- return jQuerySub;
-};
-
-})();
-var curCSS, iframe, iframeDoc,
- ralpha = /alpha\([^)]*\)/i,
- ropacity = /opacity=([^)]*)/,
- rposition = /^(top|right|bottom|left)$/,
- rmargin = /^margin/,
- rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
- rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
- rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
- elemdisplay = {},
-
- cssShow = { position: "absolute", visibility: "hidden", display: "block" },
- cssNormalTransform = {
- letterSpacing: 0,
- fontWeight: 400,
- lineHeight: 1
- },
-
- cssExpand = [ "Top", "Right", "Bottom", "Left" ],
- cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
-
- eventsToggle = jQuery.fn.toggle;
-
-// return a css property mapped to a potentially vendor prefixed property
-function vendorPropName( style, name ) {
-
- // shortcut for names that are not vendor prefixed
- if ( name in style ) {
- return name;
- }
-
- // check for vendor prefixed names
- var capName = name.charAt(0).toUpperCase() + name.slice(1),
- origName = name,
- i = cssPrefixes.length;
-
- while ( i-- ) {
- name = cssPrefixes[ i ] + capName;
- if ( name in style ) {
- return name;
- }
- }
+// Attach a bunch of functions for handling common AJAX events
+ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+ jQuery.fn[ o ] = function( f ){
+ return this.on( o, f );
+ };
+ });
- return origName;
-}
+ jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
-function isHidden( elem, el ) {
- elem = el || elem;
- return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
-}
+ return jQuery.ajax({
+ type: method,
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ };
+ });
-function showHide( elements, show ) {
- var elem, display,
- values = [],
- index = 0,
- length = elements.length;
+ jQuery.extend({
- for ( ; index < length; index++ ) {
- elem = elements[ index ];
- if ( !elem.style ) {
- continue;
- }
- values[ index ] = jQuery._data( elem, "olddisplay" );
- if ( show ) {
- // Reset the inline display of this element to learn if it is
- // being hidden by cascaded rules or not
- if ( !values[ index ] && elem.style.display === "none" ) {
- elem.style.display = "";
- }
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
- // Set elements which have been overridden with display: none
- // in a stylesheet to whatever the default browser style is
- // for such an element
- if ( elem.style.display === "" && isHidden( elem ) ) {
- values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
- }
- } else {
- display = curCSS( elem, "display" );
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
- if ( !values[ index ] && display !== "none" ) {
- jQuery._data( elem, "olddisplay", display );
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ if ( settings ) {
+ // Building a settings object
+ ajaxExtend( target, jQuery.ajaxSettings );
+ } else {
+ // Extending ajaxSettings
+ settings = target;
+ target = jQuery.ajaxSettings;
}
- }
- }
+ ajaxExtend( target, settings );
+ return target;
+ },
- // Set the display of most of the elements in a second loop
- // to avoid the constant reflow
- for ( index = 0; index < length; index++ ) {
- elem = elements[ index ];
- if ( !elem.style ) {
- continue;
- }
- if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
- elem.style.display = show ? values[ index ] || "" : "none";
- }
- }
+ ajaxSettings: {
+ url: ajaxLocation,
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ text: "text/plain",
+ json: "application/json, text/javascript",
+ "*": allTypes
+ },
- return elements;
-}
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
-jQuery.fn.extend({
- css: function( name, value ) {
- return jQuery.access( this, function( elem, name, value ) {
- return value !== undefined ?
- jQuery.style( elem, name, value ) :
- jQuery.css( elem, name );
- }, name, value, arguments.length > 1 );
- },
- show: function() {
- return showHide( this, true );
- },
- hide: function() {
- return showHide( this );
- },
- toggle: function( state, fn2 ) {
- var bool = typeof state === "boolean";
-
- if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
- return eventsToggle.apply( this, arguments );
- }
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
- return this.each(function() {
- if ( bool ? state : isHidden( this ) ) {
- jQuery( this ).show();
- } else {
- jQuery( this ).hide();
- }
- });
- }
-});
+ // List of data converters
+ // 1) key format is "source_type destination_type" (a single space in-between)
+ // 2) the catchall symbol "*" can be used for source_type
+ converters: {
-jQuery.extend({
- // Add in style property hooks for overriding the default
- // behavior of getting and setting a style property
- cssHooks: {
- opacity: {
- get: function( elem, computed ) {
- if ( computed ) {
- // We should always get a number back from opacity
- var ret = curCSS( elem, "opacity" );
- return ret === "" ? "1" : ret;
+ // Convert anything to text
+ "* text": window.String,
- }
- }
- }
- },
-
- // Exclude the following css properties to add px
- cssNumber: {
- "fillOpacity": true,
- "fontWeight": true,
- "lineHeight": true,
- "opacity": true,
- "orphans": true,
- "widows": true,
- "zIndex": true,
- "zoom": true
- },
-
- // Add in properties whose names you wish to fix before
- // setting or getting the value
- cssProps: {
- // normalize float css property
- "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
- },
-
- // Get and set the style property on a DOM Node
- style: function( elem, name, value, extra ) {
- // Don't set styles on text and comment nodes
- if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
- return;
- }
+ // Text to html (true = no transformation)
+ "text html": true,
- // Make sure that we're working with the right name
- var ret, type, hooks,
- origName = jQuery.camelCase( name ),
- style = elem.style;
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
- name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
- // gets hook for the prefixed version
- // followed by the unprefixed version
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ context: true,
+ url: true
+ }
+ },
- // Check if we're setting a value
- if ( value !== undefined ) {
- type = typeof value;
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
- // convert relative number strings (+= or -=) to relative numbers. #7345
- if ( type === "string" && (ret = rrelNum.exec( value )) ) {
- value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
- // Fixes bug #9237
- type = "number";
- }
+ // Main method
+ ajax: function( url, options ) {
- // Make sure that NaN and null values aren't set. See: #7116
- if ( value == null || type === "number" && isNaN( value ) ) {
- return;
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
}
- // If a number was passed in, add 'px' to the (except for certain CSS properties)
- if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
- value += "px";
- }
+ // Force options to be an object
+ options = options || {};
- // If a hook was provided, use that value, otherwise just set the specified value
- if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
- // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
- // Fixes bug #5509
- try {
- style[ name ] = value;
- } catch(e) {}
- }
+ var // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events
+ // It's the callbackContext if one was provided in the options
+ // and if it's a DOM node or a jQuery collection
+ globalEventContext = callbackContext !== s &&
+ ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+ jQuery( callbackContext ) : jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // ifModified key
+ ifModifiedKey,
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+ // transport
+ transport,
+ // timeout handle
+ timeoutTimer,
+ // Cross-domain detection vars
+ parts,
+ // The jqXHR state
+ state = 0,
+ // To know if global events are to be dispatched
+ fireGlobals,
+ // Loop variable
+ i,
+ // Fake xhr
+ jqXHR = {
- } else {
- // If a hook was provided get the non-computed value from there
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
- return ret;
- }
+ readyState: 0,
- // Otherwise just get the value from the style object
- return style[ name ];
- }
- },
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( !state ) {
+ var lname = name.toLowerCase();
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match === undefined ? null : match;
+ },
- css: function( elem, name, numeric, extra ) {
- var val, num, hooks,
- origName = jQuery.camelCase( name );
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ statusText = statusText || "abort";
+ if ( transport ) {
+ transport.abort( statusText );
+ }
+ done( 0, statusText );
+ return this;
+ }
+ };
- // Make sure that we're working with the right name
- name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+ // Callback for when everything is done
+ // It is defined here because jslint complains if it is declared
+ // at the end of the function (which would be more logical and readable)
+ function done( status, nativeStatusText, responses, headers ) {
- // gets hook for the prefixed version
- // followed by the unprefixed version
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
- // If a hook was provided get the computed value from there
- if ( hooks && "get" in hooks ) {
- val = hooks.get( elem, true, extra );
- }
+ // State is "done" now
+ state = 2;
- // Otherwise, if a way to get the computed value exists, use that
- if ( val === undefined ) {
- val = curCSS( elem, name );
- }
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
- //convert "normal" to computed value
- if ( val === "normal" && name in cssNormalTransform ) {
- val = cssNormalTransform[ name ];
- }
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
- // Return, converting to number if forced or a qualifier was provided and val looks numeric
- if ( numeric || extra !== undefined ) {
- num = parseFloat( val );
- return numeric || jQuery.isNumeric( num ) ? num || 0 : val;
- }
- return val;
- },
-
- // A method for quickly swapping in/out CSS properties to get correct calculations
- swap: function( elem, options, callback ) {
- var ret, name,
- old = {};
-
- // Remember the old values, and insert the new ones
- for ( name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
+ // Cache response headers
+ responseHeadersString = headers || "";
- ret = callback.call( elem );
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
- // Revert the old values
- for ( name in options ) {
- elem.style[ name ] = old[ name ];
- }
+ var isSuccess,
+ success,
+ error,
+ statusText = nativeStatusText,
+ response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
+ lastModified,
+ etag;
- return ret;
- }
-});
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
-// NOTE: To any future maintainer, we've used both window.getComputedStyle
-// and getComputedStyle here to produce a better gzip size
-if ( window.getComputedStyle ) {
- curCSS = function( elem, name ) {
- var ret, width, minWidth, maxWidth,
- computed = getComputedStyle( elem, null ),
- style = elem.style;
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
- if ( computed ) {
+ if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
+ jQuery.lastModified[ ifModifiedKey ] = lastModified;
+ }
+ if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
+ jQuery.etag[ ifModifiedKey ] = etag;
+ }
+ }
- ret = computed[ name ];
- if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
- ret = jQuery.style( elem, name );
- }
+ // If not modified
+ if ( status === 304 ) {
- // A tribute to the "awesome hack by Dean Edwards"
- // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
- // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
- // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
- if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
- width = style.width;
- minWidth = style.minWidth;
- maxWidth = style.maxWidth;
+ statusText = "notmodified";
+ isSuccess = true;
- style.minWidth = style.maxWidth = style.width = ret;
- ret = computed.width;
+ // If we have data
+ } else {
- style.width = width;
- style.minWidth = minWidth;
- style.maxWidth = maxWidth;
- }
- }
+ try {
+ success = ajaxConvert( s, response );
+ statusText = "success";
+ isSuccess = true;
+ } catch(e) {
+ // We have a parsererror
+ statusText = "parsererror";
+ error = e;
+ }
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( !statusText || status ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
- return ret;
- };
-} else if ( document.documentElement.currentStyle ) {
- curCSS = function( elem, name ) {
- var left, rsLeft,
- ret = elem.currentStyle && elem.currentStyle[ name ],
- style = elem.style;
-
- // Avoid setting ret to empty string here
- // so we don't default to auto
- if ( ret == null && style && style[ name ] ) {
- ret = style[ name ];
- }
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = "" + ( nativeStatusText || statusText );
- // From the awesome hack by Dean Edwards
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
- // If we're not dealing with a regular pixel number
- // but a number that has a weird ending, we need to convert it to pixels
- // but not position css attributes, as those are proportional to the parent element instead
- // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
- if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
- // Remember the original values
- left = style.left;
- rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
- // Put in the new values to get a computed value out
- if ( rsLeft ) {
- elem.runtimeStyle.left = elem.currentStyle.left;
- }
- style.left = name === "fontSize" ? "1em" : ret;
- ret = style.pixelLeft + "px";
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
- // Revert the changed values
- style.left = left;
- if ( rsLeft ) {
- elem.runtimeStyle.left = rsLeft;
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
}
- }
- return ret === "" ? "auto" : ret;
- };
-}
-
-function setPositiveNumber( elem, value, subtract ) {
- var matches = rnumsplit.exec( value );
- return matches ?
- Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
- value;
-}
-
-function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
- var i = extra === ( isBorderBox ? "border" : "content" ) ?
- // If we already have the right measurement, avoid augmentation
- 4 :
- // Otherwise initialize for horizontal or vertical properties
- name === "width" ? 1 : 0,
-
- val = 0;
-
- for ( ; i < 4; i += 2 ) {
- // both box models exclude margin, so add it if we want it
- if ( extra === "margin" ) {
- // we use jQuery.css instead of curCSS here
- // because of the reliableMarginRight CSS hook!
- val += jQuery.css( elem, extra + cssExpand[ i ], true );
- }
+ // Attach deferreds
+ deferred.promise( jqXHR );
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+ jqXHR.complete = completeDeferred.add;
- // From this point on we use curCSS for maximum performance (relevant in animations)
- if ( isBorderBox ) {
- // border-box includes padding, so remove it if we want content
- if ( extra === "content" ) {
- val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
- }
+ // Status-dependent callbacks
+ jqXHR.statusCode = function( map ) {
+ if ( map ) {
+ var tmp;
+ if ( state < 2 ) {
+ for ( tmp in map ) {
+ statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+ }
+ } else {
+ tmp = map[ jqXHR.status ];
+ jqXHR.then( tmp, tmp );
+ }
+ }
+ return this;
+ };
- // at this point, extra isn't border nor margin, so remove border
- if ( extra !== "margin" ) {
- val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+
+ // Determine if a cross-domain request is in order
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
}
- } else {
- // at this point, extra isn't content, so add padding
- val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
- // at this point, extra isn't content nor padding, so add border
- if ( extra !== "padding" ) {
- val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
}
- }
- }
- return val;
-}
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
-function getWidthOrHeight( elem, name, extra ) {
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return false;
+ }
- // Start with offset property, which is equivalent to the border-box value
- var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
- valueIsBorderBox = true,
- isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
- if ( val <= 0 ) {
- // Fall back to computed then uncomputed css if necessary
- val = curCSS( elem, name );
- if ( val < 0 || val == null ) {
- val = elem.style[ name ];
- }
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
- // Computed unit is not pixels. Stop here and return.
- if ( rnumnonpx.test(val) ) {
- return val;
- }
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
- // we need the check for style in case a browser which returns unreliable values
- // for getComputedStyle silently falls back to the reliable elem.style
- valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
- // Normalize "", auto, and prepare for extra
- val = parseFloat( val ) || 0;
- }
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
- // use the active box-sizing model to add/subtract irrelevant styles
- return ( val +
- augmentWidthOrHeight(
- elem,
- name,
- extra || ( isBorderBox ? "border" : "content" ),
- valueIsBorderBox
- )
- ) + "px";
-}
-
-
-// Try to determine the default display value of an element
-function css_defaultDisplay( nodeName ) {
- if ( elemdisplay[ nodeName ] ) {
- return elemdisplay[ nodeName ];
- }
+ // If data is available, append data to url
+ if ( s.data ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
- var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
- display = elem.css("display");
- elem.remove();
-
- // If the simple way fails,
- // get element's real default display by attaching it to a temp iframe
- if ( display === "none" || display === "" ) {
- // Use the already-created iframe if possible
- iframe = document.body.appendChild(
- iframe || jQuery.extend( document.createElement("iframe"), {
- frameBorder: 0,
- width: 0,
- height: 0
- })
- );
-
- // Create a cacheable copy of the iframe document on first call.
- // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
- // document to it; WebKit & Firefox won't allow reusing the iframe document.
- if ( !iframeDoc || !iframe.createElement ) {
- iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
- iframeDoc.write("<!doctype html><html><body>");
- iframeDoc.close();
- }
+ // Get ifModifiedKey before adding the anti-cache parameter
+ ifModifiedKey = s.url;
- elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
- display = curCSS( elem, "display" );
- document.body.removeChild( iframe );
- }
+ var ts = jQuery.now(),
+ // try replacing _= if it is there
+ ret = s.url.replace( rts, "$1_=" + ts );
- // Store the correct default display
- elemdisplay[ nodeName ] = display;
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+ }
+ }
- return display;
-}
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
-jQuery.each([ "height", "width" ], function( i, name ) {
- jQuery.cssHooks[ name ] = {
- get: function( elem, computed, extra ) {
- if ( computed ) {
- if ( elem.offsetWidth !== 0 || curCSS( elem, "display" ) !== "none" ) {
- return getWidthOrHeight( elem, name, extra );
- } else {
- return jQuery.swap( elem, cssShow, function() {
- return getWidthOrHeight( elem, name, extra );
- });
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ ifModifiedKey = ifModifiedKey || s.url;
+ if ( jQuery.lastModified[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+ }
+ if ( jQuery.etag[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
}
}
- },
- set: function( elem, value, extra ) {
- return setPositiveNumber( elem, value, extra ?
- augmentWidthOrHeight(
- elem,
- name,
- extra,
- jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
- ) : 0
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
);
- }
- };
-});
-
-if ( !jQuery.support.opacity ) {
- jQuery.cssHooks.opacity = {
- get: function( elem, computed ) {
- // IE uses filters for opacity
- return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
- ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
- computed ? "1" : "";
- },
-
- set: function( elem, value ) {
- var style = elem.style,
- currentStyle = elem.currentStyle,
- opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
- filter = currentStyle && currentStyle.filter || style.filter || "";
- // IE has trouble with opacity if it does not have layout
- // Force it by setting the zoom level
- style.zoom = 1;
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
- // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
- if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
- style.removeAttribute ) {
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already
+ jqXHR.abort();
+ return false;
- // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
- // if "filter:" is present at all, clearType is disabled, we want to avoid this
- // style.removeAttribute is IE Only, but so apparently is this code path...
- style.removeAttribute( "filter" );
+ }
- // if there there is no filter style applied in a css rule, we are done
- if ( currentStyle && !currentStyle.filter ) {
- return;
- }
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
}
- // otherwise, set new filter values
- style.filter = ralpha.test( filter ) ?
- filter.replace( ralpha, opacity ) :
- filter + " " + opacity;
- }
- };
-}
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
-// These hooks cannot be added until DOM ready because the support test
-// for it is not run until after DOM ready
-jQuery(function() {
- if ( !jQuery.support.reliableMarginRight ) {
- jQuery.cssHooks.marginRight = {
- get: function( elem, computed ) {
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
- // Work around by temporarily setting element display to inline-block
- return jQuery.swap( elem, { "display": "inline-block" }, function() {
- if ( computed ) {
- return curCSS( elem, "marginRight" );
- }
- });
- }
- };
- }
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout( function(){
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
- // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
- // getComputedStyle returns percent when specified for top/left/bottom/right
- // rather than make the css module depend on the offset module, we just check for it here
- if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
- jQuery.each( [ "top", "left" ], function( i, prop ) {
- jQuery.cssHooks[ prop ] = {
- get: function( elem, computed ) {
- if ( computed ) {
- var ret = curCSS( elem, prop );
- // if curCSS returns percentage, fallback to offset
- return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret;
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch (e) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
}
}
- };
- });
- }
-
-});
-
-if ( jQuery.expr && jQuery.expr.filters ) {
- jQuery.expr.filters.hidden = function( elem ) {
- return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none");
- };
-
- jQuery.expr.filters.visible = function( elem ) {
- return !jQuery.expr.filters.hidden( elem );
- };
-}
+ }
-// These hooks are used by animate to expand properties
-jQuery.each({
- margin: "",
- padding: "",
- border: "Width"
-}, function( prefix, suffix ) {
- jQuery.cssHooks[ prefix + suffix ] = {
- expand: function( value ) {
- var i,
+ return jqXHR;
+ },
- // assumes a single number if not a string
- parts = typeof value === "string" ? value.split(" ") : [ value ],
- expanded = {};
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a, traditional ) {
+ var s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : value;
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
- for ( i = 0; i < 4; i++ ) {
- expanded[ prefix + cssExpand[ i ] + suffix ] =
- parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
}
- return expanded;
- }
- };
-
- if ( !rmargin.test( prefix ) ) {
- jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
- }
-});
-var r20 = /%20/g,
- rbracket = /\[\]$/,
- rCRLF = /\r?\n/g,
- rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
- rselectTextarea = /^(?:select|textarea)/i;
-
-jQuery.fn.extend({
- serialize: function() {
- return jQuery.param( this.serializeArray() );
- },
- serializeArray: function() {
- return this.map(function(){
- return this.elements ? jQuery.makeArray( this.elements ) : this;
- })
- .filter(function(){
- return this.name && !this.disabled &&
- ( this.checked || rselectTextarea.test( this.nodeName ) ||
- rinput.test( this.type ) );
- })
- .map(function( i, elem ){
- var val = jQuery( this ).val();
-
- return val == null ?
- null :
- jQuery.isArray( val ) ?
- jQuery.map( val, function( val, i ){
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- }) :
- { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- }).get();
- }
-});
-
-//Serialize an array of form elements or a set of
-//key/values into a query string
-jQuery.param = function( a, traditional ) {
- var prefix,
- s = [],
- add = function( key, value ) {
- // If value is a function, invoke it and return its value
- value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
- s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
- };
-
- // Set traditional to true for jQuery <= 1.3.2 behavior.
- if ( traditional === undefined ) {
- traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
- }
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
- // If an array was passed in, assume that it is an array of form elements.
- if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
- // Serialize the form elements
- jQuery.each( a, function() {
- add( this.name, this.value );
- });
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
- } else {
- // If traditional, encode the "old" way (the way 1.3.2 or older
- // did it), otherwise encode params recursively.
- for ( prefix in a ) {
- buildParams( prefix, a[ prefix ], traditional, add );
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
}
- }
-
- // Return the resulting serialization
- return s.join( "&" ).replace( r20, "+" );
-};
+ });
-function buildParams( prefix, obj, traditional, add ) {
- var name;
+ function buildParams( prefix, obj, traditional, add ) {
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
- if ( jQuery.isArray( obj ) ) {
- // Serialize array item.
- jQuery.each( obj, function( i, v ) {
- if ( traditional || rbracket.test( prefix ) ) {
- // Treat each array item as a scalar.
- add( prefix, v );
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
- } else {
- // If array item is non-scalar (array or object), encode its
- // numeric index to resolve deserialization ambiguity issues.
- // Note that rack (as of 1.0.0) can't currently deserialize
- // nested arrays properly, and attempting to do so may cause
- // a server error. Possible fixes are to modify rack's
- // deserialization algorithm or to provide an option or flag
- // to force array serialization to be shallow.
- buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( var name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
}
- });
- } else if ( !traditional && jQuery.type( obj ) === "object" ) {
- // Serialize object item.
- for ( name in obj ) {
- buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
}
-
- } else {
- // Serialize scalar item.
- add( prefix, obj );
}
-}
-var // Document location
- ajaxLocation,
- // Document location segments
- ajaxLocParts,
-
- rhash = /#.*$/,
- rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
- // #7653, #8125, #8152: local protocol detection
- rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
- rnoContent = /^(?:GET|HEAD)$/,
- rprotocol = /^\/\//,
- rquery = /\?/,
- rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
- rts = /([?&])_=[^&]*/,
- rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
-
- // Keep a copy of the old load method
- _load = jQuery.fn.load,
-
- /* Prefilters
- * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
- * 2) These are called:
- * - BEFORE asking for a transport
- * - AFTER param serialization (s.data is a string if s.processData is true)
- * 3) key is the dataType
- * 4) the catchall symbol "*" can be used
- * 5) execution will start with transport dataType and THEN continue down to "*" if needed
- */
- prefilters = {},
- /* Transports bindings
- * 1) key is the dataType
- * 2) the catchall symbol "*" can be used
- * 3) selection will start with transport dataType and THEN go to "*" if needed
- */
- transports = {},
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+ jQuery.extend({
- // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
- allTypes = ["*/"] + ["*"];
+ // Counter for holding the number of active queries
+ active: 0,
-// #8138, IE may throw an exception when accessing
-// a field from window.location if document.domain has been set
-try {
- ajaxLocation = location.href;
-} catch( e ) {
- // Use the href attribute of an A element
- // since IE will modify it given document.location
- ajaxLocation = document.createElement( "a" );
- ajaxLocation.href = "";
- ajaxLocation = ajaxLocation.href;
-}
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {}
-// Segment location into parts
-ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+ });
-// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
-function addToPrefiltersOrTransports( structure ) {
+ /* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+ function ajaxHandleResponses( s, jqXHR, responses ) {
- // dataTypeExpression is optional and defaults to "*"
- return function( dataTypeExpression, func ) {
+ var contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields,
+ ct,
+ type,
+ finalDataType,
+ firstDataType;
- if ( typeof dataTypeExpression !== "string" ) {
- func = dataTypeExpression;
- dataTypeExpression = "*";
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
}
- var dataType, list, placeBefore,
- dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),
- i = 0,
- length = dataTypes.length;
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+ }
+ }
- if ( jQuery.isFunction( func ) ) {
- // For each dataType in the dataTypeExpression
- for ( ; i < length; i++ ) {
- dataType = dataTypes[ i ];
- // We control if we're asked to add before
- // any existing element
- placeBefore = /^\+/.test( dataType );
- if ( placeBefore ) {
- dataType = dataType.substr( 1 ) || "*";
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
}
- list = structure[ dataType ] = structure[ dataType ] || [];
- // then we add to the structure accordingly
- list[ placeBefore ? "unshift" : "push" ]( func );
}
}
- };
-}
-// Base inspection function for prefilters and transports
-function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
- dataType /* internal */, inspected /* internal */ ) {
-
- dataType = dataType || options.dataTypes[ 0 ];
- inspected = inspected || {};
-
- inspected[ dataType ] = true;
-
- var selection,
- list = structure[ dataType ],
- i = 0,
- length = list ? list.length : 0,
- executeOnly = ( structure === prefilters );
-
- for ( ; i < length && ( executeOnly || !selection ); i++ ) {
- selection = list[ i ]( options, originalOptions, jqXHR );
- // If we got redirected to another dataType
- // we try there if executing only and not done already
- if ( typeof selection === "string" ) {
- if ( !executeOnly || inspected[ selection ] ) {
- selection = undefined;
- } else {
- options.dataTypes.unshift( selection );
- selection = inspectPrefiltersOrTransports(
- structure, options, originalOptions, jqXHR, selection, inspected );
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
}
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
}
- }
- // If we're only executing or nothing was selected
- // we try the catchall dataType if not done already
- if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
- selection = inspectPrefiltersOrTransports(
- structure, options, originalOptions, jqXHR, "*", inspected );
- }
- // unnecessary when only executing (prefilters)
- // but it'll be ignored by the caller in that case
- return selection;
-}
-// A special extend for ajax options
-// that takes "flat" options (not to be deep extended)
-// Fixes #9887
-function ajaxExtend( target, src ) {
- var key, deep,
- flatOptions = jQuery.ajaxSettings.flatOptions || {};
- for ( key in src ) {
- if ( src[ key ] !== undefined ) {
- ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
}
}
- if ( deep ) {
- jQuery.extend( true, target, deep );
- }
-}
-
-jQuery.fn.load = function( url, params, callback ) {
- if ( typeof url !== "string" && _load ) {
- return _load.apply( this, arguments );
- }
-
- // Don't do a request if no elements are being requested
- if ( !this.length ) {
- return this;
- }
- var selector, type, response,
- self = this,
- off = url.indexOf(" ");
+// Chain conversions given the request and the original response
+ function ajaxConvert( s, response ) {
- if ( off >= 0 ) {
- selector = url.slice( off, url.length );
- url = url.slice( 0, off );
- }
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
- // If it's a function
- if ( jQuery.isFunction( params ) ) {
+ var dataTypes = s.dataTypes,
+ converters = {},
+ i,
+ key,
+ length = dataTypes.length,
+ tmp,
+ // Current and previous dataTypes
+ current = dataTypes[ 0 ],
+ prev,
+ // Conversion expression
+ conversion,
+ // Conversion function
+ conv,
+ // Conversion functions (transitive conversion)
+ conv1,
+ conv2;
+
+ // For each dataType in the chain
+ for ( i = 1; i < length; i++ ) {
+
+ // Create converters map
+ // with lowercased keys
+ if ( i === 1 ) {
+ for ( key in s.converters ) {
+ if ( typeof key === "string" ) {
+ converters[ key.toLowerCase() ] = s.converters[ key ];
+ }
+ }
+ }
- // We assume that it's the callback
- callback = params;
- params = undefined;
+ // Get the dataTypes
+ prev = current;
+ current = dataTypes[ i ];
- // Otherwise, build a param string
- } else if ( typeof params === "object" ) {
- type = "POST";
- }
+ // If current is auto dataType, update it to prev
+ if ( current === "*" ) {
+ current = prev;
+ // If no auto and dataTypes are actually different
+ } else if ( prev !== "*" && prev !== current ) {
- // Request the remote document
- jQuery.ajax({
- url: url,
+ // Get the converter
+ conversion = prev + " " + current;
+ conv = converters[ conversion ] || converters[ "* " + current ];
- // if "type" variable is undefined, then "GET" method will be used
- type: type,
- dataType: "html",
- data: params,
- complete: function( jqXHR, status ) {
- if ( callback ) {
- self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ // If there is no direct converter, search transitively
+ if ( !conv ) {
+ conv2 = undefined;
+ for ( conv1 in converters ) {
+ tmp = conv1.split( " " );
+ if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
+ conv2 = converters[ tmp[1] + " " + current ];
+ if ( conv2 ) {
+ conv1 = converters[ conv1 ];
+ if ( conv1 === true ) {
+ conv = conv2;
+ } else if ( conv2 === true ) {
+ conv = conv1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ // If we found no converter, dispatch an error
+ if ( !( conv || conv2 ) ) {
+ jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+ }
+ // If found converter is not an equivalence
+ if ( conv !== true ) {
+ // Convert with 1 or 2 converters accordingly
+ response = conv ? conv( response ) : conv2( conv1(response) );
+ }
}
}
- }).done(function( responseText ) {
-
- // Save response for use in complete callback
- response = arguments;
-
- // See if a selector was specified
- self.html( selector ?
+ return response;
+ }
- // Create a dummy div to hold the results
- jQuery("<div>")
- // inject the contents of the document in, removing the scripts
- // to avoid any 'Permission Denied' errors in IE
- .append( responseText.replace( rscript, "" ) )
- // Locate the specified elements
- .find( selector ) :
- // If not, just inject the full result
- responseText );
+ var jsc = jQuery.now(),
+ jsre = /(\=)\?(&|$)|\?\?/i;
+// Default jsonp settings
+ jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ return jQuery.expando + "_" + ( jsc++ );
+ }
});
- return this;
-};
+// Detect, normalize options and install callbacks for jsonp requests
+ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var inspectData = ( typeof s.data === "string" ) && /^application\/x\-www\-form\-urlencoded/.test( s.contentType );
+
+ if ( s.dataTypes[ 0 ] === "jsonp" ||
+ s.jsonp !== false && ( jsre.test( s.url ) ||
+ inspectData && jsre.test( s.data ) ) ) {
+
+ var responseContainer,
+ jsonpCallback = s.jsonpCallback =
+ jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+ previous = window[ jsonpCallback ],
+ url = s.url,
+ data = s.data,
+ replace = "$1" + jsonpCallback + "$2";
+
+ if ( s.jsonp !== false ) {
+ url = url.replace( jsre, replace );
+ if ( s.url === url ) {
+ if ( inspectData ) {
+ data = data.replace( jsre, replace );
+ }
+ if ( s.data === data ) {
+ // Add callback manually
+ url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+ }
+ }
+ }
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
- jQuery.fn[ o ] = function( f ){
- return this.on( o, f );
- };
-});
-
-jQuery.each( [ "get", "post" ], function( i, method ) {
- jQuery[ method ] = function( url, data, callback, type ) {
- // shift arguments if data argument was omitted
- if ( jQuery.isFunction( data ) ) {
- type = type || callback;
- callback = data;
- data = undefined;
- }
+ s.url = url;
+ s.data = data;
- return jQuery.ajax({
- type: method,
- url: url,
- data: data,
- success: callback,
- dataType: type
- });
- };
-});
+ // Install callback
+ window[ jsonpCallback ] = function( response ) {
+ responseContainer = [ response ];
+ };
-jQuery.extend({
+ // Clean-up function
+ jqXHR.always(function() {
+ // Set callback back to previous value
+ window[ jsonpCallback ] = previous;
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( previous ) ) {
+ window[ jsonpCallback ]( responseContainer[ 0 ] );
+ }
+ });
- getScript: function( url, callback ) {
- return jQuery.get( url, undefined, callback, "script" );
- },
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( jsonpCallback + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
- getJSON: function( url, data, callback ) {
- return jQuery.get( url, data, callback, "json" );
- },
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
- // Creates a full fledged settings object into target
- // with both ajaxSettings and settings fields.
- // If target is omitted, writes into ajaxSettings.
- ajaxSetup: function( target, settings ) {
- if ( settings ) {
- // Building a settings object
- ajaxExtend( target, jQuery.ajaxSettings );
- } else {
- // Extending ajaxSettings
- settings = target;
- target = jQuery.ajaxSettings;
+ // Delegate to script
+ return "script";
}
- ajaxExtend( target, settings );
- return target;
- },
-
- ajaxSettings: {
- url: ajaxLocation,
- isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
- global: true,
- type: "GET",
- contentType: "application/x-www-form-urlencoded; charset=UTF-8",
- processData: true,
- async: true,
- /*
- timeout: 0,
- data: null,
- dataType: null,
- username: null,
- password: null,
- cache: null,
- throws: false,
- traditional: false,
- headers: {},
- */
+ });
+
+
+
+// Install script dataType
+ jQuery.ajaxSetup({
accepts: {
- xml: "application/xml, text/xml",
- html: "text/html",
- text: "text/plain",
- json: "application/json, text/javascript",
- "*": allTypes
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
},
-
contents: {
- xml: /xml/,
- html: /html/,
- json: /json/
- },
-
- responseFields: {
- xml: "responseXML",
- text: "responseText"
+ script: /javascript|ecmascript/
},
-
- // List of data converters
- // 1) key format is "source_type destination_type" (a single space in-between)
- // 2) the catchall symbol "*" can be used for source_type
converters: {
-
- // Convert anything to text
- "* text": window.String,
-
- // Text to html (true = no transformation)
- "text html": true,
-
- // Evaluate text as a json expression
- "text json": jQuery.parseJSON,
-
- // Parse text as xml
- "text xml": jQuery.parseXML
- },
-
- // For options that shouldn't be deep extended:
- // you can add your own custom options here if
- // and when you create one that shouldn't be
- // deep extended (see ajaxExtend)
- flatOptions: {
- context: true,
- url: true
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
}
- },
-
- ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
- ajaxTransport: addToPrefiltersOrTransports( transports ),
-
- // Main method
- ajax: function( url, options ) {
+ });
- // If url is an object, simulate pre-1.5 signature
- if ( typeof url === "object" ) {
- options = url;
- url = undefined;
+// Handle cache's special case and global
+ jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
}
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+ });
- // Force options to be an object
- options = options || {};
-
- var // ifModified key
- ifModifiedKey,
- // Response headers
- responseHeadersString,
- responseHeaders,
- // transport
- transport,
- // timeout handle
- timeoutTimer,
- // Cross-domain detection vars
- parts,
- // To know if global events are to be dispatched
- fireGlobals,
- // Loop variable
- i,
- // Create the final options object
- s = jQuery.ajaxSetup( {}, options ),
- // Callbacks context
- callbackContext = s.context || s,
- // Context for global events
- // It's the callbackContext if one was provided in the options
- // and if it's a DOM node or a jQuery collection
- globalEventContext = callbackContext !== s &&
- ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
- jQuery( callbackContext ) : jQuery.event,
- // Deferreds
- deferred = jQuery.Deferred(),
- completeDeferred = jQuery.Callbacks( "once memory" ),
- // Status-dependent callbacks
- statusCode = s.statusCode || {},
- // Headers (they are sent all at once)
- requestHeaders = {},
- requestHeadersNames = {},
- // The jqXHR state
- state = 0,
- // Default abort message
- strAbort = "canceled",
- // Fake xhr
- jqXHR = {
-
- readyState: 0,
-
- // Caches the header
- setRequestHeader: function( name, value ) {
- if ( !state ) {
- var lname = name.toLowerCase();
- name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
- requestHeaders[ name ] = value;
- }
- return this;
- },
-
- // Raw string
- getAllResponseHeaders: function() {
- return state === 2 ? responseHeadersString : null;
- },
+// Bind script tag hack transport
+ jQuery.ajaxTransport( "script", function(s) {
- // Builds headers hashtable if needed
- getResponseHeader: function( key ) {
- var match;
- if ( state === 2 ) {
- if ( !responseHeaders ) {
- responseHeaders = {};
- while( ( match = rheaders.exec( responseHeadersString ) ) ) {
- responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
- }
- }
- match = responseHeaders[ key.toLowerCase() ];
- }
- return match === undefined ? null : match;
- },
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
- // Overrides response content-type header
- overrideMimeType: function( type ) {
- if ( !state ) {
- s.mimeType = type;
- }
- return this;
- },
+ var script,
+ head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
- // Cancel the request
- abort: function( statusText ) {
- statusText = statusText || strAbort;
- if ( transport ) {
- transport.abort( statusText );
- }
- done( 0, statusText );
- return this;
- }
- };
+ return {
- // Callback for when everything is done
- // It is defined here because jslint complains if it is declared
- // at the end of the function (which would be more logical and readable)
- function done( status, nativeStatusText, responses, headers ) {
- var isSuccess, success, error, response, modified,
- statusText = nativeStatusText;
+ send: function( _, callback ) {
- // Called once
- if ( state === 2 ) {
- return;
- }
+ script = document.createElement( "script" );
- // State is "done" now
- state = 2;
+ script.async = "async";
- // Clear timeout if it exists
- if ( timeoutTimer ) {
- clearTimeout( timeoutTimer );
- }
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
- // Dereference transport for early garbage collection
- // (no matter how long the jqXHR object will be used)
- transport = undefined;
+ script.src = s.url;
- // Cache response headers
- responseHeadersString = headers || "";
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
- // Set readyState
- jqXHR.readyState = status > 0 ? 4 : 0;
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
- // Get response data
- if ( responses ) {
- response = ajaxHandleResponses( s, jqXHR, responses );
- }
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
- // If successful, handle type chaining
- if ( status >= 200 && status < 300 || status === 304 ) {
+ // Remove the script
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
- if ( s.ifModified ) {
+ // Dereference the script
+ script = undefined;
- modified = jqXHR.getResponseHeader("Last-Modified");
- if ( modified ) {
- jQuery.lastModified[ ifModifiedKey ] = modified;
- }
- modified = jqXHR.getResponseHeader("Etag");
- if ( modified ) {
- jQuery.etag[ ifModifiedKey ] = modified;
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( 0, 1 );
}
}
+ };
+ }
+ });
- // If not modified
- if ( status === 304 ) {
- statusText = "notmodified";
- isSuccess = true;
- // If we have data
- } else {
- isSuccess = ajaxConvert( s, response );
- statusText = isSuccess.state;
- success = isSuccess.data;
- error = isSuccess.error;
- isSuccess = !error;
- }
- } else {
- // We extract error from statusText
- // then normalize statusText and status for non-aborts
- error = statusText;
- if ( !statusText || status ) {
- statusText = "error";
- if ( status < 0 ) {
- status = 0;
- }
- }
+ var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject ? function() {
+ // Abort all pending requests
+ for ( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( 0, 1 );
}
+ } : false,
+ xhrId = 0,
+ xhrCallbacks;
- // Set data for the fake xhr object
- jqXHR.status = status;
- jqXHR.statusText = "" + ( nativeStatusText || statusText );
+// Functions to create xhrs
+ function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+ }
- // Success/Error
- if ( isSuccess ) {
- deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
- } else {
- deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
- }
+ function createActiveXHR() {
+ try {
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+ } catch( e ) {}
+ }
- // Status-dependent callbacks
- jqXHR.statusCode( statusCode );
- statusCode = undefined;
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+ jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
- if ( fireGlobals ) {
- globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
- [ jqXHR, s, isSuccess ? success : error ] );
- }
+// Determine support properties
+ (function( xhr ) {
+ jQuery.extend( jQuery.support, {
+ ajax: !!xhr,
+ cors: !!xhr && ( "withCredentials" in xhr )
+ });
+ })( jQuery.ajaxSettings.xhr() );
- // Complete
- completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+// Create transport if the browser can provide an xhr
+ if ( jQuery.support.ajax ) {
- if ( fireGlobals ) {
- globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
- // Handle the global AJAX counter
- if ( !( --jQuery.active ) ) {
- jQuery.event.trigger( "ajaxStop" );
- }
- }
- }
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
- // Attach deferreds
- deferred.promise( jqXHR );
- jqXHR.success = jqXHR.done;
- jqXHR.error = jqXHR.fail;
- jqXHR.complete = completeDeferred.add;
+ var callback;
- // Status-dependent callbacks
- jqXHR.statusCode = function( map ) {
- if ( map ) {
- var tmp;
- if ( state < 2 ) {
- for ( tmp in map ) {
- statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
- }
- } else {
- tmp = map[ jqXHR.status ];
- jqXHR.always( tmp );
- }
- }
- return this;
- };
+ return {
+ send: function( headers, complete ) {
- // Remove hash character (#7531: and string promotion)
- // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
- // We also use the url parameter if available
- s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
-
- // Extract dataTypes list
- s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
-
- // Determine if a cross-domain request is in order
- if ( s.crossDomain == null ) {
- parts = rurl.exec( s.url.toLowerCase() );
- s.crossDomain = !!( parts &&
- ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
- ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
- ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
- );
- }
+ // Get a new xhr
+ var xhr = s.xhr(),
+ handle,
+ i;
- // Convert data if not already a string
- if ( s.data && s.processData && typeof s.data !== "string" ) {
- s.data = jQuery.param( s.data, s.traditional );
- }
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
- // Apply prefilters
- inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
- // If request was aborted inside a prefilter, stop there
- if ( state === 2 ) {
- return jqXHR;
- }
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
- // We can fire global events as of now if asked to
- fireGlobals = s.global;
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
- // Uppercase the type
- s.type = s.type.toUpperCase();
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( _ ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+
+ var status,
+ statusText,
+ responseHeaders,
+ responses,
+ xml;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occured
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
- // Determine if request has content
- s.hasContent = !rnoContent.test( s.type );
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+ responses = {};
+ xml = xhr.responseXML;
+
+ // Construct response list
+ if ( xml && xml.documentElement /* #4958 */ ) {
+ responses.xml = xml;
+ }
+
+ // When requesting binary data, IE6-9 will throw an exception
+ // on any attempt to access responseText (#11426)
+ try {
+ responses.text = xhr.responseText;
+ } catch( _ ) {
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
- // Watch for a new set of requests
- if ( fireGlobals && jQuery.active++ === 0 ) {
- jQuery.event.trigger( "ajaxStart" );
- }
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
- // More options handling for requests with no content
- if ( !s.hasContent ) {
+ // if we're in sync mode or it's in cache
+ // and has been retrieved directly (IE6 & IE7)
+ // we need to manually fire the callback
+ if ( !s.async || xhr.readyState === 4 ) {
+ callback();
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
- // If data is available, append data to url
- if ( s.data ) {
- s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
- // #9682: remove data so that it's not used in an eventual retry
- delete s.data;
+ abort: function() {
+ if ( callback ) {
+ callback(0,1);
+ }
+ }
+ };
}
+ });
+ }
- // Get ifModifiedKey before adding the anti-cache parameter
- ifModifiedKey = s.url;
-
- // Add anti-cache in url if needed
- if ( s.cache === false ) {
- var ts = jQuery.now(),
- // try replacing _= if it is there
- ret = s.url.replace( rts, "$1_=" + ts );
- // if nothing was replaced, add timestamp to the end
- s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
- }
- }
- // Set the correct header, if data is being sent
- if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
- jqXHR.setRequestHeader( "Content-Type", s.contentType );
- }
+ var elemdisplay = {},
+ iframe, iframeDoc,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ],
+ fxNow;
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
- if ( s.ifModified ) {
- ifModifiedKey = ifModifiedKey || s.url;
- if ( jQuery.lastModified[ ifModifiedKey ] ) {
- jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
- }
- if ( jQuery.etag[ ifModifiedKey ] ) {
- jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
- }
- }
+ jQuery.fn.extend({
+ show: function( speed, easing, callback ) {
+ var elem, display;
- // Set the Accepts header for the server, depending on the dataType
- jqXHR.setRequestHeader(
- "Accept",
- s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
- s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
- s.accepts[ "*" ]
- );
-
- // Check for headers option
- for ( i in s.headers ) {
- jqXHR.setRequestHeader( i, s.headers[ i ] );
- }
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("show", 3), speed, easing, callback );
- // Allow custom headers/mimetypes and early abort
- if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
- // Abort if not done already and return
- return jqXHR.abort();
+ } else {
+ for ( var i = 0, j = this.length; i < j; i++ ) {
+ elem = this[ i ];
- }
+ if ( elem.style ) {
+ display = elem.style.display;
- // aborting is no longer a cancellation
- strAbort = "abort";
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
+ display = elem.style.display = "";
+ }
- // Install callbacks on deferreds
- for ( i in { success: 1, error: 1, complete: 1 } ) {
- jqXHR[ i ]( s[ i ] );
- }
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( (display === "" && jQuery.css(elem, "display") === "none") ||
+ !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+ jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+ }
+ }
+ }
- // Get transport
- transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ elem = this[ i ];
- // If no transport, we auto-abort
- if ( !transport ) {
- done( -1, "No Transport" );
- } else {
- jqXHR.readyState = 1;
- // Send global event
- if ( fireGlobals ) {
- globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
- }
- // Timeout
- if ( s.async && s.timeout > 0 ) {
- timeoutTimer = setTimeout( function(){
- jqXHR.abort( "timeout" );
- }, s.timeout );
- }
+ if ( elem.style ) {
+ display = elem.style.display;
- try {
- state = 1;
- transport.send( requestHeaders, done );
- } catch (e) {
- // Propagate exception as error if not done
- if ( state < 2 ) {
- done( -1, e );
- // Simply rethrow otherwise
- } else {
- throw e;
+ if ( display === "" || display === "none" ) {
+ elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
+ }
+ }
}
+
+ return this;
}
- }
+ },
+
+ hide: function( speed, easing, callback ) {
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("hide", 3), speed, easing, callback);
- return jqXHR;
- },
+ } else {
+ var elem, display,
+ i = 0,
+ j = this.length;
- // Counter for holding the number of active queries
- active: 0,
+ for ( ; i < j; i++ ) {
+ elem = this[i];
+ if ( elem.style ) {
+ display = jQuery.css( elem, "display" );
- // Last-Modified header cache for next request
- lastModified: {},
- etag: {}
+ if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
+ jQuery._data( elem, "olddisplay", display );
+ }
+ }
+ }
-});
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ if ( this[i].style ) {
+ this[i].style.display = "none";
+ }
+ }
-/* Handles responses to an ajax request:
- * - sets all responseXXX fields accordingly
- * - finds the right dataType (mediates between content-type and expected dataType)
- * - returns the corresponding response
- */
-function ajaxHandleResponses( s, jqXHR, responses ) {
+ return this;
+ }
+ },
- var ct, type, finalDataType, firstDataType,
- contents = s.contents,
- dataTypes = s.dataTypes,
- responseFields = s.responseFields;
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
- // Fill responseXXX fields
- for ( type in responseFields ) {
- if ( type in responses ) {
- jqXHR[ responseFields[type] ] = responses[ type ];
- }
- }
+ toggle: function( fn, fn2, callback ) {
+ var bool = typeof fn === "boolean";
- // Remove auto dataType and get content-type in the process
- while( dataTypes[ 0 ] === "*" ) {
- dataTypes.shift();
- if ( ct === undefined ) {
- ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
- }
- }
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
- // Check if we're dealing with a known content-type
- if ( ct ) {
- for ( type in contents ) {
- if ( contents[ type ] && contents[ type ].test( ct ) ) {
- dataTypes.unshift( type );
- break;
- }
- }
- }
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
- // Check to see if we have a response for the expected dataType
- if ( dataTypes[ 0 ] in responses ) {
- finalDataType = dataTypes[ 0 ];
- } else {
- // Try convertible dataTypes
- for ( type in responses ) {
- if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
- finalDataType = type;
- break;
- }
- if ( !firstDataType ) {
- firstDataType = type;
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2, callback);
}
- }
- // Or just use first one
- finalDataType = finalDataType || firstDataType;
- }
- // If we found a dataType
- // We add the dataType to the list if needed
- // and return the corresponding response
- if ( finalDataType ) {
- if ( finalDataType !== dataTypes[ 0 ] ) {
- dataTypes.unshift( finalDataType );
- }
- return responses[ finalDataType ];
- }
-}
+ return this;
+ },
-// Chain conversions given the request and the original response
-function ajaxConvert( s, response ) {
-
- var conv, conv2, current, tmp,
- // Work with a copy of dataTypes in case we need to modify it for conversion
- dataTypes = s.dataTypes.slice(),
- prev = dataTypes[ 0 ],
- converters = {},
- i = 0;
-
- // Apply the dataFilter if provided
- if ( s.dataFilter ) {
- response = s.dataFilter( response, s.dataType );
- }
+ fadeTo: function( speed, to, easing, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, easing, callback);
+ },
- // Create converters map with lowercased keys
- if ( dataTypes[ 1 ] ) {
- for ( conv in s.converters ) {
- converters[ conv.toLowerCase() ] = s.converters[ conv ];
- }
- }
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed( speed, easing, callback );
- // Convert to each sequential dataType, tolerating list modification
- for ( ; (current = dataTypes[++i]); ) {
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete, [ false ] );
+ }
- // There's only work to do if current dataType is non-auto
- if ( current !== "*" ) {
+ // Do not change referenced properties as per-property easing will be lost
+ prop = jQuery.extend( {}, prop );
- // Convert response if prev dataType is non-auto and differs from current
- if ( prev !== "*" && prev !== current ) {
+ function doAnimation() {
+ // XXX 'this' does not always have a nodeName when running the
+ // test suite
- // Seek a direct converter
- conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+ if ( optall.queue === false ) {
+ jQuery._mark( this );
+ }
- // If none found, seek a pair
- if ( !conv ) {
- for ( conv2 in converters ) {
-
- // If conv2 outputs current
- tmp = conv2.split(" ");
- if ( tmp[ 1 ] === current ) {
-
- // If prev can be converted to accepted input
- conv = converters[ prev + " " + tmp[ 0 ] ] ||
- converters[ "* " + tmp[ 0 ] ];
- if ( conv ) {
- // Condense equivalence converters
- if ( conv === true ) {
- conv = converters[ conv2 ];
-
- // Otherwise, insert the intermediate dataType
- } else if ( converters[ conv2 ] !== true ) {
- current = tmp[ 0 ];
- dataTypes.splice( i--, 0, current );
- }
+ var opt = jQuery.extend( {}, optall ),
+ isElement = this.nodeType === 1,
+ hidden = isElement && jQuery(this).is(":hidden"),
+ name, val, p, e, hooks, replace,
+ parts, start, end, unit,
+ method;
+
+ // will store per property easing and be used to determine when an animation is complete
+ opt.animatedProperties = {};
+
+ // first pass over propertys to expand / normalize
+ for ( p in prop ) {
+ name = jQuery.camelCase( p );
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ }
- break;
+ if ( ( hooks = jQuery.cssHooks[ name ] ) && "expand" in hooks ) {
+ replace = hooks.expand( prop[ name ] );
+ delete prop[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'p' from above because we have the correct "name"
+ for ( p in replace ) {
+ if ( ! ( p in prop ) ) {
+ prop[ p ] = replace[ p ];
}
}
}
}
- // Apply converter (if not an equivalence)
- if ( conv !== true ) {
-
- // Unless errors are allowed to bubble, catch and return them
- if ( conv && s["throws"] ) {
- response = conv( response );
+ for ( name in prop ) {
+ val = prop[ name ];
+ // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+ if ( jQuery.isArray( val ) ) {
+ opt.animatedProperties[ name ] = val[ 1 ];
+ val = prop[ name ] = val[ 0 ];
} else {
- try {
- response = conv( response );
- } catch ( e ) {
- return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
- }
+ opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
}
- }
- }
- // Update prev for next iteration
- prev = current;
- }
- }
+ if ( val === "hide" && hidden || val === "show" && !hidden ) {
+ return opt.complete.call( this );
+ }
- return { state: "success", data: response };
-}
-var oldCallbacks = [],
- rquestion = /\?/,
- rjsonp = /(=)\?(?=&|$)|\?\?/,
- nonce = jQuery.now();
+ if ( isElement && ( name === "height" || name === "width" ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
-// Default jsonp settings
-jQuery.ajaxSetup({
- jsonp: "callback",
- jsonpCallback: function() {
- var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
- this[ callback ] = true;
- return callback;
- }
-});
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( this, "display" ) === "inline" &&
+ jQuery.css( this, "float" ) === "none" ) {
-// Detect, normalize options and install callbacks for jsonp requests
-jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
-
- var callbackName, overwritten, responseContainer,
- data = s.data,
- url = s.url,
- hasCallback = s.jsonp !== false,
- replaceInUrl = hasCallback && rjsonp.test( url ),
- replaceInData = hasCallback && !replaceInUrl && typeof data === "string" &&
- !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") &&
- rjsonp.test( data );
-
- // Handle iff the expected data type is "jsonp" or we have a parameter to set
- if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) {
-
- // Get callback name, remembering preexisting value associated with it
- callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
- s.jsonpCallback() :
- s.jsonpCallback;
- overwritten = window[ callbackName ];
-
- // Insert callback into url or form data
- if ( replaceInUrl ) {
- s.url = url.replace( rjsonp, "$1" + callbackName );
- } else if ( replaceInData ) {
- s.data = data.replace( rjsonp, "$1" + callbackName );
- } else if ( hasCallback ) {
- s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
- }
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
+ this.style.display = "inline-block";
- // Use data converter to retrieve json after script execution
- s.converters["script json"] = function() {
- if ( !responseContainer ) {
- jQuery.error( callbackName + " was not called" );
- }
- return responseContainer[ 0 ];
- };
+ } else {
+ this.style.zoom = 1;
+ }
+ }
+ }
+ }
- // force json dataType
- s.dataTypes[ 0 ] = "json";
+ if ( opt.overflow != null ) {
+ this.style.overflow = "hidden";
+ }
- // Install callback
- window[ callbackName ] = function() {
- responseContainer = arguments;
- };
+ for ( p in prop ) {
+ e = new jQuery.fx( this, opt, p );
+ val = prop[ p ];
- // Clean-up function (fires after converters)
- jqXHR.always(function() {
- // Restore preexisting value
- window[ callbackName ] = overwritten;
+ if ( rfxtypes.test( val ) ) {
- // Save back as free
- if ( s[ callbackName ] ) {
- // make sure that re-using the options doesn't screw things around
- s.jsonpCallback = originalSettings.jsonpCallback;
+ // Tracks whether to show or hide based on private
+ // data attached to the element
+ method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
+ if ( method ) {
+ jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
+ e[ method ]();
+ } else {
+ e[ val ]();
+ }
- // save the callback name for future use
- oldCallbacks.push( callbackName );
- }
+ } else {
+ parts = rfxnum.exec( val );
+ start = e.cur();
+
+ if ( parts ) {
+ end = parseFloat( parts[2] );
+ unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" ) {
+ jQuery.style( this, p, (end || 1) + unit);
+ start = ( (end || 1) / e.cur() ) * start;
+ jQuery.style( this, p, start + unit);
+ }
- // Call if it was a function and we have a response
- if ( responseContainer && jQuery.isFunction( overwritten ) ) {
- overwritten( responseContainer[ 0 ] );
- }
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] ) {
+ end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
+ }
- responseContainer = overwritten = undefined;
- });
+ e.custom( start, end, unit );
- // Delegate to script
- return "script";
- }
-});
-// Install script dataType
-jQuery.ajaxSetup({
- accepts: {
- script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
- },
- contents: {
- script: /javascript|ecmascript/
- },
- converters: {
- "text script": function( text ) {
- jQuery.globalEval( text );
- return text;
- }
- }
-});
+ } else {
+ e.custom( start, val, "" );
+ }
+ }
+ }
-// Handle cache's special case and global
-jQuery.ajaxPrefilter( "script", function( s ) {
- if ( s.cache === undefined ) {
- s.cache = false;
- }
- if ( s.crossDomain ) {
- s.type = "GET";
- s.global = false;
- }
-});
+ // For JS strict compliance
+ return true;
+ }
-// Bind script tag hack transport
-jQuery.ajaxTransport( "script", function(s) {
+ return optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
- // This transport only deals with cross domain requests
- if ( s.crossDomain ) {
+ stop: function( type, clearQueue, gotoEnd ) {
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
- var script,
- head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+ return this.each(function() {
+ var index,
+ hadTimers = false,
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ // clear marker counters if we know they won't be
+ if ( !gotoEnd ) {
+ jQuery._unmark( true, this );
+ }
- return {
+ function stopQueue( elem, data, index ) {
+ var hooks = data[ index ];
+ jQuery.removeData( elem, index, true );
+ hooks.stop( gotoEnd );
+ }
- send: function( _, callback ) {
+ if ( type == null ) {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
+ stopQueue( this, data, index );
+ }
+ }
+ } else if ( data[ index = type + ".run" ] && data[ index ].stop ){
+ stopQueue( this, data, index );
+ }
- script = document.createElement( "script" );
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ if ( gotoEnd ) {
- script.async = "async";
+ // force the next step to be the last
+ timers[ index ]( true );
+ } else {
+ timers[ index ].saveState();
+ }
+ hadTimers = true;
+ timers.splice( index, 1 );
+ }
+ }
- if ( s.scriptCharset ) {
- script.charset = s.scriptCharset;
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( !( gotoEnd && hadTimers ) ) {
+ jQuery.dequeue( this, type );
}
+ });
+ }
+
+ });
+
+// Animations created synchronously will run synchronously
+ function createFxNow() {
+ setTimeout( clearFxNow, 0 );
+ return ( fxNow = jQuery.now() );
+ }
- script.src = s.url;
+ function clearFxNow() {
+ fxNow = undefined;
+ }
- // Attach handlers for all browsers
- script.onload = script.onreadystatechange = function( _, isAbort ) {
+// Generate parameters to create a standard animation
+ function genFx( type, num ) {
+ var obj = {};
- if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
+ obj[ this ] = type;
+ });
- // Handle memory leak in IE
- script.onload = script.onreadystatechange = null;
+ return obj;
+ }
- // Remove the script
- if ( head && script.parentNode ) {
- head.removeChild( script );
- }
+// Generate shortcuts for custom animations
+ jQuery.each({
+ slideDown: genFx( "show", 1 ),
+ slideUp: genFx( "hide", 1 ),
+ slideToggle: genFx( "toggle", 1 ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+ }, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+ });
- // Dereference the script
- script = undefined;
+ jQuery.extend({
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
- // Callback if not abort
- if ( !isAbort ) {
- callback( 200, "success" );
- }
- }
- };
- // Use insertBefore instead of appendChild to circumvent an IE6 bug.
- // This arises when a base node is used (#2709 and #4378).
- head.insertBefore( script, head.firstChild );
- },
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
- abort: function() {
- if ( script ) {
- script.onload( 0, 1 );
- }
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
}
- };
- }
-});
-var xhrCallbacks,
- // #5280: Internet Explorer will keep connections alive if we don't abort on unload
- xhrOnUnloadAbort = window.ActiveXObject ? function() {
- // Abort all pending requests
- for ( var key in xhrCallbacks ) {
- xhrCallbacks[ key ]( 0, 1 );
- }
- } : false,
- xhrId = 0;
-// Functions to create xhrs
-function createStandardXHR() {
- try {
- return new window.XMLHttpRequest();
- } catch( e ) {}
-}
+ // Queueing
+ opt.old = opt.complete;
-function createActiveXHR() {
- try {
- return new window.ActiveXObject( "Microsoft.XMLHTTP" );
- } catch( e ) {}
-}
+ opt.complete = function( noUnmark ) {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
-// Create the request object
-// (This is still attached to ajaxSettings for backward compatibility)
-jQuery.ajaxSettings.xhr = window.ActiveXObject ?
- /* Microsoft failed to properly
- * implement the XMLHttpRequest in IE7 (can't request local files),
- * so we use the ActiveXObject when it is available
- * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
- * we need a fallback.
- */
- function() {
- return !this.isLocal && createStandardXHR() || createActiveXHR();
- } :
- // For all other browsers, use the standard XMLHttpRequest object
- createStandardXHR;
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ } else if ( noUnmark !== false ) {
+ jQuery._unmark( this );
+ }
+ };
+
+ return opt;
+ },
-// Determine support properties
-(function( xhr ) {
- jQuery.extend( jQuery.support, {
- ajax: !!xhr,
- cors: !!xhr && ( "withCredentials" in xhr )
- });
-})( jQuery.ajaxSettings.xhr() );
+ easing: {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;
+ }
+ },
-// Create transport if the browser can provide an xhr
-if ( jQuery.support.ajax ) {
+ timers: [],
- jQuery.ajaxTransport(function( s ) {
- // Cross domain only allowed if supported through XMLHttpRequest
- if ( !s.crossDomain || jQuery.support.cors ) {
+ fx: function( elem, options, prop ) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
- var callback;
+ options.orig = options.orig || {};
+ }
- return {
- send: function( headers, complete ) {
+ });
- // Get a new xhr
- var handle, i,
- xhr = s.xhr();
+ jQuery.fx.prototype = {
+ // Simple function for setting a style value
+ update: function() {
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
- // Open the socket
- // Passing null username, generates a login popup on Opera (#2865)
- if ( s.username ) {
- xhr.open( s.type, s.url, s.async, s.username, s.password );
- } else {
- xhr.open( s.type, s.url, s.async );
- }
+ ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
+ },
- // Apply custom fields if provided
- if ( s.xhrFields ) {
- for ( i in s.xhrFields ) {
- xhr[ i ] = s.xhrFields[ i ];
- }
- }
+ // Get the current size
+ cur: function() {
+ if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
+ return this.elem[ this.prop ];
+ }
- // Override mime type if needed
- if ( s.mimeType && xhr.overrideMimeType ) {
- xhr.overrideMimeType( s.mimeType );
- }
+ var parsed,
+ r = jQuery.css( this.elem, this.prop );
+ // Empty strings, null, undefined and "auto" are converted to 0,
+ // complex values such as "rotate(1rad)" are returned as is,
+ // simple values such as "10px" are parsed to Float.
+ return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
+ },
- // X-Requested-With header
- // For cross-domain requests, seeing as conditions for a preflight are
- // akin to a jigsaw puzzle, we simply never set it to be sure.
- // (it can always be set on a per-request basis or even using ajaxSetup)
- // For same-domain requests, won't change header if already provided.
- if ( !s.crossDomain && !headers["X-Requested-With"] ) {
- headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ // Start an animation from one number to another
+ custom: function( from, to, unit ) {
+ var self = this,
+ fx = jQuery.fx;
+
+ this.startTime = fxNow || createFxNow();
+ this.end = to;
+ this.now = this.start = from;
+ this.pos = this.state = 0;
+ this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
+
+ function t( gotoEnd ) {
+ return self.step( gotoEnd );
+ }
+
+ t.queue = this.options.queue;
+ t.elem = this.elem;
+ t.saveState = function() {
+ if ( jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
+ if ( self.options.hide ) {
+ jQuery._data( self.elem, "fxshow" + self.prop, self.start );
+ } else if ( self.options.show ) {
+ jQuery._data( self.elem, "fxshow" + self.prop, self.end );
}
+ }
+ };
- // Need an extra try/catch for cross domain requests in Firefox 3
- try {
- for ( i in headers ) {
- xhr.setRequestHeader( i, headers[ i ] );
- }
- } catch( _ ) {}
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval( fx.tick, fx.interval );
+ }
+ },
- // Do send the request
- // This may raise an exception which is actually
- // handled in jQuery.ajax (so no try/catch here)
- xhr.send( ( s.hasContent && s.data ) || null );
+ // Simple 'show' function
+ show: function() {
+ var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
- // Listener
- callback = function( _, isAbort ) {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
+ this.options.show = true;
- var status,
- statusText,
- responseHeaders,
- responses,
- xml;
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any flash of content
+ if ( dataShow !== undefined ) {
+ // This show is picking up where a previous hide or show left off
+ this.custom( this.cur(), dataShow );
+ } else {
+ this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
+ }
- // Firefox throws exceptions when accessing properties
- // of an xhr when a network error occurred
- // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
- try {
+ // Start by showing the element
+ jQuery( this.elem ).show();
+ },
- // Was never called and is aborted or complete
- if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+ // Simple 'hide' function
+ hide: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
+ this.options.hide = true;
- // Only called once
- callback = undefined;
+ // Begin the animation
+ this.custom( this.cur(), 0 );
+ },
- // Do not keep as active anymore
- if ( handle ) {
- xhr.onreadystatechange = jQuery.noop;
- if ( xhrOnUnloadAbort ) {
- delete xhrCallbacks[ handle ];
- }
- }
+ // Each step of an animation
+ step: function( gotoEnd ) {
+ var p, n, complete,
+ t = fxNow || createFxNow(),
+ done = true,
+ elem = this.elem,
+ options = this.options;
- // If it's an abort
- if ( isAbort ) {
- // Abort it manually if needed
- if ( xhr.readyState !== 4 ) {
- xhr.abort();
- }
- } else {
- status = xhr.status;
- responseHeaders = xhr.getAllResponseHeaders();
- responses = {};
- xml = xhr.responseXML;
-
- // Construct response list
- if ( xml && xml.documentElement /* #4958 */ ) {
- responses.xml = xml;
- }
+ if ( gotoEnd || t >= options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
- // When requesting binary data, IE6-9 will throw an exception
- // on any attempt to access responseText (#11426)
- try {
- responses.text = xhr.responseText;
- } catch( _ ) {
- }
+ options.animatedProperties[ this.prop ] = true;
- // Firefox throws an exception when accessing
- // statusText for faulty cross-domain requests
- try {
- statusText = xhr.statusText;
- } catch( e ) {
- // We normalize with Webkit giving an empty statusText
- statusText = "";
- }
+ for ( p in options.animatedProperties ) {
+ if ( options.animatedProperties[ p ] !== true ) {
+ done = false;
+ }
+ }
- // Filter status for non standard behaviors
+ if ( done ) {
+ // Reset the overflow
+ if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
- // If the request is local and we have data: assume a success
- // (success with no data won't get notified, that's the best we
- // can do given current implementations)
- if ( !status && s.isLocal && !s.crossDomain ) {
- status = responses.text ? 200 : 404;
- // IE - #1450: sometimes returns 1223 when it should be 204
- } else if ( status === 1223 ) {
- status = 204;
- }
- }
- }
- } catch( firefoxAccessException ) {
- if ( !isAbort ) {
- complete( -1, firefoxAccessException );
- }
- }
+ jQuery.each( [ "", "X", "Y" ], function( index, value ) {
+ elem.style[ "overflow" + value ] = options.overflow[ index ];
+ });
+ }
- // Call complete if needed
- if ( responses ) {
- complete( status, statusText, responses, responseHeaders );
- }
- };
+ // Hide the element if the "hide" operation was done
+ if ( options.hide ) {
+ jQuery( elem ).hide();
+ }
- if ( !s.async ) {
- // if we're in sync mode we fire the callback
- callback();
- } else if ( xhr.readyState === 4 ) {
- // (IE6 & IE7) if it's in cache and has been
- // retrieved directly we need to fire the callback
- setTimeout( callback, 0 );
- } else {
- handle = ++xhrId;
- if ( xhrOnUnloadAbort ) {
- // Create the active xhrs callbacks list if needed
- // and attach the unload handler
- if ( !xhrCallbacks ) {
- xhrCallbacks = {};
- jQuery( window ).unload( xhrOnUnloadAbort );
- }
- // Add to list of active xhrs callbacks
- xhrCallbacks[ handle ] = callback;
+ // Reset the properties, if the item has been hidden or shown
+ if ( options.hide || options.show ) {
+ for ( p in options.animatedProperties ) {
+ jQuery.style( elem, p, options.orig[ p ] );
+ jQuery.removeData( elem, "fxshow" + p, true );
+ // Toggle data is no longer needed
+ jQuery.removeData( elem, "toggle" + p, true );
}
- xhr.onreadystatechange = callback;
}
- },
- abort: function() {
- if ( callback ) {
- callback(0,1);
+ // Execute the complete function
+ // in the event that the complete function throws an exception
+ // we must ensure it won't be called twice. #5684
+
+ complete = options.complete;
+ if ( complete ) {
+
+ options.complete = false;
+ complete.call( elem );
}
}
- };
- }
- });
-}
-var fxNow, timerId,
- rfxtypes = /^(?:toggle|show|hide)$/,
- rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
- rrun = /queueHooks$/,
- animationPrefilters = [ defaultPrefilter ],
- tweeners = {
- "*": [function( prop, value ) {
- var end, unit, prevScale,
- tween = this.createTween( prop, value ),
- parts = rfxnum.exec( value ),
- target = tween.cur(),
- start = +target || 0,
- scale = 1;
-
- if ( parts ) {
- end = +parts[2];
- unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
-
- // We need to compute starting value
- if ( unit !== "px" && start ) {
- // Iteratively approximate from a nonzero starting point
- // Prefer the current property, because this process will be trivial if it uses the same units
- // Fallback to end or a simple constant
- start = jQuery.css( tween.elem, prop, true ) || end || 1;
-
- do {
- // If previous iteration zeroed out, double until we get *something*
- // Use a string for doubling factor so we don't accidentally see scale as unchanged below
- prevScale = scale = scale || ".5";
-
- // Adjust and apply
- start = start / scale;
- jQuery.style( tween.elem, prop, start + unit );
-
- // Update scale, tolerating zeroes from tween.cur()
- scale = tween.cur() / target;
-
- // Stop looping if we've hit the mark or scale is unchanged
- } while ( scale !== 1 && scale !== prevScale );
- }
-
- tween.unit = unit;
- tween.start = start;
- // If a +=/-= token was provided, we're doing a relative animation
- tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
- }
- return tween;
- }]
- };
-// Animations created synchronously will run synchronously
-function createFxNow() {
- setTimeout(function() {
- fxNow = undefined;
- }, 0 );
- return ( fxNow = jQuery.now() );
-}
-
-function createTweens( animation, props ) {
- jQuery.each( props, function( prop, value ) {
- var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
- index = 0,
- length = collection.length;
- for ( ; index < length; index++ ) {
- if ( collection[ index ].call( animation, prop, value ) ) {
-
- // we're done with this property
- return;
- }
- }
- });
-}
-
-function Animation( elem, properties, options ) {
- var result,
- index = 0,
- tweenerIndex = 0,
- length = animationPrefilters.length,
- deferred = jQuery.Deferred().always( function() {
- // don't match elem in the :animated selector
- delete tick.elem;
- }),
- tick = function() {
- var currentTime = fxNow || createFxNow(),
- remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
- percent = 1 - ( remaining / animation.duration || 0 ),
- index = 0,
- length = animation.tweens.length;
-
- for ( ; index < length ; index++ ) {
- animation.tweens[ index ].run( percent );
- }
-
- deferred.notifyWith( elem, [ animation, percent, remaining ]);
-
- if ( percent < 1 && length ) {
- return remaining;
- } else {
- deferred.resolveWith( elem, [ animation ] );
return false;
- }
- },
- animation = deferred.promise({
- elem: elem,
- props: jQuery.extend( {}, properties ),
- opts: jQuery.extend( true, { specialEasing: {} }, options ),
- originalProperties: properties,
- originalOptions: options,
- startTime: fxNow || createFxNow(),
- duration: options.duration,
- tweens: [],
- createTween: function( prop, end, easing ) {
- var tween = jQuery.Tween( elem, animation.opts, prop, end,
- animation.opts.specialEasing[ prop ] || animation.opts.easing );
- animation.tweens.push( tween );
- return tween;
- },
- stop: function( gotoEnd ) {
- var index = 0,
- // if we are going to the end, we want to run all the tweens
- // otherwise we skip this part
- length = gotoEnd ? animation.tweens.length : 0;
-
- for ( ; index < length ; index++ ) {
- animation.tweens[ index ].run( 1 );
- }
- // resolve when we played the last frame
- // otherwise, reject
- if ( gotoEnd ) {
- deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ // classical easing cannot be used with an Infinity duration
+ if ( options.duration == Infinity ) {
+ this.now = t;
} else {
- deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ n = t - this.startTime;
+ this.state = n / options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
+ this.now = this.start + ( (this.end - this.start) * this.pos );
}
- return this;
+ // Perform the next step of the animation
+ this.update();
}
- }),
- props = animation.props;
-
- propFilter( props, animation.opts.specialEasing );
-
- for ( ; index < length ; index++ ) {
- result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
- if ( result ) {
- return result;
- }
- }
-
- createTweens( animation, props );
- if ( jQuery.isFunction( animation.opts.start ) ) {
- animation.opts.start.call( elem, animation );
- }
-
- jQuery.fx.timer(
- jQuery.extend( tick, {
- anim: animation,
- queue: animation.opts.queue,
- elem: elem
- })
- );
-
- // attach callbacks from options
- return animation.progress( animation.opts.progress )
- .done( animation.opts.done, animation.opts.complete )
- .fail( animation.opts.fail )
- .always( animation.opts.always );
-}
-
-function propFilter( props, specialEasing ) {
- var index, name, easing, value, hooks;
-
- // camelCase, specialEasing and expand cssHook pass
- for ( index in props ) {
- name = jQuery.camelCase( index );
- easing = specialEasing[ name ];
- value = props[ index ];
- if ( jQuery.isArray( value ) ) {
- easing = value[ 1 ];
- value = props[ index ] = value[ 0 ];
- }
-
- if ( index !== name ) {
- props[ name ] = value;
- delete props[ index ];
+ return true;
}
+ };
- hooks = jQuery.cssHooks[ name ];
- if ( hooks && "expand" in hooks ) {
- value = hooks.expand( value );
- delete props[ name ];
+ jQuery.extend( jQuery.fx, {
+ tick: function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
- // not quite $.extend, this wont overwrite keys already present.
- // also - reusing 'index' from above because we have the correct "name"
- for ( index in value ) {
- if ( !( index in props ) ) {
- props[ index ] = value[ index ];
- specialEasing[ index ] = easing;
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
}
}
- } else {
- specialEasing[ name ] = easing;
- }
- }
-}
-jQuery.Animation = jQuery.extend( Animation, {
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
- tweener: function( props, callback ) {
- if ( jQuery.isFunction( props ) ) {
- callback = props;
- props = [ "*" ];
- } else {
- props = props.split(" ");
- }
+ interval: 13,
- var prop,
- index = 0,
- length = props.length;
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
- for ( ; index < length ; index++ ) {
- prop = props[ index ];
- tweeners[ prop ] = tweeners[ prop ] || [];
- tweeners[ prop ].unshift( callback );
- }
- },
+ speeds: {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
- prefilter: function( callback, prepend ) {
- if ( prepend ) {
- animationPrefilters.unshift( callback );
- } else {
- animationPrefilters.push( callback );
- }
- }
-});
-
-function defaultPrefilter( elem, props, opts ) {
- var index, prop, value, length, dataShow, tween, hooks, oldfire,
- anim = this,
- style = elem.style,
- orig = {},
- handled = [],
- hidden = elem.nodeType && isHidden( elem );
-
- // handle queue: false promises
- if ( !opts.queue ) {
- hooks = jQuery._queueHooks( elem, "fx" );
- if ( hooks.unqueued == null ) {
- hooks.unqueued = 0;
- oldfire = hooks.empty.fire;
- hooks.empty.fire = function() {
- if ( !hooks.unqueued ) {
- oldfire();
- }
- };
- }
- hooks.unqueued++;
+ step: {
+ opacity: function( fx ) {
+ jQuery.style( fx.elem, "opacity", fx.now );
+ },
- anim.always(function() {
- // doing this makes sure that the complete handler will be called
- // before this completes
- anim.always(function() {
- hooks.unqueued--;
- if ( !jQuery.queue( elem, "fx" ).length ) {
- hooks.empty.fire();
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ } else {
+ fx.elem[ fx.prop ] = fx.now;
}
- });
- });
- }
-
- // height/width overflow pass
- if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
- // Make sure that nothing sneaks out
- // Record all 3 overflow attributes because IE does not
- // change the overflow attribute when overflowX and
- // overflowY are set to the same value
- opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
-
- // Set display property to inline-block for height/width
- // animations on inline elements that are having width/height animated
- if ( jQuery.css( elem, "display" ) === "inline" &&
- jQuery.css( elem, "float" ) === "none" ) {
-
- // inline-level elements accept inline-block;
- // block-level elements need to be inline with layout
- if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
- style.display = "inline-block";
-
- } else {
- style.zoom = 1;
}
}
- }
+ });
- if ( opts.overflow ) {
- style.overflow = "hidden";
- if ( !jQuery.support.shrinkWrapBlocks ) {
- anim.done(function() {
- style.overflow = opts.overflow[ 0 ];
- style.overflowX = opts.overflow[ 1 ];
- style.overflowY = opts.overflow[ 2 ];
- });
+// Ensure props that can't be negative don't go there on undershoot easing
+ jQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {
+ // exclude marginTop, marginLeft, marginBottom and marginRight from this list
+ if ( prop.indexOf( "margin" ) ) {
+ jQuery.fx.step[ prop ] = function( fx ) {
+ jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
+ };
}
+ });
+
+ if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
}
+// Try to restore the default display value of an element
+ function defaultDisplay( nodeName ) {
- // show/hide pass
- for ( index in props ) {
- value = props[ index ];
- if ( rfxtypes.exec( value ) ) {
- delete props[ index ];
- if ( value === ( hidden ? "hide" : "show" ) ) {
- continue;
- }
- handled.push( index );
- }
- }
+ if ( !elemdisplay[ nodeName ] ) {
- length = handled.length;
- if ( length ) {
- dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
- if ( hidden ) {
- jQuery( elem ).show();
- } else {
- anim.done(function() {
- jQuery( elem ).hide();
- });
- }
- anim.done(function() {
- var prop;
- jQuery.removeData( elem, "fxshow", true );
- for ( prop in orig ) {
- jQuery.style( elem, prop, orig[ prop ] );
- }
- });
- for ( index = 0 ; index < length ; index++ ) {
- prop = handled[ index ];
- tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
- orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
+ var body = document.body,
+ elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
+ display = elem.css( "display" );
+ elem.remove();
- if ( !( prop in dataShow ) ) {
- dataShow[ prop ] = tween.start;
- if ( hidden ) {
- tween.end = tween.start;
- tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ // If the simple way fails,
+ // get element's real default display by attaching it to a temp iframe
+ if ( display === "none" || display === "" ) {
+ // No iframe to use yet, so create it
+ if ( !iframe ) {
+ iframe = document.createElement( "iframe" );
+ iframe.frameBorder = iframe.width = iframe.height = 0;
}
- }
- }
- }
-}
-
-function Tween( elem, options, prop, end, easing ) {
- return new Tween.prototype.init( elem, options, prop, end, easing );
-}
-jQuery.Tween = Tween;
-
-Tween.prototype = {
- constructor: Tween,
- init: function( elem, options, prop, end, easing, unit ) {
- this.elem = elem;
- this.prop = prop;
- this.easing = easing || "swing";
- this.options = options;
- this.start = this.now = this.cur();
- this.end = end;
- this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
- },
- cur: function() {
- var hooks = Tween.propHooks[ this.prop ];
-
- return hooks && hooks.get ?
- hooks.get( this ) :
- Tween.propHooks._default.get( this );
- },
- run: function( percent ) {
- var eased,
- hooks = Tween.propHooks[ this.prop ];
-
- this.pos = eased = jQuery.easing[ this.easing ]( percent, this.options.duration * percent, 0, 1, this.options.duration );
- this.now = ( this.end - this.start ) * eased + this.start;
-
- if ( this.options.step ) {
- this.options.step.call( this.elem, this.now, this );
- }
- if ( hooks && hooks.set ) {
- hooks.set( this );
- } else {
- Tween.propHooks._default.set( this );
- }
- return this;
- }
-};
+ body.appendChild( iframe );
-Tween.prototype.init.prototype = Tween.prototype;
+ // Create a cacheable copy of the iframe document on first call.
+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+ // document to it; WebKit & Firefox won't allow reusing the iframe document.
+ if ( !iframeDoc || !iframe.createElement ) {
+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+ iframeDoc.write( ( jQuery.support.boxModel ? "<!doctype html>" : "" ) + "<html><body>" );
+ iframeDoc.close();
+ }
-Tween.propHooks = {
- _default: {
- get: function( tween ) {
- var result;
+ elem = iframeDoc.createElement( nodeName );
- if ( tween.elem[ tween.prop ] != null &&
- (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
- return tween.elem[ tween.prop ];
- }
+ iframeDoc.body.appendChild( elem );
- // passing any value as a 4th parameter to .css will automatically
- // attempt a parseFloat and fallback to a string if the parse fails
- // so, simple values such as "10px" are parsed to Float.
- // complex values such as "rotate(1rad)" are returned as is.
- result = jQuery.css( tween.elem, tween.prop, false, "" );
- // Empty strings, null, undefined and "auto" are converted to 0.
- return !result || result === "auto" ? 0 : result;
- },
- set: function( tween ) {
- // use step hook for back compat - use cssHook if its there - use .style if its
- // available and use plain properties where available
- if ( jQuery.fx.step[ tween.prop ] ) {
- jQuery.fx.step[ tween.prop ]( tween );
- } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
- jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
- } else {
- tween.elem[ tween.prop ] = tween.now;
+ display = jQuery.css( elem, "display" );
+ body.removeChild( iframe );
}
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
}
+
+ return elemdisplay[ nodeName ];
}
-};
-// Remove in 2.0 - this supports IE8's panic based approach
-// to setting things on disconnected nodes
-Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
- set: function( tween ) {
- if ( tween.elem.nodeType && tween.elem.parentNode ) {
- tween.elem[ tween.prop ] = tween.now;
- }
- }
-};
-
-jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
- var cssFn = jQuery.fn[ name ];
- jQuery.fn[ name ] = function( speed, easing, callback ) {
- return speed == null || typeof speed === "boolean" ||
- // special check for .toggle( handler, handler, ... )
- ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?
- cssFn.apply( this, arguments ) :
- this.animate( genFx( name, true ), speed, easing, callback );
- };
-});
-jQuery.fn.extend({
- fadeTo: function( speed, to, easing, callback ) {
- // show any hidden elements after setting opacity to 0
- return this.filter( isHidden ).css( "opacity", 0 ).show()
+ var getOffset,
+ rtable = /^t(?:able|d|h)$/i,
+ rroot = /^(?:body|html)$/i;
+
+ if ( "getBoundingClientRect" in document.documentElement ) {
+ getOffset = function( elem, doc, docElem, box ) {
+ try {
+ box = elem.getBoundingClientRect();
+ } catch(e) {}
- // animate to the value specified
- .end().animate({ opacity: to }, speed, easing, callback );
- },
- animate: function( prop, speed, easing, callback ) {
- var empty = jQuery.isEmptyObject( prop ),
- optall = jQuery.speed( speed, easing, callback ),
- doAnimation = function() {
- // Operate on a copy of prop so per-property easing won't be lost
- var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+ // Make sure we're not dealing with a disconnected DOM node
+ if ( !box || !jQuery.contains( docElem, elem ) ) {
+ return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
+ }
- // Empty animations resolve immediately
- if ( empty ) {
- anim.stop( true );
- }
- };
+ var body = doc.body,
+ win = getWindow( doc ),
+ clientTop = docElem.clientTop || body.clientTop || 0,
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
+ scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
+ top = box.top + scrollTop - clientTop,
+ left = box.left + scrollLeft - clientLeft;
- return empty || optall.queue === false ?
- this.each( doAnimation ) :
- this.queue( optall.queue, doAnimation );
- },
- stop: function( type, clearQueue, gotoEnd ) {
- var stopQueue = function( hooks ) {
- var stop = hooks.stop;
- delete hooks.stop;
- stop( gotoEnd );
+ return { top: top, left: left };
};
- if ( typeof type !== "string" ) {
- gotoEnd = clearQueue;
- clearQueue = type;
- type = undefined;
- }
- if ( clearQueue && type !== false ) {
- this.queue( type || "fx", [] );
- }
+ } else {
+ getOffset = function( elem, doc, docElem ) {
+ var computedStyle,
+ offsetParent = elem.offsetParent,
+ prevOffsetParent = elem,
+ body = doc.body,
+ defaultView = doc.defaultView,
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+ top = elem.offsetTop,
+ left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ break;
+ }
- return this.each(function() {
- var dequeue = true,
- index = type != null && type + "queueHooks",
- timers = jQuery.timers,
- data = jQuery._data( this );
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
- if ( index ) {
- if ( data[ index ] && data[ index ].stop ) {
- stopQueue( data[ index ] );
- }
- } else {
- for ( index in data ) {
- if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
- stopQueue( data[ index ] );
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
}
+
+ prevOffsetParent = offsetParent;
+ offsetParent = elem.offsetParent;
}
- }
- for ( index = timers.length; index--; ) {
- if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
- timers[ index ].anim.stop( gotoEnd );
- dequeue = false;
- timers.splice( index, 1 );
+ if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
}
- }
- // start the next in the queue if the last step wasn't forced
- // timers currently will call their complete callbacks, which will dequeue
- // but only if they were gotoEnd
- if ( dequeue || !gotoEnd ) {
- jQuery.dequeue( this, type );
+ prevComputedStyle = computedStyle;
}
- });
- }
-});
-
-// Generate parameters to create a standard animation
-function genFx( type, includeWidth ) {
- var which,
- attrs = { height: type },
- i = 0;
-
- // if we include width, step value is 1 to do all cssExpand values,
- // if we don't include width, step value is 2 to skip over Left and Right
- for( ; i < 4 ; i += 2 - includeWidth ) {
- which = cssExpand[ i ];
- attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
- }
-
- if ( includeWidth ) {
- attrs.opacity = attrs.width = type;
- }
- return attrs;
-}
-
-// Generate shortcuts for custom animations
-jQuery.each({
- slideDown: genFx("show"),
- slideUp: genFx("hide"),
- slideToggle: genFx("toggle"),
- fadeIn: { opacity: "show" },
- fadeOut: { opacity: "hide" },
- fadeToggle: { opacity: "toggle" }
-}, function( name, props ) {
- jQuery.fn[ name ] = function( speed, easing, callback ) {
- return this.animate( props, speed, easing, callback );
- };
-});
-
-jQuery.speed = function( speed, easing, fn ) {
- var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
- complete: fn || !fn && easing ||
- jQuery.isFunction( speed ) && speed,
- duration: speed,
- easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
- };
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+ top += body.offsetTop;
+ left += body.offsetLeft;
+ }
- opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
- opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
- // normalize opt.queue - true/undefined/null -> "fx"
- if ( opt.queue == null || opt.queue === true ) {
- opt.queue = "fx";
+ return { top: top, left: left };
+ };
}
- // Queueing
- opt.old = opt.complete;
-
- opt.complete = function() {
- if ( jQuery.isFunction( opt.old ) ) {
- opt.old.call( this );
- }
-
- if ( opt.queue ) {
- jQuery.dequeue( this, opt.queue );
+ jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
}
- };
- return opt;
-};
+ var elem = this[0],
+ doc = elem && elem.ownerDocument;
-jQuery.easing = {
- linear: function( p ) {
- return p;
- },
- swing: function( p ) {
- return 0.5 - Math.cos( p*Math.PI ) / 2;
- }
-};
-
-jQuery.timers = [];
-jQuery.fx = Tween.prototype.init;
-jQuery.fx.tick = function() {
- var timer,
- timers = jQuery.timers,
- i = 0;
-
- for ( ; i < timers.length; i++ ) {
- timer = timers[ i ];
- // Checks the timer has not already been removed
- if ( !timer() && timers[ i ] === timer ) {
- timers.splice( i--, 1 );
+ if ( !doc ) {
+ return null;
}
- }
- if ( !timers.length ) {
- jQuery.fx.stop();
- }
-};
+ if ( elem === doc.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
-jQuery.fx.timer = function( timer ) {
- if ( timer() && jQuery.timers.push( timer ) && !timerId ) {
- timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
- }
-};
-
-jQuery.fx.interval = 13;
-
-jQuery.fx.stop = function() {
- clearInterval( timerId );
- timerId = null;
-};
-
-jQuery.fx.speeds = {
- slow: 600,
- fast: 200,
- // Default speed
- _default: 400
-};
-
-// Back Compat <1.8 extension point
-jQuery.fx.step = {};
-
-if ( jQuery.expr && jQuery.expr.filters ) {
- jQuery.expr.filters.animated = function( elem ) {
- return jQuery.grep(jQuery.timers, function( fn ) {
- return elem === fn.elem;
- }).length;
+ return getOffset( elem, doc, doc.documentElement );
};
-}
-var rroot = /^(?:body|html)$/i;
-
-jQuery.fn.offset = function( options ) {
- if ( arguments.length ) {
- return options === undefined ?
- this :
- this.each(function( i ) {
- jQuery.offset.setOffset( this, options, i );
- });
- }
- var box, docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, top, left,
- elem = this[ 0 ],
- doc = elem && elem.ownerDocument;
+ jQuery.offset = {
- if ( !doc ) {
- return;
- }
+ bodyOffset: function( body ) {
+ var top = body.offsetTop,
+ left = body.offsetLeft;
- if ( (body = doc.body) === elem ) {
- return jQuery.offset.bodyOffset( elem );
- }
+ if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+ left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+ }
+
+ return { top: top, left: left };
+ },
- docElem = doc.documentElement;
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
- // Make sure we're not dealing with a disconnected DOM node
- if ( !jQuery.contains( docElem, elem ) ) {
- return { top: 0, left: 0 };
- }
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
- box = elem.getBoundingClientRect();
- win = getWindow( doc );
- clientTop = docElem.clientTop || body.clientTop || 0;
- clientLeft = docElem.clientLeft || body.clientLeft || 0;
- scrollTop = win.pageYOffset || docElem.scrollTop;
- scrollLeft = win.pageXOffset || docElem.scrollLeft;
- top = box.top + scrollTop - clientTop;
- left = box.left + scrollLeft - clientLeft;
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
- return { top: top, left: left };
-};
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
-jQuery.offset = {
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
- bodyOffset: function( body ) {
- var top = body.offsetTop,
- left = body.offsetLeft;
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
- if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
- top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
- left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
}
+ };
- return { top: top, left: left };
- },
- setOffset: function( elem, options, i ) {
- var position = jQuery.css( elem, "position" );
+ jQuery.fn.extend({
- // set position first, in-case top/left are set even on static elem
- if ( position === "static" ) {
- elem.style.position = "relative";
- }
+ position: function() {
+ if ( !this[0] ) {
+ return null;
+ }
- var curElem = jQuery( elem ),
- curOffset = curElem.offset(),
- curCSSTop = jQuery.css( elem, "top" ),
- curCSSLeft = jQuery.css( elem, "left" ),
- calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
- props = {}, curPosition = {}, curTop, curLeft;
-
- // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
- if ( calculatePosition ) {
- curPosition = curElem.position();
- curTop = curPosition.top;
- curLeft = curPosition.left;
- } else {
- curTop = parseFloat( curCSSTop ) || 0;
- curLeft = parseFloat( curCSSLeft ) || 0;
- }
+ var elem = this[0],
- if ( jQuery.isFunction( options ) ) {
- options = options.call( elem, i, curOffset );
- }
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
- if ( options.top != null ) {
- props.top = ( options.top - curOffset.top ) + curTop;
- }
- if ( options.left != null ) {
- props.left = ( options.left - curOffset.left ) + curLeft;
- }
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
- if ( "using" in options ) {
- options.using.call( elem, props );
- } else {
- curElem.css( props );
- }
- }
-};
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+ offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+ parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
-jQuery.fn.extend({
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ },
- position: function() {
- if ( !this[0] ) {
- return;
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
}
+ });
- var elem = this[0],
-
- // Get *real* offsetParent
- offsetParent = this.offsetParent(),
-
- // Get correct offsets
- offset = this.offset(),
- parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
- // Subtract element margins
- // note: when an element has margin: auto the offsetLeft and marginLeft
- // are the same in Safari causing offset.left to incorrectly be 0
- offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
- offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+// Create scrollLeft and scrollTop methods
+ jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
- // Add offsetParent borders
- parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
- parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
- // Subtract the two offsets
- return {
- top: offset.top - parentOffset.top,
- left: offset.left - parentOffset.left
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
};
- },
+ });
- offsetParent: function() {
- return this.map(function() {
- var offsetParent = this.offsetParent || document.body;
- while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
- offsetParent = offsetParent.offsetParent;
- }
- return offsetParent || document.body;
- });
+ function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
}
-});
-// Create scrollLeft and scrollTop methods
-jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
- var top = /Y/.test( prop );
- jQuery.fn[ method ] = function( val ) {
- return jQuery.access( this, function( elem, method, val ) {
- var win = getWindow( elem );
- if ( val === undefined ) {
- return win ? (prop in win) ? win[ prop ] :
- win.document.documentElement[ method ] :
- elem[ method ];
- }
+// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
+ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ var clientProp = "client" + name,
+ scrollProp = "scroll" + name,
+ offsetProp = "offset" + name;
- if ( win ) {
- win.scrollTo(
- !top ? val : jQuery( win ).scrollLeft(),
- top ? val : jQuery( win ).scrollTop()
- );
+ // innerHeight and innerWidth
+ jQuery.fn[ "inner" + name ] = function() {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, "padding" ) ) :
+ this[ type ]() :
+ null;
+ };
- } else {
- elem[ method ] = val;
- }
- }, method, val, arguments.length, null );
- };
-});
-
-function getWindow( elem ) {
- return jQuery.isWindow( elem ) ?
- elem :
- elem.nodeType === 9 ?
- elem.defaultView || elem.parentWindow :
- false;
-}
-// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
-jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
- jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
- // margin is only for outerHeight, outerWidth
- jQuery.fn[ funcName ] = function( margin, value ) {
- var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
- extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+ // outerHeight and outerWidth
+ jQuery.fn[ "outer" + name ] = function( margin ) {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
+ this[ type ]() :
+ null;
+ };
+ jQuery.fn[ type ] = function( value ) {
return jQuery.access( this, function( elem, type, value ) {
- var doc;
+ var doc, docElemProp, orig, ret;
if ( jQuery.isWindow( elem ) ) {
- // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
- // isn't a whole lot we can do. See pull request at this URL for discussion:
- // https://github.com/jquery/jquery/pull/764
- return elem.document.documentElement[ "client" + name ];
+ // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
+ doc = elem.document;
+ docElemProp = doc.documentElement[ clientProp ];
+ return jQuery.support.boxModel && docElemProp ||
+ doc.body && doc.body[ clientProp ] || docElemProp;
}
// Get document width or height
if ( elem.nodeType === 9 ) {
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
doc = elem.documentElement;
- // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
- // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ // when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]
+ // so we can't use max, as it'll choose the incorrect offset[Width/Height]
+ // instead we use the correct client[Width/Height]
+ // support:IE6
+ if ( doc[ clientProp ] >= doc[ scrollProp ] ) {
+ return doc[ clientProp ];
+ }
+
return Math.max(
- elem.body[ "scroll" + name ], doc[ "scroll" + name ],
- elem.body[ "offset" + name ], doc[ "offset" + name ],
- doc[ "client" + name ]
+ elem.body[ scrollProp ], doc[ scrollProp ],
+ elem.body[ offsetProp ], doc[ offsetProp ]
);
}
- return value === undefined ?
- // Get width or height on the element, requesting but not forcing parseFloat
- jQuery.css( elem, type, value, extra ) :
+ // Get width or height on the element
+ if ( value === undefined ) {
+ orig = jQuery.css( elem, type );
+ ret = parseFloat( orig );
+ return jQuery.isNumeric( ret ) ? ret : orig;
+ }
- // Set width or height on the element
- jQuery.style( elem, type, value, extra );
- }, type, chainable ? margin : undefined, chainable );
+ // Set the width or height on the element
+ jQuery( elem ).css( type, value );
+ }, type, value, arguments.length, null );
};
});
-});
+
+
+
+
// Expose jQuery to the global object
-window.jQuery = window.$ = jQuery;
+ window.jQuery = window.$ = jQuery;
// Expose jQuery as an AMD module, but only for AMD loaders that
// understand the issues with loading multiple versions of jQuery
// file names, and jQuery is normally delivered in a lowercase file name.
// Do this after creating the global so that if an AMD module wants to call
// noConflict to hide this version of jQuery, it will work.
-if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
- define( "jquery", [], function () { return jQuery; } );
-}
+ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+ }
+
+
})( window );
+++ /dev/null
-.js-messagebox {
- margin: 1em 5%;
- padding: 0.5em 2.5%;
- border: 1px solid #ccc;
- background-color: #fcfcfc;
- font-size: 0.8em;
-}
-.js-messagebox .js-messagebox-group {
- margin: 1px;
- padding: 0.5em 2.5%;
- border-bottom: 1px solid #ddd;
-}
-.js-messagebox .js-messagebox-group:last-child {
- border-bottom: thin none transparent;
-}
\ No newline at end of file
+++ /dev/null
-/**
- * jQuery messageBox
- *
- * Function to inform the user of something. Use sparingly (since there's mw.log for
- * messages aimed at developers / debuggers). Based on the function in MediaWiki's
- * legacy javascript (wikibits.js) by Aryeh Gregor called jsMsg() added in r23233.
- *
- * @author Krinkle <krinklemail@gmail.com>
- *
- * Dual license:
- * @license CC-BY 3.0 <http://creativecommons.org/licenses/by/3.0>
- * @license GPL2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
- */
-( function ( $ ) {
-
-/** @return jQuery object of the message box */
-$.messageBoxNew = function ( options ) {
- options = $.extend( {
- // unique identifier for this message box
- id: 'js-messagebox',
-
- // jQuery/CSS selector
- parent: 'body',
-
- // 'prepend' or 'append'
- insert: 'prepend'
- }, options );
- var $curBox = $( '#' + options.id );
- // Only create a new box if it doesn't exist already
- if ( $curBox.length > 0 ) {
- if ( $curBox.hasClass( 'js-messagebox' ) ) {
- return $curBox;
- } else {
- return $curBox.addClass( 'js-messagebox' );
- }
- } else {
- var $newBox = $( '<div>', {
- 'id': options.id,
- 'class': 'js-messagebox',
- 'css': {
- 'display': 'none'
- }
- });
- if ( $( options.parent ).length < 1 ) {
- options.parent = 'body';
- }
- if ( options.insert === 'append' ) {
- $newBox.appendTo( options.parent );
- return $newBox;
- } else {
- $newBox.prependTo( options.parent );
- return $newBox;
- }
- }
-};
-
-/**
- * Calling with no message or message set to empty string or null will hide the group,
- * setting 'replace' to true as well will reset and hide the group entirely.
- * If there are no visible groups the main message box is hidden automatically,
- * and shown again once there are messages
- * @return {jQuery}: jQuery object of message group.
- */
-$.messageBox = function ( options ) {
- options = $.extend( {
- message: '',
- group: 'default',
- // if replace=true, it replaces any previous message in this group
- replace: false,
- target: 'js-messagebox'
- }, options );
- var $target = $.messageBoxNew( { id: options.target } );
- var groupID = options.target + '-' + options.group;
- var $group = $( '#' + groupID );
- // Create group container if not existant
- if ( $group.length < 1 ) {
- $group = $( '<div>', {
- 'id': groupID,
- 'class': 'js-messagebox-group'
- });
- $target.prepend( $group );
- }
- // Replace ?
- if ( options.replace === true ) {
- $group.empty();
- }
- // Hide it ?
- if ( options.message === '' || options.message === null ) {
- $group.hide();
- } else {
- // Actual message addition
- $group.prepend( $( '<p>' ).append( options.message ) ).show();
- $target.slideDown();
- }
- // If the last visible group was just hidden, slide the entire box up
- // Othere wise slideDown (if already visible nothing will happen)
- if ( $target.find( '> *:visible' ).length === 0 ) {
- // to avoid a sudden dissapearance of the last group followed by
- // a slide up of only the outline, show it for a second
- $group.show();
- $target.slideUp();
- $group.hide();
- } else {
- $target.slideDown();
- }
- return $group;
-};
-
-}( jQuery ) );
return true;
},
compareObject: function ( objectA, objectB ) {
+ var prop, type;
// Do a simple check if the types match
if ( typeof objectA === typeof objectB ) {
if ( objectA === objectB ) {
return true;
} else {
- var prop;
// Iterate over each property
for ( prop in objectA ) {
// Check if this property is also present in the other object
if ( prop in objectB ) {
// Compare the types of the properties
- var type = typeof objectA[prop];
+ type = typeof objectA[prop];
if ( type === typeof objectB[prop] ) {
// Recursively check objects inside this one
switch ( type ) {
$.fn.placeholder = function () {
return this.each( function () {
+ var placeholder, $input;
// If the HTML5 placeholder attribute is supported, use it
if ( this.placeholder && 'placeholder' in document.createElement( this.tagName ) ) {
return;
}
- var placeholder = this.getAttribute( 'placeholder' );
- var $input = $(this);
+ placeholder = this.getAttribute( 'placeholder' );
+ $input = $(this);
// Show initially, if empty
if ( this.value === '' || this.value === placeholder ) {
* other constructor. Otherwise "missingTests" will include all methods that
* were not called from that instance.
*/
- var CompletenessTest = function ( masterVariable, ignoreFn ) {
+ function CompletenessTest( masterVariable, ignoreFn ) {
// Keep track in these objects. Keyed by strings with the
// method names (ie. 'my.foo', 'my.bar', etc.) values are boolean true.
});
return this;
- };
+ }
/* Static members */
CompletenessTest.ACTION_INJECT = 500;
/**
- * QUnit v1.9.0 - A JavaScript Unit Testing Framework
+ * QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
- * http://docs.jquery.com/QUnit
+ * http://qunitjs.com
*
- * Copyright (c) 2012 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * or GPL (GPL-LICENSE.txt) licenses.
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
*/
/** Font Family and Sizes */
/** Resets */
-#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
+#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0;
padding: 0;
}
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
+ overflow: hidden;
}
#qunit-userAgent {
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
+#qunit-modulefilter-container {
+ float: right;
+}
/** Tests: Pass/Fail */
/**
- * QUnit v1.9.0 - A JavaScript Unit Testing Framework
+ * QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
- * http://docs.jquery.com/QUnit
+ * http://qunitjs.com
*
- * Copyright (c) 2012 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * or GPL (GPL-LICENSE.txt) licenses.
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
*/
(function( window ) {
fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
+ // Keep a local reference to Date (GH-283)
+ Date = window.Date,
defined = {
setTimeout: typeof window.setTimeout !== "undefined",
sessionStorage: (function() {
// call on start of module test to prepend name to all tests
module: function( name, testEnvironment ) {
config.currentModule = name;
- config.currentModuleTestEnviroment = testEnvironment;
+ config.currentModuleTestEnvironment = testEnvironment;
+ config.modules[name] = true;
},
asyncTest: function( testName, expected, callback ) {
async: async,
callback: callback,
module: config.currentModule,
- moduleTestEnvironment: config.currentModuleTestEnviroment,
+ moduleTestEnvironment: config.currentModuleTestEnvironment,
stack: sourceFromStacktrace( 2 )
});
// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
expect: function( asserts ) {
- config.current.expected = asserts;
+ if (arguments.length === 1) {
+ config.current.expected = asserts;
+ } else {
+ return config.current.expected;
+ }
},
start: function( count ) {
var source,
details = {
+ module: config.current.module,
+ name: config.current.testName,
result: result,
message: msg
};
}
],
+ // Set of all modules.
+ modules: {},
+
// logging callback queues
begin: [],
done: [],
},
// Resets the test setup. Useful for tests that modify the DOM.
- // If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
reset: function() {
- var fixture;
-
- if ( window.jQuery ) {
- jQuery( "#qunit-fixture" ).html( config.fixture );
- } else {
- fixture = id( "qunit-fixture" );
- if ( fixture ) {
- fixture.innerHTML = config.fixture;
- }
+ var fixture = id( "qunit-fixture" );
+ if ( fixture ) {
+ fixture.innerHTML = config.fixture;
}
},
var output, source,
details = {
+ module: config.current.module,
+ name: config.current.testName,
result: result,
message: message,
actual: actual,
var output,
details = {
+ module: config.current.module,
+ name: config.current.testName,
result: false,
message: message
};
runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue
- var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes,
+ var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter,
+ numModules = 0,
+ moduleFilterHtml = "",
urlConfigHtml = "",
oldconfig = extend( {}, config );
urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
}
+ moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined ? "selected" : "" ) + ">< All Modules ></option>";
+ for ( i in config.modules ) {
+ if ( config.modules.hasOwnProperty( i ) ) {
+ numModules += 1;
+ moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>";
+ }
+ }
+ moduleFilterHtml += "</select>";
+
// `userAgent` initialized at top of scope
userAgent = id( "qunit-userAgent" );
if ( userAgent ) {
window.location = QUnit.url( params );
});
toolbar.appendChild( urlConfigCheckboxes );
+
+ if (numModules > 1) {
+ moduleFilter = document.createElement( 'span' );
+ moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
+ moduleFilter.innerHTML = moduleFilterHtml;
+ addEvent( moduleFilter, "change", function() {
+ var selectBox = moduleFilter.getElementsByTagName("select")[0],
+ selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+
+ window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
+ });
+ toolbar.appendChild(moduleFilter);
+ }
}
// `main` initialized at top of scope
}
QUnit.pushFailure( error, filePath + ":" + linerNr );
} else {
- QUnit.test( "global failure", function() {
+ QUnit.test( "global failure", extend( function() {
QUnit.pushFailure( error, filePath + ":" + linerNr );
- });
+ }, { validTest: validTest } ) );
}
return false;
}
}
}
+ // scroll back to top to show results
+ if ( window.scrollTo ) {
+ window.scrollTo(0, 0);
+ }
+
runLoggingCallbacks( "done", QUnit, {
failed: config.stats.bad,
passed: passed,
module = config.module && config.module.toLowerCase(),
fullName = (test.module + ": " + test.testName).toLowerCase();
+ // Internally-generated tests are always valid
+ if ( test.callback && test.callback.validTest === validTest ) {
+ delete test.callback.validTest;
+ return true;
+ }
+
if ( config.testNumber ) {
return test.testNumber === config.testNumber;
}
a.global === b.global &&
// (gmi) ...
a.ignoreCase === b.ignoreCase &&
- a.multiline === b.multiline;
+ a.multiline === b.multiline &&
+ a.sticky === b.sticky;
},
// - skip when the property is a method of an instance (OOP)
$.fn.extend({
focus: ( function ( jqFocus ) {
return function () {
+ var $w, state, result;
if ( arguments.length === 0 ) {
- var $w = $( window );
- var state = {top: $w.scrollTop(), left: $w.scrollLeft()};
- var result = jqFocus.apply( this, arguments );
+ $w = $( window );
+ state = {top: $w.scrollTop(), left: $w.scrollLeft()};
+ result = jqFocus.apply( this, arguments );
window.scrollTo( state.top, state.left );
return result;
}
* in some browsers (IE/Opera)
*/
getSelection: function () {
- var e = this.get( 0 );
- var retval = '';
- if ( $(e).is( ':hidden' ) ) {
+ var retval, range,
+ el = this.get( 0 );
+
+ if ( $(el).is( ':hidden' ) ) {
// Do nothing
+ retval = '';
} else if ( document.selection && document.selection.createRange ) {
- activateElementOnIE( e );
- var range = document.selection.createRange();
+ activateElementOnIE( el );
+ range = document.selection.createRange();
retval = range.text;
- } else if ( e.selectionStart || e.selectionStart === 0 ) {
- retval = e.value.substring( e.selectionStart, e.selectionEnd );
+ } else if ( el.selectionStart || el.selectionStart === 0 ) {
+ retval = el.value.substring( el.selectionStart, el.selectionEnd );
}
+
return retval;
},
/**
encapsulateSelection: function ( options ) {
return this.each( function () {
var selText, scrollTop, insertText,
+ isSample, range, range2, range3, startPos, endPos,
pre = options.pre,
post = options.post;
* Wrap each line of the selected text with pre and post
*/
function doSplitLines( selText, pre, post ) {
- var insertText = '';
- var selTextArr = selText.split( '\n' );
- for ( var i = 0; i < selTextArr.length; i++ ) {
+ var i,
+ insertText = '',
+ selTextArr = selText.split( '\n' );
+ for ( i = 0; i < selTextArr.length; i++ ) {
insertText += pre + selTextArr[i] + post;
if ( i !== selTextArr.length - 1 ) {
insertText += '\n';
return insertText;
}
- var isSample = false;
+ isSample = false;
if ( this.style.display === 'none' ) {
// Do nothing
} else if ( document.selection && document.selection.createRange ) {
selText = $(this).textSelection( 'getSelection' );
scrollTop = this.scrollTop;
- var range = document.selection.createRange();
+ range = document.selection.createRange();
checkSelectedText();
insertText = pre + selText + post;
insertText = doSplitLines( selText, pre, post );
}
if ( options.ownline && range.moveStart ) {
- var range2 = document.selection.createRange();
+ range2 = document.selection.createRange();
range2.collapse();
range2.moveStart( 'character', -1 );
// FIXME: Which check is correct?
insertText = "\n" + insertText;
pre += "\n";
}
- var range3 = document.selection.createRange();
+ range3 = document.selection.createRange();
range3.collapse( false );
range3.moveEnd( 'character', 1 );
if ( range3.text !== "\r" && range3.text !== "\n" && range3.text !== "" ) {
}
selText = $(this).textSelection( 'getSelection' );
- var startPos = this.selectionStart;
- var endPos = this.selectionEnd;
+ startPos = this.selectionStart;
+ endPos = this.selectionEnd;
scrollTop = this.scrollTop;
checkSelectedText();
if ( options.selectionStart !== undefined
// whatever we do later (bug 31847).
activateElementOnIE( e );
- // IE Support
- var preFinished = false;
- var periFinished = false;
- var postFinished = false;
- var preText, rawPreText, periText;
- var rawPeriText, postText, rawPostText;
- // Create range containing text in the selection
- var periRange = document.selection.createRange().duplicate();
- // Create range containing text before the selection
- var preRange = rangeForElementIE( e );
+ var
+ preText, rawPreText, periText,
+ rawPeriText, postText, rawPostText,
+
+ // IE Support
+ preFinished = false,
+ periFinished = false,
+ postFinished = false,
+ // Range containing text in the selection
+ periRange = document.selection.createRange().duplicate(),
+ // Range containing text before the selection
+ preRange,
+ // Range containing text after the selection
+ postRange;
+
+ preRange = rangeForElementIE( e ),
// Move the end where we need it
preRange.setEndPoint( 'EndToStart', periRange );
- // Create range containing text after the selection
- var postRange = rangeForElementIE( e );
+
+ postRange = rangeForElementIE( e );
// Move the start where we need it
postRange.setEndPoint( 'StartToEnd', periRange );
+
// Load the text values we need to compare
preText = rawPreText = preRange.text;
periText = rawPeriText = periRange.text;
postText = rawPostText = postRange.text;
+
/*
* Check each range for trimmed newlines by shrinking the range by 1
* character and seeing if the text property has changed. If it has
*/
setSelection: function ( options ) {
return this.each( function () {
+ var selection, length, newLines;
if ( $(this).is( ':hidden' ) ) {
// Do nothing
} else if ( this.selectionStart || this.selectionStart === 0 ) {
this.selectionEnd = options.end;
}
} else if ( document.body.createTextRange ) {
- var selection = rangeForElementIE( this );
- var length = this.value.length;
+ selection = rangeForElementIE( this );
+ length = this.value.length;
// IE doesn't count \n when computing the offset, so we won't either
- var newLines = this.value.match( /\n/g );
+ newLines = this.value.match( /\n/g );
if ( newLines ) {
length = length - newLines.length;
}
// Silence that error
try {
selection.select();
- } catch( e ) { }
+ } catch ( e ) { }
}
});
},
return ( $.client.profile().platform === 'mac' ? 13 : ( $.client.profile().platform === 'linux' ? 15 : 16 ) ) * row;
}
return this.each(function () {
+ var scroll, range, savedRange, pos, oldScrollTop;
if ( $(this).is( ':hidden' ) ) {
// Do nothing
} else if ( this.selectionStart || this.selectionStart === 0 ) {
// Mozilla
- var scroll = getCaretScrollPosition( this );
+ scroll = getCaretScrollPosition( this );
if ( options.force || scroll < $(this).scrollTop() ||
scroll > $(this).scrollTop() + $(this).height() ) {
$(this).scrollTop( scroll );
* cover that case, we'll force it to act by moving one
* character back and forth.
*/
- var range = document.body.createTextRange();
- var savedRange = document.selection.createRange();
- var pos = $(this).textSelection( 'getCaretPosition' );
- var oldScrollTop = this.scrollTop;
+ range = document.body.createTextRange();
+ savedRange = document.selection.createRange();
+ pos = $(this).textSelection( 'getCaretPosition' );
+ oldScrollTop = this.scrollTop;
range.moveToElementText( this );
range.collapse();
range.move( 'character', pos + 1);
/**
* Additional mw.Api methods to assist with API calls related to categories.
*/
-
-( function( $, mw, undefined ) {
+( function ( mw, $ ) {
$.extend( mw.Api.prototype, {
/**
* @param err {Function} optional callback to run if api error
* @return ajax call object
*/
- isCategory: function( title, success, err ) {
- var params = {
- prop: 'categoryinfo',
- titles: title.toString()
- },
- ok = function( data ) {
- var exists = false;
- if ( data.query && data.query.pages ) {
- $.each( data.query.pages, function( id, page ) {
- if ( page.categoryinfo ) {
- exists = true;
- }
- } );
- }
- success( exists );
- };
+ isCategory: function ( title, success, err ) {
+ var params, ok;
+ params = {
+ prop: 'categoryinfo',
+ titles: title.toString()
+ };
+ ok = function ( data ) {
+ var exists = false;
+ if ( data.query && data.query.pages ) {
+ $.each( data.query.pages, function ( id, page ) {
+ if ( page.categoryinfo ) {
+ exists = true;
+ }
+ } );
+ }
+ success( exists );
+ };
return this.get( params, { ok: ok, err: err } );
},
* @param err {Function} optional callback to run if api error
* @return {jqXHR}
*/
- getCategoriesByPrefix: function( prefix, success, err ) {
-
- // fetch with allpages to only get categories that have a corresponding description page.
- var params = {
+ getCategoriesByPrefix: function ( prefix, success, err ) {
+ // Fetch with allpages to only get categories that have a corresponding description page.
+ var params, ok;
+ params = {
'list': 'allpages',
'apprefix': prefix,
'apnamespace': mw.config.get('wgNamespaceIds').category
};
-
- var ok = function( data ) {
+ ok = function ( data ) {
var texts = [];
if ( data.query && data.query.allpages ) {
- $.each( data.query.allpages, function( i, category ) {
+ $.each( data.query.allpages, function ( i, category ) {
texts.push( new mw.Title( category.title ).getNameText() );
} );
}
* @param async {Boolean} optional asynchronousness (default = true = async)
* @return {jqXHR}
*/
- getCategories: function( title, success, err, async ) {
+ getCategories: function ( title, success, err, async ) {
var params, ok;
params = {
prop: 'categories',
if ( async === undefined ) {
async = true;
}
- ok = function( data ) {
+ ok = function ( data ) {
var ret = false;
if ( data.query && data.query.pages ) {
- $.each( data.query.pages, function( id, page ) {
+ $.each( data.query.pages, function ( id, page ) {
if ( page.categories ) {
if ( typeof ret !== 'object' ) {
ret = [];
}
- $.each( page.categories, function( i, cat ) {
+ $.each( page.categories, function ( i, cat ) {
ret.push( new mw.Title( cat.title ) );
} );
}
} );
-} )( jQuery, mediaWiki );
+}( mediaWiki, jQuery ) );
/**
* Additional mw.Api methods to assist with API calls related to editing wiki pages.
*/
-
-( function( $, mw, undefined ) {
+( function ( mw, $ ) {
// Cache token so we don't have to keep fetching new ones for every single request.
var cachedToken = null;
* @param err {Function} [optional] error callback
* @return {jqXHR}
*/
- postWithEditToken: function( params, ok, err ) {
- var api = this, useTokenToPost, getTokenIfBad;
+ postWithEditToken: function ( params, ok, err ) {
+ var useTokenToPost, getTokenIfBad,
+ api = this;
if ( cachedToken === null ) {
// We don't have a valid cached token, so get a fresh one and try posting.
// We do not trap any 'badtoken' or 'notoken' errors, because we don't want
// an infinite loop. If this fresh token is bad, something else is very wrong.
- useTokenToPost = function( token ) {
+ useTokenToPost = function ( token ) {
params.token = token;
api.post( params, ok, err );
};
// We do have a token, but it might be expired. So if it is 'bad' then
// start over with a new token.
params.token = cachedToken;
- getTokenIfBad = function( code, result ) {
+ getTokenIfBad = function ( code, result ) {
if ( code === 'badtoken' ) {
- cachedToken = null; // force a new token
+ // force a new token, clear any old one
+ cachedToken = null;
api.postWithEditToken( params, ok, err );
} else {
err( code, result );
* @param err {Function} error callback
* @return {jqXHR}
*/
- getEditToken: function( tokenCallback, err ) {
+ getEditToken: function ( tokenCallback, err ) {
var parameters = {
action: 'tokens',
type: 'edit'
},
- ok = function( data ) {
+ ok = function ( data ) {
var token;
// If token type is not available for this user,
// key 'edittoken' is missing or can contain Boolean false
* @param err {Function} error handler
* @return {jqXHR}
*/
- newSection: function( title, header, message, ok, err ) {
+ newSection: function ( title, header, message, ok, err ) {
var params = {
action: 'edit',
section: 'new',
} );
-} )( jQuery, mediaWiki );
+}( mediaWiki, jQuery ) );
/**
* mw.Api objects represent the API of a particular MediaWiki server.
*/
-( function( $, mw, undefined ) {
+( function ( mw, $ ) {
/**
* @var defaultOptions {Object}
* @param options {Object} See defaultOptions documentation above. Ajax options can also be
* overridden for each individual request to jQuery.ajax() later on.
*/
- mw.Api = function( options ) {
+ mw.Api = function ( options ) {
if ( options === undefined ) {
options = {};
* @param {Object|Function} [optional] ajax options
* @return {jQuery.Promise}
*/
- get: function( parameters, ajaxOptions ) {
+ get: function ( parameters, ajaxOptions ) {
ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
ajaxOptions.type = 'GET';
return this.ajax( parameters, ajaxOptions );
* @param {Object|Function} [optional] ajax options
* @return {jQuery.Promise}
*/
- post: function( parameters, ajaxOptions ) {
+ post: function ( parameters, ajaxOptions ) {
ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
ajaxOptions.type = 'POST';
return this.ajax( parameters, ajaxOptions );
* - done: API response data as first argument
* - fail: errorcode as first arg, details (string or object) as second arg.
*/
- ajax: function( parameters, ajaxOptions ) {
+ ajax: function ( parameters, ajaxOptions ) {
var token,
apiDeferred = $.Deferred();
'exists'
];
-})( jQuery, mediaWiki );
+}( mediaWiki, jQuery ) );
* @param err {Function} [optional] deprecated (error callback)
* @return {jQuery.Promise}
*/
- parse: function( wikiText, ok, err ) {
+ parse: function ( wikiText, ok, err ) {
var apiDeferred = $.Deferred();
// Backwards compatibility (< MW 1.20)
}
} );
-} )( mediaWiki, jQuery );
+}( mediaWiki, jQuery ) );
* Additional mw.Api methods to assist with API calls to the API module of the TitleBlacklist extension.
*/
-( function( $, mw, undefined ) {
+( function ( mw, $ ) {
$.extend( mw.Api.prototype, {
/**
* @param err {Function} optional callback to run if api error
* @return {jqXHR}
*/
- isBlacklisted: function( title, success, err ) {
+ isBlacklisted: function ( title, success, err ) {
var params = {
action: 'titleblacklist',
tbaction: 'create',
tbtitle: title.toString()
},
- ok = function( data ) {
+ ok = function ( data ) {
var result;
// this fails open (if nothing valid is returned by the api, allows the title)
}
} );
-} )( jQuery, mediaWiki );
+
+}( mediaWiki, jQuery ) );
* Additional mw.Api methods to assist with (un)watching wiki pages.
* @since 1.19
*/
-( function( $, mw ) {
+( function ( mw, $ ) {
/**
* @context {mw.Api}
} );
-} )( jQuery, mediaWiki );
+}( mediaWiki, jQuery ) );
otherAction = action === 'watch' ? 'unwatch' : 'watch';
$li = $link.closest( 'li' );
- mw.util.jsMessage( watchResponse.message, 'ajaxwatch' );
+ mw.notify( $.parseHTML( watchResponse.message ), { tag: 'watch-self' } );
// Set link to opposite
updateWatchLink( $link, otherAction );
},
// Error
function () {
- var cleanTitle, html, link;
+ var cleanTitle, msg, link;
// Reset link to non-loading mode
updateWatchLink( $link, action );
title: cleanTitle
}, cleanTitle
);
- html = mw.msg( 'watcherrortext', link );
+ msg = mw.messsage( 'watcherrortext', link );
// Report to user about the error
- mw.util.jsMessage( html, 'ajaxwatch' );
+ mw.notify( msg, { tag: 'watch-self' } );
}
);
}
var
+ /**
+ * Public methods (defined later)
+ */
+ fn,
+
/**
* Strip some illegal chars: control chars, colon, less than, greater than,
* brackets, braces, pipe, whitespace and normal spaces. This still leaves some insanity
/* Public methods */
- var fn = {
+ fn = {
constructor: Title,
/**
* Constructs the HTML for the debugging toolbar
*/
buildHtml: function () {
- var $container, $bits, panes, id;
+ var $container, $bits, panes, id, gitInfo;
$container = $( '<div id="mw-debug-toolbar" class="mw-debug"></div>' );
* @return {jQuery}
*/
function bitDiv( id ) {
- return $( '<div>' ).attr({
+ return $( '<div>' ).prop({
id: 'mw-debug-' + id,
- 'class': 'mw-debug-bit'
+ className: 'mw-debug-bit'
})
.appendTo( $bits );
}
*/
function paneLabel( id, text ) {
return $( '<a>' )
- .attr({
- 'class': 'mw-debug-panelabel',
+ .prop({
+ className: 'mw-debug-panelabel',
href: '#mw-debug-pane-' + id
})
.text( text );
* @return {jQuery}
*/
function paneTriggerBitDiv( id, text, count ) {
- if( count ) {
+ if ( count ) {
text = text + ' (' + count + ')';
}
- return $( '<div>' ).attr({
+ return $( '<div>' ).prop({
id: 'mw-debug-' + id,
- 'class': 'mw-debug-bit mw-debug-panelink'
+ className: 'mw-debug-bit mw-debug-panelink'
})
.append( paneLabel( id, text ) )
.appendTo( $bits );
paneTriggerBitDiv( 'includes', 'PHP includes', this.data.includes.length );
- var gitInfo = '';
+ gitInfo = '';
if ( this.data.gitRevision !== false ) {
gitInfo = '(' + this.data.gitRevision.substring( 0, 7 ) + ')';
if ( this.data.gitViewUrl !== false ) {
- gitInfo = $( '<a>' ).attr( 'href', this.data.gitViewUrl ).text( gitInfo );
+ gitInfo = $( '<a>' )
+ .attr( 'href', this.data.gitViewUrl )
+ .text( gitInfo );
}
}
bitDiv( 'mwversion' )
- .append( $( '<a href="//www.mediawiki.org/"></a>' ).text( 'MediaWiki' ) )
- .append( ': ' + this.data.mwVersion + ' ' )
+ .append( $( '<a href="//www.mediawiki.org/">MediaWiki</a>' ) )
+ .append( document.createTextNode( ': ' + this.data.mwVersion + ' ' ) )
.append( gitInfo );
if ( this.data.gitBranch !== false ) {
}
$( '<div>' )
- .attr({
- 'class': 'mw-debug-pane',
+ .prop({
+ className: 'mw-debug-pane',
id: 'mw-debug-pane-' + id
})
.append( panes[id] )
$table = $( '<table id="mw-debug-console">' );
- $('<colgroup>').css( 'width', /*padding=*/20 + ( 10 * /*fontSize*/11 ) ).appendTo( $table );
- $('<colgroup>').appendTo( $table );
- $('<colgroup>').css( 'width', 350 ).appendTo( $table );
+ $( '<colgroup>' ).css( 'width', /* padding = */ 20 + ( 10 * /* fontSize = */ 11 ) ).appendTo( $table );
+ $( '<colgroup>' ).appendTo( $table );
+ $( '<colgroup>' ).css( 'width', 350 ).appendTo( $table );
entryTypeText = function( entryType ) {
$( '<tr>' )
.append( $( '<td>' )
.text( entry.typeText )
- .attr( 'class', 'mw-debug-console-' + entry.type )
+ .addClass( 'mw-debug-console-' + entry.type )
)
.append( $( '<td>' ).html( entry.msg ) )
.append( $( '<td>' ).text( entry.caller ) )
$table = $( '<table id="mw-debug-querylist"></table>' );
$( '<tr>' )
- .append( $('<th>#</th>').css( 'width', '4em' ) )
- .append( $('<th>SQL</th>') )
- .append( $('<th>Time</th>').css( 'width', '8em' ) )
- .append( $('<th>Call</th>').css( 'width', '18em' ) )
+ .append( $( '<th>#</th>' ).css( 'width', '4em' ) )
+ .append( $( '<th>SQL</th>' ) )
+ .append( $( '<th>Time</th>' ).css( 'width', '8em' ) )
+ .append( $( '<th>Call</th>' ).css( 'width', '18em' ) )
.appendTo( $table );
for ( i = 0, length = this.data.queries.length; i < length; i += 1 ) {
for ( i = 0, length = this.data.debugLog.length; i < length; i += 1 ) {
line = this.data.debugLog[i];
$( '<li>' )
- .html( mw.html.escape( line ).replace( /\n/g, "<br />\n" ) )
+ .html( mw.html.escape( line ).replace( /\n/g, '<br />\n' ) )
.appendTo( $list );
}
// If there is no console, use our own log box
mw.loader.using( 'jquery.footHovzer', function () {
- var d = new Date(),
+ var hovzer,
+ d = new Date(),
// Create HH:MM:SS.MIL timestamp
time = ( d.getHours() < 10 ? '0' + d.getHours() : d.getHours() ) +
':' + ( d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes() ) +
backgroundColor: 'white',
borderTop: 'solid 2px #ADADAD'
} );
- var hovzer = $.getFootHovzer();
+ hovzer = $.getFootHovzer();
hovzer.$.append( $log );
hovzer.update();
}
--- /dev/null
+/**
+ * Stylesheet for mediawiki.notification module
+ */
+
+#mw-notification-area {
+ position: absolute;
+ top: 1em;
+ right: 1em;
+ width: 20em;
+ line-height: 1.35;
+ z-index: 10000;
+}
+
+.mw-notification {
+ padding: 0.25em 1em;
+ margin-bottom: 0.5em;
+ border: solid 1px #ddd;
+ background-color: #fcfcfc;
+ /* Message hides on-click */
+ /* See also mediawiki.notification.js */
+ cursor: pointer;
+}
+
+.mw-notification-title {
+ font-weight: bold;
+}
--- /dev/null
+/**
+ * Implements mediaWiki.notification library
+ */
+( function ( mw, $ ) {
+ 'use strict';
+
+ var isPageReady = false,
+ isInitialized = false,
+ preReadyNotifQueue = [],
+ /**
+ * @var {jQuery}
+ * The #mw-notification-area div that all notifications are contained inside.
+ */
+ $area = null;
+
+ /**
+ * Creates a Notification object for 1 message.
+ * Does not insert anything into the document (see .start()).
+ *
+ * @constructor
+ * @see mw.notification.notify
+ */
+ function Notification( message, options ) {
+ var $notification, $notificationTitle, $notificationContent;
+
+ $notification = $( '<div class="mw-notification"></div>' )
+ .data( 'mw.notification', this )
+ .addClass( options.autoHide ? 'mw-notification-autohide' : 'mw-notification-noautohide' );
+
+ if ( options.tag ) {
+ // Sanitize options.tag before it is used by any code. (Including Notification class methods)
+ options.tag = options.tag.replace( /[ _\-]+/g, '-' ).replace( /[^\-a-z0-9]+/ig, '' );
+ if ( options.tag ) {
+ $notification.addClass( 'mw-notification-tag-' + options.tag );
+ } else {
+ delete options.tag;
+ }
+ }
+
+ if ( options.title ) {
+ $notificationTitle = $( '<div class="mw-notification-title"></div>' )
+ .text( options.title )
+ .appendTo( $notification );
+ }
+
+ $notificationContent = $( '<div class="mw-notification-content"></div>' );
+
+ if ( typeof message === 'object' ) {
+ // Handle mw.Message objects separately from DOM nodes and jQuery objects
+ if ( message instanceof mw.Message ) {
+ $notificationContent.html( message.parse() );
+ } else {
+ $notificationContent.append( message );
+ }
+ } else {
+ $notificationContent.text( message );
+ }
+
+ $notificationContent.appendTo( $notification );
+
+ // Private state parameters, meant for internal use only
+ // isOpen: Set to true after .start() is called to avoid double calls.
+ // Set back to false after .close() to avoid duplicating the close animation.
+ // isPaused: false after .resume(), true after .pause(). Avoids duplicating or breaking the hide timeouts.
+ // Set to true initially so .start() can call .resume().
+ // message: The message passed to the notification. Unused now but may be used in the future
+ // to stop replacement of a tagged notification with another notification using the same message.
+ // options: The options passed to the notification with a little sanitization. Used by various methods.
+ // $notification: jQuery object containing the notification DOM node.
+ this.isOpen = false;
+ this.isPaused = true;
+ this.message = message;
+ this.options = options;
+ this.$notification = $notification;
+ }
+
+ /**
+ * Start the notification.
+ * This inserts it into the page, closes any matching tagged notifications,
+ * handles the fadeIn animations and repacement transitions, and starts autoHide timers.
+ */
+ Notification.prototype.start = function () {
+ var
+ // Local references
+ $notification, options,
+ // Original opacity so that we can animate back to it later
+ opacity,
+ // Other notification elements matching the same tag
+ $tagMatches,
+ outerHeight,
+ placeholderHeight;
+
+ if ( this.isOpen ) {
+ return;
+ }
+
+ this.isOpen = true;
+
+ options = this.options;
+ $notification = this.$notification;
+
+ opacity = this.$notification.css( 'opacity' );
+
+ // Set the opacity to 0 so we can fade in later.
+ $notification.css( 'opacity', 0 );
+
+ if ( options.tag ) {
+ // Check to see if there are any tagged notifications with the same tag as the new one
+ $tagMatches = $area.find( '.mw-notification-tag-' + options.tag );
+ }
+
+ // If we found a tagged notification use the replacement pattern instead of the new
+ // notification fade-in pattern.
+ if ( options.tag && $tagMatches.length ) {
+
+ // Iterate over the tag matches to find the outerHeight we should use
+ // for the placeholder.
+ outerHeight = 0;
+ $tagMatches.each( function () {
+ var notif = $( this ).data( 'mw.notification' );
+ if ( notif ) {
+ // Use the notification's height + padding + border + margins
+ // as the placeholder height.
+ outerHeight = notif.$notification.outerHeight( true );
+ if ( notif.$replacementPlaceholder ) {
+ // Grab the height of a placeholder that has not finished animating.
+ placeholderHeight = notif.$replacementPlaceholder.height();
+ // Remove any placeholders added by a previous tagged
+ // notification that was in the middle of replacing another.
+ // This also makes sure that we only grab the placeholderHeight
+ // for the most recent notification.
+ notif.$replacementPlaceholder.remove();
+ delete notif.$replacementPlaceholder;
+ }
+ // Close the previous tagged notification
+ // Since we're replacing it do this with a fast speed and don't output a placeholder
+ // since we're taking care of that transition ourselves.
+ notif.close( { speed: 'fast', placeholder: false } );
+ }
+ } );
+ if ( placeholderHeight !== undefined ) {
+ // If the other tagged notification was in the middle of replacing another
+ // tagged notification, continue from the placeholder's height instead of
+ // using the outerHeight of the notification.
+ outerHeight = placeholderHeight;
+ }
+
+ $notification
+ // Insert the new notification before the tagged notification(s)
+ .insertBefore( $tagMatches.first() )
+ .css( {
+ // Use an absolute position so that we can use a placeholder to gracefully push other notifications
+ // into the right spot.
+ position: 'absolute',
+ width: $notification.width()
+ } )
+ // Fade-in the notification
+ .animate( { opacity: opacity },
+ {
+ duration: 'slow',
+ complete: function () {
+ // After we've faded in clear the opacity and let css take over
+ $( this ).css( { opacity: '' } );
+ }
+ } );
+
+ // Create a clear placeholder we can use to make the notifications around the notification that is being
+ // replaced expand or contract gracefully to fit the height of the new notification.
+ var self = this;
+ self.$replacementPlaceholder = $( '<div>' )
+ // Set the height to the space the previous notification or placeholder took
+ .css( 'height', outerHeight )
+ // Make sure that this placeholder is at the very end of this tagged notification group
+ .insertAfter( $tagMatches.eq( -1 ) )
+ // Animate the placeholder height to the space that this new notification will take up
+ .animate( { height: $notification.outerHeight( true ) },
+ {
+ // Do space animations fast
+ speed: 'fast',
+ complete: function () {
+ // Reset the notification position after we've finished the space animation
+ // However do not do it if the placeholder was removed because another tagged
+ // notification went and closed this one.
+ if ( self.$replacementPlaceholder ) {
+ $notification.css( 'position', '' );
+ }
+ // Finally, remove the placeholder from the DOM
+ $( this ).remove();
+ }
+ } );
+ } else {
+ // Append to the notification area and fade in to the original opacity.
+ $notification
+ .appendTo( $area )
+ .animate( { opacity: opacity },
+ {
+ duration: 'fast',
+ complete: function () {
+ // After we've faded in clear the opacity and let css take over
+ $( this ).css( 'opacity', '' );
+ }
+ }
+ );
+ }
+
+ // By default a notification is paused.
+ // If this notification is within the first {autoHideLimit} notifications then
+ // start the auto-hide timer as soon as it's created.
+ var autohideCount = $area.find( '.mw-notification-autohide' ).length;
+ if ( autohideCount <= notification.autoHideLimit ) {
+ this.resume();
+ }
+ };
+
+ /**
+ * Pause any running auto-hide timer for this notification
+ */
+ Notification.prototype.pause = function () {
+ if ( this.isPaused ) {
+ return;
+ }
+ this.isPaused = true;
+
+ if ( this.timeout ) {
+ clearTimeout( this.timeout );
+ delete this.timeout;
+ }
+ };
+
+ /**
+ * Start autoHide timer if not already started.
+ * Does nothing if autoHide is disabled.
+ * Either to resume from pause or to make the first start.
+ */
+ Notification.prototype.resume = function () {
+ var notif = this;
+ if ( !notif.isPaused ) {
+ return;
+ }
+ // Start any autoHide timeouts
+ if ( notif.options.autoHide ) {
+ notif.isPaused = false;
+ notif.timeout = setTimeout( function () {
+ // Already finished, so don't try to re-clear it
+ delete notif.timeout;
+ notif.close();
+ }, notification.autoHideSeconds * 1000 );
+ }
+ };
+
+ /**
+ * Close/hide the notification.
+ *
+ * @param {Object} options An object containing options for the closing of the notification.
+ * These are typically only used internally.
+ * - speed: Use a close speed different than the default 'slow'.
+ * - placeholder: Set to false to disable the placeholder transition.
+ */
+ Notification.prototype.close = function ( options ) {
+ if ( !this.isOpen ) {
+ return;
+ }
+ this.isOpen = false;
+ // Clear any remaining timeout on close
+ this.pause();
+
+ options = $.extend( {
+ speed: 'slow',
+ placeholder: true
+ }, options );
+
+ // Remove the mw-notification-autohide class from the notification to avoid
+ // having a half-closed notification counted as a notification to resume
+ // when handling {autoHideLimit}.
+ this.$notification.removeClass( 'mw-notification-autohide' );
+
+ // Now that a notification is being closed. Start auto-hide timers for any
+ // notification that has now become one of the first {autoHideLimit} notifications.
+ notification.resume();
+
+ this.$notification
+ .css( {
+ // Don't trigger any mouse events while fading out, just in case the cursor
+ // happens to be right above us when we transition upwards.
+ pointerEvents: 'none',
+ // Set an absolute position so we can move upwards in the animation.
+ // Notification replacement doesn't look right unless we use an animation like this.
+ position: 'absolute',
+ // We must fix the width to avoid it shrinking horizontally.
+ width: this.$notification.width()
+ } )
+ // Fix the top/left position to the current computed position from which we
+ // can animate upwards.
+ .css( this.$notification.position() )
+ // Animate opacity and top to create fade upwards animation for notification closing
+ .animate( {
+ opacity: 0,
+ top: '-=35'
+ }, {
+ duration: options.speed,
+ complete: function () {
+ // Remove the notification
+ $( this ).remove();
+ if ( options.placeholder ) {
+ // Use a fast slide up animation after closing to make it look like the notifications
+ // below slide up into place when the notification disappears
+ $placeholder.slideUp( 'fast', function () {
+ // Remove the placeholder
+ $( this ).remove();
+ } );
+ }
+ }
+ } );
+
+ if ( options.placeholder ) {
+ // Insert a placeholder with a height equal to the height of the
+ // notification plus it's vertical margins in place of the notification
+ var $placeholder = $( '<div>' )
+ .css( 'height', this.$notification.outerHeight( true ) )
+ .insertBefore( this.$notification );
+ }
+ };
+
+ /**
+ * Helper function, take a list of notification divs and call
+ * a function on the Notification instance attached to them
+ *
+ * @param {jQuery} $notifications A jQuery object containing notification divs
+ * @param {string} fn The name of the function to call on the Notification instance
+ */
+ function callEachNotification( $notifications, fn ) {
+ $notifications.each( function () {
+ var notif = $( this ).data( 'mw.notification' );
+ if ( notif ) {
+ notif[fn]();
+ }
+ } );
+ }
+
+ /**
+ * Initialisation
+ * (don't call before document ready)
+ */
+ function init() {
+ if ( !isInitialized ) {
+ isInitialized = true;
+ $area = $( '<div id="mw-notification-area"></div>' )
+ // Pause auto-hide timers when the mouse is in the notification area.
+ .on( {
+ mouseenter: notification.pause,
+ mouseleave: notification.resume
+ } )
+ // When clicking on a notification close it.
+ .on( 'click', '.mw-notification', function () {
+ var notif = $( this ).data( 'mw.notification' );
+ if ( notif ) {
+ notif.close();
+ }
+ } )
+ // Stop click events from <a> tags from propogating to prevent clicking.
+ // on links from hiding a notification.
+ .on( 'click', 'a', function ( e ) {
+ e.stopPropagation();
+ } );
+
+ // Prepend the notification area to the content area and save it's object.
+ mw.util.$content.prepend( $area );
+ }
+ }
+
+ var notification = {
+ /**
+ * Pause auto-hide timers for all notifications.
+ * Notifications will not auto-hide until resume is called.
+ */
+ pause: function () {
+ callEachNotification(
+ $area.children( '.mw-notification' ),
+ 'pause'
+ );
+ },
+
+ /**
+ * Resume any paused auto-hide timers from the beginning.
+ * Only the first {autoHideLimit} timers will be resumed.
+ */
+ resume: function () {
+ callEachNotification(
+ // Only call resume on the first {autoHideLimit} notifications.
+ // Exclude noautohide notifications to avoid bugs where {autoHideLimit}
+ // { autoHide: false } notifications are at the start preventing any
+ // auto-hide notifications from being autohidden.
+ $area.children( '.mw-notification-autohide' ).slice( 0, notification.autoHideLimit ),
+ 'resume'
+ );
+ },
+
+ /**
+ * Display a notification message to the user.
+ *
+ * @param {mixed} message The DOM-element, jQuery object, mw.Message instance,
+ * or plaintext string to be used as the message.
+ * @param {Object} options The options to use for the notification.
+ * See mw.notification.defaults for details.
+ */
+ notify: function ( message, options ) {
+ var notif;
+ options = $.extend( {}, notification.defaults, options );
+
+ notif = new Notification( message, options );
+
+ if ( isPageReady ) {
+ notif.start();
+ } else {
+ preReadyNotifQueue.push( notif );
+ }
+ },
+
+ /**
+ * @var {Object}
+ * The defaults for mw.notification.notify's options parameter
+ * autoHide:
+ * A boolean indicating whether the notifification should automatically
+ * be hidden after shown. Or if it should persist.
+ *
+ * tag:
+ * An optional string. When a notification is tagged only one message
+ * with that tag will be displayed. Trying to display a new notification
+ * with the same tag as one already being displayed will cause the other
+ * notification to be closed and this new notification to open up inside
+ * the same place as the previous notification.
+ *
+ * title:
+ * An optional title for the notification. Will be displayed above the
+ * content. Usually in bold.
+ */
+ defaults: {
+ autoHide: true,
+ tag: false,
+ title: undefined
+ },
+
+ /**
+ * @var {number}
+ * Number of seconds to wait before auto-hiding notifications.
+ */
+ autoHideSeconds: 5,
+
+ /**
+ * @var {number}
+ * Maximum number of notifications to count down auto-hide timers for.
+ * Only the first {autoHideLimit} notifications being displayed will
+ * auto-hide. Any notifications further down in the list will only start
+ * counting down to auto-hide after the first few messages have closed.
+ *
+ * This basically represents the number of notifications the user should
+ * be able to process in {autoHideSeconds} time.
+ */
+ autoHideLimit: 3
+ };
+
+ $( function () {
+ var notif;
+
+ init();
+
+ // Handle pre-ready queue.
+ isPageReady = true;
+ while ( preReadyNotifQueue.length ) {
+ notif = preReadyNotifQueue.shift();
+ notif.start();
+ }
+ } );
+
+ mw.notification = notification;
+
+}( mediaWiki, jQuery ) );
--- /dev/null
+/**
+ * Implements mediaWiki.notify function
+ */
+( function ( mw ) {
+ 'use strict';
+
+ /**
+ * @see mw.notification.notify
+ */
+ mw.notify = function ( message, options ) {
+ // Don't bother loading the whole notification system if we never use it.
+ mw.loader.using( 'mediawiki.notification', function () {
+ // Don't bother calling mw.loader.using a second time after we've already loaded mw.notification.
+ mw.notify = mw.notification.notify;
+ // Call notify with the notification the user requested of us.
+ mw.notify( message, options );
+ } );
+ };
+
+}( mediaWiki ) );
\ No newline at end of file
* User object
*/
function User( options, tokens ) {
+ var user, callbacks;
/* Private Members */
- var that = this;
- var callbacks = {};
+ user = this;
+ callbacks = {};
/**
* Gets the current user's groups or rights.
* @return String: Random set of 32 alpha-numeric characters
*/
function generateId() {
- var id = '';
- var seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
- for ( var i = 0, r; i < 32; i++ ) {
+ var i, r,
+ id = '',
+ seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+ for ( i = 0; i < 32; i++ ) {
r = Math.floor( Math.random() * seed.length );
id += seed.substring( r, r + 1 );
}
* @return Boolean
*/
this.isAnon = function () {
- return that.getName() === null;
+ return user.getName() === null;
};
/**
* @deprecated since 1.20 use mw.user.isAnon() instead
*/
this.anonymous = function () {
- return that.isAnon();
+ return user.isAnon();
};
/**
* @return String: User name or random session ID
*/
this.id = function() {
- var name = that.getName();
+ var id,
+ name = user.getName();
if ( name ) {
return name;
}
- var id = $.cookie( 'mediaWiki.user.id' );
+ id = $.cookie( 'mediaWiki.user.id' );
if ( typeof id === 'undefined' || id === null ) {
id = generateId();
}
* } );
*/
this.bucket = function ( key, options ) {
+ var cookie, parts, version, bucket,
+ range, k, rand, total;
+
options = $.extend( {
- 'buckets': {},
- 'version': 0,
- 'tracked': false,
- 'expires': 30
+ buckets: {},
+ version: 0,
+ tracked: false,
+ expires: 30
}, options || {} );
- var cookie = $.cookie( 'mediaWiki.user.bucket:' + key );
- var bucket = null;
- var version = 0;
+
+ cookie = $.cookie( 'mediaWiki.user.bucket:' + key );
+
// Bucket information is stored as 2 integers, together as version:bucket like: "1:2"
if ( typeof cookie === 'string' && cookie.length > 2 && cookie.indexOf( ':' ) > 0 ) {
- var parts = cookie.split( ':' );
+ parts = cookie.split( ':' );
if ( parts.length > 1 && Number( parts[0] ) === options.version ) {
version = Number( parts[0] );
bucket = String( parts[1] );
}
}
- if ( bucket === null ) {
+ if ( bucket === undefined ) {
if ( !$.isPlainObject( options.buckets ) ) {
throw 'Invalid buckets error. Object expected for options.buckets.';
}
version = Number( options.version );
// Find range
- var range = 0, k;
+ range = 0;
for ( k in options.buckets ) {
range += options.buckets[k];
}
// Select random value within range
- var rand = Math.random() * range;
+ rand = Math.random() * range;
// Determine which bucket the value landed in
- var total = 0;
+ total = 0;
for ( k in options.buckets ) {
bucket = k;
total += options.buckets[k];
'use strict';
// Local cache and alias
- var hideMessageTimeout,
- messageBoxEvents = false,
- util = {
+ var util = {
/**
* Initialisation
init: function () {
var profile, $tocTitle, $tocToggleLink, hideTocCookie;
- /* Set up $.messageBox */
- $.messageBoxNew( {
- id: 'mw-js-message',
- parent: '#content'
- } );
-
/* Set tooltipAccessKeyPrefix */
profile = $.client.profile();
&& profile.name === 'safari'
&& profile.layoutVersion > 526 ) {
util.tooltipAccessKeyPrefix = 'ctrl-alt-';
-
+ // Firefox 14+ on Mac
+ } else if ( profile.platform === 'mac'
+ && profile.name === 'firefox'
+ && profile.versionNumber >= 14 ) {
+ util.tooltipAccessKeyPrefix = 'ctrl-option-';
// Safari/Konqueror on any platform, or any browser on Mac
// (but not Safari on Windows)
} else if ( !( profile.platform === 'win' && profile.name === 'safari' )
}
/* Fill $content var */
- if ( $( '#bodyContent' ).length ) {
- // Vector, Monobook, Chick etc.
- util.$content = $( '#bodyContent' );
-
- } else if ( $( '#mw_contentholder' ).length ) {
- // Modern
- util.$content = $( '#mw_contentholder' );
+ util.$content = ( function () {
+ var $content, selectors = [
+ // The preferred standard for setting $content (class="mw-body")
+ // You may also use (class="mw-body mw-body-primary") if you use
+ // mw-body in multiple locations.
+ // Or class="mw-body-primary" if you want $content to be deeper
+ // in the dom than mw-body
+ '.mw-body-primary',
+ '.mw-body',
+
+ /* Legacy fallbacks for setting the content */
+ // Vector, Monobook, Chick, etc... based skins
+ '#bodyContent',
+
+ // Modern based skins
+ '#mw_contentholder',
+
+ // Standard, CologneBlue
+ '#article',
+
+ // #content is present on almost all if not all skins. Most skins (the above cases)
+ // have #content too, but as an outer wrapper instead of the article text container.
+ // The skins that don't have an outer wrapper do have #content for everything
+ // so it's a good fallback
+ '#content',
+
+ // If nothing better is found fall back to our bodytext div that is guaranteed to be here
+ '#mw-content-text',
+
+ // Should never happen... well, it could if someone is not finished writing a skin and has
+ // not inserted bodytext yet. But in any case <body> should always exist
+ 'body'
+ ];
+ for ( var i = 0, l = selectors.length; i < l; i++ ) {
+ $content = $( selectors[i] ).first();
+ if ( $content.length ) {
+ return $content;
+ }
+ }
- } else if ( $( '#article' ).length ) {
- // Standard, CologneBlue
- util.$content = $( '#article' );
-
- } else {
- // #content is present on almost all if not all skins. Most skins (the above cases)
- // have #content too, but as an outer wrapper instead of the article text container.
- // The skins that don't have an outer wrapper do have #content for everything
- // so it's a good fallback
- util.$content = $( '#content' );
- }
+ // Make sure we don't unset util.$content if it was preset and we don't find anything
+ return util.$content;
+ } )();
// Table of contents toggle
$tocTitle = $( '#toctitle' );
/*
* @var jQuery
- * A jQuery object that refers to the page-content element
+ * A jQuery object that refers to the content area element
* Populated by init().
*/
$content: null,
* Calling with no arguments, with an empty string or null will hide the message
*
* @param message {mixed} The DOM-element, jQuery object or HTML-string to be put inside the message box.
- * @param className {String} Used in adding a class; should be different for each call
* to allow CSS/JS to hide different boxes. null = no class used.
- * @return {Boolean} True on success, false on failure.
+ * @depreceated Use mw.notify
*/
- jsMessage: function ( message, className ) {
- var $messageDiv = $( '#mw-js-message' );
-
+ jsMessage: function ( message ) {
if ( !arguments.length || message === '' || message === null ) {
- $messageDiv.empty().hide();
- stopHideMessageTimeout();
- return true; // Emptying and hiding message is intended behaviour, return true
- } else {
- // We special-case skin structures provided by the software. Skins that
- // choose to abandon or significantly modify our formatting can just define
- // an mw-js-message div to start with.
- if ( !$messageDiv.length ) {
- $messageDiv = $( '<div id="mw-js-message"></div>' );
- if ( util.$content.parent().length ) {
- util.$content.parent().prepend( $messageDiv );
- } else {
- return false;
- }
- }
-
- if ( !messageBoxEvents ) {
- messageBoxEvents = true;
- $messageDiv
- .on( {
- 'mouseenter': stopHideMessageTimeout,
- 'mouseleave': startHideMessageTimeout,
- 'click': hideMessage
- } )
- .on( 'click', 'a', function ( e ) {
- // Prevent links, even those that don't exist yet, from causing the
- // message box to close when clicked
- e.stopPropagation();
- } );
- }
-
- if ( className ) {
- $messageDiv.prop( 'className', 'mw-js-message-' + className );
- }
-
- if ( typeof message === 'object' ) {
- $messageDiv.empty();
- $messageDiv.append( message );
- } else {
- $messageDiv.html( message );
- }
-
- $messageDiv.slideDown();
- startHideMessageTimeout();
return true;
}
+ if ( typeof message !== 'object' ) {
+ message = $.parseHTML( message );
+ }
+ mw.notify( message, { autoHide: true, tag: 'legacy' } );
+ return true;
},
/**
}
};
- // Message auto-hide helpers
- function hideMessage() {
- $( '#mw-js-message' ).fadeOut( 'slow' );
- }
- function stopHideMessageTimeout() {
- clearTimeout( hideMessageTimeout );
- }
- function startHideMessageTimeout() {
- clearTimeout( hideMessageTimeout );
- hideMessageTimeout = setTimeout( hideMessage, 5000 );
- }
-
mw.util = util;
}( mediaWiki, jQuery ) );
<!-- contentholder does nothing by default, but it allows users to style the text inside
the content area without affecting the meaning of 'em' in #mw_content, which is used
for the margins -->
- <div id="mw_contentholder">
+ <div id="mw_contentholder" class="mw-body">
<div class='mw-topboxes'>
<div id="mw-js-message" style="display:none;"<?php $this->html('userlangattributes')?>></div>
<div class="mw-topbox" id="siteSub"><?php $this->msg('tagline') ?></div>
$this->html( 'headelement' );
?><div id="globalWrapper">
-<div id="column-content"><div id="content">
+<div id="column-content"><div id="content" class="mw-body-primary">
<a id="top"></a>
<?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice') ?></div><?php } ?>
*/
(function( $ ) {
window.doLivePreview = function( e ) {
+ var previewShowing = false;
+
e.preventDefault();
$( mw ).trigger( 'LivePreviewPrepare' );
- var postData = $('#editform').formToArray();
- postData.push( { 'name' : 'wpPreview', 'value' : '1' } );
+ var $wikiPreview = $( '#wikiPreview' );
+
+ $( '#mw-content-text' ).css( 'position', 'relative' );
+
+ if ( $wikiPreview.is( ':visible' ) ) {
+ previewShowing = true;
+ }
+
+ // show #wikiPreview if it's hidden (if it is hidden, it's also empty, so nothing changes in the rendering)
+ // to be able to scroll to it
+ $wikiPreview.show();
+
+ // Jump to where the preview will appear
+ $wikiPreview[0].scrollIntoView();
+
+ var postData = $('#editform').formToArray(); // formToArray: from jquery.form
+ postData.push( { 'name' : e.target.name, 'value' : '1' } );
// Hide active diff, used templates, old preview if shown
- var copyElements = ['#wikiPreview', '.templatesUsed', '.hiddencats',
+ var copyElements = ['#wikiPreview', '#wikiDiff', '.templatesUsed', '.hiddencats',
'#catlinks', '#p-lang', '.mw-summary-preview'];
var copySelector = copyElements.join(',');
- $.each( copyElements, function(k,v) { $(v).fadeOut('fast'); } );
+ $.each( copyElements, function( k, v ) {
+ $( v ).fadeTo( 'fast', 0.4 );
+ } );
// Display a loading graphic
var loadSpinner = $('<div class="mw-ajax-loader"/>');
- $('#wikiPreview').before( loadSpinner );
+ // Move away from header (default is -16px)
+ loadSpinner.css( 'top', '0' );
+
+ // If the preview is already showing, overlay the spinner on top of it.
+ if ( previewShowing ) {
+ loadSpinner.css( {
+ 'position': 'absolute',
+ 'z-index': '3',
+ 'left': '50%',
+ 'margin-left': '-16px'
+ } );
+ }
+ $wikiPreview.before( loadSpinner );
var page = $('<div/>');
var target = $('#editform').attr('action');
$(copyElements[i]).prop( 'class', newClasses );
}
- $.each( copyElements, function(k,v) {
+ $.each( copyElements, function( k, v ) {
// Don't belligerently show elements that are supposed to be hidden
- $(v).fadeIn( 'fast', function() { $(this).css('display', ''); } );
+ $( v ).fadeTo( 'fast', 1, function() {
+ $( this ).css( 'display', '' );
+ } );
} );
loadSpinner.remove();
} );
};
- // Shamelessly stolen from the jQuery form plugin, which is licensed under the GPL.
- // http://jquery.malsup.com/form/#download
- $.fn.formToArray = function() {
- var a = [];
- if (this.length == 0) return a;
-
- var form = this[0];
- var els = form.elements;
- if (!els) return a;
- for(var i=0, max=els.length; i < max; i++) {
- var el = els[i];
- var n = el.name;
- if (!n) continue;
-
- var v = $.fieldValue(el, true);
- if (v && v.constructor == Array) {
- for(var j=0, jmax=v.length; j < jmax; j++)
- a.push({name: n, value: v[j]});
- }
- else if (v !== null && typeof v != 'undefined')
- a.push({name: n, value: v});
- }
-
- if (form.clk) {
- // input type=='image' are not found in elements array! handle it here
- var $input = $(form.clk), input = $input[0], n = input.name;
- if (n && !input.disabled && input.type == 'image') {
- a.push({name: n, value: $input.val()});
- a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
- }
- }
- return a;
- };
-
- /**
- * Returns the value of the field element.
- */
- $.fieldValue = function(el, successful) {
- var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
- if (typeof successful == 'undefined') successful = true;
-
- if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
- (t == 'checkbox' || t == 'radio') && !el.checked ||
- (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
- tag == 'select' && el.selectedIndex == -1))
- return null;
-
- if (tag == 'select') {
- var index = el.selectedIndex;
- if (index < 0) return null;
- var a = [], ops = el.options;
- var one = (t == 'select-one');
- var max = (one ? index+1 : ops.length);
- for(var i=(one ? index : 0); i < max; i++) {
- var op = ops[i];
- if (op.selected) {
- var v = op.value;
- if (!v) // extra pain for IE...
- v = (op.attributes && op.attributes['value'] &&
- !(op.attributes['value'].specified))
- ? op.text : op.value;
- if (one) return v;
- a.push(v);
- }
- }
- return a;
- }
- return el.value;
- };
-
$(document).ready( function() {
// construct space for interwiki links if missing
// (it is usually not shown when action=edit, but shown if action=submit)
$( '.editCheckboxes' ).before( $( '<div>' ).addClass( 'mw-summary-preview' ) );
}
- $( '#wpPreview' ).click( doLivePreview );
+ // construct space for diff if missing. also load diff styles.
+ if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
+ $( '#wikiPreview' ).after( $( '<div>' ).attr( 'id', 'wikiDiff' ) );
+ // diff styles are by default only loaded when needed
+ // if there was no diff container, we can expect the styles not to be there either
+ mw.loader.load( 'mediawiki.action.history.diff' );
+ }
+
+ $( '#wpPreview, #wpDiff' ).click( doLivePreview );
} );
}) ( jQuery );
cursor: pointer;
}
-div#mw-js-message {
- margin: 1em 5%;
- padding: 0.5em 2.5%;
- border: solid 1px #ddd;
- background-color: #fcfcfc;
- /* Message hides on-click */
- /* See also mw.util.jsMessage */
- cursor: pointer;
-}
-
/* Edit section links */
/* Correct directionality when page dir is different from site/user dir */
/* @noflip */
input#wpSummary {
width: 80%;
+ margin: 1em 0;
}
/**
* Add a cute little box at the top of the screen to inform the user of
* something, replacing any preexisting message.
*
- * @deprecated since 1.17 Use mw.util.jsMessage instead.
+ * @deprecated since 1.17 Use mw.util.notify instead.
* @param {String|HTMLElement} message To be put inside the message box.
- * @param {String} className Used in adding a class; Can be used to selectively
- * apply CSS to a certain category of messages. null = no class used.
- * @return {Boolean} True on success, false on failure
*/
window.jsMsg = function () {
return mw.util.jsMessage.apply( mw.util, arguments );
}
#powersearch p {
- margin-top: 0px;
+ margin-top: 0;
}
div.multipageimagenavbox {
font-size: 127%;
}
-/* jsMessage */
-
-div#mw-js-message {
- position: absolute;
- margin: 0;
- padding: 0.25em 1em;
- right: 1em;
- top: 1em;
- width: 20em;
- z-index: 10000;
- -moz-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.125);
- -webkit-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.125);
- box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.125);
+/* mediawiki.notification */
+.skin-monobook .mw-notification {
+ -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.125);
+ -moz-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.125);
+ box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.125);
}
position: relative;
width: 100%;
}
-div#mw-js-message {
+div#bodyContent {
+ line-height: 1.5em;
+}
+
+/* mediawiki.notification */
+.skin-vector #mw-notification-area {
+ top: 7em;
+ font-size: 0.8em;
+}
+.skin-vector .mw-notification {
background-color: #fff;
background-color: rgba(255, 255, 255, 0.93);
- font-size: 0.8em;
- position: absolute;
- margin: 0;
- padding: 1em 2em;
- right: 1em;
- top: 7em;
- width: 20em;
- z-index: 10000;
+ padding: 0.75em 1.5em;
border: solid 1px #a7d7f9;
border-radius: 0.75em;
- -moz-box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.125);
- -webkit-box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.125);
- box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.125);
-}
-div#bodyContent {
- line-height: 1.5em;
+ -webkit-box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.125);
+ -moz-box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.125);
+ box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.125);
}
/* Watch/Unwatch Icon Styling */
</p>
!! end
+!! test
+Broken image links with HTML captions (bug 39700)
+!! input
+[[File:Nonexistent|<script></script>]]
+[[File:Nonexistent|100px|<script></script>]]
+[[File:Nonexistent|<]]
+[[File:Nonexistent|a<i>b</i>c]]
+!! result
+<p><a href="/index.php?title=Special:Upload&wpDestFile=Nonexistent" class="new" title="File:Nonexistent"><script></script></a>
+<a href="/index.php?title=Special:Upload&wpDestFile=Nonexistent" class="new" title="File:Nonexistent"><script></script></a>
+<a href="/index.php?title=Special:Upload&wpDestFile=Nonexistent" class="new" title="File:Nonexistent"><</a>
+<a href="/index.php?title=Special:Upload&wpDestFile=Nonexistent" class="new" title="File:Nonexistent">abc</a>
+</p>
+!! end
+
!! test
Plain link to URL
!! input
</p>
!! end
+!!test
+Bug 34939 - Case insensitive link parsing ([HttP://])
+!! input
+[HttP://MediaWiki.Org/]
+!! result
+<p><a rel="nofollow" class="external autonumber" href="HttP://MediaWiki.Org/">[1]</a>
+</p>
+!! end
+
+!!test
+Bug 34939 - Case insensitive link parsing ([HttP:// title])
+!! input
+[HttP://MediaWiki.Org/ MediaWiki]
+!! result
+<p><a rel="nofollow" class="external text" href="HttP://MediaWiki.Org/">MediaWiki</a>
+</p>
+!! end
+
+!!test
+Bug 34939 - Case insensitive link parsing (HttP://)
+!! input
+HttP://MediaWiki.Org/
+!! result
+<p><a rel="nofollow" class="external free" href="HttP://MediaWiki.Org/">HttP://MediaWiki.Org/</a>
+</p>
+!! end
+
TODO:
more images
);
}
+ /**
+ * Put each HTML element on its own line and then equals() the results
+ *
+ * Use for nicely formatting of PHPUnit diff output when comparing very
+ * simple HTML
+ *
+ * @since 1.20
+ *
+ * @param String $expected HTML on oneline
+ * @param String $actual HTML on oneline
+ * @param String $msg Optional message
+ */
+ protected function assertHTMLEquals( $expected, $actual, $msg='' ) {
+ $expected = str_replace( '>', ">\n", $expected );
+ $actual = str_replace( '>', ">\n", $actual );
+
+ $this->assertEquals( $expected, $actual, $msg );
+ }
+
/**
* Does an associative sort that works for objects.
*
private static $oldContLang;
private static $oldLanguageCode;
private static $oldNamespaces;
+ private static $oldHTML5;
public function setUp() {
- global $wgLang, $wgContLang, $wgLanguageCode;
-
+ global $wgLang, $wgContLang, $wgLanguageCode, $wgHTML5;
+
+ // Save globals
self::$oldLang = $wgLang;
self::$oldContLang = $wgContLang;
self::$oldNamespaces = $wgContLang->getNamespaces();
self::$oldLanguageCode = $wgLanguageCode;
-
+ self::$oldHTML5 = $wgHTML5;
+
$wgLanguageCode = 'en';
$wgContLang = $wgLang = Language::factory( $wgLanguageCode );
101 => 'Custom_talk',
) );
}
-
+
public function tearDown() {
- global $wgLang, $wgContLang, $wgLanguageCode;
+ global $wgLang, $wgContLang, $wgLanguageCode, $wgHTML5;
+ // Restore globals
$wgContLang->setNamespaces( self::$oldNamespaces );
$wgLang = self::$oldLang;
$wgContLang = self::$oldContLang;
$wgLanguageCode = self::$oldLanguageCode;
+ $wgHTML5 = self::$oldHTML5;
+ }
+
+ /**
+ * Wrapper to easily set $wgHTML5 = true.
+ * Original value will be restored after test completion.
+ * @todo Move to MediaWikiTestCase
+ */
+ public function enableHTML5() {
+ global $wgHTML5;
+ $wgHTML5 = true;
+ }
+ /**
+ * Wrapper to easily set $wgHTML5 = false
+ * Original value will be restored after test completion.
+ * @todo Move to MediaWikiTestCase
+ */
+ public function disableHTML5() {
+ global $wgHTML5;
+ $wgHTML5 = false;
}
public function testExpandAttributesSkipsNullAndFalse() {
--- /dev/null
+<?php
+
+class LocalisationCacheTest extends MediaWikiTestCase {
+ public function testPuralRulesFallback() {
+ $cache = Language::getLocalisationCache();
+
+ $this->assertEquals(
+ $cache->getItem( 'ru', 'pluralRules' ),
+ $cache->getItem( 'os', 'pluralRules' ),
+ 'os plural rules (undefined) fallback to ru (defined)'
+ );
+
+ $this->assertEquals(
+ $cache->getItem( 'ru', 'compiledPluralRules' ),
+ $cache->getItem( 'os', 'compiledPluralRules' ),
+ 'os compiled plural rules (undefined) fallback to ru (defined)'
+ );
+
+ $this->assertNotEquals(
+ $cache->getItem( 'ksh', 'pluralRules' ),
+ $cache->getItem( 'de', 'pluralRules' ),
+ 'ksh plural rules (defined) dont fallback to de (defined)'
+ );
+
+ $this->assertNotEquals(
+ $cache->getItem( 'ksh', 'compiledPluralRules' ),
+ $cache->getItem( 'de', 'compiledPluralRules' ),
+ 'ksh compiled plural rules (defined) dont fallback to de (defined)'
+ );
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Tests timestamp parsing and output.
+ */
+class TimestampTest extends MediaWikiTestCase {
+ /**
+ * Test parsing of valid timestamps and outputing to MW format.
+ * @dataProvider provideValidTimestamps
+ */
+ function testValidParse( $format, $original, $expected ) {
+ $timestamp = new MWTimestamp( $original );
+ $this->assertEquals( $expected, $timestamp->getTimestamp( TS_MW ) );
+ }
+
+ /**
+ * Test outputting valid timestamps to different formats.
+ * @dataProvider provideValidTimestamps
+ */
+ function testValidOutput( $format, $expected, $original ) {
+ $timestamp = new MWTimestamp( $original );
+ $this->assertEquals( $expected, (string) $timestamp->getTimestamp( $format ) );
+ }
+
+ /**
+ * Test an invalid timestamp.
+ * @expectedException TimestampException
+ */
+ function testInvalidParse() {
+ $timestamp = new MWTimestamp( "This is not a timestamp." );
+ }
+
+ /**
+ * Test requesting an invalid output format.
+ * @expectedException TimestampException
+ */
+ function testInvalidOutput() {
+ $timestamp = new MWTimestamp( '1343761268' );
+ $timestamp->getTimestamp( 98 );
+ }
+
+ /**
+ * Test human readable timestamp format.
+ */
+ function testHumanOutput() {
+ $timestamp = new MWTimestamp( time() - 3600 );
+ $this->assertEquals( "1 hour ago", $timestamp->getHumanTimestamp()->toString() );
+ }
+
+ /**
+ * Returns a list of valid timestamps in the format:
+ * array( type, timestamp_of_type, timestamp_in_MW )
+ */
+ function provideValidTimestamps() {
+ return array(
+ // Various formats
+ array( TS_UNIX, '1343761268', '20120731190108' ),
+ array( TS_MW, '20120731190108', '20120731190108' ),
+ array( TS_DB, '2012-07-31 19:01:08', '20120731190108' ),
+ array( TS_ISO_8601, '2012-07-31T19:01:08Z', '20120731190108' ),
+ array( TS_ISO_8601_BASIC, '20120731T190108Z', '20120731190108' ),
+ array( TS_EXIF, '2012:07:31 19:01:08', '20120731190108' ),
+ array( TS_RFC2822, 'Tue, 31 Jul 2012 19:01:08 GMT', '20120731190108' ),
+ array( TS_ORACLE, '31-07-2012 19:01:08.000000', '20120731190108' ),
+ array( TS_POSTGRES, '2012-07-31 19:01:08 GMT', '20120731190108' ),
+ array( TS_DB2, '2012-07-31 19:01:08', '20120731190108' ),
+ // Some extremes and weird values
+ array( TS_ISO_8601, '9999-12-31T23:59:59Z', '99991231235959' ),
+ array( TS_UNIX, '-62135596801', '00001231235959' )
+ );
+ }
+}
}
+ /**
+ * @dataProvider provideCasesForGetpageviewlanguage
+ */
+ function testGetpageviewlanguage( $expected, $titleText, $contLang, $lang, $variant, $msg='' ) {
+ // Save globals
+ global $wgContLang, $wgLang, $wgAllowUserJs, $wgLanguageCode, $wgDefaultLanguageVariant;
+ $save['wgContLang'] = $wgContLang;
+ $save['wgLang'] = $wgLang;
+ $save['wgAllowUserJs'] = $wgAllowUserJs;
+ $save['wgLanguageCode'] = $wgLanguageCode;
+ $save['wgDefaultLanguageVariant'] = $wgDefaultLanguageVariant;
+
+ // Setup test environnement:
+ $wgContLang = Language::factory( $contLang );
+ $wgLang = Language::factory( $lang );
+ # To test out .js titles:
+ $wgAllowUserJs = true;
+ $wgLanguageCode = $contLang;
+ $wgDefaultLanguageVariant = $variant;
+
+ $title = Title::newFromText( $titleText );
+ $this->assertInstanceOf( 'Title', $title,
+ "Test must be passed a valid title text, you gave '$titleText'"
+ );
+ $this->assertEquals( $expected,
+ $title->getPageViewLanguage()->getCode(),
+ $msg
+ );
+
+ // Restore globals
+ $wgContLang = $save['wgContLang'];
+ $wgLang = $save['wgLang'];
+ $wgAllowUserJs = $save['wgAllowUserJs'];
+ $wgLanguageCode = $save['wgLanguageCode'];
+ $wgDefaultLanguageVariant = $save['wgDefaultLanguageVariant'];
+ }
+
+ function provideCasesForGetpageviewlanguage() {
+ # Format:
+ # - expected
+ # - Title name
+ # - wgContLang (expected in most case)
+ # - wgLang (on some specific pages)
+ # - wgDefaultLanguageVariant
+ # - Optional message
+ return array(
+ array( 'fr', 'Main_page', 'fr', 'fr', false ),
+ array( 'es', 'Main_page', 'es', 'zh-tw', false ),
+ array( 'zh', 'Main_page', 'zh', 'zh-tw', false ),
+
+ array( 'es', 'Main_page', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'es', 'MediaWiki:About', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'es', 'MediaWiki:About/', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'de', 'MediaWiki:About/de', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.js', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.css', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Common.js', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Monobook.css', 'es', 'zh-tw', 'zh-cn' ),
+
+ array( 'zh-cn', 'Main_page', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh', 'MediaWiki:About', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh', 'MediaWiki:About/', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'de', 'MediaWiki:About/de', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh-cn', 'MediaWiki:About/zh-cn', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh-tw', 'MediaWiki:About/zh-tw', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.js', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.css', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Common.js', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Monobook.css', 'zh', 'zh-tw', 'zh-cn' ),
+
+ array( 'zh-tw', 'Special:NewPages', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'zh-tw', 'Special:NewPages', 'zh', 'zh-tw', 'zh-cn' ),
+
+ );
+ }
}
"ORDER BY field " .
"LIMIT 1"
),
+ array(
+ array(
+ 'tables' => array( 'table', 't2' => 'table2' ),
+ 'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
+ 'conds' => array( 'alias' => 'text' ),
+ 'options' => array( 'LIMIT' => 1, 'GROUP BY' => 'field', 'HAVING' => 'COUNT(*) > 1' ),
+ 'join_conds' => array( 't2' => array(
+ 'LEFT JOIN', 'tid = t2.id'
+ )),
+ ),
+ "SELECT tid,field,field2 AS alias,t2.id " .
+ "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
+ "WHERE alias = 'text' " .
+ "GROUP BY field HAVING COUNT(*) > 1 " .
+ "LIMIT 1"
+ ),
+ array(
+ array(
+ 'tables' => array( 'table', 't2' => 'table2' ),
+ 'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
+ 'conds' => array( 'alias' => 'text' ),
+ 'options' => array( 'LIMIT' => 1, 'GROUP BY' => array( 'field', 'field2' ), 'HAVING' => array( 'COUNT(*) > 1', 'field' => 1 ) ),
+ 'join_conds' => array( 't2' => array(
+ 'LEFT JOIN', 'tid = t2.id'
+ )),
+ ),
+ "SELECT tid,field,field2 AS alias,t2.id " .
+ "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
+ "WHERE alias = 'text' " .
+ "GROUP BY field,field2 HAVING (COUNT(*) > 1) AND field = '1' " .
+ "LIMIT 1"
+ ),
);
}
),
"(CASE WHEN field = 'text' THEN 1 ELSE NULL END)"
),
+ array(
+ array(
+ 'conds' => array( 'field' => 'text', 'field2' => 'anothertext' ),
+ 'true' => 1,
+ 'false' => 'NULL',
+ ),
+ "(CASE WHEN field = 'text' AND field2 = 'anothertext' THEN 1 ELSE NULL END)"
+ ),
array(
array(
'conds' => 'field=1',
*
* @group FileRepo
* @group FileBackend
+ * @group medium
*/
class FileBackendTest extends MediaWikiTestCase {
private $backend, $multiBackend;
<?php
/**
* @group FileRepo
+ * @group medium
*/
class StoreBatchTest extends MediaWikiTestCase {
public abstract function elementInstancesProvider();
/**
- * Provides instances of the concrete class being tested.
+ * Returns the name of the concrete class being tested.
*
* @since 1.20
*
- * @return array
+ * @return string
*/
- public abstract function instanceProvider();
+ public abstract function getInstanceClass();
/**
- * Returns the name of the concrete class being tested.
+ * Provides instances of the concrete class being tested.
*
* @since 1.20
*
- * @return string
+ * @return array
*/
- public abstract function getInstanceClass();
+ public function instanceProvider() {
+ $instances = array();
+
+ foreach ( $this->elementInstancesProvider() as $elementInstances ) {
+ $instances[] = $this->getNew( $elementInstances );
+ }
+
+ return $this->arrayWrap( $instances );
+ }
/**
* @since 1.20
$this->assertEquals( '2020:07:14 01:36:05', $meta['DateTimeDigitized'] );
$this->assertEquals( '1997:03:02 00:01:02', $meta['DateTimeOriginal'] );
}
- /* File has an invalid time (+ one valid but really weird time)
+ /**
+ * File has an invalid time (+ one valid but really weird time)
* that shouldn't be included
+ * @expectedException TimestampException
*/
public function testIPTCDatesInvalid() {
$meta = BitmapMetadataHandler::Jpeg( $this->filePath .
'advanced', array( 2, 14 ),
'Bug 33583: search with no option should honor User search preferences'
),
+ array(
+ $EMPTY_REQUEST, array_fill_keys( array_map( function( $ns ) {
+ return "searchNs$ns";
+ }, $defaultNS ), 0 ) + array( 'searchNs2' => 1, 'searchNs14' => 1 ),
+ 'advanced', array( 2, 14 ),
+ 'Bug 33583: search with no option should honor User search preferences'
+ . 'and have all other namespace disabled'
+ ),
);
}
mw.user.getGroups( function ( groups ) {
// First group should always be '*'
assert.equal( $.type( groups ), 'array', 'Callback gets an array' );
- assert.equal( groups[0], '*', '"*"" is the first group' );
+ assert.notStrictEqual( $.inArray( '*', groups ), -1, '"*"" is in the list' );
// Sort needed because of different methods if creating the arrays,
// only the content matters.
assert.deepEqual( groups.sort(), mw.config.get( 'wgUserGroups' ).sort(), 'Array contains all groups, just like wgUserGroups' );
}
}
+ $thumbName = $img->thumbName( $params );
+ if ( !strlen( $thumbName ) ) { // invalid params?
+ wfThumbError( 400, 'The specified thumbnail parameters are not valid.' );
+ wfProfileOut( __METHOD__ );
+ return;
+ }
+
+ $disposition = $img->getThumbDisposition( $thumbName );
+ $headers[] = "Content-Disposition: $disposition";
+
// Stream the file if it exists already...
try {
- $thumbName = $img->thumbName( $params );
- if ( strlen( $thumbName ) ) { // valid params?
- // For 404 handled thumbnails, we only use the the base name of the URI
- // for the thumb params and the parent directory for the source file name.
- // Check that the zone relative path matches up so squid caches won't pick
- // up thumbs that would not be purged on source file deletion (bug 34231).
- if ( isset( $params['rel404'] ) // thumbnail was handled via 404
- && urldecode( $params['rel404'] ) !== $img->getThumbRel( $thumbName ) )
- {
- wfThumbError( 404, 'The source file for the specified thumbnail does not exist.' );
- wfProfileOut( __METHOD__ );
- return;
- }
- $thumbPath = $img->getThumbPath( $thumbName );
- if ( $img->getRepo()->fileExists( $thumbPath ) ) {
- $img->getRepo()->streamFile( $thumbPath, $headers );
- wfProfileOut( __METHOD__ );
- return;
- }
+ // For 404 handled thumbnails, we only use the the base name of the URI
+ // for the thumb params and the parent directory for the source file name.
+ // Check that the zone relative path matches up so squid caches won't pick
+ // up thumbs that would not be purged on source file deletion (bug 34231).
+ if ( isset( $params['rel404'] ) // thumbnail was handled via 404
+ && urldecode( $params['rel404'] ) !== $img->getThumbRel( $thumbName ) )
+ {
+ wfThumbError( 404, 'The source file for the specified thumbnail does not exist.' );
+ wfProfileOut( __METHOD__ );
+ return;
+ }
+ $thumbPath = $img->getThumbPath( $thumbName );
+ if ( $img->getRepo()->fileExists( $thumbPath ) ) {
+ $img->getRepo()->streamFile( $thumbPath, $headers );
+ wfProfileOut( __METHOD__ );
+ return;
}
} catch ( MWException $e ) {
wfThumbError( 500, $e->getHTML() );