From 8a4a1edf047f2c272f663866eb7b5fcd644d65b3 Mon Sep 17 00:00:00 2001 From: John Resig Date: Wed, 22 Mar 2006 03:33:07 +0000 Subject: [PATCH] Inital Import. --- ajax/ajax.js | 88 +++++ browse/.htaccess | 5 + browse/Pack.pm | 467 ++++++++++++++++++++++++++ browse/ParseMaster.pm | 207 ++++++++++++ browse/browse-new.cgi | 85 +++++ browse/browse.cgi | 51 +++ browse/copyright.txt | 17 + core/core.js | 748 ++++++++++++++++++++++++++++++++++++++++++ event/event.js | 73 +++++ fx/fx.js | 170 ++++++++++ sort/sort.js | 57 ++++ tmpl/tmpl.js | 106 ++++++ 12 files changed, 2074 insertions(+) create mode 100644 ajax/ajax.js create mode 100644 browse/.htaccess create mode 100644 browse/Pack.pm create mode 100644 browse/ParseMaster.pm create mode 100755 browse/browse-new.cgi create mode 100755 browse/browse.cgi create mode 100644 browse/copyright.txt create mode 100644 core/core.js create mode 100644 event/event.js create mode 100644 fx/fx.js create mode 100644 sort/sort.js create mode 100644 tmpl/tmpl.js diff --git a/ajax/ajax.js b/ajax/ajax.js new file mode 100644 index 000000000..87eadbf67 --- /dev/null +++ b/ajax/ajax.js @@ -0,0 +1,88 @@ +// AJAX Plugin +// Docs Here: +// http://jquery.com/docs/ajax/ + +if ( typeof XMLHttpRequest == 'undefined' && typeof window.ActiveXObject == 'function') { + var XMLHttpRequest = function() { + return new ActiveXObject((navigator.userAgent.toLowerCase().indexOf('msie 5') >= 0) ? + "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP"); + }; +} + +$.xml = function( type, url, data, ret ) { + var xml = new XMLHttpRequest(); + + if ( xml ) { + xml.open(type || "GET", url, true); + + if ( data ) + xml.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + + if ( ret ) + xml.onreadystatechange = function() { + if ( xml.readyState == 4 ) ret(xml); + }; + + xml.send(data) + } +}; + +$.httpData = function(r,type) { + return r.getResponseHeader("content-type").indexOf("xml") > 0 || type == "xml" ? + r.responseXML : r.responseText; +}; + +$.get = function( url, ret, type ) { + $.xml( "GET", url, null, function(r) { + if ( ret ) ret( $.httpData(r,type) ); + }); +}; + +$.getXML = function( url, ret ) { + $.get( url, ret, "xml" ); +}; + +$.post = function( url, data, ret, type ) { + $.xml( "POST", url, $.param(data), function(r) { + if ( ret ) ret( $.httpData(r,type) ); + }); +}; + +$.postXML = function( url, data, ret ) { + $.post( url, data, ret, "xml" ); +}; + +$.param = function(a) { + var s = []; + for ( var i in a ) + s[s.length] = i + "=" + encodeURIComponent( a[i] ); + return s.join("&"); +}; + +$.fn.load = function(a,o,f) { + // Arrrrghhhhhhhh!! + // I overwrote the event plugin's .load + // this won't happen again, I hope -John + if ( a && a.constructor == Function ) + return this.bind("load", a); + + var t = "GET"; + if ( o && o.constructor == Function ) { + f = o; o = null; + } + if (o != null) { + o = $.param(o); + t = "POST"; + } + var self = this; + $.xml(t,a,o,function(h){ + var h = h.responseText; + self.html(h).find("script").each(function(){ + try { + eval( this.text || this.textContent || this.innerHTML ); + } catch(e){} + }); + if(f)f(h); + }); + return this; +}; diff --git a/browse/.htaccess b/browse/.htaccess new file mode 100644 index 000000000..bd61da621 --- /dev/null +++ b/browse/.htaccess @@ -0,0 +1,5 @@ +RewriteEngine On +RewriteRule ^$ /docs/SourceCode/ [L,QSA] +RewriteRule ^([^/]+).js$ browse-new.cgi?v=$1 [L,QSA] +RewriteRule ^([^/]+)/$ browse-new.cgi?v=$1 [L,QSA] +RewriteRule ^([^/]+)/([a-z0-9-]+)/?$ browse-new.cgi?v=$1&custom=$2 [L,QSA] diff --git a/browse/Pack.pm b/browse/Pack.pm new file mode 100644 index 000000000..fbd22923f --- /dev/null +++ b/browse/Pack.pm @@ -0,0 +1,467 @@ +#Pack (July 2005) +# Based on "Pack.js" by Dean Edwards +# Ported to Perl by Rob Seiler, ELR Software Pty Ltd +# Copyright 2005. License + +package Pack; +use strict; +use Data::Dumper; + +use ParseMaster; + +# Package wide variable declarations +use vars qw/$VERSION $PM_VERSION + $_X_encodePrivate $_JSunpack $_JSdecode %baseLookup + $_X_encode10 $_X_encode36 $_X_encode62 $_X_encode95 + $_JSencode10 $_JSencode36 $_JSencode62 $_JSencode95 + @_X_parsers + $_X_script $_X_encoding $_X_fastDecode $_X_specialChars + /; +$VERSION = '024'; +$PM_VERSION = $ParseMaster::VERSION; + +# Package wide constants +my $X_IGNORE = q{$1}; +my $X_ENCODE = q/\x24encode\(\x24count\)/; # NB: requires g modifier +my $PERL = 'perl'; # Flag to indicate whether we need to use one of our "internal" Perl encoding functions +my $JSCRIPT = 'jscript'; # or embed a pre-build JScript encoding function +######################################## + +################## +sub pack($$$$) { # require 4 arguments +################## +#print Dumper(@_); + ($_X_script, $_X_encoding, $_X_fastDecode, $_X_specialChars) = @_; + # validate parameters (sort of!) + $_X_script .= "\n"; + $_X_encoding = ($_X_encoding > 95) ? 95 : $_X_encoding; + + @_X_parsers = (); # Reset parsers + +#################### + sub _X_pack($) { # require 1 argument +#################### + # apply all parsing routines + my $X_script = shift; + for (my $i = 0; $inew(); + # make safe + $parser->escapeChar("\\"); + # protect strings + $parser->add(q/'[^'\n\r]*'/, $X_IGNORE); + $parser->add(q/"[^"\n\r]*"/, $X_IGNORE); + # remove comments + $parser->add(q/\/\/[^\n\r]*[\n\r]/); + $parser->add(q/\/\*[^*]*\*+([^\/][^*]*\*+)*\//); + # protect regular expressions + $parser->add(q/\s+(\/[^\/\n\r\*][^\/\n\r]*\/g?i?)/, q{$2}); # IGNORE + $parser->add(q/[^\w\x24\/'"*)\?:]\/[^\/\n\r\*][^\/\n\r]*\/g?i?/, $X_IGNORE); + # remove: ;;; doSomething(); + $parser->add(q/;;[^\n\r]+[\n\r]/) if ($_X_specialChars); + # remove redundant semi-colons + $parser->add(q/;+\s*([};])/, q{$2}); + # remove white-space + $parser->add(q/(\b|\x24)\s+(\b|\x24)/, q{$2 $3}); + $parser->add(q/([+\-])\s+([+\-])/, q{$2 $3}); + $parser->add(q/\s+/, ''); + # done + return $parser->exec($X_script); + } + +############################### + sub _X_encodeSpecialChars { # +############################### + my $X_script = shift; + my $parser = ParseMaster->new(); + # replace: $name -> n, $$name -> $$na + $parser->add(q/((\x24+)([a-zA-Z\x24_]+))(\d*)/, + sub { + my $X_offset = pop; + my @X_match = @_; + my $X_length = length($X_match[$X_offset+2]); + my $lengthnext = length($X_match[$X_offset+3]); + my $X_start = $X_length - ((($X_length - $lengthnext) > 0) ? ($X_length - $lengthnext) : 0); + my $str = $X_match[$X_offset+1]; + $str = substr($str,$X_start,$X_length) . $X_match[$X_offset+4]; + return "$str"; + }); + # replace: _name -> _0, double-underscore (__name) is ignored + my $X_regexp = q/\b_[A-Za-z\d]\w*/; + # build the word list + my %X_keywords = &_X_analyze($X_script, $X_regexp, $_X_encodePrivate); +#print Dumper(%X_keywords); + # quick ref + my $X_encoded = \$X_keywords{X_encoded}; # eg _private1 => '_0',_private2 => '_1'; +#print Dumper($X_encoded); + $parser->add($X_regexp, sub {my $X_offset = pop; my @X_match = @_; return ${$X_encoded}->{$X_match[$X_offset]};}); + + return $parser->exec($X_script); + }; + +########################### + sub _X_encodeKeywords { # +########################### + my $X_script = shift; + # escape high-ascii values already in the script (i.e. in strings) + if ($_X_encoding > 62) {$X_script = &_X_escape95($X_script)}; + # create the parser + my $parser = ParseMaster->new(); + my $X_encode = &_X_getEncoder($_X_encoding,$PERL); + # for high-ascii, don't encode single character low-ascii + my $X_regexp = ($_X_encoding > 62) ? q/\w\w+/ : q/\w+/; + # build the word list + my %X_keywords = &_X_analyze($X_script, $X_regexp, $X_encode); +#print Dumper(%X_keywords); + my $X_encoded = \$X_keywords{X_encoded}; # eg alert => 2, function => 10 etc + # encode + $parser->add($X_regexp, sub {my $X_offset = pop; my @X_match = @_; return ${$X_encoded}->{$X_match[$X_offset]};}); + # if encoded, wrap the script in a decoding function + + return $X_script && _X_bootStrap(\$parser->exec($X_script), \%X_keywords); + } + +#################### + sub _X_analyze { # +#################### +#print Dumper(@_); + my ($X_script, $X_regexp, $X_encode) = @_; + # analyse + # retreive all words in the script + my @X_all = $X_script =~ m/$X_regexp/g; # Save all captures in a list context + my %XX_sorted = (); # list of words sorted by frequency + my %XX_encoded = (); # dictionary of word->encoding + my %XX_protected = (); # instances of "protected" words + if (@X_all) { + my @X_unsorted = (); # same list, not sorted + my %X_protected = (); # "protected" words (dictionary of word->"word") + my %X_values = (); # dictionary of charCode->encoding (eg. 256->ff) + my %X_count = (); # word->count + my $i = scalar(@X_all); my $j = 0; my $X_word = ''; + # count the occurrences - used for sorting later + do { + $X_word = '$' . $X_all[--$i]; + if (!exists($X_count{$X_word})) { + $X_count{$X_word} = [0,$i]; # Store both the usage count and original array position (ie a secondary sort key) + $X_unsorted[$j] = $X_word; + # make a dictionary of all of the protected words in this script + # these are words that might be mistaken for encoding + $X_values{$j} = &$X_encode($j); + my $v = '$'.$X_values{$j}; + $X_protected{$v} = $j++; + } + # increment the word counter + $X_count{$X_word}[0]++; + } while ($i); +#print Dumper (%X_values); +#print Dumper (@X_unsorted); +#print Dumper (%X_protected); + # prepare to sort the word list, first we must protect + # words that are also used as codes. we assign them a code + # equivalent to the word itself. + # e.g. if "do" falls within our encoding range + # then we store keywords["do"] = "do"; + # this avoids problems when decoding + $i = scalar(@X_unsorted); + do { + $X_word = $X_unsorted[--$i]; + if (exists($X_protected{$X_word})) { + $XX_sorted{$X_protected{$X_word}} = substr($X_word,1); + $XX_protected{$X_protected{$X_word}} = 1; # true + $X_count{$X_word}[0] = 0; + } + } while ($i); +#print Dumper (%XX_protected); +#print Dumper (%XX_sorted); +#print Dumper (%X_count); + # sort the words by frequency + # Sort with count a primary key and original array order as secondary key - which is apparently the default in javascript! + @X_unsorted = sort ({($X_count{$b}[0] - $X_count{$a}[0]) or ($X_count{$b}[1] <=> $X_count{$a}[1])} @X_unsorted); +#print Dumper (@X_unsorted) . "\n"; + + $j = 0; + # because there are "protected" words in the list + # we must add the sorted words around them + do { + if (!exists($XX_sorted{$i})) {$XX_sorted{$i} = substr($X_unsorted[$j++],1)} + $XX_encoded{$XX_sorted{$i}} = $X_values{$i}; + } while (++$i < scalar(@X_unsorted)); + } +#print Dumper(X_sorted => \%XX_sorted, X_encoded => \%XX_encoded, X_protected => \%XX_protected); + return (X_sorted => \%XX_sorted, X_encoded => \%XX_encoded, X_protected => \%XX_protected); + } + +###################### + sub _X_bootStrap { # +###################### + # build the boot function used for loading and decoding + my ($X_packed, $X_keywords) = @_; # Reference arguments! +#print Dumper ($X_keywords) . "\n"; + + # $packed: the packed script - dereference and escape + $X_packed = "'" . &_X_escape($$X_packed) ."'"; + + my %sorted = %{$$X_keywords{X_sorted}}; # Dereference to local variables + my %protected = %{$$X_keywords{X_protected}}; # for simplicity + + my @sorted = (); + foreach my $key (keys %sorted) {$sorted[$key] = $sorted{$key}}; # Convert hash to a standard list + + # ascii: base for encoding + my $X_ascii = ((scalar(@sorted) > $_X_encoding) ? $_X_encoding : scalar(@sorted)) || 1; + + # count: number of (unique {RS}) words contained in the script + my $X_count = scalar(@sorted); # Use $X_count for assigning $X_ascii + + # keywords: list of words contained in the script + foreach my $i (keys %protected) {$sorted[$i] = ''}; # Blank out protected words +#print Dumper(@sorted) . "\n"; + + # convert from a string to an array - prepare keywords as a JScript string->array {RS} + $X_keywords = "'" . join('|',@sorted) . "'.split('|')"; + + # encode: encoding function (used for decoding the script) + my $X_encode = $_X_encoding > 62 ? $_JSencode95 : &_X_getEncoder($X_ascii,$JSCRIPT); # This is a JScript function (as a string) + $X_encode =~ s/_encoding/\x24ascii/g; $X_encode =~ s/arguments\.callee/\x24encode/g; + my $X_inline = '$count' . ($X_ascii > 10 ? '.toString($ascii)' : ''); + + # decode: code snippet to speed up decoding + my $X_decode = ''; + if ($_X_fastDecode) { + # create the decoder + $X_decode = &_X_getFunctionBody($_JSdecode); # ie from the Javascript literal function + if ($_X_encoding > 62) {$X_decode =~ s/\\\\w/[\\xa1-\\xff]/g} + # perform the encoding inline for lower ascii values + elsif ($X_ascii < 36) {$X_decode =~ s/$X_ENCODE/$X_inline/g} + # special case: when $X_count==0 there ar no keywords. i want to keep + # the basic shape of the unpacking funcion so i'll frig the code... + if (!$X_count) {$X_decode =~ s/(\x24count)\s*=\s*1/$1=0/} + } + + # boot function + my $X_unpack = $_JSunpack; + if ($_X_fastDecode) { + # insert the decoder + $X_unpack =~ s/\{/\{$X_decode;/; + } + $X_unpack =~ s/"/'/g; + if ($_X_encoding > 62) { # high-ascii + # get rid of the word-boundaries for regexp matches + $X_unpack =~ s/'\\\\b'\s*\+|\+\s*'\\\\b'//g; # Not checked! {RS} + } + if ($X_ascii > 36 || $_X_encoding > 62 || $_X_fastDecode) { + # insert the encode function + $X_unpack =~ s/\{/\{\$encode=$X_encode;/; + } else { + # perform the encoding inline + $X_unpack =~ s/$X_ENCODE/$X_inline/; + } + + # arguments {RS} Do this before using &pack because &pack changes the pack parameters (eg $fastDecode) in Perl!! + my $X_params = "$X_packed,$X_ascii,$X_count,$X_keywords"; # Interpolate to comma separated string + if ($_X_fastDecode) { + # insert placeholders for the decoder + $X_params .= ',0,{}'; + } + + # pack the boot function too + $X_unpack = &pack($X_unpack,0,0,1); + + # the whole thing + return "eval(" . $X_unpack . "(" . $X_params . "))\n"; + }; + +####################### + sub _X_getEncoder { # +####################### + # mmm.. ..which one do i need ?? ({RS} Perl or JScript ??) + my ($X_ascii,$language) = @_; + my $perl_encoder = ($X_ascii > 10) ? ($X_ascii > 36) ? ($X_ascii > 62) ? $_X_encode95 : $_X_encode62 : $_X_encode36 : $_X_encode10; + my $jscript_encoder = ($X_ascii > 10) ? ($X_ascii > 36) ? ($X_ascii > 62) ? $_JSencode95 : $_JSencode62 : $_JSencode36 : $_JSencode10; + return ($language eq $JSCRIPT) ? $jscript_encoder : $perl_encoder; + }; + +############################# +# Perl versions of encoders # +############################# + # base10 zero encoding - characters: 0123456789 + $_X_encode10 = sub {return &_encodeBase(shift,10)}; + # base36 - characters: 0123456789abcdefghijklmnopqrstuvwxyz + $_X_encode36 = sub {return &_encodeBase(shift,36)}; + # base62 - characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + $_X_encode62 = sub {return &_encodeBase(shift,62)}; + # high-ascii values - characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ + $_X_encode95 = sub {return &_encodeBase(shift,95)}; + # Lookup character sets for baseN encoding + $baseLookup{10} = [(0..9)[0..9]]; # base 10 + $baseLookup{36} = [(0..9,'a'..'z')[0..35]]; # base 36 + $baseLookup{62} = [(0..9,'a'..'z','A'..'Z')[0..61]]; # base 62 + $baseLookup{95} = (); for (my $i=0; $i<95; $i++) {$baseLookup{95}[$i] = chr($i+161)}; # base95 (high ascii) +#print Dumper(%baseLookup); +##################### + sub _encodeBase { # +##################### + # Generic base conversion function using defined lookup arrays (perl version only) + my ($X_charCode, $base) = @_; + my $X_encoded = ''; + # Do we know this encoding? + if (exists ($baseLookup{$base})) { + if ($X_charCode == 0) {$X_encoded = $baseLookup{$base}[0]} + while($X_charCode > 0) { + $X_encoded = $baseLookup{$base}[$X_charCode % $base] . $X_encoded; + $X_charCode = int($X_charCode / $base); + } + } + else {$X_encoded = "$X_charCode"} # default is to return unchanged (ie as for base 10) if no baselookup is available + return $X_encoded; + }; + +############################# + $_X_encodePrivate = sub { # +############################# + # special _chars + my $X_charCode = shift; + return '_' . $X_charCode; + }; + +############################ + sub _X_escape($script) { # +############################ + # protect characters used by the parser + my $X_script = shift; + $X_script =~ s/([\\'])/\\$1/g; + return $X_script; + }; + +##################### + sub _X_escape95 { # +##################### + # protect high-ascii characters already in the script + my $X_script = shift; + $X_script =~ s/([\xa1-\xff])/sprintf("\\x%1x",ord($1))/eg; + return $X_script; + }; + +############################ + sub _X_getFunctionBody { # +############################ + # extract the body of a function (ie between opening/closing {}) - consistent with Dean Edwards approach + my $X_function = shift; + $X_function =~ m/^.*\{(.*)\}*$/sg; # Multiline, global (greedy) + my $start = index($X_function,'{'); + my $end = rindex($X_function,'}'); + $X_function = substr($X_function,($start+1),($end-1-$start)); + return $X_function; + }; + +###################### + sub _X_globalize { # +###################### + # set the global flag on a RegExp (you have to create a new one) !!! Unused in perl version + # my $X_regexp = shift; + }; + + # build the parsing routine + &_X_addParser(\&_X_basicCompression); + &_X_addParser(\&_X_encodeSpecialChars) if ($_X_specialChars); + &_X_addParser(\&_X_encodeKeywords) if ($_X_encoding); + + # go! + return &_X_pack($_X_script); +} + +######################## +# Javascript Literals # +######################## + +# JScript function "_unpack" - from DeanEdwards pack.js (NB: No ";" after final "}") +($_JSunpack) = <<'END_JSCRIPT_UNPACK'; +/* unpacking function - this is the boot strap function */ +/* data extracted from this packing routine is passed to */ +/* this function when decoded in the target */ +function($packed, $ascii, $count, $keywords, $encode, $decode) { + while ($count--) + if ($keywords[$count]) + $packed = $packed.replace(new RegExp('\\b' + $encode($count) + '\\b', 'g'), $keywords[$count]); + /* RS_Debug = $packed; */ /* {RS} !!!!!!!!! */ + return $packed; +} +END_JSCRIPT_UNPACK + +# JScript function "_decode" - from DeanEdwards pack.js +($_JSdecode) = <<'END_JSCRIPT_DECODE'; + /* code-snippet inserted into the unpacker to speed up decoding */ + function() { + /* does the browser support String.replace where the */ + /* replacement value is a function? */ + if (!''.replace(/^/, String)) { + /* decode all the values we need */ + while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count); + /* global replacement function */ + $keywords = [function($encoded){return $decode[$encoded]}]; + /* generic match */ + $encode = function(){return'\\w+'}; + /* reset the loop counter - we are now doing a global replace */ + $count = 1; + } + }; +END_JSCRIPT_DECODE + +# JScript versions of encoders +($_JSencode10) = <<'END_JSCRIPT_ENCODE10'; + /* zero encoding */ + /* characters: 0123456789 */ + function($charCode) { + return $charCode; + }; +END_JSCRIPT_ENCODE10 + +($_JSencode36) = <<'END_JSCRIPT_ENCODE36'; + /* inherent base36 support */ + /* characters: 0123456789abcdefghijklmnopqrstuvwxyz */ + function($charCode) { + return $charCode.toString(36); + }; +END_JSCRIPT_ENCODE36 + +($_JSencode62) = <<'END_JSCRIPT_ENCODE62'; + /* hitch a ride on base36 and add the upper case alpha characters */ + /* characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ */ + function($charCode) { + return ($charCode < _encoding ? '' : arguments.callee(parseInt($charCode / _encoding))) + + (($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36)); + }; +END_JSCRIPT_ENCODE62 + +($_JSencode95) = <<'END_JSCRIPT_ENCODE95'; + /* use high-ascii values */ + /* characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ */ + function($charCode) { + return ($charCode < _encoding ? '' : arguments.callee($charCode / _encoding)) + + String.fromCharCode($charCode % _encoding + 161); + }; +END_JSCRIPT_ENCODE95 + +########### +# END # +########### +1; # Pack # +########### diff --git a/browse/ParseMaster.pm b/browse/ParseMaster.pm new file mode 100644 index 000000000..f07ba6804 --- /dev/null +++ b/browse/ParseMaster.pm @@ -0,0 +1,207 @@ +#ParseMaster (July 25 2005) +# Based on "ParseMaster.js" by Dean Edwards +# Ported to Perl by Rob Seiler, ELR Software Pty Ltd +# Copyright 2005. License + +package ParseMaster; +use strict; +use Data::Dumper; + +# Package wide variable declarations +use vars qw/$VERSION + @_X_escaped @_X_patterns + /; + +$VERSION = '017'; + +# constants +my $X_EXPRESSION = 0; +my $X_REPLACEMENT = 1; +my $X_LENGTH = 2; + +# re's used to determine nesting levels +my $X_GROUPS = qr/\(/o; # NB: Requires g modifier! +my $X_SUB_REPLACE = qr/\$\d/o; +my $X_INDEXED = qr/^\$\d+$/o; +my $XX_ESCAPE = qr/\\./o; # NB: Requires g modifier! +my $XX_DELETED = qr/\001[^\001]*\001/o; # NB: Requires g modifier! +my $DIGIT = qr/[^\D]/o; # Yep - this is a digit - contains no non-digits + +# Constructor +sub new { + my $class = shift; + my $self = {}; + @_X_escaped = (); # Re-initialize global for each instance + @_X_patterns = (); # Re-initialize global for each instance + # Instance variables - access by similarly named set/get functions + $self->{_ignoreCase_} = 0; + $self->{_escapeChar_} = ''; + bless ($self, $class); + return $self; +} + +sub ignoreCase { + my ($self, $value) = @_; + if (defined($value)) { + $self->{_ignoreCase_} = $value; + } + return $self->{_ignoreCase_}; +} + +sub escapeChar{ + my ($self, $value) = @_; + if (defined($value)) { + $self->{_escapeChar_} = $value; + } + return $self->{_escapeChar_}; +} + +####################### +# Public Parsemaster functions + +my $X_DELETE = sub(@$) { + my $X_offset = pop; + my @X_match = @_; + return (chr(001) . $X_match[$X_offset] . chr(001)); +}; # NB semicolon required for closure! + +# create and add a new pattern to the patterns collection +sub add { + my ($self, $expression, $X_replacement) = @_; + if (!$X_replacement) {$X_replacement = $X_DELETE}; + + # count the number of sub-expressions + my $temp = &_X_internalEscape($expression); + my $length = 1; # Always at least one because each pattern is itself a sub-expression + $length += $temp =~ s/$X_GROUPS//g; # One way to count the left capturing parentheses in the regexp string + + # does the pattern deal with sub-expressions? + if ((ref($X_replacement) ne "CODE") && ($X_replacement =~ m/$X_SUB_REPLACE/)) { + if ($X_replacement =~ m/$X_INDEXED/) { # a simple lookup? (eg "$2") + # store the index (used for fast retrieval of matched strings) + $X_replacement = substr($X_replacement,1) - 1; + } + else { # a complicated lookup (eg "Hello $2 $1") + my $i = $length; + while ($i) { # Had difficulty getting Perl to do Dean's splitting and joining of strings containing $'s + my $str = '$a[$o+' . ($i-1) . ']'; # eg $a[$o+1] + $X_replacement =~ s/\$$i/$str/; # eg $2 $3 -> $a[$o+1] $a[$o+2] + $i--; + } + # build a function to do the lookup - returns interpolated string of array lookups + $X_replacement = eval('sub {my $o=pop; my @a=@_; return "' . $X_replacement . '"};'); + } + } + else {} + # pass the modified arguments + &_X_add($expression || q/^$/, $X_replacement, $length); +} + +# execute the global replacement +sub exec { +#print Dumper(@_X_patterns); + my ($self, $X_string) = @_; + my $escChar = $self->escapeChar(); + my $ignoreCase = $self->ignoreCase(); + my ($regexp,$captures) = &_getPatterns(); # Concatenated and parenthesized regexp eg '(regex1)|(regex2)|(regex3)' etc + $X_string = &_X_escape($X_string, $escChar); + if ($ignoreCase) {$X_string =~ s/$regexp/{&_X_replacement(&_matchVars($captures,\$X_string))}/gie} # Pass $X_String as a + else {$X_string =~ s/$regexp/{&_X_replacement(&_matchVars($captures,\$X_string))}/ge} # reference for speed + + $X_string = &_X_unescape($X_string, $escChar); + $X_string =~ s/$XX_DELETED//g; + return $X_string; +} + +sub _X_add { + push (@_X_patterns, [@_]); # Save each argument set as is into an array of arrays +} + +# this is the global replace function (it's quite complicated) +sub _X_replacement { + my (@arguments) = @_; +#print Dumper (@arguments); + if ($arguments[0] le '') {return ''} + # Dereference last index (source String) here - faster than in _matchVars (maybe not needed at all?) + $arguments[$#arguments] = ${$arguments[$#arguments]}; + my $i = 1; + # loop through the patterns + for (my $j=0; $jheader('text/javascript'); +my $c = $cgi->param('c') || 'compressed'; +my $v = $cgi->param('v') || 'latest'; +my $live = 0; +#$v = "0.10" if ( $v eq 'latest' ); +if ( $v eq 'dev' ) { + $live = 1; + $c = 'sane'; + $v = 'latest'; +} elsif ( $v eq 'debug' ) { + $c = 'sane'; + $v = 'latest'; +} + +my @files = $cgi->param('files') ? + split(',', join(',', $cgi->param('files')) ): + ("jquery","fx","event","ajax"); + +if ($cgi->param('custom') && $cgi->param('custom') !~ /-/) { + $c = $cgi->param('custom'); +} + +my $md5 = $cgi->param('custom') || join('-',dupe(@files),$v,$c); +my $j = "build/$md5\.js"; +my $stamp = "/* Built " . localtime() . " */\n"; + +if ( !-e $j && !$live ) { + my $f = getf(); + open( F, ">$j" ); + print F $stamp; + print F $c eq 'compressed' ? &Pack::pack($f, 62, 1, 0) : $f; + close( F ); + + if ( $c eq 'compressed' ) { + my $tj = $j; + $tj =~ s/$c\.js$/sane\.js/; + open( F, ">$tj" ); + print F $stamp; + print F $f; + close( F ); + } +} + +if ( $cgi->param('files') ) { + print $cgi->redirect("/src/$v/$md5/"); +} else { + #print $cgi->header('text/javascript'); + if ( $live ) { + print getf(); + } else { + my $t = `cat copyright.txt $j`; + $v = $v eq 'latest' ? 'Current' : "Version $v"; + $t =~ s/\$VERSION/$v/ig; + $t =~ s/\$MD5/$md5/ig; + my $url = $cgi->param('v') . "/"; + $url .= $cgi->param('custom') . "/" if ( $cgi->param('custom') ); + $t =~ s/\$URL/$url/ig; + print $t; + } +} + +sub getf { + my $f = ''; + foreach ( @files ) { + $f .= `cat $_/$_\-$v\.js`; + } + $f =~ s/\r//g; + $f; +} + +sub dupe { + my %check; + $check{$_} = 1 foreach (@_); + return sort keys %check; +} diff --git a/browse/browse.cgi b/browse/browse.cgi new file mode 100755 index 000000000..751af3b55 --- /dev/null +++ b/browse/browse.cgi @@ -0,0 +1,51 @@ +#!/usr/bin/perl + +use Pack; +use CGI; +use LWP::Simple; +use Digest::MD5 qw(md5_hex); + +chdir("/home/jquery/www/src/"); + +my $cgi = new CGI(); +my $c = $cgi->param('c') || 'compressed'; +my $v = $cgi->param('v'); +#$v = "0.10" if ( $v eq 'latest' ); +my @files = $cgi->param('files') ? + split(',', join(',', $cgi->param('files')) ): + ("jquery","minifx","fx","event"); + +my $md5 = $cgi->param('custom') || join('-',dupe(@files),$v,$c); +my $j = "build/$md5\.js"; + +if ( !-e $j ) { + my $f = ''; + foreach ( @files ) { + $f .= `cat $_/$_\-$v\.js`; + } + $f =~ s/\r//g; + my $o = $c eq 'compressed' ? &Pack::pack($f, 62, 1, 0) : $f; + open( F, ">$j" ); + print F $o; + close( F ); +} + +if ( $cgi->param('files') ) { + print $cgi->redirect("/src/$v/$md5/"); +} else { + print $cgi->header('text/javascript'); + my $t = `cat copyright.txt $j`; + $v = $v eq 'latest' ? 'Current' : "Version $v"; + $t =~ s/\$VERSION/$v/ig; + $t =~ s/\$MD5/$md5/ig; + my $url = $cgi->param('v') . "/"; + $url .= $cgi->param('custom') . "/" if ( $cgi->param('custom') ); + $t =~ s/\$URL/$url/ig; + print $t; +} + +sub dupe { + my %check; + $check{$_} = 1 foreach (@_); + return sort keys %check; +} diff --git a/browse/copyright.txt b/browse/copyright.txt new file mode 100644 index 000000000..9fd2a074e --- /dev/null +++ b/browse/copyright.txt @@ -0,0 +1,17 @@ +/* + * jQuery - $VERSION + * New Wave Javascript + * http://jquery.com/ + * + * To use, place this HTML into the ... of your web page: + * + * + * This licensed under the Creative Commons Attribution-ShareAlike License. + * License Info: http://creativecommons.org/licenses/by-sa/2.5/ + * + *** NOTE: + * This code is compressed, for the original code please visit jquery.com. + * If you don't see anything below this comment, it's a bug with Firefox + * the code is there, it's just one long, compressed, line - trust me. + *** + */ diff --git a/core/core.js b/core/core.js new file mode 100644 index 000000000..6b1d2f1cb --- /dev/null +++ b/core/core.js @@ -0,0 +1,748 @@ +/* + * JQuery (http://jquery.com/) + * By John Resig (http://ejohn.org/) + * Under an Attribution, Share Alike License + */ + +function $(a,c) { + var $a = a || $.context || document; + var $c = c && c.$jquery && c.get(0) || c; + + // Since we're using Prototype's $ function, + // be nice and have backwards compatability + if ( typeof Prototype != "undefined" ) { + if ( $a.constructor == String ) { + var re = new RegExp( "[^a-zA-Z0-9_-]" ); + if ( !re.test($a) ) { + $c = $c && $c.documentElement || document; + if ( $c.getElementsByTagName($a).length == 0 ) { + var obj = $c.getElementById($a); + if ( obj != null ) return obj; + } + } + } else if ( $a.constructor == Array ) { + return $.map( $a, function(b){ + if ( b.constructor == String ) + return document.getElementById(b); + return b; + }); + } + } + + // Load Dynamic Function List + var self = { + cur: $.Select($a,$c), + $jquery: "0.30", + + // The only two getters + size: function() {return this.get().length}, + get: function(i) { + return i == null ? this.cur : this.cur[i]; + }, + + each: function(f) { + for ( var i = 0; i < this.size(); i++ ) + $.apply( this.get(i), f, [i] ); + return this; + }, + set: function(a,b) { + return this.each(function(){ + if ( b == null ) + for ( var j in a ) + $.attr(this,j,a[j]); + else + $.attr(this,a,b); + }); + }, + html: function(h) { + return h == null && this.size() ? + this.get(0).innerHTML : this.set( "innerHTML", h ); + }, + val: function(h) { + return h == null && this.size() ? + this.get(0).value : this.set( "value", h ); + }, + + css: function(a,b) { + return this.each(function(){ + if ( !b ) + for ( var j in a ) + $.attr(this.style,j,a[j]); + else + $.attr(this.style,a,b); + }); + }, + toggle: function() { + return this.each(function(){ + var d = $.getCSS(this,"display"); + if ( d == "none" || d == '' ) + $(this).show(); + else + $(this).hide(); + }); + }, + show: function(a) { + return this.each(function(){ + this.style.display = this.$$oldblock ? this.$$oldblock : ''; + if ( $.getCSS(this,"display") == "none" ) this.style.display = 'block'; + }); + }, + hide: function(a) { + return this.each(function(){ + this.$$oldblock = $.getCSS(this,"display"); + if ( this.$$oldblock == "none" ) this.$$oldblock = 'block'; + this.style.display = 'none'; + }); + }, + addClass: function(c) { + return this.each(function(){ + if ($.hasWord(this,c)) return; + this.className += ( this.className.length > 0 ? " " : "" ) + c; + }); + }, + removeClass: function(c) { + return this.each(function(){ + this.className = c == null ? '' : + this.className.replace( + new RegExp('(^|\\s*\\b[^-])'+c+'($|\\b(?=[^-]))', 'g'), ''); + }); + }, + // TODO: Optomize + toggleClass: function(c) { + return this.each(function(){ + if ($.hasWord(this,c)) + this.className = + this.className.replace( + new RegExp('(\\s*\\b[^-])'+c+'($|\\b(?=[^-]))', 'g'), ''); + else + this.className += ( this.className.length > 0 ? " " : "" ) + c; + }); + }, + remove: function() { + this.each(function(){this.parentNode.removeChild( this );}); + this.cur = []; + return this; + }, + + wrap: function() { + var a = $.clean(arguments); + return this.each(function(){ + var b = a[0].cloneNode(true); + this.parentNode.insertBefore( b, this ); + while ( b.firstChild ) b = b.firstChild; + b.appendChild( this ); + }); + }, + + append: function() { + var clone = this.size() > 1; + var a = $.clean(arguments); + return this.each(function(){ + for ( var i in a ) + this.appendChild( clone ? a[i].cloneNode(true) : a[i] ); + }); + }, + + appendTo: function() { + var a = arguments; + return this.each(function(){ + for ( var i = 0; i < a.length; i++ ) + $(a[i]).append( this ); + }); + }, + + prepend: function() { + var clone = this.size() > 1; + var a = $.clean(arguments); + return this.each(function(){ + for ( var i = a.length - 1; i >= 0; i-- ) + this.insertBefore( clone ? a[i].cloneNode(true) : a[i], this.firstChild ); + }); + }, + + before: function() { + var clone = this.size() > 1; + var a = $.clean(arguments); + return this.each(function(){ + for ( var i in a ) + this.parentNode.insertBefore( clone ? a[i].cloneNode(true) : a[i], this ); + }); + }, + + after: function() { + var clone = this.size() > 1; + var a = $.clean(arguments); + return this.each(function(){ + for ( var i = a.length - 1; i >= 0; i-- ) + this.parentNode.insertBefore( clone ? a[i].cloneNode(true) : a[i], this.nextSibling ); + }); + }, + + empty: function() { + return this.each(function(){ + while ( this.firstChild ) + this.removeChild( this.firstChild ); + }); + }, + + bind: function(t,f) { + return this.each(function(){addEvent(this,t,f);}); + }, + unbind: function(t,f) { + return this.each(function(){removeEvent(this,t,f);}); + }, + trigger: function(t) { + return this.each(function(){triggerEvent(this,t);}); + }, + + find: function(t) { + var old = [], ret = []; + this.each(function(){ + old[old.length] = this; + ret = $.merge( ret, $.Select(t,this) ); + }); + this.old = old; + this.cur = ret; + return this; + }, + end: function() { + this.cur = this.old; + return this; + }, + + parent: function(a) { + if ( a == null ) a = 1; + this.cur = $.map(this.cur,function(d){ + var b = $.parents(d); + if ( a == 0 ) + return b; + else if ( a.constructor == String ) { + var c = $.filter(a,b); + return c.length > 0 ? c[0] : null; + } else + return b.length >= a ? b[a-1] : null; + }); + return this; + }, + + parents: function(a) { + return this; + }, + + filter: function(t) { + this.cur = $.filter(t,this.cur).r; + return this; + }, + not: function(t) { + this.cur = t.constructor == String ? + $.filter(t,this.cur,false).r : + $.grep(this.cur,function(a){return a != t;}); + return this; + }, + add: function(t) { + this.cur = $.merge( this.cur, t.constructor == String ? + $.Select(t) : t.constructor == Array ? t : [t] ); + return this; + }, + is: function(t) { + return $.filter(t,this.cur).r.length > 0; + }, + isNot: function(t) { + return !this.s(t); + } + }; + + // TODO: Remove need to return this + for ( var i in $.fn ) { + if ( self[i] != null ) + self["_"+i] = self[i]; + self[i] = $.fn[i]; + } + + if ( typeof Prototype != "undefined" && $a.constructor != String ) { + if ( $c ) $a = self.get(); + for ( var i in self ) {(function(j){ + try { + if ( $a[j] == null ) { + $a[j] = function() { + return $.apply(self,self[j],arguments); + }; + } + } catch(e) {} + })(i);} + return $a; + } + + return self; +} + +$.apply = function(o,f,a) { + a = a || []; + if ( f.apply ) + return f.apply( o, a ); + else { + var p = []; + for (var i = 0; i < a.length; i++) + p[i] = 'a['+i+']'; + o.$$exec = this; + var r = eval('o.$$exec(' + p.join(',') + ')'); + o.$$exec = null; + return r; + } +}; + +$.getCSS = function(e,p) { + // Adapted from Prototype 1.4.0 + if ( p == 'height' || p == 'width' ) { + if ($.getCSS(e,"display") != 'none') + return p == 'height' ? + e.offsetHeight || parseInt(e.style.height) : + e.offsetWidth || parseInt(e.style.width); + var els = e.style; + var ov = els.visibility; + var op = els.position; + var od = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = ''; + var oHeight = e.clientHeight || parseInt(e.style.height); + var oWidth = e.clientWidth || parseInt(e.style.width); + els.display = od; + els.position = op; + els.visibility = ov; + return p == 'height' ? oHeight : oWidth; + } + + if (e.style[p]) + return e.style[p]; + else if (e.currentStyle) + return e.currentStyle[p]; + else if (document.defaultView && document.defaultView.getComputedStyle) { + p = p.replace(/([A-Z])/g,"-$1"); + p = p.toLowerCase(); + var s = document.defaultView.getComputedStyle(e,""); + var r = s ? s.getPropertyValue(p) : p; + return r; + } else + return null; +}; +$.css = $.getCSS; + +$.clean = function(a) { + var r = []; + for ( var i = 0; i < a.length; i++ ) + if ( a[i].constructor == String ) { + var div = document.createElement("div"); + div.innerHTML = a[i]; + for ( var j = 0; j < div.childNodes.length; j++ ) + r[r.length] = div.childNodes[j]; + } else if ( a[i].length ) + for ( var j = 0; j < a[i].length; j++ ) + r[r.length] = a[i][j]; + else if ( a[i] != null ) + r[r.length] = + a[i].nodeType ? a[i] : document.createTextNode(a[i].toString()); + return r; +}; + +$.g = { + '': "m[2] == '*' || a.nodeName.toUpperCase() == m[2].toUpperCase()", + '#': "a.id == m[2]", + ':': { + lt: "i < m[3]-0", + gt: "i > m[3]-0", + nth: "m[3] - 0 == i", + eq: "m[3] - 0 == i", + first: "i == 0", + last: "i == r.length - 1", + even: "i % 2 == 0", + odd: "i % 2 == 1", + "first-child": "$.sibling(a,0).cur", + "nth-child": "(m[3] == 'even'?$.sibling(a,m[3]).n % 2 == 0 :(m[3] == 'odd'?$.sibling(a,m[3]).n % 2 == 1:$.sibling(a,m[3]).cur))", + "last-child": "$.sibling(a,0,true).cur", + "nth-last-child": "$.sibling(a,m[3],true).cur", + "first-of-type": "$.ofType(a,0)", + "nth-of-type": "$.ofType(a,m[3])", + "last-of-type": "$.ofType(a,0,true)", + "nth-last-of-type": "$.ofType(a,m[3],true)", + "only-of-type": "$.ofType(a) == 1", + "only-child": "$.sibling(a).length == 1", + parent: "a.childNodes.length > 0", + empty: "a.childNodes.length == 0", + root: "a == ( a.ownerDocument ? a.ownerDocument : document ).documentElement", + contains: "(a.innerText || a.innerHTML).indexOf(m[3]) != -1", + visible: "(!a.type || a.type != 'hidden') && ($.getCSS(a,'display') != 'none' && $.getCSS(a,'visibility') != 'hidden')", + hidden: "(a.type && a.type == 'hidden') || $.getCSS(a,'display') == 'none' || $.getCSS(a,'visibility') == 'hidden'", + enabled: "a.disabled == false", + disabled: "a.disabled", + checked: "a.checked" + }, + // TODO: Write getAttribute helper + ".": "$.hasWord(a.className||a.getAttribute('class'),m[2])", + "@": { + "=": "$.attr(a,m[3]) == m[4]", + "!=": "$.attr(a,m[3]) != m[4]", + "~=": "$.hasWord($.attr(a,m[3]),m[4])", + "|=": "$.attr(a,m[3]).indexOf(m[4]) == 0", + "^=": "$.attr(a,m[3]).indexOf(m[4]) == 0", + "$=": "$.attr(a,m[3]).substr( $.attr(a,m[3]).length - m[4].length, m[4].length ) == m[4]", + "*=": "$.attr(a,m[3]).indexOf(m[4]) >= 0", + "": "m[3] == '*' ? a.attributes.length > 0 : $.attr(a,m[3])" + }, + "[": "$.Select(m[2],a).length > 0" +}; + +$.fn = {}; + +$.Select = function( t, context ) { + context = context || $.context || document; + if ( t.constructor != String ) return [t]; + + if ( t.indexOf("//") == 0 ) { + context = context.documentElement; + t = t.substr(2,t.length); + } else if ( t.indexOf("/") == 0 ) { + context = context.documentElement; + t = t.substr(1,t.length); + // FIX Assume the root element is right :( + if ( t.indexOf('/') ) + t = t.substr(t.indexOf('/'),t.length); + } + + var ret = [context]; + var done = []; + var last = null; + + while ( t.length > 0 && last != t ) { + var r = []; + last = t; + + t = $.cleanSpaces(t); + + var re = new RegExp( "^//", "i" ); + t = t.replace( re, "" ); + + if ( t.indexOf('..') == 0 || t.indexOf('/..') == 0 ) { + if ( t.indexOf('/') == 0 ) + t = t.substr(1,t.length); + r = $.map( ret, function(a){ return a.parentNode; } ); + t = t.substr(2,t.length); + t = $.cleanSpaces(t); + } else if ( t.indexOf('>') == 0 || t.indexOf('/') == 0 ) { + r = $.map( ret, function(a){ return ( a.childNodes.length > 0 ? $.sibling( a.firstChild ) : null ); } ); + t = t.substr(1,t.length); + t = $.cleanSpaces(t); + } else if ( t.indexOf('+') == 0 ) { + r = $.map( ret, function(a){ return $.sibling(a).next; } ); + t = t.substr(1,t.length); + t = $.cleanSpaces(t); + } else if ( t.indexOf('~') == 0 ) { + r = $.map( ret, function(a){ + var r = []; + var s = $.sibling(a); + if ( s.n > 0 ) + for ( var i = s.n; i < s.length; i++ ) + r[r.length] = s[i]; + return r; + } ); + t = t.substr(1,t.length); + t = $.cleanSpaces(t); + } else if ( t.indexOf(',') == 0 || t.indexOf('|') == 0 ) { + if ( ret[0] == context ) ret.shift(); + done = $.merge( done, ret ); + r = ret = [context]; + t = " " + t.substr(1,t.length); + } else { + var re = new RegExp( "^([#.]?)([a-z0-9\\*_-]*)", "i" ); + var m = re.exec(t); + + if ( m[1] == "#" ) { // Ummm, should make this work in all XML docs + var oid = document.getElementById(m[2]); + r = oid ? [oid] : []; + t = t.replace( re, "" ); + } else { + if ( m[2] == "" || m[1] == "." ) m[2] = "*"; + + for ( var i = 0; i < ret.length; i++ ) { + var o = ret[i]; + if ( o ) { + switch( m[2] ) { + case '*': + r = $.merge( $.getAll(o), r ); + break; + case 'text': case 'radio': case 'checkbox': case 'hidden': + case 'button': case 'submit': case 'image': case 'password': + case 'reset': case 'file': + r = $.merge( $.grep( $.tag(o,"input"), + function(a){ return a.type == m[2] }), r ); + break; + case 'input': + r = $.merge( $.tag(o,"input"), r ); + r = $.merge( $.tag(o,"select"), r ); + r = $.merge( $.tag(o,"textarea"), r ); + break; + default: + r = $.merge( r, $.tag(o,m[2]) ); + break; + } + } + } + } + } + + var val = $.filter(t,r); + ret = r = val.r; + t = $.cleanSpaces(val.t); + } + + if ( ret && ret[0] == context ) ret.shift(); + done = $.merge( done, ret ); + return done; +}; + +$.tag = function(a,b){ + return a && typeof a.getElementsByTagName != "undefined" ? + a.getElementsByTagName( b ) : []; +}; + +$.attr = function(o,a,v){ + if ( a && a.constructor == String ) { + var fix = { + 'for': 'htmlFor', + 'text': 'cssText', + 'class': 'className', + 'float': 'cssFloat' + }; + a = (fix[a] && fix[a].replace && fix[a]) || a; + var r = new RegExp("-([a-z])","ig"); + a = a.replace(r,function(z,b){return b.toUpperCase();}); + if ( v != null ) { + o[a] = v; + if ( o.setAttribute ) o.setAttribute(a,v); + } + return o[a] || o.getAttribute(a) || ''; + } else return ''; +}; + +$.filter = function(t,r,not) { + var g = $.grep; + if ( not == false ) var g = function(a,f) {return $.grep(a,f,true);}; + + while ( t.length > 0 && t.match(/^[:\\.#\\[a-zA-Z\\*]/) ) { + var re = new RegExp( "^\\[ *@([a-z0-9\\(\\)_-]+) *([~!\\|\\*$^=]*) *'?\"?([^'\"]*)'?\"? *\\]", "i" ); + var m = re.exec(t); + + if ( m != null ) { + m = ['', '@', m[2], m[1], m[3]]; + } else { + var re = new RegExp( "^(\\[) *([^\\]]*) *\\]", "i" ); + var m = re.exec(t); + + if ( m == null ) { + var re = new RegExp( "^(:)([a-z0-9\\*_-]*)\\( *[\"']?([^ \\)'\"]*)['\"]? *\\)", "i" ); + var m = re.exec(t); + + if ( m == null ) { + var re = new RegExp( "^([:\\.#]*)([a-z0-9\\*_-]*)", "i" ); + var m = re.exec(t); + } + } + } + t = t.replace( re, "" ); + + if ( m[1] == ":" && m[2] == "not" ) + r = $.filter(m[3],r,false).r; + else { + if ( $.g[m[1]].constructor == String ) + var f = $.g[m[1]]; + else if ( $.g[m[1]][m[2]] ) + var f = $.g[m[1]][m[2]]; + + if ( f != null ) { + eval("f = function(a,i){return " + f + "}"); + r = g( r, f ); + } + } + } + return { r: r, t: t }; +}; + +$.parents = function(a){ + var b = []; + var c = a.parentNode; + while ( c != null && c != c.documentElement ) { + b[b.length] = c; + c = c.parentNode; + } + return b; +}; + +$.cleanSpaces = function(t){return t.replace(/^\s+|\s+$/g, '')}; + +$.ofType = function(a,n,e) { + var t = $.grep($.sibling(a),function(b){return b.nodeName == a.nodeName}); + if ( e ) n = t.length - n - 1; + return n != null ? t[n] == a : t.length; +}; + +$.sibling = function(a,n,e) { + var type = []; + var tmp = a.parentNode.childNodes; + for ( var i = 0; i < tmp.length; i++ ) { + if ( tmp[i].nodeType == 1 ) + type[type.length] = tmp[i]; + if ( tmp[i] == a ) + type.n = type.length - 1; + } + if ( e ) n = type.length - n - 1; + type.cur = ( type[n] == a ); + type.prev = ( type.n > 0 ? type[type.n - 1] : null ); + type.next = ( type.n < type.length - 1 ? type[type.n + 1] : null ); + return type; +}; + +$.hasWord = function(e,a) { + if ( e == null ) return false; + if ( e.className != null ) e = e.className; + return new RegExp("(^|\\s)" + a + "(\\s|$)").test(e) +}; + +$.getAll = function(o,r) { + r = r || []; + var s = o.childNodes; + for ( var i = 0; i < s.length; i++ ) { + if ( s[i].nodeType == 1 ) { + r[r.length] = s[i]; + $.getAll( s[i], r ); + } + } + return r; +}; + +$.merge = function(a,b) { + var d = []; + for ( var j = 0; j < b.length; j++ ) + d[j] = b[j]; + + for ( var i = 0; i < a.length; i++ ) { + var c = true; + for ( var j = 0; j < b.length; j++ ) + if ( a[i] == b[j] ) + c = false; + if ( c ) + d[d.length] = a[i]; + } + return d; +}; + +$.grep = function(a,f,s) { + var r = []; + if ( a != null ) + for ( var i = 0; i < a.length; i++ ) + if ( (!s && f(a[i],i)) || (s && !f(a[i],i)) ) + r[r.length] = a[i]; + return r; +}; + +$.map = function(a,f) { + var r = []; + for ( var i = 0; i < a.length; i++ ) { + var t = f(a[i],i); + if ( t != null ) { + if ( t.constructor != Array ) t = [t]; + r = $.merge( t, r ); + } + } + return r; +}; + +// Bind an event to an element +// Original by Dean Edwards +function addEvent(element, type, handler) { + if ( element.location ) element = window; // Ughhhhh.... + if (!handler.$$guid) handler.$$guid = addEvent.guid++; + if (!element.events) element.events = {}; + var handlers = element.events[type]; + if (!handlers) { + handlers = element.events[type] = {}; + if (element["on" + type]) + handlers[0] = element["on" + type]; + } + handlers[handler.$$guid] = handler; + element["on" + type] = handleEvent; +}; +addEvent.guid = 1; + +// Detach an event or set of events from an element +function removeEvent(element, type, handler) { + if (element.events) { + if (type && element.events[type]) { + if ( handler ) { + delete element.events[type][handler.$$guid]; + } else { + for ( var i in element.events[type] ) + delete element.events[type][i]; + } + } else { + for ( var i in element.events ) + removeEvent( element, i ); + } + } +}; + +function triggerEvent(element,type) { + if ( element["on" + type] ) + element["on" + type]({ type: type }); +} + +function handleEvent(event) { + var returnValue = true; + event = event || fixEvent(window.event); + var handlers = []; + for ( var i in this.events[event.type] ) + handlers[handlers.length] = this.events[event.type][i]; + for ( var i = 0; i < handlers.length; i++ ) { + try { + if ( handlers[i].constructor == Function ) { + this.$$handleEvent = handlers[i]; + if (this.$$handleEvent(event) === false) { + event.preventDefault(); + event.stopPropagation(); + returnValue = false; + } + } + } catch(e){} + } + return returnValue; +}; + +function fixEvent(event) { + event.preventDefault = fixEvent.preventDefault; + event.stopPropagation = fixEvent.stopPropagation; + return event; +}; +fixEvent.preventDefault = function() { + this.returnValue = false; +}; +fixEvent.stopPropagation = function() { + this.cancelBubble = true; +}; + +// Move to module + +$.fn.text = function(e) { + e = e || this.cur; + var t = ""; + for ( var j = 0; j < e.length; j++ ) { + for ( var i = 0; i < e[j].childNodes.length; i++ ) + t += e[j].childNodes[i].nodeType != 1 ? + e[j].childNodes[i].nodeValue : + $.fn.text(e[j].childNodes[i].childNodes); + } + return t; +}; + +setTimeout(function(){ + if ( typeof Prototype != "undefined" && $.g == null && $.clean == null ) + throw "Error: You are overwriting jQuery, please include jQuery last."; +}, 1000); diff --git a/event/event.js b/event/event.js new file mode 100644 index 000000000..e11a2c0b6 --- /dev/null +++ b/event/event.js @@ -0,0 +1,73 @@ +var e = ["blur","focus","contextmenu","load","resize","scroll","unload", + "click","dblclick","mousedown","mouseup","mouseenter","mouseleave", + "mousemove","mouseover","mouseout","change","reset","select","submit", + "keydown","keypress","keyup","abort","error","ready"]; +for ( var i = 0; i < e.length; i++ ) { + (function(){ + var o = e[i]; + $.fn[o] = function(f){ return this.bind(o, f); }; + $.fn["un"+o] = function(f){ return this.unbind(o, f); }; + $.fn["do"+o] = function(){ return this.trigger(o); }; + $.fn["one"+o] = function(f){ return this.bind(o, function(e){ + if ( this[o+f] != null ) return true; + this[o+f]++; + return $.apply(this,f,[e]); + }); }; + + // Deprecated + //$.fn["on"+o] = function(f){ return this.bind(o, f); }; + })(); +} + +$.fn.hover = function(f,g) { + // Check if mouse(over|out) are still within the same parent element + return this.each(function(){ + var obj = this; + addEvent(this, "mouseover", function(e) { + var p = ( e.fromElement != null ? e.fromElement : e.relatedTarget ); + while ( p && p != obj ) p = p.parentNode; + if ( p == obj ) return false; + return $.apply(obj,f,[e]); + }); + addEvent(this, "mouseout", function(e) { + var p = ( e.toElement != null ? e.toElement : e.relatedTarget ); + while ( p && p != obj ) p = p.parentNode; + if ( p == obj ) return false; + return $.apply(obj,g,[e]); + }); + }); +}; + +// Deprecated +$.fn.onhover = $.fn.hover; + +$.fn.ready = function(f) { + return this.each(function(){ + if ( this.$$timer ) { + this.$$ready.push( f ); + } else { + var obj = this; + this.$$ready = [ f ]; + this.$$timer = setInterval( function(){ + if ( obj && obj.getElementsByTagName && obj.getElementById && obj.body ) { + clearInterval( obj.$$timer ); + obj.$$timer = null; + for ( var i = 0; i < obj.$$ready.length; i++ ) + $.apply( obj, obj.$$ready[i] ); + obj.$$ready = null; + } + }, 13 ); + } + }); +}; + +// Deprecated +$.fn.onready = $.fn.ready; + +$.fn.toggle = function(a,b) { + return a && b ? this.click(function(e){ + this.$$last = this.$$last == a ? b : a; + e.preventDefault(); + return $.apply( this, this.$$last, [e] ) || false; + }) : this._toggle(); +}; diff --git a/fx/fx.js b/fx/fx.js new file mode 100644 index 000000000..6e4892042 --- /dev/null +++ b/fx/fx.js @@ -0,0 +1,170 @@ +function fx(el,op,ty,tz){ + var z = this; + z.a = function(){z.el.style[ty]=z.now+z.o.unit}; + z.max = function(){return z.el["io"+ty]||z.el["natural"+tz]||z.el["scroll"+tz]||z.cur()}; + z.cur = function(){return parseInt($.getCSS(z.el,ty))}; + z.show = function(){z.ss("block");z.custom(0,z.max())}; + z.hide = function(){z.el.$o=$.getCSS(z.el,"overflow");z.el["io"+ty]=this.cur();z.custom(z.cur(),0)}; + z.ss = function(a){if(y.display!=a)y.display=a}; + z.toggle = function(){if(z.cur()>0)z.hide();else z.show()}; + z.modify = function(a){z.custom(z.cur(),z.cur()+a)}; + z.clear = function(){clearInterval(z.timer);z.timer=null}; + z.el = el.constructor==String?document.getElementById(el):el; + var y = z.el.style; + z.oo = y.overflow; + y.overflow = "hidden"; + z.o = { + unit: "px", + duration: (op && op.duration) || 400, + onComplete: (op && op.onComplete) || op + }; + z.step = function(f,tt){ + var t = (new Date).getTime(); + var p = (t - z.s) / z.o.duration; + if (t >= z.o.duration+z.s) { + z.now = tt; + z.clear(); + setTimeout(function(){ + y.overflow = z.oo; + if(y.height=="0px"||y.width=="0px")z.ss("none"); + $.setAuto( z.el, "height" ); + $.setAuto( z.el, "width" ); + if(z.o.onComplete.constructor == Function){z.el.$_ = z.o.onComplete;z.el.$_();} + },13); + } else + z.now = ((-Math.cos(p*Math.PI)/2) + 0.5) * (tt-f) + f; + z.a(); + }; + z.custom = function(f,t){ + if(z.timer)return;this.now=f;z.a();z.io=z.cur();z.s=(new Date).getTime(); + z.timer=setInterval(function(){z.step(f,t);}, 13); + }; +} +fx.fn = ["show","hide","toggle"]; +fx.ty = ["Height","Width","Left","Top"]; +for(var i in fx.ty){(function(){ + var c = fx.ty[i]; + fx[c] = function(a,b){ + return new fx(a,b,c.toLowerCase(),c);}; +})()} +fx.Opacity = function(a,b){ + var o = new fx(a,b,"opacity"); + o.cur = function(){return parseFloat(o.el.style.opacity);}; + o.a = function() { + var e = o.el.style; + if (o.now == 1) o.now = 0.9999; + if (window.ActiveXObject) + e.filter = "alpha(opacity=" + o.now*100 + ")"; + e.opacity = o.now; + }; + o.io = o.now = 1; + o.a(); + return o; +}; +fx.Resize = function(e,o){ + var z = this; + var h = new fx.Height(e,o); + if(o) o.onComplete = null; + var w = new fx.Width(e,o); + function c(a,b,c){return (!a||a==c||b==c);} + for(var i in fx.fn){(function(){ + var j = fx.fn[i]; + z[j] = function(a,b){ + if(c(a,b,"height")) h[j](); + if(c(a,b,"width")) w[j](); + }; + })()} + z.modify = function(c,d){ + h.modify(c); + w.modify(d); + }; +}; +fx.FadeSize = function(e,o){ + var z = this; + var p = new fx.Opacity(e,o); + if(o) o.onComplete = null; + var r = new fx.Resize(e,o); + for(var i in fx.fn){(function(){ + var j = fx.fn[i]; + z[j] = function(a,b){p[j]();r[j](a,b);}; + })()} +}; + +$.speed = function(s,o) { + if ( o && o.constructor == Function ) o = { onComplete: o }; + o = o || {}; + var ss = {"crawl":1200,"xslow":850,"slow":600,"medium":400,"fast":200,"xfast":75,"normal":400}; + o.duration = typeof s == "number" ? s : ss[s] || 400; + return o; +}; + +$.fn.hide = function(a,o) { + o = $.speed(a,o); + return a ? this.each(function(){ + new fx.FadeSize(this,o).hide(); + }) : this._hide(); +}; + +$.fn.show = function(a,o) { + o = $.speed(a,o); + return a ? this.each(function(){ + new fx.FadeSize(this,o).show(); + }) : this._show(); +}; + +$.fn.slideDown = function(a,o) { + o = $.speed(a,o); + return this.each(function(){ + new fx.Resize(this,o).show("height"); + }); +}; + +$.fn.slideUp = function(a,o) { + o = $.speed(a,o); + return this.each(function(){ + new fx.Resize(this,o).hide("height"); + }); +}; + +$.fn.fadeOut = function(a,o) { + o = $.speed(a,o); + return a ? this.each(function(){ + new fx.Opacity(this,o).hide(); + }) : this._hide(); +}; + +$.fn.fadeIn = function(a,o) { + o = $.speed(a,o); + return a ? this.each(function(){ + new fx.Opacity(this,o).show(); + }) : this._show(); +}; + +$.fn.center = function(f) { + return this.each(function(){ + if ( !f && this.nodeName == 'IMG' && + !this.offsetWidth && !this.offsetHeight ) { + var self = this; + setTimeout(function(){ + $(self).center(true); + }, 13); + } else { + var s = this.style; + var p = this.parentNode; + if ( $.css(p,"position") == 'static' ) + p.style.position = 'relative'; + s.position = 'absolute'; + s.left = parseInt(($.css(p,"width") - $.css(this,"width"))/2) + "px"; + s.top = parseInt(($.css(p,"height") - $.css(this,"height"))/2) + "px"; + } + }); +}; + +$.setAuto = function(e,p) { + var a = e.style[p]; + var o = $.css(e,p); + e.style[p] = 'auto'; + var n = $.css(e,p); + if ( o != n ) + e.style[p] = a; +}; diff --git a/sort/sort.js b/sort/sort.js new file mode 100644 index 000000000..5a08b77b3 --- /dev/null +++ b/sort/sort.js @@ -0,0 +1,57 @@ +$.fn.sort = function(f) { + cur = cur.sort(function(a,b){ + if ( typeof f == 'object' ) + var ret = f(a,b); + else + var ret = $.fn.genericSort(a,b,f); + + if ( a < b ) + b.parentNode.insertBefore( a, b ); + else if ( a > b ) + a.parentNode.insertBefore( b, a ); + return ret; + }); + return this; +} + +$.fn.reverse = function() { + cur[0].parentNode.appendChild( cur[0] ); + for ( var i = 1; cur && i < cur.length; i++ ) + cur[i-1].parentNode.insertBefore( cur[i], cur[i-1] ); + cur = cur.reverse(); + return this; +} + +$.fn.genericSort = function(a,b,c) { + if ( typeof a == "string" || typeof b == "string" ) { + } else if ( c != null ) { + a = sibling(a.firstChild)[c].innerText; + b = sibling(b.firstChild)[c].innerText; + } else { + a = a.innerText; + b = b.innerText; + } + + // Case insensitive + a = a.toLowerCase(); + b = b.toLowerCase(); + + // Figure out if it's an American-style date + var re = new RegExp( "^(\d{2}).(\d{2}).(\d{2,4})$" ); + var ma = re.exec(a); + var mb = re.exec(b); + + if ( ma.length && mb.length ) { + a = ma.reverse().join(''); + b = mb.reverse().join(''); + } + + // If it contains a number, sort on that only + if ( a.match(/\d/) ) { + var re = new RegExp("[^0-9.-]","ig"); + a = parseFloat( a.replace( re, "" ) ); + b = parseFloat( b.replace( re, "" ) ); + } + + return ( a < b ? -1 : ( a > b ? 1 : 0 ) ); +} diff --git a/tmpl/tmpl.js b/tmpl/tmpl.js new file mode 100644 index 000000000..2ada8fafd --- /dev/null +++ b/tmpl/tmpl.js @@ -0,0 +1,106 @@ +$.fn.get = function(i) { + return i == null ? + this.$$unclean ? $.sibling(this.$$unclean[0]) : this.cur : + (this.get())[i]; +}; + +$.fn._get = function(i) { + return i == null ? this.cur : this.cur[i]; +}; + +$.fn.set = function(a,b) { + return this.each(function(){ + if ( b == null ) + for ( var j in a ) + this[$.attr(j)] = a[j]; + else { + if ( b.constructor != String ) { // TODO: Fix this + for ( var i in b ) { + var c = $.Select(i,this); + for ( var j in c ) + c[j][$.attr(a)] = b[i]; + } + } else + this[$.attr(a)] = b; + } + }); +}; + +function $C(a) { + if ( a.indexOf('<') >= 0 ) { + if ( a.indexOf('= 0 ) { + var r = $C("table").html(""+a+""); + r.$$unclean = r.get(0).childNodes[0].childNodes; + } else { + var r = $C("div").html(a); + r.$$unclean = r.get(0).childNodes; + } + return r; + } else { + return $(document.createElement(a),document); + } +}; + +$.fn.appendTo = function() { + var self = this; + var a = arguments; + return this.each(function(){ + for ( var i = 0; i < a.length; i++ ) { + if ( self.$$unclean ) + $(a[i]).append( self.get() ); + else + $(a[i]).append( this ); + } + }); +}; + +$.clean = function(a) { + var r = []; + for ( var i = 0; i < a.length; i++ ) { + if ( a[i].constructor == String ) { + // Cool, but has scary side-effects + //a[i] = a[i].replace( /#([a-zA-Z0-9_-]+)/g, " id='$1' " ); + //a[i] = a[i].replace( /\.([a-zA-Z0-9_-]+)/g, " class='$1' " ); + var div = document.createElement("div"); + div.innerHTML = a[i]; + for ( var j = 0; j < div.childNodes.length; j++ ) + r[r.length] = div.childNodes[j]; + } else if ( a[i].length ) { + for ( var j = 0; j < a[i].length; j++ ) + r[r.length] = a[i][j]; + } else { + r[r.length] = a[i]; + } + } + return r; +}; + +// Frequently-used Accessors +window.cssQuery = $.Select; +document.getElementsByClass = function(a){return $.Select("."+a)}; +document.getElementsBySelector = $.Select; + + + // Make Xpath Axes Sane + //var re = new RegExp( "/?descendant::", "i" ); + //t = t.replace( re, " " ); + //var re = new RegExp( "/?child::", "i" ); + //t = t.replace( re, "/" ); + // If only... + //var re = new RegExp( "/?following-sibling::", "i" ); + //t = t.replace( re, " + " ); + //var re = new RegExp( "/?preceding-sibling::", "i" ); + //t = t.replace( re, " ~ " ); + //var re = new RegExp( "/?self::", "i" ); + //t = t.replace( re, "" ); + //var re = new RegExp( "/?parent::", "i" ); + //t = t.replace( re, " .. " ); + + // following + // preceding + // ancestor + // ancestor-or-self + // descendant-or-self + +// Deprecated +//style: function(a,b){ return this.css(a,b); },