# HG changeset patch # User ymh # Date 1275952595 -7200 # Node ID ecdfc63274bf2b8398ba175d288d953228a22d02 first import diff -r 000000000000 -r ecdfc63274bf .project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.project Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,17 @@ + + + eulalie + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff -r 000000000000 -r ecdfc63274bf .pydevproject --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.pydevproject Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,7 @@ + + + + +Default +python 2.6 + diff -r 000000000000 -r ecdfc63274bf sbin/sync/sync_ldt_platform --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbin/sync/sync_ldt_platform Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -e +if [ -d ~/tmp/blinkster_V$1 ]; then + rm -fr ~/tmp/blinkster_V$1; +fi + +hg archive -r V$1 ~/tmp/blinkster_V$1 + +#text2unix ~/tmp/blinkster_V$1 + +if [ -d ~/tmp/blinkster_V$1 ]; then + cat < pip +# - PIL -> pip +# - pyxml -> pip +# - 4Suite-xml - easy_install ftp://ftp.4suite.org/pub/4Suite/4Suite-XML-1.0.2.tar.bz2 +# - pylucene - script + +src_base = os.path.join(here,"res","src") +lib_path = os.path.abspath(os.path.join(here,"res","lib")) +patch_path = os.path.abspath(os.path.join(here,"res","patch")) + +EXTRA_TEXT = "URLS = { \n" + +EXTRA_TEXT += " 'DISTRIBUTE' : { 'setup': 'distribute', 'url': 'http://pypi.python.org/packages/source/d/distribute/distribute-0.6.13.tar.gz', 'local': '"+ os.path.abspath(os.path.join(src_base,"distribute-0.6.13.tar.gz"))+"'},\n" +EXTRA_TEXT += " 'PSYCOPG2' : { 'setup': 'psycopg2','url': 'http://initd.org/pub/software/psycopg/psycopg2-2.2.1.tar.gz', 'local': '"+ os.path.abspath(os.path.join(src_base,"psycopg2-2.2.1.tar.gz"))+"'},\n" +EXTRA_TEXT += " 'MYSQL' : { 'setup': 'mysql-python', 'url': 'http://sourceforge.net/projects/mysql-python/files/mysql-python-test/1.2.3c1/MySQL-python-1.2.3c1.tar.gz/download', 'local' : '"+ os.path.abspath(os.path.join(src_base,"MySQL-python-1.2.3c1.tar.gz"))+"'},\n" +EXTRA_TEXT += " 'FOURSUITE_XML' : { 'setup': '4Suite-XML', 'url': 'ftp://ftp.4suite.org/pub/4Suite/4Suite-XML-1.0.2.tar.bz2', 'local': '"+ os.path.abspath(os.path.join(src_base,"4Suite-XML-1.0.2.tar.bz2"))+"'},\n" +EXTRA_TEXT += " 'PYLUCENE' : { 'setup': 'http://apache.crihan.fr/dist/lucene/pylucene/pylucene-3.0.1-1-src.tar.gz', 'url': 'http://apache.crihan.fr/dist/lucene/pylucene/pylucene-3.0.1-1-src.tar.gz', 'local': '"+ os.path.abspath(os.path.join(src_base,"pylucene-3.0.1-1-src.tar.gz"))+"'},\n" +EXTRA_TEXT += " 'PIL' : { 'setup': 'pil', 'url': 'http://effbot.org/downloads/Imaging-1.1.7.tar.gz', 'local': '"+ os.path.abspath(os.path.join(src_base,"Imaging-1.1.7.tar.gz"))+"'},\n" +EXTRA_TEXT += " 'PYXML' : { 'setup': 'http://sourceforge.net/projects/pyxml/files/pyxml/0.8.4/PyXML-0.8.4.tar.gz/download', 'url': 'http://sourceforge.net/projects/pyxml/files/pyxml/0.8.4/PyXML-0.8.4.tar.gz/download', 'local': '"+ os.path.abspath(os.path.join(src_base,"PyXML-0.8.4.tar.gz"))+"', 'patch': '"+os.path.join(patch_path,"pyxml.patch")+"'},\n" +EXTRA_TEXT += " 'JSON' : { 'setup': 'simplejson', 'url': 'http://pypi.python.org/packages/source/s/simplejson/simplejson-2.1.1.tar.gz', 'local': '"+ os.path.abspath(os.path.join(src_base,"simplejson-2.1.1.tar.gz"))+"'},\n" +EXTRA_TEXT += " 'DJANGO' : { 'setup': 'django', 'url': 'http://www.djangoproject.com/download/1.2.1/tarball/', 'local': '"+ os.path.abspath(os.path.join(src_base,"Django-1.2.1.tar.gz"))+"'},\n" +EXTRA_TEXT += " 'DJANGO-EXTENSIONS' : { 'setup': 'django-extensions', 'url':'http://django-command-extensions.googlecode.com/files/django-extensions-0.4.1.tar.gz', 'local':'"+ os.path.abspath(os.path.join(src_base,"django-extensions-0.4.1.tar.gz"))+"' },\n" +EXTRA_TEXT += " 'DJANGO-REGISTRATION' : { 'setup': 'django-registration', 'url':'http://bitbucket.org/ubernostrum/django-registration/get/tip.tar.gz', 'local':'"+ os.path.abspath(os.path.join(src_base,"django-registration.tar.gz"))+"' },\n" +EXTRA_TEXT += "}\n" + +EXTRA_TEXT += "import sys\n" +EXTRA_TEXT += "sys.path.append('"+lib_path+"')\n" + +EXTRA_TEXT += """ + +import shutil +import tarfile +import urllib +import platform +import patch + + +INDEX_URL = 'http://pypi.python.org/simple/' + + +def extend_parser(parser): + parser.add_option( + '--index-url', + metavar='INDEX_URL', + dest='index_url', + default='', + help='base URL of Python Package Index') + parser.add_option( + '--type-install', + metavar='type_install', + dest='type_install', + default='local', + help='type install : local, url, setup') + + +def adjust_options(options, args): + pass + + +def after_install(options, home_dir): + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) + base_dir = os.path.dirname(home_dir) + src_dir = join(home_dir, 'src') + tmp_dir = join(home_dir, 'tmp') + ensure_dir(src_dir) + ensure_dir(tmp_dir) + system_str = platform.system() + + res_source_key = options.type_install + + logger.indent += 2 + try: + + #get pylucene + logger.notify("Get Pylucene from %s " % URLS['PYLUCENE'][res_source_key]) + pylucene_src = os.path.join(src_dir,"pylucene.tar.gz") + urllib.urlretrieve(URLS['PYLUCENE'][res_source_key], pylucene_src) + tf = tarfile.open(pylucene_src,'r:gz') + pylucene_base_path = os.path.join(src_dir,"pylucene") + logger.notify("Extract Pylucene to %s " % pylucene_base_path) + tf.extractall(pylucene_base_path) + tf.close() + + pylucene_src_path = os.path.join(pylucene_base_path, os.listdir(pylucene_base_path)[0]) + jcc_src_path = os.path.abspath(os.path.join(pylucene_src_path,"jcc")) + + #install jcc + + #patch for linux + if system_str == 'Linux' : + olddir = os.getcwd() + patch_dest_path = os.path.join(lib_dir,'site-packages','setuptools-0.6c11-py'+'%s.%s' % (sys.version_info[0], sys.version_info[1])+'.egg') + logger.notify("Patch jcc : %s " % (patch_dest_path)) + os.chdir(patch_dest_path) + p = patch.fromfile(os.path.join(jcc_src_path,"jcc","patches","patch.43.0.6c11")) + p.apply() + os.chdir(olddir) + + logger.notify("Install jcc") + call_subprocess([os.path.abspath(os.path.join(home_dir, 'bin', 'python')), 'setup.py', 'install'], + cwd=jcc_src_path, + filter_stdout=filter_python_develop, + show_stdout=True) + #install pylucene + + logger.notify("Install pylucene") + #modify makefile + makefile_path = os.path.join(pylucene_src_path,"Makefile") + logger.notify("Modify makefile %s " % makefile_path) + shutil.move( makefile_path, makefile_path+"~" ) + + destination= open( makefile_path, "w" ) + source= open( makefile_path+"~", "r" ) + destination.write("PREFIX_PYTHON="+os.path.abspath(home_dir)+"\\n") + destination.write("ANT=ant\\n") + destination.write("PYTHON=$(PREFIX_PYTHON)/bin/python\\n") + + if system_str == "Darwin": + if sys.version_info >= (2,6): + destination.write("JCC=$(PYTHON) -m jcc.__main__ --shared --arch x86_64 --arch i386\\n") + else: + destination.write("JCC=$(PYTHON) -m jcc --shared --arch x86_64 --arch i386\\n") + destination.write("NUM_FILES=2\\n") + elif system_str == "Windows": + destination.write("JCC=$(PYTHON) -m jcc.__main__ --shared --arch x86_64 --arch i386\\n") + destination.write("NUM_FILES=2\\n") + else: + destination.write("JCC=$(PYTHON) -m jcc --shared\\n") + destination.write("NUM_FILES=2\\n") + for line in source: + destination.write( line ) + source.close() + destination.close() + os.remove(makefile_path+"~" ) + + logger.notify("pylucene make") + call_subprocess(['make'], + cwd=os.path.abspath(pylucene_src_path), + filter_stdout=filter_python_develop, + show_stdout=True) + + logger.notify("pylucene make install") + call_subprocess(['make', 'install'], + cwd=os.path.abspath(pylucene_src_path), + filter_stdout=filter_python_develop, + show_stdout=True) + + logger.notify("PyXML install : %s " % URLS['PYXML'][res_source_key]) + if sys.version_info >= (2,6): + logger.notify("PyXML -> python version >= 2.6 : patching") + pyxml_src = os.path.join(src_dir,"pyxml.tar.gz") + urllib.urlretrieve(URLS['PYXML'][res_source_key], pyxml_src) + logger.notify("PyXML -> python version >= 2.6 : extract archive") + tf = tarfile.open(pyxml_src,'r:gz') + pyxml_base_path = os.path.join(src_dir,"pyxml") + tf.extractall(pyxml_base_path) + tf.close() + + #patch + pyxml_version = os.listdir(pyxml_base_path)[0] + pyxml_path = os.path.join(pyxml_base_path, pyxml_version) + olddir = os.getcwd() + os.chdir(pyxml_path) + logger.notify("PyXML -> python version >= 2.6 : do patch %s : %s " % (pyxml_path, URLS['PYXML']['patch'])) + p = patch.fromfile(URLS['PYXML']['patch']) + p.apply() + os.chdir(olddir) + logger.notify("PyXML -> python version >= 2.6 : install") + call_subprocess([os.path.abspath(os.path.join(home_dir, 'bin', 'pip')), 'install', '-E', os.path.abspath(home_dir), '--build='+os.path.abspath(pyxml_base_path), '--no-download', pyxml_version], + cwd=os.path.abspath(tmp_dir), + filter_stdout=filter_python_develop, + show_stdout=True) + else: + call_subprocess([os.path.abspath(os.path.join(home_dir, 'bin', 'pip')), 'install', '-E', os.path.abspath(home_dir), URLS['PYXML'][res_source_key]], + cwd=os.path.abspath(tmp_dir), + filter_stdout=filter_python_develop, + show_stdout=True) + + + NORMAL_INSTALL = [ #(key,method) + ('DISTRIBUTE', 'pip', None), + ('PSYCOPG2', 'pip', None), + ('MYSQL', 'pip', None), + ('PIL', 'pip', None), + ('FOURSUITE_XML','easy_install', None), + ('DJANGO','pip', None), + ('DJANGO-EXTENSIONS', 'pip', None), + ('DJANGO-REGISTRATION', 'easy_install', '-Z') + ] + + if sys.version_info < (2,6): + NORMAL_INSTALL.append(('JSON','pip')) + + + for key, method, options in NORMAL_INSTALL: + logger.notify("Install %s from %s with %s" % (key,URLS[key][res_source_key],method)) + if method == 'pip': + args = [os.path.abspath(os.path.join(home_dir, 'bin', 'pip')), 'install', '-E', os.path.abspath(home_dir), URLS[key][res_source_key]] + if options : + args.insert(4,options) + call_subprocess(args, + cwd=os.path.abspath(tmp_dir), + filter_stdout=filter_python_develop, + show_stdout=True) + else: + args = [os.path.abspath(os.path.join(home_dir, 'bin', 'easy_install')), URLS[key][res_source_key]] + if options : + args.insert(1,options) + call_subprocess(args, + cwd=os.path.abspath(tmp_dir), + filter_stdout=filter_python_develop, + show_stdout=True) + + + logger.notify("Clear source dir") + shutil.rmtree(src_dir) + + finally: + logger.indent -= 2 + script_dir = join(base_dir, 'bin') + logger.notify('Run "%s Package" to install new packages that provide builds' + % join(script_dir, 'easy_install')) + +def ensure_dir(dir): + if not os.path.exists(dir): + logger.notify('Creating directory %s' % dir) + os.makedirs(dir) + +def filter_python_develop(line): + if not line.strip(): + return Logger.DEBUG + for prefix in ['Searching for', 'Reading ', 'Best match: ', 'Processing ', + 'Moving ', 'Adding ', 'running ', 'writing ', 'Creating ', + 'creating ', 'Copying ']: + if line.startswith(prefix): + return Logger.DEBUG + return Logger.NOTIFY +""" + +def main(): + python_version = ".".join(map(str,sys.version_info[0:2])) + text = virtualenv.create_bootstrap_script(EXTRA_TEXT, python_version=python_version) + if os.path.exists(script_name): + f = open(script_name) + cur_text = f.read() + f.close() + else: + cur_text = '' + print 'Updating %s' % script_name + if cur_text == 'text': + print 'No update' + else: + print 'Script changed; updating...' + f = open(script_name, 'w') + f.write(text) + f.close() + +if __name__ == '__main__': + main() + diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/lib/patch.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbin/virtualenv/res/lib/patch.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,589 @@ +""" Patch utility to apply unified diffs + + Brute-force line-by-line non-recursive parsing + + Copyright (c) 2008-2010 anatoly techtonik + Available under the terms of MIT license + + Project home: http://code.google.com/p/python-patch/ + + + $Id: patch.py 76 2010-04-08 19:10:21Z techtonik $ + $HeadURL: https://python-patch.googlecode.com/svn/trunk/patch.py $ +""" + +__author__ = "techtonik.rainforce.org" +__version__ = "10.04" + +import copy +import logging +import re +# cStringIO doesn't support unicode in 2.5 +from StringIO import StringIO +from logging import debug, info, warning + +from os.path import exists, isfile, abspath +from os import unlink + + +#------------------------------------------------ +# Logging is controlled by "python_patch" logger + +debugmode = False + +logger = logging.getLogger("python_patch") +loghandler = logging.StreamHandler() +logger.addHandler(loghandler) + +debug = logger.debug +info = logger.info +warning = logger.warning + +#: disable library logging by default +logger.setLevel(logging.CRITICAL) + +#------------------------------------------------ + + +def fromfile(filename): + """ Parse patch file and return Patch() object + """ + + info("reading patch from file %s" % filename) + fp = open(filename, "rb") + patch = Patch(fp) + fp.close() + return patch + + +def fromstring(s): + """ Parse text string and return Patch() object + """ + + return Patch( + StringIO.StringIO(s) + ) + + + +class HunkInfo(object): + """ Parsed hunk data container (hunk starts with @@ -R +R @@) """ + + def __init__(self): + self.startsrc=None #: line count starts with 1 + self.linessrc=None + self.starttgt=None + self.linestgt=None + self.invalid=False + self.text=[] + + def copy(self): + return copy.copy(self) + +# def apply(self, estream): +# """ write hunk data into enumerable stream +# return strings one by one until hunk is +# over +# +# enumerable stream are tuples (lineno, line) +# where lineno starts with 0 +# """ +# pass + + + +class Patch(object): + + def __init__(self, stream=None): + + # define Patch data members + # table with a row for every source file + + #: list of source filenames + self.source=None + self.target=None + #: list of lists of hunks + self.hunks=None + #: file endings statistics for every hunk + self.hunkends=None + + if stream: + self.parse(stream) + + def copy(self): + return copy.copy(self) + + def parse(self, stream): + """ parse unified diff """ + self.source = [] + self.target = [] + self.hunks = [] + self.hunkends = [] + + # define possible file regions that will direct the parser flow + header = False # comments before the patch body + filenames = False # lines starting with --- and +++ + + hunkhead = False # @@ -R +R @@ sequence + hunkbody = False # + hunkskip = False # skipping invalid hunk mode + + header = True + lineends = dict(lf=0, crlf=0, cr=0) + nextfileno = 0 + nexthunkno = 0 #: even if index starts with 0 user messages number hunks from 1 + + # hunkinfo holds parsed values, hunkactual - calculated + hunkinfo = HunkInfo() + hunkactual = dict(linessrc=None, linestgt=None) + + fe = enumerate(stream) + for lineno, line in fe: + + # analyze state + if header and line.startswith("--- "): + header = False + # switch to filenames state + filenames = True + #: skip hunkskip and hunkbody code until you read definition of hunkhead + if hunkbody: + # process line first + if re.match(r"^[- \+\\]", line): + # gather stats about line endings + if line.endswith("\r\n"): + self.hunkends[nextfileno-1]["crlf"] += 1 + elif line.endswith("\n"): + self.hunkends[nextfileno-1]["lf"] += 1 + elif line.endswith("\r"): + self.hunkends[nextfileno-1]["cr"] += 1 + + if line.startswith("-"): + hunkactual["linessrc"] += 1 + elif line.startswith("+"): + hunkactual["linestgt"] += 1 + elif not line.startswith("\\"): + hunkactual["linessrc"] += 1 + hunkactual["linestgt"] += 1 + hunkinfo.text.append(line) + # todo: handle \ No newline cases + else: + warning("invalid hunk no.%d at %d for target file %s" % (nexthunkno, lineno+1, self.target[nextfileno-1])) + # add hunk status node + self.hunks[nextfileno-1].append(hunkinfo.copy()) + self.hunks[nextfileno-1][nexthunkno-1]["invalid"] = True + # switch to hunkskip state + hunkbody = False + hunkskip = True + + # check exit conditions + if hunkactual["linessrc"] > hunkinfo.linessrc or hunkactual["linestgt"] > hunkinfo.linestgt: + warning("extra hunk no.%d lines at %d for target %s" % (nexthunkno, lineno+1, self.target[nextfileno-1])) + # add hunk status node + self.hunks[nextfileno-1].append(hunkinfo.copy()) + self.hunks[nextfileno-1][nexthunkno-1]["invalid"] = True + # switch to hunkskip state + hunkbody = False + hunkskip = True + elif hunkinfo.linessrc == hunkactual["linessrc"] and hunkinfo.linestgt == hunkactual["linestgt"]: + self.hunks[nextfileno-1].append(hunkinfo.copy()) + # switch to hunkskip state + hunkbody = False + hunkskip = True + + # detect mixed window/unix line ends + ends = self.hunkends[nextfileno-1] + if ((ends["cr"]!=0) + (ends["crlf"]!=0) + (ends["lf"]!=0)) > 1: + warning("inconsistent line ends in patch hunks for %s" % self.source[nextfileno-1]) + if debugmode: + debuglines = dict(ends) + debuglines.update(file=self.target[nextfileno-1], hunk=nexthunkno) + debug("crlf: %(crlf)d lf: %(lf)d cr: %(cr)d\t - file: %(file)s hunk: %(hunk)d" % debuglines) + + if hunkskip: + match = re.match("^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))?", line) + if match: + # switch to hunkhead state + hunkskip = False + hunkhead = True + elif line.startswith("--- "): + # switch to filenames state + hunkskip = False + filenames = True + if debugmode and len(self.source) > 0: + debug("- %2d hunks for %s" % (len(self.hunks[nextfileno-1]), self.source[nextfileno-1])) + + if filenames: + if line.startswith("--- "): + if nextfileno in self.source: + warning("skipping invalid patch for %s" % self.source[nextfileno]) + del self.source[nextfileno] + # double source filename line is encountered + # attempt to restart from this second line + re_filename = "^--- ([^\t]+)" + match = re.match(re_filename, line) + # todo: support spaces in filenames + if match: + self.source.append(match.group(1).strip()) + else: + warning("skipping invalid filename at line %d" % lineno) + # switch back to header state + filenames = False + header = True + elif not line.startswith("+++ "): + if nextfileno in self.source: + warning("skipping invalid patch with no target for %s" % self.source[nextfileno]) + del self.source[nextfileno] + else: + # this should be unreachable + warning("skipping invalid target patch") + filenames = False + header = True + else: + if nextfileno in self.target: + warning("skipping invalid patch - double target at line %d" % lineno) + del self.source[nextfileno] + del self.target[nextfileno] + nextfileno -= 1 + # double target filename line is encountered + # switch back to header state + filenames = False + header = True + else: + re_filename = "^\+\+\+ ([^\t]+)" + match = re.match(re_filename, line) + if not match: + warning("skipping invalid patch - no target filename at line %d" % lineno) + # switch back to header state + filenames = False + header = True + else: + self.target.append(match.group(1).strip()) + nextfileno += 1 + # switch to hunkhead state + filenames = False + hunkhead = True + nexthunkno = 0 + self.hunks.append([]) + self.hunkends.append(lineends.copy()) + continue + + if hunkhead: + match = re.match("^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))?", line) + if not match: + if nextfileno-1 not in self.hunks: + warning("skipping invalid patch with no hunks for file %s" % self.target[nextfileno-1]) + # switch to header state + hunkhead = False + header = True + continue + else: + # switch to header state + hunkhead = False + header = True + else: + hunkinfo.startsrc = int(match.group(1)) + hunkinfo.linessrc = 1 + if match.group(3): hunkinfo.linessrc = int(match.group(3)) + hunkinfo.starttgt = int(match.group(4)) + hunkinfo.linestgt = 1 + if match.group(6): hunkinfo.linestgt = int(match.group(6)) + hunkinfo.invalid = False + hunkinfo.text = [] + + hunkactual["linessrc"] = hunkactual["linestgt"] = 0 + + # switch to hunkbody state + hunkhead = False + hunkbody = True + nexthunkno += 1 + continue + else: + if not hunkskip: + warning("patch file incomplete - %s" % filename) + # sys.exit(?) + else: + # duplicated message when an eof is reached + if debugmode and len(self.source) > 0: + debug("- %2d hunks for %s" % (len(self.hunks[nextfileno-1]), self.source[nextfileno-1])) + + info("total files: %d total hunks: %d" % (len(self.source), sum(len(hset) for hset in self.hunks))) + + + def apply(self): + """ apply parsed patch """ + + total = len(self.source) + for fileno, filename in enumerate(self.source): + + f2patch = filename + if not exists(f2patch): + f2patch = self.target[fileno] + if not exists(f2patch): + warning("source/target file does not exist\n--- %s\n+++ %s" % (filename, f2patch)) + continue + if not isfile(f2patch): + warning("not a file - %s" % f2patch) + continue + filename = f2patch + + info("processing %d/%d:\t %s" % (fileno+1, total, filename)) + + # validate before patching + f2fp = open(filename) + hunkno = 0 + hunk = self.hunks[fileno][hunkno] + hunkfind = [] + hunkreplace = [] + validhunks = 0 + canpatch = False + for lineno, line in enumerate(f2fp): + if lineno+1 < hunk.startsrc: + continue + elif lineno+1 == hunk.startsrc: + hunkfind = [x[1:].rstrip("\r\n") for x in hunk.text if x[0] in " -"] + hunkreplace = [x[1:].rstrip("\r\n") for x in hunk.text if x[0] in " +"] + #pprint(hunkreplace) + hunklineno = 0 + + # todo \ No newline at end of file + + # check hunks in source file + if lineno+1 < hunk.startsrc+len(hunkfind)-1: + if line.rstrip("\r\n") == hunkfind[hunklineno]: + hunklineno+=1 + else: + debug("hunk no.%d doesn't match source file %s" % (hunkno+1, filename)) + # file may be already patched, but we will check other hunks anyway + hunkno += 1 + if hunkno < len(self.hunks[fileno]): + hunk = self.hunks[fileno][hunkno] + continue + else: + break + + # check if processed line is the last line + if lineno+1 == hunk.startsrc+len(hunkfind)-1: + debug("file %s hunk no.%d -- is ready to be patched" % (filename, hunkno+1)) + hunkno+=1 + validhunks+=1 + if hunkno < len(self.hunks[fileno]): + hunk = self.hunks[fileno][hunkno] + else: + if validhunks == len(self.hunks[fileno]): + # patch file + canpatch = True + break + else: + if hunkno < len(self.hunks[fileno]): + warning("premature end of source file %s at hunk %d" % (filename, hunkno+1)) + + f2fp.close() + + if validhunks < len(self.hunks[fileno]): + if self._match_file_hunks(filename, self.hunks[fileno]): + warning("already patched %s" % filename) + else: + warning("source file is different - %s" % filename) + if canpatch: + backupname = filename+".orig" + if exists(backupname): + warning("can't backup original file to %s - aborting" % backupname) + else: + import shutil + shutil.move(filename, backupname) + if self.write_hunks(backupname, filename, self.hunks[fileno]): + warning("successfully patched %s" % filename) + unlink(backupname) + else: + warning("error patching file %s" % filename) + shutil.copy(filename, filename+".invalid") + warning("invalid version is saved to %s" % filename+".invalid") + # todo: proper rejects + shutil.move(backupname, filename) + + # todo: check for premature eof + + + def can_patch(self, filename): + """ Check if specified filename can be patched. Returns None if file can + not be found among source filenames. False if patch can not be applied + clearly. True otherwise. + + :returns: True, False or None + """ + idx = self._get_file_idx(filename, source=True) + if idx == None: + return None + return self._match_file_hunks(filename, self.hunks[idx]) + + + def _match_file_hunks(self, filepath, hunks): + matched = True + fp = open(abspath(filepath)) + + class NoMatch(Exception): + pass + + lineno = 1 + line = fp.readline() + hno = None + try: + for hno, h in enumerate(hunks): + # skip to first line of the hunk + while lineno < h.starttgt: + if not len(line): # eof + debug("check failed - premature eof before hunk: %d" % (hno+1)) + raise NoMatch + line = fp.readline() + lineno += 1 + for hline in h.text: + if hline.startswith("-"): + continue + if not len(line): + debug("check failed - premature eof on hunk: %d" % (hno+1)) + # todo: \ No newline at the end of file + raise NoMatch + if line.rstrip("\r\n") != hline[1:].rstrip("\r\n"): + debug("file is not patched - failed hunk: %d" % (hno+1)) + raise NoMatch + line = fp.readline() + lineno += 1 + + except NoMatch: + matched = False + # todo: display failed hunk, i.e. expected/found + + fp.close() + return matched + + + def patch_stream(self, instream, hunks): + """ Generator that yields stream patched with hunks iterable + + Converts lineends in hunk lines to the best suitable format + autodetected from input + """ + + # todo: At the moment substituted lineends may not be the same + # at the start and at the end of patching. Also issue a + # warning/throw about mixed lineends (is it really needed?) + + hunks = iter(hunks) + + srclineno = 1 + + lineends = {'\n':0, '\r\n':0, '\r':0} + def get_line(): + """ + local utility function - return line from source stream + collecting line end statistics on the way + """ + line = instream.readline() + # 'U' mode works only with text files + if line.endswith("\r\n"): + lineends["\r\n"] += 1 + elif line.endswith("\n"): + lineends["\n"] += 1 + elif line.endswith("\r"): + lineends["\r"] += 1 + return line + + for hno, h in enumerate(hunks): + debug("hunk %d" % (hno+1)) + # skip to line just before hunk starts + while srclineno < h.startsrc: + yield get_line() + srclineno += 1 + + for hline in h.text: + # todo: check \ No newline at the end of file + if hline.startswith("-") or hline.startswith("\\"): + get_line() + srclineno += 1 + continue + else: + if not hline.startswith("+"): + get_line() + srclineno += 1 + line2write = hline[1:] + # detect if line ends are consistent in source file + if sum([bool(lineends[x]) for x in lineends]) == 1: + newline = [x for x in lineends if lineends[x] != 0][0] + yield line2write.rstrip("\r\n")+newline + else: # newlines are mixed + yield line2write + + for line in instream: + yield line + + + def write_hunks(self, srcname, tgtname, hunks): + src = open(srcname, "rb") + tgt = open(tgtname, "wb") + + debug("processing target file %s" % tgtname) + + tgt.writelines(self.patch_stream(src, hunks)) + + tgt.close() + src.close() + return True + + + def _get_file_idx(self, filename, source=None): + """ Detect index of given filename within patch. + + :param filename: + :param source: search filename among sources (True), + targets (False), or both (None) + :returns: int or None + """ + filename = abspath(filename) + if source == True or source == None: + for i,fnm in enumerate(self.source): + if filename == abspath(fnm): + return i + if source == False or source == None: + for i,fnm in enumerate(self.target): + if filename == abspath(fnm): + return i + + + + +from optparse import OptionParser +from os.path import exists +import sys + +if __name__ == "__main__": + opt = OptionParser(usage="%prog [options] unipatch-file", version="python-patch %s" % __version__) + opt.add_option("--debug", action="store_true", dest="debugmode", help="debug mode") + (options, args) = opt.parse_args() + + if not args: + opt.print_version() + opt.print_help() + sys.exit() + debugmode = options.debugmode + patchfile = args[0] + if not exists(patchfile) or not isfile(patchfile): + sys.exit("patch file does not exist - %s" % patchfile) + + + if debugmode: + loglevel = logging.DEBUG + logformat = "%(levelname)8s %(message)s" + else: + loglevel = logging.INFO + logformat = "%(message)s" + logger.setLevel(loglevel) + loghandler.setFormatter(logging.Formatter(logformat)) + + + + patch = fromfile(patchfile) + #pprint(patch) + patch.apply() + + # todo: document and test line ends handling logic - patch.py detects proper line-endings + # for inserted hunks and issues a warning if patched file has incosistent line ends diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/patch/pyxml.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbin/virtualenv/res/patch/pyxml.patch Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,28 @@ +diff -ur xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py b/xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py +--- xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py 2003-03-11 15:01:34.000000000 +0100 ++++ xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py 2009-05-25 16:32:26.000000000 +0200 +@@ -24,8 +24,8 @@ + self._rel = rel + nt = ParsedNodeTest.ParsedNodeTest('node', '') + ppl = ParsedPredicateList.ParsedPredicateList([]) +- as = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') +- self._step = ParsedStep.ParsedStep(as, nt, ppl) ++ asp = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') ++ self._step = ParsedStep.ParsedStep(asp, nt, ppl) + return + + def evaluate(self, context): +diff -ur a/xml/xpath/ParsedAbbreviatedRelativeLocationPath.py b/xml/xpath/ParsedAbbreviatedRelativeLocationPath.py +--- xml/xpath/ParsedAbbreviatedRelativeLocationPath.py 2003-03-11 15:01:34.000000000 +0100 ++++ xml/xpath/ParsedAbbreviatedRelativeLocationPath.py 2009-05-25 16:27:55.000000000 +0200 +@@ -28,8 +28,8 @@ + self._right = right + nt = ParsedNodeTest.ParsedNodeTest('node','') + ppl = ParsedPredicateList.ParsedPredicateList([]) +- as = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') +- self._middle = ParsedStep.ParsedStep(as, nt, ppl) ++ asp = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self') ++ self._middle = ParsedStep.ParsedStep(asp, nt, ppl) + + def evaluate(self, context): + res = [] diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/4Suite-XML-1.0.2.tar.bz2 Binary file sbin/virtualenv/res/src/4Suite-XML-1.0.2.tar.bz2 has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/Django-1.2.1.tar.gz Binary file sbin/virtualenv/res/src/Django-1.2.1.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/Imaging-1.1.7.tar.gz Binary file sbin/virtualenv/res/src/Imaging-1.1.7.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/MySQL-python-1.2.3c1.tar.gz Binary file sbin/virtualenv/res/src/MySQL-python-1.2.3c1.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/PyXML-0.8.4.tar.gz Binary file sbin/virtualenv/res/src/PyXML-0.8.4.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/distribute-0.6.13.tar.gz Binary file sbin/virtualenv/res/src/distribute-0.6.13.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/django-registration.tar.gz Binary file sbin/virtualenv/res/src/django-registration.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/psycopg2-2.2.1.tar.gz Binary file sbin/virtualenv/res/src/psycopg2-2.2.1.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/pylucene-3.0.1-1-src.tar.gz Binary file sbin/virtualenv/res/src/pylucene-3.0.1-1-src.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf sbin/virtualenv/res/src/simplejson-2.1.1.tar.gz Binary file sbin/virtualenv/res/src/simplejson-2.1.1.tar.gz has changed diff -r 000000000000 -r ecdfc63274bf web/eulalie/.htaccess.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/.htaccess.tmpl Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,12 @@ +SetHandler python-program +PythonHandler ldt.core.handlers.modpython +SetEnv DJANGO_SETTINGS_MODULE eulalie.settings +SetEnv PY_USE_XMLPLUS true +PythonInterpreter eulalie +PythonOption django.root /~ymh/eulalie/eulalie +PythonOption virtualenv.activate_path /Users/ymh/dev/workspace/eulalie/sbin/virtualenv/env/venv/bin/activate_this.py +PythonDebug on +PythonPath "['/Users/ymh/Sites/eulalie'] + sys.path" +Header set Pragma "no-cache" +Header set Cache-Control "no-cache" +Header set Expires "-1" diff -r 000000000000 -r ecdfc63274bf web/eulalie/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/__init__.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,16 @@ +VERSION = (0,2) + +VERSION_STR = unicode(".".join(map(lambda i:"%02d" % (i,), VERSION))) + + +def get_version(): + version = '%s.%s' % (VERSION[0], VERSION[1]) + if VERSION[2]: + version = '%s.%s' % (version, VERSION[2]) + if VERSION[3:] == ('alpha', 0): + version = '%s pre-alpha' % version + else: + if VERSION[3] != 'final': + version = '%s %s %s' % (version, VERSION[3], VERSION[4]) + return version + diff -r 000000000000 -r ecdfc63274bf web/eulalie/config.py.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/config.py.tmpl Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,62 @@ +import os, logging + +SITE_ID = 1 + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)).lstrip("/")+"/" +BASE_URL = '/~ymh/eulalie/' +WEB_URL = 'http://localhost/' +MEDIA_BASE_URL = BASE_URL + 'static/' +STREAM_URL = MEDIA_BASE_URL + "/content/" + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = os.path.abspath(BASE_DIR + "../static/") + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = MEDIA_BASE_URL + +CONTENT_ROOT = MEDIA_ROOT + "media/content/" + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = MEDIA_URL + 'admin/' +IRIUSER_MEDIA_PREFIX = MEDIA_URL + 'iriuser/' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': 'eulalie', # Or path to database file if using sqlite3. + 'USER': 'iri', # Not used with sqlite3. + 'PASSWORD': 'iri', # Not used with sqlite3. + 'HOST': 'localhost', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '5432', # Set to empty string for default. Not used with sqlite3. + } +} + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +LOG_FILE = os.path.join(BASE_DIR,"../log/log.txt") +LOG_LEVEL = logging.DEBUG + +INDEX_PATH = os.path.abspath(BASE_DIR + "../index/") + + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +EMAIL_USE_TLS = True +EMAIL_HOST = 'smtp.gmail.com' +EMAIL_HOST_USER = 'iri.ddc@gmail.com' +EMAIL_HOST_PASSWORD = 'ddciripompidou' +EMAIL_PORT = 587 + +ACCOUNT_ACTIVATION_DAYS = 7 +REGISTRATION_OPEN = False + diff -r 000000000000 -r ecdfc63274bf web/eulalie/locale/fr/LC_MESSAGES/django.mo Binary file web/eulalie/locale/fr/LC_MESSAGES/django.mo has changed diff -r 000000000000 -r ecdfc63274bf web/eulalie/locale/fr/LC_MESSAGES/django.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/locale/fr/LC_MESSAGES/django.po Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,105 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-17 02:27+0100\n" +"PO-Revision-Date: 2010-02-17 02:57+0100\n" +"Last-Translator: Yves-Marie Haussonne \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: settings.py:38 +msgid "French" +msgstr "Français" + +#: templates/base.html:53 +msgid "Langue" +msgstr "Langue" + +#: templates/iriuser/user/login_form.html:38 +msgid "Profiles" +msgstr "Profile" + +#: templates/iriuser/user/login_form.html:39 +msgid "Space" +msgstr "Esp. perso." + +#: templates/iriuser/user/login_form.html:41 +msgid "Create an account" +msgstr "Créer un compte" + +#: templates/iriuser/user/login_form.html:43 +msgid "Log out" +msgstr "déconnexion" + +#: templates/iriuser/user/login_form.html:46 +#: templates/iriuser/user/login_form.html:54 +#: templates/registration/login.html:14 +msgid "Log in" +msgstr "Connexion" + +#: templates/iriuser/user/login_form.html:59 +msgid "create account" +msgstr "Créer un compte" + +#: templates/iriuser/user/login_form.html:63 +msgid "Pseudo" +msgstr "Pseudo" + +#: templates/iriuser/user/login_form.html:66 +#: templates/iriuser/user/login_form.html:73 +msgid "this field is compulsory" +msgstr "Ce champs et obligatoire" + +#: templates/iriuser/user/login_form.html:70 +msgid "Password" +msgstr "Mot de passe" + +#: templates/iriuser/user/login_form.html:77 +msgid "reset password" +msgstr "Réinitialiser le mot de passe" + +#: templates/iriuser/user/login_form.html:80 +msgid "Connection" +msgstr "Connexion" + +#: templates/tictac/workspace.html:34 +msgid "content list" +msgstr "Liste des contenus" + +#: templates/tictac/workspace.html:39 +#: templates/tictac/workspace.html:52 +msgid "open ldt" +msgstr "Ouvrir sous Lignes de Temps" + +#: templates/tictac/workspace.html:40 +msgid "create project" +msgstr "Créer un projet" + +#: templates/tictac/workspace.html:47 +msgid "project list" +msgstr "Liste des projets" + +#: templates/tictac/workspace.html:53 +msgid "copy project" +msgstr "Copier projet" + +#: templates/registration/login.html:17 +msgid "Sorry, that's not a valid username or password." +msgstr "Désolé, mais ce n'est pas un identifiant ou un mot de passe valide" + +#: templates/registration/login.html:25 +msgid "login" +msgstr "Connexion" + +#: templates/registration/login.html:29 +msgid "Forget password?" +msgstr "Mot de passe oublié ?" + diff -r 000000000000 -r ecdfc63274bf web/eulalie/manage.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/manage.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff -r 000000000000 -r ecdfc63274bf web/eulalie/settings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/settings.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,137 @@ +#@PydevCodeAnalysisIgnore +import os.path +# Django settings for eulalie project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': '', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/Paris' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'fr-fr' + +ugettext = lambda s: s + +LANGUAGES = ( + ('fr', ugettext('French')), +) + + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +IRIUSER_MEDIA_PREFIX = '/iriuser/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 't^lii5_z@tho$%6t&b#dm#t9nz$$ylyclxvkdiyqbl+(dnt(ma' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +) + +TEMPLATE_CONTEXT_PROCESSORS = ( + "django.core.context_processors.auth", + "django.core.context_processors.debug", + "django.core.context_processors.i18n", + "django.core.context_processors.media", + "iriuser.utils.context_processors.iriuser", + "eulalie.utils.context_processors.version", + "eulalie.utils.context_processors.base", +) + + +ROOT_URLCONF = 'eulalie.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join(os.path.basename(__file__), 'templates'), +) + +INSTALLED_APPS = ( + 'django_extensions', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.admin', + 'eulalie', + 'registration', + 'iriuser', + 'iriuser.core', + 'iriuser.ldt', + 'iriuser.user', + 'iriuser.management', +) + +DECOUPAGE_BLACKLIST = ( + "de_PPP", +) + +ZIP_BLACKLIST = ( + "__MACOSX", +) + +from config import * + +LOGIN_URL = BASE_URL + 'eulalie/accounts/login/' +LOGOUT_URL = BASE_URL + 'eulalie' +ACCOUNT_ACTIVATION_DAYS = 7 + + + + diff -r 000000000000 -r ecdfc63274bf web/eulalie/templates/base.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/templates/base.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,83 @@ +{% load i18n %} +{% load logintag %} + + + + + + {% block title %}Tic-Tac{% endblock %} + {% block js_import %} + + + + {% endblock %} + {% block css_import %} + + + + + + + + {% endblock %} + + {% block js_declaration %} + {% endblock %} + + + +
+ + + +
+ +
+ {% block toolbar %} + + + + + +
{% block login %}{% loginAjax user%}{% endblock %} + {% if LANGUAGES.1 %} +
+
+ + + +
+
+ {% endif %} +
+ {% endblock %} +
+
+ {% block content %}{% endblock %} +
+
+ +
+ + diff -r 000000000000 -r ecdfc63274bf web/eulalie/templates/eulalie/workspace.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/templates/eulalie/workspace.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,78 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block js_declaration %} +{{block.super}} + + +{% endblock %} + +{% block css_import %} +{{block.super}} + +{% endblock %} + +{% block content %} + +
+

{% trans "content list" %}

+ +{% for content in contents %} + + + + + +{% endfor %} +
{{ content.title }}{% trans "open ldt" %}{% trans "create project" %}
+
+ +
+

{% trans "project list" %}

+ +{% for project in projects %} + + + + + +{% endfor %} +
{{ project.title }}{% trans "open ldt" %}{% trans "copy project" %}
+
+ +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/eulalie/templates/iriuser/user/login_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/templates/iriuser/user/login_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,78 @@ +{% load i18n %} +{# print user's state and form of login #} +{% block js_import %} +{{block.super}} + + +{% endblock %} +{% block css_import %} +{{block.super}} +{% endblock %} +
+
diff -r 000000000000 -r ecdfc63274bf web/eulalie/templates/registration/login.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/templates/registration/login.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,34 @@ +{% extends "registration/base.html" %} +{% load i18n %} +{% block js_declaration %}{{ block.super }} + +{% endblock %} + +{% block login %} +{% endblock %} + +{% block content_title %}{% trans 'Log in' %}{% endblock %} +{% block iricontent %} + {% if form.errors %} +

{% trans "Sorry, that's not a valid username or password." %}

+ {% endif %} + +
+ {% csrf_token %} + +
    + {{form.as_ul}} +
  • +
+
+ +{% endblock %} + + + diff -r 000000000000 -r ecdfc63274bf web/eulalie/urls.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/urls.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,25 @@ +from django.conf.urls.defaults import patterns,include +from django.contrib import admin + +# Uncomment the next two lines to enable the admin: +admin.autodiscover() + +urlpatterns = patterns('', + # Example: + # (r'^eulalie/', include('eulalie.foo.urls')), + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + (r'^admin/', include(admin.site.urls)), + (r'^i18n/', include('django.conf.urls.i18n')), + + (r'^ldt/', include('iriuser.ldt.urls')), + (r'^user/', include('iriuser.user.urls')), + + (r'^accounts/', include('registration.backends.default.urls')), + + (r'^/?$', "eulalie.views.workspace"), +) diff -r 000000000000 -r ecdfc63274bf web/eulalie/utils/__init__.py diff -r 000000000000 -r ecdfc63274bf web/eulalie/utils/context_processors.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/utils/context_processors.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,11 @@ +from django.conf import settings +import eulalie #@UnresolvedImport + +def version(request): + return {'VERSION': eulalie.VERSION_STR } + +def base(request): + return {'BASE_URL': settings.BASE_URL, 'MEDIA_URL': settings.MEDIA_URL } + +def web(request): + return {'WEB_URL': settings.WEB_URL } diff -r 000000000000 -r ecdfc63274bf web/eulalie/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/eulalie/views.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,19 @@ +from django.shortcuts import render_to_response +from django.contrib.auth.decorators import login_required +from django.template import RequestContext +from iriuser.ldt.models import Content, Project + + +@login_required +def workspace(request): + + # list of contents + content_list = Content.objects.all() + + # get list of projects + project_list = Project.objects.filter(state=2) + + # render list + return render_to_response("eulalie/workspace.html", + {'contents': content_list, 'projects': project_list}, + context_instance=RequestContext(request)) diff -r 000000000000 -r ecdfc63274bf web/index/.keepme diff -r 000000000000 -r ecdfc63274bf web/ldt/.htaccess.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/.htaccess.tmpl Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,11 @@ +SetHandler python-program +PythonPath "['D:/wuj/dev/ldt', 'D:/wuj/dev/ldt/lib'] + sys.path" +PythonHandler django.core.handlers.modpython +SetEnv DJANGO_SETTINGS_MODULE ldt.settings +SetEnv PY_USE_XMLPLUS true +PythonInterpreter ldt +PythonOption django.root /dev/ldt/ldt +PythonDebug on +Header set Pragma "no-cache" +Header set Cache-Control "no-cache" +Header set Expires "-1" \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/__init__.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,3 @@ +VERSION = (0,1) + +VERSION_STR = unicode(".".join(map(lambda i:"%02d" % (i,), VERSION))) diff -r 000000000000 -r ecdfc63274bf web/ldt/admin.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/admin.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,30 @@ +from django.contrib import admin +from ldt.management import test_cms + +""" +site admin pour cms page +""" +if test_cms(): + class AdminSite(admin.AdminSite): + index_template = 'admin/page_index.html' + login_template = 'admin/page_login.html' + app_index_template = 'admin/page_app_index.html' + + admin_site = AdminSite() + + from cms.models import Page + from cms.admin import pageadmin + + class CmsPageAdmin(pageadmin.PageAdmin): + change_list_template = "admin/cms_change_list.html" + change_form_template = "admin/cms_change_form.html" + + admin_site.register(Page, CmsPageAdmin) + + from cms.plugins.snippet.models import Snippet + from cms.plugins.snippet.admin import SnippetAdmin + + class CmsSnippetAdmin(SnippetAdmin): + change_form_template = "admin/page_change_form.html" + change_list_template = "admin/page_change_list.html" + admin_site.register(Snippet, CmsSnippetAdmin) \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/core/__init__.py diff -r 000000000000 -r ecdfc63274bf web/ldt/core/handlers/__init__.py diff -r 000000000000 -r ecdfc63274bf web/ldt/core/handlers/modpython.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/core/handlers/modpython.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,6 @@ +import django.core.handlers.modpython + +def handler(req): + activate_this = req.get_options().get("virtualenv.activate_path") + execfile(activate_this, dict(__file__=activate_this)) + return django.core.handlers.modpython.handler(req) \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/core/models.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/core/models.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,22 @@ +from django.db import models +from django.contrib.auth.models import * + + +class Owner(models.Model): + user = models.ForeignKey(User, blank=True, null=True) + group = models.ForeignKey(Group, blank=True, null=True) + + def __unicode__(self): + if self.user: + return self.user.username + else: + return self.group.name + + +class Document(models.Model): + owner= models.ForeignKey(Owner, blank = True, null=True) + + class Meta: + abstract = True + + diff -r 000000000000 -r ecdfc63274bf web/ldt/core/tests.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/core/tests.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff -r 000000000000 -r ecdfc63274bf web/ldt/core/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/core/views.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,1 @@ +# Create your views here. diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/__init__.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +import lucene +from django.conf import settings + +lucene.initVM(lucene.CLASSPATH) + +STORE = lucene.FSDirectory.getDirectory(settings.INDEX_PATH, False) +ANALYZER = lucene.PerFieldAnalyzerWrapper(lucene.StandardAnalyzer()) +ANALYZER.addAnalyzer("tags",lucene.FrenchAnalyzer()) +ANALYZER.addAnalyzer("title",lucene.FrenchAnalyzer()) +ANALYZER.addAnalyzer("abstract",lucene.FrenchAnalyzer()) +ANALYZER.addAnalyzer("all",lucene.FrenchAnalyzer()) + +VERSION = (0,1) +VERSION_STR = unicode(".".join(map(lambda i:"%02d" % (i,), VERSION))) diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/admin.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/admin.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,81 @@ +from django.contrib import admin +from django.conf.urls.defaults import * +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.conf import settings +from models import * +from forms import * +from fileimport import * +from ldt.ldt import STORE +from ldt.ldt import ANALYZER + +import lucene + +admin.site.register(Project) + +class ContentAdmin(admin.ModelAdmin): + + def import_file(self, request): + if request.method =='POST': + form = LdtImportForm(request.POST, request.FILES) + if form.is_valid(): + filetoprocess =form.cleaned_data['importFile'] + flatten = form.cleaned_data['flatten'] + videoPath = form.cleaned_data['videoPath'] + # fi = None + fi = FileImport(filetoprocess, videoPath, flatten) + try: + fi.processFile() + args = {'message': "File imported"} + except FileImportError: + non_field_errors = form.non_field_errors() + non_field_errors.append("Error when importing : unknown file type") + form._errors["__all__"] = non_field_errors + args = {'message': "Can not import file, unknown file type", 'form': form} + + else: + non_field_errors = form.non_field_errors() + non_field_errors.append("Error when importing : invalid form") + form._errors["__all__"] = non_field_errors + args = {'message': "Error when importing : invalid form", 'form': form} + else: + form = LdtImportForm() + args = {'form': form, 'current_app': self.admin_site.name, 'current_action' : 'import_file'} + return render_to_response('admin/ldt/content/upload_form.html', args, context_instance=RequestContext(request)) + + def reindex(self, request): + message = None + if request.method == "POST": + form = ReindexForm(request.POST) + if form.is_valid(): + # try: + writer = lucene.IndexWriter(STORE, ANALYZER, True) + writer.setMaxFieldLength(1048576) + contentList = form.cleaned_data["contents"] + indexer = ContentIndexer(contentList,writer) + indexer.index_all() + + writer.close() + message = "Indexation ok : " + repr(form.cleaned_data["contents"]) + form = ReindexForm() + # except Exception, inst: + # non_field_errors = form.non_field_errors() + # non_field_errors.append("Error when reindexing : " + cgi.escape(repr(inst))) + # form._errors["__all__"] = non_field_errors + #message = "ERROR : " + repr(non_field_errors) + else: + form = ReindexForm() + + return render_to_response('admin/ldt/content/reindex_form.html', {'form': form, 'message':message, 'current_app': self.admin_site.name, 'current_action' : 'reindex' }, context_instance=RequestContext(request)) + + def get_urls(self): + urls = super(ContentAdmin, self).get_urls() + content_urls = patterns('', + url(r'^reindex/$', self.admin_site.admin_view(self.reindex), name="ldt_content_reindex"), + # (r'^admin/ldt/content/import/upload/$', 'ldt.ldt.views.uploadFile'), + url(r'^import/$', self.admin_site.admin_view(self.import_file), name="ldt_content_import_file") + ) + return content_urls + urls + + +admin.site.register(Content, ContentAdmin) diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/contentindexer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/contentindexer.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,206 @@ +import tempfile +import os +import os.path +import shutil +from ldt.utils import zipfileext +import urllib +# import ldt.utils.log +import ldt.utils.xml +from django.conf import settings +from models import Content +import xml +import xml.dom +import xml.dom.minidom +import xml.dom.ext +import xml.xpath +import fnmatch +import uuid +import shutil +import lucene +from ldt.ldt import STORE +from ldt.ldt import ANALYZER + +def Property(func): + return property(**func()) + + +class ContentIndexer(object): + + def __init__(self, contentList, writer, decoupage_blackList = settings.DECOUPAGE_BLACKLIST): + self.__contentList = contentList + self.__decoupage_blacklist = decoupage_blackList + self.__writer = writer + + @Property + def decoupage_blacklist(): #@NoSelf + doc = """get blacklist""" #@UnusedVariable + + def fget(self): + if self.__decoupage_blacklist is None: + self.__decoupage_blacklist = () + return self.__decoupage_blacklist + + def fset(self, value): + self.__decoupage_blacklist = value + + def fdel(self): + del self.__decoupage_blacklist + + return locals() + + def index_all(self): + for content in self.__contentList: + self.index_content(content) + + def index_content(self, content): + url =content.iri_url() + filepath = urllib.urlopen(url) + doc = xml.dom.minidom.parse(filepath) + + self.__writer.deleteDocuments(lucene.Term("iri_id", content.iri_id)) + + con = xml.xpath.Context.Context(doc, 1, 1, None) + res = xml.xpath.Evaluate("/iri/body/ensembles/ensemble", context=con) + + for ensemble in res: + ensembleId = ensemble.getAttribute("id") + + for decoupageNode in ensemble.childNodes: + if decoupageNode.nodeType != xml.dom.Node.ELEMENT_NODE or decoupageNode.tagName != "decoupage" or decoupageNode.getAttribute("id") in self.decoupage_blacklist: + continue + + decoupId = decoupageNode.getAttribute("id") + res = xml.xpath.Evaluate("elements/element", decoupageNode) + for elementNode in res: + doc = lucene.Document() + elementId = elementNode.getAttribute("id") + tags = elementNode.getAttribute("tags") + + if tags is not None: + tags.replace(",", ";") + + if tags is None or len(tags) == 0: + tags = "" + restagnode = xml.xpath.Evaluate("tag/text()", elementNode) + for tagnode in restagnode: + tags = tags + " ; " + tagnode.data + + if tags is None or len(tags) == 0: + tags = "" + restagnode = xml.xpath.Evaluate("tags/tag/text()", elementNode) + for tagnode in restagnode: + tags = tags + " ; " + tagnode.data + + title = "" + for txtRes in xml.xpath.Evaluate("title/text()", elementNode): + title = title + txtRes.data + + abstract = "" + for txtRes in xml.xpath.Evaluate("abstract/text()", elementNode): + abstract = abstract + txtRes.data + + doc.add(lucene.Field("iri_id", content.iri_id, lucene.Field.Store.YES, lucene.Field.Index.UN_TOKENIZED)) + doc.add(lucene.Field("ensemble_id", ensembleId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("decoupage_id", decoupId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("element_id", elementId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("title", title, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + + self.__writer.addDocument(doc) + + self.__writer.flush() + + +class ProjectIndexer(object): + + def __init__(self, projectList, writer, decoupage_blackList = settings.DECOUPAGE_BLACKLIST): + self.__projectList = projectList + self.__decoupage_blacklist = decoupage_blackList + self.__writer = writer + + @Property + def decoupage_blacklist(): #@NoSelf + doc = """get blacklist""" #@UnusedVariable + + def fget(self): + if self.__decoupage_blacklist is None: + self.__decoupage_blacklist = () + return self.__decoupage_blacklist + + def fset(self, value): + self.__decoupage_blacklist = value + + def fdel(self): + del self.__decoupage_blacklist + + return locals() + + def index_all(self): + for project in self.__projectList: + self.index_project(project) + + def index_project(self, project): + + # pocketfilms.utils.log.debug("Indexing project : "+str(project.iri_id)) + doc = xml.dom.minidom.parseString(project.ldt) + + self.__writer.deleteDocuments(lucene.Term("iri_id", project.iri_id)) + + con = xml.xpath.Context.Context(doc, 1, 1, None) + res = xml.xpath.Evaluate("/iri/annotations/content", context=con) + + for content in res: + contentId = content.getAttribute("id") + + ensembleId = "ens_perso" + + for decoupageNode in content.childNodes: + # pocketfilms.utils.log.debug("Indexing content decoupage : "+ repr(decoupageNode.nodeType) + " in " + repr(self.decoupage_blacklist)) + if decoupageNode.nodeType != xml.dom.Node.ELEMENT_NODE or decoupageNode.tagName != "decoupage" or decoupageNode.getAttribute("id") in self.decoupage_blacklist: + continue + + decoupId = decoupageNode.getAttribute("id") + res = xml.xpath.Evaluate("elements/element", decoupageNode) + for elementNode in res: + doc = lucene.Document() + elementId = elementNode.getAttribute("id") + tags = elementNode.getAttribute("tags") + + if tags is not None: + tags.replace(",", ";") + + if tags is None or len(tags) == 0: + tags = "" + restagnode = xml.xpath.Evaluate("tag/text()", elementNode) + for tagnode in restagnode: + tags = tags + " ; " + tagnode.data + + if tags is None or len(tags) == 0: + tags = "" + restagnode = xml.xpath.Evaluate("tags/tag/text()", elementNode) + for tagnode in restagnode: + tags = tags + " ; " + tagnode.data + + title = "" + for txtRes in xml.xpath.Evaluate("title/text()", elementNode): + title = title + txtRes.data + + abstract = "" + for txtRes in xml.xpath.Evaluate("abstract/text()", elementNode): + abstract = abstract + txtRes.data + + doc.add(lucene.Field("project_id", project.iri_id, lucene.Field.Store.YES, lucene.Field.Index.UN_TOKENIZED)) + doc.add(lucene.Field("iri_id", contentId, lucene.Field.Store.YES, lucene.Field.Index.UN_TOKENIZED)) + doc.add(lucene.Field("ensemble_id", ensembleId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("decoupage_id", decoupId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("element_id", elementId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("title", title, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + + self.__writer.addDocument(doc) + + self.__writer.flush() diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/fileimport.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/fileimport.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,375 @@ +import tempfile +import os.path +import shutil +from django.core.exceptions import ObjectDoesNotExist +from ldt.utils import zipfileext +from django.conf import settings +from models import Content +import xml.dom.minidom +import xml.dom.ext #@UnresolvedImport +import xml.xpath #@UnresolvedImport +import fnmatch +import uuid +import urllib + +class FileImportError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + + +def Property(func): + return property(**func()) + +class IriInfo(object): + + + def __init__(self, id, order, titledesc, basepath="", videopath=settings.STREAM_URL, decoupage_blacklist = settings.DECOUPAGE_BLACKLIST, flatten = True): + self.id = id + self.basepath = basepath + self.order = order + self.src = "" + self.annotations = None + self.videopath = videopath + self.videourl = "" + self.title = None + self.desc = None + self.created = False + self.content = None + self.decoupage_blacklist = decoupage_blacklist + if self.decoupage_blacklist is None: + self.decoupage_blacklist = () + self.flatten = flatten + + + + def processIri(self): + # for just import a file ldt and get the title for every media + if 'http' in self.src: + url = urllib.urlopen(self.src) + doc = xml.dom.minidom.parse(url) + con = xml.xpath.Context.Context(doc, 1, 1, None) + #open .iri and get the title + res = xml.xpath.Evaluate("/iri/head/meta[@name='title']/@content", context=con) + self.title = res[0].value + + #for import a zip, get title and copy file .iri in the media directory + else: + path = os.path.join(self.basepath, self.src) + doc = xml.dom.minidom.parse(path) + + con = xml.xpath.Context.Context(doc, 1, 1, None) + + res = xml.xpath.Evaluate("/iri/head/meta[@name='title']/@content", context=con) + self.title = res[0].value + + res = xml.xpath.Evaluate("/iri/body/ensembles",context=con) + ensemblesnode = res[0] + + ensembleids = [] + + for node in ensemblesnode.childNodes: + if node.nodeType == xml.dom.Node.ELEMENT_NODE and node.tagName == "ensemble": + id = node.getAttribute("id") + if id not in ensembleids: + ensembleids.append(id) + + if self.annotations is not None: + newEnsemble = None + for cnode in self.annotations.childNodes: + if cnode.nodeType == xml.dom.Node.ELEMENT_NODE and cnode.tagName == "decoupage": + if newEnsemble is None: + newensemble = doc.createElement('ensemble') + ensembleid = self.id+"_"+str(uuid.uuid1()) + newensemble.setAttribute('id',ensembleid) + + newensemble.setAttribute('title', self.annotations.getAttribute('title')) + newensemble.setAttribute('author', self.annotations.getAttribute('author')) + newensemble.setAttribute('date', self.annotations.getAttribute('date')) + newensemble.setAttribute('abstract', self.annotations.getAttribute('abstract')) + ensemblesnode.appendChild(newensemble) + ensembleids.append(ensembleid) + newDecoupageNode = cnode.cloneNode(True) + newensemble.appendChild(newDecoupageNode) + elif cnode.nodeType == xml.dom.Node.ELEMENT_NODE and cnode.tagName == "ensemble": + ensembleid = cnode.getAttribute(u"id") + cloneNode = cnode.cloneNode(True) + if ensembleid in ensembleids: + ensembleid = self.id+"_"+str(uuid.uuid1()) + cloneNode.setAttribute(u"id", ensembleid) + ensembleids.append(ensembleid) + ensemblesnode.appendChild(cloneNode) + + if self.flatten: + res = xml.xpath.Evaluate("/iri/body/medias/media[@id='video']/video", context=con) + src_video = res[0].getAttribute('src') + self.videourl = os.path.basename(src_video) + res[0].setAttribute('src', self.videourl) + + f = open(path, "w") + try: + xml.dom.ext.Print(doc, stream=f) + finally: + f.close() + + + destPath = os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "media"), "ldt"), self.id); + if not os.path.exists(destPath): + os.makedirs(destPath) + shutil.move(os.path.join(self.basepath, self.src), os.path.join(destPath, os.path.basename(self.src))) + self.src = self.id + u"/" + os.path.basename(self.src) + + + + def saveContent(self): + #if 'http' in self.src: + # url = self.src + #else: + # url = self.id + u"/" + os.path.basename(self.src) + content, self.created = Content.objects.get_or_create(iri_id=self.id, defaults = {'iriurl': self.src, 'title':self.title, 'description':self.desc, 'videopath': self.videopath}) + if not self.created: + content.iriurl = self.src + content.title = self.title + content.description = self.desc + content.save() + + content.iriurl = self.src + content.videopath = self.videopath.rstrip("/") + "/" + + content.iri = self.id + u"/" + os.path.basename(self.src) + content.title = self.title + content.description = self.desc + content.save() + + self.content = content + + def process(self): + self.processIri() + self.saveContent() + +class BaseFileImport(object): + + def __init__(self, filepath, videopath): + self.__filepath = filepath + self.__tempdir = "" + self.__videopath = videopath + self.__author = None + + + def filepath(): #@NoSelf + doc = """Docstring""" #@UnusedVariable + + def fget(self): + return self.__filepath + + def fset(self, value): + self.__filepath = value + + def fdel(self): + del self.__filepath + + return locals() + + filepath = property(**filepath()) + + def videopath(): #@NoSelf + doc = """Docstring""" #@UnusedVariable + + def fget(self): + return self.__videopath + + def fset(self, value): + self.__videopath = value + + def fdel(self): + del self.__videopath + + return locals() + + videopath = property(**videopath()) + + def author(): #@NoSelf + doc = """Docstring""" #@UnusedVariable + + def fget(self): + return self.__author + + def fset(self, value): + self.__author = value + + def fdel(self): + del self.__author + + return locals() + + author = property(**author()) + + +class FileImport(BaseFileImport): + + def __init__(self, filepath, videopath, flatten): + BaseFileImport.__init__(self, filepath, videopath) + self.__checkExistingMedia = False + self.__flatten = flatten + + def checkExistingMedia(): #@NoSelf + doc = """Docstring""" #@UnusedVariable + + def fget(self): + return self.__checkExistingMedia + + def fset(self, value): + self.__checkExistingMedia = value + + def fdel(self): + del self.__checkExistingMedia + + return locals() + + checkExistingMedia = property(**checkExistingMedia()) + + def flatten(): #@NoSelf + doc = """Docstring""" #@UnusedVariable + + def fget(self): + return self.__flatten + + def fset(self, value): + self.__flatten = value + + def fdel(self): + del self.__flatten + + return locals() + flatten = property(**flatten()) + + def processLdt(self, ldtpath=None): + + # list iri + # see if there is some comments + # inject comment in iri + # copy iri in folder + # create or update content + contents = {} + if ldtpath: + doc = xml.dom.minidom.parse(ldtpath) + else: + doc = xml.dom.minidom.parse(self.filepath) + + con = xml.xpath.Context.Context(doc, 1, 1, None) + + #get author from file ldt + result = xml.xpath.Evaluate("/iri/project", context=con) + for pnode in result: + author = pnode.getAttribute("user") + if author: + self.author = unicode(author) + break + + result = xml.xpath.Evaluate("/iri/medias/media", context=con) + + for i, medianode in enumerate(result): + # get iri file's id from file ldt + id = medianode.attributes['id'].value + if self.checkExistingMedia: + try: + Content.objects.get(iri_id=id) + do_pass = True + except ObjectDoesNotExist: #Content.DoesNotExist + do_pass = False + else: + do_pass = False + if not do_pass: + if not (contents.has_key(id)): + # Create instance iriInfo(id, order, titledesc, basepath="", videopath=settings.STREAM_URL) + if ldtpath: + contents[id] = IriInfo(id, i, "", os.path.dirname(ldtpath), flatten=self.flatten) + else: + contents[id] = IriInfo(id, i, "", flatten=self.flatten) + # Get iri file's url from ldt. This url can be relative path or absolute path. + contents[id].src = medianode.attributes['src'].value + if medianode.attributes['video'].value !="": + contents[id].videopath = medianode.attributes['video'].value + elif self.videopath !="" or self.videopath: + contents[id].videopath = self.videopath + else: + contents[id].videopath =settings.STREAM_URL + + + #get annotation of file ldt + result = xml.xpath.Evaluate("/iri/annotations/content", context=con) + + for contentnode in result: + id = contentnode.attributes['id'].value + # pocketfilms.utils.log.debug("ID : " + str(id)) + if contents.has_key(id): + if self.author: + contentnode.setAttribute("author", unicode(self.author)) + contents[id].annotations = contentnode + + #go throught values + for iriinfo in contents.values(): + + iriinfo.process() + + # if yes update + # if no create + # move iri file to the proper place + #return list of iriInfo + + def processFile(self): + if self.filepath.name.endswith(".ldt"): + self.processLdt() + elif self.filepath.name.endswith(".zip"): + self.processZip() + else: + raise FileImportError("Bad file type") + + + def processZip(self): + # """ extraire .zip, pass to method processLdt""" + # create temp directory + self.__tempdir = tempfile.mkdtemp() + openfiles = [] + flvfiles = [] + processedids = [] + + try: + zipfile = zipfileext.ZipFileExt(self.filepath) + zipfile.unzip_into_dir(self.__tempdir) + #load ldt + foldersToProcess = [self.__tempdir] + while len(foldersToProcess): + # pocketfilms.utils.log.debug("folder stack length : "+ str(len(foldersToProcess))) + currentFolder = foldersToProcess.pop() + for entry in os.listdir(currentFolder): + if entry in settings.ZIP_BLACKLIST: + continue + entryPath = os.path.join(currentFolder, entry) + if(os.path.isdir(entryPath)): + # pocketfilms.utils.log.debug("Push folder : " + entryPath) + foldersToProcess.append(entryPath) + elif fnmatch.fnmatch(entry, "*.ldt"): + # pocketfilms.utils.log.debug("Process file : " + entryPath) + ldtid = self.processLdt(entryPath) + processedids.append(ldtid) + elif fnmatch.fnmatch(entry, "*.flv"): + flvfiles.append(entryPath) + + if settings.CONTENT_ROOT and os.path.exists(settings.CONTENT_ROOT): + for entry in flvfiles: + shutil.copy(entry, settings.CONTENT_ROOT) + + finally: + for f in openfiles: + f.close() + shutil.rmtree(self.__tempdir) + # delete directory + return processedids + + # def processFileLdt(self): + # processedids = [] + # ldtid = self.processLdt(self.filepath) + # processedids.append(ldtid) + # return processedids diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/forms.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,29 @@ +from django import forms +from models import Project, Content +import uuid + +class LdtImportForm(forms.Form): + importFile = forms.FileField() + videoPath = forms.CharField(required=False) + flatten = forms.BooleanField(required=False, initial=True) + +class LdtAddForm(forms.ModelForm): + title = forms.CharField() + # contents = forms.ModelMultipleChoiceField(Content.objects.all()) + # owner = forms.ModelChoiceField(Author.objects.all()) + class Meta: + model = Project + exclude = ("ldt_id", "ldt", "created_by", "changed_by", "creation_date", "modification_date", "state", "owner") + +class ReindexForm(forms.Form): + contents = forms.ModelMultipleChoiceField(Content.objects.all()) + +class SearchForm(forms.Form): + search = forms.CharField() + field = forms.ChoiceField([(u"all", u"all"), (u"title", u"title"), (u"abstract", u"resume"), (u"tags", u"tags")]) + +class AddProjectForm (forms.Form): + title = forms.CharField() + +class CopyProjectForm (forms.Form): + title = forms.CharField() diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/models.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/models.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,73 @@ +from django.db import models +from django.conf import settings +from ldt.core.models import Document, Owner +from django.utils.translation import ugettext_lazy as _ +from utils import create_ldt, copy_ldt +import uuid + +class Content(models.Model): + iri_id = models.CharField(max_length=1024, unique=True) + iriurl = models.URLField() + videopath = models.URLField(null=True, blank=True) + creation_date = models.DateTimeField(auto_now_add=True) + update_date = models.DateTimeField(auto_now=True) + title = models.CharField(max_length=1024, null=True, blank=True) + description = models.TextField(null=True, blank=True) + external_id = models.CharField(max_length=1024, null=True, blank=True) + # authors = models.ManyToManyField(Author) + + def __unicode__(self): + return str(self.id) + ": " + self.iri_id + + def iri_url(self, web_url=settings.WEB_URL): + if 'http' in self.iriurl or 'https' in self.iriurl: + return self.iriurl + else: + return unicode(web_url) + unicode(settings.MEDIA_URL)+u"media/ldt/"+unicode(self.iriurl) + + +class Project(Document): + STATE_CHOICES=( + (1, 'edition'), + (2, 'published'), + (3, 'moderated'), + (4, 'rejected'), + (5, 'deleted') + ) + ldt_id = models.CharField(max_length=1024, unique=True) + ldt = models.TextField(null=True) + title = models.CharField(max_length=1024) + contents = models.ManyToManyField(Content) + creation_date = models.DateTimeField(auto_now_add=True) + modification_date = models.DateTimeField(auto_now=True) + created_by = models.CharField(_("created by"), max_length=70) + changed_by = models.CharField(_("changed by"), max_length=70) + state = models.IntegerField(choices=STATE_CHOICES, default=1) + + def __unicode__(self): + return unicode(self.id) + u": " + unicode(self.ldt_id) + + @staticmethod + def create_project(user, title, contents): + owner = Owner.objects.get(user=user) + project = Project(title=title, owner=owner) + project.ldt_id = str(uuid.uuid1()) + project.created_by=user.username + project.changed_by=user.username + project.state = 1 + project.save() + for content in contents: + project.contents.add(content) + project.save() + return create_ldt(project, user) + + def copy_project(self, user, title): + owner = Owner.objects.get(user=user) + project = Project(title=title, owner=owner) + project = copy_ldt(self, project, user) + project.save() + for content in self.contents.all(): + project.contents.add(content) + project.save() + return project + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/projectindexer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/projectindexer.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,110 @@ +import tempfile +import os +import os.path +import shutil +import ldt.utils.xml +from ldt import settings +import xml +import xml.dom +import xml.dom.minidom +import xml.dom.ext +import xml.xpath +import lucene +from ldt.ldt import STORE +from ldt.ldt import ANALYZER + +def Property(func): + return property(**func()) + +class ProjectIndexer(object): + def __init__(self, projectList, writer, decoupage_blackList = settings.DECOUPAGE_BLACKLIST): + self.__projectList = projectList + self.__decoupage_blacklist = decoupage_blackList + self.__writer = writer + + @Property + def decoupage_blacklist(): #@NoSelf + doc = """get blacklist""" #@UnusedVariable + + def fget(self): + if self.__decoupage_blacklist is None: + self.__decoupage_blacklist = () + return self.__decoupage_blacklist + + def fset(self, value): + self.__decoupage_blacklist = value + + def fdel(self): + del self.__decoupage_blacklist + + return locals() + + def index_all(self): + for project in self.__projectList: + self.index_project(project) + + def index_project(self, project): + # ldt.utils.log.debug("Indexing project : "+str(project.ldt_id)) + ldt=project.ldt + doc = xml.dom.minidom.parseString(ldt.encode( "utf-8" )) + + self.__writer.deleteDocuments(lucene.Term("ldt_id", project.ldt_id)) + + con = xml.xpath.Context.Context(doc, 1, 1, None) + res = xml.xpath.Evaluate("/iri/annotations/content", context=con) + + for content in res: + contentId = content.getAttribute("id") + + res =xml.xpath.Evaluate("ensemble", content) + for ensemble in res: + ensembleId = ensemble.getAttribute("id") + + for decoupageNode in ensemble.childNodes: + # ldt.utils.log.debug("Indexing project decoupage : "+ repr(decoupageNode.nodeType) + " in " + repr(self.decoupage_blacklist)) + if decoupageNode.nodeType != xml.dom.Node.ELEMENT_NODE or decoupageNode.tagName != "decoupage" or decoupageNode.getAttribute("id") in self.decoupage_blacklist: + continue + + decoupId = decoupageNode.getAttribute("id") + res = xml.xpath.Evaluate("elements/element", decoupageNode) + for elementNode in res: + doc = lucene.Document() + elementId = elementNode.getAttribute("id") + tags = elementNode.getAttribute("tags") + + if tags is not None: + tags.replace(",", ";") + + if tags is None or len(tags) == 0: + tags = "" + restagnode = xml.xpath.Evaluate("tag/text()", elementNode) + for tagnode in restagnode: + tags = tags + " ; " + tagnode.data + + if tags is None or len(tags) == 0: + tags = "" + restagnode = xml.xpath.Evaluate("tags/tag/text()", elementNode) + for tagnode in restagnode: + tags = tags + " ; " + tagnode.data + + title = "" + for txtRes in xml.xpath.Evaluate("title/text()", elementNode): + title = title + txtRes.data + + abstract = "" + for txtRes in xml.xpath.Evaluate("abstract/text()", elementNode): + abstract = abstract + txtRes.data + + doc.add(lucene.Field("ldt_id", project.ldt_id, lucene.Field.Store.YES, lucene.Field.Index.UN_TOKENIZED)) + doc.add(lucene.Field("iri_id", contentId, lucene.Field.Store.YES, lucene.Field.Index.UN_TOKENIZED)) + doc.add(lucene.Field("ensemble_id", ensembleId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("decoupage_id", decoupId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("element_id", elementId, lucene.Field.Store.YES, lucene.Field.Index.NO)) + doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("title", title, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.NO, lucene.Field.Index.TOKENIZED)) + + self.__writer.addDocument(doc) + + self.__writer.flush() \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/admin/ldt/app_action.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/admin/ldt/app_action.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,11 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block breadcrumbs %} +{% endblock %} + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/admin/ldt/app_index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/admin/ldt/app_index.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,30 @@ +{% extends "admin/app_index.html" %} +{% load i18n %} + +{% block content %} +{{ block.super }} + +
+ + + + + + + + + + +
Import
+ Import an ldt +  
+ Reindex +  
+
+ +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/admin/ldt/content/reindex_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/admin/ldt/content/reindex_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,30 @@ +{% extends "admin/ldt/app_action.html" %} +{% load i18n %} +{# reindex contents #} + +{% block content %} + +{% if message %} +
+

+{{ message }} +

+
+{% endif %} +{% if form. %} +
+
+{% endif %} +
+
+ {% csrf_token %} + + {{ form.as_table }} +
+ +
+
+ +Back to administration page + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/admin/ldt/content/search_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/admin/ldt/content/search_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +{% extends "base.html" %} + +{% block content %} + +
+ + + {{ form.as_table }} +
+ +
+ + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/admin/ldt/content/upload_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/admin/ldt/content/upload_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,28 @@ +{% extends "admin/ldt/app_action.html" %} +{# import an ldt #} +{% block content %} +

Vous pouvez importer un fichier ldt ou un zip qui compresse un fichier .ldt et plusieurs fichiers .iri.

+

Bien verifiez vous que le chemin de source est absolute pour un fichier ldt lors qu'il est tout seul, alors qu'il est relatif s'il est dans le zip

+

Vous pouvez indiquer le chemin de video si vous avez besoin

+{% if message %} +
+

+{{ message }} +

+
+{% endif %} + +{% if form %} + +
+ {% csrf_token %} + + {{ form.as_table }} +
+ +
+{% endif %} + +Back to administration page + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/iriuser/ldt/copy_ldt.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/iriuser/ldt/copy_ldt.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,22 @@ +{% load i18n %} +{# form of copy of project ldt #} + + + + + + + +
+
{% trans "Copy your project" %}
+
+ {% csrf_token %} + + + + +
+
+ + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/iriuser/ldt/create_ldt.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/iriuser/ldt/create_ldt.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,29 @@ +{% load i18n %} +{# form of creation of project ldt #} + + + + + + + +
+
{% trans "Create your project" %}
+
+ {% csrf_token %} + + + +
{% trans "List of contents" %}
+
    + {% for content in contents %} +
  • {{content.iri_id}}
  • + {% endfor %} +
+ + +
+
+ + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/iriuser/ldt/init_ldt.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/iriuser/ldt/init_ldt.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,52 @@ + + + + + + + + Ligne de Temps - IRI + + + + + + +
  +
+ + + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/iriuser/ldt/ldt_list.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/iriuser/ldt/ldt_list.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,81 @@ +{% extends "ldt/user/user_base.html" %} +{# list of projects ldt #} +{% load i18n %} +{% block js_import %}{{ block.super }} + + +{% endblock %} +{% block css_import %} +{{ block.super }} + +{% endblock %} + +{% block breadcrumb %} +
  • +
  • {% trans "Space" %}
  • +
  • {% trans "Ldt Project" %}
  • +{% endblock %} +{% block content_title %}{% trans "Ldt Project" %}{% endblock %} + +{% block iricontent %} +
    +{% trans 'Create new project'%} + + + + + + + + + + {% for ldt in ldtProjects %} + + + {% ifequal ldt.state 2%} + + {% else %} + + {% endifequal %} + + {% endfor %} + +
    {% trans "Project" %}
    {% trans "title" %}{% trans " published" %}
    {{ ldt.title }}TrueFalse
    +
    +{% endblock %} + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/iriuser/ldt/loading.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/iriuser/ldt/loading.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,27 @@ + + + + + + + +
    +
    +loading +
    +
    + + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/templates/iriuser/ldt/save_done.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/templates/iriuser/ldt/save_done.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,4 @@ +

    done

    +

    {{ldt}}

    +

    {{id}}

    +

    title:{{title}}

    \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/tests.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/tests.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/urls.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/urls.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,35 @@ +from django.conf.urls.defaults import * +from ldt.management import test_ldt + +# Uncomment the next two lines to enable the admin: +# from django.contrib import admin +# admin.autodiscover() + +urlpatterns = patterns('ldt.ldt', + url(r'^searchInit/(?P.*)/(?P.*)$', 'views.searchInit'), + url(r'^searchForm/$', 'views.searchForm'), + url(r'^search/$', 'views.searchIndex'), + url(r'^search/(?P.*)/(?P.*)$', 'views.searchIndexGet'), + url(r'^searchLdt/(?P.*)/(?P.*)$', 'views.searchLdt'), + url(r'^searchSeg/(?P.*)/(?P.*)$', 'views.searchSegments'), + url(r'^index/(?P.*)$', 'views.index'), + url(r'^init/(?P.*)/(?P.*)$', 'views.init'), + url(r'^ldt/(?P.*)$', 'views.ldt'), + url(r'^search/loading/$', 'views.loading'), + url(r'^create/(?P.*)$', 'views.create_project'), + url(r'^copy/(?P.*)$', 'views.copy_project'), +) + +if test_ldt(): + urlpatterns += patterns('ldt.ldt', + url(r'^space/ldt/$', 'views.list_ldt'), + url(r'^space/ldt/indexproject/(?P.*)$', 'views.indexProject'), + url(r'^space/ldt/init/(?P.*)/(?P.+)$', 'views.init'), + url(r'^space/ldt/project/(?P.*)$', 'views.ldtProject'), + url(r'^space/ldt/create/$', 'views.create_ldt_view'), + url(r'^space/ldt/created_done/$', 'views.created_ldt'), + url(r'^space/ldt/save/$', 'views.save_ldtProject'), + url(r'^space/ldt/publish/(?P.*)$', 'views.publish'), + url(r'^space/ldt/unpublish/(?P.*)$', 'views.unpublish'), + +) diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/utils.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/utils.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,266 @@ +import lucene +from ldt.ldt import STORE +from ldt.ldt import ANALYZER +from Ft.Xml import MarkupWriter +import uuid +import django.core.urlresolvers +from django.conf import settings +import urllib +import xml.dom +import xml.dom.minidom +import xml.dom.ext +import xml.xpath +import os +import os.path + +class LdtSearch(object): + + def query(self, field, query): + indexSearcher = lucene.IndexSearcher(STORE) + queryParser = lucene.QueryParser(field, lucene.FrenchAnalyzer()) + queryParser.setDefaultOperator(lucene.QueryParser.Operator.AND) + queryObj = queryParser.parse(query) + hits = indexSearcher.search(queryObj) + + res = [] + for hit in hits: + doc = lucene.Hit.cast_(hit).getDocument() + res.append({"iri_id":doc.get("iri_id"),"ensemble_id":doc.get("ensemble_id"),"decoupage_id":doc.get("decoupage_id"), "element_id":doc.get("element_id")}) + return res + + def queryAll(self, query): + return self.query("all", query) + +class LdtUtils(object): + + def generateLdt(self, contentList, file, title = u"", author=u"IRI Web", web_url=u"", media_url="", startSegment = None, contributions=None): + + writer = MarkupWriter(file, indent = u"yes") + writer.startDocument() + writer.startElement(u"iri") + writer.simpleElement(u"project", attributes={u"id":unicode(str(uuid.uuid1())), u"title":unicode(title) , u"user":author, u"abstract":u""}) + writer.startElement(u"medias") + for content in contentList: + videopath = unicode(settings.STREAM_URL) + if content.videopath : + videopath = unicode(content.videopath) + writer.simpleElement(u"media", attributes={u"id":content.iri_id,u"src":content.iri_url(web_url),u"video":videopath,u"pict":u"",u"extra":u""}) + writer.endElement(u"medias") + + if contributions is None: + contributions = [] + annotations_nodes = {} + for contrib in contributions: + doc = xml.dom.minidom.parseString(contrib.ldtproject.ldt.encode("utf-8")) + con = xml.xpath.Context.Context(doc, 1, 1, None) + res = xml.xpath.Evaluate("/iri/annotations/content", context=con) + for content in res: + contentid = content.getAttribute("id") + if annotations_nodes.has_key(contentid): + contentnode = annotations_nodes[contentid] + else: + contentnode = {"id":contentid, "ensembles":[]} + annotations_nodes[contentid]=contentnode + for ens in content.childNodes: + if ens.nodeType == xml.dom.Node.ELEMENT_NODE and ens.tagName.endswith("ensemble"): + contentnode["ensembles"].append(ens.toprettyxml()) + + if len(annotations_nodes) > 0: + writer.startElement(u"annotations") + for content in contentList: + if content.content_base.iri_id in annotations_nodes: + contentnode = annotations_nodes[content.content_base.iri_id] + if contentnode is not None: + if len(contentnode["ensembles"])>0: + writer.startElement(u"content", attributes={"id":contentnode["id"]}) + writer.text(u"") + for ens in contentnode["ensembles"]: + writer.xmlFragment(ens.encode("utf-8")) + writer.endElement(u"content") + else: + writer.simpleElement(u"content", attributes={"id":contentnode["id"]}) + writer.endElement(u"annotations") + else: + writer.simpleElement(u"annotations") + + + writer.startElement(u"displays") + if len(contentList) > 0: + writer.startElement(u"display", attributes={u"id":u"0",u"title":u"generated",u"idsel":contentList[0].iri_id,u"tc":u"0"}) + for content in contentList: + writer.startElement(u"content", attributes={u"id":content.iri_id}) + filepath = urllib.urlopen(content.iri_url()) + doc = xml.dom.minidom.parse(filepath) + con = xml.xpath.Context.Context(doc, 1, 1, None) + res = xml.xpath.Evaluate("/iri/body/ensembles/ensemble/decoupage", context=con) + for decoupagenode in res: + decoupage_id = decoupagenode.getAttribute(u"id") + ensemble_id = decoupagenode.parentNode.getAttribute(u"id") + writer.simpleElement(u"decoupage", attributes={u"id":decoupage_id,u"idens":ensemble_id}) + writer.endElement(u"content") + if startSegment is not None: + writer.startElement(u"activeSegment") + writer.simpleElement(u"id",attributes={u"idctt" : startSegment["idcontent"],u"idens" : startSegment["idgroup"], u"idcut" : startSegment["idcutting"], u"idseg" : startSegment["idsegment"]}) + writer.endElement(u"activeSegment") + + writer.endElement(u"display") + writer.endElement(u"displays") + writer.simpleElement(u"edits") + writer.endElement(u"iri") + + def generateInit(self, url, method, search=None): + + import xml.dom + import xml.dom.ext + + impl = xml.dom.getDOMImplementation() + doc = impl.createDocument(xml.dom.EMPTY_NAMESPACE, 'iri', None) + + elementFiles = doc.createElement('files') + doc.documentElement.appendChild(elementFiles) + + elementInit = doc.createElement('init') + elementFiles.appendChild(elementInit) + + elementfile = doc.createElement('file') + + elementfile.setAttribute('src',settings.WEB_URL + django.core.urlresolvers.reverse(method, args=url)) + elementfile.setAttribute('display', '1') + if(search): + elementfile.setAttribute("segsel",settings.WEB_URL + django.core.urlresolvers.reverse(search, args=url)) + + + # /*chemin video : tant que le serveur de media n'est pas up, */ + elementfile.setAttribute('video', settings.STREAM_URL) + elementfile.setAttribute('pict', "") + elementfile.setAttribute('extra', "") + + elementInit.appendChild(elementfile); + + elementRecent = doc.createElement('recent'); + elementFiles.appendChild(elementRecent); + + + elementLibrary = doc.createElement('library'); + elementFiles.appendChild(elementLibrary); + + username = '' + id = '' + elementUser = doc.createElement('user') + elementUser.setAttribute('name', username) + elementUser.setAttribute('id', id) + doc.documentElement.appendChild(elementUser) + + return doc + +def create_ldt(project, user): + + contentList=project.contents.all() + + """create xml""" + + # create a dom + impl = xml.dom.getDOMImplementation() + dom = impl.createDocument(xml.dom.EMPTY_NAMESPACE, 'iri', None) + #node project + elementProject = dom.createElement('project') + dom.documentElement.appendChild(elementProject) + + + elementProject.setAttribute('abstract', "") + elementProject.setAttribute('title', project.title) + elementProject.setAttribute('user', user.username) + elementProject.setAttribute('id', project.ldt_id) + #node medias + elementMedias = dom.createElement('medias') + dom.documentElement.appendChild(elementMedias) + + idsel = None + for content in contentList: + if not idsel: + idsel = content.iri_id + elementMedia = dom.createElement('media') + elementMedia.setAttribute('id', content.iri_id) + elementMedia.setAttribute('src', content.iri_url()) + if content.videopath and content.videopath !="": + elementMedia.setAttribute('video', content.videopath) + else: + elementMedia.setAttribute('video', settings.STREAM_URL) + elementMedia.setAttribute('pict', "") + elementMedia.setAttribute('extra', "") + elementMedias.appendChild(elementMedia) + if not idsel: + idsel = "" + + #node annotations + elementAnnotations = dom.createElement('annotations') + dom.documentElement.appendChild(elementAnnotations) + #node displays + elementDisplays = dom.createElement('displays') + elementDisplay = dom.createElement('display') + elementDisplay.setAttribute('id', '0') + elementDisplay.setAttribute('title', 'Init view') + elementDisplay.setAttribute('idsel', idsel) + elementDisplay.setAttribute('tc', '0') + elementDisplay.setAttribute('zoom', '0') + elementDisplay.setAttribute('scroll', '0') + elementDisplay.setAttribute('infoBAB', '') + #node content + for content in contentList: + elementContent = dom.createElement('content') + elementContent.setAttribute('id', content.iri_id) + if not 'http' in content.iriurl: + #eg: "iiiielizabethrosse/ENMI08-III_elizabethrosse.iri" + url = content.iri_url() + else: + url =content.iriurl + file = urllib.urlopen(url) + doc = xml.dom.minidom.parse(file) + con = xml.xpath.Context.Context(doc, 1, 1, None) + res = xml.xpath.Evaluate("/iri/body/ensembles/ensemble/decoupage", context=con) + #node decoupage + for decoupagenode in res: + decoupage_id = decoupagenode.getAttribute(u"id") + ensemble_id = decoupagenode.parentNode.getAttribute(u"id") + elementDecoupage = dom.createElement('decoupage') + elementDecoupage.setAttribute('idens', ensemble_id) + elementDecoupage.setAttribute('id', decoupage_id) + elementContent.appendChild(elementDecoupage) + elementDisplay.appendChild(elementContent) + + elementDisplays.appendChild(elementDisplay) + dom.documentElement.appendChild(elementDisplays) + + elementEdits = dom.createElement('edits') + dom.documentElement.appendChild(elementEdits) + # write dom in Project.ldt + project.ldt = dom.documentElement.toprettyxml() + #save Project + project.save() + return project + + +def copy_ldt(project, new_project, user): + new_project.ldt_id = str(uuid.uuid1()) + new_project.created_by=user.username + new_project.changed_by=user.username + new_project.state = 1 + + contentList=project.contents.all() + + """create xml""" + + # create a dom + dom = xml.dom.minidom.parseString(project.ldt.encode("utf-8")) + con = xml.xpath.Context.Context(dom, 1, 1, None) + res = xml.xpath.Evaluate("iri/project", context=con) + for elementProject in res: + elementProject.setAttribute('abstract', "") + elementProject.setAttribute('title', new_project.title) + elementProject.setAttribute('user', user.username) + elementProject.setAttribute('id', new_project.ldt_id) + + new_project.ldt = dom.documentElement.toprettyxml() + #save Project + new_project.save() + return new_project diff -r 000000000000 -r ecdfc63274bf web/ldt/ldt/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/ldt/views.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,287 @@ +import django.core.urlresolvers +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render_to_response, get_object_or_404 +from django.template import RequestContext +from django.core.urlresolvers import reverse +from django.contrib.auth.decorators import login_required +from django.conf import settings +from fileimport import * +from forms import LdtImportForm, LdtAddForm, SearchForm, AddProjectForm, CopyProjectForm +from ldt.core.models import Owner +from models import * +from utils import * +from contentindexer import * +from string import Template +from Ft.Xml import MarkupWriter +import cgi +import uuid +import base64 +import lucene +import xml.dom +import xml.dom.ext +import xml.dom.minidom + + + +def searchForm(request): + form = SearchForm() + return render_to_response('ldt/ldt/search_form.html',{'form': form} , context_instance=RequestContext(request)) + +def searchIndex(request): + + sform = SearchForm(request.POST) + if sform.is_valid(): + search = sform.cleaned_data["search"] + + + queryStr = base64.urlsafe_b64encode(search.encode('utf8')) + field = request.POST["field"] + language_code = request.LANGUAGE_CODE[:2] + + url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt.views.searchInit", args=[field, queryStr]) + return render_to_response('ldt/ldt/init_ldt.html', {'MEDIA_URL': settings.MEDIA_URL, 'colorurl': settings.MEDIA_URL+'swf/ldt/pkg/color.xml', 'i18nurl': settings.MEDIA_URL+'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.MEDIA_URL+'swf/ldt/', 'url': url}, context_instance=RequestContext(request)) + else: + resp = HttpResponse() + resp.write("Error : No result"); + +def searchIndexGet(request, field, query): + + language_code = request.LANGUAGE_CODE[:2] + url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt.views.searchInit", args=[field, query]) + return render_to_response('irisuser/ldt/init_ldt.html', {'MEDIA_URL': settings.MEDIA_URL, 'colorurl': settings.MEDIA_URL+'swf/ldt/pkg/color.xml', 'i18nurl': settings.MEDIA_URL+'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.MEDIA_URL+'swf/ldt/', 'url': url}, context_instance=RequestContext(request)) + +def searchInit(request, field, query): + + ldtgen = LdtUtils() + + doc = ldtgen.generateInit([field,query], 'ldt.ldt.views.searchLdt', 'ldt.ldt.views.searchSegments') + + resp = HttpResponse(mimetype="text/xml;charset=utf-8") + xml.dom.ext.PrettyPrint(doc, resp) + return resp + +def searchLdt(request, field, query, edition=None): + + contentList = [] + resp = HttpResponse(mimetype="text/xml") + queryStr = "" + + if query and len(query)>0: + queryStr = base64.urlsafe_b64decode(query.encode("ascii")).decode("utf8") + searcher = LdtSearch() + ids = {} + + for result in searcher.query(field, queryStr): + ids[result["iri_id"]] = "" + + id_list = ids.keys() + + if edition is not None: + ids_editions = map(lambda t:t[0], filter(lambda id: id[0] is not None, Speak.objects.filter(session__day__edition=edition).order_by("session__start_ts", "order").values_list("content__iri_id"))) + id_list = filter(lambda id: id in id_list, ids_editions) + + contentList = Content.objects.filter(iri_id__in=id_list) + + + ldtgen = LdtUtils() + ldtgen.generateLdt(contentList, file=resp, title = u"Recherche : " + queryStr) + + return resp + + +def searchSegments(request, field, query, edition=None): + + if query and len(query)>0: + searcher = LdtSearch() + + queryStr = base64.urlsafe_b64decode(query.encode("ascii")).decode("utf8") + res = searcher.query(field, queryStr) + else: + res = [] + + iri_ids = None + + if edition is not None: + iri_ids = map(lambda t:t[0], filter(lambda id: id[0] is not None, Speak.objects.filter(session__day__edition=edition).order_by("session__start_ts", "order").values_list("content__iri_id"))) + + doc = xml.dom.getDOMImplementation().createDocument(None, "iri", None) + + for resultMap in res: + if iri_ids is None or resultMap['iri_id'] in iri_ids: + elem = doc.createElement('seg') + elem.setAttribute('idctt', resultMap['iri_id']) + elem.setAttribute('idens', resultMap['ensemble_id']) + elem.setAttribute('iddec', resultMap['decoupage_id']) + elem.setAttribute('idseg', resultMap['element_id']) + elem.setAttribute('idvue', "") + elem.setAttribute('crit', "") + doc.documentElement.appendChild(elem) + + return HttpResponse(doc.toprettyxml(encoding='utf-8'), mimetype="text/xml;charset=utf-8") + +@login_required +def list_ldt(request): + contents = Content.objects.all() + try: + owner = Owner.objects.get(user=request.user) + except: + return HttpResponseRedirect(settings.LOGIN_URL) + ldtProjects = Project.objects.filter(owner=owner) + context={ + 'contents': contents, + 'ldtProjects': ldtProjects.reverse(), + } + return render_to_response('ldt/ldt/ldt_list.html', context, context_instance=RequestContext(request)) + +def create_ldt_view(request): + if request.method == "POST" : + form = LdtAddForm(request.POST) + if form.is_valid(): + user = request.user + Project.create_project(title=form.cleaned_data['title'], user=user, contents=form.cleaned_data['contents']) + return HttpResponseRedirect(reverse("ldt.ldt.views.list_ldt")) + else: + form = LdtAddForm() + contents = Content.objects.all() + return render_to_response('ldt/ldt/create_ldt.html', {'contents': contents, 'form': form,'create_project_action':reverse(create_ldt_view)}, context_instance=RequestContext(request)) + +def created_ldt(request): + return render_to_response('ldt/ldt/done.html', context_instance=RequestContext(request)) + +def indexProject(request, id): + + urlStr = settings.WEB_URL + reverse("ldt.ldt.views.init", args=['ldtProject', id]) + posturl= settings.WEB_URL + reverse("ldt.ldt.views.save_ldtProject") + language_code = request.LANGUAGE_CODE[:2] + + ldt = get_object_or_404(Project, ldt_id=id) + if ldt.state ==2: #published + readonly = 'true' + else: + readonly = 'false' + + return render_to_response('ldt/ldt/init_ldt.html', {'MEDIA_URL': settings.MEDIA_URL, 'colorurl': settings.MEDIA_URL+'swf/ldt/pkg/color.xml', 'i18nurl': settings.MEDIA_URL+'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.MEDIA_URL+'swf/ldt/', 'url': urlStr, 'posturl': posturl, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request)) + +def init(request, method, url): + ldtgen = LdtUtils() + + doc = ldtgen.generateInit([url], 'ldt.ldt.views.'+method, None) + + resp = HttpResponse(mimetype="text/xml") + resp['Cache-Control']='no-cache, must-revalidate' + resp['Pragma']='no-cache' + xml.dom.ext.PrettyPrint(doc, resp) + return resp + +def ldtProject(request, id): + resp = HttpResponse(mimetype="text/xml") + resp['Cache-Control']='no-cache, must-revalidate' + resp['Pragma']='no-cache' + + project = Project.objects.get(ldt_id=id) + resp.write(project.ldt) + return resp + +def save_ldtProject(request): + if request.method=="POST": + ldt = request.POST['ldt'] + id = request.POST['id'] + ldtproject=Project.objects.get(ldt_id=id) + #save xml ldt + ldtproject.ldt=ldt + #get new title + dom = xml.dom.minidom.parseString(ldt.encode( "utf-8" )) + con = xml.xpath.Context.Context(dom, 1, 1, None) + result = xml.xpath.Evaluate("/iri/project",context=con) + for pnode in result: + title=pnode.getAttribute("title") + break + #set new title + ldtproject.title=title + #get new content list + new_contents=[] + result = xml.xpath.Evaluate("/iri/medias/media", context=con) + for medianode in result: + id = medianode.attributes['id'].value + new_contents.append(id) + # set new content list + for c in ldtproject.contents.all(): + if not c.iri_id in new_contents: + ldtproject.contents.remove(c) + ldtproject.save() + else: + ldt = '' + return render_to_response('ldt/ldt/save_done.html', {'ldt': ldt, 'id':id, 'title':title, 'contents': new_contents}, context_instance=RequestContext(request)) + +@login_required +def publish(request, id): + ldt = get_object_or_404(Project, ldt_id=id) + ldt.state = 2 #published + ldt.save() + return HttpResponseRedirect(reverse("ldt.ldt.views.list_ldt")) + +@login_required +def unpublish(request, id): + ldt = get_object_or_404(Project, ldt_id=id) + ldt.state = 1 #edition + ldt.save() + return HttpResponseRedirect(reverse("ldt.ldt.views.list_ldt")) + + +def index(request, url): + + urlStr = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt.views.init", args=['ldt',url]) + language_code = request.LANGUAGE_CODE[:2] + + return render_to_response('ldt/ldt/init_ldt.html', {'MEDIA_URL': settings.MEDIA_URL, 'colorurl': settings.MEDIA_URL+'swf/ldt/pkg/color.xml', 'i18nurl': settings.MEDIA_URL+'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.MEDIA_URL+'swf/ldt/', 'url': urlStr, 'weburl':settings.WEB_URL+settings.BASE_URL}, context_instance=RequestContext(request)) + + +def ldt(request, url, startSegment = None): + + import Ft + from Ft.Xml import MarkupWriter + + resp = HttpResponse(mimetype="text/xml; charset=utf-8") + resp['Cache-Control'] = 'no-cache' + + contentList = Content.objects.filter(iri_id=url) + + ldtgen = LdtUtils() + ldtgen.generateLdt(contentList, file=resp, title = contentList[0].title, startSegment=startSegment) + + return resp + + +def loading(request): + return render_to_response('ldt/ldt/loading.html', context_instance=RequestContext(request)) + + +@login_required +def create_project(request, iri_id): + + content = get_object_or_404(Content, iri_id=iri_id) + contents = [ content, ] + if request.method == "POST" : + form = AddProjectForm(request.POST) + if form.is_valid(): + user=request.user + project = Project.create_project(title=form.cleaned_data['title'], user=user, contents=contents) + return HttpResponseRedirect(reverse('ldt.ldt.views.indexProject', args=[project.ldt_id])) + else: + form = AddProjectForm() + return render_to_response('ldt/ldt/create_ldt.html', {'form':form, 'contents':contents, 'iri_id':iri_id, 'create_project_action':reverse("ldt.ldt.views.create_project",args=[iri_id])}, context_instance=RequestContext(request)) + +@login_required +def copy_project(request, ldt_id): + + project = get_object_or_404(Project, ldt_id=ldt_id) + if request.method == "POST" : + form = CopyProjectForm(request.POST) + if form.is_valid(): + user=request.user + project = project.copy_project(title=request.POST['title'], user=user) + return HttpResponseRedirect(reverse('ldt.ldt.views.indexProject', args=[project.ldt_id])) + else: + form = CopyProjectForm + return render_to_response('ldt/ldt/copy_ldt.html', {'form':form, 'project':project}, context_instance=RequestContext(request)) + diff -r 000000000000 -r ecdfc63274bf web/ldt/locale/en/LC_MESSAGES/django.mo Binary file web/ldt/locale/en/LC_MESSAGES/django.mo has changed diff -r 000000000000 -r ecdfc63274bf web/ldt/locale/en/LC_MESSAGES/django.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/locale/en/LC_MESSAGES/django.po Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,648 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-03-09 08:48-0600\n" +"PO-Revision-Date: 2010-02-17 03:53+0100\n" +"Last-Translator: Yves-Marie Haussonne \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ldt/models.py:43 +msgid "created by" +msgstr "created by" + +#: ldt/models.py:44 +msgid "changed by" +msgstr "changed by" + +#: ldt/templates/admin/ldt/app_action.html:6 +#: templates/admin/cms_change_list.html:7 +#: templates/admin/page_app_index.html:8 +#: templates/admin/page_change_form.html:17 +#: templates/admin/page_change_list.html:25 +#: user/templates/registration/logged_out.html:4 +msgid "Home" +msgstr "Home" + +#: ldt/templates/iriuser/ldt/copy_ldt.html:12 +msgid "Copy your project" +msgstr "Copy your project" + +#: ldt/templates/iriuser/ldt/copy_ldt.html:15 +#: ldt/templates/iriuser/ldt/create_ldt.html:15 +msgid "Title" +msgstr "Title" + +#: ldt/templates/iriuser/ldt/copy_ldt.html:18 +msgid "Copy" +msgstr "Copy" + +#: ldt/templates/iriuser/ldt/create_ldt.html:12 +msgid "Create your project" +msgstr "Create your project" + +#: ldt/templates/iriuser/ldt/create_ldt.html:18 +msgid "List of contents" +msgstr "List of contents" + +#: ldt/templates/iriuser/ldt/create_ldt.html:25 +msgid "Create" +msgstr "Create" + +#: ldt/templates/iriuser/ldt/ldt_list.html:50 +#: templates/admin/page_base.html:19 +#: user/templates/iriuser/user/login_form.html:33 +#: user/templates/iriuser/user/space.html:6 +#: user/templates/iriuser/user/space.html:9 +msgid "Space" +msgstr "Space" + +#: ldt/templates/iriuser/ldt/ldt_list.html:51 +#: ldt/templates/iriuser/ldt/ldt_list.html:53 +msgid "Ldt Project" +msgstr "Ldt Project" + +#: ldt/templates/iriuser/ldt/ldt_list.html:57 +msgid "Create new project" +msgstr "Create new project" + +#: ldt/templates/iriuser/ldt/ldt_list.html:59 +msgid "Project" +msgstr "Project" + +#: ldt/templates/iriuser/ldt/ldt_list.html:62 +msgid "title" +msgstr "Title" + +#: ldt/templates/iriuser/ldt/ldt_list.html:63 +msgid " published" +msgstr " published" + +#: templates/admin/cms_change_form.html:30 +msgid "Approve page deletion" +msgstr "Approve page deletion" + +#: templates/admin/cms_change_form.html:36 +#, python-format +msgid "(requires approvement at %(moderation_level)s level)" +msgstr "(requires approvement at %(moderation_level)s level)" + +#: templates/admin/cms_change_form.html:37 +msgid "(you can perform actions on this page directly)" +msgstr "(you can perform actions on this page directly)" + +#: templates/admin/cms_change_form.html:50 +msgid "Remove delete request" +msgstr "Remove delete request" + +#: templates/admin/cms_change_form.html:52 +msgid "Approve delete" +msgstr "Approve delete" + +#: templates/admin/cms_change_form.html:52 +msgid "Approve" +msgstr "Approve" + +#: templates/admin/cms_change_form.html:52 +#: templates/admin/cms_change_form.html:53 +msgid "draft" +msgstr "draft" + +#: templates/admin/cms_change_form.html:53 +msgid "Preview" +msgstr "Preview" + +#: templates/admin/cms_change_form.html:56 +#: templates/admin/page_change_form.html:27 +msgid "History" +msgstr "History" + +#: templates/admin/cms_change_form.html:57 +#: templates/admin/page_change_form.html:28 +msgid "View on site" +msgstr "View on site" + +#: templates/admin/cms_change_form.html:87 +#: templates/admin/page_change_form.html:38 +#: templates/admin/page_change_list.html:54 +#: templates/cms/admin/cms/page/change_form.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Please correct the error below." +msgstr[1] "Please correct the errors below." + +#: templates/admin/cms_change_form.html:107 +msgid "All permissions" +msgstr "All permissions" + +#: templates/admin/cms_change_form.html:108 +#: templates/admin/cms_change_form.html:120 +msgid "Loading..." +msgstr "Loading..." + +#: templates/admin/cms_change_form.html:119 +msgid "Page states" +msgstr "Page states" + +#: templates/admin/cms_change_form.html:142 +#, python-format +msgid "" +"This page must be moderated at level %(moderation_level)s, post a message " +"for moderator." +msgstr "" +"This page must be moderated at level %(moderation_level)s, post a message " +"for moderator." + +#: templates/admin/cms_change_form.html:144 +msgid "Request approvemet" +msgstr "Request approvemet" + +#: templates/admin/cms_change_form.html:234 +#: user/templates/registration/registration_form.html:16 +msgid "Save" +msgstr "Save" + +#: templates/admin/cms_change_form.html:235 +msgid "Save and continue editing" +msgstr "Save and continue editing" + +#: templates/admin/cms_change_list.html:51 +msgid "Successfully moved" +msgstr "Successfully moved" + +#: templates/admin/cms_change_list.html:76 +#, python-format +msgid "Recover deleted %(name)s" +msgstr "Recover deleted %(name)s" + +#: templates/admin/cms_change_list.html:79 +#: templates/admin/page_change_list.html:46 +#, python-format +msgid "Add %(name)s" +msgstr "Add %(name)s" + +#: templates/admin/cms_change_list.html:91 +msgid "Pages on:" +msgstr "Pages on:" + +#: templates/admin/cms_change_list.html:108 +msgid "on" +msgstr "on" + +#: templates/admin/cms_change_list.html:108 +msgid "off" +msgstr "off" + +#: templates/admin/cms_change_list.html:110 +#: templates/admin/page_change_list.html:65 +msgid "Filter" +msgstr "Filter" + +#: templates/admin/index.html:18 templates/admin/page_index.html:18 +#, python-format +msgid "Models available in the %(name)s application." +msgstr "Models available in the %(name)s application." + +#: templates/admin/index.html:19 templates/admin/page_app_index.html:10 +#: templates/admin/page_index.html:19 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" + +#: templates/admin/index.html:29 templates/admin/page_change_form.html:20 +#: templates/admin/page_index.html:29 +msgid "Add" +msgstr "Add" + +#: templates/admin/index.html:35 templates/admin/page_index.html:35 +msgid "Change" +msgstr "changed by" + +#: templates/admin/index.html:64 templates/admin/page_index.html:45 +msgid "You don't have permission to edit anything." +msgstr "You don't have permission to edit anything." + +#: templates/admin/index.html:72 templates/admin/page_index.html:53 +msgid "Recent Actions" +msgstr "Recent Actions" + +#: templates/admin/index.html:73 templates/admin/page_index.html:54 +msgid "My Actions" +msgstr "My Actions" + +#: templates/admin/index.html:77 templates/admin/page_index.html:58 +msgid "None available" +msgstr "None available" + +#: templates/admin/index.html:91 templates/admin/page_index.html:72 +msgid "Unknown content" +msgstr "Unknown content" + +#: templates/admin/page_base.html:20 templates/admin/page_index.html:11 +msgid "Pages" +msgstr "Pages" + +#: templates/admin/page_base_site.html:7 +msgid "Django administration" +msgstr "Django administration" + +#: templates/admin/page_login.html:8 +msgid "Connexion" +msgstr "Login" + +#: templates/admin/page_login.html:20 +msgid "Username:" +msgstr "Username:" + +#: templates/admin/page_login.html:24 +msgid "Password:" +msgstr "Password:" + +#: templates/admin/page_login.html:29 +#: user/templates/registration/login.html:29 +msgid "Create an account" +msgstr "Create an account" + +#: templates/admin/page_login.html:30 +#: user/templates/registration/login.html:30 +msgid "Forget password?" +msgstr "Forget password?" + +#: templates/admin/page_login.html:32 +#: user/templates/iriuser/user/login_form.html:37 +#: user/templates/iriuser/user/login_form.html:45 +#: user/templates/registration/login.html:14 +#: user/templates/registration/password_reset_complete.html:14 +msgid "Log in" +msgstr "Log in" + +#: templates/cms/admin/cms/page/change_form.html:11 +msgid "Documentation" +msgstr "Documentation" + +#: templates/cms/admin/cms/page/change_form.html:11 +msgid "Change password" +msgstr "Change password" + +#: templates/cms/admin/cms/page/change_form.html:11 +#: user/templates/iriuser/user/login_form.html:34 +msgid "Log out" +msgstr "Log out" + +#: templates/cms/admin/cms/page/change_form.html:42 +msgid "Ordering" +msgstr "Ordering" + +#: templates/cms/admin/cms/page/change_form.html:45 +msgid "Order:" +msgstr "Order:" + +#: user/admin.py:15 +msgid "User details" +msgstr "User details" + +#: user/admin.py:16 +msgid "Groups" +msgstr "Groups" + +#: user/admin.py:17 +msgid "Permissions" +msgstr "Permissions" + +#: user/admin.py:27 user/templates/iriuser/user/login_form.html:61 +msgid "Password" +msgstr "Password" + +#: user/forms.py:31 +msgid "New password" +msgstr "New password" + +#: user/forms.py:33 +msgid "New password confirmation" +msgstr "New password confirmation" + +#: user/forms.py:78 user/forms.py:79 +msgid "E-mail" +msgstr "E-mail" + +#: user/forms.py:90 +msgid "The two emails didn't match." +msgstr "The two emails didn't match." + +#: user/views.py:45 user/templates/registration/login.html:17 +msgid "Sorry, that's not a valid username or password." +msgstr "Sorry, that's not a valid username or password." + +#: user/templates/iriuser/user/change_email.html:6 +#: user/templates/iriuser/user/change_email_done.html:6 +#: user/templates/iriuser/user/login_form.html:32 +#: user/templates/registration/password_change_done.html:7 +#: user/templates/registration/password_change_form.html:13 +msgid "Profiles" +msgstr "Profiles" + +#: user/templates/iriuser/user/change_email.html:7 +#: user/templates/iriuser/user/change_email.html:10 +msgid "Modification de l'adresse émail" +msgstr "E-mail change" + +#: user/templates/iriuser/user/change_email.html:26 +msgid "" +"Please enter your new e-mail twice so we can verify you typed it in " +"correctly." +msgstr "" +"Please enter your new e-mail twice so we can verify you typed it in " +"correctly." + +#: user/templates/iriuser/user/change_email.html:32 +msgid "email" +msgstr "email" + +#: user/templates/iriuser/user/change_email.html:41 +msgid "Confirmation de l'adresse émail" +msgstr "E-mail confirmation" + +#: user/templates/iriuser/user/change_email.html:48 +msgid "change my e-mail" +msgstr "Change my e-mail" + +#: user/templates/iriuser/user/change_email_done.html:7 +#: user/templates/iriuser/user/change_email_done.html:10 +msgid "email change" +msgstr "email change" + +#: user/templates/iriuser/user/change_email_done.html:12 +msgid "email changed" +msgstr "changed by" + +#: user/templates/iriuser/user/change_email_done.html:13 +msgid "back to profile" +msgstr "back to profile" + +#: user/templates/iriuser/user/home.html:9 +msgid "Se connecter" +msgstr "Login" + +#: user/templates/iriuser/user/home.html:10 +msgid "Créer un compte" +msgstr "Create an account" + +#: user/templates/iriuser/user/home.html:11 +msgid "récupérer mot de passe" +msgstr "Forget password?" + +#: user/templates/iriuser/user/login_form.html:50 +msgid "create account" +msgstr "create account" + +#: user/templates/iriuser/user/login_form.html:54 +msgid "Pseudo" +msgstr "Username" + +#: user/templates/iriuser/user/login_form.html:57 +#: user/templates/iriuser/user/login_form.html:64 +msgid "this field is compulsory" +msgstr "this field is compulsory" + +#: user/templates/iriuser/user/login_form.html:68 +msgid "reset password" +msgstr "reset password" + +#: user/templates/iriuser/user/login_form.html:71 +msgid "Connection" +msgstr "Login" + +#: user/templates/iriuser/user/profile.html:6 +#: user/templates/registration/password_change_form.html:14 +#: user/templates/registration/password_change_form.html:17 +msgid "Password change" +msgstr "Password change" + +#: user/templates/iriuser/user/profile.html:7 +msgid "Mail change" +msgstr "Mail change" + +#: user/templates/iriuser/user/space.html:13 +msgid "Page" +msgstr "Pages" + +#: user/templates/iriuser/user/space.html:16 +msgid "Projets Lignes de temps" +msgstr "Lignes de temps projects" + +#: user/templates/registration/activate.html:6 +#: user/templates/registration/activate.html:9 +msgid "Activate account" +msgstr "Activate account" + +#: user/templates/registration/activate.html:12 +msgid "You have activated your account" +msgstr "You have activated your account" + +#: user/templates/registration/activate.html:13 +msgid "Go back to login page" +msgstr "Go back to login page" + +#: user/templates/registration/activation_complete.html:4 +#: user/templates/registration/registration_complete.html:8 +msgid "Sign up successfully" +msgstr "Sign up successfully" + +#: user/templates/registration/activation_complete.html:6 +msgid "activation completed" +msgstr "activation completed" + +#: user/templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "Thanks for spending some quality time with the Web site today." + +#: user/templates/registration/logged_out.html:10 +msgid "Log in again" +msgstr "Log in again" + +#: user/templates/registration/login.html:25 +msgid "login" +msgstr "login" + +#: user/templates/registration/password_change_done.html:3 +#: user/templates/registration/password_change_done.html:11 +msgid "password change successful" +msgstr "password change successful" + +#: user/templates/registration/password_change_done.html:8 +msgid "password change" +msgstr "password change" + +#: user/templates/registration/password_change_done.html:14 +msgid "Your password has been changed." +msgstr "Your password has been changed." + +#: user/templates/registration/password_change_done.html:15 +msgid "Go back to profiles" +msgstr "Go back to profiles" + +#: user/templates/registration/password_change_form.html:20 +msgid "" +"Please enter your old password, for security's sake, and then enter your new " +"password twice so we can verify you typed it in correctly." +msgstr "" +"Please enter your old password, for security's sake, and then enter your new " +"password twice so we can verify you typed it in correctly." + +#: user/templates/registration/password_change_form.html:26 +msgid "Old password:" +msgstr "Old password:" + +#: user/templates/registration/password_change_form.html:32 +#: user/templates/registration/password_reset_confirm.html:19 +msgid "New password:" +msgstr "New password:" + +#: user/templates/registration/password_change_form.html:38 +#: user/templates/registration/password_reset_confirm.html:21 +msgid "Confirm password:" +msgstr "Confirm password:" + +#: user/templates/registration/password_change_form.html:44 +#: user/templates/registration/password_reset_confirm.html:22 +msgid "Change my password" +msgstr "Change my password" + +#: user/templates/registration/password_reset_complete.html:6 +#: user/templates/registration/password_reset_confirm.html:6 +#: user/templates/registration/password_reset_confirm.html:9 +#: user/templates/registration/password_reset_done.html:6 +#: user/templates/registration/password_reset_form.html:13 +#: user/templates/registration/password_reset_form.html:15 +#: user/templates/registration/password_reset_form.html:18 +msgid "Password reset" +msgstr "Password reset" + +#: user/templates/registration/password_reset_complete.html:9 +msgid "Password reset complete" +msgstr "Password reset complete" + +#: user/templates/registration/password_reset_complete.html:12 +msgid "Your password has been set. You may go ahead and log in now." +msgstr "Your password has been set. You may go ahead and log in now." + +#: user/templates/registration/password_reset_confirm.html:15 +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." + +#: user/templates/registration/password_reset_confirm.html:27 +msgid "Password reset unsuccessful" +msgstr "Password reset unsuccessful" + +#: user/templates/registration/password_reset_confirm.html:29 +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." + +#: user/templates/registration/password_reset_done.html:8 +msgid "Password reset successful" +msgstr "Password reset successful" + +#: user/templates/registration/password_reset_done.html:12 +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." + +#: user/templates/registration/password_reset_email.html:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "You're receiving this e-mail because you requested a password reset" + +#: user/templates/registration/password_reset_email.html:3 +#, python-format +msgid "for your user account at %(site_name)s" +msgstr "for your user account at %(site_name)s" + +#: user/templates/registration/password_reset_email.html:5 +msgid "Please go to the following page and choose a new password:" +msgstr "Please go to the following page and choose a new password:" + +#: user/templates/registration/password_reset_email.html:9 +msgid "Your username, in case you've forgotten:" +msgstr "Your username, in case you've forgotten:" + +#: user/templates/registration/password_reset_email.html:11 +msgid "Thanks for using our site!" +msgstr "Thanks for using our site!" + +#: user/templates/registration/password_reset_email.html:13 +#, python-format +msgid "The %(site_name)s team" +msgstr "The %(site_name)s team" + +#: user/templates/registration/password_reset_form.html:22 +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." +msgstr "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." + +#: user/templates/registration/password_reset_form.html:27 +msgid "Adresse émail" +msgstr "E-mail" + +#: user/templates/registration/password_reset_form.html:32 +msgid "Reset my password" +msgstr "Reset my password" + +#: user/templates/registration/registration_active.html:5 +#: user/templates/registration/registration_active.html:7 +msgid "Activate the account" +msgstr "Activate the account" + +#: user/templates/registration/registration_active.html:9 +msgid "" +"Vous avez bien activé votre compte, vous pouvez accedez à votre espace " +"personnel." +msgstr "" +"Vous avez bien activé votre compte, vous pouvez accedez à votre espace " +"personnel." + +#: user/templates/registration/registration_active.html:10 +msgid "retourner à la page de connexion" +msgstr "go back to login page" + +#: user/templates/registration/registration_complete.html:6 +#: user/templates/registration/registration_form.html:11 +msgid "Sign up" +msgstr "Sign up" + +#: user/templates/registration/registration_complete.html:10 +msgid "" +"We've e-mailed you instructions for activate your account to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"We've e-mailed you instructions for activate your account to the e-mail " +"address you submitted. You should be receiving it shortly." + +#~ msgid "Changement de l'adresse émail" +#~ msgstr "E-mail change" + +#~ msgid "Mot de passe" +#~ msgstr "Password" + +#~ msgid "Déconnexion" +#~ msgstr "Logout" diff -r 000000000000 -r ecdfc63274bf web/ldt/locale/fr/LC_MESSAGES/django.mo Binary file web/ldt/locale/fr/LC_MESSAGES/django.mo has changed diff -r 000000000000 -r ecdfc63274bf web/ldt/locale/fr/LC_MESSAGES/django.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/locale/fr/LC_MESSAGES/django.po Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,619 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-03-09 08:48-0600\n" +"PO-Revision-Date: 2010-03-09 15:52+0100\n" +"Last-Translator: Yves-Marie Haussonne \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ldt/models.py:43 +msgid "created by" +msgstr "créé par" + +#: ldt/models.py:44 +msgid "changed by" +msgstr "modifié par" + +#: ldt/templates/admin/ldt/app_action.html:6 +#: templates/admin/cms_change_list.html:7 +#: templates/admin/page_app_index.html:8 +#: templates/admin/page_change_form.html:17 +#: templates/admin/page_change_list.html:25 +#: user/templates/registration/logged_out.html:4 +msgid "Home" +msgstr "Accueil" + +#: ldt/templates/iriuser/ldt/copy_ldt.html:12 +msgid "Copy your project" +msgstr "Copier votre projet" + +#: ldt/templates/iriuser/ldt/copy_ldt.html:15 +#: ldt/templates/iriuser/ldt/create_ldt.html:15 +msgid "Title" +msgstr "Titre" + +#: ldt/templates/iriuser/ldt/copy_ldt.html:18 +msgid "Copy" +msgstr "Copier" + +#: ldt/templates/iriuser/ldt/create_ldt.html:12 +msgid "Create your project" +msgstr "Créer votre projet Lignes de Temps" + +#: ldt/templates/iriuser/ldt/create_ldt.html:18 +msgid "List of contents" +msgstr "Liste de contenus" + +#: ldt/templates/iriuser/ldt/create_ldt.html:25 +msgid "Create" +msgstr "Créer" + +#: ldt/templates/iriuser/ldt/ldt_list.html:50 +#: templates/admin/page_base.html:19 +#: user/templates/iriuser/user/login_form.html:33 +#: user/templates/iriuser/user/space.html:6 +#: user/templates/iriuser/user/space.html:9 +msgid "Space" +msgstr "Esp. perso" + +#: ldt/templates/iriuser/ldt/ldt_list.html:51 +#: ldt/templates/iriuser/ldt/ldt_list.html:53 +msgid "Ldt Project" +msgstr "Projet lignes de temps" + +#: ldt/templates/iriuser/ldt/ldt_list.html:57 +msgid "Create new project" +msgstr "Créer un nouveau projet Ligne de Temps" + +#: ldt/templates/iriuser/ldt/ldt_list.html:59 +msgid "Project" +msgstr "Projet" + +#: ldt/templates/iriuser/ldt/ldt_list.html:62 +msgid "title" +msgstr "Titre" + +#: ldt/templates/iriuser/ldt/ldt_list.html:63 +msgid " published" +msgstr "Publié" + +#: templates/admin/cms_change_form.html:30 +msgid "Approve page deletion" +msgstr "Accepter l'effacement de la page" + +#: templates/admin/cms_change_form.html:36 +#, python-format +msgid "(requires approvement at %(moderation_level)s level)" +msgstr "(Demande l'approbation au niveau %(moderation_level)s)" + +#: templates/admin/cms_change_form.html:37 +msgid "(you can perform actions on this page directly)" +msgstr "(Vous pouvez agir sur cette page directement)" + +#: templates/admin/cms_change_form.html:50 +msgid "Remove delete request" +msgstr "Effacer la requête d'affacement" + +#: templates/admin/cms_change_form.html:52 +msgid "Approve delete" +msgstr "Accepter l'effacement" + +#: templates/admin/cms_change_form.html:52 +msgid "Approve" +msgstr "Accepter" + +#: templates/admin/cms_change_form.html:52 +#: templates/admin/cms_change_form.html:53 +msgid "draft" +msgstr "brouillon" + +#: templates/admin/cms_change_form.html:53 +msgid "Preview" +msgstr "Aperçu" + +#: templates/admin/cms_change_form.html:56 +#: templates/admin/page_change_form.html:27 +msgid "History" +msgstr "Histoire" + +#: templates/admin/cms_change_form.html:57 +#: templates/admin/page_change_form.html:28 +msgid "View on site" +msgstr "Voir sur le site" + +#: templates/admin/cms_change_form.html:87 +#: templates/admin/page_change_form.html:38 +#: templates/admin/page_change_list.html:54 +#: templates/cms/admin/cms/page/change_form.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Veuillez corriger l'erreur ci-dessous" +msgstr[1] "Veuillez corriger les erreurs ci-dessous" + +#: templates/admin/cms_change_form.html:107 +msgid "All permissions" +msgstr "Toutes le parmissions" + +#: templates/admin/cms_change_form.html:108 +#: templates/admin/cms_change_form.html:120 +msgid "Loading..." +msgstr "Chargement..." + +#: templates/admin/cms_change_form.html:119 +msgid "Page states" +msgstr "Etat de la page" + +#: templates/admin/cms_change_form.html:142 +#, python-format +msgid "This page must be moderated at level %(moderation_level)s, post a message for moderator." +msgstr "Le niveau nécessaire pour modérer cette page est le niveau %(moderation_level)s, laisser un message pour le modérateur" + +#: templates/admin/cms_change_form.html:144 +msgid "Request approvemet" +msgstr "Demander l'approbation" + +#: templates/admin/cms_change_form.html:234 +#: user/templates/registration/registration_form.html:16 +msgid "Save" +msgstr "Enregistrer" + +#: templates/admin/cms_change_form.html:235 +msgid "Save and continue editing" +msgstr "Sauver et continuer l'édition" + +#: templates/admin/cms_change_list.html:51 +msgid "Successfully moved" +msgstr "Déplacement réussi" + +#: templates/admin/cms_change_list.html:76 +#, python-format +msgid "Recover deleted %(name)s" +msgstr "Récupérer %(name)s effacé" + +#: templates/admin/cms_change_list.html:79 +#: templates/admin/page_change_list.html:46 +#, python-format +msgid "Add %(name)s" +msgstr "Ajouter %(name)s" + +#: templates/admin/cms_change_list.html:91 +msgid "Pages on:" +msgstr "Pages sur:" + +#: templates/admin/cms_change_list.html:108 +msgid "on" +msgstr "on" + +#: templates/admin/cms_change_list.html:108 +msgid "off" +msgstr "off" + +#: templates/admin/cms_change_list.html:110 +#: templates/admin/page_change_list.html:65 +msgid "Filter" +msgstr "Filtre" + +#: templates/admin/index.html:18 +#: templates/admin/page_index.html:18 +#, python-format +msgid "Models available in the %(name)s application." +msgstr "Le modèle disponible dans l'application %(name)s." + +#: templates/admin/index.html:19 +#: templates/admin/page_app_index.html:10 +#: templates/admin/page_index.html:19 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" + +#: templates/admin/index.html:29 +#: templates/admin/page_change_form.html:20 +#: templates/admin/page_index.html:29 +msgid "Add" +msgstr "Ajouter" + +#: templates/admin/index.html:35 +#: templates/admin/page_index.html:35 +msgid "Change" +msgstr "modifié par" + +#: templates/admin/index.html:64 +#: templates/admin/page_index.html:45 +msgid "You don't have permission to edit anything." +msgstr "Vous n'aver pas l'autorisation d'éditer quoi que ce soit." + +#: templates/admin/index.html:72 +#: templates/admin/page_index.html:53 +msgid "Recent Actions" +msgstr "Actions récentes" + +#: templates/admin/index.html:73 +#: templates/admin/page_index.html:54 +msgid "My Actions" +msgstr "Mes actions" + +#: templates/admin/index.html:77 +#: templates/admin/page_index.html:58 +msgid "None available" +msgstr "Aucune disponible" + +#: templates/admin/index.html:91 +#: templates/admin/page_index.html:72 +msgid "Unknown content" +msgstr "Contenu inconnu" + +#: templates/admin/page_base.html:20 +#: templates/admin/page_index.html:11 +msgid "Pages" +msgstr "Pages" + +#: templates/admin/page_base_site.html:7 +msgid "Django administration" +msgstr "Administration de Django" + +#: templates/admin/page_login.html:8 +msgid "Connexion" +msgstr "Connexion" + +#: templates/admin/page_login.html:20 +msgid "Username:" +msgstr "Nom de utilisateur :" + +#: templates/admin/page_login.html:24 +msgid "Password:" +msgstr "Mot de passe :" + +#: templates/admin/page_login.html:29 +#: user/templates/registration/login.html:29 +msgid "Create an account" +msgstr "Créer un compte" + +#: templates/admin/page_login.html:30 +#: user/templates/registration/login.html:30 +msgid "Forget password?" +msgstr "Oubliez le mot de passe?" + +#: templates/admin/page_login.html:32 +#: user/templates/iriuser/user/login_form.html:37 +#: user/templates/iriuser/user/login_form.html:45 +#: user/templates/registration/login.html:14 +#: user/templates/registration/password_reset_complete.html:14 +msgid "Log in" +msgstr "Connexion" + +#: templates/cms/admin/cms/page/change_form.html:11 +msgid "Documentation" +msgstr "Documentation" + +#: templates/cms/admin/cms/page/change_form.html:11 +msgid "Change password" +msgstr "Modifier le mot de passe" + +#: templates/cms/admin/cms/page/change_form.html:11 +#: user/templates/iriuser/user/login_form.html:34 +msgid "Log out" +msgstr "Déconnexion" + +#: templates/cms/admin/cms/page/change_form.html:42 +msgid "Ordering" +msgstr "Ordre" + +#: templates/cms/admin/cms/page/change_form.html:45 +msgid "Order:" +msgstr "Ordre :" + +#: user/admin.py:15 +msgid "User details" +msgstr "Détail utilisateur" + +#: user/admin.py:16 +msgid "Groups" +msgstr "Groupes" + +#: user/admin.py:17 +msgid "Permissions" +msgstr "Permissions" + +#: user/admin.py:27 +#: user/templates/iriuser/user/login_form.html:61 +msgid "Password" +msgstr "Mot de passe" + +#: user/forms.py:31 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: user/forms.py:33 +msgid "New password confirmation" +msgstr "Confirmation du nouveau mot de passe" + +#: user/forms.py:78 +#: user/forms.py:79 +msgid "E-mail" +msgstr "E-mail" + +#: user/forms.py:90 +msgid "The two emails didn't match." +msgstr "les deux emails ne correspondent pas" + +#: user/views.py:45 +#: user/templates/registration/login.html:17 +msgid "Sorry, that's not a valid username or password." +msgstr "Saisissez un nom d'utilisateur et un mot de passe valide." + +#: user/templates/iriuser/user/change_email.html:6 +#: user/templates/iriuser/user/change_email_done.html:6 +#: user/templates/iriuser/user/login_form.html:32 +#: user/templates/registration/password_change_done.html:7 +#: user/templates/registration/password_change_form.html:13 +msgid "Profiles" +msgstr "Mon profil" + +#: user/templates/iriuser/user/change_email.html:7 +#: user/templates/iriuser/user/change_email.html:10 +msgid "Modification de l'adresse émail" +msgstr "Modification de l'adresse email" + +#: user/templates/iriuser/user/change_email.html:26 +msgid "Please enter your new e-mail twice so we can verify you typed it in correctly." +msgstr "Saisissez deux fois votre nouvelle adresse émail afin de vérifier qu'il est correctment" + +#: user/templates/iriuser/user/change_email.html:32 +msgid "email" +msgstr "adresse émail" + +#: user/templates/iriuser/user/change_email.html:41 +msgid "Confirmation de l'adresse émail" +msgstr "Confirmation de l'adresse email" + +#: user/templates/iriuser/user/change_email.html:48 +msgid "change my e-mail" +msgstr "Changer l'adresse émail" + +#: user/templates/iriuser/user/change_email_done.html:7 +#: user/templates/iriuser/user/change_email_done.html:10 +msgid "email change" +msgstr "Modification de l'adresse émail" + +#: user/templates/iriuser/user/change_email_done.html:12 +msgid "email changed" +msgstr "email modifié" + +#: user/templates/iriuser/user/change_email_done.html:13 +msgid "back to profile" +msgstr "Retourner à mon profil" + +#: user/templates/iriuser/user/home.html:9 +msgid "Se connecter" +msgstr "Se connecter" + +#: user/templates/iriuser/user/home.html:10 +msgid "Créer un compte" +msgstr "Créere un compte" + +#: user/templates/iriuser/user/home.html:11 +msgid "récupérer mot de passe" +msgstr "Récupérer le mot de passe" + +#: user/templates/iriuser/user/login_form.html:50 +msgid "create account" +msgstr "Créer un compte" + +#: user/templates/iriuser/user/login_form.html:54 +msgid "Pseudo" +msgstr "Pseudo" + +#: user/templates/iriuser/user/login_form.html:57 +#: user/templates/iriuser/user/login_form.html:64 +msgid "this field is compulsory" +msgstr "Ce champs est obligatoire" + +#: user/templates/iriuser/user/login_form.html:68 +msgid "reset password" +msgstr "Réinitialiser le mot de passe" + +#: user/templates/iriuser/user/login_form.html:71 +msgid "Connection" +msgstr "Connexion" + +#: user/templates/iriuser/user/profile.html:6 +#: user/templates/registration/password_change_form.html:14 +#: user/templates/registration/password_change_form.html:17 +msgid "Password change" +msgstr "Modification du mot de passe" + +#: user/templates/iriuser/user/profile.html:7 +msgid "Mail change" +msgstr "Modification de l'adresse émail" + +#: user/templates/iriuser/user/space.html:13 +msgid "Page" +msgstr "Pages" + +#: user/templates/iriuser/user/space.html:16 +msgid "Projets Lignes de temps" +msgstr "Projets Lignes de temps" + +#: user/templates/registration/activate.html:6 +#: user/templates/registration/activate.html:9 +msgid "Activate account" +msgstr "Activer le compte" + +#: user/templates/registration/activate.html:12 +msgid "You have activated your account" +msgstr "Vous avez bien activé votre compte." + +#: user/templates/registration/activate.html:13 +msgid "Go back to login page" +msgstr "Retourner à la page de connexion" + +#: user/templates/registration/activation_complete.html:4 +#: user/templates/registration/registration_complete.html:8 +msgid "Sign up successfully" +msgstr "Création de compte avec succès" + +#: user/templates/registration/activation_complete.html:6 +msgid "activation completed" +msgstr "Activation terminée" + +#: user/templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "Merci de votre visite." + +#: user/templates/registration/logged_out.html:10 +msgid "Log in again" +msgstr "Se reconnecter" + +#: user/templates/registration/login.html:25 +msgid "login" +msgstr "Connexion" + +#: user/templates/registration/password_change_done.html:3 +#: user/templates/registration/password_change_done.html:11 +msgid "password change successful" +msgstr "Changement de mot de passe réussi" + +#: user/templates/registration/password_change_done.html:8 +msgid "password change" +msgstr "Changement de mot de passe" + +#: user/templates/registration/password_change_done.html:14 +msgid "Your password has been changed." +msgstr "Votre mot de passe a été changeé." + +#: user/templates/registration/password_change_done.html:15 +msgid "Go back to profiles" +msgstr "Retourner à la page de mon profil" + +#: user/templates/registration/password_change_form.html:20 +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "Par sécurité, veuillez enter votre ancien mot de passe puis le nouveau a deux reprise afin de savoir si vous l'avez taper correctement " + +#: user/templates/registration/password_change_form.html:26 +msgid "Old password:" +msgstr "Ancien mot de passe :" + +#: user/templates/registration/password_change_form.html:32 +#: user/templates/registration/password_reset_confirm.html:19 +msgid "New password:" +msgstr "Nouveau mot de passe :" + +#: user/templates/registration/password_change_form.html:38 +#: user/templates/registration/password_reset_confirm.html:21 +msgid "Confirm password:" +msgstr "Confirmer le mot de passe :" + +#: user/templates/registration/password_change_form.html:44 +#: user/templates/registration/password_reset_confirm.html:22 +msgid "Change my password" +msgstr "Modifier mon mot de passe" + +#: user/templates/registration/password_reset_complete.html:6 +#: user/templates/registration/password_reset_confirm.html:6 +#: user/templates/registration/password_reset_confirm.html:9 +#: user/templates/registration/password_reset_done.html:6 +#: user/templates/registration/password_reset_form.html:13 +#: user/templates/registration/password_reset_form.html:15 +#: user/templates/registration/password_reset_form.html:18 +msgid "Password reset" +msgstr "réinitialiser e mot de passe" + +#: user/templates/registration/password_reset_complete.html:9 +msgid "Password reset complete" +msgstr "Réinitialisation du mot de passe terminée" + +#: user/templates/registration/password_reset_complete.html:12 +msgid "Your password has been set. You may go ahead and log in now." +msgstr "Votre mot de passe a été fixé. vous pouvez vous connecter maintenant." + +#: user/templates/registration/password_reset_confirm.html:15 +msgid "Please enter your new password twice so we can verify you typed it in correctly." +msgstr "veuillez enter votre nouveau mot de pass deux fois afin de le vérifier." + +#: user/templates/registration/password_reset_confirm.html:27 +msgid "Password reset unsuccessful" +msgstr "Reinitialisation du mot de pass a échoué" + +#: user/templates/registration/password_reset_confirm.html:29 +msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." +msgstr "Le lien de réinitialisation du mot de passe n'est pas valide, certainement car il a déjà été utilisé. veuiller demander une nouvelle réinitialisation." + +#: user/templates/registration/password_reset_done.html:8 +msgid "Password reset successful" +msgstr "Réinitialisation du mot de passe réussie" + +#: user/templates/registration/password_reset_done.html:12 +msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." +msgstr "Nous vous avons envoyer les instructions de reinitialisation de votre mot de passe à l'adresse email que vous nous avez fournie. vous devriez les recevoir bientôt." + +#: user/templates/registration/password_reset_email.html:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "Vous recevez ce mail car vous avez damender la réinitialisation du mot de passe" + +#: user/templates/registration/password_reset_email.html:3 +#, python-format +msgid "for your user account at %(site_name)s" +msgstr "Pour votre compte sur le site %(site_name)s" + +#: user/templates/registration/password_reset_email.html:5 +msgid "Please go to the following page and choose a new password:" +msgstr "veuillez aller à la page suivante et choisissez un nouveau mot de passe :" + +#: user/templates/registration/password_reset_email.html:9 +msgid "Your username, in case you've forgotten:" +msgstr "Pour rappel votre nom d'autilisateur :" + +#: user/templates/registration/password_reset_email.html:11 +msgid "Thanks for using our site!" +msgstr "Merci de votre visite." + +#: user/templates/registration/password_reset_email.html:13 +#, python-format +msgid "The %(site_name)s team" +msgstr "L'équipe du site %(site_name)s" + +#: user/templates/registration/password_reset_form.html:22 +msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." +msgstr "Mot de passe oublié ? Entrez votre adresse email ci-dessous pour recevoir les instructions pour en entrer un nouveau." + +#: user/templates/registration/password_reset_form.html:27 +msgid "Adresse émail" +msgstr "Adresse email" + +#: user/templates/registration/password_reset_form.html:32 +msgid "Reset my password" +msgstr "Reinitialiser mon mot de passe" + +#: user/templates/registration/registration_active.html:5 +#: user/templates/registration/registration_active.html:7 +msgid "Activate the account" +msgstr "Activer le compte" + +#: user/templates/registration/registration_active.html:9 +msgid "Vous avez bien activé votre compte, vous pouvez accedez à votre espace personnel." +msgstr "Vous avez bien activé votre compte, vous pouvez accedez à votre espace personnel." + +#: user/templates/registration/registration_active.html:10 +msgid "retourner à la page de connexion" +msgstr "retourner à la page de connexion" + +#: user/templates/registration/registration_complete.html:6 +#: user/templates/registration/registration_form.html:11 +msgid "Sign up" +msgstr "Création d'un compte" + +#: user/templates/registration/registration_complete.html:10 +msgid "We've e-mailed you instructions for activate your account to the e-mail address you submitted. You should be receiving it shortly." +msgstr "Nous vous avons envoyé par courriel les instructions pour activer le compte à l'adresse que vous avez indiquée. Vous devriez le recevoir rapidement." + +#~ msgid "Password (Verification)" +#~ msgstr "Mot de passe (Vérification)" diff -r 000000000000 -r ecdfc63274bf web/ldt/management/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/management/__init__.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,66 @@ +from django.db.models import signals +from django.conf import settings +from django.contrib.auth.models import User, Group +from ldt.core.models import Owner +from ldt.user.models import ldt, IriGroup +from django.contrib.contenttypes.models import ContentType +# import logging +from django.core.exceptions import ObjectDoesNotExist + + +def post_save_ldt(instance, raw, created, **kwargs): + signals.post_save.send(sender=User, instance=instance, raw=raw, created=created) + +signals.post_save.connect(post_save_ldt, ldt) + +def post_save_irigroup(instance, raw, created, **kwargs): + signals.post_save.send(sender=Group, instance=instance, raw=raw, created=created) + +signals.post_save.connect(post_save_irigroup, IriGroup) + +def post_save_user(instance, raw, created, **kwargs): + if created: + try: + owner = Owner.objects.get(user=instance) + except ObjectDoesNotExist: + owner=Owner(user=instance) + owner.save() + +signals.post_save.connect(post_save_user, User) + +def post_save_group(instance, raw, created, **kwargs): + if created: + try: + owner = Owner.objects.get(group=instance) + except ObjectDoesNotExist: + owner=Owner(group=instance) + owner.save() + +signals.post_save.connect(post_save_group, Group) + + +def test_cms(): + if 'cms' in settings.INSTALLED_APPS: + return True + else: + return False + +def test_ldt(): + if 'ldt.ldt' in settings.INSTALLED_APPS: + return True + else: + return False + +def get_content_type_list() : + content_type_list = [] + if test_cms(): + content_type = ContentType.objects.get(app_label='cms', model='page') + content_type_list.append(content_type) + content_type = ContentType.objects.get(app_label='snippet', model='snippet') + content_type_list.append(content_type) + # if test_ldt(): + # content_type = ContentType.objects.get(app_label='ldt', model='content') + # content_type_list.append(content_type) + return content_type_list + + diff -r 000000000000 -r ecdfc63274bf web/ldt/media/css/ldt.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/css/ldt.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,122 @@ +#addldtform +{ + font-size: 16px; + background: #ffffff scroll repeat 0 0; + border: 1px solid #666666; + text-align: left; + width: 700px; +} + +#addldtform .title +{ + color: #666666; + font-weight:bold !important; + font-size:16px; + position: relative; + padding:8px 12px; +} + +#addldtform .title .closebutton +{ + float: right; + text-decoration: none; + color:#666666; +} + + +#addldtform .form-row +{ + border-bottom: 1px solid #eeeeee; + font-size: 15px; + padding: 8px 12px; +} + +#addldtform label +{ + float: left; + padding: 3px 8px 0 0; + width:8em; + color: #333333 !important; + font-weight: bold !important; +} +#addldtform input +{ + font-size: 15px; + font-weight: normal; + padding:2px 3px; + vertical-align: middle; + margin : 2px 0; + background-color: #ffffff; + border: 1px solid #cccccc; +} + +#addldtform .checkbox +{ + padding: 6px 3px 3px 30px; +} + +#addldtform .submit-row input +{ + color:black; + border-color:#DDDDDD #AAAAAA #AAAAAA #DDDDDD; + background:#dddddd; + padding: 3px; + margin:0 10px 10px 10px; +} +/* +#ldtlist{ + width:60%; + overflow:auto; + padding:1em; +} +*/ +#ldtlist table { + border-collapse: collapse; + border-color: #ccc; + width:100%; +} +#ldtlist table caption{ + color:black; + font-size:15px; + font-weight:bold; + padding:5px; + text-align:left; + text-transform:uppercase; +} +#ldtlist td, th { + font-size: 11px; + line-height: 13px; + border-bottom: 1px solid #eee; + vertical-align: top; + padding: 5px; + font-family: "Lucida Grande", Verdana, Arial, sans-serif; +} + + +#ldtlist table thead { + color: #666; + padding: 2px 5px; + font-size: 13px; + background: #e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; + border-left: 1px solid #ddd; + border-bottom: 1px solid #ddd; + white-space: nowrap; + vertical-align: middle; + font-weight: bold; + text-align: center; +} + +#ldtlist table tbody td { + border-left: 1px solid #ddd; + text-align: center; +} + +#ldtlist table tbody td:first-child { + border-left: 0; + border-right: 1px solid #ddd; + text-align: left; +} + +#ldtlist table tfoot { + color: #666; +} diff -r 000000000000 -r ecdfc63274bf web/ldt/media/css/style.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/css/style.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,47 @@ +#loginstate a, #loginstate a:hover, #loginstate a:visited, #loginstate a:link, #loginstate a:active { + color:#0063DC; + margin-right:4px; + text-decoration:none; +} + +#loginstate a:hover{ + text-decoration: underline; +} + +#loginstate ul { + margin:0; + padding:0; + float: left; +} +#loginstate li{ + display: inline; + padding:0; + margin:0; +} +#loginstate #user{ + color: #000000; + font-weight: bold; + margin-right:4px; +} +#loginstate ul .usertool a, +#loginstate ul .usertool a:link, +#loginstate ul .usertool a:visited { + color:#0063DC; + text-decoration:none; +} + +#loginstate ul .usertool a:hover { + color:#0063DC; + text-decoration:underline; +} + +.errorlist +{ + color: red; + font-size:12px +} + + + + + diff -r 000000000000 -r ecdfc63274bf web/ldt/media/css/style_base.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/css/style_base.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,202 @@ +body +{ font-family: Arial, Helvetica, sans serif; + padding: 0px; + margin: 0px; + background-color: #f9f9f9; + font-size: 12px; +} + +a +{ + color: #0045A3; + text-decoration:none; +} + +a:hover +{ + color: #990000; + text-decoration: underline; +} + +p +{ + font-size:12px; + font-weight:normal; + margin:0; + padding:0; +} + +th +{ + text-align: left; +} +.button +{ + margin: 3px 0; + margin-left: 25px; + background: #3366CC; + padding: 0 6px; + border-color: #6699CC #3366CC #3366CC #6699CC; + border-style: solid; + border-width: 1px 2px 2px 1px; + font-size: 13px; + font-style: normal; + font-weight: bold; + color: #ffffff; +} + +.errorlist +{ + color: red; + font-size:12px +} +#header +{ + background-color: #ffffcc; + height: 50px; +} + +#logo +{ +} + +#usertool +{ +} + +#loginstate +{ + color:#0045A3; +} + +#menu +{ + width: 200px; + vertical-align: top; +} + +#container +{ + width: 90%; + margin: 10px auto; + background-color: #fff; + color: #000; +} +} +#content +{ +} + +#footer +{ +} + +/* page login *//* +#loginarea +{ + margin: 0 auto; + margin-top: 100px; + overflow: hidden; + width: 362px; + border: 2px solid #CCCCCC; +} + +#loginarea .title +{ + font-size: 15px; + color: #FFFFFF; + background: #990000 scroll repeat left top; + font-weight:bold; + height:34px; + position: relative; + line-height: 34px; + overflow: hidden; + text-transform: uppercase; +} + +#loginarea .title div +{ + margin-left: 12px; +} + +#loginarea .login-form +{ + margin-top:20px; + margin-left:25px; +} + +#loginarea .login-form .inputbox +{ + font-size: 13px; + line-height:20px; + text-align: left; +} + +#loginarea .login-form label +{ + font-size: 14px; + font-weight: bold; +} +/* +#loginarea .login-form .button +{ + margin: 3px 0; + margin-left: 25px; + background: #3366CC; + padding: 0 6px; + border-color: #6699CC #3366CC #3366CC #6699CC; + border-style: solid; + border-width: 1px 2px 2px 1px; + font-size: 13px; + font-style: normal; + font-weight: bold; + color: #ffffff; +} + +#loginarea a +{ + font-size: 12px; + background:url("norm_left.gif") no-repeat left top; + padding:5px 15px; + margin: 5px; +} + +#nav { + float:left; + width:100%; + font-size:93%; + line-height:normal; + background:#828282 repeat-x scroll 0 0; + margin:0; + padding:0; + list-style:none; +} + +#nav a:link, +#nav a:visited { + color:#fff; + background:#828282 repeat-x scroll 0 0; + padding:20px 40px 4px 10px; + float:left; + width:auto; + border-right:1px solid #999999; +} + +#nav li a:hover { + color:#fff; + background:#999999 none repeat scroll 0 0; +} + +#space #nav-space a, #profile #nav-profile a +{ + background:#666666 none repeat scroll 0 0; +} + +#space #nav-space, #profile #nav-profile +{ + background:#666666 none repeat scroll 0 0; + color:#FFFFFF; +} +*/ + + diff -r 000000000000 -r ecdfc63274bf web/ldt/media/img/loadingAnimation.gif Binary file web/ldt/media/img/loadingAnimation.gif has changed diff -r 000000000000 -r ecdfc63274bf web/ldt/media/js/jquery.DOMWindow.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/js/jquery.DOMWindow.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,372 @@ +(function($){ + + //closeDOMWindow + $.fn.closeDOMWindow = function(settings){ + + if(!settings){settings={};} + + var run = function(passingThis){ + + if(settings.anchoredClassName){ + var $anchorClassName = $('.'+settings.anchoredClassName); + $anchorClassName.fadeOut('fast',function(){ + if($.fn.draggable){ + $anchorClassName.draggable('destory').trigger("unload").remove(); + }else{ + $anchorClassName.trigger("unload").remove(); + } + }); + if(settings.functionCallOnClose){settings.functionCallAfterClose();} + }else{ + var $DOMWindowOverlay = $('#DOMWindowOverlay'); + var $DOMWindow = $('#DOMWindow'); + $DOMWindowOverlay.fadeOut('fast',function(){ + $DOMWindowOverlay.trigger('unload').unbind().remove(); + }); + $DOMWindow.fadeOut('fast',function(){ + if($.fn.draggable){ + $DOMWindow.draggable("destroy").trigger("unload").remove(); + }else{ + $DOMWindow.trigger("unload").remove(); + } + }); + + $(window).unbind('scroll.DOMWindow'); + $(window).unbind('resize.DOMWindow'); + + if($.fn.openDOMWindow.isIE6){$('#DOMWindowIE6FixIframe').remove();} + if(settings.functionCallOnClose){settings.functionCallAfterClose();} + } + }; + + if(settings.eventType){//if used with $(). + return this.each(function(index){ + $(this).bind(settings.eventType, function(){ + run(this); + return false; + }); + }); + }else{//else called as $.function + run(); + } + + }; + + //allow for public call, pass settings + $.closeDOMWindow = function(s){$.fn.closeDOMWindow(s);}; + + //openDOMWindow + $.fn.openDOMWindow = function(instanceSettings){ + + var shortcut = $.fn.openDOMWindow; + + //default settings combined with callerSettings//////////////////////////////////////////////////////////////////////// + + shortcut.defaultsSettings = { + anchoredClassName:'', + anchoredSelector:'', + borderColor:'#ccc', + borderSize:'4', + draggable:0, + eventType:null, //click, blur, change, dblclick, error, focus, load, mousedown, mouseout, mouseup etc... + fixedWindowY:100, + functionCallOnOpen:null, + functionCallOnClose:null, + height:500, + loader:0, + loaderHeight:0, + loaderImagePath:'', + loaderWidth:0, + modal:0, + overlay:1, + overlayColor:'#000', + overlayOpacity:'85', + positionLeft:0, + positionTop:0, + positionType:'centered', // centered, anchored, absolute, fixed + width:500, + windowBGColor:'#fff', + windowBGImage:null, // http path + windowHTTPType:'get', + windowPadding:10, + windowSource:'inline', //inline, ajax, iframe + windowSourceID:'', + windowSourceURL:'', + windowSourceAttrURL:'href', + windowOverflow : 'auto', + ajaxParameters : {} + }; + + var settings = $.extend({}, $.fn.openDOMWindow.defaultsSettings , instanceSettings || {}); + + //Public functions + + shortcut.viewPortHeight = function(){ return self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;}; + shortcut.viewPortWidth = function(){ return self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;}; + shortcut.scrollOffsetHeight = function(){ return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;}; + shortcut.scrollOffsetWidth = function(){ return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;}; + shortcut.isIE6 = typeof document.body.style.maxHeight === "undefined"; + + //Private Functions///////////////////////////////////////////////////////////////////////////////////////////////////////// + + var sizeOverlay = function(){ + var $DOMWindowOverlay = $('#DOMWindowOverlay'); + if(shortcut.isIE6){//if IE 6 + var overlayViewportHeight = document.documentElement.offsetHeight + document.documentElement.scrollTop - 4; + var overlayViewportWidth = document.documentElement.offsetWidth - 21; + $DOMWindowOverlay.css({'height':overlayViewportHeight +'px','width':overlayViewportWidth+'px'}); + }else{//else Firefox, safari, opera, IE 7+ + $DOMWindowOverlay.css({'height':'100%','width':'100%','position':'fixed'}); + } + }; + + var sizeIE6Iframe = function(){ + var overlayViewportHeight = document.documentElement.offsetHeight + document.documentElement.scrollTop - 4; + var overlayViewportWidth = document.documentElement.offsetWidth - 21; + $('#DOMWindowIE6FixIframe').css({'height':overlayViewportHeight +'px','width':overlayViewportWidth+'px'}); + }; + + var centerDOMWindow = function() { + var $DOMWindow = $('#DOMWindow'); + if(settings.height + 50 > shortcut.viewPortHeight()){//added 50 to be safe + $DOMWindow.css('left',Math.round(shortcut.viewPortWidth()/2) + shortcut.scrollOffsetWidth() - Math.round(($DOMWindow.outerWidth())/2)); + }else{ + $DOMWindow.css('left',Math.round(shortcut.viewPortWidth()/2) + shortcut.scrollOffsetWidth() - Math.round(($DOMWindow.outerWidth())/2)); + $DOMWindow.css('top',Math.round(shortcut.viewPortHeight()/2) + shortcut.scrollOffsetHeight() - Math.round(($DOMWindow.outerHeight())/2)); + } + }; + + var centerLoader = function() { + var $DOMWindowLoader = $('#DOMWindowLoader'); + if(shortcut.isIE6){//if IE 6 + $DOMWindowLoader.css({'left':Math.round(shortcut.viewPortWidth()/2) + shortcut.scrollOffsetWidth() - Math.round(($DOMWindowLoader.innerWidth())/2),'position':'absolute'}); + $DOMWindowLoader.css({'top':Math.round(shortcut.viewPortHeight()/2) + shortcut.scrollOffsetHeight() - Math.round(($DOMWindowLoader.innerHeight())/2),'position':'absolute'}); + }else{ + $DOMWindowLoader.css({'left':'50%','top':'50%','position':'fixed'}); + } + + }; + + var fixedDOMWindow = function(){ + var $DOMWindow = $('#DOMWindow'); + $DOMWindow.css('left', settings.positionLeft + shortcut.scrollOffsetWidth()); + $DOMWindow.css('top', + settings.positionTop + shortcut.scrollOffsetHeight()); + }; + + var showDOMWindow = function(instance){ + if(arguments[0]){ + $('.'+instance+' #DOMWindowLoader').remove(); + $('.'+instance+' #DOMWindowContent').fadeIn('fast',function(){if(settings.functionCallOnOpen){settings.functionCallOnOpen();}}); + $('.'+instance+ '.closeDOMWindow').click(function(){ + $.closeDOMWindow(); + return false; + }); + }else{ + $('#DOMWindowLoader').remove(); + $('#DOMWindow').fadeIn('fast',function(){if(settings.functionCallOnOpen){settings.functionCallOnOpen();}}); + $('#DOMWindow .closeDOMWindow').click(function(){ + $.closeDOMWindow(); + return false; + }); + } + + }; + + var urlQueryToObject = function(s, q){ + var query = typeof(q) != 'undefined' ? q : {}; + s.replace(/b([^&=]*)=([^&=]*)b/g, function (m, a, d) { + if (typeof query[a] != 'undefined') { + query[a] += ',' + d; + } else { + query[a] = d; + } + }); + return query; + }; + + //Run Routine /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + var run = function(passingThis){ + + //get values from element clicked, or assume its passed as an option + settings.windowSourceID = $(passingThis).attr('href') || settings.windowSourceID; + settings.windowSourceURL = $(passingThis).attr(settings.windowSourceAttrURL) || settings.windowSourceURL; + settings.windowBGImage = settings.windowBGImage ? 'background-image:url('+settings.windowBGImage+')' : ''; + var urlOnly, urlQueryObject; + + if(settings.positionType == 'anchored'){//anchored DOM window + + var anchoredPositions = $(settings.anchoredSelector).position(); + var anchoredPositionX = anchoredPositions.left + settings.positionLeft; + var anchoredPositionY = anchoredPositions.top + settings.positionTop; + + $('body').append('
    '); + //loader + if(settings.loader && settings.loaderImagePath !== ''){ + $('.'+settings.anchoredClassName).append('
    '); + + } + + if($.fn.draggable){ + if(settings.draggable){$('.' + settings.anchoredClassName).draggable({cursor:'move'});} + } + + switch(settings.windowSource){ + case 'inline'://////////////////////////////// inline ////////////////////////////////////////// + $('.' + settings.anchoredClassName+" #DOMWindowContent").append($(settings.windowSourceID).children()); + $('.' + settings.anchoredClassName).unload(function(){// move elements back when you're finished + $('.' + settings.windowSourceID).append( $('.' + settings.anchoredClassName+" #DOMWindowContent").children()); + }); + showDOMWindow(settings.anchoredClassName); + break; + case 'iframe'://////////////////////////////// iframe ////////////////////////////////////////// + $('.' + settings.anchoredClassName+" #DOMWindowContent").append(''); + $('.'+settings.anchoredClassName+'Iframe').load(showDOMWindow(settings.anchoredClassName)); + break; + case 'ajax'://////////////////////////////// ajax ////////////////////////////////////////// + if(settings.windowHTTPType == 'post'){ + + if(settings.windowSourceURL.indexOf("?") !== -1){//has a query string + urlOnly = settings.windowSourceURL.substr(0, settings.windowSourceURL.indexOf("?")); + urlQueryObject = urlQueryToObject(settings.windowSourceURL, settings.ajaxParameters); + }else{ + urlOnly = settings.windowSourceURL; + urlQueryObject = settings.ajaxParameters; + } + $('.' + settings.anchoredClassName+" #DOMWindowContent").load(urlOnly,urlQueryObject,function(){ + showDOMWindow(settings.anchoredClassName); + }); + }else{ + if(settings.windowSourceURL.indexOf("?") == -1){ //no query string, so add one + settings.windowSourceURL += '?'; + } + $('.' + settings.anchoredClassName+" #DOMWindowContent").load( + settings.windowSourceURL + '&random=' + (new Date().getTime()),function(){ + showDOMWindow(settings.anchoredClassName); + }); + } + break; + } + + }else{//centered, fixed, absolute DOM window + + //overlay & modal + if(settings.overlay){ + $('body').append(''); + if(shortcut.isIE6){//if IE 6 + $('body').append(''); + sizeIE6Iframe(); + } + sizeOverlay(); + var $DOMWindowOverlay = $('#DOMWindowOverlay'); + $DOMWindowOverlay.fadeIn('fast'); + if(!settings.modal){$DOMWindowOverlay.click(function(){$.closeDOMWindow();});} + } + + //loader + if(settings.loader && settings.loaderImagePath !== ''){ + $('body').append('
    '); + centerLoader(); + } + + //add DOMwindow + $('body').append(''); + + var $DOMWindow = $('#DOMWindow'); + //centered, absolute, or fixed + switch(settings.positionType){ + case 'centered': + centerDOMWindow(); + if(settings.height + 50 > shortcut.viewPortHeight()){//added 50 to be safe + $DOMWindow.css('top', (settings.fixedWindowY + shortcut.scrollOffsetHeight()) + 'px'); + } + break; + case 'absolute': + $DOMWindow.css({'top':(settings.positionTop+shortcut.scrollOffsetHeight())+'px','left':(settings.positionLeft+shortcut.scrollOffsetWidth())+'px'}); + if($.fn.draggable){ + if(settings.draggable){$DOMWindow.draggable({cursor:'move'});} + } + break; + case 'fixed': + fixedDOMWindow(); + break; + case 'anchoredSingleWindow': + var anchoredPositions = $(settings.anchoredSelector).position(); + var anchoredPositionX = anchoredPositions.left + settings.positionLeft; + var anchoredPositionY = anchoredPositions.top + settings.positionTop; + $DOMWindow.css({'top':anchoredPositionY + 'px','left':anchoredPositionX+'px'}); + + break; + } + + $(window).bind('scroll.DOMWindow',function(){ + if(settings.overlay){sizeOverlay();} + if(shortcut.isIE6){sizeIE6Iframe();} + if(settings.positionType == 'centered'){centerDOMWindow();} + if(settings.positionType == 'fixed'){fixedDOMWindow();} + }); + + $(window).bind('resize.DOMWindow',function(){ + if(shortcut.isIE6){sizeIE6Iframe();} + if(settings.overlay){sizeOverlay();} + if(settings.positionType == 'centered'){centerDOMWindow();} + }); + + switch(settings.windowSource){ + case 'inline'://////////////////////////////// inline ////////////////////////////////////////// + $DOMWindow.append($(settings.windowSourceID).children()); + $DOMWindow.unload(function(){// move elements back when you're finished + $(settings.windowSourceID).append($DOMWindow.children()); + }); + showDOMWindow(); + break; + case 'iframe'://////////////////////////////// iframe ////////////////////////////////////////// + var name = 'DOMWindowIframe'+Math.round(Math.random()*1000); + $DOMWindow.append(''); + $('#DOMWindowIframe').load(showDOMWindow()); + break; + case 'ajax'://////////////////////////////// ajax ////////////////////////////////////////// + if(settings.windowHTTPType == 'post'){ + + if(settings.windowSourceURL.indexOf("?") !== -1){//has a query string + urlOnly = settings.windowSourceURL.substr(0, settings.windowSourceURL.indexOf("?")); + urlQueryObject = urlQueryToObject(settings.windowSourceURL, settings.ajaxParameters); + }else{ + urlOnly = settings.windowSourceURL; + urlQueryObject = settings.ajaxParameters; + } + $DOMWindow.load(urlOnly,urlQueryObject,function(){ + showDOMWindow(); + }); + }else{ + if(settings.windowSourceURL.indexOf("?") == -1){ //no query string, so add one + settings.windowSourceURL += '?'; + } + $DOMWindow.load( + settings.windowSourceURL + '&random=' + (new Date().getTime()),function(){ + showDOMWindow(); + }); + } + break; + } + + }//end if anchored, or absolute, fixed, centered + + };//end run() + + if(settings.eventType){//if used with $(). + return this.each(function(index){ + $(this).bind(settings.eventType,function(){ + run(this); + return false; + }); + }); + }else{//else called as $.function + run(); + } + + };//end function openDOMWindow + + //allow for public call, pass settings + $.openDOMWindow = function(s){$.fn.openDOMWindow(s);}; + +})(jQuery); diff -r 000000000000 -r ecdfc63274bf web/ldt/media/js/jquery.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/js/jquery.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
    ","
    "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

    ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
    ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
    ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
    ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/media/js/jquery.validate.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/js/jquery.validate.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,1131 @@ +/* + * jQuery validation plug-in 1.5.5 + * + * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ + * http://docs.jquery.com/Plugins/Validation + * + * Copyright (c) 2006 - 2008 Jörn Zaefferer + * + * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function($) { + +$.extend($.fn, { + // http://docs.jquery.com/Plugins/Validation/validate + validate: function( options ) { + + // if nothing is selected, return nothing; can't chain anyway + if (!this.length) { + options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" ); + return; + } + + // check if a validator for this form was already created + var validator = $.data(this[0], 'validator'); + if ( validator ) { + return validator; + } + + validator = new $.validator( options, this[0] ); + $.data(this[0], 'validator', validator); + + if ( validator.settings.onsubmit ) { + + // allow suppresing validation by adding a cancel class to the submit button + this.find("input, button").filter(".cancel").click(function() { + validator.cancelSubmit = true; + }); + + // when a submitHandler is used, capture the submitting button + if (validator.settings.submitHandler) { + this.find("input, button").filter(":submit").click(function() { + validator.submitButton = this; + }); + } + + // validate the form on submit + this.submit( function( event ) { + if ( validator.settings.debug ) + // prevent form submit to be able to see console output + event.preventDefault(); + + function handle() { + if ( validator.settings.submitHandler ) { + if (validator.submitButton) { + // insert a hidden input as a replacement for the missing submit button + var hidden = $("").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); + } + validator.settings.submitHandler.call( validator, validator.currentForm ); + if (validator.submitButton) { + // and clean up afterwards; thanks to no-block-scope, hidden can be referenced + hidden.remove(); + } + return false; + } + return true; + } + + // prevent submit for invalid forms or custom submit handlers + if ( validator.cancelSubmit ) { + validator.cancelSubmit = false; + return handle(); + } + if ( validator.form() ) { + if ( validator.pendingRequest ) { + validator.formSubmitted = true; + return false; + } + return handle(); + } else { + validator.focusInvalid(); + return false; + } + }); + } + + return validator; + }, + // http://docs.jquery.com/Plugins/Validation/valid + valid: function() { + if ( $(this[0]).is('form')) { + return this.validate().form(); + } else { + var valid = true; + var validator = $(this[0].form).validate(); + this.each(function() { + valid &= validator.element(this); + }); + return valid; + } + }, + // attributes: space seperated list of attributes to retrieve and remove + removeAttrs: function(attributes) { + var result = {}, + $element = this; + $.each(attributes.split(/\s/), function(index, value) { + result[value] = $element.attr(value); + $element.removeAttr(value); + }); + return result; + }, + // http://docs.jquery.com/Plugins/Validation/rules + rules: function(command, argument) { + var element = this[0]; + + if (command) { + var settings = $.data(element.form, 'validator').settings; + var staticRules = settings.rules; + var existingRules = $.validator.staticRules(element); + switch(command) { + case "add": + $.extend(existingRules, $.validator.normalizeRule(argument)); + staticRules[element.name] = existingRules; + if (argument.messages) + settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); + break; + case "remove": + if (!argument) { + delete staticRules[element.name]; + return existingRules; + } + var filtered = {}; + $.each(argument.split(/\s/), function(index, method) { + filtered[method] = existingRules[method]; + delete existingRules[method]; + }); + return filtered; + } + } + + var data = $.validator.normalizeRules( + $.extend( + {}, + $.validator.metadataRules(element), + $.validator.classRules(element), + $.validator.attributeRules(element), + $.validator.staticRules(element) + ), element); + + // make sure required is at front + if (data.required) { + var param = data.required; + delete data.required; + data = $.extend({required: param}, data); + } + + return data; + } +}); + +// Custom selectors +$.extend($.expr[":"], { + // http://docs.jquery.com/Plugins/Validation/blank + blank: function(a) {return !$.trim(a.value);}, + // http://docs.jquery.com/Plugins/Validation/filled + filled: function(a) {return !!$.trim(a.value);}, + // http://docs.jquery.com/Plugins/Validation/unchecked + unchecked: function(a) {return !a.checked;} +}); + +// constructor for validator +$.validator = function( options, form ) { + this.settings = $.extend( {}, $.validator.defaults, options ); + this.currentForm = form; + this.init(); +}; + +$.validator.format = function(source, params) { + if ( arguments.length == 1 ) + return function() { + var args = $.makeArray(arguments); + args.unshift(source); + return $.validator.format.apply( this, args ); + }; + if ( arguments.length > 2 && params.constructor != Array ) { + params = $.makeArray(arguments).slice(1); + } + if ( params.constructor != Array ) { + params = [ params ]; + } + $.each(params, function(i, n) { + source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); + }); + return source; +}; + +$.extend($.validator, { + + defaults: { + messages: {}, + groups: {}, + rules: {}, + errorClass: "error", + validClass: "valid", + errorElement: "label", + focusInvalid: true, + errorContainer: $( [] ), + errorLabelContainer: $( [] ), + onsubmit: true, + ignore: [], + ignoreTitle: false, + onfocusin: function(element) { + this.lastActive = element; + + // hide error label and remove error class on focus if enabled + if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { + this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); + this.errorsFor(element).hide(); + } + }, + onfocusout: function(element) { + if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { + this.element(element); + } + }, + onkeyup: function(element) { + if ( element.name in this.submitted || element == this.lastElement ) { + this.element(element); + } + }, + onclick: function(element) { + if ( element.name in this.submitted ) + this.element(element); + }, + highlight: function( element, errorClass, validClass ) { + $(element).addClass(errorClass).removeClass(validClass); + }, + unhighlight: function( element, errorClass, validClass ) { + $(element).removeClass(errorClass).addClass(validClass); + } + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults + setDefaults: function(settings) { + $.extend( $.validator.defaults, settings ); + }, + + messages: { + required: "This field is required.", + remote: "Please fix this field.", + email: "Please enter a valid email address.", + url: "Please enter a valid URL.", + date: "Please enter a valid date.", + dateISO: "Please enter a valid date (ISO).", + dateDE: "Bitte geben Sie ein gültiges Datum ein.", + number: "Please enter a valid number.", + numberDE: "Bitte geben Sie eine Nummer ein.", + digits: "Please enter only digits", + creditcard: "Please enter a valid credit card number.", + equalTo: "Please enter the same value again.", + accept: "Please enter a value with a valid extension.", + maxlength: $.validator.format("Please enter no more than {0} characters."), + minlength: $.validator.format("Please enter at least {0} characters."), + rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), + range: $.validator.format("Please enter a value between {0} and {1}."), + max: $.validator.format("Please enter a value less than or equal to {0}."), + min: $.validator.format("Please enter a value greater than or equal to {0}.") + }, + + autoCreateRanges: false, + + prototype: { + + init: function() { + this.labelContainer = $(this.settings.errorLabelContainer); + this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); + this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); + this.submitted = {}; + this.valueCache = {}; + this.pendingRequest = 0; + this.pending = {}; + this.invalid = {}; + this.reset(); + + var groups = (this.groups = {}); + $.each(this.settings.groups, function(key, value) { + $.each(value.split(/\s/), function(index, name) { + groups[name] = key; + }); + }); + var rules = this.settings.rules; + $.each(rules, function(key, value) { + rules[key] = $.validator.normalizeRule(value); + }); + + function delegate(event) { + var validator = $.data(this[0].form, "validator"); + validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] ); + } + $(this.currentForm) + .delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate) + .delegate("click", ":radio, :checkbox", delegate); + + if (this.settings.invalidHandler) + $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/form + form: function() { + this.checkForm(); + $.extend(this.submitted, this.errorMap); + this.invalid = $.extend({}, this.errorMap); + if (!this.valid()) + $(this.currentForm).triggerHandler("invalid-form", [this]); + this.showErrors(); + return this.valid(); + }, + + checkForm: function() { + this.prepareForm(); + for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { + this.check( elements[i] ); + } + return this.valid(); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/element + element: function( element ) { + element = this.clean( element ); + this.lastElement = element; + this.prepareElement( element ); + this.currentElements = $(element); + var result = this.check( element ); + if ( result ) { + delete this.invalid[element.name]; + } else { + this.invalid[element.name] = true; + } + if ( !this.numberOfInvalids() ) { + // Hide error containers on last error + this.toHide = this.toHide.add( this.containers ); + } + this.showErrors(); + return result; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/showErrors + showErrors: function(errors) { + if(errors) { + // add items to error list and map + $.extend( this.errorMap, errors ); + this.errorList = []; + for ( var name in errors ) { + this.errorList.push({ + message: errors[name], + element: this.findByName(name)[0] + }); + } + // remove items from success list + this.successList = $.grep( this.successList, function(element) { + return !(element.name in errors); + }); + } + this.settings.showErrors + ? this.settings.showErrors.call( this, this.errorMap, this.errorList ) + : this.defaultShowErrors(); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/resetForm + resetForm: function() { + if ( $.fn.resetForm ) + $( this.currentForm ).resetForm(); + this.submitted = {}; + this.prepareForm(); + this.hideErrors(); + this.elements().removeClass( this.settings.errorClass ); + }, + + numberOfInvalids: function() { + return this.objectLength(this.invalid); + }, + + objectLength: function( obj ) { + var count = 0; + for ( var i in obj ) + count++; + return count; + }, + + hideErrors: function() { + this.addWrapper( this.toHide ).hide(); + }, + + valid: function() { + return this.size() == 0; + }, + + size: function() { + return this.errorList.length; + }, + + focusInvalid: function() { + if( this.settings.focusInvalid ) { + try { + $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus(); + } catch(e) { + // ignore IE throwing errors when focusing hidden elements + } + } + }, + + findLastActive: function() { + var lastActive = this.lastActive; + return lastActive && $.grep(this.errorList, function(n) { + return n.element.name == lastActive.name; + }).length == 1 && lastActive; + }, + + elements: function() { + var validator = this, + rulesCache = {}; + + // select all valid inputs inside the form (no submit or reset buttons) + // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved + return $([]).add(this.currentForm.elements) + .filter(":input") + .not(":submit, :reset, :image, [disabled]") + .not( this.settings.ignore ) + .filter(function() { + !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); + + // select only the first element for each name, and only those with rules specified + if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) + return false; + + rulesCache[this.name] = true; + return true; + }); + }, + + clean: function( selector ) { + return $( selector )[0]; + }, + + errors: function() { + return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext ); + }, + + reset: function() { + this.successList = []; + this.errorList = []; + this.errorMap = {}; + this.toShow = $([]); + this.toHide = $([]); + this.formSubmitted = false; + this.currentElements = $([]); + }, + + prepareForm: function() { + this.reset(); + this.toHide = this.errors().add( this.containers ); + }, + + prepareElement: function( element ) { + this.reset(); + this.toHide = this.errorsFor(element); + }, + + check: function( element ) { + element = this.clean( element ); + + // if radio/checkbox, validate first element in group instead + if (this.checkable(element)) { + element = this.findByName( element.name )[0]; + } + + var rules = $(element).rules(); + var dependencyMismatch = false; + for( method in rules ) { + var rule = { method: method, parameters: rules[method] }; + try { + var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters ); + + // if a method indicates that the field is optional and therefore valid, + // don't mark it as valid when there are no other rules + if ( result == "dependency-mismatch" ) { + dependencyMismatch = true; + continue; + } + dependencyMismatch = false; + + if ( result == "pending" ) { + this.toHide = this.toHide.not( this.errorsFor(element) ); + return; + } + + if( !result ) { + this.formatAndAdd( element, rule ); + return false; + } + } catch(e) { + this.settings.debug && window.console && console.log("exception occured when checking element " + element.id + + ", check the '" + rule.method + "' method"); + throw e; + } + } + if (dependencyMismatch) + return; + if ( this.objectLength(rules) ) + this.successList.push(element); + return true; + }, + + // return the custom message for the given element and validation method + // specified in the element's "messages" metadata + customMetaMessage: function(element, method) { + if (!$.metadata) + return; + + var meta = this.settings.meta + ? $(element).metadata()[this.settings.meta] + : $(element).metadata(); + + return meta && meta.messages && meta.messages[method]; + }, + + // return the custom message for the given element name and validation method + customMessage: function( name, method ) { + var m = this.settings.messages[name]; + return m && (m.constructor == String + ? m + : m[method]); + }, + + // return the first defined argument, allowing empty strings + findDefined: function() { + for(var i = 0; i < arguments.length; i++) { + if (arguments[i] !== undefined) + return arguments[i]; + } + return undefined; + }, + + defaultMessage: function( element, method) { + return this.findDefined( + this.customMessage( element.name, method ), + this.customMetaMessage( element, method ), + // title is never undefined, so handle empty string as undefined + !this.settings.ignoreTitle && element.title || undefined, + $.validator.messages[method], + "Warning: No message defined for " + element.name + "" + ); + }, + + formatAndAdd: function( element, rule ) { + var message = this.defaultMessage( element, rule.method ); + if ( typeof message == "function" ) + message = message.call(this, rule.parameters, element); + this.errorList.push({ + message: message, + element: element + }); + this.errorMap[element.name] = message; + this.submitted[element.name] = message; + }, + + addWrapper: function(toToggle) { + if ( this.settings.wrapper ) + toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); + return toToggle; + }, + + defaultShowErrors: function() { + for ( var i = 0; this.errorList[i]; i++ ) { + var error = this.errorList[i]; + this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); + this.showLabel( error.element, error.message ); + } + if( this.errorList.length ) { + this.toShow = this.toShow.add( this.containers ); + } + if (this.settings.success) { + for ( var i = 0; this.successList[i]; i++ ) { + this.showLabel( this.successList[i] ); + } + } + if (this.settings.unhighlight) { + for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) { + this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); + } + } + this.toHide = this.toHide.not( this.toShow ); + this.hideErrors(); + this.addWrapper( this.toShow ).show(); + }, + + validElements: function() { + return this.currentElements.not(this.invalidElements()); + }, + + invalidElements: function() { + return $(this.errorList).map(function() { + return this.element; + }); + }, + + showLabel: function(element, message) { + var label = this.errorsFor( element ); + if ( label.length ) { + // refresh error/success class + label.removeClass().addClass( this.settings.errorClass ); + + // check if we have a generated label, replace the message then + label.attr("generated") && label.html(message); + } else { + // create label + label = $("<" + this.settings.errorElement + "/>") + .attr({"for": this.idOrName(element), generated: true}) + .addClass(this.settings.errorClass) + .html(message || ""); + if ( this.settings.wrapper ) { + // make sure the element is visible, even in IE + // actually showing the wrapped element is handled elsewhere + label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); + } + if ( !this.labelContainer.append(label).length ) + this.settings.errorPlacement + ? this.settings.errorPlacement(label, $(element) ) + : label.insertAfter(element); + } + if ( !message && this.settings.success ) { + label.text(""); + typeof this.settings.success == "string" + ? label.addClass( this.settings.success ) + : this.settings.success( label ); + } + this.toShow = this.toShow.add(label); + }, + + errorsFor: function(element) { + return this.errors().filter("[for='" + this.idOrName(element) + "']"); + }, + + idOrName: function(element) { + return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); + }, + + checkable: function( element ) { + return /radio|checkbox/i.test(element.type); + }, + + findByName: function( name ) { + // select by name and filter by form for performance over form.find("[name=...]") + var form = this.currentForm; + return $(document.getElementsByName(name)).map(function(index, element) { + return element.form == form && element.name == name && element || null; + }); + }, + + getLength: function(value, element) { + switch( element.nodeName.toLowerCase() ) { + case 'select': + return $("option:selected", element).length; + case 'input': + if( this.checkable( element) ) + return this.findByName(element.name).filter(':checked').length; + } + return value.length; + }, + + depend: function(param, element) { + return this.dependTypes[typeof param] + ? this.dependTypes[typeof param](param, element) + : true; + }, + + dependTypes: { + "boolean": function(param, element) { + return param; + }, + "string": function(param, element) { + return !!$(param, element.form).length; + }, + "function": function(param, element) { + return param(element); + } + }, + + optional: function(element) { + return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; + }, + + startRequest: function(element) { + if (!this.pending[element.name]) { + this.pendingRequest++; + this.pending[element.name] = true; + } + }, + + stopRequest: function(element, valid) { + this.pendingRequest--; + // sometimes synchronization fails, make sure pendingRequest is never < 0 + if (this.pendingRequest < 0) + this.pendingRequest = 0; + delete this.pending[element.name]; + if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) { + $(this.currentForm).submit(); + } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { + $(this.currentForm).triggerHandler("invalid-form", [this]); + } + }, + + previousValue: function(element) { + return $.data(element, "previousValue") || $.data(element, "previousValue", previous = { + old: null, + valid: true, + message: this.defaultMessage( element, "remote" ) + }); + } + + }, + + classRuleSettings: { + required: {required: true}, + email: {email: true}, + url: {url: true}, + date: {date: true}, + dateISO: {dateISO: true}, + dateDE: {dateDE: true}, + number: {number: true}, + numberDE: {numberDE: true}, + digits: {digits: true}, + creditcard: {creditcard: true} + }, + + addClassRules: function(className, rules) { + className.constructor == String ? + this.classRuleSettings[className] = rules : + $.extend(this.classRuleSettings, className); + }, + + classRules: function(element) { + var rules = {}; + var classes = $(element).attr('class'); + classes && $.each(classes.split(' '), function() { + if (this in $.validator.classRuleSettings) { + $.extend(rules, $.validator.classRuleSettings[this]); + } + }); + return rules; + }, + + attributeRules: function(element) { + var rules = {}; + var $element = $(element); + + for (method in $.validator.methods) { + var value = $element.attr(method); + if (value) { + rules[method] = value; + } + } + + // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs + if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { + delete rules.maxlength; + } + + return rules; + }, + + metadataRules: function(element) { + if (!$.metadata) return {}; + + var meta = $.data(element.form, 'validator').settings.meta; + return meta ? + $(element).metadata()[meta] : + $(element).metadata(); + }, + + staticRules: function(element) { + var rules = {}; + var validator = $.data(element.form, 'validator'); + if (validator.settings.rules) { + rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; + } + return rules; + }, + + normalizeRules: function(rules, element) { + // handle dependency check + $.each(rules, function(prop, val) { + // ignore rule when param is explicitly false, eg. required:false + if (val === false) { + delete rules[prop]; + return; + } + if (val.param || val.depends) { + var keepRule = true; + switch (typeof val.depends) { + case "string": + keepRule = !!$(val.depends, element.form).length; + break; + case "function": + keepRule = val.depends.call(element, element); + break; + } + if (keepRule) { + rules[prop] = val.param !== undefined ? val.param : true; + } else { + delete rules[prop]; + } + } + }); + + // evaluate parameters + $.each(rules, function(rule, parameter) { + rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; + }); + + // clean number parameters + $.each(['minlength', 'maxlength', 'min', 'max'], function() { + if (rules[this]) { + rules[this] = Number(rules[this]); + } + }); + $.each(['rangelength', 'range'], function() { + if (rules[this]) { + rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; + } + }); + + if ($.validator.autoCreateRanges) { + // auto-create ranges + if (rules.min && rules.max) { + rules.range = [rules.min, rules.max]; + delete rules.min; + delete rules.max; + } + if (rules.minlength && rules.maxlength) { + rules.rangelength = [rules.minlength, rules.maxlength]; + delete rules.minlength; + delete rules.maxlength; + } + } + + // To support custom messages in metadata ignore rule methods titled "messages" + if (rules.messages) { + delete rules.messages + } + + return rules; + }, + + // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} + normalizeRule: function(data) { + if( typeof data == "string" ) { + var transformed = {}; + $.each(data.split(/\s/), function() { + transformed[this] = true; + }); + data = transformed; + } + return data; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/addMethod + addMethod: function(name, method, message) { + $.validator.methods[name] = method; + $.validator.messages[name] = message || $.validator.messages[name]; + if (method.length < 3) { + $.validator.addClassRules(name, $.validator.normalizeRule(name)); + } + }, + + methods: { + + // http://docs.jquery.com/Plugins/Validation/Methods/required + required: function(value, element, param) { + // check if dependency is met + if ( !this.depend(param, element) ) + return "dependency-mismatch"; + switch( element.nodeName.toLowerCase() ) { + case 'select': + var options = $("option:selected", element); + return options.length > 0 && ( element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0); + case 'input': + if ( this.checkable(element) ) + return this.getLength(value, element) > 0; + default: + return $.trim(value).length > 0; + } + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/remote + remote: function(value, element, param) { + if ( this.optional(element) ) + return "dependency-mismatch"; + + var previous = this.previousValue(element); + + if (!this.settings.messages[element.name] ) + this.settings.messages[element.name] = {}; + this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message; + + param = typeof param == "string" && {url:param} || param; + + if ( previous.old !== value ) { + previous.old = value; + var validator = this; + this.startRequest(element); + var data = {}; + data[element.name] = value; + $.ajax($.extend(true, { + url: param, + mode: "abort", + port: "validate" + element.name, + dataType: "json", + data: data, + success: function(response) { + var valid = response === true; + if ( valid ) { + var submitted = validator.formSubmitted; + validator.prepareElement(element); + validator.formSubmitted = submitted; + validator.successList.push(element); + validator.showErrors(); + } else { + var errors = {}; + errors[element.name] = previous.message = response || validator.defaultMessage( element, "remote" ); + validator.showErrors(errors); + } + previous.valid = valid; + validator.stopRequest(element, valid); + } + }, param)); + return "pending"; + } else if( this.pending[element.name] ) { + return "pending"; + } + return previous.valid; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/minlength + minlength: function(value, element, param) { + return this.optional(element) || this.getLength($.trim(value), element) >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/maxlength + maxlength: function(value, element, param) { + return this.optional(element) || this.getLength($.trim(value), element) <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/rangelength + rangelength: function(value, element, param) { + var length = this.getLength($.trim(value), element); + return this.optional(element) || ( length >= param[0] && length <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/min + min: function( value, element, param ) { + return this.optional(element) || value >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/max + max: function( value, element, param ) { + return this.optional(element) || value <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/range + range: function( value, element, param ) { + return this.optional(element) || ( value >= param[0] && value <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/email + email: function(value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ + return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/url + url: function(value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ + return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/date + date: function(value, element) { + return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/dateISO + dateISO: function(value, element) { + return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/dateDE + dateDE: function(value, element) { + return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/number + number: function(value, element) { + return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/numberDE + numberDE: function(value, element) { + return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/digits + digits: function(value, element) { + return this.optional(element) || /^\d+$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/creditcard + // based on http://en.wikipedia.org/wiki/Luhn + creditcard: function(value, element) { + if ( this.optional(element) ) + return "dependency-mismatch"; + // accept only digits and dashes + if (/[^0-9-]+/.test(value)) + return false; + var nCheck = 0, + nDigit = 0, + bEven = false; + + value = value.replace(/\D/g, ""); + + for (n = value.length - 1; n >= 0; n--) { + var cDigit = value.charAt(n); + var nDigit = parseInt(cDigit, 10); + if (bEven) { + if ((nDigit *= 2) > 9) + nDigit -= 9; + } + nCheck += nDigit; + bEven = !bEven; + } + + return (nCheck % 10) == 0; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/accept + accept: function(value, element, param) { + param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; + return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/equalTo + equalTo: function(value, element, param) { + return value == $(param).val(); + } + + } + +}); + +// deprecated, use $.validator.format instead +$.format = $.validator.format; + +})(jQuery); + +// ajax mode: abort +// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); +// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() +;(function($) { + var ajax = $.ajax; + var pendingRequests = {}; + $.ajax = function(settings) { + // create settings for compatibility with ajaxSetup + settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings)); + var port = settings.port; + if (settings.mode == "abort") { + if ( pendingRequests[port] ) { + pendingRequests[port].abort(); + } + return (pendingRequests[port] = ajax.apply(this, arguments)); + } + return ajax.apply(this, arguments); + }; +})(jQuery); + +// provides cross-browser focusin and focusout events +// IE has native support, in other browsers, use event caputuring (neither bubbles) + +// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation +// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target + +// provides triggerEvent(type: String, target: Element) to trigger delegated events +;(function($) { + $.each({ + focus: 'focusin', + blur: 'focusout' + }, function( original, fix ){ + $.event.special[fix] = { + setup:function() { + if ( $.browser.msie ) return false; + this.addEventListener( original, $.event.special[fix].handler, true ); + }, + teardown:function() { + if ( $.browser.msie ) return false; + this.removeEventListener( original, + $.event.special[fix].handler, true ); + }, + handler: function(e) { + arguments[0] = $.event.fix(e); + arguments[0].type = fix; + return $.event.handle.apply(this, arguments); + } + }; + }); + $.extend($.fn, { + delegate: function(type, delegate, handler) { + return this.bind(type, function(event) { + var target = $(event.target); + if (target.is(delegate)) { + return handler.apply(target, arguments); + } + }); + }, + triggerEvent: function(type, target) { + return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]); + } + }) +})(jQuery); diff -r 000000000000 -r ecdfc63274bf web/ldt/media/js/login_ajax/jquery.login.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/js/login_ajax/jquery.login.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,77 @@ +$(document).ready(function() { + $('#password').keypress(function(e) { + if(e.which == 13) { + jQuery('#submit').focus().click(); + } + }); + + + $("#submit").click(function() { + var username=$("#username").val(); + var password=$("#password").val(); + var data = {'username': username, 'password': password, 'reload': reload}; + if(username=="" && password=="") + { + $("#login_form_username_error").show(); + $("#login_form_password_error").show(); + $("#username").addClass("ajaxform_invalid"); + $("#password").addClass("ajaxform_invalid"); + } + else if(username=="" && password!="") + { + $("#login_form_username_error").show(); + $("#username").addClass("ajaxform_invalid"); + } + else if(password=="" && username!="") + { + $("#login_form_password_error").show(); + $("#password").addClass("ajaxform_invalid"); + } + else{ + + $.ajax({ + type: "POST", + url : url_login_ajax, + dataType:'json', + data: data, + error: function (){ + $("#msg").html("fail to connect"); + }, + success: function(data, reload){ //if success, refrash un bout de page pour afficher le nom de utilisateur et déconnecter. + if (data.message!="successful") + { + $("#msg").html(data.message).show(); + } + else{ + // $("#floatdialog_mask_loginform").hide(); + //window.location.reload(); + if (data.reload=='true'){ + window.location.reload(); + } + else{ + //$("#loginstate").html(''+data.username+' | déconnection'); + //$("#loginstate").html(''); + var $DOMWindowOverlay = $('#DOMWindowOverlay'); + var $DOMWindow = $('#DOMWindow'); + $DOMWindowOverlay.fadeOut('fast',function(){ + $DOMWindowOverlay.trigger('unload').unbind().remove(); + }); + $DOMWindow.fadeOut('fast',function(){ + if($.fn.draggable){ + $DOMWindow.draggable("destroy").trigger("unload").remove(); + }else{ + $DOMWindow.trigger("unload").remove(); + } + }); + $("#loginstate").html(data.html); + } + } + + + } + }); + } + }); +}) + + diff -r 000000000000 -r ecdfc63274bf web/ldt/media/js/login_ajax/login_ajax.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/js/login_ajax/login_ajax.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,75 @@ +#loginform +{ + font-size: 16px; + background: #ffffff scroll repeat 0 0; + /*border: 2px solid #666666;*/ + text-align: left; + /*width: 400px;*/ +} + +#loginform .title +{ + color: #FFFFFF; + background: #990000 scroll repeat left top; + font-weight:bold; + height:34px; + position: relative; + line-height: 34px; + overflow: hidden; + text-transform: uppercase; +} + +#loginform .title div +{ + font-size: 16px; + margin-left:12px; +} + +#loginform .title .closeDOMWindow +{ + float: right; + text-decoration: none; + color:#ffffff; + padding-right:2px; +} + +#loginform .ajaxform_invalid{ + background: #ffdddd none repeat scroll 0 0; +} + +#loginform .ajaxform_error{ + display: none; + color:red; + font-size: 11px; + line-height: 13px; +} + +#loginform #msg{ + display:none; + background:#FBE3E4 none repeat scroll 0 0; + color: red; + padding:0.5em; + border-color:#FBC2C4; + font-size: 13px; + font-weight:bold; +} + +#loginform dl { + font-size:13px; + line-height:22px; +} + +#loginform dl dt{ + clear:left; + color:#666666; + float:left; + font-weight:bold; + width:100px +} + +#loginform dl dd { + margin-left: 110px; + padding-bottom: 8px; +} + + diff -r 000000000000 -r ecdfc63274bf web/ldt/media/js/swfobject.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/media/js/swfobject.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,5 @@ +/* SWFObject v2.1 + Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis + This software is released under the MIT License +*/ +var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write(" +{% endif %} + + +{% if add %} + +{% endif %} + + +{% endblock %} + +{% block content_title %} + {% if moderation_delete_request %} +

    {% trans "Approve page deletion" %}

    + + {% else %} + +

    {{ title }} + {% if CMS_MODERATOR %} + {% if moderation_required %}{% blocktrans %}(requires approvement at {{ moderation_level }} level){% endblocktrans %} + {% else %}{% trans '(you can perform actions on this page directly)' %} + {% endif %} + {% endif %} +

    + {% endif %} + +{% endblock %} + +{% block content %}
    + +{% block object-tools %} +{% if change %}{% if not is_popup %} + +{% endif %}{% endif %} +{% endblock %} + + +
    {% block form_top %}{% endblock %} +{{ adminForm.fields.parent }} + + + +{% if show_language_tabs %} +
    + {% for lang_code, lang_name in traduction_language %} + + {% endfor %} +
    +{% endif %} + + +
    +{% if show_language_tabs %} +

    +{% endif %} +{% if is_popup %}{% endif %} +{% if save_on_top %}{% submit_row %}{% endif %} +{% if errors %} +

    + {% blocktrans count errors|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} +

    +
      {% for error in adminform.form.non_field_errors %}
    • {{ error }}
    • {% endfor %}
    +{% endif %} + +{% for fieldset in adminform %} + {% include "admin/cms/page/includes/fieldset.html" %} +{% endfor %} + + +{% for inline_admin_formset in inline_admin_formsets %} + {% include inline_admin_formset.opts.template %} +{% endfor %} + + +{% if not add %} + {% if CMS_PERMISSION and has_change_permissions_permission %} +
    + +
    + {% endif %} + + {% if CMS_MODERATOR and has_moderate_permission %} +
    + +
    + {% endif %} + + {% if moderation_delete_request %}{% endif %} + + {% if CMS_MODERATOR and moderation_required %} +
    +

    {% blocktrans %}This page must be moderated at level {{ moderation_level }}, post a message for moderator.{% endblocktrans %}

    +
    +
    +
    + + + {% endif %} + +{% endif %} + +{% block after_related_objects %}{% endblock %} + +{% if add %} +
    + + +
    +{% else %} + {% if not moderation_delete_request %}{% submit_row %}{% endif %} +{% endif %} + +{% if add %} + +{% endif %} + +{# JavaScript for prepopulated fields #} +{% prepopulated_fields_js %} + +
    +
    +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/cms_change_list.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/cms_change_list.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,125 @@ +{% extends "admin/page_change_list.html" %} +{% load adminmedia admin_list i18n cms_admin js %} +{% block bodyclass %}change-list{% endblock %} + +{% if not is_popup %}{% block breadcrumbs %} + +{% endblock %}{% endif %} + +{% block coltype %}flex{% endblock %} +{% block extrahead %}{{ block.super }} + + + + + + + + + + + + + + + + + + +{% if cl.is_filtered %} + +{% endif %} +{% endblock %} + +{% block content %} + + + +
    + +{% block object-tools %} + + + + {% include "admin/cms/page/loading.html" %} + +{% endblock %} +
    +{% block search %} + + +{% if cl.has_access_to_multiple_sites %} +
    {% trans "Pages on:" %} + +
    +{% else %} + +{% endif %} + +{% search_form cl %} +{% endblock %} +{% block date_hierarchy %}{% date_hierarchy cl %}{% endblock %} + +{% block filters %} +{% if cl.has_filters %} + + +Filter: {% if cl.is_filtered %}{% trans "on" %}{% else %}{% trans "off" %}{% endif %} + +{% endif %} +{% endblock %} + +{% include "admin/cms/page/change_list_tree.html" %} + +
    +
    + +
    + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/index.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,99 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block extrastyle %}{{ block.super }}{% endblock %} + +{% block coltype %}colMS{% endblock %} + +{% block bodyclass %}dashboard{% endblock %} + +{% block breadcrumbs %}{% endblock %} + +{% block content %} +
    + +{% if app_list %} + {% for app in app_list %} +
    + + + {% for model in app.models %} + + {% if model.perms.change %} + + {% else %} + + {% endif %} + + {% if model.perms.add %} + + {% else %} + + {% endif %} + + {% if model.perms.change %} + + {% else %} + + {% endif %} + + {% endfor %} +
    {% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}
    {{ model.name }}{{ model.name }}{% trans 'Add' %} {% trans 'Change' %} 
    +
    + {% endfor %} +
    + + + + + + + + + + +
    Import
    + Import an ldt +   +
    + Reindex +   +
    +
    +{% else %} +

    {% trans "You don't have permission to edit anything." %}

    +{% endif %} +
    +{% endblock %} + +{% block sidebar %} + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/page_app_index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/page_app_index.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,15 @@ +{% extends "admin/page_index.html" %} +{% load i18n %} + +{% if not is_popup %} + +{% block breadcrumbs %} +{% endblock %} + +{% endif %} + +{% block sidebar %}{% endblock %} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/page_base.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/page_base.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,45 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block css_import %} +{{ block.super }} + + {% if LANGUAGE_BIDI %}{% endif %} +{% endblock %} + + + + + {% block header %}{{block.super}} + {% block nav-global %}{% endblock %} + {% endblock %} + + {% block breadcrumb %} +
  • +
  • {% trans "Space" %}
  • +
  • {% trans "Pages" %}
  • + {% endblock %} + + + {% if messages %} +
      {% for message in messages %}
    • {{ message }}
    • {% endfor %}
    + {% endif %} + + {% block content_title %}{% if title %}{{ title }}{% endif %}{% endblock %} + + + {% block content_admin %} +
    + {% block pretitle %}{% endblock %} + {% block content %} + {% block object-tools %}{% endblock %} + {{ content }} + {% endblock %} + {% block sidebar %}{% endblock %} +
    +
    + {% endblock %} + + + + diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/page_base_site.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/page_base_site.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,10 @@ +{% extends "admin/page_base.html" %} +{% load i18n %} + +{% block title %}Django Administration{% endblock %} + +{% block branding %} +

    {% trans 'Django administration' %}

    +{% endblock %} + +{% block nav-global %}{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/page_change_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/page_change_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,66 @@ +{% extends "admin/page_base_site.html" %} +{% load i18n admin_modify adminmedia %} + +{% block extrahead %}{{ block.super }} + +{{ media }} +{% endblock %} + +{% block extrastyle %}{{ block.super }}{% endblock %} + +{% block coltype %}{% if ordered_objects %}colMS{% else %}colM{% endif %}{% endblock %} + +{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %} + +{% block breadcrumbs %}{% if not is_popup %} + +{% endif %}{% endblock %} + +{% block content %}
    +{% block object-tools %} +{% if change %}{% if not is_popup %} + +{% endif %}{% endif %} +{% endblock %} +
    {% block form_top %}{% endblock %} +
    +{% if is_popup %}{% endif %} +{% if save_on_top %}{% submit_row %}{% endif %} +{% if errors %} +

    + {% blocktrans count errors|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} +

    +
      {% for error in adminform.form.non_field_errors %}
    • {{ error }}
    • {% endfor %}
    +{% endif %} + +{% for fieldset in adminform %} + {% include "admin/includes/fieldset.html" %} +{% endfor %} + +{% block after_field_sets %}{% endblock %} + +{% for inline_admin_formset in inline_admin_formsets %} + {% include inline_admin_formset.opts.template %} +{% endfor %} + +{% block after_related_objects %}{% endblock %} + +{% submit_row %} + +{% if adminform and add %} + +{% endif %} + +{# JavaScript for prepopulated fields #} +{% prepopulated_fields_js %} + +
    +
    +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/page_change_list.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/page_change_list.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,85 @@ +{% extends "admin/page_base_site.html" %} +{% load adminmedia admin_list i18n %} + +{% block extrastyle %} + {{ block.super }} + + {% if cl.formset %} + + + {% endif %} + {{ media }} + {% if not actions_on_top and not actions_on_bottom %} + + {% endif %} +{% endblock %} + +{% block bodyclass %}change-list{% endblock %} + +{% if not is_popup %} + {% block breadcrumbs %} + + {% endblock %} +{% endif %} + +{% block coltype %}flex{% endblock %} + +{% block content %} +
    + {% block object-tools %} + {% if has_add_permission %} + + {% endif %} + {% endblock %} + {% if cl.formset.errors %} +

    + {% blocktrans count cl.formset.errors|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} +

    +
      {% for error in cl.formset.non_field_errors %}
    • {{ error }}
    • {% endfor %}
    + {% endif %} +
    + {% block search %}{% search_form cl %}{% endblock %} + {% block date_hierarchy %}{% date_hierarchy cl %}{% endblock %} + + {% block filters %} + {% if cl.has_filters %} +
    +

    {% trans 'Filter' %}

    + {% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %} +
    + {% endif %} + {% endblock %} + +
    + {% if cl.formset %} + {{ cl.formset.management_form }} + {% endif %} + + {% block result_list %} + {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %} + {% result_list cl %} + {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %} + {% endblock %} + {% block pagination %}{% pagination cl %}{% endblock %} +
    +
    +
    +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/page_index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/page_index.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,80 @@ +{% extends "admin/page_base_site.html" %} +{% load i18n %} + +{% block extrastyle %}{{ block.super }}{% endblock %} + +{% block coltype %}colMS{% endblock %} + +{% block bodyclass %}dashboard{% endblock %} + +{% block breadcrumbs %}{% endblock %} +{% block content_title %}{% trans "Pages" %}{% endblock %} +{% block content %} +
    + +{% if app_list %} + {% for app in app_list %} +
    + + + {% for model in app.models %} + + {% if model.perms.change %} + + {% else %} + + {% endif %} + + {% if model.perms.add %} + + {% else %} + + {% endif %} + + {% if model.perms.change %} + + {% else %} + + {% endif %} + + {% endfor %} +
    {% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}
    {{ model.name }}{{ model.name }}{% trans 'Add' %} {% trans 'Change' %} 
    +
    + {% endfor %} +{% else %} +

    {% trans "You don't have permission to edit anything." %}

    +{% endif %} +
    +{% endblock %} + +{% block sidebar %} + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/page_login.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/page_login.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,41 @@ +{% extends "admin/page_base_site.html" %} +{% load i18n %} + +{% block extrastyle %}{% load adminmedia %}{{ block.super }}{% endblock %} + +{% block bodyclass %}{% endblock %} + +{% block content_title %}{% trans "Connexion" %}{% endblock %} + +{% block breadcrumbs %}{% endblock %} + +{% block content %} +{% if error_message %} +

    {{ error_message }}

    +{% endif %} +
    +
    + + + + + + + + + + + + + + +
    {% trans "Create an account" %} + {% trans "Forget password?" %} +
    +
    + + +
    +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/admin/show_menu.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/admin/show_menu.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,4 @@ +{% load cms_tags %} +{% load i18n %} + +{% show_menu 0 100 100 100 %} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/templates/cms/admin/cms/page/change_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templates/cms/admin/cms/page/change_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,62 @@ +{% extends "admin/base_site.html" %} +{% load i18n admin_modify adminmedia cms_admin %} +{% block extrahead %}{{ block.super }} + +{% for js in javascript_imports %}{% include_admin_script js %}{% endfor %} +{% endblock %} +{% block stylesheet %}{% admin_media_prefix %}css/forms.css" /> +{% trans 'Documentation' %} / {% trans 'Change password' %} / {% trans 'Log out' %}{% endblock %} +{% block breadcrumbs %}{% endblock %} +{% block content %}
    +{% block object-tools %} +{% if change %}{% endif %} +{% endblock %} +
    {% block form_top %}{% endblock %} +
    +{% if is_popup %}{% endif %} + +{% if opts.admin.save_on_top %}{% submit_row %}{% endif %} +{% if form.error_dict %} +

    + {% blocktrans count form.error_dict.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} +

    +{% endif %} +{% for bound_field_set in bound_field_sets %} +
    + {% if bound_field_set.name %}

    {{ bound_field_set.name }}

    {% endif %} + {% if bound_field_set.description %}
    {{ bound_field_set.description }}
    {% endif %} + {% for bound_field_line in bound_field_set %} + {% admin_field_line bound_field_line %} + {% for bound_field in bound_field_line %} + {% filter_interface_script_maybe bound_field %} + {% endfor %} + {% endfor %} +
    +{% endfor %} +{% block after_field_sets %}{% endblock %} +{% if change %} + {% if ordered_objects %} +

    {% trans "Ordering" %}

    +
    + {% if form.order_.errors %}{{ form.order_.html_error_list }}{% endif %} +

    {{ form.order_ }}

    +
    + {% endif %} +{% endif %} +{% for related_object in inline_related_objects %}{% cms_edit_inline related_object %}{% endfor %} +{% block after_related_objects %}{% endblock %} +{% submit_row %} +{% if add %} + +{% endif %} +{% if auto_populated_fields %} + +{% endif %} +
    +
    +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/templatetags/__init__.py diff -r 000000000000 -r ecdfc63274bf web/ldt/templatetags/iriusermedia.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/templatetags/iriusermedia.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +from django.template import Library + +register = Library() + +def ldt_media_prefix(): + """ + Returns the string contained in the setting ldt_MEDIA_PREFIX. + """ + try: + from django.conf import settings + except ImportError: + return '' + return settings.ldt_MEDIA_PREFIX +ldt_media_prefix = register.simple_tag(ldt_media_prefix) diff -r 000000000000 -r ecdfc63274bf web/ldt/user/__init__.py diff -r 000000000000 -r ecdfc63274bf web/ldt/user/admin.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/admin.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,42 @@ +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin, GroupAdmin +from django.utils.translation import ugettext as _ +from ldt import settings +from copy import deepcopy +from forms import ldtForm, IriGroupForm +from models import ldt, IriGroup + + +class ldtAdmin(UserAdmin): + list_display = ('username', 'email', 'first_name', 'last_name') + + fieldsets = [ + (None, {'fields': ('username', ('password1', 'password2'))}), + (_('User details'), {'fields': (('first_name', 'last_name'), 'email')}), + (_('Groups'), {'fields': ('groups',)}), + (_('Permissions'), {'fields': ('is_staff', 'user_permissions')}), + ] + form = ldtForm + model = ldt + filter_horizontal = ('user_permissions',) + + def get_fieldsets(self, request, obj=None): + fieldsets = deepcopy(self.fieldsets) + if not '/add' in request.path: + fieldsets[0] = (None, {'fields': ('username',)}) + fieldsets.append((_('Password'), {'fields': ('password1', 'password2'), 'classes': ('collapse',)})) + return fieldsets + + def add_view(self, request): + return super(UserAdmin, self).add_view(request) + +admin.site.unregister(ldt) +admin.site.register(ldt, ldtAdmin) + +class IriGroupAdmin(admin.ModelAdmin): + form = IriGroupForm + model = IriGroup + filter_horizontal = ('permissions',) + +admin.site.unregister(IriGroup) +admin.site.register(IriGroup, IriGroupAdmin) diff -r 000000000000 -r ecdfc63274bf web/ldt/user/forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/forms.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,98 @@ +from django import forms +from django.contrib.auth.models import User, Permission, Group +from django.forms.util import ErrorList +from django.contrib.auth.forms import UserCreationForm +from django.utils.translation import gettext as _ +from models import ldt, IriGroup +from ldt.management import get_content_type_list + + +class ldtForm(UserCreationForm): + + class Meta: + model = ldt + + def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, + initial=None, error_class=ErrorList, label_suffix=':', + empty_permitted=False, instance=None): + + if instance: + initial = initial or {} + + super(ldtForm, self).__init__(data, files, auto_id, prefix, + initial, error_class, label_suffix, empty_permitted, instance) + + # filtre les permissions necessaires + content_type_list = get_content_type_list() + self.fields['user_permissions'].queryset = Permission.objects.filter(content_type__in = content_type_list) + + if instance: + self.fields['password1'].required = False + self.fields['password1'].label = _('New password') + self.fields['password2'].required = False + self.fields['password2'].label = _('New password confirmation') + + self._password_change = True + + def clean_username(self): + if self.instance: + return self.cleaned_data['username'] + return super(ldtForm, self).clean_username() + + def clean_password2(self): + if self.instance and self.cleaned_data['password1'] == '' and self.cleaned_data['password2'] == '': + self._password_change = False + return u'' + return super(ldtForm, self).clean_password2() + + + def save(self, commit=True): + Super = self._password_change and ldtForm or UserCreationForm + user = super(Super, self).save(commit=False) + # if user.pk != None: + # self.save_m2m() + + if commit: + user.save() + + return user + +class IriGroupForm(forms.ModelForm): + class meta: + model = IriGroup + + def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, + initial=None, error_class=ErrorList, label_suffix=':', + empty_permitted=False, instance=None): + if instance: + initial = initial or {} + + super(IriGroupForm, self).__init__(data, files, auto_id, prefix, + initial, error_class, label_suffix, empty_permitted, instance) + + # filtre les permissions necessaires + content_type_list = get_content_type_list() + self.fields['permissions'].queryset = Permission.objects.filter(content_type__in = content_type_list) + +class EmailChangeForm(forms.Form): + email1 = forms.EmailField(label=_("E-mail"), max_length=75) + email2 = forms.EmailField(label=_("E-mail"), max_length=75) + + def __init__(self, user=None, *args, **kwargs): + self.user = user + super(EmailChangeForm, self).__init__(*args, **kwargs) + + def clean_email2(self): + email1 = self.cleaned_data.get('email1') + email2 = self.cleaned_data.get('email2') + if email1 and email2: + if email1 != email2: + raise forms.ValidationError(_("The two emails didn't match.")) + return email2 + + + def save(self): + self.user.email=self.cleaned_data['email1'] + self.user.save() + return self.user + diff -r 000000000000 -r ecdfc63274bf web/ldt/user/models.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/models.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,42 @@ +from django.db import models +from django.contrib.auth.models import User, Group, UserManager +from django.utils.translation import gettext as _ +from django.contrib import admin +import datetime + + +class IriGroup(Group): + description = models.TextField(null=True, blank=True) + + def __unicode__(self): + return self.name + + +class ldt(User): + irigroups = models.ManyToManyField(IriGroup, blank=True) + + class Meta: + verbose_name = 'iri user' + verbose_name_plural = 'iri users' + + def __unicode__(self): + return self.username + + +class ldtManager(UserManager): + def create_user(self, username, email, password=None): + "Creates and saves a User with the given username, e-mail and password." + now = datetime.datetime.now() + user = ldt(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now) + if password: + user.set_password(password) + else: + user.set_unusable_password() + user.save() + return user + +User.objects = ldtManager() +User.objects.contribute_to_class(User, "objects") + +admin.site.register(ldt) +admin.site.register(IriGroup) diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/iriuser/user/change_email.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/iriuser/user/change_email.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,51 @@ +{% extends "ldt/user/user_base.html" %} +{# form of email address's change #} +{% load i18n %} +{% block breadcrumb %} +
  • +
  • {% trans "Profiles" %}
  • +
  • {% trans "Modification de l'adresse émail" %}
  • +{% endblock %} + +{% block content_title %}{% trans "Modification de l'adresse émail" %}{% endblock %} +{% block js_declaration %}{{ block.super }} + +{% endblock %} +{% block css_import %} +{{ block.super }} + +{% endblock %} + +{% block iricontent %} +

    {% trans "Please enter your new e-mail twice so we can verify you typed it in correctly." %}

    +
    +{% csrf_token %} + + + + + + + + + + + + +
    + + + + {{form.email1.errors}}
    + + + + {{form.email1.errors}}
    +
    +{% endblock%} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/iriuser/user/change_email_done.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/iriuser/user/change_email_done.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +{% extends "ldt/user/user_base.html" %} +{# if email is changed successfully, retrun this page #} +{% load i18n %} +{% block breadcrumb %} +
  • +
  • {% trans "Profiles" %}
  • +
  • {% trans "email change" %}
  • +{% endblock %} + +{% block content_title %}{% trans "email change" %}{% endblock %} +{% block iricontent %} +

    {% trans "email changed" %}

    +{% trans "back to profile" %} +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/iriuser/user/home.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/iriuser/user/home.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block title %}Home{% endblock %} + +{% block content_base %} + +

    Welcome

    +
  • {% trans "Se connecter" %}
  • +
  • {% trans "Créer un compte" %}
  • +
  • {% trans "récupérer mot de passe" %}
  • + +{% endblock %} + diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/iriuser/user/login_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/iriuser/user/login_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,75 @@ +{% load i18n %} +{# print user's state and form of login #} +{% block js_import %} +{{block.super}} + + +{% endblock %} +{% block css_import %} +{{block.super}} +{% endblock %} +
    +
    diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/iriuser/user/profile.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/iriuser/user/profile.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,9 @@ +{% extends "ldt/user/user_base.html" %} +{# user's profiles(change password, change email) #} +{% load i18n %} +{% block iricontent %} + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/iriuser/user/space.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/iriuser/user/space.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,19 @@ +{% extends "ldt/user/user_base.html" %} +{# user's space (edit page or project lignes de temps) #} +{% load i18n %} +{% block breadcrumb %} +
  • +
  • {% trans "Space" %}
  • +{% endblock %} + +{% block content_title %}{% trans "Space" %}{% endblock %} +{% block iricontent%} + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/iriuser/user/user_base.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/iriuser/user/user_base.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,15 @@ +{% extends "base.html" %} +{# this page inherit base html, all pages of ldt inherit this page. #} +{# all contents are writed in the "iricontent" block #} +{% load i18n %} +{% block js_import %}{{ block.super }} +{% endblock %} +{% block css_import %}{{ block.super }} +{% endblock%} + + +{% block content %} +
    + {% block iricontent %}{% endblock %} +
    +{% endblock%} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/activate.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/activate.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +{% extends "registration/base.html" %} +{% load i18n %} + +{% block breadcrumb %} +
  • +
  • {% trans "Activate account" %}
  • +{% endblock %} + +{% block content_title %}{% trans 'Activate account' %}{% endblock %} + +{% block iricontent %} +

    {% trans "You have activated your account" %}

    +{% trans "Go back to login page" %} +{% endblock %} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/activation_complete.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/activation_complete.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,8 @@ +{% extends "registration/base.html" %} +{% load i18n %} + +{% block content_title %}{% trans 'Sign up successfully' %}{% endblock %} +{% block iricontent %} +

    {% trans "activation completed" %}

    + +{% endblock%} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/activation_email.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/activation_email.txt Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,4 @@ +Pour confirmer que ce compte vous appartient vraiment et afin +d’activer les fonctions, +veuillez suivre ce lien dans votre navigateur dans {{expiration_days}} jours: +http://{{site }}{% url registration.views.activate activation_key %} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/activation_email_subject.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/activation_email_subject.txt Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,1 @@ +Confirmation d’adresse de email pour ldt \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/base.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/base.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,10 @@ +{% extends "ldt/user/user_base.html" %} +{% block js_import %}{{ block.super }} +{% endblock %} +{% block css_import %} +{{ block.super }} + +{% endblock %} +{% block pageclass %}profile{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/logged_out.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/logged_out.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,12 @@ +{% extends "registration/base.html" %} +{% load i18n %} + +{% trans 'Home' %} + +{% block iricontent %} + +

    {% trans "Thanks for spending some quality time with the Web site today." %}

    + +

    {% trans 'Log in again' %}

    + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/login.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/login.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,35 @@ +{% extends "registration/base.html" %} +{% load i18n %} +{% block js_declaration %}{{ block.super }} + +{% endblock %} + +{% block login %} +{% endblock %} + +{% block content_title %}{% trans 'Log in' %}{% endblock %} +{% block iricontent %} + {% if form.errors %} +

    {% trans "Sorry, that's not a valid username or password." %}

    + {% endif %} + +
    + {% csrf_token %} + +
      + {{form.as_ul}} +
    • +
    +
    + +{% endblock %} + + + diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/logout.html diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/password_change_done.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/password_change_done.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,17 @@ +{% extends "registration/base.html" %} +{% load i18n %} +{% block title %}{% trans 'password change successful' %}{% endblock %} + +{% block breadcrumb %} +
  • +
  • {% trans "Profiles" %}
  • +
  • {% trans "password change" %}
  • +{% endblock %} + +{% block content_title %}{% trans "password change successful" %}{% endblock %} +{% block iricontent %} + +

    {% trans 'Your password has been changed.' %}

    +{% trans 'Go back to profiles' %} + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/password_change_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/password_change_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,47 @@ +{% extends "registration/base.html" %} +{% load i18n %} +{% block js_import %}{{ block.super }} + + +{% endblock %} +{% block breadcrumb %} +
  • +
  • {% trans "Profiles" %}
  • +
  • {% trans 'Password change' %}
  • +{% endblock %} + +{% block content_title %}{% trans 'Password change' %}{% endblock %} +{% block iricontent %} + +

    {% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}

    + +
    + + + + + + + + + + + + + + + + + + + +
    {{ form.old_password.errors }}
    {{ form.new_password1.errors }}
    {{ form.new_password2.errors }}
    + + +
    + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/password_reset_complete.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/password_reset_complete.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,16 @@ +{% extends "registration/base.html" %} +{% load i18n %} + +{% block breadcrumb %} +
  • +
  • {% trans 'Password reset' %}
  • +{% endblock %} + +{% block content_title %}{% trans 'Password reset complete' %}{% endblock %} +{% block iricontent %} + +

    {% trans "Your password has been set. You may go ahead and log in now." %}

    + +

    {% trans 'Log in' %}

    + +{% endblock %} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/password_reset_confirm.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/password_reset_confirm.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,33 @@ +{% extends "registration/base.html" %} +{% load i18n %} + +{% block breadcrumb %} +
  • +
  • {% trans 'Password reset' %}
  • +{% endblock %} + +{% block content_title %}{% trans 'Password reset' %}{% endblock %} + +{% block iricontent %} + +{% if validlink %} + +

    {% trans "Please enter your new password twice so we can verify you typed it in correctly." %}

    + +
    +{{ form.new_password1.errors }} +

    {{ form.new_password1 }}

    +{{ form.new_password2.errors }} +

    {{ form.new_password2 }}

    +

    +
    + +{% else %} + +

    {% trans 'Password reset unsuccessful' %}

    + +

    {% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}

    + +{% endif %} + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/password_reset_done.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/password_reset_done.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +{% extends "registration/base.html" %} +{% load i18n %} + +{% block breadcrumb %} +
  • +
  • {% trans 'Password reset' %}
  • +{% endblock %} +{% block content_title %}{% trans 'Password reset successful' %}{% endblock %} + +{% block iricontent %} + +

    {% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}

    + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/password_reset_email.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/password_reset_email.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,15 @@ +{% load i18n %}{% autoescape off %} +{% trans "You're receiving this e-mail because you requested a password reset" %} +{% blocktrans %}for your user account at {{ site_name }}{% endblocktrans %}. + +{% trans "Please go to the following page and choose a new password:" %} +{% block reset_link %} +{{ protocol }}://{{ domain }}{% url django.contrib.auth.views.password_reset_confirm uidb36=uid, token=token %} +{% endblock %} +{% trans "Your username, in case you've forgotten:" %} {{ user.username }} + +{% trans "Thanks for using our site!" %} + +{% blocktrans %}The {{ site_name }} team{% endblocktrans %} + +{% endautoescape %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/password_reset_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/password_reset_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,36 @@ +{% extends "registration/base.html" %} +{% load i18n %} +{% block js_import %}{{ block.super }} + +{% endblock %} + +{% block breadcrumb %} +
  • +
  • {% trans 'Password reset' %}
  • +{% endblock %} +{% block content_title %}{% trans 'Password reset' %}{% endblock %} + + +{% block title %}{% trans "Password reset" %}{% endblock %} + +{% block iricontent%} + +

    {% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}

    + +
    + + + + + + + + +
    {{ form.email.errors }}
    +
    + +{% endblock %} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/registration_active.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/registration_active.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,11 @@ +{% extends "registration/base.html" %} +{% load i18n %} +{% block breadcrumb %} +
  • +
  • {% trans 'Activate the account' %}
  • +{% endblock %} +{% block content_title %}{% trans 'Activate the account' %}{% endblock %} +{% block iricontent%} +

    {% trans 'Vous avez bien activé votre compte, vous pouvez accedez à votre espace personnel.' %}

    +{% trans 'retourner à la page de connexion' %} +{% endblock %} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/registration_complete.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/registration_complete.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,12 @@ +{% extends "registration/base.html" %} +{% load i18n %} + +{% block breadcrumb %} +
  • +
  • {% trans 'Sign up' %}
  • +{% endblock %} +{% block content_title %}{% trans 'Sign up successfully' %}{% endblock %} +{% block iricontent %} +

    {% trans "We've e-mailed you instructions for activate your account to the e-mail address you submitted. You should be receiving it shortly." %}

    + +{% endblock%} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templates/registration/registration_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templates/registration/registration_form.html Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,20 @@ +{% extends "registration/base.html" %} +{% load i18n %} +{% block js_import %}{{ block.super }} + +{% endblock %} + +{% block content_title %}{% trans 'Sign up' %}{% endblock %} +{% block iricontent%} +
    {% csrf_token %} +
      +{{form.as_ul}} +
    • +
    +
    + +{% endblock%} diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templatetags/__init__.py diff -r 000000000000 -r ecdfc63274bf web/ldt/user/templatetags/logintag.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/templatetags/logintag.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,9 @@ +from django import template +from django.template.loader import get_template + +register = template.Library() + +def loginAjax(user, reload=None): + return {'user': user, 'reload': reload} + +register.inclusion_tag('ldt/user/login_form.html')(loginAjax) diff -r 000000000000 -r ecdfc63274bf web/ldt/user/tests.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/tests.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff -r 000000000000 -r ecdfc63274bf web/ldt/user/urls.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/urls.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,19 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', + url(r'^loginAjax/$', 'ldt.user.views.loginAjax'), + url(r'^profile/', 'ldt.user.views.profile'), + url(r'^logout/', 'ldt.user.views.logout_view'), + url(r'^space/$', 'ldt.user.views.space'), + url(r'^emailchange/$', 'ldt.user.views.change_email'), + url(r'^emailchange/done/$', 'ldt.user.views.change_email_done'), +# url(r'^space/ldt/$', 'ldt.ldt.views.list_ldt'), +# url(r'^space/ldt/indexproject/(?P.*)$', 'ldt.ldt.views.indexProject'), +# url(r'^space/ldt/init/(?P.*)/(?P.*)$', 'ldt.ldt.views.init'), +# url(r'^space/ldt/project/(?P.*)$', 'ldt.ldt.views.ldtProject'), +# url(r'^space/ldt/create/$', 'ldt.ldt.views.create_ldt_view'), +# url(r'^space/ldt/created_done/$', 'ldt.ldt.views.created_ldt'), +# url(r'^space/ldt/save/$', 'ldt.ldt.views.save_ldtProject'), +# url(r'^space/ldt/publish/(?P.*)$', 'ldt.ldt.views.publish'), +# url(r'^space/ldt/unpublish/(?P.*)$', 'ldt.ldt.views.unpublish'), +) diff -r 000000000000 -r ecdfc63274bf web/ldt/user/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/user/views.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,75 @@ +from django.conf import settings +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render_to_response +from django.contrib.auth import authenticate, login, logout +from django.contrib.auth.decorators import login_required +# from django.contrib.sites.models import Site, RequestSite +from django.template import RequestContext, Context, loader +from django.utils.translation import ugettext as _ +from django.core.urlresolvers import reverse +from forms import EmailChangeForm +from django.utils import simplejson +from ldt.management import test_cms, test_ldt + + +def home(request): + return render_to_response('ldt/user/home.html',context_instance=RequestContext(request)) + +@login_required +def profile(request): + return render_to_response('ldt/user/profile.html', context_instance=RequestContext(request)) + +@login_required +def space(request, page_id=None, slug=None): + cms = test_cms() + ldt = test_ldt() + context={ + 'cms': cms, + 'ldt': ldt + } + return render_to_response('ldt/user/space.html', context, context_instance=RequestContext(request)) + + + +def logout_view(request): + logout(request) + # return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) + return HttpResponseRedirect(settings.LOGOUT_URL) + + +def loginAjax(request, loginstate_template_name='ldt/user/login_form.html'): + if request.method == "POST": + username=request.POST["username"] + password=request.POST["password"] + user = authenticate(username=username, password=password) + error_message = _(u"Sorry, that's not a valid username or password.") + if user is not None: + if user.is_active: + login(request, user) + context = RequestContext(request, { 'username': user.username,}) + template = loader.get_template(loginstate_template_name) + html = template.render(context) + return HttpResponse(simplejson.dumps({'message': u'successful', 'username': user.username, 'html': html, 'reload': request.POST["reload"],})) + else: + return HttpResponse(simplejson.dumps({'message': error_message,})) + else: + return HttpResponse(simplejson.dumps({'message': error_message,})) + return render_to_response('ldt/user/login_ajax.html', context_instance=RequestContext(request)) + +@login_required +def change_email(request, post_change_redirect=None): + if post_change_redirect is None: + post_change_redirect = reverse('ldt.user.views.change_email_done') + if request.method == "POST": + form = EmailChangeForm(request.user, request.POST) + if form.is_valid(): + form.save() + return HttpResponseRedirect(post_change_redirect) + else: + form = EmailChangeForm(request.user) + return render_to_response('ldt/user/change_email.html', {'form': form,}, context_instance=RequestContext(request)) + +@login_required +def change_email_done(request, template_name='ldt/user/change_email_done.html'): + return render_to_response(template_name, context_instance=RequestContext(request)) + diff -r 000000000000 -r ecdfc63274bf web/ldt/utils/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/utils/__init__.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,2 @@ + + \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/utils/context_processors.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/utils/context_processors.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,4 @@ +from django.conf import settings + +def ldt(request): + return {'ldt_MEDIA_PREFIX': settings.ldt_MEDIA_PREFIX } diff -r 000000000000 -r ecdfc63274bf web/ldt/utils/xml.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/utils/xml.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,7 @@ +def getText(anode): + nodelist = anode.childNodes + rc = "" + for node in nodelist: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/ldt/utils/zipfileext.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/utils/zipfileext.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,14 @@ +import zipfile, os, os.path + +class ZipFileExt(zipfile.ZipFile): + def unzip_into_dir(self, dir): + if not os.path.exists(dir): + os.mkdir(dir, 0777) + for name in self.namelist(): + if name.endswith('/'): + os.mkdir(os.path.join(dir,name)) + else: + outfile = open(os.path.join(dir,name), 'wb') + outfile.write(self.read(name)) + outfile.close() + diff -r 000000000000 -r ecdfc63274bf web/log/.keepme diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/base.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/base.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,746 @@ +/* + DJANGO Admin styles +*/ + +body { + margin: 0; + padding: 0; + font-size: 12px; + font-family: "Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; + color: #333; + background: #fff; +} + +/* LINKS */ + +a:link, a:visited { + color: #5b80b2; + text-decoration: none; +} + +a:hover { + color: #036; +} + +a img { + border: none; +} + +a.section:link, a.section:visited { + color: white; + text-decoration: none; +} + +/* GLOBAL DEFAULTS */ + +p, ol, ul, dl { + margin: .2em 0 .8em 0; +} + +p { + padding: 0; + line-height: 140%; +} + +h1,h2,h3,h4,h5 { + font-weight: bold; +} + +h1 { + font-size: 18px; + color: #666; + padding: 0 6px 0 0; + margin: 0 0 .2em 0; +} + +h2 { + font-size: 16px; + margin: 1em 0 .5em 0; +} + +h2.subhead { + font-weight: normal; + margin-top: 0; +} + +h3 { + font-size: 14px; + margin: .8em 0 .3em 0; + color: #666; + font-weight: bold; +} + +h4 { + font-size: 12px; + margin: 1em 0 .8em 0; + padding-bottom: 3px; +} + +h5 { + font-size: 10px; + margin: 1.5em 0 .5em 0; + color: #666; + text-transform: uppercase; + letter-spacing: 1px; +} + +ul li { + list-style-type: square; + padding: 1px 0; +} + +ul.plainlist { + margin-left: 0 !important; +} + +ul.plainlist li { + list-style-type: none; +} + +li ul { + margin-bottom: 0; +} + +li, dt, dd { + font-size: 11px; + line-height: 14px; +} + +dt { + font-weight: bold; + margin-top: 4px; +} + +dd { + margin-left: 0; +} + +form { + margin: 0; + padding: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +blockquote { + font-size: 11px; + color: #777; + margin-left: 2px; + padding-left: 10px; + border-left: 5px solid #ddd; +} + +code, pre { + font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; + background: inherit; + color: #666; + font-size: 11px; +} + +pre.literal-block { + margin: 10px; + background: #eee; + padding: 6px 8px; +} + +code strong { + color: #930; +} + +hr { + clear: both; + color: #eee; + background-color: #eee; + height: 1px; + border: none; + margin: 0; + padding: 0; + font-size: 1px; + line-height: 1px; +} + +/* TEXT STYLES & MODIFIERS */ + +.small { + font-size: 11px; +} + +.tiny { + font-size: 10px; +} + +p.tiny { + margin-top: -2px; +} + +.mini { + font-size: 9px; +} + +p.mini { + margin-top: -3px; +} + +.help, p.help { + font-size: 10px !important; + color: #999; +} + +p img, h1 img, h2 img, h3 img, h4 img, td img { + vertical-align: middle; +} + +.quiet, a.quiet:link, a.quiet:visited { + color: #999 !important; + font-weight: normal !important; +} + +.quiet strong { + font-weight: bold !important; +} + +.float-right { + float: right; +} + +.float-left { + float: left; +} + +.clear { + clear: both; +} + +.align-left { + text-align: left; +} + +.align-right { + text-align: right; +} + +.example { + margin: 10px 0; + padding: 5px 10px; + background: #efefef; +} + +.nowrap { + white-space: nowrap; +} + +/* TABLES */ + +table { + border-collapse: collapse; + border-color: #ccc; +} + +td, th { + font-size: 11px; + line-height: 13px; + border-bottom: 1px solid #eee; + vertical-align: top; + padding: 5px; + font-family: "Lucida Grande", Verdana, Arial, sans-serif; +} + +th { + text-align: left; + font-size: 12px; + font-weight: bold; +} + +thead th, +tfoot td { + color: #666; + padding: 2px 5px; + font-size: 11px; + background: #e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; + border-left: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} + +tfoot td { + border-bottom: none; + border-top: 1px solid #ddd; +} + +thead th:first-child, +tfoot td:first-child { + border-left: none !important; +} + +thead th.optional { + font-weight: normal !important; +} + +fieldset table { + border-right: 1px solid #eee; +} + +tr.row-label td { + font-size: 9px; + padding-top: 2px; + padding-bottom: 0; + border-bottom: none; + color: #666; + margin-top: -1px; +} + +tr.alt { + background: #f6f6f6; +} + +.row1 { + background: #EDF3FE; +} + +.row2 { + background: white; +} + +/* SORTABLE TABLES */ + +thead th a:link, thead th a:visited { + color: #666; + display: block; +} + +table thead th.sorted { + background-position: bottom left !important; +} + +table thead th.sorted a { + padding-right: 13px; +} + +table thead th.ascending a { + background: url(../img/admin/arrow-down.gif) right .4em no-repeat; +} + +table thead th.descending a { + background: url(../img/admin/arrow-up.gif) right .4em no-repeat; +} + +/* ORDERABLE TABLES */ + +table.orderable tbody tr td:hover { + cursor: move; +} + +table.orderable tbody tr td:first-child { + padding-left: 14px; + background-image: url(../img/admin/nav-bg-grabber.gif); + background-repeat: repeat-y; +} + +table.orderable-initalized .order-cell, body>tr>td.order-cell { + display: none; +} + +/* FORM DEFAULTS */ + +input, textarea, select, .form-row p { + margin: 2px 0; + padding: 2px 3px; + vertical-align: middle; + font-family: "Lucida Grande", Verdana, Arial, sans-serif; + font-weight: normal; + font-size: 11px; +} + +textarea { + vertical-align: top !important; +} + +input[type=text], input[type=password], textarea, select, .vTextField { + border: 1px solid #ccc; +} + +/* FORM BUTTONS */ + +.button, input[type=submit], input[type=button], .submit-row input { + background: white url(../img/admin/nav-bg.gif) bottom repeat-x; + padding: 3px 5px; + color: black; + border: 1px solid #bbb; + border-color: #ddd #aaa #aaa #ddd; +} + +.button:active, input[type=submit]:active, input[type=button]:active { + background-image: url(../img/admin/nav-bg-reverse.gif); + background-position: top; +} + +.button.default, input[type=submit].default, .submit-row input.default { + border: 2px solid #5b80b2; + background: #7CA0C7 url(../img/admin/default-bg.gif) bottom repeat-x; + font-weight: bold; + color: white; + float: right; +} + +.button.default:active, input[type=submit].default:active { + background-image: url(../img/admin/default-bg-reverse.gif); + background-position: top; +} + +/* MODULES */ + +.module { + border: 1px solid #ccc; + margin-bottom: 5px; + background: white; +} + +.module p, .module ul, .module h3, .module h4, .module dl, .module pre { + padding-left: 10px; + padding-right: 10px; +} + +.module blockquote { + margin-left: 12px; +} + +.module ul, .module ol { + margin-left: 1.5em; +} + +.module h3 { + margin-top: .6em; +} + +.module h2, .module caption, .inline-group h2 { + margin: 0; + padding: 2px 5px 3px 5px; + font-size: 11px; + text-align: left; + font-weight: bold; + background: #7CA0C7 url(../img/admin/default-bg.gif) top left repeat-x; + color: white; +} + +.module table { + border-collapse: collapse; +} + +/* MESSAGES & ERRORS */ + +ul.messagelist { + padding: 0 0 5px 0; + margin: 0; +} + +ul.messagelist li { + font-size: 12px; + display: block; + padding: 4px 5px 4px 25px; + margin: 0 0 3px 0; + border-bottom: 1px solid #ddd; + color: #666; + background: #ffc url(../img/admin/icon_success.gif) 5px .3em no-repeat; +} + +.errornote { + font-size: 12px !important; + display: block; + padding: 4px 5px 4px 25px; + margin: 0 0 3px 0; + border: 1px solid red; + color: red; + background: #ffc url(../img/admin/icon_error.gif) 5px .3em no-repeat; +} + +ul.errorlist { + margin: 0 !important; + padding: 0 !important; +} + +.errorlist li { + font-size: 12px !important; + display: block; + padding: 4px 5px 4px 25px; + margin: 0 0 3px 0; + border: 1px solid red; + color: white; + background: red url(../img/admin/icon_alert.gif) 5px .3em no-repeat; +} + +td ul.errorlist { + margin: 0 !important; + padding: 0 !important; +} + +td ul.errorlist li { + margin: 0 !important; +} + +.errors { + background: #ffc; +} + +.errors input, .errors select { + border: 1px solid red; +} + +div.system-message { + background: #ffc; + margin: 10px; + padding: 6px 8px; + font-size: .8em; +} + +div.system-message p.system-message-title { + padding: 4px 5px 4px 25px; + margin: 0; + color: red; + background: #ffc url(../img/admin/icon_error.gif) 5px .3em no-repeat; +} + +.description { + font-size: 12px; + padding: 5px 0 0 12px; +} + +/* BREADCRUMBS */ + +div.breadcrumbs { + background: white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x; + padding: 2px 8px 3px 8px; + font-size: 11px; + color: #999; + border-top: 1px solid white; + border-bottom: 1px solid #ccc; + text-align: left; +} + +/* ACTION ICONS */ + +.addlink { + padding-left: 12px; + background: url(../img/admin/icon_addlink.gif) 0 .2em no-repeat; +} + +.changelink { + padding-left: 12px; + background: url(../img/admin/icon_changelink.gif) 0 .2em no-repeat; +} + +.deletelink { + padding-left: 12px; + background: url(../img/admin/icon_deletelink.gif) 0 .25em no-repeat; +} + +a.deletelink:link, a.deletelink:visited { + color: #CC3434; +} + +a.deletelink:hover { + color: #993333; +} + +/* OBJECT TOOLS */ + +.object-tools { + font-size: 10px; + font-weight: bold; + font-family: Arial,Helvetica,sans-serif; + padding-left: 0; + float: right; + position: relative; + margin-top: -2.4em; + margin-bottom: -2em; +} + +.form-row .object-tools { + margin-top: 5px; + margin-bottom: 5px; + float: none; + height: 2em; + padding-left: 3.5em; +} + +.object-tools li { + display: block; + float: left; + background: url(../img/admin/tool-left.gif) 0 0 no-repeat; + padding: 0 0 0 8px; + margin-left: 2px; + height: 16px; +} + +.object-tools li:hover { + background: url(../img/admin/tool-left_over.gif) 0 0 no-repeat; +} + +.object-tools a:link, .object-tools a:visited { + display: block; + float: left; + color: white; + padding: .1em 14px .1em 8px; + height: 14px; + background: #999 url(../img/admin/tool-right.gif) 100% 0 no-repeat; +} + +.object-tools a:hover, .object-tools li:hover a { + background: #5b80b2 url(../img/admin/tool-right_over.gif) 100% 0 no-repeat; +} + +.object-tools a.viewsitelink, .object-tools a.golink { + background: #999 url(../img/admin/tooltag-arrowright.gif) top right no-repeat; + padding-right: 28px; +} + +.object-tools a.viewsitelink:hover, .object-tools a.golink:hover { + background: #5b80b2 url(../img/admin/tooltag-arrowright_over.gif) top right no-repeat; +} + +.object-tools a.addlink { + background: #999 url(../img/admin/tooltag-add.gif) top right no-repeat; + padding-right: 28px; +} + +.object-tools a.addlink:hover { + background: #5b80b2 url(../img/admin/tooltag-add_over.gif) top right no-repeat; +} + +/* OBJECT HISTORY */ + +table#change-history { + width: 100%; +} + +table#change-history tbody th { + width: 16em; +} + +/* PAGE STRUCTURE */ + +#container { + position: relative; + width: 100%; + min-width: 760px; + padding: 0; +} + +#content { + margin: 10px 15px; +} + +#header { + width: 100%; +} + +#content-main { + float: left; + width: 100%; +} + +#content-related { + float: right; + width: 18em; + position: relative; + margin-right: -19em; +} + +#footer { + clear: both; + padding: 10px; +} + +/* COLUMN TYPES */ + +.colMS { + margin-right: 20em !important; +} + +.colSM { + margin-left: 20em !important; +} + +.colSM #content-related { + float: left; + margin-right: 0; + margin-left: -19em; +} + +.colSM #content-main { + float: right; +} + +.popup .colM { + width: 95%; +} + +.subcol { + float: left; + width: 46%; + margin-right: 15px; +} + +.dashboard #content { + width: 500px; +} + +/* HEADER */ + +#header { + background: #417690; + color: #ffc; + overflow: hidden; +} + +#header a:link, #header a:visited { + color: white; +} + +#header a:hover { + text-decoration: underline; +} + +#branding h1 { + padding: 0 10px; + font-size: 18px; + margin: 8px 0; + font-weight: normal; + color: #f4f379; +} + +#branding h2 { + padding: 0 10px; + font-size: 14px; + margin: -8px 0 8px 0; + font-weight: normal; + color: #ffc; +} + +#user-tools { + position: absolute; + top: 0; + right: 0; + padding: 1.2em 10px; + font-size: 11px; + text-align: right; +} + +/* SIDEBAR */ + +#content-related h3 { + font-size: 12px; + color: #666; + margin-bottom: 3px; +} + +#content-related h4 { + font-size: 11px; +} + +#content-related .module h2 { + background: #eee url(../img/admin/nav-bg.gif) bottom left repeat-x; + color: #666; +} + diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/changelists.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/changelists.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,284 @@ +/* CHANGELISTS */ + +#changelist { + position: relative; + width: 100%; +} + +#changelist table { + width: 100%; +} + +.change-list .filtered table { + border-right: 1px solid #ddd; +} + +.change-list .filtered { + min-height: 400px; +} + +.change-list .filtered { + background: white url(../img/admin/changelist-bg.gif) top right repeat-y !important; +} + +.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { + margin-right: 160px !important; + width: auto !important; +} + +.change-list .filtered table tbody th { + padding-right: 1em; +} + +#changelist .toplinks { + border-bottom: 1px solid #ccc !important; +} + +#changelist .paginator { + color: #666; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + background: white url(../img/admin/nav-bg.gif) 0 180% repeat-x; + overflow: hidden; +} + +.change-list .filtered .paginator { + border-right: 1px solid #ddd; +} + +/* CHANGELIST TABLES */ + +#changelist table thead th { + white-space: nowrap; + vertical-align: middle; +} + +#changelist table thead th.action-checkbox-column { + width: 1.5em; + text-align: center; +} + +#changelist table tbody td { + border-left: 1px solid #ddd; +} + +#changelist table tbody td:first-child { + border-left: 0; + border-right: 1px solid #ddd; + text-align: center; +} + +#changelist table tfoot { + color: #666; +} + +/* TOOLBAR */ + +#changelist #toolbar { + padding: 3px; + border-bottom: 1px solid #ddd; + background: #e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; + color: #666; +} + +#changelist #toolbar form input { + font-size: 11px; + padding: 1px 2px; +} + +#changelist #toolbar form #searchbar { + padding: 2px; +} + +#changelist #changelist-search img { + vertical-align: middle; +} + +/* FILTER COLUMN */ + +#changelist-filter { + position: absolute; + top: 0; + right: 0; + z-index: 1000; + width: 160px; + border-left: 1px solid #ddd; + background: #efefef; + margin: 0; +} + +#changelist-filter h2 { + font-size: 11px; + padding: 2px 5px; + border-bottom: 1px solid #ddd; +} + +#changelist-filter h3 { + font-size: 12px; + margin-bottom: 0; +} + +#changelist-filter ul { + padding-left: 0; + margin-left: 10px; +} + +#changelist-filter li { + list-style-type: none; + margin-left: 0; + padding-left: 0; +} + +#changelist-filter a { + color: #999; +} + +#changelist-filter a:hover { + color: #036; +} + +#changelist-filter li.selected { + border-left: 5px solid #ccc; + padding-left: 5px; + margin-left: -10px; +} + +#changelist-filter li.selected a { + color: #5b80b2 !important; +} + +/* DATE DRILLDOWN */ + +.change-list ul.toplinks { + display: block; + background: white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x; + border-top: 1px solid white; + float: left; + padding: 0 !important; + margin: 0 !important; + width: 100%; +} + +.change-list ul.toplinks li { + float: left; + width: 9em; + padding: 3px 6px; + font-weight: bold; + list-style-type: none; +} + +.change-list ul.toplinks .date-back a { + color: #999; +} + +.change-list ul.toplinks .date-back a:hover { + color: #036; +} + +/* PAGINATOR */ + +.paginator { + font-size: 11px; + padding-top: 10px; + padding-bottom: 10px; + line-height: 22px; + margin: 0; + border-top: 1px solid #ddd; +} + +.paginator a:link, .paginator a:visited { + padding: 2px 6px; + border: solid 1px #ccc; + background: white; + text-decoration: none; +} + +.paginator a.showall { + padding: 0 !important; + border: none !important; +} + +.paginator a.showall:hover { + color: #036 !important; + background: transparent !important; +} + +.paginator .end { + border-width: 2px !important; + margin-right: 6px; +} + +.paginator .this-page { + padding: 2px 6px; + font-weight: bold; + font-size: 13px; + vertical-align: top; +} + +.paginator a:hover { + color: white; + background: #5b80b2; + border-color: #036; +} + +/* ACTIONS */ + +.filtered .actions { + margin-right: 160px !important; + border-right: 1px solid #ddd; +} + +#changelist table input { + margin: 0; +} + +#changelist table tbody tr.selected { + background-color: #FFFFCC; +} + +#changelist .actions { + color: #999; + padding: 3px; + border-top: 1px solid #fff; + border-bottom: 1px solid #ddd; + background: white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x; +} + +#changelist .actions.selected { + background: #fffccf; + border-top: 1px solid #fffee8; + border-bottom: 1px solid #edecd6; +} + +#changelist .actions span.all, +#changelist .actions span.action-counter, +#changelist .actions span.clear, +#changelist .actions span.question { + font-size: 11px; + margin: 0 0.5em; + display: none; +} + +#changelist .actions:last-child { + border-bottom: none; +} + +#changelist .actions select { + border: 1px solid #aaa; + margin-left: 0.5em; + padding: 1px 2px; +} + +#changelist .actions label { + font-size: 11px; + margin-left: 0.5em; +} + +#changelist #action-toggle { + display: none; +} + +#changelist .actions .button { + font-size: 11px; + padding: 1px 2px; +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/dashboard.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/dashboard.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,24 @@ +/* DASHBOARD */ + +.dashboard .module table th { + width: 100%; +} + +.dashboard .module table td { + white-space: nowrap; +} + +.dashboard .module table td a { + display: block; + padding-right: .6em; +} + +/* RECENT ACTIONS MODULE */ + +.module ul.actionlist { + margin-left: 0; +} + +ul.actionlist li { + list-style-type: none; +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/forms.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/forms.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,354 @@ +@import url('widgets.css'); + +/* FORM ROWS */ + +.form-row { + overflow: hidden; + padding: 8px 12px; + font-size: 11px; + border-bottom: 1px solid #eee; +} + +.form-row img, .form-row input { + vertical-align: middle; +} + +form .form-row p { + padding-left: 0; + font-size: 11px; +} + +/* FORM LABELS */ + +form h4 { + margin: 0 !important; + padding: 0 !important; + border: none !important; +} + +label { + font-weight: normal !important; + color: #666; + font-size: 12px; +} + +.required label, label.required { + font-weight: bold !important; + color: #333 !important; +} + +/* RADIO BUTTONS */ + +form ul.radiolist li { + list-style-type: none; +} + +form ul.radiolist label { + float: none; + display: inline; +} + +form ul.inline { + margin-left: 0; + padding: 0; +} + +form ul.inline li { + float: left; + padding-right: 7px; +} + +/* ALIGNED FIELDSETS */ + +.aligned label { + display: block; + padding: 3px 10px 0 0; + float: left; + width: 8em; +} + +.aligned ul label { + display: inline; + float: none; + width: auto; +} + +.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { + width: 350px; +} + +form .aligned p, form .aligned ul { + margin-left: 7em; + padding-left: 30px; +} + +form .aligned table p { + margin-left: 0; + padding-left: 0; +} + +form .aligned p.help { + padding-left: 38px; +} + +.aligned .vCheckboxLabel { + float: none !important; + display: inline; + padding-left: 4px; +} + +.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { + width: 610px; +} + +.checkbox-row p.help { + margin-left: 0; + padding-left: 0 !important; +} + +fieldset .field-box { + float: left; + margin-right: 20px; +} + +/* WIDE FIELDSETS */ + +.wide label { + width: 15em !important; +} + +form .wide p { + margin-left: 15em; +} + +form .wide p.help { + padding-left: 38px; +} + +.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { + width: 450px; +} + +/* COLLAPSED FIELDSETS */ + +fieldset.collapsed * { + display: none; +} + +fieldset.collapsed h2, fieldset.collapsed { + display: block !important; +} + +fieldset.collapsed h2 { + background-image: url(../img/admin/nav-bg.gif); + background-position: bottom left; + color: #999; +} + +fieldset.collapsed .collapse-toggle { + background: transparent; + display: inline !important; +} + +/* MONOSPACE TEXTAREAS */ + +fieldset.monospace textarea { + font-family: "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace; +} + +/* SUBMIT ROW */ + +.submit-row { + padding: 5px 7px; + text-align: right; + background: white url(../img/admin/nav-bg.gif) 0 100% repeat-x; + border: 1px solid #ccc; + margin: 5px 0; + overflow: hidden; +} + +.submit-row input { + margin: 0 0 0 5px; +} + +.submit-row p { + margin: 0.3em; +} + +.submit-row p.deletelink-box { + float: left; +} + +.submit-row .deletelink { + background: url(../img/admin/icon_deletelink.gif) 0 50% no-repeat; + padding-left: 14px; +} + +/* CUSTOM FORM FIELDS */ + +.vSelectMultipleField { + vertical-align: top !important; +} + +.vCheckboxField { + border: none; +} + +.vDateField, .vTimeField { + margin-right: 2px; +} + +.vURLField { + width: 30em; +} + +.vLargeTextField, .vXMLLargeTextField { + width: 48em; +} + +.flatpages-flatpage #id_content { + height: 40.2em; +} + +.module table .vPositiveSmallIntegerField { + width: 2.2em; +} + +.vTextField { + width: 20em; +} + +.vIntegerField { + width: 5em; +} + +.vForeignKeyRawIdAdminField { + width: 5em; +} + +/* INLINES */ + +.inline-group { + padding: 0; + border: 1px solid #ccc; + margin: 10px 0; +} + +.inline-group .aligned label { + width: 8em; +} + +.inline-related { + position: relative; +} + +.inline-related h3 { + margin: 0; + color: #666; + padding: 3px 5px; + font-size: 11px; + background: #e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; + border-bottom: 1px solid #ddd; +} + +.inline-related h3 span.delete { + float: right; +} + +.inline-related h3 span.delete label { + margin-left: 2px; + font-size: 11px; +} + +.inline-related fieldset { + margin: 0; + background: #fff; + border: none; +} + +.inline-related fieldset.module h3 { + margin: 0; + padding: 2px 5px 3px 5px; + font-size: 11px; + text-align: left; + font-weight: bold; + background: #bcd; + color: #fff; +} + +.inline-group .tabular fieldset.module { + border: none; + border-bottom: 1px solid #ddd; +} + +.inline-related.tabular fieldset.module table { + width: 100%; +} + +.last-related fieldset { + border: none; +} + +.inline-group .tabular tr.has_original td { + padding-top: 2em; +} + +.inline-group .tabular tr td.original { + padding: 2px 0 0 0; + width: 0; + _position: relative; +} + +.inline-group .tabular th.original { + width: 0px; + padding: 0; +} + +.inline-group .tabular td.original p { + position: absolute; + left: 0; + height: 1.1em; + padding: 2px 7px; + overflow: hidden; + font-size: 9px; + font-weight: bold; + color: #666; + _width: 700px; +} + +.inline-group ul.tools { + padding: 0; + margin: 0; + list-style: none; +} + +.inline-group ul.tools li { + display: inline; + padding: 0 5px; +} + +.inline-group div.add-row, +.inline-group .tabular tr.add-row td { + color: #666; + padding: 3px 5px; + border-bottom: 1px solid #ddd; + background: #e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; +} + +.inline-group .tabular tr.add-row td { + padding: 4px 5px 3px; + border-bottom: none; +} + +.inline-group ul.tools a.add, +.inline-group div.add-row a, +.inline-group .tabular tr.add-row td a { + background: url(../img/admin/icon_addlink.gif) 0 50% no-repeat; + padding-left: 14px; + font-size: 11px; + outline: 0; /* Remove dotted border around link */ +} + +.empty-form { + display: none; +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/ie.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/ie.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,57 @@ +/* IE 6 & 7 */ + +/* Proper fixed width for dashboard in IE6 */ + +.dashboard #content { + *width: 768px; +} + +.dashboard #content-main { + *width: 535px; +} + +/* IE 6 ONLY */ + +/* Keep header from flowing off the page */ + +#container { + _position: static; +} + +/* Put the right sidebars back on the page */ + +.colMS #content-related { + _margin-right: 0; + _margin-left: 10px; + _position: static; +} + +/* Put the left sidebars back on the page */ + +.colSM #content-related { + _margin-right: 10px; + _margin-left: -115px; + _position: static; +} + +.form-row { + _height: 1%; +} + +/* Fix right margin for changelist filters in IE6 */ + +#changelist-filter ul { + _margin-right: -10px; +} + +/* IE ignores min-height, but treats height as if it were min-height */ + +.change-list .filtered { + _height: 400px; +} + +/* IE doesn't know alpha transparency in PNGs */ + +.inline-deletelink { + background: transparent url(../img/admin/inline-delete-8bit.png) no-repeat; +} \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/login.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/login.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,54 @@ +/* LOGIN FORM */ + +body.login { + background: #eee; +} + +.login #container { + background: white; + border: 1px solid #ccc; + width: 28em; + min-width: 300px; + margin-left: auto; + margin-right: auto; + margin-top: 100px; +} + +.login #content-main { + width: 100%; +} + +.login form { + margin-top: 1em; +} + +.login .form-row { + padding: 4px 0; + float: left; + width: 100%; +} + +.login .form-row label { + float: left; + width: 9em; + padding-right: 0.5em; + line-height: 2em; + text-align: right; + font-size: 1em; + color: #333; +} + +.login .form-row #id_username, .login .form-row #id_password { + width: 14em; +} + +.login span.help { + font-size: 10px; + display: block; +} + +.login .submit-row { + clear: both; + padding: 1em 0 0 9.4em; +} + diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/rtl.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,217 @@ +body { + direction: rtl; +} + +/* LOGIN */ + +.login .form-row { + float: right; +} + +.login .form-row label { + float: right; + padding-left: 0.5em; + padding-right: 0; + text-align: left; +} + +.login .submit-row { + clear: both; + padding: 1em 9.4em 0 0; +} + +/* GLOBAL */ + +th { + text-align: right; +} + +.module h2, .module caption { + text-align: right; +} + +.addlink, .changelink { + padding-left: 0px; + padding-right: 12px; + background-position: 100% 0.2em; +} + +.deletelink { + padding-left: 0px; + padding-right: 12px; + background-position: 100% 0.25em; +} + +.object-tools { + float: left; +} + +/* LAYOUT */ + +#user-tools { + right: auto; + left: 0; + text-align: left; +} + +div.breadcrumbs { + text-align: right; +} + +#content-main { + float: right; +} + +#content-related { + float: left; + margin-left: -19em; + margin-right: auto; +} + +.colMS { + margin-left: 20em !important; + margin-right: 10px !important; +} + +/* dashboard styles */ + +.dashboard .module table td a { + padding-left: .6em; + padding-right: 12px; +} + +/* changelists styles */ + +.change-list .filtered { + background: white url(../img/admin/changelist-bg_rtl.gif) top left repeat-y !important; +} + +.change-list .filtered table { + border-left: 1px solid #ddd; + border-right: 0px none; +} + +#changelist-filter { + right: auto; + left: 0; + border-left: 0px none; + border-right: 1px solid #ddd; +} + +.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { + margin-right: 0px !important; + margin-left: 160px !important; +} + +#changelist-filter li.selected { + border-left: 0px none; + padding-left: 0px; + margin-left: 0; + border-right: 5px solid #ccc; + padding-right: 5px; + margin-right: -10px; +} + +.filtered .actions { + border-left:1px solid #DDDDDD; + margin-left:160px !important; + border-right: 0 none; + margin-right:0 !important; +} + +/* FORMS */ + +.aligned label { + padding: 0 0 3px 1em; + float: right; +} + +.submit-row { + text-align: left +} + +.submit-row p.deletelink-box { + float: right; +} + +.submit-row .deletelink { + background: url(../img/admin/icon_deletelink.gif) 0 50% no-repeat; + padding-right: 14px; +} + +.vDateField, .vTimeField { + margin-left: 2px; +} + +form ul.inline li { + float: right; + padding-right: 0; + padding-left: 7px; +} + +input[type=submit].default, .submit-row input.default { + float: left; +} + +fieldset .field-box { + float: right; + margin-left: 20px; +} + +.errorlist li { + background-position: 100% .3em; + padding: 4px 25px 4px 5px; +} + +.errornote { + background-position: 100% .3em; + padding: 4px 25px 4px 5px; +} + +/* WIDGETS */ + +.calendarnav-previous { + top: 0; + left: auto; + right: 0; +} + +.calendarnav-next { + top: 0; + right: auto; + left: 0; +} + +.calendar caption, .calendarbox h2 { + text-align: center; +} + +.selector { + float: right; +} + +.selector .selector-filter { + text-align: right; +} + +.inline-deletelink { + float: left; +} + +/* MISC */ + +.inline-related h2, .inline-group h2 { + text-align: right +} + +.inline-related h3 span.delete { + padding-right: 20px; + padding-left: inherit; + left: 10px; + right: inherit; +} + +.inline-related h3 span.delete label { + margin-left: inherit; + margin-right: 2px; +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/css/widgets.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/css/widgets.css Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,506 @@ +/* SELECTOR (FILTER INTERFACE) */ + +.selector { + width: 580px; + float: left; +} + +.selector select { + width: 270px; + height: 17.2em; +} + +.selector-available, .selector-chosen { + float: left; + width: 270px; + text-align: center; + margin-bottom: 5px; +} + +.selector-available h2, .selector-chosen h2 { + border: 1px solid #ccc; +} + +.selector .selector-available h2 { + background: white url(../img/admin/nav-bg.gif) bottom left repeat-x; + color: #666; +} + +.selector .selector-filter { + background: white; + border: 1px solid #ccc; + border-width: 0 1px; + padding: 3px; + color: #999; + font-size: 10px; + margin: 0; + text-align: left; +} + +.selector .selector-chosen .selector-filter { + padding: 4px 5px; +} + +.selector .selector-available input { + width: 230px; +} + +.selector ul.selector-chooser { + float: left; + width: 22px; + height: 50px; + background: url(../img/admin/chooser-bg.gif) top center no-repeat; + margin: 8em 3px 0 3px; + padding: 0; +} + +.selector-chooser li { + margin: 0; + padding: 3px; + list-style-type: none; +} + +.selector select { + margin-bottom: 5px; + margin-top: 0; +} + +.selector-add, .selector-remove { + width: 16px; + height: 16px; + display: block; + text-indent: -3000px; +} + +.selector-add { + background: url(../img/admin/selector-add.gif) top center no-repeat; + margin-bottom: 2px; +} + +.selector-remove { + background: url(../img/admin/selector-remove.gif) top center no-repeat; +} + +a.selector-chooseall, a.selector-clearall { + display: block; + width: 6em; + text-align: left; + margin-left: auto; + margin-right: auto; + font-weight: bold; + color: #666; + padding: 3px 0 3px 18px; +} + +a.selector-chooseall:hover, a.selector-clearall:hover { + color: #036; +} + +a.selector-chooseall { + width: 7em; + background: url(../img/admin/selector-addall.gif) left center no-repeat; +} + +a.selector-clearall { + background: url(../img/admin/selector-removeall.gif) left center no-repeat; +} + + +/* STACKED SELECTORS */ + +.stacked { + float: left; + width: 500px; +} + +.stacked select { + width: 480px; + height: 10.1em; +} + +.stacked .selector-available, .stacked .selector-chosen { + width: 480px; +} + +.stacked .selector-available { + margin-bottom: 0; +} + +.stacked .selector-available input { + width: 442px; +} + +.stacked ul.selector-chooser { + height: 22px; + width: 50px; + margin: 0 0 3px 40%; + background: url(../img/admin/chooser_stacked-bg.gif) top center no-repeat; +} + +.stacked .selector-chooser li { + float: left; + padding: 3px 3px 3px 5px; +} + +.stacked .selector-chooseall, .stacked .selector-clearall { + display: none; +} + +.stacked .selector-add { + background-image: url(../img/admin/selector_stacked-add.gif); +} + +.stacked .selector-remove { + background-image: url(../img/admin/selector_stacked-remove.gif); +} + + +/* DATE AND TIME */ + +p.datetime { + line-height: 20px; + margin: 0; + padding: 0; + color: #666; + font-size: 11px; + font-weight: bold; +} + +.datetime span { + font-size: 11px; + color: #ccc; + font-weight: normal; + white-space: nowrap; +} + +table p.datetime { + font-size: 10px; + margin-left: 0; + padding-left: 0; +} + +/* FILE UPLOADS */ + +p.file-upload { + line-height: 20px; + margin: 0; + padding: 0; + color: #666; + font-size: 11px; + font-weight: bold; +} + +.file-upload a { + font-weight: normal; +} + +.file-upload .deletelink { + margin-left: 5px; +} + +/* CALENDARS & CLOCKS */ + +.calendarbox, .clockbox { + margin: 5px auto; + font-size: 11px; + width: 16em; + text-align: center; + background: white; + position: relative; +} + +.clockbox { + width: auto; +} + +.calendar { + margin: 0; + padding: 0; +} + +.calendar table { + margin: 0; + padding: 0; + border-collapse: collapse; + background: white; + width: 99%; +} + +.calendar caption, .calendarbox h2 { + margin: 0; + font-size: 11px; + text-align: center; + border-top: none; +} + +.calendar th { + font-size: 10px; + color: #666; + padding: 2px 3px; + text-align: center; + background: #e1e1e1 url(../img/admin/nav-bg.gif) 0 50% repeat-x; + border-bottom: 1px solid #ddd; +} + +.calendar td { + font-size: 11px; + text-align: center; + padding: 0; + border-top: 1px solid #eee; + border-bottom: none; +} + +.calendar td.selected a { + background: #C9DBED; +} + +.calendar td.nonday { + background: #efefef; +} + +.calendar td.today a { + background: #ffc; +} + +.calendar td a, .timelist a { + display: block; + font-weight: bold; + padding: 4px; + text-decoration: none; + color: #444; +} + +.calendar td a:hover, .timelist a:hover { + background: #5b80b2; + color: white; +} + +.calendar td a:active, .timelist a:active { + background: #036; + color: white; +} + +.calendarnav { + font-size: 10px; + text-align: center; + color: #ccc; + margin: 0; + padding: 1px 3px; +} + +.calendarnav a:link, #calendarnav a:visited, #calendarnav a:hover { + color: #999; +} + +.calendar-shortcuts { + background: white; + font-size: 10px; + line-height: 11px; + border-top: 1px solid #eee; + padding: 3px 0 4px; + color: #ccc; +} + +.calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { + display: block; + position: absolute; + font-weight: bold; + font-size: 12px; + background: #C9DBED url(../img/admin/default-bg.gif) bottom left repeat-x; + padding: 1px 4px 2px 4px; + color: white; +} + +.calendarnav-previous:hover, .calendarnav-next:hover { + background: #036; +} + +.calendarnav-previous { + top: 0; + left: 0; +} + +.calendarnav-next { + top: 0; + right: 0; +} + +.calendar-cancel { + margin: 0 !important; + padding: 0; + font-size: 10px; + background: #e1e1e1 url(../img/admin/nav-bg.gif) 0 50% repeat-x; + border-top: 1px solid #ddd; +} + +.calendar-cancel a { + padding: 2px; + color: #999; +} + +ul.timelist, .timelist li { + list-style-type: none; + margin: 0; + padding: 0; +} + +.timelist a { + padding: 2px; +} + +/* INLINE ORDERER */ + +ul.orderer { + position: relative; + padding: 0 !important; + margin: 0 !important; + list-style-type: none; +} + +ul.orderer li { + list-style-type: none; + display: block; + padding: 0; + margin: 0; + border: 1px solid #bbb; + border-width: 0 1px 1px 0; + white-space: nowrap; + overflow: hidden; + background: #e2e2e2 url(../img/admin/nav-bg-grabber.gif) repeat-y; +} + +ul.orderer li:hover { + cursor: move; + background-color: #ddd; +} + +ul.orderer li a.selector { + margin-left: 12px; + overflow: hidden; + width: 83%; + font-size: 10px !important; + padding: 0.6em 0; +} + +ul.orderer li a:link, ul.orderer li a:visited { + color: #333; +} + +ul.orderer li .inline-deletelink { + position: absolute; + right: 4px; + margin-top: 0.6em; +} + +ul.orderer li.selected { + background-color: #f8f8f8; + border-right-color: #f8f8f8; +} + +ul.orderer li.deleted { + background: #bbb url(../img/admin/deleted-overlay.gif); +} + +ul.orderer li.deleted a:link, ul.orderer li.deleted a:visited { + color: #888; +} + +ul.orderer li.deleted .inline-deletelink { + background-image: url(../img/admin/inline-restore.png); +} + +ul.orderer li.deleted:hover, ul.orderer li.deleted a.selector:hover { + cursor: default; +} + +/* EDIT INLINE */ + +.inline-deletelink { + float: right; + text-indent: -9999px; + background: transparent url(../img/admin/inline-delete.png) no-repeat; + width: 15px; + height: 15px; + border: 0px none; + outline: 0; /* Remove dotted border around link */ +} + +.inline-deletelink:hover { + background-position: -15px 0; + cursor: pointer; +} + +.editinline button.addlink { + border: 0px none; + color: #5b80b2; + font-size: 100%; + cursor: pointer; +} + +.editinline button.addlink:hover { + color: #036; + cursor: pointer; +} + +.editinline table .help { + text-align: right; + float: right; + padding-left: 2em; +} + +.editinline tfoot .addlink { + white-space: nowrap; +} + +.editinline table thead th:last-child { + border-left: none; +} + +.editinline tr.deleted { + background: #ddd url(../img/admin/deleted-overlay.gif); +} + +.editinline tr.deleted .inline-deletelink { + background-image: url(../img/admin/inline-restore.png); +} + +.editinline tr.deleted td:hover { + cursor: default; +} + +.editinline tr.deleted td:first-child { + background-image: none !important; +} + +/* EDIT INLINE - STACKED */ + +.editinline-stacked { + min-width: 758px; +} + +.editinline-stacked .inline-object { + margin-left: 210px; + background: white; +} + +.editinline-stacked .inline-source { + float: left; + width: 200px; + background: #f8f8f8; +} + +.editinline-stacked .inline-splitter { + float: left; + width: 9px; + background: #f8f8f8 url(../img/admin/inline-splitter-bg.gif) 50% 50% no-repeat; + border-right: 1px solid #ccc; +} + +.editinline-stacked .controls { + clear: both; + background: #e1e1e1 url(../img/admin/nav-bg.gif) top left repeat-x; + padding: 3px 4px; + font-size: 11px; + border-top: 1px solid #ddd; +} + diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/arrow-down.gif Binary file web/static/admin/img/admin/arrow-down.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/arrow-up.gif Binary file web/static/admin/img/admin/arrow-up.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/changelist-bg.gif Binary file web/static/admin/img/admin/changelist-bg.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/changelist-bg_rtl.gif Binary file web/static/admin/img/admin/changelist-bg_rtl.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/chooser-bg.gif Binary file web/static/admin/img/admin/chooser-bg.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/chooser_stacked-bg.gif Binary file web/static/admin/img/admin/chooser_stacked-bg.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/default-bg-reverse.gif Binary file web/static/admin/img/admin/default-bg-reverse.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/default-bg.gif Binary file web/static/admin/img/admin/default-bg.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/deleted-overlay.gif Binary file web/static/admin/img/admin/deleted-overlay.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon-no.gif Binary file web/static/admin/img/admin/icon-no.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon-unknown.gif Binary file web/static/admin/img/admin/icon-unknown.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon-yes.gif Binary file web/static/admin/img/admin/icon-yes.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_addlink.gif Binary file web/static/admin/img/admin/icon_addlink.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_alert.gif Binary file web/static/admin/img/admin/icon_alert.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_calendar.gif Binary file web/static/admin/img/admin/icon_calendar.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_changelink.gif Binary file web/static/admin/img/admin/icon_changelink.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_clock.gif Binary file web/static/admin/img/admin/icon_clock.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_deletelink.gif Binary file web/static/admin/img/admin/icon_deletelink.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_error.gif Binary file web/static/admin/img/admin/icon_error.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_searchbox.png Binary file web/static/admin/img/admin/icon_searchbox.png has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/icon_success.gif Binary file web/static/admin/img/admin/icon_success.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/inline-delete-8bit.png Binary file web/static/admin/img/admin/inline-delete-8bit.png has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/inline-delete.png Binary file web/static/admin/img/admin/inline-delete.png has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/inline-restore-8bit.png Binary file web/static/admin/img/admin/inline-restore-8bit.png has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/inline-restore.png Binary file web/static/admin/img/admin/inline-restore.png has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/inline-splitter-bg.gif Binary file web/static/admin/img/admin/inline-splitter-bg.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/nav-bg-grabber.gif Binary file web/static/admin/img/admin/nav-bg-grabber.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/nav-bg-reverse.gif Binary file web/static/admin/img/admin/nav-bg-reverse.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/nav-bg.gif Binary file web/static/admin/img/admin/nav-bg.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/selector-add.gif Binary file web/static/admin/img/admin/selector-add.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/selector-addall.gif Binary file web/static/admin/img/admin/selector-addall.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/selector-remove.gif Binary file web/static/admin/img/admin/selector-remove.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/selector-removeall.gif Binary file web/static/admin/img/admin/selector-removeall.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/selector-search.gif Binary file web/static/admin/img/admin/selector-search.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/selector_stacked-add.gif Binary file web/static/admin/img/admin/selector_stacked-add.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/selector_stacked-remove.gif Binary file web/static/admin/img/admin/selector_stacked-remove.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tool-left.gif Binary file web/static/admin/img/admin/tool-left.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tool-left_over.gif Binary file web/static/admin/img/admin/tool-left_over.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tool-right.gif Binary file web/static/admin/img/admin/tool-right.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tool-right_over.gif Binary file web/static/admin/img/admin/tool-right_over.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tooltag-add.gif Binary file web/static/admin/img/admin/tooltag-add.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tooltag-add_over.gif Binary file web/static/admin/img/admin/tooltag-add_over.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tooltag-arrowright.gif Binary file web/static/admin/img/admin/tooltag-arrowright.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/admin/tooltag-arrowright_over.gif Binary file web/static/admin/img/admin/tooltag-arrowright_over.gif has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/gis/move_vertex_off.png Binary file web/static/admin/img/gis/move_vertex_off.png has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/img/gis/move_vertex_on.png Binary file web/static/admin/img/gis/move_vertex_on.png has changed diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/LICENSE-JQUERY.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/LICENSE-JQUERY.txt Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,20 @@ +Copyright (c) 2010 John Resig, http://jquery.com/ + +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 to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/SelectBox.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/SelectBox.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,111 @@ +var SelectBox = { + cache: new Object(), + init: function(id) { + var box = document.getElementById(id); + var node; + SelectBox.cache[id] = new Array(); + var cache = SelectBox.cache[id]; + for (var i = 0; (node = box.options[i]); i++) { + cache.push({value: node.value, text: node.text, displayed: 1}); + } + }, + redisplay: function(id) { + // Repopulate HTML select box from cache + var box = document.getElementById(id); + box.options.length = 0; // clear all options + for (var i = 0, j = SelectBox.cache[id].length; i < j; i++) { + var node = SelectBox.cache[id][i]; + if (node.displayed) { + box.options[box.options.length] = new Option(node.text, node.value, false, false); + } + } + }, + filter: function(id, text) { + // Redisplay the HTML select box, displaying only the choices containing ALL + // the words in text. (It's an AND search.) + var tokens = text.toLowerCase().split(/\s+/); + var node, token; + for (var i = 0; (node = SelectBox.cache[id][i]); i++) { + node.displayed = 1; + for (var j = 0; (token = tokens[j]); j++) { + if (node.text.toLowerCase().indexOf(token) == -1) { + node.displayed = 0; + } + } + } + SelectBox.redisplay(id); + }, + delete_from_cache: function(id, value) { + var node, delete_index = null; + for (var i = 0; (node = SelectBox.cache[id][i]); i++) { + if (node.value == value) { + delete_index = i; + break; + } + } + var j = SelectBox.cache[id].length - 1; + for (var i = delete_index; i < j; i++) { + SelectBox.cache[id][i] = SelectBox.cache[id][i+1]; + } + SelectBox.cache[id].length--; + }, + add_to_cache: function(id, option) { + SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1}); + }, + cache_contains: function(id, value) { + // Check if an item is contained in the cache + var node; + for (var i = 0; (node = SelectBox.cache[id][i]); i++) { + if (node.value == value) { + return true; + } + } + return false; + }, + move: function(from, to) { + var from_box = document.getElementById(from); + var to_box = document.getElementById(to); + var option; + for (var i = 0; (option = from_box.options[i]); i++) { + if (option.selected && SelectBox.cache_contains(from, option.value)) { + SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); + SelectBox.delete_from_cache(from, option.value); + } + } + SelectBox.redisplay(from); + SelectBox.redisplay(to); + }, + move_all: function(from, to) { + var from_box = document.getElementById(from); + var to_box = document.getElementById(to); + var option; + for (var i = 0; (option = from_box.options[i]); i++) { + if (SelectBox.cache_contains(from, option.value)) { + SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); + SelectBox.delete_from_cache(from, option.value); + } + } + SelectBox.redisplay(from); + SelectBox.redisplay(to); + }, + sort: function(id) { + SelectBox.cache[id].sort( function(a, b) { + a = a.text.toLowerCase(); + b = b.text.toLowerCase(); + try { + if (a > b) return 1; + if (a < b) return -1; + } + catch (e) { + // silently fail on IE 'unknown' exception + } + return 0; + } ); + }, + select_all: function(id) { + var box = document.getElementById(id); + for (var i = 0; i < box.options.length; i++) { + box.options[i].selected = 'selected'; + } + } +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/SelectFilter2.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/SelectFilter2.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,117 @@ +/* +SelectFilter2 - Turns a multiple-select box into a filter interface. + +Different than SelectFilter because this is coupled to the admin framework. + +Requires core.js, SelectBox.js and addevent.js. +*/ + +function findForm(node) { + // returns the node of the form containing the given node + if (node.tagName.toLowerCase() != 'form') { + return findForm(node.parentNode); + } + return node; +} + +var SelectFilter = { + init: function(field_id, field_name, is_stacked, admin_media_prefix) { + if (field_id.match(/__prefix__/)){ + // Don't intialize on empty forms. + return; + } + var from_box = document.getElementById(field_id); + from_box.id += '_from'; // change its ID + from_box.className = 'filtered'; + + // Remove

    , because it just gets in the way. + var ps = from_box.parentNode.getElementsByTagName('p'); + for (var i=0; i or

    + var selector_div = quickElement('div', from_box.parentNode); + selector_div.className = is_stacked ? 'selector stacked' : 'selector'; + + //
    + var selector_available = quickElement('div', selector_div, ''); + selector_available.className = 'selector-available'; + quickElement('h2', selector_available, interpolate(gettext('Available %s'), [field_name])); + var filter_p = quickElement('p', selector_available, ''); + filter_p.className = 'selector-filter'; + quickElement('img', filter_p, '', 'src', admin_media_prefix + 'img/admin/selector-search.gif'); + filter_p.appendChild(document.createTextNode(' ')); + var filter_input = quickElement('input', filter_p, '', 'type', 'text'); + filter_input.id = field_id + '_input'; + selector_available.appendChild(from_box); + var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'href', 'javascript: (function(){ SelectBox.move_all("' + field_id + '_from", "' + field_id + '_to"); })()'); + choose_all.className = 'selector-chooseall'; + + //
      + var selector_chooser = quickElement('ul', selector_div, ''); + selector_chooser.className = 'selector-chooser'; + var add_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Add'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_from","' + field_id + '_to");})()'); + add_link.className = 'selector-add'; + var remove_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Remove'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_to","' + field_id + '_from");})()'); + remove_link.className = 'selector-remove'; + + //
      + var selector_chosen = quickElement('div', selector_div, ''); + selector_chosen.className = 'selector-chosen'; + quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s'), [field_name])); + var selector_filter = quickElement('p', selector_chosen, gettext('Select your choice(s) and click ')); + selector_filter.className = 'selector-filter'; + quickElement('img', selector_filter, '', 'src', admin_media_prefix + (is_stacked ? 'img/admin/selector_stacked-add.gif':'img/admin/selector-add.gif'), 'alt', 'Add'); + var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name')); + to_box.className = 'filtered'; + var clear_all = quickElement('a', selector_chosen, gettext('Clear all'), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from");})()'); + clear_all.className = 'selector-clearall'; + + from_box.setAttribute('name', from_box.getAttribute('name') + '_old'); + + // Set up the JavaScript event handlers for the select box filter interface + addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); }); + addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); }); + addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); }); + addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); }); + addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); }); + SelectBox.init(field_id + '_from'); + SelectBox.init(field_id + '_to'); + // Move selected from_box options to to_box + SelectBox.move(field_id + '_from', field_id + '_to'); + }, + filter_key_up: function(event, field_id) { + from = document.getElementById(field_id + '_from'); + // don't submit form if user pressed Enter + if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) { + from.selectedIndex = 0; + SelectBox.move(field_id + '_from', field_id + '_to'); + from.selectedIndex = 0; + return false; + } + var temp = from.selectedIndex; + SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value); + from.selectedIndex = temp; + return true; + }, + filter_key_down: function(event, field_id) { + from = document.getElementById(field_id + '_from'); + // right arrow -- move across + if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) { + var old_index = from.selectedIndex; + SelectBox.move(field_id + '_from', field_id + '_to'); + from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index; + return false; + } + // down arrow -- wrap around + if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) { + from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1; + } + // up arrow -- wrap around + if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) { + from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1; + } + return true; + } +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/actions.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/actions.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,139 @@ +(function($) { + $.fn.actions = function(opts) { + var options = $.extend({}, $.fn.actions.defaults, opts); + var actionCheckboxes = $(this); + var list_editable_changed = false; + checker = function(checked) { + if (checked) { + showQuestion(); + } else { + reset(); + } + $(actionCheckboxes).attr("checked", checked) + .parent().parent().toggleClass(options.selectedClass, checked); + } + updateCounter = function() { + var sel = $(actionCheckboxes).filter(":checked").length; + $(options.counterContainer).html(interpolate( + ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { + sel: sel, + cnt: _actions_icnt + }, true)); + $(options.allToggle).attr("checked", function() { + if (sel == actionCheckboxes.length) { + value = true; + showQuestion(); + } else { + value = false; + clearAcross(); + } + return value; + }); + } + showQuestion = function() { + $(options.acrossClears).hide(); + $(options.acrossQuestions).show(); + $(options.allContainer).hide(); + } + showClear = function() { + $(options.acrossClears).show(); + $(options.acrossQuestions).hide(); + $(options.actionContainer).toggleClass(options.selectedClass); + $(options.allContainer).show(); + $(options.counterContainer).hide(); + } + reset = function() { + $(options.acrossClears).hide(); + $(options.acrossQuestions).hide(); + $(options.allContainer).hide(); + $(options.counterContainer).show(); + } + clearAcross = function() { + reset(); + $(options.acrossInput).val(0); + $(options.actionContainer).removeClass(options.selectedClass); + } + // Show counter by default + $(options.counterContainer).show(); + // Check state of checkboxes and reinit state if needed + $(this).filter(":checked").each(function(i) { + $(this).parent().parent().toggleClass(options.selectedClass); + updateCounter(); + if ($(options.acrossInput).val() == 1) { + showClear(); + } + }); + $(options.allToggle).show().click(function() { + checker($(this).attr("checked")); + updateCounter(); + }); + $("div.actions span.question a").click(function(event) { + event.preventDefault(); + $(options.acrossInput).val(1); + showClear(); + }); + $("div.actions span.clear a").click(function(event) { + event.preventDefault(); + $(options.allToggle).attr("checked", false); + clearAcross(); + checker(0); + updateCounter(); + }); + lastChecked = null; + $(actionCheckboxes).click(function(event) { + if (!event) { var event = window.event; } + var target = event.target ? event.target : event.srcElement; + if (lastChecked && $.data(lastChecked) != $.data(target) && event.shiftKey == true) { + var inrange = false; + $(lastChecked).attr("checked", target.checked) + .parent().parent().toggleClass(options.selectedClass, target.checked); + $(actionCheckboxes).each(function() { + if ($.data(this) == $.data(lastChecked) || $.data(this) == $.data(target)) { + inrange = (inrange) ? false : true; + } + if (inrange) { + $(this).attr("checked", target.checked) + .parent().parent().toggleClass(options.selectedClass, target.checked); + } + }); + } + $(target).parent().parent().toggleClass(options.selectedClass, target.checked); + lastChecked = target; + updateCounter(); + }); + $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() { + list_editable_changed = true; + }); + $('form#changelist-form button[name="index"]').click(function(event) { + if (list_editable_changed) { + return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); + } + }); + $('form#changelist-form input[name="_save"]').click(function(event) { + var action_changed = false; + $('div.actions select option:selected').each(function() { + if ($(this).val()) { + action_changed = true; + } + }); + if (action_changed) { + if (list_editable_changed) { + return confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")); + } else { + return confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.")); + } + } + }); + } + /* Setup plugin defaults */ + $.fn.actions.defaults = { + actionContainer: "div.actions", + counterContainer: "span.action-counter", + allContainer: "div.actions span.all", + acrossInput: "div.actions input.select-across", + acrossQuestions: "div.actions span.question", + acrossClears: "div.actions span.clear", + allToggle: "#action-toggle", + selectedClass: "selected" + } +})(django.jQuery); diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/actions.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/actions.min.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,7 @@ +(function(a){a.fn.actions=function(h){var b=a.extend({},a.fn.actions.defaults,h),e=a(this),f=false;checker=function(c){c?showQuestion():reset();a(e).attr("checked",c).parent().parent().toggleClass(b.selectedClass,c)};updateCounter=function(){var c=a(e).filter(":checked").length;a(b.counterContainer).html(interpolate(ngettext("%(sel)s of %(cnt)s selected","%(sel)s of %(cnt)s selected",c),{sel:c,cnt:_actions_icnt},true));a(b.allToggle).attr("checked",function(){if(c==e.length){value=true;showQuestion()}else{value= +false;clearAcross()}return value})};showQuestion=function(){a(b.acrossClears).hide();a(b.acrossQuestions).show();a(b.allContainer).hide()};showClear=function(){a(b.acrossClears).show();a(b.acrossQuestions).hide();a(b.actionContainer).toggleClass(b.selectedClass);a(b.allContainer).show();a(b.counterContainer).hide()};reset=function(){a(b.acrossClears).hide();a(b.acrossQuestions).hide();a(b.allContainer).hide();a(b.counterContainer).show()};clearAcross=function(){reset();a(b.acrossInput).val(0);a(b.actionContainer).removeClass(b.selectedClass)}; +a(b.counterContainer).show();a(this).filter(":checked").each(function(){a(this).parent().parent().toggleClass(b.selectedClass);updateCounter();a(b.acrossInput).val()==1&&showClear()});a(b.allToggle).show().click(function(){checker(a(this).attr("checked"));updateCounter()});a("div.actions span.question a").click(function(c){c.preventDefault();a(b.acrossInput).val(1);showClear()});a("div.actions span.clear a").click(function(c){c.preventDefault();a(b.allToggle).attr("checked",false);clearAcross();checker(0); +updateCounter()});lastChecked=null;a(e).click(function(c){if(!c)c=window.event;var d=c.target?c.target:c.srcElement;if(lastChecked&&a.data(lastChecked)!=a.data(d)&&c.shiftKey==true){var g=false;a(lastChecked).attr("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked);a(e).each(function(){if(a.data(this)==a.data(lastChecked)||a.data(this)==a.data(d))g=g?false:true;g&&a(this).attr("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked)})}a(d).parent().parent().toggleClass(b.selectedClass, +d.checked);lastChecked=d;updateCounter()});a("form#changelist-form table#result_list tr").find("td:gt(0) :input").change(function(){f=true});a('form#changelist-form button[name="index"]').click(function(){if(f)return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."))});a('form#changelist-form input[name="_save"]').click(function(){var c=false;a("div.actions select option:selected").each(function(){if(a(this).val())c= +true});if(c)return f?confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")):confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."))})};a.fn.actions.defaults={actionContainer:"div.actions",counterContainer:"span.action-counter",allContainer:"div.actions span.all",acrossInput:"div.actions input.select-across", +acrossQuestions:"div.actions span.question",acrossClears:"div.actions span.clear",allToggle:"#action-toggle",selectedClass:"selected"}})(django.jQuery); diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/admin/DateTimeShortcuts.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/admin/DateTimeShortcuts.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,274 @@ +// Inserts shortcut buttons after all of the following: +// +// + +var DateTimeShortcuts = { + calendars: [], + calendarInputs: [], + clockInputs: [], + calendarDivName1: 'calendarbox', // name of calendar
      that gets toggled + calendarDivName2: 'calendarin', // name of
      that contains calendar + calendarLinkName: 'calendarlink',// name of the link that is used to toggle + clockDivName: 'clockbox', // name of clock
      that gets toggled + clockLinkName: 'clocklink', // name of the link that is used to toggle + shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts + admin_media_prefix: '', + init: function() { + // Get admin_media_prefix by grabbing it off the window object. It's + // set in the admin/base.html template, so if it's not there, someone's + // overridden the template. In that case, we'll set a clearly-invalid + // value in the hopes that someone will examine HTTP requests and see it. + if (window.__admin_media_prefix__ != undefined) { + DateTimeShortcuts.admin_media_prefix = window.__admin_media_prefix__; + } else { + DateTimeShortcuts.admin_media_prefix = '/missing-admin-media-prefix/'; + } + + var inputs = document.getElementsByTagName('input'); + for (i=0; i + //

      Choose a time

      + // + //

      Cancel

      + //
      + + var clock_box = document.createElement('div'); + clock_box.style.display = 'none'; + clock_box.style.position = 'absolute'; + clock_box.className = 'clockbox module'; + clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num); + document.body.appendChild(clock_box); + addEvent(clock_box, 'click', DateTimeShortcuts.cancelEventPropagation); + + quickElement('h2', clock_box, gettext('Choose a time')); + time_list = quickElement('ul', clock_box, ''); + time_list.className = 'timelist'; + time_format = get_format('TIME_INPUT_FORMATS')[0]; + quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().strftime('" + time_format + "'));"); + quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,0,0,0,0).strftime('" + time_format + "'));"); + quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,6,0,0,0).strftime('" + time_format + "'));"); + quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,12,0,0,0).strftime('" + time_format + "'));"); + + cancel_p = quickElement('p', clock_box, ''); + cancel_p.className = 'calendar-cancel'; + quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');'); + }, + openClock: function(num) { + var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num) + var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num) + + // Recalculate the clockbox position + // is it left-to-right or right-to-left layout ? + if (getStyle(document.body,'direction')!='rtl') { + clock_box.style.left = findPosX(clock_link) + 17 + 'px'; + } + else { + // since style's width is in em, it'd be tough to calculate + // px value of it. let's use an estimated px for now + // TODO: IE returns wrong value for findPosX when in rtl mode + // (it returns as it was left aligned), needs to be fixed. + clock_box.style.left = findPosX(clock_link) - 110 + 'px'; + } + clock_box.style.top = findPosY(clock_link) - 30 + 'px'; + + // Show the clock box + clock_box.style.display = 'block'; + addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; }); + }, + dismissClock: function(num) { + document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none'; + window.document.onclick = null; + }, + handleClockQuicklink: function(num, val) { + DateTimeShortcuts.clockInputs[num].value = val; + DateTimeShortcuts.clockInputs[num].focus(); + DateTimeShortcuts.dismissClock(num); + }, + // Add calendar widget to a given field. + addCalendar: function(inp) { + var num = DateTimeShortcuts.calendars.length; + + DateTimeShortcuts.calendarInputs[num] = inp; + + // Shortcut links (calendar icon and "Today" link) + var shortcuts_span = document.createElement('span'); + shortcuts_span.className = DateTimeShortcuts.shortCutsClass; + inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); + var today_link = document.createElement('a'); + today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);'); + today_link.appendChild(document.createTextNode(gettext('Today'))); + var cal_link = document.createElement('a'); + cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');'); + cal_link.id = DateTimeShortcuts.calendarLinkName + num; + quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar')); + shortcuts_span.appendChild(document.createTextNode('\240')); + shortcuts_span.appendChild(today_link); + shortcuts_span.appendChild(document.createTextNode('\240|\240')); + shortcuts_span.appendChild(cal_link); + + // Create calendarbox div. + // + // Markup looks like: + // + //
      + //

      + // + // February 2003 + //

      + //
      + // + //
      + //
      + // Yesterday | Today | Tomorrow + //
      + //

      Cancel

      + //
      + var cal_box = document.createElement('div'); + cal_box.style.display = 'none'; + cal_box.style.position = 'absolute'; + cal_box.className = 'calendarbox module'; + cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num); + document.body.appendChild(cal_box); + addEvent(cal_box, 'click', DateTimeShortcuts.cancelEventPropagation); + + // next-prev links + var cal_nav = quickElement('div', cal_box, ''); + var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');'); + cal_nav_prev.className = 'calendarnav-previous'; + var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');'); + cal_nav_next.className = 'calendarnav-next'; + + // main box + var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num); + cal_main.className = 'calendar'; + DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num)); + DateTimeShortcuts.calendars[num].drawCurrent(); + + // calendar shortcuts + var shortcuts = quickElement('div', cal_box, ''); + shortcuts.className = 'calendar-shortcuts'; + quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);'); + shortcuts.appendChild(document.createTextNode('\240|\240')); + quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);'); + shortcuts.appendChild(document.createTextNode('\240|\240')); + quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);'); + + // cancel bar + var cancel_p = quickElement('p', cal_box, ''); + cancel_p.className = 'calendar-cancel'; + quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');'); + }, + openCalendar: function(num) { + var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num) + var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num) + var inp = DateTimeShortcuts.calendarInputs[num]; + + // Determine if the current value in the input has a valid date. + // If so, draw the calendar with that date's year and month. + if (inp.value) { + var date_parts = inp.value.split('-'); + var year = date_parts[0]; + var month = parseFloat(date_parts[1]); + if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) { + DateTimeShortcuts.calendars[num].drawDate(month, year); + } + } + + // Recalculate the clockbox position + // is it left-to-right or right-to-left layout ? + if (getStyle(document.body,'direction')!='rtl') { + cal_box.style.left = findPosX(cal_link) + 17 + 'px'; + } + else { + // since style's width is in em, it'd be tough to calculate + // px value of it. let's use an estimated px for now + // TODO: IE returns wrong value for findPosX when in rtl mode + // (it returns as it was left aligned), needs to be fixed. + cal_box.style.left = findPosX(cal_link) - 180 + 'px'; + } + cal_box.style.top = findPosY(cal_link) - 75 + 'px'; + + cal_box.style.display = 'block'; + addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; }); + }, + dismissCalendar: function(num) { + document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none'; + window.document.onclick = null; + }, + drawPrev: function(num) { + DateTimeShortcuts.calendars[num].drawPreviousMonth(); + }, + drawNext: function(num) { + DateTimeShortcuts.calendars[num].drawNextMonth(); + }, + handleCalendarCallback: function(num) { + format = get_format('DATE_INPUT_FORMATS')[0]; + // the format needs to be escaped a little + format = format.replace('\\', '\\\\'); + format = format.replace('\r', '\\r'); + format = format.replace('\n', '\\n'); + format = format.replace('\t', '\\t'); + format = format.replace("'", "\\'"); + return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[", + num, + "].value = new Date(y, m-1, d).strftime('", + format, + "');DateTimeShortcuts.calendarInputs[", + num, + "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+", + num, + ").style.display='none';}"].join(''); + }, + handleCalendarQuickLink: function(num, offset) { + var d = new Date(); + d.setDate(d.getDate() + offset) + DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]); + DateTimeShortcuts.calendarInputs[num].focus(); + DateTimeShortcuts.dismissCalendar(num); + }, + cancelEventPropagation: function(e) { + if (!e) e = window.event; + e.cancelBubble = true; + if (e.stopPropagation) e.stopPropagation(); + } +} + +addEvent(window, 'load', DateTimeShortcuts.init); diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/admin/RelatedObjectLookups.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/admin/RelatedObjectLookups.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,96 @@ +// Handles related-objects functionality: lookup link for raw_id_fields +// and Add Another links. + +function html_unescape(text) { + // Unescape a string that was escaped using django.utils.html.escape. + text = text.replace(/</g, '<'); + text = text.replace(/>/g, '>'); + text = text.replace(/"/g, '"'); + text = text.replace(/'/g, "'"); + text = text.replace(/&/g, '&'); + return text; +} + +// IE doesn't accept periods or dashes in the window name, but the element IDs +// we use to generate popup window names may contain them, therefore we map them +// to allowed characters in a reversible way so that we can locate the correct +// element when the popup window is dismissed. +function id_to_windowname(text) { + text = text.replace(/\./g, '__dot__'); + text = text.replace(/\-/g, '__dash__'); + return text; +} + +function windowname_to_id(text) { + text = text.replace(/__dot__/g, '.'); + text = text.replace(/__dash__/g, '-'); + return text; +} + +function showRelatedObjectLookupPopup(triggeringLink) { + var name = triggeringLink.id.replace(/^lookup_/, ''); + name = id_to_windowname(name); + var href; + if (triggeringLink.href.search(/\?/) >= 0) { + href = triggeringLink.href + '&pop=1'; + } else { + href = triggeringLink.href + '?pop=1'; + } + var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); + win.focus(); + return false; +} + +function dismissRelatedLookupPopup(win, chosenId) { + var name = windowname_to_id(win.name); + var elem = document.getElementById(name); + if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { + elem.value += ',' + chosenId; + } else { + document.getElementById(name).value = chosenId; + } + win.close(); +} + +function showAddAnotherPopup(triggeringLink) { + var name = triggeringLink.id.replace(/^add_/, ''); + name = id_to_windowname(name); + href = triggeringLink.href + if (href.indexOf('?') == -1) { + href += '?_popup=1'; + } else { + href += '&_popup=1'; + } + var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); + win.focus(); + return false; +} + +function dismissAddAnotherPopup(win, newId, newRepr) { + // newId and newRepr are expected to have previously been escaped by + // django.utils.html.escape. + newId = html_unescape(newId); + newRepr = html_unescape(newRepr); + var name = windowname_to_id(win.name); + var elem = document.getElementById(name); + if (elem) { + if (elem.nodeName == 'SELECT') { + var o = new Option(newRepr, newId); + elem.options[elem.options.length] = o; + o.selected = true; + } else if (elem.nodeName == 'INPUT') { + if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { + elem.value += ',' + newId; + } else { + elem.value = newId; + } + } + } else { + var toId = name + "_to"; + elem = document.getElementById(toId); + var o = new Option(newRepr, newId); + SelectBox.add_to_cache(toId, o); + SelectBox.redisplay(toId); + } + win.close(); +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/admin/ordering.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/admin/ordering.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,137 @@ +addEvent(window, 'load', reorder_init); + +var lis; +var top = 0; +var left = 0; +var height = 30; + +function reorder_init() { + lis = document.getElementsBySelector('ul#orderthese li'); + var input = document.getElementsBySelector('input[name=order_]')[0]; + setOrder(input.value.split(',')); + input.disabled = true; + draw(); + // Now initialise the dragging behaviour + var limit = (lis.length - 1) * height; + for (var i = 0; i < lis.length; i++) { + var li = lis[i]; + var img = document.getElementById('handle'+li.id); + li.style.zIndex = 1; + Drag.init(img, li, left + 10, left + 10, top + 10, top + 10 + limit); + li.onDragStart = startDrag; + li.onDragEnd = endDrag; + img.style.cursor = 'move'; + } +} + +function submitOrderForm() { + var inputOrder = document.getElementsBySelector('input[name=order_]')[0]; + inputOrder.value = getOrder(); + inputOrder.disabled=false; +} + +function startDrag() { + this.style.zIndex = '10'; + this.className = 'dragging'; +} + +function endDrag(x, y) { + this.style.zIndex = '1'; + this.className = ''; + // Work out how far along it has been dropped, using x co-ordinate + var oldIndex = this.index; + var newIndex = Math.round((y - 10 - top) / height); + // 'Snap' to the correct position + this.style.top = (10 + top + newIndex * height) + 'px'; + this.index = newIndex; + moveItem(oldIndex, newIndex); +} + +function moveItem(oldIndex, newIndex) { + // Swaps two items, adjusts the index and left co-ord for all others + if (oldIndex == newIndex) { + return; // Nothing to swap; + } + var direction, lo, hi; + if (newIndex > oldIndex) { + lo = oldIndex; + hi = newIndex; + direction = -1; + } else { + direction = 1; + hi = oldIndex; + lo = newIndex; + } + var lis2 = new Array(); // We will build the new order in this array + for (var i = 0; i < lis.length; i++) { + if (i < lo || i > hi) { + // Position of items not between the indexes is unaffected + lis2[i] = lis[i]; + continue; + } else if (i == newIndex) { + lis2[i] = lis[oldIndex]; + continue; + } else { + // Item is between the two indexes - move it along 1 + lis2[i] = lis[i - direction]; + } + } + // Re-index everything + reIndex(lis2); + lis = lis2; + draw(); +// document.getElementById('hiddenOrder').value = getOrder(); + document.getElementsBySelector('input[name=order_]')[0].value = getOrder(); +} + +function reIndex(lis) { + for (var i = 0; i < lis.length; i++) { + lis[i].index = i; + } +} + +function draw() { + for (var i = 0; i < lis.length; i++) { + var li = lis[i]; + li.index = i; + li.style.position = 'absolute'; + li.style.left = (10 + left) + 'px'; + li.style.top = (10 + top + (i * height)) + 'px'; + } +} + +function getOrder() { + var order = new Array(lis.length); + for (var i = 0; i < lis.length; i++) { + order[i] = lis[i].id.substring(1, 100); + } + return order.join(','); +} + +function setOrder(id_list) { + /* Set the current order to match the lsit of IDs */ + var temp_lis = new Array(); + for (var i = 0; i < id_list.length; i++) { + var id = 'p' + id_list[i]; + temp_lis[temp_lis.length] = document.getElementById(id); + } + reIndex(temp_lis); + lis = temp_lis; + draw(); +} + +function addEvent(elm, evType, fn, useCapture) +// addEvent and removeEvent +// cross-browser event handling for IE5+, NS6 and Mozilla +// By Scott Andrew +{ + if (elm.addEventListener){ + elm.addEventListener(evType, fn, useCapture); + return true; + } else if (elm.attachEvent){ + var r = elm.attachEvent("on"+evType, fn); + return r; + } else { + elm['on'+evType] = fn; + } +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/calendar.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/calendar.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,156 @@ +/* +calendar.js - Calendar functions by Adrian Holovaty +*/ + +function removeChildren(a) { // "a" is reference to an object + while (a.hasChildNodes()) a.removeChild(a.lastChild); +} + +// quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]); +function quickElement() { + var obj = document.createElement(arguments[0]); + if (arguments[2] != '' && arguments[2] != null) { + var textNode = document.createTextNode(arguments[2]); + obj.appendChild(textNode); + } + var len = arguments.length; + for (var i = 3; i < len; i += 2) { + obj.setAttribute(arguments[i], arguments[i+1]); + } + arguments[1].appendChild(obj); + return obj; +} + +// CalendarNamespace -- Provides a collection of HTML calendar-related helper functions +var CalendarNamespace = { + monthsOfYear: gettext('January February March April May June July August September October November December').split(' '), + daysOfWeek: gettext('S M T W T F S').split(' '), + firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')), + isLeapYear: function(year) { + return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0)); + }, + getDaysInMonth: function(month,year) { + var days; + if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) { + days = 31; + } + else if (month==4 || month==6 || month==9 || month==11) { + days = 30; + } + else if (month==2 && CalendarNamespace.isLeapYear(year)) { + days = 29; + } + else { + days = 28; + } + return days; + }, + draw: function(month, year, div_id, callback) { // month = 1-12, year = 1-9999 + var today = new Date(); + var todayDay = today.getDate(); + var todayMonth = today.getMonth()+1; + var todayYear = today.getFullYear(); + var todayClass = ''; + + month = parseInt(month); + year = parseInt(year); + var calDiv = document.getElementById(div_id); + removeChildren(calDiv); + var calTable = document.createElement('table'); + quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month-1] + ' ' + year); + var tableBody = quickElement('tbody', calTable); + + // Draw days-of-week header + var tableRow = quickElement('tr', tableBody); + for (var i = 0; i < 7; i++) { + quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]); + } + + var startingPos = new Date(year, month-1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); + var days = CalendarNamespace.getDaysInMonth(month, year); + + // Draw blanks before first of month + tableRow = quickElement('tr', tableBody); + for (var i = 0; i < startingPos; i++) { + var _cell = quickElement('td', tableRow, ' '); + _cell.style.backgroundColor = '#f3f3f3'; + } + + // Draw days of month + var currentDay = 1; + for (var i = startingPos; currentDay <= days; i++) { + if (i%7 == 0 && currentDay != 1) { + tableRow = quickElement('tr', tableBody); + } + if ((currentDay==todayDay) && (month==todayMonth) && (year==todayYear)) { + todayClass='today'; + } else { + todayClass=''; + } + var cell = quickElement('td', tableRow, '', 'class', todayClass); + + quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '('+year+','+month+','+currentDay+'));'); + currentDay++; + } + + // Draw blanks after end of month (optional, but makes for valid code) + while (tableRow.childNodes.length < 7) { + var _cell = quickElement('td', tableRow, ' '); + _cell.style.backgroundColor = '#f3f3f3'; + } + + calDiv.appendChild(calTable); + } +} + +// Calendar -- A calendar instance +function Calendar(div_id, callback) { + // div_id (string) is the ID of the element in which the calendar will + // be displayed + // callback (string) is the name of a JavaScript function that will be + // called with the parameters (year, month, day) when a day in the + // calendar is clicked + this.div_id = div_id; + this.callback = callback; + this.today = new Date(); + this.currentMonth = this.today.getMonth() + 1; + this.currentYear = this.today.getFullYear(); +} +Calendar.prototype = { + drawCurrent: function() { + CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback); + }, + drawDate: function(month, year) { + this.currentMonth = month; + this.currentYear = year; + this.drawCurrent(); + }, + drawPreviousMonth: function() { + if (this.currentMonth == 1) { + this.currentMonth = 12; + this.currentYear--; + } + else { + this.currentMonth--; + } + this.drawCurrent(); + }, + drawNextMonth: function() { + if (this.currentMonth == 12) { + this.currentMonth = 1; + this.currentYear++; + } + else { + this.currentMonth++; + } + this.drawCurrent(); + }, + drawPreviousYear: function() { + this.currentYear--; + this.drawCurrent(); + }, + drawNextYear: function() { + this.currentYear++; + this.drawCurrent(); + } +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/collapse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/collapse.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,27 @@ +(function($) { + $(document).ready(function() { + // Add anchor tag for Show/Hide link + $("fieldset.collapse").each(function(i, elem) { + // Don't hide if fields in this fieldset have errors + if ( $(elem).find("div.errors").length == 0 ) { + $(elem).addClass("collapsed"); + $(elem).find("h2").first().append(' (' + gettext("Show") + + ')'); + } + }); + // Add toggle to anchor tag + $("fieldset.collapse a.collapse-toggle").toggle( + function() { // Show + $(this).text(gettext("Hide")); + $(this).closest("fieldset").removeClass("collapsed"); + return false; + }, + function() { // Hide + $(this).text(gettext("Show")); + $(this).closest("fieldset").addClass("collapsed"); + return false; + } + ); + }); +})(django.jQuery); diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/collapse.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/collapse.min.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,2 @@ +(function(a){a(document).ready(function(){a("fieldset.collapse").each(function(c,b){if(a(b).find("div.errors").length==0){a(b).addClass("collapsed");a(b).find("h2").first().append(' ('+gettext("Show")+")")}});a("fieldset.collapse a.collapse-toggle").toggle(function(){a(this).text(gettext("Hide"));a(this).closest("fieldset").removeClass("collapsed");return false},function(){a(this).text(gettext("Show"));a(this).closest("fieldset").addClass("collapsed"); +return false})})})(django.jQuery); diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/compress.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/compress.py Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,47 @@ +#!/usr/bin/env python +import os +import optparse +import subprocess +import sys + +here = os.path.dirname(__file__) + +def main(): + usage = "usage: %prog [file1..fileN]" + description = """With no file paths given this script will automatically +compress all jQuery-based files of the admin app. Requires the Google Closure +Compiler library and Java version 6 or later.""" + parser = optparse.OptionParser(usage, description=description) + parser.add_option("-c", dest="compiler", default="~/bin/compiler.jar", + help="path to Closure Compiler jar file") + parser.add_option("-v", "--verbose", + action="store_true", dest="verbose") + parser.add_option("-q", "--quiet", + action="store_false", dest="verbose") + (options, args) = parser.parse_args() + + compiler = os.path.expanduser(options.compiler) + if not os.path.exists(compiler): + sys.exit("Google Closure compiler jar file %s not found. Please use the -c option to specify the path." % compiler) + + if not args: + if options.verbose: + sys.stdout.write("No filenames given; defaulting to admin scripts\n") + args = [os.path.join(here, f) for f in [ + "actions.js", "collapse.js", "inlines.js", "prepopulate.js"]] + + for arg in args: + if not arg.endswith(".js"): + arg = arg + ".js" + to_compress = os.path.expanduser(arg) + if os.path.exists(to_compress): + to_compress_min = "%s.min.js" % "".join(arg.rsplit(".js")) + cmd = "java -jar %s --js %s --js_output_file %s" % (compiler, to_compress, to_compress_min) + if options.verbose: + sys.stdout.write("Running: %s\n" % cmd) + subprocess.call(cmd.split()) + else: + sys.stdout.write("File %s not found. Sure it exists?\n" % to_compress) + +if __name__ == '__main__': + main() diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/core.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/core.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,221 @@ +// Core javascript helper functions + +// basic browser identification & version +var isOpera = (navigator.userAgent.indexOf("Opera")>=0) && parseFloat(navigator.appVersion); +var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]); + +// Cross-browser event handlers. +function addEvent(obj, evType, fn) { + if (obj.addEventListener) { + obj.addEventListener(evType, fn, false); + return true; + } else if (obj.attachEvent) { + var r = obj.attachEvent("on" + evType, fn); + return r; + } else { + return false; + } +} + +function removeEvent(obj, evType, fn) { + if (obj.removeEventListener) { + obj.removeEventListener(evType, fn, false); + return true; + } else if (obj.detachEvent) { + obj.detachEvent("on" + evType, fn); + return true; + } else { + return false; + } +} + +// quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]); +function quickElement() { + var obj = document.createElement(arguments[0]); + if (arguments[2] != '' && arguments[2] != null) { + var textNode = document.createTextNode(arguments[2]); + obj.appendChild(textNode); + } + var len = arguments.length; + for (var i = 3; i < len; i += 2) { + obj.setAttribute(arguments[i], arguments[i+1]); + } + arguments[1].appendChild(obj); + return obj; +} + +// ---------------------------------------------------------------------------- +// Cross-browser xmlhttp object +// from http://jibbering.com/2002/4/httprequest.html +// ---------------------------------------------------------------------------- +var xmlhttp; +/*@cc_on @*/ +/*@if (@_jscript_version >= 5) + try { + xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); + } catch (e) { + try { + xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); + } catch (E) { + xmlhttp = false; + } + } +@else + xmlhttp = false; +@end @*/ +if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { + xmlhttp = new XMLHttpRequest(); +} + +// ---------------------------------------------------------------------------- +// Find-position functions by PPK +// See http://www.quirksmode.org/js/findpos.html +// ---------------------------------------------------------------------------- +function findPosX(obj) { + var curleft = 0; + if (obj.offsetParent) { + while (obj.offsetParent) { + curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft); + obj = obj.offsetParent; + } + // IE offsetParent does not include the top-level + if (isIE && obj.parentElement){ + curleft += obj.offsetLeft - obj.scrollLeft; + } + } else if (obj.x) { + curleft += obj.x; + } + return curleft; +} + +function findPosY(obj) { + var curtop = 0; + if (obj.offsetParent) { + while (obj.offsetParent) { + curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop); + obj = obj.offsetParent; + } + // IE offsetParent does not include the top-level + if (isIE && obj.parentElement){ + curtop += obj.offsetTop - obj.scrollTop; + } + } else if (obj.y) { + curtop += obj.y; + } + return curtop; +} + +//----------------------------------------------------------------------------- +// Date object extensions +// ---------------------------------------------------------------------------- +Date.prototype.getCorrectYear = function() { + // Date.getYear() is unreliable -- + // see http://www.quirksmode.org/js/introdate.html#year + var y = this.getYear() % 100; + return (y < 38) ? y + 2000 : y + 1900; +} + +Date.prototype.getTwelveHours = function() { + hours = this.getHours(); + if (hours == 0) { + return 12; + } + else { + return hours <= 12 ? hours : hours-12 + } +} + +Date.prototype.getTwoDigitMonth = function() { + return (this.getMonth() < 9) ? '0' + (this.getMonth()+1) : (this.getMonth()+1); +} + +Date.prototype.getTwoDigitDate = function() { + return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate(); +} + +Date.prototype.getTwoDigitTwelveHour = function() { + return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours(); +} + +Date.prototype.getTwoDigitHour = function() { + return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours(); +} + +Date.prototype.getTwoDigitMinute = function() { + return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes(); +} + +Date.prototype.getTwoDigitSecond = function() { + return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds(); +} + +Date.prototype.getISODate = function() { + return this.getCorrectYear() + '-' + this.getTwoDigitMonth() + '-' + this.getTwoDigitDate(); +} + +Date.prototype.getHourMinute = function() { + return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute(); +} + +Date.prototype.getHourMinuteSecond = function() { + return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond(); +} + +Date.prototype.strftime = function(format) { + var fields = { + c: this.toString(), + d: this.getTwoDigitDate(), + H: this.getTwoDigitHour(), + I: this.getTwoDigitTwelveHour(), + m: this.getTwoDigitMonth(), + M: this.getTwoDigitMinute(), + p: (this.getHours() >= 12) ? 'PM' : 'AM', + S: this.getTwoDigitSecond(), + w: '0' + this.getDay(), + x: this.toLocaleDateString(), + X: this.toLocaleTimeString(), + y: ('' + this.getFullYear()).substr(2, 4), + Y: '' + this.getFullYear(), + '%' : '%' + }; + var result = '', i = 0; + while (i < format.length) { + if (format.charAt(i) === '%') { + result = result + fields[format.charAt(i + 1)]; + ++i; + } + else { + result = result + format.charAt(i); + } + ++i; + } + return result; +} + +// ---------------------------------------------------------------------------- +// String object extensions +// ---------------------------------------------------------------------------- +String.prototype.pad_left = function(pad_length, pad_string) { + var new_string = this; + for (var i = 0; new_string.length < pad_length; i++) { + new_string = pad_string + new_string; + } + return new_string; +} + +// ---------------------------------------------------------------------------- +// Get the computed style for and element +// ---------------------------------------------------------------------------- +function getStyle(oElm, strCssRule){ + var strValue = ""; + if(document.defaultView && document.defaultView.getComputedStyle){ + strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule); + } + else if(oElm.currentStyle){ + strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){ + return p1.toUpperCase(); + }); + strValue = oElm.currentStyle[strCssRule]; + } + return strValue; +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/dateparse.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/dateparse.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,233 @@ +/* 'Magic' date parsing, by Simon Willison (6th October 2003) + http://simon.incutio.com/archive/2003/10/06/betterDateInput + Adapted for 6newslawrence.com, 28th January 2004 +*/ + +/* Finds the index of the first occurence of item in the array, or -1 if not found */ +if (typeof Array.prototype.indexOf == 'undefined') { + Array.prototype.indexOf = function(item) { + var len = this.length; + for (var i = 0; i < len; i++) { + if (this[i] == item) { + return i; + } + } + return -1; + }; +} +/* Returns an array of items judged 'true' by the passed in test function */ +if (typeof Array.prototype.filter == 'undefined') { + Array.prototype.filter = function(test) { + var matches = []; + var len = this.length; + for (var i = 0; i < len; i++) { + if (test(this[i])) { + matches[matches.length] = this[i]; + } + } + return matches; + }; +} + +var monthNames = gettext("January February March April May June July August September October November December").split(" "); +var weekdayNames = gettext("Sunday Monday Tuesday Wednesday Thursday Friday Saturday").split(" "); + +/* Takes a string, returns the index of the month matching that string, throws + an error if 0 or more than 1 matches +*/ +function parseMonth(month) { + var matches = monthNames.filter(function(item) { + return new RegExp("^" + month, "i").test(item); + }); + if (matches.length == 0) { + throw new Error("Invalid month string"); + } + if (matches.length > 1) { + throw new Error("Ambiguous month"); + } + return monthNames.indexOf(matches[0]); +} +/* Same as parseMonth but for days of the week */ +function parseWeekday(weekday) { + var matches = weekdayNames.filter(function(item) { + return new RegExp("^" + weekday, "i").test(item); + }); + if (matches.length == 0) { + throw new Error("Invalid day string"); + } + if (matches.length > 1) { + throw new Error("Ambiguous weekday"); + } + return weekdayNames.indexOf(matches[0]); +} + +/* Array of objects, each has 're', a regular expression and 'handler', a + function for creating a date from something that matches the regular + expression. Handlers may throw errors if string is unparseable. +*/ +var dateParsePatterns = [ + // Today + { re: /^tod/i, + handler: function() { + return new Date(); + } + }, + // Tomorrow + { re: /^tom/i, + handler: function() { + var d = new Date(); + d.setDate(d.getDate() + 1); + return d; + } + }, + // Yesterday + { re: /^yes/i, + handler: function() { + var d = new Date(); + d.setDate(d.getDate() - 1); + return d; + } + }, + // 4th + { re: /^(\d{1,2})(st|nd|rd|th)?$/i, + handler: function(bits) { + var d = new Date(); + d.setDate(parseInt(bits[1], 10)); + return d; + } + }, + // 4th Jan + { re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i, + handler: function(bits) { + var d = new Date(); + d.setDate(parseInt(bits[1], 10)); + d.setMonth(parseMonth(bits[2])); + return d; + } + }, + // 4th Jan 2003 + { re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i, + handler: function(bits) { + var d = new Date(); + d.setDate(parseInt(bits[1], 10)); + d.setMonth(parseMonth(bits[2])); + d.setYear(bits[3]); + return d; + } + }, + // Jan 4th + { re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i, + handler: function(bits) { + var d = new Date(); + d.setDate(parseInt(bits[2], 10)); + d.setMonth(parseMonth(bits[1])); + return d; + } + }, + // Jan 4th 2003 + { re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?,? (\d{4})$/i, + handler: function(bits) { + var d = new Date(); + d.setDate(parseInt(bits[2], 10)); + d.setMonth(parseMonth(bits[1])); + d.setYear(bits[3]); + return d; + } + }, + // next Tuesday - this is suspect due to weird meaning of "next" + { re: /^next (\w+)$/i, + handler: function(bits) { + var d = new Date(); + var day = d.getDay(); + var newDay = parseWeekday(bits[1]); + var addDays = newDay - day; + if (newDay <= day) { + addDays += 7; + } + d.setDate(d.getDate() + addDays); + return d; + } + }, + // last Tuesday + { re: /^last (\w+)$/i, + handler: function(bits) { + throw new Error("Not yet implemented"); + } + }, + // mm/dd/yyyy (American style) + { re: /(\d{1,2})\/(\d{1,2})\/(\d{4})/, + handler: function(bits) { + var d = new Date(); + d.setYear(bits[3]); + d.setDate(parseInt(bits[2], 10)); + d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0 + return d; + } + }, + // yyyy-mm-dd (ISO style) + { re: /(\d{4})-(\d{1,2})-(\d{1,2})/, + handler: function(bits) { + var d = new Date(); + d.setYear(parseInt(bits[1])); + d.setMonth(parseInt(bits[2], 10) - 1); + d.setDate(parseInt(bits[3], 10)); + return d; + } + }, +]; + +function parseDateString(s) { + for (var i = 0; i < dateParsePatterns.length; i++) { + var re = dateParsePatterns[i].re; + var handler = dateParsePatterns[i].handler; + var bits = re.exec(s); + if (bits) { + return handler(bits); + } + } + throw new Error("Invalid date string"); +} + +function fmt00(x) { + // fmt00: Tags leading zero onto numbers 0 - 9. + // Particularly useful for displaying results from Date methods. + // + if (Math.abs(parseInt(x)) < 10){ + x = "0"+ Math.abs(x); + } + return x; +} + +function parseDateStringISO(s) { + try { + var d = parseDateString(s); + return d.getFullYear() + '-' + (fmt00(d.getMonth() + 1)) + '-' + fmt00(d.getDate()) + } + catch (e) { return s; } +} +function magicDate(input) { + var messagespan = input.id + 'Msg'; + try { + var d = parseDateString(input.value); + input.value = d.getFullYear() + '-' + (fmt00(d.getMonth() + 1)) + '-' + + fmt00(d.getDate()); + input.className = ''; + // Human readable date + if (document.getElementById(messagespan)) { + document.getElementById(messagespan).firstChild.nodeValue = d.toDateString(); + document.getElementById(messagespan).className = 'normal'; + } + } + catch (e) { + input.className = 'error'; + var message = e.message; + // Fix for IE6 bug + if (message.indexOf('is null or not an object') > -1) { + message = 'Invalid date string'; + } + if (document.getElementById(messagespan)) { + document.getElementById(messagespan).firstChild.nodeValue = message; + document.getElementById(messagespan).className = 'error'; + } + } +} diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/getElementsBySelector.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/getElementsBySelector.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,167 @@ +/* document.getElementsBySelector(selector) + - returns an array of element objects from the current document + matching the CSS selector. Selectors can contain element names, + class names and ids and can be nested. For example: + + elements = document.getElementsBySelect('div#main p a.external') + + Will return an array of all 'a' elements with 'external' in their + class attribute that are contained inside 'p' elements that are + contained inside the 'div' element which has id="main" + + New in version 0.4: Support for CSS2 and CSS3 attribute selectors: + See http://www.w3.org/TR/css3-selectors/#attribute-selectors + + Version 0.4 - Simon Willison, March 25th 2003 + -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows + -- Opera 7 fails +*/ + +function getAllChildren(e) { + // Returns all children of element. Workaround required for IE5/Windows. Ugh. + return e.all ? e.all : e.getElementsByTagName('*'); +} + +document.getElementsBySelector = function(selector) { + // Attempt to fail gracefully in lesser browsers + if (!document.getElementsByTagName) { + return new Array(); + } + // Split selector in to tokens + var tokens = selector.split(' '); + var currentContext = new Array(document); + for (var i = 0; i < tokens.length; i++) { + token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');; + if (token.indexOf('#') > -1) { + // Token is an ID selector + var bits = token.split('#'); + var tagName = bits[0]; + var id = bits[1]; + var element = document.getElementById(id); + if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) { + // ID not found or tag with that ID not found, return false. + return new Array(); + } + // Set currentContext to contain just this element + currentContext = new Array(element); + continue; // Skip to next token + } + if (token.indexOf('.') > -1) { + // Token contains a class selector + var bits = token.split('.'); + var tagName = bits[0]; + var className = bits[1]; + if (!tagName) { + tagName = '*'; + } + // Get elements matching tag, filter them for class selector + var found = new Array; + var foundCount = 0; + for (var h = 0; h < currentContext.length; h++) { + var elements; + if (tagName == '*') { + elements = getAllChildren(currentContext[h]); + } else { + try { + elements = currentContext[h].getElementsByTagName(tagName); + } + catch(e) { + elements = []; + } + } + for (var j = 0; j < elements.length; j++) { + found[foundCount++] = elements[j]; + } + } + currentContext = new Array; + var currentContextIndex = 0; + for (var k = 0; k < found.length; k++) { + if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) { + currentContext[currentContextIndex++] = found[k]; + } + } + continue; // Skip to next token + } + // Code to deal with attribute selectors + if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) { + var tagName = RegExp.$1; + var attrName = RegExp.$2; + var attrOperator = RegExp.$3; + var attrValue = RegExp.$4; + if (!tagName) { + tagName = '*'; + } + // Grab all of the tagName elements within current context + var found = new Array; + var foundCount = 0; + for (var h = 0; h < currentContext.length; h++) { + var elements; + if (tagName == '*') { + elements = getAllChildren(currentContext[h]); + } else { + elements = currentContext[h].getElementsByTagName(tagName); + } + for (var j = 0; j < elements.length; j++) { + found[foundCount++] = elements[j]; + } + } + currentContext = new Array; + var currentContextIndex = 0; + var checkFunction; // This function will be used to filter the elements + switch (attrOperator) { + case '=': // Equality + checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); }; + break; + case '~': // Match one of space seperated words + checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); }; + break; + case '|': // Match start with value followed by optional hyphen + checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); }; + break; + case '^': // Match starts with value + checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); }; + break; + case '$': // Match ends with value - fails with "Warning" in Opera 7 + checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); }; + break; + case '*': // Match ends with value + checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); }; + break; + default : + // Just test for existence of attribute + checkFunction = function(e) { return e.getAttribute(attrName); }; + } + currentContext = new Array; + var currentContextIndex = 0; + for (var k = 0; k < found.length; k++) { + if (checkFunction(found[k])) { + currentContext[currentContextIndex++] = found[k]; + } + } + // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue); + continue; // Skip to next token + } + // If we get here, token is JUST an element (not a class or ID selector) + tagName = token; + var found = new Array; + var foundCount = 0; + for (var h = 0; h < currentContext.length; h++) { + var elements = currentContext[h].getElementsByTagName(tagName); + for (var j = 0; j < elements.length; j++) { + found[foundCount++] = elements[j]; + } + } + currentContext = found; + } + return currentContext; +} + +/* That revolting regular expression explained +/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/ + \---/ \---/\-------------/ \-------/ + | | | | + | | | The value + | | ~,|,^,$,* or = + | Attribute + Tag +*/ diff -r 000000000000 -r ecdfc63274bf web/static/admin/js/inlines.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/static/admin/js/inlines.js Tue Jun 08 01:16:35 2010 +0200 @@ -0,0 +1,148 @@ +/** + * Django admin inlines + * + * Based on jQuery Formset 1.1 + * @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com) + * @requires jQuery 1.2.6 or later + * + * Copyright (c) 2009, Stanislaus Madueke + * All rights reserved. + * + * Spiced up with Code from Zain Memon's GSoC project 2009 + * and modified for Django by Jannis Leidel + * + * Licensed under the New BSD License + * See: http://www.opensource.org/licenses/bsd-license.php + */ +(function($) { + $.fn.formset = function(opts) { + var options = $.extend({}, $.fn.formset.defaults, opts); + var updateElementIndex = function(el, prefix, ndx) { + var id_regex = new RegExp("(" + prefix + "-\\d+)"); + var replacement = prefix + "-" + ndx; + if ($(el).attr("for")) { + $(el).attr("for", $(el).attr("for").replace(id_regex, replacement)); + } + if (el.id) { + el.id = el.id.replace(id_regex, replacement); + } + if (el.name) { + el.name = el.name.replace(id_regex, replacement); + } + }; + var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").attr("autocomplete", "off"); + var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").attr("autocomplete", "off"); + // only show the add button if we are allowed to add more items, + // note that max_num = None translates to a blank string. + var showAddButton = maxForms.val() == '' || (maxForms.val()-totalForms.val()) > 0; + $(this).each(function(i) { + $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); + }); + if ($(this).length && showAddButton) { + var addButton; + if ($(this).attr("tagName") == "TR") { + // If forms are laid out as table rows, insert the + // "add" button in a new table row: + var numCols = this.eq(0).children().length; + $(this).parent().append('' + options.addText + ""); + addButton = $(this).parent().find("tr:last a"); + } else { + // Otherwise, insert it immediately after the last form: + $(this).filter(":last").after('"); + addButton = $(this).filter(":last").next().find("a"); + } + addButton.click(function() { + var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS"); + var nextIndex = parseInt(totalForms.val()); + var template = $("#" + options.prefix + "-empty"); + var row = template.clone(true); + row.removeClass(options.emptyCssClass) + .addClass(options.formCssClass) + .attr("id", options.prefix + "-" + nextIndex) + .insertBefore($(template)); + row.find("*") + .filter(function() { + var el = $(this); + return el.attr("id") && el.attr("id").search(/__prefix__/) >= 0; + }).each(function() { + var el = $(this); + el.attr("id", el.attr("id").replace(/__prefix__/g, nextIndex)); + }) + .end() + .filter(function() { + var el = $(this); + return el.attr("name") && el.attr("name").search(/__prefix__/) >= 0; + }).each(function() { + var el = $(this); + el.attr("name", el.attr("name").replace(/__prefix__/g, nextIndex)); + }); + if (row.is("tr")) { + // If the forms are laid out in table rows, insert + // the remove button into the last table cell: + row.children(":last").append('"); + } else if (row.is("ul") || row.is("ol")) { + // If they're laid out as an ordered/unordered list, + // insert an
    • after the last list item: + row.append('
    • ' + options.deleteText + "
    • "); + } else { + // Otherwise, just insert the remove button as the + // last child element of the form's container: + row.children(":first").append('' + options.deleteText + ""); + } + row.find("input,select,textarea,label,a").each(function() { + updateElementIndex(this, options.prefix, totalForms.val()); + }); + // Update number of total forms + $(totalForms).val(nextIndex + 1); + // Hide add button in case we've hit the max, except we want to add infinitely + if ((maxForms.val() != '') && (maxForms.val()-totalForms.val()) <= 0) { + addButton.parent().hide(); + } + // The delete button of each row triggers a bunch of other things + row.find("a." + options.deleteCssClass).click(function() { + // Remove the parent form containing this button: + var row = $(this).parents("." + options.formCssClass); + row.remove(); + // If a post-delete callback was provided, call it with the deleted form: + if (options.removed) { + options.removed(row); + } + // Update the TOTAL_FORMS form count. + var forms = $("." + options.formCssClass); + $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); + // Show add button again once we drop below max + if ((maxForms.val() == '') || (maxForms.val()-forms.length) > 0) { + addButton.parent().show(); + } + // Also, update names and ids for all remaining form controls + // so they remain in sequence: + for (var i=0, formCount=forms.length; i0;a(this).each(function(){a(this).not("."+b.emptyCssClass).addClass(b.formCssClass)}); +if(a(this).length&&g){var i;if(a(this).attr("tagName")=="TR"){g=this.eq(0).children().length;a(this).parent().append(''+b.addText+"");i=a(this).parent().find("tr:last a")}else{a(this).filter(":last").after('");i=a(this).filter(":last").next().find("a")}i.click(function(){var e=a("#id_"+b.prefix+"-TOTAL_FORMS"),f=parseInt(e.val()), +j=a("#"+b.prefix+"-empty"),d=j.clone(true);d.removeClass(b.emptyCssClass).addClass(b.formCssClass).attr("id",b.prefix+"-"+f).insertBefore(a(j));d.find("*").filter(function(){var c=a(this);return c.attr("id")&&c.attr("id").search(/__prefix__/)>=0}).each(function(){var c=a(this);c.attr("id",c.attr("id").replace(/__prefix__/g,f))}).end().filter(function(){var c=a(this);return c.attr("name")&&c.attr("name").search(/__prefix__/)>=0}).each(function(){var c=a(this);c.attr("name",c.attr("name").replace(/__prefix__/g, +f))});if(d.is("tr"))d.children(":last").append('");else d.is("ul")||d.is("ol")?d.append('
    • '+b.deleteText+"
    • "):d.children(":first").append(''+b.deleteText+"");d.find("input,select,textarea,label,a").each(function(){l(this,b.prefix,e.val())});a(e).val(f+1);h.val()!=""&& +h.val()-e.val()<=0&&i.parent().hide();d.find("a."+b.deleteCssClass).click(function(){var c=a(this).parents("."+b.formCssClass);c.remove();b.removed&&b.removed(c);c=a("."+b.formCssClass);a("#id_"+b.prefix+"-TOTAL_FORMS").val(c.length);if(h.val()==""||h.val()-c.length>0)i.parent().show();for(var k=0,m=c.length;k)[^>]*$|^#([\w-]+)$/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwnProperty = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + indexOf = Array.prototype.indexOf; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + 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 ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // 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 ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + if ( elem ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && /^\w+$/.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.4.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // 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 ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // 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 = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + 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 ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( 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( slice.apply( this, arguments ), + "slice", 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 || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + 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; + } + + // Recurse if we're merging object literal values or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { + var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src + : jQuery.isArray(copy) ? [] : {}; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // Handle when the DOM is ready + ready: function() { + // Make sure that the DOM is not already loaded + if ( !jQuery.isReady ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + return jQuery.ready(); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // 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); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // 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 toString.call(obj) === "[object Function]"; + }, + + isArray: function( obj ) { + return toString.call(obj) === "[object Array]"; + }, + + 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 || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor + && !hasOwnProperty.call(obj, "constructor") + && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwnProperty.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") + .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + 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; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + trim: function( text ) { + return (text || "").replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = []; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + if ( !inv !== !callback( elems[ i ], i ) ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) || + /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) || + /(msie) ([\w.]+)/.exec( ua ) || + !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +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; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// 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( error ) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + +// Mutifunctional method to get and set values to a collection +// The value/s can be optionally by executed if its a function +function access( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; +} + +function now() { + return (new Date).getTime(); +} +(function() { + + jQuery.support = {}; + + var root = document.documentElement, + script = document.createElement("script"), + div = document.createElement("div"), + id = "script" + now(); + + div.style.display = "none"; + div.innerHTML = "
      a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.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 insted) + style: /red/.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: div.getElementsByTagName("input")[0].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: document.createElement("select").appendChild( document.createElement("option") ).selected, + + parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null, + + // Will be defined later + deleteExpando: true, + checkClone: false, + scriptEval: false, + noCloneEvent: true, + boxModel: null + }; + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support.scriptEval = true; + delete window[ id ]; + } + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete script.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + root.removeChild( script ); + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = ""; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"); + div.style.width = div.style.paddingLeft = "1px"; + + document.body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + document.body.removeChild( div ).style.display = 'none'; + + div = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + root = script = div = all = a = null; +})(); + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; +var expando = "jQuery" + now(), uuid = 0, windowData = {}; + +jQuery.extend({ + cache: {}, + + expando:expando, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + "object": true, + "applet": true + }, + + data: function( elem, name, data ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache; + + if ( !id && typeof name === "string" && data === undefined ) { + return null; + } + + // Compute a unique ID for the element + if ( !id ) { + id = ++uuid; + } + + // Avoid generating a new cache unless none exists and we + // want to manipulate it. + if ( typeof name === "object" ) { + elem[ expando ] = id; + thisCache = cache[ id ] = jQuery.extend(true, {}, name); + + } else if ( !cache[ id ] ) { + elem[ expando ] = id; + cache[ id ] = {}; + } + + thisCache = cache[ id ]; + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + return typeof name === "string" ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( thisCache ) { + // Remove the section of cache data + delete thisCache[ name ]; + + // If we've removed all the data, remove the element's cache + if ( jQuery.isEmptyObject(thisCache) ) { + jQuery.removeData( elem ); + } + } + + // Otherwise, we want to remove all of the element's data + } else { + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + // Completely remove the data cache + delete cache[ id ]; + } + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + if ( typeof key === "undefined" && this.length ) { + return jQuery.data( this[0] ); + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + } + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } else { + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() { + jQuery.data( this, key, value ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + 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(); + + // 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"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i, elem ) { + 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() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); +var rclass = /[\n\t]/g, + rspace = /\s+/, + rreturn = /\r/g, + rspecialurl = /href|src|style/, + rtype = /(button|input)/i, + rfocusable = /(button|input|object|select|textarea)/i, + rclickable = /^(a|area)$/i, + rradiocheck = /radio|checkbox/; + +jQuery.fn.extend({ + attr: function( name, value ) { + return access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspace ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", setClass = elem.className; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split(rspace); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var 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) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), 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 + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( value === undefined ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + return (elem.attributes.value || {}).specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var 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 + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc 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 ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Typecast each time if the value is a Function and the appended + // value is therefore different each time. + if ( typeof val === "number" ) { + val += ""; + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't set attributes on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + if ( name in elem && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + elem[ name ] = value; + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // 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/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + + // elem is actually elem.style ... set the style + // Using attr for specific style information is now deprecated. Use style instead. + return jQuery.style( elem, name, value ); + } +}); +var rnamespaces = /\.(.*)$/, + fcleanup = function( nm ) { + return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { + return "\\" + ch; + }); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery.data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events = elemData.events || {}, + eventHandle = elemData.handle, eventHandle; + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + handleObj.guid = handler.guid; + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // 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 the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + 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, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)") + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( var j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( var j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[expando] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + jQuery.each( jQuery.cache, function() { + if ( this.events && this.events[type] ) { + jQuery.event.trigger( event, data, this.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery.data( elem, "handle" ); + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var target = event.target, old, + isClick = jQuery.nodeName(target, "a") && type === "click", + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ type ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + type ]; + + if ( old ) { + target[ "on" + type ] = null; + } + + jQuery.event.triggered = true; + target[ type ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( old ) { + target[ "on" + type ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace, events; + + event = arguments[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + var events = jQuery.data(this, "events"), handlers = events[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, arguments ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, body = document.body; + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) { + event.which = event.charCode || event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); + }, + + remove: function( handleObj ) { + var remove = true, + type = handleObj.origType.replace(rnamespaces, ""); + + jQuery.each( jQuery.data(this, "events").live || [], function() { + if ( type === this.origType.replace(rnamespaces, "") ) { + remove = false; + return false; + } + }); + + if ( remove ) { + jQuery.event.remove( this, handleObj.origType, liveHandler ); + } + } + + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( this.setInterval ) { + this.onbeforeunload = eventHandle; + } + + return false; + }, + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +var removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + elem.removeEventListener( type, handle, false ); + } : + function( elem, type, handle ) { + elem.detachEvent( "on" + type, handle ); + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = now(); + + // Mark it as fixed + this[ 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) + 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 +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var formElems = /textarea|input|select/i, + + changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery.data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery.data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + return jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information/focus[in] is not needed anymore + beforeactivate: function( e ) { + var elem = e.target; + jQuery.data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return formElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return formElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, 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; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + context.each(function(){ + jQuery.event.add( this, liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + }); + + } else { + // unbind live handler + context.unbind( liveConvert( type, selector ), fn ); + } + } + + return this; + } +}); + +function liveHandler( event ) { + var stop, elems = [], selectors = [], args = arguments, + related, match, handleObj, elem, j, i, l, data, + events = jQuery.data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) + if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { + return; + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( match[i].selector === handleObj.selector ) { + elem = match[i].elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) { + stop = false; + break; + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); +} + +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").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( fn ) { + return fn ? this.bind( name, fn ) : this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + +// Prevent memory leaks in IE +// Window isn't included so as not to unbind existing unload events +// More info: +// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ +if ( window.attachEvent && !window.addEventListener ) { + window.attachEvent("onunload", function() { + for ( var id in jQuery.cache ) { + if ( jQuery.cache[ id ].handle ) { + // Try/Catch is to handle iframes being unloaded, see #4280 + try { + jQuery.event.remove( jQuery.cache[ id ].handle.elem ); + } catch(e) {} + } + } + }); +} +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// 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 || []; + var origContext = context = context || document; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context), + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } 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]) ) { + var ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + var 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 ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + var 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 = []; + } + } + + 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 ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + 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 results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set, match; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +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|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string"; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // 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; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + 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); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return /h\d/i.test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return /input|select|textarea|button/i.test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + 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 ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var i = 0, l = not.length; i < l; i++ ) { + if ( not[i] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = 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 === "=" ? + 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; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS; + +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, function(all, num){ + return "\\" + (num - 0 + 1); + })); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// 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; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var i = 0, l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( var i = 0; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.compareDocumentPosition ? -1 : 1; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.sourceIndex ? -1 : 1; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.ownerDocument ? -1 : 1; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +function getText( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +} + +// 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(); + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // 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]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(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]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "

      "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
      "; + + // 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; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +var contains = document.compareDocumentPosition ? function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +var 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; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // 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, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = getText; +jQuery.isXMLDoc = isXML; +jQuery.contains = contains; + +return; + +window.Sizzle = Sizzle; + +})(); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + slice = Array.prototype.slice; + +// Implement the identical functionality for filter and not +var winnow = function( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), length = 0; + + for ( var 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 ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + 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); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + if ( jQuery.isArray( selectors ) ) { + var ret = [], cur = this[0], match, matches = {}, selector; + + if ( cur && selectors.length ) { + for ( var i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur }); + delete matches[selector]; + } + } + cur = cur.parentNode; + } + } + + return ret; + } + + var pos = jQuery.expr.match.POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + return this.map(function( i, cur ) { + while ( cur && cur.ownerDocument && cur !== context ) { + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) { + return cur; + } + cur = cur.parentNode; + } + return null; + }); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // 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 || this.context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// 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; +} + +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 ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call(arguments).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], cur = elem[dir]; + 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; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g, + rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i, + rtagName = /<([\w:]+)/, + rtbody = /"; + }, + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
      ", "
      " ], + thead: [ 1, "", "
      " ], + tr: [ 2, "", "
      " ], + td: [ 3, "", "
      " ], + col: [ 2, "", "
      " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and