First commit to Fossee of testapp has the basic Pykata framework on django with some specific changes to Problems model and some views to suit an exam like system
Binary file testappproj/.database.sqlite3 has changed
Binary file testappproj/__init__.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/manage.py Mon May 17 22:33:59 2010 +0530
@@ -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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/settings.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,95 @@
+import os
+import sys
+# Django settings for testappproj project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+ROOT = os.path.dirname(sys.modules[__name__].__file__)
+
+DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+DATABASE_NAME = '.database.sqlite3' # Or path to database file if using sqlite3.
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_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 = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+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/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 's2er59!c4*5-bi5tz)j-#=ngw^p&z8&w-#ft&+sv!_^0m#88pd'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+)
+
+
+# Our own Auth Profile Module so that we can change django registration
+AUTH_PROFILE_MODULE="testapp.Test_User"
+
+#SETTINGS related to registration
+ACCOUNT_ACTIVATION_DAYS=1
+
+
+ROOT_URLCONF = 'testappproj.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(ROOT, 'templates')
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.admin',
+ 'testappproj.testapp',
+ 'registration',
+)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/settings.py.pykata Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,43 @@
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Minimal Django settings."""
+
+import os
+
+
+DEBUG=True
+
+#APPEND_SLASH = False
+# DEBUG = os.environ['SERVER_SOFTWARE'].startswith('Dev')
+INSTALLED_APPS = (
+ 'testapp',
+ )
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.http.ConditionalGetMiddleware',
+)
+ROOT_URLCONF = 'urls'
+TEMPLATE_CONTEXT_PROCESSORS = ()
+TEMPLATE_DEBUG = DEBUG
+TEMPLATE_DIRS = (
+ os.path.join(os.path.dirname(__file__), 'templates'),
+ )
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ )
+FILE_UPLOAD_HANDLERS = (
+ 'django.core.files.uploadhandler.MemoryFileUploadHandler',
+)
+FILE_UPLOAD_MAX_MEMORY_SIZE = 1048576 # 1 MB
Binary file testappproj/settings.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/settings.py~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,85 @@
+import os
+import sys
+# Django settings for testappproj project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+ROOT = os.path.dirname(sys.modules[__name__].__file__)
+
+DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+DATABASE_NAME = '' # Or path to database file if using sqlite3.
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_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 = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+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/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 's2er59!c4*5-bi5tz)j-#=ngw^p&z8&w-#ft&+sv!_^0m#88pd'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+)
+
+ROOT_URLCONF = 'testappproj.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(ROOT, 'templates')
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'testapp',
+)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/static/appjs.js Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,10 @@
+
+
+function loadcode(id) {
+
+$("#solve_" + id).load(location.protocol + "//" + location.host +
+ "/code/" + id + "/",function() {
+ alert("something happened here")
+ });
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/static/appjs.js~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,15 @@
+$(document).ready(function(){
+$("a").click(function(event){
+ alert("As you can see, the link no longer took you to jquery.com");
+ event.preventDefault();
+ });
+ });
+
+
+
+function loadcode(id) {
+
+$("#solve_" + id).load(location.protocol + "//" + location.host +
+ "/code/" + id + "/");
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/static/jquery.js Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,2992 @@
+(function(){
+/*
+ * jQuery 1.2.1 - New Wave Javascript
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2007-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $
+ * $Rev: 3353 $
+ */
+
+// Map over jQuery in case of overwrite
+if ( typeof jQuery != "undefined" )
+ var _jQuery = jQuery;
+
+var jQuery = window.jQuery = function(selector, context) {
+ // If the context is a namespace object, return a new object
+ return this instanceof jQuery ?
+ this.init(selector, context) :
+ new jQuery(selector, context);
+};
+
+// Map over the $ in case of overwrite
+if ( typeof $ != "undefined" )
+ var _$ = $;
+
+// Map the jQuery namespace to the '$' one
+window.$ = jQuery;
+
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+
+jQuery.fn = jQuery.prototype = {
+ init: function(selector, context) {
+ // Make sure that a selection was provided
+ selector = selector || document;
+
+ // Handle HTML strings
+ if ( typeof selector == "string" ) {
+ var m = quickExpr.exec(selector);
+ if ( m && (m[1] || !context) ) {
+ // HANDLE: $(html) -> $(array)
+ if ( m[1] )
+ selector = jQuery.clean( [ m[1] ], context );
+
+ // HANDLE: $("#id")
+ else {
+ var tmp = document.getElementById( m[3] );
+ if ( tmp )
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( tmp.id != m[3] )
+ return jQuery().find( selector );
+ else {
+ this[0] = tmp;
+ this.length = 1;
+ return this;
+ }
+ else
+ selector = [];
+ }
+
+ // HANDLE: $(expr)
+ } else
+ return new jQuery( context ).find( selector );
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction(selector) )
+ return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( selector );
+
+ return this.setArray(
+ // HANDLE: $(array)
+ selector.constructor == Array && selector ||
+
+ // HANDLE: $(arraylike)
+ // Watch for when an array-like object is passed as the selector
+ (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
+
+ // HANDLE: $(*)
+ [ selector ] );
+ },
+
+ jquery: "1.2.1",
+
+ size: function() {
+ return this.length;
+ },
+
+ length: 0,
+
+ get: function( num ) {
+ return num == undefined ?
+
+ // Return a 'clean' array
+ jQuery.makeArray( this ) :
+
+ // Return just the object
+ this[num];
+ },
+
+ pushStack: function( a ) {
+ var ret = jQuery(a);
+ ret.prevObject = this;
+ return ret;
+ },
+
+ setArray: function( a ) {
+ this.length = 0;
+ Array.prototype.push.apply( this, a );
+ return this;
+ },
+
+ each: function( fn, args ) {
+ return jQuery.each( this, fn, args );
+ },
+
+ index: function( obj ) {
+ var pos = -1;
+ this.each(function(i){
+ if ( this == obj ) pos = i;
+ });
+ return pos;
+ },
+
+ attr: function( key, value, type ) {
+ var obj = key;
+
+ // Look for the case where we're accessing a style value
+ if ( key.constructor == String )
+ if ( value == undefined )
+ return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined;
+ else {
+ obj = {};
+ obj[ key ] = value;
+ }
+
+ // Check to see if we're setting style values
+ return this.each(function(index){
+ // Set all the styles
+ for ( var prop in obj )
+ jQuery.attr(
+ type ? this.style : this,
+ prop, jQuery.prop(this, obj[prop], type, index, prop)
+ );
+ });
+ },
+
+ css: function( key, value ) {
+ return this.attr( key, value, "curCSS" );
+ },
+
+ text: function(e) {
+ if ( typeof e != "object" && e != null )
+ return this.empty().append( document.createTextNode( e ) );
+
+ var t = "";
+ jQuery.each( e || this, function(){
+ jQuery.each( this.childNodes, function(){
+ if ( this.nodeType != 8 )
+ t += this.nodeType != 1 ?
+ this.nodeValue : jQuery.fn.text([ this ]);
+ });
+ });
+ return t;
+ },
+
+ wrapAll: function(html) {
+ if ( this[0] )
+ // The elements to wrap the target around
+ jQuery(html, this[0].ownerDocument)
+ .clone()
+ .insertBefore(this[0])
+ .map(function(){
+ var elem = this;
+ while ( elem.firstChild )
+ elem = elem.firstChild;
+ return elem;
+ })
+ .append(this);
+
+ return this;
+ },
+
+ wrapInner: function(html) {
+ return this.each(function(){
+ jQuery(this).contents().wrapAll(html);
+ });
+ },
+
+ wrap: function(html) {
+ return this.each(function(){
+ jQuery(this).wrapAll(html);
+ });
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, 1, function(a){
+ this.appendChild( a );
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, -1, function(a){
+ this.insertBefore( a, this.firstChild );
+ });
+ },
+
+ before: function() {
+ return this.domManip(arguments, false, 1, function(a){
+ this.parentNode.insertBefore( a, this );
+ });
+ },
+
+ after: function() {
+ return this.domManip(arguments, false, -1, function(a){
+ this.parentNode.insertBefore( a, this.nextSibling );
+ });
+ },
+
+ end: function() {
+ return this.prevObject || jQuery([]);
+ },
+
+ find: function(t) {
+ var data = jQuery.map(this, function(a){ return jQuery.find(t,a); });
+ return this.pushStack( /[^+>] [^+>]/.test( t ) || t.indexOf("..") > -1 ?
+ jQuery.unique( data ) : data );
+ },
+
+ clone: function(events) {
+ // Do the clone
+ var ret = this.map(function(){
+ return this.outerHTML ? jQuery(this.outerHTML)[0] : this.cloneNode(true);
+ });
+
+ // Need to set the expando to null on the cloned set if it exists
+ // removeData doesn't work here, IE removes it from the original as well
+ // this is primarily for IE but the data expando shouldn't be copied over in any browser
+ var clone = ret.find("*").andSelf().each(function(){
+ if ( this[ expando ] != undefined )
+ this[ expando ] = null;
+ });
+
+ // Copy the events from the original to the clone
+ if (events === true)
+ this.find("*").andSelf().each(function(i) {
+ var events = jQuery.data(this, "events");
+ for ( var type in events )
+ for ( var handler in events[type] )
+ jQuery.event.add(clone[i], type, events[type][handler], events[type][handler].data);
+ });
+
+ // Return the cloned set
+ return ret;
+ },
+
+ filter: function(t) {
+ return this.pushStack(
+ jQuery.isFunction( t ) &&
+ jQuery.grep(this, function(el, index){
+ return t.apply(el, [index]);
+ }) ||
+
+ jQuery.multiFilter(t,this) );
+ },
+
+ not: function(t) {
+ return this.pushStack(
+ t.constructor == String &&
+ jQuery.multiFilter(t, this, true) ||
+
+ jQuery.grep(this, function(a) {
+ return ( t.constructor == Array || t.jquery )
+ ? jQuery.inArray( a, t ) < 0
+ : a != t;
+ })
+ );
+ },
+
+ add: function(t) {
+ return this.pushStack( jQuery.merge(
+ this.get(),
+ t.constructor == String ?
+ jQuery(t).get() :
+ t.length != undefined && (!t.nodeName || jQuery.nodeName(t, "form")) ?
+ t : [t] )
+ );
+ },
+
+ is: function(expr) {
+ return expr ? jQuery.multiFilter(expr,this).length > 0 : false;
+ },
+
+ hasClass: function(expr) {
+ return this.is("." + expr);
+ },
+
+ val: function( val ) {
+ if ( val == undefined ) {
+ if ( this.length ) {
+ var elem = this[0];
+
+ // We need to handle select boxes special
+ if ( jQuery.nodeName(elem, "select") ) {
+ var index = elem.selectedIndex,
+ a = [],
+ 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
+ var val = jQuery.browser.msie && !option.attributes["value"].specified ? option.text : option.value;
+
+ // We don't need an array for one selects
+ if ( one )
+ return val;
+
+ // Multi-Selects return an array
+ a.push(val);
+ }
+ }
+
+ return a;
+
+ // Everything else, we just grab the value
+ } else
+ return this[0].value.replace(/\r/g, "");
+ }
+ } else
+ return this.each(function(){
+ if ( val.constructor == Array && /radio|checkbox/.test(this.type) )
+ this.checked = (jQuery.inArray(this.value, val) >= 0 ||
+ jQuery.inArray(this.name, val) >= 0);
+ else if ( jQuery.nodeName(this, "select") ) {
+ var tmp = val.constructor == Array ? val : [val];
+
+ jQuery("option", this).each(function(){
+ this.selected = (jQuery.inArray(this.value, tmp) >= 0 ||
+ jQuery.inArray(this.text, tmp) >= 0);
+ });
+
+ if ( !tmp.length )
+ this.selectedIndex = -1;
+ } else
+ this.value = val;
+ });
+ },
+
+ html: function( val ) {
+ return val == undefined ?
+ ( this.length ? this[0].innerHTML : null ) :
+ this.empty().append( val );
+ },
+
+ replaceWith: function( val ) {
+ return this.after( val ).remove();
+ },
+
+ eq: function(i){
+ return this.slice(i, i+1);
+ },
+
+ slice: function() {
+ return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
+ },
+
+ map: function(fn) {
+ return this.pushStack(jQuery.map( this, function(elem,i){
+ return fn.call( elem, i, elem );
+ }));
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ },
+
+ domManip: function(args, table, dir, fn) {
+ var clone = this.length > 1, a;
+
+ return this.each(function(){
+ if ( !a ) {
+ a = jQuery.clean(args, this.ownerDocument);
+ if ( dir < 0 )
+ a.reverse();
+ }
+
+ var obj = this;
+
+ if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") )
+ obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody"));
+
+ jQuery.each( a, function(){
+ var elem = clone ? this.cloneNode(true) : this;
+ if ( !evalScript(0, elem) )
+ fn.call( obj, elem );
+ });
+ });
+ }
+};
+
+function evalScript(i, elem){
+ var script = jQuery.nodeName(elem, "script");
+
+ if ( script ) {
+ 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);
+
+ } else if ( elem.nodeType == 1 )
+ jQuery("script", elem).each(evalScript);
+
+ return script;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+ // copy reference to target object
+ var target = arguments[0] || {}, a = 1, al = arguments.length, deep = false;
+
+ // Handle a deep copy situation
+ if ( target.constructor == Boolean ) {
+ deep = target;
+ target = arguments[1] || {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( al == 1 ) {
+ target = this;
+ a = 0;
+ }
+
+ var prop;
+
+ for ( ; a < al; a++ )
+ // Only deal with non-null/undefined values
+ if ( (prop = arguments[a]) != null )
+ // Extend the base object
+ for ( var i in prop ) {
+ // Prevent never-ending loop
+ if ( target == prop[i] )
+ continue;
+
+ // Recurse if we're merging object values
+ if ( deep && typeof prop[i] == 'object' && target[i] )
+ jQuery.extend( target[i], prop[i] );
+
+ // Don't bring in undefined values
+ else if ( prop[i] != undefined )
+ target[i] = prop[i];
+ }
+
+ // Return the modified object
+ return target;
+};
+
+var expando = "jQuery" + (new Date()).getTime(), uuid = 0, win = {};
+
+jQuery.extend({
+ noConflict: function(deep) {
+ window.$ = _$;
+ if ( deep )
+ window.jQuery = _jQuery;
+ return jQuery;
+ },
+
+ // This may seem like some crazy code, but trust me when I say that this
+ // is the only cross-browser way to do this. --John
+ isFunction: function( fn ) {
+ return !!fn && typeof fn != "string" && !fn.nodeName &&
+ fn.constructor != Array && /function/i.test( fn + "" );
+ },
+
+ // check if an element is in a XML document
+ isXMLDoc: function(elem) {
+ return elem.documentElement && !elem.body ||
+ elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+ },
+
+ // Evalulates a script in a global context
+ // Evaluates Async. in Safari 2 :-(
+ globalEval: function( data ) {
+ data = jQuery.trim( data );
+ if ( data ) {
+ if ( window.execScript )
+ window.execScript( data );
+ else if ( jQuery.browser.safari )
+ // safari doesn't provide a synchronous global eval
+ window.setTimeout( data, 0 );
+ else
+ eval.call( window, data );
+ }
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+ },
+
+ cache: {},
+
+ data: function( elem, name, data ) {
+ elem = elem == window ? win : elem;
+
+ var id = elem[ expando ];
+
+ // Compute a unique ID for the element
+ if ( !id )
+ id = elem[ expando ] = ++uuid;
+
+ // Only generate the data cache if we're
+ // trying to access or manipulate it
+ if ( name && !jQuery.cache[ id ] )
+ jQuery.cache[ id ] = {};
+
+ // Prevent overriding the named cache with undefined values
+ if ( data != undefined )
+ jQuery.cache[ id ][ name ] = data;
+
+ // Return the named cache data, or the ID for the element
+ return name ? jQuery.cache[ id ][ name ] : id;
+ },
+
+ removeData: function( elem, name ) {
+ elem = elem == window ? win : elem;
+
+ var id = elem[ expando ];
+
+ // If we want to remove a specific section of the element's data
+ if ( name ) {
+ if ( jQuery.cache[ id ] ) {
+ // Remove the section of cache data
+ delete jQuery.cache[ id ][ name ];
+
+ // If we've removed all the data, remove the element's cache
+ name = "";
+ for ( name in jQuery.cache[ id ] ) break;
+ if ( !name )
+ jQuery.removeData( elem );
+ }
+
+ // Otherwise, we want to remove all of the element's data
+ } else {
+ // Clean up the element expando
+ try {
+ delete elem[ expando ];
+ } catch(e){
+ // IE has trouble directly removing the expando
+ // but it's ok with using removeAttribute
+ if ( elem.removeAttribute )
+ elem.removeAttribute( expando );
+ }
+
+ // Completely remove the data cache
+ delete jQuery.cache[ id ];
+ }
+ },
+
+ // args is for internal usage only
+ each: function( obj, fn, args ) {
+ if ( args ) {
+ if ( obj.length == undefined )
+ for ( var i in obj )
+ fn.apply( obj[i], args );
+ else
+ for ( var i = 0, ol = obj.length; i < ol; i++ )
+ if ( fn.apply( obj[i], args ) === false ) break;
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( obj.length == undefined )
+ for ( var i in obj )
+ fn.call( obj[i], i, obj[i] );
+ else
+ for ( var i = 0, ol = obj.length, val = obj[0];
+ i < ol && fn.call(val,i,val) !== false; val = obj[++i] ){}
+ }
+
+ return obj;
+ },
+
+ prop: function(elem, value, type, index, prop){
+ // Handle executable functions
+ if ( jQuery.isFunction( value ) )
+ value = value.call( elem, [index] );
+
+ // exclude the following css properties to add px
+ var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
+
+ // Handle passing in a number to a CSS property
+ return value && value.constructor == Number && type == "curCSS" && !exclude.test(prop) ?
+ value + "px" :
+ value;
+ },
+
+ className: {
+ // internal only, use addClass("class")
+ add: function( elem, c ){
+ jQuery.each( (c || "").split(/\s+/), function(i, cur){
+ if ( !jQuery.className.has( elem.className, cur ) )
+ elem.className += ( elem.className ? " " : "" ) + cur;
+ });
+ },
+
+ // internal only, use removeClass("class")
+ remove: function( elem, c ){
+ elem.className = c != undefined ?
+ jQuery.grep( elem.className.split(/\s+/), function(cur){
+ return !jQuery.className.has( c, cur );
+ }).join(" ") : "";
+ },
+
+ // internal only, use is(".class")
+ has: function( t, c ) {
+ return jQuery.inArray( c, (t.className || t).toString().split(/\s+/) ) > -1;
+ }
+ },
+
+ swap: function(e,o,f) {
+ for ( var i in o ) {
+ e.style["old"+i] = e.style[i];
+ e.style[i] = o[i];
+ }
+ f.apply( e, [] );
+ for ( var i in o )
+ e.style[i] = e.style["old"+i];
+ },
+
+ css: function(e,p) {
+ if ( p == "height" || p == "width" ) {
+ var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"];
+
+ jQuery.each( d, function(){
+ old["padding" + this] = 0;
+ old["border" + this + "Width"] = 0;
+ });
+
+ jQuery.swap( e, old, function() {
+ if ( jQuery(e).is(':visible') ) {
+ oHeight = e.offsetHeight;
+ oWidth = e.offsetWidth;
+ } else {
+ e = jQuery(e.cloneNode(true))
+ .find(":radio").removeAttr("checked").end()
+ .css({
+ visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0"
+ }).appendTo(e.parentNode)[0];
+
+ var parPos = jQuery.css(e.parentNode,"position") || "static";
+ if ( parPos == "static" )
+ e.parentNode.style.position = "relative";
+
+ oHeight = e.clientHeight;
+ oWidth = e.clientWidth;
+
+ if ( parPos == "static" )
+ e.parentNode.style.position = "static";
+
+ e.parentNode.removeChild(e);
+ }
+ });
+
+ return p == "height" ? oHeight : oWidth;
+ }
+
+ return jQuery.curCSS( e, p );
+ },
+
+ curCSS: function(elem, prop, force) {
+ var ret, stack = [], swap = [];
+
+ // A helper method for determining if an element's values are broken
+ function color(a){
+ if ( !jQuery.browser.safari )
+ return false;
+
+ var ret = document.defaultView.getComputedStyle(a,null);
+ return !ret || ret.getPropertyValue("color") == "";
+ }
+
+ if (prop == "opacity" && jQuery.browser.msie) {
+ ret = jQuery.attr(elem.style, "opacity");
+ return ret == "" ? "1" : ret;
+ }
+
+ if (prop.match(/float/i))
+ prop = styleFloat;
+
+ if (!force && elem.style[prop])
+ ret = elem.style[prop];
+
+ else if (document.defaultView && document.defaultView.getComputedStyle) {
+
+ if (prop.match(/float/i))
+ prop = "float";
+
+ prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase();
+ var cur = document.defaultView.getComputedStyle(elem, null);
+
+ if ( cur && !color(elem) )
+ ret = cur.getPropertyValue(prop);
+
+ // If the element isn't reporting its values properly in Safari
+ // then some display: none elements are involved
+ else {
+ // Locate all of the parent display: none elements
+ for ( var a = elem; a && color(a); a = a.parentNode )
+ stack.unshift(a);
+
+ // Go through and make them visible, but in reverse
+ // (It would be better if we knew the exact display type that they had)
+ for ( a = 0; a < stack.length; a++ )
+ if ( color(stack[a]) ) {
+ swap[a] = stack[a].style.display;
+ stack[a].style.display = "block";
+ }
+
+ // Since we flip the display style, we have to handle that
+ // one special, otherwise get the value
+ ret = prop == "display" && swap[stack.length-1] != null ?
+ "none" :
+ document.defaultView.getComputedStyle(elem,null).getPropertyValue(prop) || "";
+
+ // Finally, revert the display styles back
+ for ( a = 0; a < swap.length; a++ )
+ if ( swap[a] != null )
+ stack[a].style.display = swap[a];
+ }
+
+ if ( prop == "opacity" && ret == "" )
+ ret = "1";
+
+ } else if (elem.currentStyle) {
+ var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();});
+ ret = elem.currentStyle[prop] || elem.currentStyle[newProp];
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !/^\d+(px)?$/i.test(ret) && /^\d/.test(ret) ) {
+ var style = elem.style.left;
+ var runtimeStyle = elem.runtimeStyle.left;
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ elem.style.left = ret || 0;
+ ret = elem.style.pixelLeft + "px";
+ elem.style.left = style;
+ elem.runtimeStyle.left = runtimeStyle;
+ }
+ }
+
+ return ret;
+ },
+
+ clean: function(a, doc) {
+ var r = [];
+ doc = doc || document;
+
+ jQuery.each( a, function(i,arg){
+ if ( !arg ) return;
+
+ if ( arg.constructor == Number )
+ arg = arg.toString();
+
+ // Convert html string into DOM nodes
+ if ( typeof arg == "string" ) {
+ // Fix "XHTML"-style tags in all browsers
+ arg = arg.replace(/(<(\w+)[^>]*?)\/>/g, function(m, all, tag){
+ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i)? m : all+"></"+tag+">";
+ });
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var s = jQuery.trim(arg).toLowerCase(), div = doc.createElement("div"), tb = [];
+
+ var wrap =
+ // option or optgroup
+ !s.indexOf("<opt") &&
+ [1, "<select>", "</select>"] ||
+
+ !s.indexOf("<leg") &&
+ [1, "<fieldset>", "</fieldset>"] ||
+
+ s.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+ [1, "<table>", "</table>"] ||
+
+ !s.indexOf("<tr") &&
+ [2, "<table><tbody>", "</tbody></table>"] ||
+
+ // <thead> matched above
+ (!s.indexOf("<td") || !s.indexOf("<th")) &&
+ [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
+
+ !s.indexOf("<col") &&
+ [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"] ||
+
+ // IE can't serialize <link> and <script> tags normally
+ jQuery.browser.msie &&
+ [1, "div<div>", "</div>"] ||
+
+ [0,"",""];
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + arg + wrap[2];
+
+ // Move to the right depth
+ while ( wrap[0]-- )
+ div = div.lastChild;
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( jQuery.browser.msie ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ if ( !s.indexOf("<table") && s.indexOf("<tbody") < 0 )
+ tb = div.firstChild && div.firstChild.childNodes;
+
+ // String was a bare <thead> or <tfoot>
+ else if ( wrap[1] == "<table>" && s.indexOf("<tbody") < 0 )
+ tb = div.childNodes;
+
+ for ( var n = tb.length-1; n >= 0 ; --n )
+ if ( jQuery.nodeName(tb[n], "tbody") && !tb[n].childNodes.length )
+ tb[n].parentNode.removeChild(tb[n]);
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( /^\s/.test(arg) )
+ div.insertBefore( doc.createTextNode( arg.match(/^\s*/)[0] ), div.firstChild );
+
+ }
+
+ arg = jQuery.makeArray( div.childNodes );
+ }
+
+ if ( 0 === arg.length && (!jQuery.nodeName(arg, "form") && !jQuery.nodeName(arg, "select")) )
+ return;
+
+ if ( arg[0] == undefined || jQuery.nodeName(arg, "form") || arg.options )
+ r.push( arg );
+ else
+ r = jQuery.merge( r, arg );
+
+ });
+
+ return r;
+ },
+
+ attr: function(elem, name, value){
+ var fix = jQuery.isXMLDoc(elem) ? {} : jQuery.props;
+
+ // Safari mis-reports the default selected property of a hidden option
+ // Accessing the parent's selectedIndex property fixes it
+ if ( name == "selected" && jQuery.browser.safari )
+ elem.parentNode.selectedIndex;
+
+ // Certain attributes only work when accessed via the old DOM 0 way
+ if ( fix[name] ) {
+ if ( value != undefined ) elem[fix[name]] = value;
+ return elem[fix[name]];
+ } else if ( jQuery.browser.msie && name == "style" )
+ return jQuery.attr( elem.style, "cssText", value );
+
+ else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName(elem, "form") && (name == "action" || name == "method") )
+ return elem.getAttributeNode(name).nodeValue;
+
+ // IE elem.getAttribute passes even for style
+ else if ( elem.tagName ) {
+
+ if ( value != undefined ) {
+ if ( name == "type" && jQuery.nodeName(elem,"input") && elem.parentNode )
+ throw "type property can't be changed";
+ elem.setAttribute( name, value );
+ }
+
+ if ( jQuery.browser.msie && /href|src/.test(name) && !jQuery.isXMLDoc(elem) )
+ return elem.getAttribute( name, 2 );
+
+ return elem.getAttribute( name );
+
+ // elem is actually elem.style ... set the style
+ } else {
+ // IE actually uses filters for opacity
+ if ( name == "opacity" && jQuery.browser.msie ) {
+ if ( value != undefined ) {
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ elem.zoom = 1;
+
+ // Set the alpha filter to set the opacity
+ elem.filter = (elem.filter || "").replace(/alpha\([^)]*\)/,"") +
+ (parseFloat(value).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+ }
+
+ return elem.filter ?
+ (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() : "";
+ }
+ name = name.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();});
+ if ( value != undefined ) elem[name] = value;
+ return elem[name];
+ }
+ },
+
+ trim: function(t){
+ return (t||"").replace(/^\s+|\s+$/g, "");
+ },
+
+ makeArray: function( a ) {
+ var r = [];
+
+ // Need to use typeof to fight Safari childNodes crashes
+ if ( typeof a != "array" )
+ for ( var i = 0, al = a.length; i < al; i++ )
+ r.push( a[i] );
+ else
+ r = a.slice( 0 );
+
+ return r;
+ },
+
+ inArray: function( b, a ) {
+ for ( var i = 0, al = a.length; i < al; i++ )
+ if ( a[i] == b )
+ return i;
+ return -1;
+ },
+
+ merge: function(first, second) {
+ // We have to loop this way because IE & Opera overwrite the length
+ // expando of getElementsByTagName
+
+ // Also, we need to make sure that the correct elements are being returned
+ // (IE returns comment nodes in a '*' query)
+ if ( jQuery.browser.msie ) {
+ for ( var i = 0; second[i]; i++ )
+ if ( second[i].nodeType != 8 )
+ first.push(second[i]);
+ } else
+ for ( var i = 0; second[i]; i++ )
+ first.push(second[i]);
+
+ return first;
+ },
+
+ unique: function(first) {
+ var r = [], done = {};
+
+ try {
+ for ( var i = 0, fl = first.length; i < fl; i++ ) {
+ var id = jQuery.data(first[i]);
+ if ( !done[id] ) {
+ done[id] = true;
+ r.push(first[i]);
+ }
+ }
+ } catch(e) {
+ r = first;
+ }
+
+ return r;
+ },
+
+ grep: function(elems, fn, inv) {
+ // If a string is passed in for the function, make a function
+ // for it (a handy shortcut)
+ if ( typeof fn == "string" )
+ fn = eval("false||function(a,i){return " + fn + "}");
+
+ var result = [];
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, el = elems.length; i < el; i++ )
+ if ( !inv && fn(elems[i],i) || inv && !fn(elems[i],i) )
+ result.push( elems[i] );
+
+ return result;
+ },
+
+ map: function(elems, fn) {
+ // If a string is passed in for the function, make a function
+ // for it (a handy shortcut)
+ if ( typeof fn == "string" )
+ fn = eval("false||function(a){return " + fn + "}");
+
+ var result = [];
+
+ // Go through the array, translating each of the items to their
+ // new value (or values).
+ for ( var i = 0, el = elems.length; i < el; i++ ) {
+ var val = fn(elems[i],i);
+
+ if ( val !== null && val != undefined ) {
+ if ( val.constructor != Array ) val = [val];
+ result = result.concat( val );
+ }
+ }
+
+ return result;
+ }
+});
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+ version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
+ safari: /webkit/.test(userAgent),
+ opera: /opera/.test(userAgent),
+ msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
+ mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)
+};
+
+var styleFloat = jQuery.browser.msie ? "styleFloat" : "cssFloat";
+
+jQuery.extend({
+ // Check to see if the W3C box model is being used
+ boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
+
+ styleFloat: jQuery.browser.msie ? "styleFloat" : "cssFloat",
+
+ props: {
+ "for": "htmlFor",
+ "class": "className",
+ "float": styleFloat,
+ cssFloat: styleFloat,
+ styleFloat: styleFloat,
+ innerHTML: "innerHTML",
+ className: "className",
+ value: "value",
+ disabled: "disabled",
+ checked: "checked",
+ readonly: "readOnly",
+ selected: "selected",
+ maxlength: "maxLength"
+ }
+});
+
+jQuery.each({
+ parent: "a.parentNode",
+ parents: "jQuery.dir(a,'parentNode')",
+ next: "jQuery.nth(a,2,'nextSibling')",
+ prev: "jQuery.nth(a,2,'previousSibling')",
+ nextAll: "jQuery.dir(a,'nextSibling')",
+ prevAll: "jQuery.dir(a,'previousSibling')",
+ siblings: "jQuery.sibling(a.parentNode.firstChild,a)",
+ children: "jQuery.sibling(a.firstChild)",
+ contents: "jQuery.nodeName(a,'iframe')?a.contentDocument||a.contentWindow.document:jQuery.makeArray(a.childNodes)"
+}, function(i,n){
+ jQuery.fn[ i ] = function(a) {
+ var ret = jQuery.map(this,n);
+ if ( a && typeof a == "string" )
+ ret = jQuery.multiFilter(a,ret);
+ return this.pushStack( jQuery.unique(ret) );
+ };
+});
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function(i,n){
+ jQuery.fn[ i ] = function(){
+ var a = arguments;
+ return this.each(function(){
+ for ( var j = 0, al = a.length; j < al; j++ )
+ jQuery(a[j])[n]( this );
+ });
+ };
+});
+
+jQuery.each( {
+ removeAttr: function( key ) {
+ jQuery.attr( this, key, "" );
+ this.removeAttribute( key );
+ },
+ addClass: function(c){
+ jQuery.className.add(this,c);
+ },
+ removeClass: function(c){
+ jQuery.className.remove(this,c);
+ },
+ toggleClass: function( c ){
+ jQuery.className[ jQuery.className.has(this,c) ? "remove" : "add" ](this, c);
+ },
+ remove: function(a){
+ if ( !a || jQuery.filter( a, [this] ).r.length ) {
+ jQuery.removeData( this );
+ this.parentNode.removeChild( this );
+ }
+ },
+ empty: function() {
+ // Clean up the cache
+ jQuery("*", this).each(function(){ jQuery.removeData(this); });
+
+ while ( this.firstChild )
+ this.removeChild( this.firstChild );
+ }
+}, function(i,n){
+ jQuery.fn[ i ] = function() {
+ return this.each( n, arguments );
+ };
+});
+
+jQuery.each( [ "Height", "Width" ], function(i,name){
+ var n = name.toLowerCase();
+
+ jQuery.fn[ n ] = function(h) {
+ return this[0] == window ?
+ jQuery.browser.safari && self["inner" + name] ||
+ jQuery.boxModel && Math.max(document.documentElement["client" + name], document.body["client" + name]) ||
+ document.body["client" + name] :
+
+ this[0] == document ?
+ Math.max( document.body["scroll" + name], document.body["offset" + name] ) :
+
+ h == undefined ?
+ ( this.length ? jQuery.css( this[0], n ) : null ) :
+ this.css( n, h.constructor == String ? h : h + "px" );
+ };
+});
+
+var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
+ "(?:[\\w*_-]|\\\\.)" :
+ "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
+ quickChild = new RegExp("^>\\s*(" + chars + "+)"),
+ quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
+ quickClass = new RegExp("^([#.]?)(" + chars + "*)");
+
+jQuery.extend({
+ expr: {
+ "": "m[2]=='*'||jQuery.nodeName(a,m[2])",
+ "#": "a.getAttribute('id')==m[2]",
+ ":": {
+ // Position Checks
+ lt: "i<m[3]-0",
+ gt: "i>m[3]-0",
+ nth: "m[3]-0==i",
+ eq: "m[3]-0==i",
+ first: "i==0",
+ last: "i==r.length-1",
+ even: "i%2==0",
+ odd: "i%2",
+
+ // Child Checks
+ "first-child": "a.parentNode.getElementsByTagName('*')[0]==a",
+ "last-child": "jQuery.nth(a.parentNode.lastChild,1,'previousSibling')==a",
+ "only-child": "!jQuery.nth(a.parentNode.lastChild,2,'previousSibling')",
+
+ // Parent Checks
+ parent: "a.firstChild",
+ empty: "!a.firstChild",
+
+ // Text Check
+ contains: "(a.textContent||a.innerText||jQuery(a).text()||'').indexOf(m[3])>=0",
+
+ // Visibility
+ visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"',
+ hidden: '"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"',
+
+ // Form attributes
+ enabled: "!a.disabled",
+ disabled: "a.disabled",
+ checked: "a.checked",
+ selected: "a.selected||jQuery.attr(a,'selected')",
+
+ // Form elements
+ text: "'text'==a.type",
+ radio: "'radio'==a.type",
+ checkbox: "'checkbox'==a.type",
+ file: "'file'==a.type",
+ password: "'password'==a.type",
+ submit: "'submit'==a.type",
+ image: "'image'==a.type",
+ reset: "'reset'==a.type",
+ button: '"button"==a.type||jQuery.nodeName(a,"button")',
+ input: "/input|select|textarea|button/i.test(a.nodeName)",
+
+ // :has()
+ has: "jQuery.find(m[3],a).length",
+
+ // :header
+ header: "/h\\d/i.test(a.nodeName)",
+
+ // :animated
+ animated: "jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length"
+ }
+ },
+
+ // The regular expressions that power the parsing engine
+ parse: [
+ // Match: [@value='test'], [@foo]
+ /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
+
+ // Match: :contains('foo')
+ /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
+
+ // Match: :even, :last-chlid, #id, .class
+ new RegExp("^([:.#]*)(" + chars + "+)")
+ ],
+
+ multiFilter: function( expr, elems, not ) {
+ var old, cur = [];
+
+ while ( expr && expr != old ) {
+ old = expr;
+ var f = jQuery.filter( expr, elems, not );
+ expr = f.t.replace(/^\s*,\s*/, "" );
+ cur = not ? elems = f.r : jQuery.merge( cur, f.r );
+ }
+
+ return cur;
+ },
+
+ find: function( t, context ) {
+ // Quickly handle non-string expressions
+ if ( typeof t != "string" )
+ return [ t ];
+
+ // Make sure that the context is a DOM Element
+ if ( context && !context.nodeType )
+ context = null;
+
+ // Set the correct context (if none is provided)
+ context = context || document;
+
+ // Initialize the search
+ var ret = [context], done = [], last;
+
+ // Continue while a selector expression exists, and while
+ // we're no longer looping upon ourselves
+ while ( t && last != t ) {
+ var r = [];
+ last = t;
+
+ t = jQuery.trim(t);
+
+ var foundToken = false;
+
+ // An attempt at speeding up child selectors that
+ // point to a specific element tag
+ var re = quickChild;
+ var m = re.exec(t);
+
+ if ( m ) {
+ var nodeName = m[1].toUpperCase();
+
+ // Perform our own iteration and filter
+ for ( var i = 0; ret[i]; i++ )
+ for ( var c = ret[i].firstChild; c; c = c.nextSibling )
+ if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName.toUpperCase()) )
+ r.push( c );
+
+ ret = r;
+ t = t.replace( re, "" );
+ if ( t.indexOf(" ") == 0 ) continue;
+ foundToken = true;
+ } else {
+ re = /^([>+~])\s*(\w*)/i;
+
+ if ( (m = re.exec(t)) != null ) {
+ r = [];
+
+ var nodeName = m[2], merge = {};
+ m = m[1];
+
+ for ( var j = 0, rl = ret.length; j < rl; j++ ) {
+ var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
+ for ( ; n; n = n.nextSibling )
+ if ( n.nodeType == 1 ) {
+ var id = jQuery.data(n);
+
+ if ( m == "~" && merge[id] ) break;
+
+ if (!nodeName || n.nodeName.toUpperCase() == nodeName.toUpperCase() ) {
+ if ( m == "~" ) merge[id] = true;
+ r.push( n );
+ }
+
+ if ( m == "+" ) break;
+ }
+ }
+
+ ret = r;
+
+ // And remove the token
+ t = jQuery.trim( t.replace( re, "" ) );
+ foundToken = true;
+ }
+ }
+
+ // See if there's still an expression, and that we haven't already
+ // matched a token
+ if ( t && !foundToken ) {
+ // Handle multiple expressions
+ if ( !t.indexOf(",") ) {
+ // Clean the result set
+ if ( context == ret[0] ) ret.shift();
+
+ // Merge the result sets
+ done = jQuery.merge( done, ret );
+
+ // Reset the context
+ r = ret = [context];
+
+ // Touch up the selector string
+ t = " " + t.substr(1,t.length);
+
+ } else {
+ // Optimize for the case nodeName#idName
+ var re2 = quickID;
+ var m = re2.exec(t);
+
+ // Re-organize the results, so that they're consistent
+ if ( m ) {
+ m = [ 0, m[2], m[3], m[1] ];
+
+ } else {
+ // Otherwise, do a traditional filter check for
+ // ID, class, and element selectors
+ re2 = quickClass;
+ m = re2.exec(t);
+ }
+
+ m[2] = m[2].replace(/\\/g, "");
+
+ var elem = ret[ret.length-1];
+
+ // Try to do a global search by ID, where we can
+ if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
+ // Optimization for HTML document case
+ var oid = elem.getElementById(m[2]);
+
+ // Do a quick check for the existence of the actual ID attribute
+ // to avoid selecting by the name attribute in IE
+ // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
+ if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
+ oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
+
+ // Do a quick check for node name (where applicable) so
+ // that div#foo searches will be really fast
+ ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
+ } else {
+ // We need to find all descendant elements
+ for ( var i = 0; ret[i]; i++ ) {
+ // Grab the tag name being searched for
+ var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
+
+ // Handle IE7 being really dumb about <object>s
+ if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
+ tag = "param";
+
+ r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
+ }
+
+ // It's faster to filter by class and be done with it
+ if ( m[1] == "." )
+ r = jQuery.classFilter( r, m[2] );
+
+ // Same with ID filtering
+ if ( m[1] == "#" ) {
+ var tmp = [];
+
+ // Try to find the element with the ID
+ for ( var i = 0; r[i]; i++ )
+ if ( r[i].getAttribute("id") == m[2] ) {
+ tmp = [ r[i] ];
+ break;
+ }
+
+ r = tmp;
+ }
+
+ ret = r;
+ }
+
+ t = t.replace( re2, "" );
+ }
+
+ }
+
+ // If a selector string still exists
+ if ( t ) {
+ // Attempt to filter it
+ var val = jQuery.filter(t,r);
+ ret = r = val.r;
+ t = jQuery.trim(val.t);
+ }
+ }
+
+ // An error occurred with the selector;
+ // just return an empty set instead
+ if ( t )
+ ret = [];
+
+ // Remove the root context
+ if ( ret && context == ret[0] )
+ ret.shift();
+
+ // And combine the results
+ done = jQuery.merge( done, ret );
+
+ return done;
+ },
+
+ classFilter: function(r,m,not){
+ m = " " + m + " ";
+ var tmp = [];
+ for ( var i = 0; r[i]; i++ ) {
+ var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
+ if ( !not && pass || not && !pass )
+ tmp.push( r[i] );
+ }
+ return tmp;
+ },
+
+ filter: function(t,r,not) {
+ var last;
+
+ // Look for common filter expressions
+ while ( t && t != last ) {
+ last = t;
+
+ var p = jQuery.parse, m;
+
+ for ( var i = 0; p[i]; i++ ) {
+ m = p[i].exec( t );
+
+ if ( m ) {
+ // Remove what we just matched
+ t = t.substring( m[0].length );
+
+ m[2] = m[2].replace(/\\/g, "");
+ break;
+ }
+ }
+
+ if ( !m )
+ break;
+
+ // :not() is a special case that can be optimized by
+ // keeping it out of the expression list
+ if ( m[1] == ":" && m[2] == "not" )
+ r = jQuery.filter(m[3], r, true).r;
+
+ // We can get a big speed boost by filtering by class here
+ else if ( m[1] == "." )
+ r = jQuery.classFilter(r, m[2], not);
+
+ else if ( m[1] == "[" ) {
+ var tmp = [], type = m[3];
+
+ for ( var i = 0, rl = r.length; i < rl; i++ ) {
+ var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
+
+ if ( z == null || /href|src|selected/.test(m[2]) )
+ z = jQuery.attr(a,m[2]) || '';
+
+ if ( (type == "" && !!z ||
+ type == "=" && z == m[5] ||
+ type == "!=" && z != m[5] ||
+ type == "^=" && z && !z.indexOf(m[5]) ||
+ type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
+ (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
+ tmp.push( a );
+ }
+
+ r = tmp;
+
+ // We can get a speed boost by handling nth-child here
+ } else if ( m[1] == ":" && m[2] == "nth-child" ) {
+ var merge = {}, tmp = [],
+ test = /(\d*)n\+?(\d*)/.exec(
+ m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
+ !/\D/.test(m[3]) && "n+" + m[3] || m[3]),
+ first = (test[1] || 1) - 0, last = test[2] - 0;
+
+ for ( var i = 0, rl = r.length; i < rl; i++ ) {
+ var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
+
+ if ( !merge[id] ) {
+ var c = 1;
+
+ for ( var n = parentNode.firstChild; n; n = n.nextSibling )
+ if ( n.nodeType == 1 )
+ n.nodeIndex = c++;
+
+ merge[id] = true;
+ }
+
+ var add = false;
+
+ if ( first == 1 ) {
+ if ( last == 0 || node.nodeIndex == last )
+ add = true;
+ } else if ( (node.nodeIndex + last) % first == 0 )
+ add = true;
+
+ if ( add ^ not )
+ tmp.push( node );
+ }
+
+ r = tmp;
+
+ // Otherwise, find the expression to execute
+ } else {
+ var f = jQuery.expr[m[1]];
+ if ( typeof f != "string" )
+ f = jQuery.expr[m[1]][m[2]];
+
+ // Build a custom macro to enclose it
+ f = eval("false||function(a,i){return " + f + "}");
+
+ // Execute it against the current filter
+ r = jQuery.grep( r, f, not );
+ }
+ }
+
+ // Return an array of filtered elements (r)
+ // and the modified expression string (t)
+ return { r: r, t: t };
+ },
+
+ dir: function( elem, dir ){
+ var matched = [];
+ var cur = elem[dir];
+ while ( cur && cur != document ) {
+ 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 && (!elem || n != elem) )
+ r.push( n );
+ }
+
+ return r;
+ }
+});
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code orignated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+ // Bind an event to an element
+ // Original by Dean Edwards
+ add: function(element, type, handler, data) {
+ // For whatever reason, IE has trouble passing the window object
+ // around, causing it to be cloned in the process
+ if ( jQuery.browser.msie && element.setInterval != undefined )
+ element = window;
+
+ // Make sure that the function being executed has a unique ID
+ if ( !handler.guid )
+ handler.guid = this.guid++;
+
+ // if data is passed, bind to handler
+ if( data != undefined ) {
+ // Create temporary function pointer to original handler
+ var fn = handler;
+
+ // Create unique handler function, wrapped around original handler
+ handler = function() {
+ // Pass arguments and context to original handler
+ return fn.apply(this, arguments);
+ };
+
+ // Store data in unique handler
+ handler.data = data;
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ handler.guid = fn.guid;
+ }
+
+ // Namespaced event handlers
+ var parts = type.split(".");
+ type = parts[0];
+ handler.type = parts[1];
+
+ // Init the element's event structure
+ var events = jQuery.data(element, "events") || jQuery.data(element, "events", {});
+
+ var handle = jQuery.data(element, "handle", function(){
+ // returned undefined or false
+ var val;
+
+ // Handle the second event of a trigger and when
+ // an event is called after a page has unloaded
+ if ( typeof jQuery == "undefined" || jQuery.event.triggered )
+ return val;
+
+ val = jQuery.event.handle.apply(element, arguments);
+
+ return val;
+ });
+
+ // Get the current list of functions bound to this event
+ var handlers = events[type];
+
+ // Init the event handler queue
+ if (!handlers) {
+ handlers = events[type] = {};
+
+ // And bind the global event handler to the element
+ if (element.addEventListener)
+ element.addEventListener(type, handle, false);
+ else
+ element.attachEvent("on" + type, handle);
+ }
+
+ // Add the function to the element's handler list
+ handlers[handler.guid] = handler;
+
+ // Keep track of which events have been used, for global triggering
+ this.global[type] = true;
+ },
+
+ guid: 1,
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function(element, type, handler) {
+ var events = jQuery.data(element, "events"), ret, index;
+
+ // Namespaced event handlers
+ if ( typeof type == "string" ) {
+ var parts = type.split(".");
+ type = parts[0];
+ }
+
+ if ( events ) {
+ // type is actually an event object here
+ if ( type && type.type ) {
+ handler = type.handler;
+ type = type.type;
+ }
+
+ if ( !type ) {
+ for ( type in events )
+ this.remove( element, type );
+
+ } else if ( events[type] ) {
+ // remove the given handler for the given type
+ if ( handler )
+ delete events[type][handler.guid];
+
+ // remove all handlers for the given type
+ else
+ for ( handler in events[type] )
+ // Handle the removal of namespaced events
+ if ( !parts[1] || events[type][handler].type == parts[1] )
+ delete events[type][handler];
+
+ // remove generic event handler if no more handlers exist
+ for ( ret in events[type] ) break;
+ if ( !ret ) {
+ if (element.removeEventListener)
+ element.removeEventListener(type, jQuery.data(element, "handle"), false);
+ else
+ element.detachEvent("on" + type, jQuery.data(element, "handle"));
+ ret = null;
+ delete events[type];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ for ( ret in events ) break;
+ if ( !ret ) {
+ jQuery.removeData( element, "events" );
+ jQuery.removeData( element, "handle" );
+ }
+ }
+ },
+
+ trigger: function(type, data, element, donative, extra) {
+ // Clone the incoming data, if any
+ data = jQuery.makeArray(data || []);
+
+ // Handle a global trigger
+ if ( !element ) {
+ // Only trigger if we've ever bound an event for it
+ if ( this.global[type] )
+ jQuery("*").add([window, document]).trigger(type, data);
+
+ // Handle triggering a single element
+ } else {
+ var val, ret, fn = jQuery.isFunction( element[ type ] || null ),
+ // Check to see if we need to provide a fake event, or not
+ evt = !data[0] || !data[0].preventDefault;
+
+ // Pass along a fake event
+ if ( evt )
+ data.unshift( this.fix({ type: type, target: element }) );
+
+ // Enforce the right trigger type
+ data[0].type = type;
+
+ // Trigger the event
+ if ( jQuery.isFunction( jQuery.data(element, "handle") ) )
+ val = jQuery.data(element, "handle").apply( element, data );
+
+ // Handle triggering native .onfoo handlers
+ if ( !fn && element["on"+type] && element["on"+type].apply( element, data ) === false )
+ val = false;
+
+ // Extra functions don't get the custom event object
+ if ( evt )
+ data.shift();
+
+ // Handle triggering of extra function
+ if ( extra && extra.apply( element, data ) === false )
+ val = false;
+
+ // Trigger the native events (except for clicks on links)
+ if ( fn && donative !== false && val !== false && !(jQuery.nodeName(element, 'a') && type == "click") ) {
+ this.triggered = true;
+ element[ type ]();
+ }
+
+ this.triggered = false;
+ }
+
+ return val;
+ },
+
+ handle: function(event) {
+ // returned undefined or false
+ var val;
+
+ // Empty object is for triggered events with no data
+ event = jQuery.event.fix( event || window.event || {} );
+
+ // Namespaced event handlers
+ var parts = event.type.split(".");
+ event.type = parts[0];
+
+ var c = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
+ args.unshift( event );
+
+ for ( var j in c ) {
+ // Pass in a reference to the handler function itself
+ // So that we can later remove it
+ args[0].handler = c[j];
+ args[0].data = c[j].data;
+
+ // Filter the functions by class
+ if ( !parts[1] || c[j].type == parts[1] ) {
+ var tmp = c[j].apply( this, args );
+
+ if ( val !== false )
+ val = tmp;
+
+ if ( tmp === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+
+ // Clean up added properties in IE to prevent memory leak
+ if (jQuery.browser.msie)
+ event.target = event.preventDefault = event.stopPropagation =
+ event.handler = event.data = null;
+
+ return val;
+ },
+
+ fix: function(event) {
+ // store a copy of the original event object
+ // and clone to set read-only properties
+ var originalEvent = event;
+ event = jQuery.extend({}, originalEvent);
+
+ // add preventDefault and stopPropagation since
+ // they will not work on the clone
+ event.preventDefault = function() {
+ // if preventDefault exists run it on the original event
+ if (originalEvent.preventDefault)
+ originalEvent.preventDefault();
+ // otherwise set the returnValue property of the original event to false (IE)
+ originalEvent.returnValue = false;
+ };
+ event.stopPropagation = function() {
+ // if stopPropagation exists run it on the original event
+ if (originalEvent.stopPropagation)
+ originalEvent.stopPropagation();
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ originalEvent.cancelBubble = true;
+ };
+
+ // Fix target property, if necessary
+ if ( !event.target && event.srcElement )
+ event.target = event.srcElement;
+
+ // check if target is a textnode (safari)
+ if (jQuery.browser.safari && event.target.nodeType == 3)
+ event.target = originalEvent.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 e = document.documentElement, b = document.body;
+ event.pageX = event.clientX + (e && e.scrollLeft || b.scrollLeft || 0);
+ event.pageY = event.clientY + (e && e.scrollTop || b.scrollTop || 0);
+ }
+
+ // Add which for key events
+ if ( !event.which && (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 )
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+ return event;
+ }
+};
+
+jQuery.fn.extend({
+ bind: function( type, data, fn ) {
+ return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+ jQuery.event.add( this, type, fn || data, fn && data );
+ });
+ },
+
+ one: function( type, data, fn ) {
+ return this.each(function(){
+ jQuery.event.add( this, type, function(event) {
+ jQuery(this).unbind(event);
+ return (fn || data).apply( this, arguments);
+ }, fn && data);
+ });
+ },
+
+ unbind: function( type, fn ) {
+ return this.each(function(){
+ jQuery.event.remove( this, type, fn );
+ });
+ },
+
+ trigger: function( type, data, fn ) {
+ return this.each(function(){
+ jQuery.event.trigger( type, data, this, true, fn );
+ });
+ },
+
+ triggerHandler: function( type, data, fn ) {
+ if ( this[0] )
+ return jQuery.event.trigger( type, data, this[0], false, fn );
+ },
+
+ toggle: function() {
+ // Save reference to arguments for access in closure
+ var a = arguments;
+
+ return this.click(function(e) {
+ // Figure out which function to execute
+ this.lastToggle = 0 == this.lastToggle ? 1 : 0;
+
+ // Make sure that clicks stop
+ e.preventDefault();
+
+ // and execute the function
+ return a[this.lastToggle].apply( this, [e] ) || false;
+ });
+ },
+
+ hover: function(f,g) {
+
+ // A private function for handling mouse 'hovering'
+ function handleHover(e) {
+ // Check if mouse(over|out) are still within the same parent element
+ var p = e.relatedTarget;
+
+ // Traverse up the tree
+ while ( p && p != this ) try { p = p.parentNode; } catch(e) { p = this; };
+
+ // If we actually just moused on to a sub-element, ignore it
+ if ( p == this ) return false;
+
+ // Execute the right function
+ return (e.type == "mouseover" ? f : g).apply(this, [e]);
+ }
+
+ // Bind the function to the two event listeners
+ return this.mouseover(handleHover).mouseout(handleHover);
+ },
+
+ ready: function(f) {
+ // Attach the listeners
+ bindReady();
+
+ // If the DOM is already ready
+ if ( jQuery.isReady )
+ // Execute the function immediately
+ f.apply( document, [jQuery] );
+
+ // Otherwise, remember the function for later
+ else
+ // Add the function to the wait list
+ jQuery.readyList.push( function() { return f.apply(this, [jQuery]); } );
+
+ return this;
+ }
+});
+
+jQuery.extend({
+ /*
+ * All the code that makes DOM Ready work nicely.
+ */
+ isReady: false,
+ readyList: [],
+
+ // Handle when the DOM is ready
+ ready: function() {
+ // Make sure that the DOM is not already loaded
+ if ( !jQuery.isReady ) {
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If there are functions bound, to execute
+ if ( jQuery.readyList ) {
+ // Execute all of them
+ jQuery.each( jQuery.readyList, function(){
+ this.apply( document );
+ });
+
+ // Reset the list of functions
+ jQuery.readyList = null;
+ }
+ // Remove event listener to avoid memory leak
+ if ( jQuery.browser.mozilla || jQuery.browser.opera )
+ document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
+
+ // Remove script element used by IE hack
+ if( !window.frames.length ) // don't remove if frames are present (#1187)
+ jQuery(window).load(function(){ jQuery("#__ie_init").remove(); });
+ }
+ }
+});
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+ "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
+ "submit,keydown,keypress,keyup,error").split(","), function(i,o){
+
+ // Handle event binding
+ jQuery.fn[o] = function(f){
+ return f ? this.bind(o, f) : this.trigger(o);
+ };
+});
+
+var readyBound = false;
+
+function bindReady(){
+ if ( readyBound ) return;
+ readyBound = true;
+
+ // If Mozilla is used
+ if ( jQuery.browser.mozilla || jQuery.browser.opera )
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
+
+ // If IE is used, use the excellent hack by Matthias Miller
+ // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
+ else if ( jQuery.browser.msie ) {
+
+ // Only works if you document.write() it
+ document.write("<scr" + "ipt id=__ie_init defer=true " +
+ "src=//:><\/script>");
+
+ // Use the defer script hack
+ var script = document.getElementById("__ie_init");
+
+ // script does not exist if jQuery is loaded dynamically
+ if ( script )
+ script.onreadystatechange = function() {
+ if ( this.readyState != "complete" ) return;
+ jQuery.ready();
+ };
+
+ // Clear from memory
+ script = null;
+
+ // If Safari is used
+ } else if ( jQuery.browser.safari )
+ // Continually check to see if the document.readyState is valid
+ jQuery.safariTimer = setInterval(function(){
+ // loaded and complete are both valid states
+ if ( document.readyState == "loaded" ||
+ document.readyState == "complete" ) {
+
+ // If either one are found, remove the timer
+ clearInterval( jQuery.safariTimer );
+ jQuery.safariTimer = null;
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ }, 10);
+
+ // A fallback to window.onload, that will always work
+ jQuery.event.add( window, "load", jQuery.ready );
+}
+jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( jQuery.isFunction( url ) )
+ return this.bind("load", url);
+
+ var off = url.indexOf(" ");
+ if ( off >= 0 ) {
+ var selector = url.slice(off, url.length);
+ url = url.slice(0, off);
+ }
+
+ callback = callback || function(){};
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params )
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = null;
+
+ // Otherwise, build a param string
+ } else {
+ params = jQuery.param( params );
+ type = "POST";
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ data: params,
+ complete: function(res, status){
+ // If successful, inject the HTML into all the matched elements
+ if ( status == "success" || status == "notmodified" )
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div/>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ res.responseText );
+
+ // Add delay to account for Safari's delay in globalEval
+ setTimeout(function(){
+ self.each( callback, [res.responseText, status, res] );
+ }, 13);
+ }
+ });
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param(this.serializeArray());
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ return jQuery.nodeName(this, "form") ?
+ jQuery.makeArray(this.elements) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ (this.checked || /select|textarea/i.test(this.nodeName) ||
+ /text|hidden|password/i.test(this.type));
+ })
+ .map(function(i, elem){
+ var val = jQuery(this).val();
+ return val == null ? null :
+ val.constructor == Array ?
+ jQuery.map( val, function(val, i){
+ return {name: elem.name, value: val};
+ }) :
+ {name: elem.name, value: val};
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+ jQuery.fn[o] = function(f){
+ return this.bind(o, f);
+ };
+});
+
+var jsc = (new Date).getTime();
+
+jQuery.extend({
+ get: function( url, data, callback, type ) {
+ // shift arguments if data argument was ommited
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = null;
+ }
+
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get(url, null, callback, "script");
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get(url, data, callback, "json");
+ },
+
+ post: function( url, data, callback, type ) {
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = {};
+ }
+
+ return jQuery.ajax({
+ type: "POST",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ ajaxSetup: function( settings ) {
+ jQuery.extend( jQuery.ajaxSettings, settings );
+ },
+
+ ajaxSettings: {
+ global: true,
+ type: "GET",
+ timeout: 0,
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ data: null
+ },
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+
+ ajax: function( s ) {
+ var jsonp, jsre = /=(\?|%3F)/g, status, data;
+
+ // Extend the settings, but re-extend 's' so that it can be
+ // checked again later (in the test suite, specifically)
+ s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+ // convert data if not already a string
+ if ( s.data && s.processData && typeof s.data != "string" )
+ s.data = jQuery.param(s.data);
+
+ // Handle JSONP Parameter Callbacks
+ if ( s.dataType == "jsonp" ) {
+ if ( s.type.toLowerCase() == "get" ) {
+ if ( !s.url.match(jsre) )
+ s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+ } else if ( !s.data || !s.data.match(jsre) )
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+ s.dataType = "json";
+ }
+
+ // Build temporary JSONP function
+ if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+ jsonp = "jsonp" + jsc++;
+
+ // Replace the =? sequence both in the query string and the data
+ if ( s.data )
+ s.data = s.data.replace(jsre, "=" + jsonp);
+ s.url = s.url.replace(jsre, "=" + jsonp);
+
+ // We need to make sure
+ // that a JSONP style response is executed properly
+ s.dataType = "script";
+
+ // Handle JSONP-style loading
+ window[ jsonp ] = function(tmp){
+ data = tmp;
+ success();
+ complete();
+ // Garbage collect
+ window[ jsonp ] = undefined;
+ try{ delete window[ jsonp ]; } catch(e){}
+ };
+ }
+
+ if ( s.dataType == "script" && s.cache == null )
+ s.cache = false;
+
+ if ( s.cache === false && s.type.toLowerCase() == "get" )
+ s.url += (s.url.match(/\?/) ? "&" : "?") + "_=" + (new Date()).getTime();
+
+ // If data is available, append data to url for get requests
+ if ( s.data && s.type.toLowerCase() == "get" ) {
+ s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+ // IE likes to send both get and post data, prevent this
+ s.data = null;
+ }
+
+ // Watch for a new set of requests
+ if ( s.global && ! jQuery.active++ )
+ jQuery.event.trigger( "ajaxStart" );
+
+ // If we're requesting a remote document
+ // and trying to load JSON or Script
+ if ( !s.url.indexOf("http") && s.dataType == "script" ) {
+ var head = document.getElementsByTagName("head")[0];
+ var script = document.createElement("script");
+ script.src = s.url;
+
+ // Handle Script loading
+ if ( !jsonp && (s.success || s.complete) ) {
+ var done = false;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function(){
+ if ( !done && (!this.readyState ||
+ this.readyState == "loaded" || this.readyState == "complete") ) {
+ done = true;
+ success();
+ complete();
+ head.removeChild( script );
+ }
+ };
+ }
+
+ head.appendChild(script);
+
+ // We handle everything using the script element injection
+ return;
+ }
+
+ var requestDone = false;
+
+ // Create the request object; Microsoft failed to properly
+ // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+ var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+
+ // Open the socket
+ xml.open(s.type, s.url, s.async);
+
+ // Set the correct header, if data is being sent
+ if ( s.data )
+ xml.setRequestHeader("Content-Type", s.contentType);
+
+ // Set the If-Modified-Since header, if ifModified mode.
+ if ( s.ifModified )
+ xml.setRequestHeader("If-Modified-Since",
+ jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+ // Set header so the called script knows that it's an XMLHttpRequest
+ xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+ // Allow custom headers/mimetypes
+ if ( s.beforeSend )
+ s.beforeSend(xml);
+
+ if ( s.global )
+ jQuery.event.trigger("ajaxSend", [xml, s]);
+
+ // Wait for a response to come back
+ var onreadystatechange = function(isTimeout){
+ // The transfer is complete and the data is available, or the request timed out
+ if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
+ requestDone = true;
+
+ // clear poll interval
+ if (ival) {
+ clearInterval(ival);
+ ival = null;
+ }
+
+ status = isTimeout == "timeout" && "timeout" ||
+ !jQuery.httpSuccess( xml ) && "error" ||
+ s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
+ "success";
+
+ if ( status == "success" ) {
+ // Watch for, and catch, XML document parse errors
+ try {
+ // process the data (runs the xml through httpData regardless of callback)
+ data = jQuery.httpData( xml, s.dataType );
+ } catch(e) {
+ status = "parsererror";
+ }
+ }
+
+ // Make sure that the request was successful or notmodified
+ if ( status == "success" ) {
+ // Cache Last-Modified header, if ifModified mode.
+ var modRes;
+ try {
+ modRes = xml.getResponseHeader("Last-Modified");
+ } catch(e) {} // swallow exception thrown by FF if header is not available
+
+ if ( s.ifModified && modRes )
+ jQuery.lastModified[s.url] = modRes;
+
+ // JSONP handles its own success callback
+ if ( !jsonp )
+ success();
+ } else
+ jQuery.handleError(s, xml, status);
+
+ // Fire the complete handlers
+ complete();
+
+ // Stop memory leaks
+ if ( s.async )
+ xml = null;
+ }
+ };
+
+ if ( s.async ) {
+ // don't attach the handler to the request, just poll it instead
+ var ival = setInterval(onreadystatechange, 13);
+
+ // Timeout checker
+ if ( s.timeout > 0 )
+ setTimeout(function(){
+ // Check to see if the request is still happening
+ if ( xml ) {
+ // Cancel the request
+ xml.abort();
+
+ if( !requestDone )
+ onreadystatechange( "timeout" );
+ }
+ }, s.timeout);
+ }
+
+ // Send the data
+ try {
+ xml.send(s.data);
+ } catch(e) {
+ jQuery.handleError(s, xml, null, e);
+ }
+
+ // firefox 1.5 doesn't fire statechange for sync requests
+ if ( !s.async )
+ onreadystatechange();
+
+ // return XMLHttpRequest to allow aborting the request etc.
+ return xml;
+
+ function success(){
+ // If a local callback was specified, fire it and pass it the data
+ if ( s.success )
+ s.success( data, status );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxSuccess", [xml, s] );
+ }
+
+ function complete(){
+ // Process result
+ if ( s.complete )
+ s.complete(xml, status);
+
+ // The request was completed
+ if ( s.global )
+ jQuery.event.trigger( "ajaxComplete", [xml, s] );
+
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ },
+
+ handleError: function( s, xml, status, e ) {
+ // If a local callback was specified, fire it
+ if ( s.error ) s.error( xml, status, e );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxError", [xml, s, e] );
+ },
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Determines if an XMLHttpRequest was successful or not
+ httpSuccess: function( r ) {
+ try {
+ return !r.status && location.protocol == "file:" ||
+ ( r.status >= 200 && r.status < 300 ) || r.status == 304 ||
+ jQuery.browser.safari && r.status == undefined;
+ } catch(e){}
+ return false;
+ },
+
+ // Determines if an XMLHttpRequest returns NotModified
+ httpNotModified: function( xml, url ) {
+ try {
+ var xmlRes = xml.getResponseHeader("Last-Modified");
+
+ // Firefox always returns 200. check Last-Modified date
+ return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
+ jQuery.browser.safari && xml.status == undefined;
+ } catch(e){}
+ return false;
+ },
+
+ httpData: function( r, type ) {
+ var ct = r.getResponseHeader("content-type");
+ var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
+ var data = xml ? r.responseXML : r.responseText;
+
+ if ( xml && data.documentElement.tagName == "parsererror" )
+ throw "parsererror";
+
+ // If the type is "script", eval it in global context
+ if ( type == "script" )
+ jQuery.globalEval( data );
+
+ // Get the JavaScript object, if JSON is used.
+ if ( type == "json" )
+ data = eval("(" + data + ")");
+
+ return data;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a ) {
+ var s = [];
+
+ // If an array was passed in, assume that it is an array
+ // of form elements
+ if ( a.constructor == Array || a.jquery )
+ // Serialize the form elements
+ jQuery.each( a, function(){
+ s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
+ });
+
+ // Otherwise, assume that it's an object of key/value pairs
+ else
+ // Serialize the key/values
+ for ( var j in a )
+ // If the value is an array then the key names need to be repeated
+ if ( a[j] && a[j].constructor == Array )
+ jQuery.each( a[j], function(){
+ s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
+ });
+ else
+ s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
+
+ // Return the resulting serialization
+ return s.join("&").replace(/%20/g, "+");
+ }
+
+});
+jQuery.fn.extend({
+ show: function(speed,callback){
+ return speed ?
+ this.animate({
+ height: "show", width: "show", opacity: "show"
+ }, speed, callback) :
+
+ this.filter(":hidden").each(function(){
+ this.style.display = this.oldblock ? this.oldblock : "";
+ if ( jQuery.css(this,"display") == "none" )
+ this.style.display = "block";
+ }).end();
+ },
+
+ hide: function(speed,callback){
+ return speed ?
+ this.animate({
+ height: "hide", width: "hide", opacity: "hide"
+ }, speed, callback) :
+
+ this.filter(":visible").each(function(){
+ this.oldblock = this.oldblock || jQuery.css(this,"display");
+ if ( this.oldblock == "none" )
+ this.oldblock = "block";
+ this.style.display = "none";
+ }).end();
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2 ){
+ return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+ this._toggle( fn, fn2 ) :
+ fn ?
+ this.animate({
+ height: "toggle", width: "toggle", opacity: "toggle"
+ }, fn, fn2) :
+ this.each(function(){
+ jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+ });
+ },
+
+ slideDown: function(speed,callback){
+ return this.animate({height: "show"}, speed, callback);
+ },
+
+ slideUp: function(speed,callback){
+ return this.animate({height: "hide"}, speed, callback);
+ },
+
+ slideToggle: function(speed, callback){
+ return this.animate({height: "toggle"}, speed, callback);
+ },
+
+ fadeIn: function(speed, callback){
+ return this.animate({opacity: "show"}, speed, callback);
+ },
+
+ fadeOut: function(speed, callback){
+ return this.animate({opacity: "hide"}, speed, callback);
+ },
+
+ fadeTo: function(speed,to,callback){
+ return this.animate({opacity: to}, speed, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var opt = jQuery.speed(speed, easing, callback);
+
+ return this[ opt.queue === false ? "each" : "queue" ](function(){
+ opt = jQuery.extend({}, opt);
+ var hidden = jQuery(this).is(":hidden"), self = this;
+
+ for ( var p in prop ) {
+ if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+ return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
+
+ if ( p == "height" || p == "width" ) {
+ // Store display property
+ opt.display = jQuery.css(this, "display");
+
+ // Make sure that nothing sneaks out
+ opt.overflow = this.style.overflow;
+ }
+ }
+
+ if ( opt.overflow != null )
+ this.style.overflow = "hidden";
+
+ opt.curAnim = jQuery.extend({}, prop);
+
+ jQuery.each( prop, function(name, val){
+ var e = new jQuery.fx( self, opt, name );
+
+ if ( /toggle|show|hide/.test(val) )
+ e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+ else {
+ var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+ start = e.cur(true) || 0;
+
+ if ( parts ) {
+ var end = parseFloat(parts[2]),
+ unit = parts[3] || "px";
+
+ // We need to compute starting value
+ if ( unit != "px" ) {
+ self.style[ name ] = (end || 1) + unit;
+ start = ((end || 1) / e.cur(true)) * start;
+ self.style[ name ] = start + unit;
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] )
+ end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+ e.custom( start, end, unit );
+ } else
+ e.custom( start, val, "" );
+ }
+ });
+
+ // For JS strict compliance
+ return true;
+ });
+ },
+
+ queue: function(type, fn){
+ if ( jQuery.isFunction(type) ) {
+ fn = type;
+ type = "fx";
+ }
+
+ if ( !type || (typeof type == "string" && !fn) )
+ return queue( this[0], type );
+
+ return this.each(function(){
+ if ( fn.constructor == Array )
+ queue(this, type, fn);
+ else {
+ queue(this, type).push( fn );
+
+ if ( queue(this, type).length == 1 )
+ fn.apply(this);
+ }
+ });
+ },
+
+ stop: function(){
+ var timers = jQuery.timers;
+
+ return this.each(function(){
+ for ( var i = 0; i < timers.length; i++ )
+ if ( timers[i].elem == this )
+ timers.splice(i--, 1);
+ }).dequeue();
+ }
+
+});
+
+var queue = function( elem, type, array ) {
+ if ( !elem )
+ return;
+
+ var q = jQuery.data( elem, type + "queue" );
+
+ if ( !q || array )
+ q = jQuery.data( elem, type + "queue",
+ array ? jQuery.makeArray(array) : [] );
+
+ return q;
+};
+
+jQuery.fn.dequeue = function(type){
+ type = type || "fx";
+
+ return this.each(function(){
+ var q = queue(this, type);
+
+ q.shift();
+
+ if ( q.length )
+ q[0].apply( this );
+ });
+};
+
+jQuery.extend({
+
+ speed: function(speed, easing, fn) {
+ var opt = speed && speed.constructor == Object ? speed : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && easing.constructor != Function && easing
+ };
+
+ opt.duration = (opt.duration && opt.duration.constructor == Number ?
+ opt.duration :
+ { slow: 600, fast: 200 }[opt.duration]) || 400;
+
+ // Queueing
+ opt.old = opt.complete;
+ opt.complete = function(){
+ jQuery(this).dequeue();
+ if ( jQuery.isFunction( opt.old ) )
+ opt.old.apply( this );
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ){
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ if ( !options.orig )
+ options.orig = {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+
+ // Simple function for setting a style value
+ update: function(){
+ if ( this.options.step )
+ this.options.step.apply( this.elem, [ this.now, this ] );
+
+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+ // Set display property to block for height/width animations
+ if ( this.prop == "height" || this.prop == "width" )
+ this.elem.style.display = "block";
+ },
+
+ // Get the current size
+ cur: function(force){
+ if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
+ return this.elem[ this.prop ];
+
+ var r = parseFloat(jQuery.curCSS(this.elem, this.prop, force));
+ return r && r > -10000 ? r : parseFloat(jQuery.css(this.elem, this.prop)) || 0;
+ },
+
+ // Start an animation from one number to another
+ custom: function(from, to, unit){
+ this.startTime = (new Date()).getTime();
+ this.start = from;
+ this.end = to;
+ this.unit = unit || this.unit || "px";
+ this.now = this.start;
+ this.pos = this.state = 0;
+ this.update();
+
+ var self = this;
+ function t(){
+ return self.step();
+ }
+
+ t.elem = this.elem;
+
+ jQuery.timers.push(t);
+
+ if ( jQuery.timers.length == 1 ) {
+ var timer = setInterval(function(){
+ var timers = jQuery.timers;
+
+ for ( var i = 0; i < timers.length; i++ )
+ if ( !timers[i]() )
+ timers.splice(i--, 1);
+
+ if ( !timers.length )
+ clearInterval( timer );
+ }, 13);
+ }
+ },
+
+ // Simple 'show' function
+ show: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ this.custom(0, this.cur());
+
+ // Make sure that we start at a small width/height to avoid any
+ // flash of content
+ if ( this.prop == "width" || this.prop == "height" )
+ this.elem.style[this.prop] = "1px";
+
+ // Start by showing the element
+ jQuery(this.elem).show();
+ },
+
+ // Simple 'hide' function
+ hide: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom(this.cur(), 0);
+ },
+
+ // Each step of an animation
+ step: function(){
+ var t = (new Date()).getTime();
+
+ if ( t > this.options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ this.options.curAnim[ this.prop ] = true;
+
+ var done = true;
+ for ( var i in this.options.curAnim )
+ if ( this.options.curAnim[i] !== true )
+ done = false;
+
+ if ( done ) {
+ if ( this.options.display != null ) {
+ // Reset the overflow
+ this.elem.style.overflow = this.options.overflow;
+
+ // Reset the display
+ this.elem.style.display = this.options.display;
+ if ( jQuery.css(this.elem, "display") == "none" )
+ this.elem.style.display = "block";
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( this.options.hide )
+ this.elem.style.display = "none";
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( this.options.hide || this.options.show )
+ for ( var p in this.options.curAnim )
+ jQuery.attr(this.elem.style, p, this.options.orig[p]);
+ }
+
+ // If a callback was provided, execute it
+ if ( done && jQuery.isFunction( this.options.complete ) )
+ // Execute the complete function
+ this.options.complete.apply( this.elem );
+
+ return false;
+ } else {
+ var n = t - this.startTime;
+ this.state = n / this.options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+ this.now = this.start + ((this.end - this.start) * this.pos);
+
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+
+};
+
+jQuery.fx.step = {
+ scrollLeft: function(fx){
+ fx.elem.scrollLeft = fx.now;
+ },
+
+ scrollTop: function(fx){
+ fx.elem.scrollTop = fx.now;
+ },
+
+ opacity: function(fx){
+ jQuery.attr(fx.elem.style, "opacity", fx.now);
+ },
+
+ _default: function(fx){
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ }
+};
+// The Offset Method
+// Originally By Brandon Aaron, part of the Dimension Plugin
+// http://jquery.com/plugins/project/dimensions
+jQuery.fn.offset = function() {
+ var left = 0, top = 0, elem = this[0], results;
+
+ if ( elem ) with ( jQuery.browser ) {
+ var absolute = jQuery.css(elem, "position") == "absolute",
+ parent = elem.parentNode,
+ offsetParent = elem.offsetParent,
+ doc = elem.ownerDocument,
+ safari2 = safari && parseInt(version) < 522;
+
+ // Use getBoundingClientRect if available
+ if ( elem.getBoundingClientRect ) {
+ box = elem.getBoundingClientRect();
+
+ // Add the document scroll offsets
+ add(
+ box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+ box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop)
+ );
+
+ // IE adds the HTML element's border, by default it is medium which is 2px
+ // IE 6 and IE 7 quirks mode the border width is overwritable by the following css html { border: 0; }
+ // IE 7 standards mode, the border is always 2px
+ if ( msie ) {
+ var border = jQuery("html").css("borderWidth");
+ border = (border == "medium" || jQuery.boxModel && parseInt(version) >= 7) && 2 || border;
+ add( -border, -border );
+ }
+
+ // Otherwise loop through the offsetParents and parentNodes
+ } else {
+
+ // Initial element offsets
+ add( elem.offsetLeft, elem.offsetTop );
+
+ // Get parent offsets
+ while ( offsetParent ) {
+ // Add offsetParent offsets
+ add( offsetParent.offsetLeft, offsetParent.offsetTop );
+
+ // Mozilla and Safari > 2 does not include the border on offset parents
+ // However Mozilla adds the border for table cells
+ if ( mozilla && /^t[d|h]$/i.test(parent.tagName) || !safari2 )
+ border( offsetParent );
+
+ // Safari <= 2 doubles body offsets with an absolutely positioned element or parent
+ if ( safari2 && !absolute && jQuery.css(offsetParent, "position") == "absolute" )
+ absolute = true;
+
+ // Get next offsetParent
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ // Get parent scroll offsets
+ while ( parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
+ // Work around opera inline/table scrollLeft/Top bug
+ if ( !/^inline|table-row.*$/i.test(jQuery.css(parent, "display")) )
+ // Subtract parent scroll offsets
+ add( -parent.scrollLeft, -parent.scrollTop );
+
+ // Mozilla does not add the border for a parent that has overflow != visible
+ if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
+ border( parent );
+
+ // Get next parent
+ parent = parent.parentNode;
+ }
+
+ // Safari doubles body offsets with an absolutely positioned element or parent
+ if ( safari2 && absolute )
+ add( -doc.body.offsetLeft, -doc.body.offsetTop );
+ }
+
+ // Return an object with top and left properties
+ results = { top: top, left: left };
+ }
+
+ return results;
+
+ function border(elem) {
+ add( jQuery.css(elem, "borderLeftWidth"), jQuery.css(elem, "borderTopWidth") );
+ }
+
+ function add(l, t) {
+ left += parseInt(l) || 0;
+ top += parseInt(t) || 0;
+ }
+};
+})();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/static/shell.js Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,193 @@
+// Copyright 2007 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview
+ * Javascript code for the interactive AJAX shell.
+ *
+ * Part of http://code.google.com/p/google-app-engine-samples/.
+ *
+ * Includes a function (shell.runStatement) that sends the current python
+ * statement in the shell prompt text box to the server, and a callback
+ * (shell.done) that displays the results when the XmlHttpRequest returns.
+ *
+ * Also includes cross-browser code (shell.getXmlHttpRequest) to get an
+ * XmlHttpRequest.
+ */
+
+/**
+ * Shell namespace.
+ * @type {Object}
+ */
+var shell = {}
+
+/**
+ * The shell history. history is an array of strings, ordered oldest to
+ * newest. historyCursor is the current history element that the user is on.
+ *
+ * The last history element is the statement that the user is currently
+ * typing. When a statement is run, it's frozen in the history, a new history
+ * element is added to the end of the array for the new statement, and
+ * historyCursor is updated to point to the new element.
+ *
+ * @type {Array}
+ */
+shell.history = [''];
+
+/**
+ * See {shell.history}
+ * @type {number}
+ */
+shell.historyCursor = 0;
+
+/**
+ * A constant for the XmlHttpRequest 'done' state.
+ * @type Number
+ */
+shell.DONE_STATE = 4;
+
+/**
+ * A cross-browser function to get an XmlHttpRequest object.
+ *
+ * @return {XmlHttpRequest?} a new XmlHttpRequest
+ */
+shell.getXmlHttpRequest = function() {
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ } else if (window.ActiveXObject) {
+ try {
+ return new ActiveXObject('Msxml2.XMLHTTP');
+ } catch(e) {
+ return new ActiveXObject('Microsoft.XMLHTTP');
+ }
+ }
+
+ return null;
+};
+
+/**
+ * This is the prompt textarea's onkeypress handler. Depending on the key that
+ * was pressed, it will run the statement, navigate the history, or update the
+ * current statement in the history.
+ *
+ * @param {Event} event the keypress event
+ * @return {Boolean} false to tell the browser not to submit the form.
+ */
+shell.onPromptKeyPress = function(event) {
+ var statement = document.getElementById('statement');
+
+ if (this.historyCursor == this.history.length - 1) {
+ // we're on the current statement. update it in the history before doing
+ // anything.
+ this.history[this.historyCursor] = statement.value;
+ }
+
+ // should we pull something from the history?
+ if (event.ctrlKey && event.keyCode == 38 /* up arrow */) {
+ if (this.historyCursor > 0) {
+ statement.value = this.history[--this.historyCursor];
+ }
+ return false;
+ } else if (event.ctrlKey && event.keyCode == 40 /* down arrow */) {
+ if (this.historyCursor < this.history.length - 1) {
+ statement.value = this.history[++this.historyCursor];
+ }
+ return false;
+ } else if (!event.altKey) {
+ // probably changing the statement. update it in the history.
+ this.historyCursor = this.history.length - 1;
+ this.history[this.historyCursor] = statement.value;
+ }
+
+ // should we submit?
+ if (event.keyCode == 13 /* enter */ && !event.altKey && !event.shiftKey) {
+ return this.runStatement();
+ }
+};
+
+/**
+ * The XmlHttpRequest callback. If the request succeeds, it adds the command
+ * and its resulting output to the shell history div.
+ *
+ * @param {XmlHttpRequest} req the XmlHttpRequest we used to send the current
+ * statement to the server
+ */
+shell.done = function(req) {
+ if (req.readyState == this.DONE_STATE) {
+ var statement = document.getElementById('statement')
+ statement.className = 'prompt';
+
+ // add the command to the shell output
+ var output = document.getElementById('output');
+
+ output.value += '\n'+'Out[]:' + statement.value;
+ statement.value = '';
+
+ // add a new history element
+ this.history.push('');
+ this.historyCursor = this.history.length - 1;
+
+ // add the command's result
+ var result = req.responseText.replace(/^\s*|\s*$/g, ''); // trim whitespace
+ if (result != '')
+ output.value += '\n'+ result ;
+
+ // scroll to the bottom
+ output.scrollTop = output.scrollHeight;
+ if (output.createTextRange) {
+ var range = output.createTextRange();
+ range.collapse(false);
+ range.select();
+ }
+ }
+};
+
+/**
+ * This is the form's onsubmit handler. It sends the python statement to the
+ * server, and registers shell.done() as the callback to run when it returns.
+ *
+ * @return {Boolean} false to tell the browser not to submit the form.
+ */
+shell.runStatement = function() {
+ var form = document.getElementById('form');
+
+ // build a XmlHttpRequest
+ var req = this.getXmlHttpRequest();
+ if (!req) {
+ document.getElementById('ajax-status').innerHTML =
+ "<span class='error'>Your browser doesn't support AJAX. :(</span>";
+ return false;
+ }
+
+ req.onreadystatechange = function() { shell.done(req); };
+
+ // build the query parameter string
+ var params = '';
+ for (i = 0; i < form.elements.length; i++) {
+ var elem = form.elements[i];
+ if (elem.type != 'submit' && elem.type != 'button' && elem.id != 'caret') {
+ var value = escape(elem.value).replace(/\+/g, '%2B'); // escape ignores +
+ params += '&' + elem.name + '=' + value;
+ }
+ }
+
+ // send the request and tell the user.
+ document.getElementById('statement').className = 'prompt processing';
+ req.open(form.method, form.action + '?' + params, true);
+ req.setRequestHeader('Content-type',
+ 'application/x-www-form-urlencoded;charset=UTF-8');
+ req.send(null);
+
+ return false;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/static/shell.js~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,193 @@
+// Copyright 2007 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview
+ * Javascript code for the interactive AJAX shell.
+ *
+ * Part of http://code.google.com/p/google-app-engine-samples/.
+ *
+ * Includes a function (shell.runStatement) that sends the current python
+ * statement in the shell prompt text box to the server, and a callback
+ * (shell.done) that displays the results when the XmlHttpRequest returns.
+ *
+ * Also includes cross-browser code (shell.getXmlHttpRequest) to get an
+ * XmlHttpRequest.
+ */
+
+/**
+ * Shell namespace.
+ * @type {Object}
+ */
+var shell = {}
+
+/**
+ * The shell history. history is an array of strings, ordered oldest to
+ * newest. historyCursor is the current history element that the user is on.
+ *
+ * The last history element is the statement that the user is currently
+ * typing. When a statement is run, it's frozen in the history, a new history
+ * element is added to the end of the array for the new statement, and
+ * historyCursor is updated to point to the new element.
+ *
+ * @type {Array}
+ */
+shell.history = [''];
+
+/**
+ * See {shell.history}
+ * @type {number}
+ */
+shell.historyCursor = 0;
+
+/**
+ * A constant for the XmlHttpRequest 'done' state.
+ * @type Number
+ */
+shell.DONE_STATE = 4;
+
+/**
+ * A cross-browser function to get an XmlHttpRequest object.
+ *
+ * @return {XmlHttpRequest?} a new XmlHttpRequest
+ */
+shell.getXmlHttpRequest = function() {
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ } else if (window.ActiveXObject) {
+ try {
+ return new ActiveXObject('Msxml2.XMLHTTP');
+ } catch(e) {
+ return new ActiveXObject('Microsoft.XMLHTTP');
+ }
+ }
+
+ return null;
+};
+
+/**
+ * This is the prompt textarea's onkeypress handler. Depending on the key that
+ * was pressed, it will run the statement, navigate the history, or update the
+ * current statement in the history.
+ *
+ * @param {Event} event the keypress event
+ * @return {Boolean} false to tell the browser not to submit the form.
+ */
+shell.onPromptKeyPress = function(event) {
+ var statement = document.getElementById('statement');
+
+ if (this.historyCursor == this.history.length - 1) {
+ // we're on the current statement. update it in the history before doing
+ // anything.
+ this.history[this.historyCursor] = statement.value;
+ }
+
+ // should we pull something from the history?
+ if (event.ctrlKey && event.keyCode == 38 /* up arrow */) {
+ if (this.historyCursor > 0) {
+ statement.value = this.history[--this.historyCursor];
+ }
+ return false;
+ } else if (event.ctrlKey && event.keyCode == 40 /* down arrow */) {
+ if (this.historyCursor < this.history.length - 1) {
+ statement.value = this.history[++this.historyCursor];
+ }
+ return false;
+ } else if (!event.altKey) {
+ // probably changing the statement. update it in the history.
+ this.historyCursor = this.history.length - 1;
+ this.history[this.historyCursor] = statement.value;
+ }
+
+ // should we submit?
+ if (event.keyCode == 13 /* enter */ && !event.altKey && !event.shiftKey) {
+ return this.runStatement();
+ }
+};
+
+/**
+ * The XmlHttpRequest callback. If the request succeeds, it adds the command
+ * and its resulting output to the shell history div.
+ *
+ * @param {XmlHttpRequest} req the XmlHttpRequest we used to send the current
+ * statement to the server
+ */
+shell.done = function(req) {
+ if (req.readyState == this.DONE_STATE) {
+ var statement = document.getElementById('statement')
+ statement.className = 'prompt';
+
+ // add the command to the shell output
+ var output = document.getElementById('output');
+
+ output.value += '\n'+'Out[]:' + statement.value;
+ statement.value = '';
+
+ // add a new history element
+ this.history.push('');
+ this.historyCursor = this.history.length - 1;
+
+ // add the command's result
+ var result = req.responseText.replace(/^\s*|\s*$/g, ''); // trim whitespace
+ if (result != '')
+ output.value += '\n'+ result ;
+
+ // scroll to the bottom
+ output.scrollTop = output.scrollHeight;
+ if (output.createTextRange) {
+ var range = output.createTextRange();
+ range.collapse(false);
+ range.select();
+ }
+ }
+};
+
+/**
+ * This is the form's onsubmit handler. It sends the python statement to the
+ * server, and registers shell.done() as the callback to run when it returns.
+ *
+ * @return {Boolean} false to tell the browser not to submit the form.
+ */
+shell.runStatement = function() {
+ var form = document.getElementById('form');
+
+ // build a XmlHttpRequest
+ var req = this.getXmlHttpRequest();
+ if (!req) {
+ document.getElementById('ajax-status').innerHTML =
+ "<span class='error'>Your browser doesn't support AJAX. :(</span>";
+ return false;
+ }
+
+ req.onreadystatechange = function() { shell.done(req); };
+
+ // build the query parameter string
+ var params = '';
+ for (i = 0; i < form.elements.length; i++) {
+ var elem = form.elements[i];
+ if (elem.type != 'submit' && elem.type != 'button' && elem.id != 'caret') {
+ var value = escape(elem.value).replace(/\+/g, '%2B'); // escape ignores +
+ params += '&' + elem.name + '=' + value;
+ }
+ }
+
+ // send the request and tell the user.
+ document.getElementById('statement').className = 'prompt processing';
+ req.open(form.method, form.action + '?' + params, true);
+ req.setRequestHeader('Content-type',
+ 'application/x-www-form-urlencoded;charset=UTF-8');
+ req.send(null);
+
+ return false;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/appjs.js Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,5 @@
+function loadcode(id) {
+ $("#solve_" + id).load(location.protocol + "//" + location.host +
+ "/code/" + id + "/");
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/appjs.js~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,5 @@
+function loadcode(id) {
+$("#solve_" + id).load(location.protocol + "//" + location.host +
+ "/code/" + id + "/");
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/base.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,49 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <script type="text/javascript" src="/static/jquery.js"></script>
+ <script type="text/javascript" src="/static/appjs.js"></script>
+ <title>Fossee Test</title>
+ <link rel="stylesheet" href="/static/pykata.css" type="text/css">
+ </head>
+ <body>
+ <div id="container">
+ <div id="header">
+ <div id="nav">
+ <a href="/">Home</a> |
+ <a href="/accounts/register">Register</a>|
+ {% if user %}
+
+ {% if user.username %}
+ {{ user.username }} |
+ <a href="/accounts/logout">Sign out</a>
+ {% else %}
+ <a href="/accounts/login">Sign in</a>{% endif %}
+ {% endif %}
+ <br /><br />
+ </div>
+ </div>
+ <div id="content">
+ {% block body %}
+ {% endblock %}
+ </div>
+ <div id="footer" style="height:50px; text-align:center;">
+ <strong>FOSSEE, 2010</strong><br />
+ <em>(Powered by MHRD)</em>
+ </div>
+ </div>
+
+ {% block scripts %}
+ {% endblock %}
+ <!-- Google Analytics tracking -->
+ <script type="text/javascript">
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+ </script>
+ <script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-7813330-1");
+ pageTracker._trackPageview();
+ } catch(err) {}</script>
+ </body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/base.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,47 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <title>Fossee Test</title>
+ <link rel="stylesheet" href="/static/pykata.css" type="text/css">
+ </head>
+ <body>
+ <div id="container">
+ <div id="header">
+ <div id="nav">
+ <a href="/">Home</a> |
+ <a href="/accounts/register">Register</a>|
+ {% if user %}
+
+ {% if user.username %}
+ {{ user.username }} |
+ <a href="/accounts/logout">Sign out</a>
+ {% else %}
+ <a href="/accounts/login">Sign in</a>{% endif %}
+ {% endif %}
+ <br /><br />
+ </div>
+ </div>
+ <div id="content">
+ {% block body %}
+ {% endblock %}
+ </div>
+ <div id="footer" style="height:50px; text-align:center;">
+ <strong>FOSSEE, 2010</strong><br />
+ <em>(Powered by MHRD)</em>
+ </div>
+ </div>
+
+ {% block scripts %}
+ {% endblock %}
+ <!-- Google Analytics tracking -->
+ <script type="text/javascript">
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+ </script>
+ <script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-7813330-1");
+ pageTracker._trackPageview();
+ } catch(err) {}</script>
+ </body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/code.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,42 @@
+{# {%extends "base.html"%} #}
+{%block body%}
+<h2>{{ problem.name }}</h2>
+
+
+{% comment %}
+{% load pykata_extras %}
+{% autoescape off %}
+<p>
+{{problem.description|force_escape|spacify_code|linebreaksbr}}
+</p>
+{% endautoescape %}
+{% endcomment %}
+
+<h3>Examples</h3>
+<pre>
+{{ problem.examples }}
+</pre>
+
+ <form method="post" action="/run/">
+ <p><strong>Enter your solution here:</strong></p>
+ <p><textarea id="code-area" name="user_code" rows="22" cols="80">
+{% ifequal pu.classname "ProblemUser" %}{{ pu.solution }}{% else %}{{ problem.skeleton }}{% endifequal %}
+
+ </textarea></p>
+ <input type="hidden" name="problem_id" value="{{ problem.key.id }}" />
+ <p><input type="submit" name="submit" value="Run" /></p>
+ </form>
+
+ <script language="javascript" type="text/javascript" src="/static/edit_area_full.js"></script>
+ <script language="javascript" type="text/javascript">
+ editAreaLoader.init({
+ id: "code-area",
+ syntax: "python",
+ start_highlight: true,
+ allow_resize: "both",
+ font_size: 14,
+ toolbar: "new_document, select_font, |, help",
+ replace_tab_by_spaces: 4
+ });
+ </script>
+{%endblock%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/code.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,42 @@
+{%extends "base.html"%}
+{%block body%}
+<h2>{{ problem.name }}</h2>
+
+
+{% comment %}
+{% load pykata_extras %}
+{% autoescape off %}
+<p>
+{{problem.description|force_escape|spacify_code|linebreaksbr}}
+</p>
+{% endautoescape %}
+{% endcomment %}
+
+<h3>Examples</h3>
+<pre>
+{{ problem.examples }}
+</pre>
+
+ <form method="post" action="/run/">
+ <p><strong>Enter your solution here:</strong></p>
+ <p><textarea id="code-area" name="user_code" rows="22" cols="80">
+{% ifequal pu.classname "ProblemUser" %}{{ pu.solution }}{% else %}{{ problem.skeleton }}{% endifequal %}
+
+ </textarea></p>
+ <input type="hidden" name="problem_id" value="{{ problem.key.id }}" />
+ <p><input type="submit" name="submit" value="Run" /></p>
+ </form>
+
+ <script language="javascript" type="text/javascript" src="/static/edit_area_full.js"></script>
+ <script language="javascript" type="text/javascript">
+ editAreaLoader.init({
+ id: "code-area",
+ syntax: "python",
+ start_highlight: true,
+ allow_resize: "both",
+ font_size: 14,
+ toolbar: "new_document, select_font, |, help",
+ replace_tab_by_spaces: 4
+ });
+ </script>
+{%endblock%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/index.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,7 @@
+{%extends "base.html"%}
+{%block body%}
+
+<p> Welcome to testapp</p>
+
+{%endblock%}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/index.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,46 @@
+{%extends "base.html"%}
+{%block body%}
+
+<p><b>Welcome</b> to PyKata ... the website for Python practice. Learning Python is a skill.
+It takes practice, not just an understanding of the theory. In fact, you can learn
+basic Python without any theory. Just read the help pages if you get stuck. Start
+with the easy problems first. Some of these have hints, or even a complete solution.
+ <big><a href="/vision">vision statement</a></big>
+ <big><a href="/statements">teacher statements</a></big>
+ <big><a href="/static/manifesto.py.txt">manifesto</a></big></p>
+
+<p><b>About Python</b> ... Python is a modern mainstream computer language, much like Java
+and C++, but simpler. It's the closest thing we could find to pseudocode, the language used
+by scientists when they want to express an idea involving computation.</p>
+
+<p>You don't have to take an entire course in programming to learn Python. Every high-school
+graduate, certainly anyone considering a career in technology, should know how to write a
+simple program. Python makes that possible. PyKata is the best way to learn Python.</p>
+
+<h2>Problem Categories</h2>
+<ul>
+ <li><a href="/category/simple">simple</a></li>
+ <li><a href="/category/logic">logic</a></li>
+ <li><a href="/category/list">list</a></li>
+ <li><a href="/category/strings">strings</a></li>
+ <li><a href="/category/math">math</a></li>
+ <li><a href="/category/loops">loops</a></li>
+ <li><a href="/category/recursion">recursion</a></li>
+ <li><a href="/category/oop">oop</a></li>
+</ul>
+
+<h3>News</h3>
+<ol>
+ <li>You can now save your work-in-progress. When solving an exercise, hitting Run automatically saves your work.</li>
+ <li>Progress indicators: We now show which problems you have solved.</li>
+</ol>
+
+<h3>This site is still under development. Coming Soon:</h3>
+<ul>
+ <li>Teacher report to view a student's progress
+ <a href="/static/T_report.htm">Mockup</a></li>
+ <li>More content!!</li>
+</ul>
+
+{%endblock%}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/new_edit_problem.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,22 @@
+{%block body%}
+
+{% if creating %}
+<h2>Upload Problems</h2>
+ <form action="/upload/" method="post" enctype="multipart/form-data">
+ <table>
+ {{ upload_form.as_table }}
+ </table>
+ <input type="submit" value="upload" />
+ </form>
+<hr />
+{% endif %}
+
+<h2>{% if creating %}Add{% else %}Edit{% endif %} Problem</h2>
+ <form action="" method="post">
+ <table>
+ {{ form.as_table }}
+ </table>
+ <input type="submit" value="Save" />
+</form>
+
+{%endblock%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/new_edit_problem.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,22 @@
+{%block body%}
+
+{% if creating %}
+<h2>Upload Problems</h2>
+ <form action="/upload/" method="post" enctype="multipart/form-data">
+ <table>
+ {{ upload_form.as_table }}
+ </table>
+ <input type="submit" value="upload" />
+ </form>
+<hr />
+{% endif %}
+
+<h2>{% if creating %}Add{% else %}Edit{% endif %} Problem</h2>
+ <form action="" method="post">
+ <table>
+ {{ form.as_table }}
+ </table>
+ <input type="submit" value="Save" />
+</form>
+
+{%endblock%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/problems.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,30 @@
+{%extends "base.html"%}
+{% block body %}
+<h2>All Problems</h2>
+<table class="problems" cellspacing="0" width="900">
+ <tr style="color:#00ce1d;font-weight:bold;text-align:center">
+ <td>Description</td>
+<!-- commented because this may be used again for doing all the score stuff -->
+{# {% if user %}<td>Solved</td><td>Edit</td>{% endif %} #}
+ </tr>
+
+{% for entry in entries %}
+<tr>
+ <td>
+ {{ entry.problem|escape }}
+ {{ entry.session|escape }}
+ <div id="solve_{{ entry.problem_id }}">
+ <a class="comment" href="#solve" onclick="return loadcode({{ entry.problem_id }})">solve</a>
+ </td>
+
+</tr>
+</div>
+{% endfor %}
+
+</table>
+
+<p>
+{% if user %}<a href="{% url testapp.views.new_edit %}">Create new problem</a>{% endif %}
+</p>
+
+{%endblock%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/problems.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,27 @@
+{%extends "base.html"%}
+{% block body %}
+<h2>All Problems</h2>
+<table class="problems" cellspacing="0" width="900">
+ <tr style="color:#00ce1d;font-weight:bold;text-align:center">
+ <td>Description</td>
+<!-- commented because this may be used again for doing all the score stuff -->
+{# {% if user %}<td>Solved</td><td>Edit</td>{% endif %} #}
+ </tr>
+
+{% for entry in entries %}
+<tr>
+ <td>
+ {{ entry.problem|escape }}
+ <a id="#solve_{{ entry.problem_id }}" class="comment" href="#solve" onclick="return loadcode({{ entry.problem_id }})">solve</a>
+ </td>
+
+</tr>
+{% endfor %}
+
+</table>
+
+<p>
+{% if user %}<a href="{% url testapp.views.new_edit %}">Create new problem</a>{% endif %}
+</p>
+
+{%endblock%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/activate.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,4 @@
+{% extends 'base.html' %}
+{% block content %}
+Your account has been successfully activated.
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/activation_email.txt Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,9 @@
+Welcome to PyTasks:
+
+Click on the following link
+http://{{site}}/accounts/activate/{{activation_key}}
+and activate your account.
+Note that the account has to activated within {{expiration_days}} days
+
+Regards,
+PyTasks Team
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/activation_email_subject.txt Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,1 @@
+Welcome to PyTasks!
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/cases.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,62 @@
+"""
+This is the "example" module.
+
+The example module supplies one function, factorial(). For example,
+
+>>> factorial(5)
+120
+"""
+
+def factorial(n):
+ """Return the factorial of n, an exact integer >= 0.
+
+ If the result is small enough to fit in an int, return an int.
+ Else return a long.
+
+ >>> [factorial(n) for n in range(6)]
+ [1, 1, 2, 6, 24, 120]
+ >>> [factorial(long(n)) for n in range(6)]
+ [1, 1, 2, 6, 24, 120]
+ >>> factorial(30)
+ 265252859812191058636308480000000L
+ >>> factorial(30L)
+ 265252859812191058636308480000000L
+ >>> factorial(-1)
+ Traceback (most recent call last):
+ ...
+ ValueError: n must be >= 0
+
+ Factorials of floats are OK, but the float must be an exact integer:
+ >>> factorial(30.1)
+ Traceback (most recent call last):
+ ...
+ ValueError: n must be exact integer
+ >>> factorial(30.0)
+ 265252859812191058636308480000000L
+
+ It must also not be ridiculously large:
+ >>> factorial(1e100)
+ Traceback (most recent call last):
+ ...
+ OverflowError: n too large
+ """
+
+ import math
+ if not n >= 0:
+ raise ValueError("n must be >= 0")
+ if math.floor(n) != n:
+ raise ValueError("n must be exact integer")
+ if n+1 == n: # catch a value like 1e300
+ raise OverflowError("n too large")
+ result = 1
+ factor = 2
+ while factor <= n:
+ result *= factor
+ factor += 1
+ return result
+
+
+if __name__ == "__main__":
+ import doctest
+ doctest.testmod()
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/logged_out.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,12 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a></div>{% endblock %}
+
+{% block content %}
+
+<p>{% trans "Thanks for spending some quality time with the Web site today." %}</p>
+
+<p><a href="../">{% trans 'Log in again' %}</a></p>
+
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/login.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,7 @@
+{% block content %}
+<form action="/accounts/login/?next=/" method="post">
+{{ form.as_p }}
+<input type="submit" value="Login" />
+</form>
+<a href="/accounts/password/reset">Forgot password?</a>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/login.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,7 @@
+{% block content %}
+<form action="/accounts/login/" method="post">
+{{ form.as_p }}
+<input type="submit" value="Login" />
+</form>
+<a href="/accounts/password/reset">Forgot password?</a>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/logout.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,6 @@
+{% extends 'base.html' %}
+{% block content %}
+You have successfully logged out of PyTasks.
+<br><br>
+<a href="/">Click here</a> to go back to PyTask Homepage
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/password_change_done.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+{% load i18n %}
+{% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %}{% trans 'Change password' %} / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {% trans 'Password change' %}</div>{% endblock %}
+
+{% block title %}{% trans 'Password change successful' %}{% endblock %}
+
+{% block content %}
+
+<h1>{% trans 'Password change successful' %}</h1>
+
+<p>{% trans 'Your password was changed.' %}</p>
+
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/password_change_form.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,26 @@
+{% extends "base.html" %}
+{% load i18n %}
+{% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %} {% trans 'Change password' %} / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %}
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password change' %}</div>{% endblock %}
+
+{% block title %}{% trans 'Password change' %}{% endblock %}
+
+{% block content %}
+
+<h1>{% trans 'Password change' %}</h1>
+
+<p>{% 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." %}</p>
+
+<form action="" method="post">
+
+{{ form.old_password.errors }}
+<p class="aligned wide"><label for="id_old_password">{% trans 'Old password:' %}</label>{{ form.old_password }}</p>
+{{ form.new_password1.errors }}
+<p class="aligned wide"><label for="id_new_password1">{% trans 'New password:' %}</label>{{ form.new_password1 }}</p>
+{{ form.new_password2.errors }}
+<p class="aligned wide"><label for="id_new_password2">{% trans 'Confirm password:' %}</label>{{ form.new_password2 }}</p>
+
+<p><input type="submit" value="{% trans 'Change my password' %}" /></p>
+</form>
+
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/password_reset_complete.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {% trans 'Password reset' %}</div>{% endblock %}
+
+{% block title %}{% trans 'Password reset complete' %}{% endblock %}
+
+{% block content %}
+
+<h1>{% trans 'Password reset complete' %}</h1>
+
+<p>{% trans "Your password has been set. You may go ahead and log in now." %}</p>
+
+<p><a href="{{ login_url }}">{% trans 'Log in' %}</a></p>
+
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/password_reset_confirm.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,32 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password reset confirmation' %}</div>{% endblock %}
+
+{% block title %}{% trans 'Password reset' %}{% endblock %}
+
+{% block content %}
+
+{% if validlink %}
+
+<h1>{% trans 'Enter new password' %}</h1>
+
+<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
+
+<form action="" method="post">
+{{ form.new_password1.errors }}
+<p class="aligned wide"><label for="id_new_password1">{% trans 'New password:' %}</label>{{ form.new_password1 }}</p>
+{{ form.new_password2.errors }}
+<p class="aligned wide"><label for="id_new_password2">{% trans 'Confirm password:' %}</label>{{ form.new_password2 }}</p>
+<p><input type="submit" value="{% trans 'Change my password' %}" /></p>
+</form>
+
+{% else %}
+
+<h1>{% trans 'Password reset unsuccessful' %}</h1>
+
+<p>{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}</p>
+
+{% endif %}
+
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/password_reset_done.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password reset' %}</div>{% endblock %}
+
+{% block title %}{% trans 'Password reset successful' %}{% endblock %}
+
+{% block content %}
+
+<h1>{% trans 'Password reset successful' %}</h1>
+
+<p>{% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}</p>
+
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/password_reset_email.html Mon May 17 22:33:59 2010 +0530
@@ -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 %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/password_reset_form.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,19 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password reset' %}</div>{% endblock %}
+
+{% block title %}{% trans "Password reset" %}{% endblock %}
+
+{% block content %}
+
+<h1>{% trans "Password reset" %}</h1>
+
+<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p>
+
+<form action="" method="post">
+{{ form.email.errors }}
+<p><label for="id_email">{% trans 'E-mail address:' %}</label> {{ form.email }} <input type="submit" value="{% trans 'Reset my password' %}" /></p>
+</form>
+
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/registration_complete.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,4 @@
+{% extends 'base.html' %}
+{% block content %}
+Please check your email for instructions on activating your account.
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/registration_form.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,7 @@
+{# {% extends 'base.html' %} #}
+{% block content %}
+<form action="/accounts/register/" method="post">
+{{ form.as_p }}
+<input type="submit" value="Submit" />
+</form>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/registration/registration_form.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,7 @@
+{% extends 'base.html' %}
+{% block content %}
+<form action="/accounts/register/" method="post">
+{{ form.as_p }}
+<input type="submit" value="Submit" />
+</form>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/run.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,22 @@
+{%extends "base.html"%}
+{%block body%}
+ {{ results }}
+
+{%endblock%}
+
+{% block scripts %}
+<script type="text/javascript" src="http://www.google.com/jsapi"></script>
+<script type="text/javascript">
+google.load("jquery", "1.3.1");
+google.setOnLoadCallback(function() {
+ $('table.run_result tbody tr td:last-child').each( function(){
+ if ($(this).text() == 'fail'){
+ $(this).parent().addClass('failure')
+ }
+ else if ($(this).text() == 'pass'){
+ $(this).parent().addClass('success')
+ }
+ });
+});
+</script>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/run.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,22 @@
+{%extends "base.html"%}
+{%block body%}
+ {{ result }}
+
+{%endblock%}
+
+{% block scripts %}
+<script type="text/javascript" src="http://www.google.com/jsapi"></script>
+<script type="text/javascript">
+google.load("jquery", "1.3.1");
+google.setOnLoadCallback(function() {
+ $('table.run_result tbody tr td:last-child').each( function(){
+ if ($(this).text() == 'fail'){
+ $(this).parent().addClass('failure')
+ }
+ else if ($(this).text() == 'pass'){
+ $(this).parent().addClass('success')
+ }
+ });
+});
+</script>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/shell.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,108 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<title> Interactive Shell </title>
+<script type="text/javascript" src="/static/shell.js"></script>
+<style type="text/css">
+body {
+ font-family: monospace;
+ font-size: 10pt;
+}
+
+p {
+ margin: 0.5em;
+}
+
+a img {
+ border: none;
+}
+
+.prompt, #output {
+ width: 45em;
+ border: 1px solid silver;
+ background-color: #f5f5f5;
+ font-size: 10pt;
+ margin: 0.5em;
+ padding: 0.5em;
+ padding-right: 0em;
+ overflow-x: hidden;
+}
+
+#toolbar {
+ margin-left: 0.5em;
+ padding-left: 0.5em;
+}
+
+#caret {
+ width: 3.5em;
+ margin-right: 0px;
+ padding-right: 0px;
+ border-right: 0px;
+}
+
+#statement {
+ width: 43em;
+ margin-left: -1em;
+ padding-left: 0px;
+ border-left: 0px;
+ background-position: top right;
+ background-repeat: no-repeat;
+}
+
+.processing {
+ background-image: url("/static/spinner.gif");
+}
+
+#ajax-status {
+ font-weight: bold;
+}
+
+.message {
+ color: #8AD;
+ font-weight: bold;
+ font-style: italic;
+}
+
+.error {
+ color: #F44;
+}
+
+.username {
+ font-weight: bold;
+}
+
+</style>
+</head>
+
+<body>
+
+<textarea id="output" rows="22" readonly="readonly">
+Response Area
+</textarea>
+
+
+
+<form id="form" action="/shell/" method="get">
+ <nobr>
+ <textarea class="prompt" id="caret" readonly="readonly" rows="4"
+ onfocus="document.getElementById('statement').focus()"> In[]: </textarea>
+ <textarea class="prompt" name="statement" id="statement" rows="4"
+ onkeypress="return shell.onPromptKeyPress(event);"></textarea>
+ </nobr>
+ <input type="hidden" name="session" value="{{ session }}" />
+ <input type="submit" style="display: none" />
+</form>
+
+<p id="ajax-status"></p>
+
+<p>use ctrl-up for history </p>
+
+
+
+<script type="text/javascript">
+document.getElementById('statement').focus();
+</script>
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/shell.html~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,106 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<title> Interactive Shell </title>
+<script type="text/javascript" src="/static/shell.js"></script>
+<style type="text/css">
+body {
+ font-family: monospace;
+ font-size: 10pt;
+}
+
+p {
+ margin: 0.5em;
+}
+
+a img {
+ border: none;
+}
+
+.prompt, #output {
+ width: 45em;
+ border: 1px solid silver;
+ background-color: #f5f5f5;
+ font-size: 10pt;
+ margin: 0.5em;
+ padding: 0.5em;
+ padding-right: 0em;
+ overflow-x: hidden;
+}
+
+#toolbar {
+ margin-left: 0.5em;
+ padding-left: 0.5em;
+}
+
+#caret {
+ width: 3.5em;
+ margin-right: 0px;
+ padding-right: 0px;
+ border-right: 0px;
+}
+
+#statement {
+ width: 43em;
+ margin-left: -1em;
+ padding-left: 0px;
+ border-left: 0px;
+ background-position: top right;
+ background-repeat: no-repeat;
+}
+
+.processing {
+ background-image: url("/static/spinner.gif");
+}
+
+#ajax-status {
+ font-weight: bold;
+}
+
+.message {
+ color: #8AD;
+ font-weight: bold;
+ font-style: italic;
+}
+
+.error {
+ color: #F44;
+}
+
+.username {
+ font-weight: bold;
+}
+
+</style>
+</head>
+
+<body>
+
+<textarea id="output" rows="22" readonly="readonly">
+Response Area
+</textarea>
+
+
+
+<form id="form" action="/shell/" method="get">
+ <nobr>
+ <textarea class="prompt" id="caret" readonly="readonly" rows="4"
+ onfocus="document.getElementById('statement').focus()"> In[]: </textarea>
+ <textarea class="prompt" name="statement" id="statement" rows="4"
+ onkeypress="return shell.onPromptKeyPress(event);"></textarea>
+ </nobr>
+ <input type="hidden" name="session" value="{{ session }}" />
+ <input type="submit" style="display: none" />
+</form>
+
+<p id="ajax-status"></p>
+
+
+
+<script type="text/javascript">
+document.getElementById('statement').focus();
+</script>
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/traceback.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,6 @@
+{%extends "base.html"%}
+{%block body%}
+<pre>
+{{ errors }}
+</pre>
+{%endblock%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/templates/upload.html Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,16 @@
+{%extends "base.html"%}
+{%block body%}
+
+<p><b>Your upload was processed!</b></p>
+<p><b>Report - </b></p>
+{% for item in report %}
+ <p>
+ {{item.name}} gave <em class='upload_{{item.status}}'>{{item.status}}</em>
+ {% ifequal item.status "error" %}
+ {{ item.upload_response }}
+ {% endifequal %}
+ </p>
+{% endfor %}
+
+{%endblock%}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/test.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,1 @@
+print "hello world"
Binary file testappproj/test.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/test.py~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,1 @@
+print "hello world"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/#forms.py# Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,54 @@
+from django import forms
+from registration.forms import RegistrationForm
+from django.utils.translation import ugettext_lazy as _
+from testapp.models import Test_User
+from registration.models import RegistrationProfile
+#from google.appengine.ext.db import djangoforms
+import models
+
+
+attrs_dict = { 'class': 'required' }
+
+PROBLEM_CHOICES=(
+ ('P', 'Plotting'),
+ ('S', 'Scripting'),
+)
+
+
+
+class ProblemForm(forms.Form):
+ Description = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),required=True,help_text="To be used as the question")
+ Problem_type = forms.ChoiceField(choices=PROBLEM_CHOICES,required=True)
+ Solution = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),help_text="comma seperated in case of multiple solutions")
+ Solution_Image = forms.ImageField()
+ Session = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}), required=True)
+
+
+ class Meta:
+ model = models.Problem
+ exclude = ('author', 'created', 'modified')
+
+
+
+class Test_UserForm(RegistrationForm):
+
+ fullname = forms.CharField(widget=forms.TextInput(attrs=attrs_dict))
+ class Meta:
+ exclude = ('special_user',)
+
+
+ def save(self, profile_callback=None):
+ new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'],
+ password=self.cleaned_data['password1'],
+ email=self.cleaned_data['email'])
+ new_profile = Test_User(user=new_user, fullname=self.cleaned_data[fullname])
+ new_profile.save()
+ return new_user
+
+
+
+class UploadForm(forms.Form):
+ file = forms.FileField()
+
+ class Meta:
+ model = None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/#views (copy).py# Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,460 @@
+# Python imports
+import doctest
+import logging
+import os
+import traceback
+
+# # AppEngine imports
+
+from django.contrib.auth.models import User
+
+from testappproj.testapp.models import *
+from django.http import HttpResponse
+
+# from google.appengine.api import users
+# from google.appengine.ext.webapp import template
+
+# from google.appengine.ext import db
+# from google.appengine.ext.db import djangoforms
+
+
+# Django imports
+#from django.conf import settings
+#settings._target = None
+#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
+#import django
+from django import http
+from django import shortcuts
+from django.template import Context ,RequestContext
+from django.template.loader import get_template
+
+# Local imports
+from forms import *
+import models
+from helpers import bulkuploader as pykataupload
+from datetime import date
+
+
+def respond(request, user,template, params=None):
+ """Helper to render a response, passing standard stuff to the response.
+
+ Args:
+ request: The request object.
+ user: The User object representing the current user; or None if nobody
+ is logged in.
+ template: The template name; '.html' is appended automatically.
+ params: A dict giving the template parameters; modified in-place.
+
+ Returns:
+ Whatever render_to_response(template, params) returns.
+
+ Raises:
+ Whatever render_to_response(template, params) raises.
+ """
+ if params is None:
+ params = {}
+ if user:
+ params['user'] = user
+ params['sign_out'] = 1
+ # params['is_admin'] = (users.is_current_user_admin())
+ else:
+ params['sign_in'] = 1
+ # if not template.endswith('.html'):
+ template += '.html'
+ return shortcuts.render_to_response(template, params)
+
+def execute_test_cases(request, test_cases, g):
+ li = []
+
+ solved = True
+ for e in test_cases:
+ if not e.want:
+ exec e.source in g
+ continue
+ call = e.source.strip()
+ got = eval(e.source.strip(), g)
+ expected = eval(e.want, g)
+
+ if got == expected:
+ status = 'pass'
+ else:
+ status = 'fail'
+ solved = False
+ li.append([call, expected, "%r" % got, status])
+
+ return li, solved
+
+
+
+
+def index(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+
+ return respond(request , user, 'index')
+
+# def contribution(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'contribution')
+
+# def help(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'help')
+
+# def about(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'about')
+
+# def vision(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'vision')
+
+# def statements(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'statements')
+
+
+def get_pu(problem):
+ '''
+ returns:
+ - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor
+ - "PU_NOT_FOUND": for signed in users when no solution has been attempted.
+ - ProblemUser: for signed in users when a solution has been attempted
+
+ '''
+# user = users.get_current_user()
+# if not user:
+# return "USER_NOT_SIGNED_IN"
+ pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user())
+ pu_results = pu_query.fetch(1)
+ if pu_results:
+ return pu_results[0]
+ return "PU_NOT_FOUND"
+
+def is_solved(problem):
+ pu = get_pu(problem)
+ if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False
+ return pu.solved
+
+def problems(request, category=None):
+ user = request.user
+
+ # if category is None:
+ # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC')
+ # else:
+ # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category)
+
+
+
+
+ # entries = []
+ # for problem in problems:
+ # e = dict(problem=problem,
+ # username=problem.author.nickname().partition('@')[0],
+ # solved=is_solved(problem))
+ # entries.append(e)
+ # problems = entries
+ entries=[]
+ problems=Problem.objects.all()
+ for problem in problems:
+ e = dict(problem=problem.name,
+ username=user.username,
+ problem_id=problem.id
+ )
+ entries.append(e)
+
+# print entries
+
+
+
+ return respond(request, user, 'problems',{'entries' : entries } )
+
+def code(request, problem_id):
+
+ print problem_id
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+# pu = get_pu(problem)
+# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time
+# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False)
+# pu.put()
+# pu = None
+
+ return respond(request, request.user ,'code' , )
+
+def run(request):
+ user = request.user
+ problem_id = request.POST.get('problem_id')
+ if problem_id:
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+ user_code = request.POST.get('user_code')
+
+ if not user_code:
+ return http.HttpResponse('bad request')
+
+ # pu = get_pu(problem)
+ # # update ProblemUser object for this user
+ # if (pu.__class__ == models.ProblemUser):
+ # pu.solution = user_code
+ # pu.put()
+
+ user_code = user_code.replace('\r\n', '\n')
+ user_code += '\n\n'
+
+ errors = ''
+
+
+ try:
+ print user_code
+ compiled = compile(user_code, 'error_file', 'exec')
+ g = {}
+ exec compiled in g
+
+# s = problem.tests.replace('\r\n', '\n')
+# s += '\n\n'
+ # test_cases = doctest.DocTestParser().get_examples(s)
+ # results, solved = execute_test_cases(request, test_cases, g)
+ # if solved:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = True
+ # pu.put()
+ # else:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = False
+ # pu.put()
+ except:
+ errors = traceback.format_exc()
+ return respond(request, user, 'traceback', {'errors': errors})
+ results="solved"
+ return respond(request, request.user, 'run', {'results': results})
+
+def new_edit(request, problem_id=None, internal=False):
+ # internal indicates that it is being called internally by uploader
+ #
+ user = request.user
+ print user.username
+ if user.is_anonymous() :
+ return http.HttpResponseForbidden('You must be an signed in to create edit a problem.')
+
+ if problem_id is None:
+ creating_new = True
+ else:
+ creating_new = False
+
+ problem = None
+ # if problem_id:
+ # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id)))
+ # if problem.author != user and not users.is_current_user_admin():
+ # return http.HttpResponseForbidden('You can only edit your own problems.')
+ # if problem is None:
+ # return http.HttpResponseNotFound('No such problem.')
+
+ form = ProblemForm(data=request.POST or None, instance=problem)
+ upload_form = UploadForm(data=request.POST)
+
+ if not request.POST:
+ return respond(request, user, 'new_edit_problem', {'form':form, 'problem':problem, 'creating':creating_new , 'upload_form' : upload_form })
+
+
+ errors = form.errors
+ if not errors:
+ try:
+ problem = form.save(commit=False)
+ except ValueError, err:
+ errors['__all__'] = unicode(err)
+
+
+ if errors:
+ print "new world"
+ if internal:
+ return ('error',errors)
+ return respond(request, user, 'new_edit_problem',
+ {'form': form, 'problem':problem, 'creating':creating_new})
+
+ if creating_new:
+ # if internal:
+ # if len(request.POST['user_id'])>0:
+ # logging.info(request.POST)
+ # problem.author = users.User(request.POST['user_id'])
+ # else:
+ # problem.author = user
+ # else:
+
+
+
+
+ problem.author = user.username
+ problem.created = date.today()
+ problem. modified=date.today()
+
+ problem.save()
+# l = []
+ # for x in problem.categories:
+ # l.extend(x.split())
+ # problem.categories = l
+ # problem.put()
+
+ if internal:
+ return ('success','success')
+
+
+ return http.HttpResponseRedirect('/problems')
+
+def upload(request):
+ """ upload handler, validates the form and calls handle_uploaded_file
+ for processing further
+ """
+ user = request.user
+ if user is None:
+ return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.')
+
+ if request.method == 'POST':
+ form = UploadForm(request.POST, request.FILES)
+ if form.is_valid():
+ submission_report = handle_uploaded_file(request)
+ print "testing"
+ print submission_report
+
+ return respond(request, user, 'upload', {'report':submission_report})
+ else:
+ return http.HttpResponseForbidden('Oops something went wrong with the upload')
+
+def handle_uploaded_file(request):
+ """ Handles uploaded data, pushes it to existing problem creating code
+ TODO: 1. make efficient by putting actual database code Here
+ 2. Add more security and validation
+ """
+ submission_data = request.FILES['file'].read()
+ if '#---' in submission_data:
+ all_submissions = submission_data.split('#---')[1:-1]
+ # ^^ ignoring the first null and last __main__ code
+ all_submissions = [ pykataupload.Submission(x) for x in all_submissions ]
+ report = []
+
+ for key,each_submission in enumerate(all_submissions):
+ # TODO: handle these later by TaskQueues to avoid timeouts on big uploads
+ # a good way would be to have ajax based status coming back to this page
+ # about each problem in the uploaded file, their status, progress etc.
+ each_submission.parse()
+ request.POST.clear()
+ request.POST.update (each_submission.data_dict)
+ upload_status, upload_response = new_edit(request, internal=True)
+
+ report.append ({'status':upload_status, 'name':each_submission['name'],
+ 'upload_response':upload_response})
+
+ # Yay this hack works :D
+ return report
+ else:
+ return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.')
+
+def shell(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+ statement=request.GET.get('statement','')
+ if statement is not '':
+
+ # the python compiler doesn't like network line endings
+ statement = statement.replace('\r\n', '\n')
+
+ # add a couple newlines at the end of the statement. this makes
+ # single-line expressions such as 'class Foo: pass' evaluate happily.
+ statement += '\n\n'
+ print "statement"+statement
+ # log and compile the statement up front
+ try:
+ logging.info('Compiling and evaluating:\n%s' % statement)
+ compiled = compile(statement, '<string>', 'single')
+ except:
+ return HttpResponse(traceback.format_exc(),mimetype="text/plain")
+# pass
+ return HttpResponse("",mimetype="text/plain")
+ else:
+ return respond(request, user, 'shell')
+ # create a dedicated module to be used as this statement's __main__
+ statement_module = new.module('__main__')
+
+ # use this request's __builtin__, since it changes on each request.
+ # this is needed for import statements, among other things.
+ import __builtin__
+ statement_module.__builtins__ = __builtin__
+
+ # load the session from the datastore
+ session = Session.get(self.request.get('session'))
+
+ # swap in our custom module for __main__. then unpickle the session
+ # globals, run the statement, and re-pickle the session globals, all
+ # inside it.
+ old_main = sys.modules.get('__main__')
+ try:
+ sys.modules['__main__'] = statement_module
+ statement_module.__name__ = '__main__'
+
+ # re-evaluate the unpicklables
+ for code in session.unpicklables:
+ exec code in statement_module.__dict__
+
+ # re-initialize the globals
+ for name, val in session.globals_dict().items():
+ try:
+ statement_module.__dict__[name] = val
+ except:
+ msg = 'Dropping %s since it could not be unpickled.\n' % name
+ self.response.out.write(msg)
+ logging.warning(msg + traceback.format_exc())
+ session.remove_global(name)
+
+ # run!
+ old_globals = dict(statement_module.__dict__)
+ try:
+ old_stdout = sys.stdout
+ old_stderr = sys.stderr
+ try:
+ sys.stdout = self.response.out
+ sys.stderr = self.response.out
+ exec compiled in statement_module.__dict__
+ finally:
+ sys.stdout = old_stdout
+ sys.stderr = old_stderr
+ except:
+ self.response.out.write(traceback.format_exc())
+ return
+
+ # extract the new globals that this statement added
+ new_globals = {}
+ for name, val in statement_module.__dict__.items():
+ if name not in old_globals or val != old_globals[name]:
+ new_globals[name] = val
+
+ if True in [isinstance(val, UNPICKLABLE_TYPES)
+ for val in new_globals.values()]:
+ # this statement added an unpicklable global. store the statement and
+ # the names of all of the globals it added in the unpicklables.
+ session.add_unpicklable(statement, new_globals.keys())
+ logging.debug('Storing this statement as an unpicklable.')
+
+ else:
+ # this statement didn't add any unpicklables. pickle and store the
+ # new globals back into the datastore.
+ for name, val in new_globals.items():
+ if not name.startswith('__'):
+ session.set_global(name, val)
+
+ finally:
+ sys.modules['__main__'] = old_main
+
+ session.put()
+
+
+
Binary file testappproj/testapp/__init__.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/forms.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,64 @@
+from django import forms
+from registration.forms import RegistrationForm
+from django.utils.translation import ugettext_lazy as _
+from testapp.models import Test_User
+from registration.models import RegistrationProfile
+#from google.appengine.ext.db import djangoforms
+import models
+
+
+attrs_dict = { 'class': 'required' }
+
+PROBLEM_CHOICES=(
+ ('P', 'Plotting'),
+ ('S', 'Scripting'),
+)
+
+SESSION_CHOICES=(
+ ('A','DAY 1 SESSION 1'),
+ ('B','DAY 1 SESSION 2'),
+ ('C','DAY 1 SESSION 3'),
+ ('D','DAY 1 SESSION 4'),
+ ('E','DAY 2 SESSION 1'),
+ ('F','DAY 2 SESSION 2'),
+ ('G','DAY 2 SESSION 3'),
+ ('H','DAY 2 SESSION 4'),
+ )
+
+
+class ProblemForm(forms.Form):
+ Description = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),required=True,help_text="To be used as the question")
+ Problem_type = forms.ChoiceField(choices=PROBLEM_CHOICES,required=True)
+ Solution = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),help_text="comma seperated in case of multiple solutions")
+ Solution_Image = forms.ImageField(required=False)
+ Session = forms.ChoiceField(choices=SESSION_CHOICES, required=True)
+
+
+ class Meta:
+ model = models.Problem
+ exclude = ('author', 'created', 'modified')
+
+
+
+class Test_UserForm(RegistrationForm):
+
+ fullname = forms.CharField(widget=forms.TextInput(attrs=attrs_dict))
+ class Meta:
+ exclude = ('special_user',)
+
+
+ def save(self, profile_callback=None):
+ new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'],
+ password=self.cleaned_data['password1'],
+ email=self.cleaned_data['email'])
+ new_profile = Test_User(user=new_user, fullname=self.cleaned_data[fullname])
+ new_profile.save()
+ return new_user
+
+
+
+class UploadForm(forms.Form):
+ file = forms.FileField()
+
+ class Meta:
+ model = None
Binary file testappproj/testapp/forms.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/forms.py~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,25 @@
+from django import forms
+#from google.appengine.ext.db import djangoforms
+import models
+
+
+class ProblemForm(forms.ModelForm):
+ name = forms.CharField(widget=forms.TextInput(attrs={'size': '80'}))
+ categories = forms.CharField(widget=forms.TextInput(attrs={'size': '80'}))
+ description = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}))
+ examples = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}))
+ skeleton = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}))
+ tests = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}))
+ other_tests = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}), required=False)
+ solution = forms.CharField(widget=forms.Textarea(attrs={'rows': '20', 'cols': '80'}), required=False)
+
+ class Meta:
+ model = models.Problem
+ exclude = ('author', 'created', 'modified')
+
+
+# class UploadForm(forms.ModelForm):
+# file = forms.FileField()
+
+# class Meta:
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/helpers/.svn/all-wcprops Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 37
+/svn/!svn/ver/36/trunk/pykata/helpers
+END
+bulkuploader.py
+K 25
+svn:wc:ra_dav:version-url
+V 53
+/svn/!svn/ver/36/trunk/pykata/helpers/bulkuploader.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 49
+/svn/!svn/ver/36/trunk/pykata/helpers/__init__.py
+END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/helpers/.svn/entries Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,96 @@
+10
+
+dir
+47
+http://pykata.googlecode.com/svn/trunk/pykata/helpers
+http://pykata.googlecode.com/svn
+
+
+
+2010-04-05T01:11:22.924441Z
+36
+ideamonk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2167b252-2954-11df-990d-a5851c616dea
+
+bulkuploader.py
+file
+
+
+
+
+2010-04-13T15:15:45.000000Z
+217236b8c5663efd46105616501ee7fb
+2010-04-05T01:11:22.924441Z
+36
+ideamonk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3102
+
+__init__.py
+file
+
+
+
+
+2010-04-13T15:15:45.000000Z
+d784fa8b6d98d27699781bd9a7cf19f0
+2010-04-05T01:11:22.924441Z
+36
+ideamonk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/helpers/.svn/text-base/__init__.py.svn-base Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,1 @@
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/helpers/.svn/text-base/bulkuploader.py.svn-base Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,94 @@
+# UploadFormat Parser -- test version
+# -- ideamonk
+
+class Submission():
+ """
+ A helper class for bulk uploads. It parses the given chunk of bulk
+ upload and tries to submit them to PyKata
+ """
+ def __init__(self, bulk_text):
+ # initialize everything as default/blank as some things might not be
+ # present in submission
+ self.data_dict = dict()
+ self.bulk_text = bulk_text
+ self.multiline_fields = ('description', 'examples')
+ self.data_dict['user_id'] = ''
+
+ def __getitem__(self, key):
+ try:
+ return self.data_dict[key]
+ except :
+ return None
+
+ def __setitem__(self, key, item):
+ # mapping to match form submission for code reuse
+ if key=='pubTests':
+ key = 'tests'
+ if key=='privTests':
+ key='other_tests'
+ if key=='userID':
+ key='user_id'
+
+ self.data_dict[key] = item
+
+ def __str__(self):
+ return str(self.bulk_text)
+
+ def parse(self):
+ """ Parses a problem submission into data fillable in the submission
+ form
+ """
+ chunks = self.bulk_text.split('#-')
+ for chunk in chunks[1:]:
+ # ^^ ignores the first comment line of the problem
+ chunk_key, chunk_data = chunk.split(':',1)
+ chunk_key = chunk_key.strip()
+ if chunk_key in self.multiline_fields:
+ # these are data surrounded in triple quotes, single or double
+ chunk_data = eval(chunk_data).strip('\r\n')
+ else:
+ chunk_data = chunk_data.strip().strip('\r\n')
+ self[chunk_key] = chunk_data
+
+ def talk(self):
+ """ Just a testing function, a submission talks about itself to everyone
+ """
+ print "Hi I am a submission problem on PyKata,"
+ print "Let me tell you something about myself - "
+ print "I was created by -", self['userID']
+ print "My name is -", self['name']
+ print "I belong to these categories -", self['categories']
+ print "Here, something more about myself --"
+ print self['description']
+ print "---------------------------------------"
+ print "My solution --"
+ print self['solution']
+ print "----------------------------------------"
+ print "My skeleton --"
+ print self['skeleton']
+ print "----------------------------------------"
+ print "Public Tests --"
+ print self['pubTests']
+ print "----------------------------------------"
+ print "Private Tests --"
+ print self['privTests']
+ print "----------------------------------------"
+ print "\n So tell me something about you too?"
+
+
+def test_submission_parse():
+ import urllib2
+ example_file = urllib2.urlopen('http://ideamonk.in/code/foo.py').read()
+ example_submissions = example_file.split('#---')[1:-1]
+ # ^^ ignore the first null string and last __main__ test code
+ example_submissions = [ Submission(x) for x in example_submissions ]
+ for key, a_submission in enumerate(example_submissions):
+ print "Problem #", key, "parsed as --"
+ print "*************************************************************"
+ a_submission.parse()
+ a_submission.talk()
+
+if __name__=='__main__':
+ # testing
+ test_submission_parse()
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/helpers/__init__.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,1 @@
+
Binary file testappproj/testapp/helpers/__init__.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/helpers/bulkuploader.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,97 @@
+# UploadFormat Parser -- test version
+# -- ideamonk
+
+class Submission():
+ """
+ A helper class for bulk uploads. It parses the given chunk of bulk
+ upload and tries to submit them to PyKata
+ """
+ def __init__(self, bulk_text):
+ # initialize everything as default/blank as some things might not be
+ # present in submission
+ self.data_dict = dict()
+ self.bulk_text = bulk_text
+ self.multiline_fields = ('description', 'examples')
+ self.data_dict['user_id'] = ''
+
+ def __getitem__(self, key):
+ try:
+ return self.data_dict[key]
+ except :
+ return None
+
+ def __setitem__(self, key, item):
+ # mapping to match form submission for code reuse
+ if key=='pubTests':
+ key = 'tests'
+ if key=='privTests':
+ key='other_tests'
+ if key=='userID':
+ key='user_id'
+
+ self.data_dict[key] = item
+
+ def __str__(self):
+ return str(self.bulk_text)
+
+ def parse(self):
+ """ Parses a problem submission into data fillable in the submission
+ form
+ """
+ chunks = self.bulk_text.split('#-')
+ for chunk in chunks[1:]:
+ # ^^ ignores the first comment line of the problem
+ chunk_key, chunk_data = chunk.split(':',1)
+ chunk_key = chunk_key.strip()
+ if chunk_key in self.multiline_fields:
+ # these are data surrounded in triple quotes, single or double
+ chunk_data = eval(chunk_data).strip('\r\n')
+ else:
+ chunk_data = chunk_data.strip().strip('\r\n')
+ self[chunk_key] = chunk_data
+
+ def talk(self):
+ """ Just a testing function, a submission talks about itself to everyone
+ """
+ print "Hi I am a submission problem on PyKata,"
+ print "Let me tell you something about myself - "
+ print "I was created by -", self['userID']
+ print "My name is -", self['name']
+ print "I belong to these categories -", self['categories']
+ print "Here, something more about myself --"
+ print self['description']
+ print "---------------------------------------"
+ print "My solution --"
+ print self['solution']
+ print "----------------------------------------"
+ print "My skeleton --"
+ print self['skeleton']
+ print "----------------------------------------"
+ print "Public Tests --"
+ print self['pubTests']
+ print "----------------------------------------"
+ print "Private Tests --"
+ print self['privTests']
+ print "----------------------------------------"
+ print "\n So tell me something about you too?"
+
+
+def test_submission_parse():
+ import urllib2
+# example_file = urllib2.urlopen('http://ideamonk.in/code/foo.py').read()
+ example_file = open('/home/amit/foo2.py').read()
+ example_submissions = example_file.split('#---')[1:-1]
+ # ^^ ignore the first null string and last __main__ test code
+ print example_submissions
+ example_submissions = [ Submission(x) for x in example_submissions ]
+
+ for key, a_submission in enumerate(example_submissions):
+ print "Problem #", key, "parsed as --"
+ print "*************************************************************"
+ a_submission.parse()
+ a_submission.talk()
+
+if __name__=='__main__':
+ # testing
+ test_submission_parse()
+
Binary file testappproj/testapp/helpers/bulkuploader.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/helpers/bulkuploader.py~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,97 @@
+# UploadFormat Parser -- test version
+# -- ideamonk
+
+class Submission():
+ """
+ A helper class for bulk uploads. It parses the given chunk of bulk
+ upload and tries to submit them to PyKata
+ """
+ def __init__(self, bulk_text):
+ # initialize everything as default/blank as some things might not be
+ # present in submission
+ self.data_dict = dict()
+ self.bulk_text = bulk_text
+ self.multiline_fields = ('description', 'examples')
+ self.data_dict['user_id'] = ''
+
+ def __getitem__(self, key):
+ try:
+ return self.data_dict[key]
+ except :
+ return None
+
+ def __setitem__(self, key, item):
+ # mapping to match form submission for code reuse
+ if key=='pubTests':
+ key = 'tests'
+ if key=='privTests':
+ key='other_tests'
+ if key=='userID':
+ key='user_id'
+
+ self.data_dict[key] = item
+
+ def __str__(self):
+ return str(self.bulk_text)
+
+ def parse(self):
+ """ Parses a problem submission into data fillable in the submission
+ form
+ """
+ chunks = self.bulk_text.split('#-')
+ for chunk in chunks[1:]:
+ # ^^ ignores the first comment line of the problem
+ chunk_key, chunk_data = chunk.split(':',1)
+ chunk_key = chunk_key.strip()
+ if chunk_key in self.multiline_fields:
+ # these are data surrounded in triple quotes, single or double
+ chunk_data = eval(chunk_data).strip('\r\n')
+ else:
+ chunk_data = chunk_data.strip().strip('\r\n')
+ self[chunk_key] = chunk_data
+
+ def talk(self):
+ """ Just a testing function, a submission talks about itself to everyone
+ """
+ print "Hi I am a submission problem on PyKata,"
+ print "Let me tell you something about myself - "
+ print "I was created by -", self['userID']
+ print "My name is -", self['name']
+ print "I belong to these categories -", self['categories']
+ print "Here, something more about myself --"
+ print self['description']
+ print "---------------------------------------"
+ print "My solution --"
+ print self['solution']
+ print "----------------------------------------"
+ print "My skeleton --"
+ print self['skeleton']
+ print "----------------------------------------"
+ print "Public Tests --"
+ print self['pubTests']
+ print "----------------------------------------"
+ print "Private Tests --"
+ print self['privTests']
+ print "----------------------------------------"
+ print "\n So tell me something about you too?"
+
+
+def test_submission_parse():
+ import urllib2
+# example_file = urllib2.urlopen('http://ideamonk.in/code/foo.py').read()
+ example_file = open('/home/amit/Downloads/foo.py').read()
+ example_submissions = example_file.split('#---')[1:-1]
+ # ^^ ignore the first null string and last __main__ test code
+ print example_submissions
+ example_submissions = [ Submission(x) for x in example_submissions ]
+
+ for key, a_submission in enumerate(example_submissions):
+ print "Problem #", key, "parsed as --"
+ print "*************************************************************"
+ a_submission.parse()
+ a_submission.talk()
+
+if __name__=='__main__':
+ # testing
+ test_submission_parse()
+
Binary file testappproj/testapp/management/__init__.pyc has changed
Binary file testappproj/testapp/management/commands/__init__.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/management/commands/seed_db.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,45 @@
+import sys
+from datetime import datetime
+from random import randrange
+
+from django.core.management.base import NoArgsCommand
+from django.contrib.auth.models import User
+
+
+
+
+
+
+from testapp.models import Test_User
+
+
+def seed_db():
+ """ a method to seed the database with random data """
+
+# defaultMentor = userEvents.createSuUser("admin", "admin@example.com", "123456", datetime.now(), "M")
+# mentor_profile = defaultMentor.get_profile()
+# userEvents.updateProfile(mentor_profile, {'rights':"AD"})
+
+ for i in range(1,21):
+
+ username = 'user'+str(i)
+ email = username+'@example.com'
+ password = '123456'
+ fullname='user user'
+# dob = datetime.now()
+# gender = "M"
+# user = userEvents.createUser(username,email,password,dob,gender)
+# create_notification("NU", user)
+ user=User.objects.create_user(username=username,email=email,password=password)
+ user.is_active = True
+ user.save()
+ test_user=Test_User(user_id=user.id,fullname=fullname)
+ test_user.save()
+
+
+class Command(NoArgsCommand):
+
+ def handle_noargs(self, **options):
+ """ Just copied the code from seed_db.py """
+
+ seed_db()
Binary file testappproj/testapp/management/commands/seed_db.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/models.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,70 @@
+from django.db import models
+from django.contrib.auth.models import User
+from django.contrib.auth.models import Group, Permission
+
+
+
+# class ProblemPermission(models.Model):
+# """Abstract page permissions
+# """
+# #who
+# user = models.ForeignKey(User)
+# #what
+# can_change = models.BooleanField("can edit", default=False)
+# can_add = models.BooleanField("can add", default=False)
+# can_delete = models.BooleanField("can delete", default=False)
+
+
+# class Meta:
+# abstract = True
+# app_label = 'testapp'
+
+PROBLEM_CHOICES=(
+ ('P', 'Plotting'),
+ ('S', 'Scripting'),
+)
+
+
+SESSION_CHOICES=(
+ ('A','DAY 1 SESSION 1'),
+ ('B','DAY 1 SESSION 2'),
+ ('C','DAY 1 SESSION 3'),
+ ('D','DAY 1 SESSION 4'),
+ ('E','DAY 2 SESSION 1'),
+ ('F','DAY 2 SESSION 2'),
+ ('G','DAY 2 SESSION 3'),
+ ('H','DAY 1 SESSION 4'),
+ )
+
+class Problem(models.Model):
+ # name = models.CharField(blank=False,max_length=255)
+ description = models.CharField(blank=False , max_length=255)
+ problem_type=models.CharField(blank = False ,max_length=1, choices=PROBLEM_CHOICES)
+ solution = models.CharField(blank=True ,max_length=255)
+ solution_image = models.ImageField(blank = True ,upload_to='plots')
+ session = models.CharField(blank=False ,max_length=1,choices=SESSION_CHOICES)
+ author = models.CharField(max_length=255)
+ created = models.DateTimeField()
+ modified = models.DateTimeField()
+
+
+
+ #if user.has_perm('testapp.add_bar') and user.has_perm('foo.change_bar') and user.has_perm('foo.delete_bar')
+
+class Test_User(models.Model):
+ #problem = models.ForeignKey('Problem')
+ user = models.ForeignKey(User, unique=True)
+ fullname=models.CharField(max_length=255)
+
+
+
+
+
+
+
+
+
+
+
+
+
Binary file testappproj/testapp/models.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/models.py~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,25 @@
+from django.db import models
+
+
+class Problem(models.Model):
+ name = models.CharField(blank=False,max_length=255)
+# categories = models.()
+ description = models.CharField(max_length=255)
+ examples = models.CharField(max_length=255)
+ skeleton = models.CharField(max_length=255)
+ tests = models.CharField(max_length=255)
+ other_tests = models.CharField(max_length=255)
+ solution = models.CharField(max_length=255)
+ author = models.CharField(max_length=255)
+ created = models.DateTimeField()
+ modified = models.DateTimeField()
+
+
+class ProblemUser(models.Model):
+ problem = models.ForeignKey('Problem')
+ # user = models.UserProperty()
+ solution = models.CharField(max_length=255)
+ solved = models.BooleanField()
+ def classname(self):
+ return "ProblemUser"
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/tests.py Mon May 17 22:33:59 2010 +0530
@@ -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
+"""}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/views (copy).py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,386 @@
+# Python imports
+import doctest
+import logging
+import os
+import traceback
+
+# # AppEngine imports
+
+from django.contrib.auth.models import User
+
+from testappproj.testapp.models import *
+from django.http import HttpResponse
+
+# from google.appengine.api import users
+# from google.appengine.ext.webapp import template
+
+# from google.appengine.ext import db
+# from google.appengine.ext.db import djangoforms
+
+
+# Django imports
+#from django.conf import settings
+#settings._target = None
+#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
+#import django
+from django import http
+from django import shortcuts
+from django.template import Context ,RequestContext
+from django.template.loader import get_template
+
+# Local imports
+from forms import *
+import models
+from helpers import bulkuploader as pykataupload
+from datetime import date
+
+
+def respond(request, user,template, params=None):
+ """Helper to render a response, passing standard stuff to the response.
+
+ Args:
+ request: The request object.
+ user: The User object representing the current user; or None if nobody
+ is logged in.
+ template: The template name; '.html' is appended automatically.
+ params: A dict giving the template parameters; modified in-place.
+
+ Returns:
+ Whatever render_to_response(template, params) returns.
+
+ Raises:
+ Whatever render_to_response(template, params) raises.
+ """
+ if params is None:
+ params = {}
+ if user:
+ params['user'] = user
+ params['sign_out'] = 1
+ # params['is_admin'] = (users.is_current_user_admin())
+ else:
+ params['sign_in'] = 1
+ # if not template.endswith('.html'):
+ template += '.html'
+ return shortcuts.render_to_response(template, params)
+
+def execute_test_cases(request, test_cases, g):
+ li = []
+
+ solved = True
+ for e in test_cases:
+ if not e.want:
+ exec e.source in g
+ continue
+ call = e.source.strip()
+ got = eval(e.source.strip(), g)
+ expected = eval(e.want, g)
+
+ if got == expected:
+ status = 'pass'
+ else:
+ status = 'fail'
+ solved = False
+ li.append([call, expected, "%r" % got, status])
+
+ return li, solved
+
+
+
+
+def index(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+
+ return respond(request , user, 'index')
+
+# def contribution(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'contribution')
+
+# def help(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'help')
+
+# def about(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'about')
+
+# def vision(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'vision')
+
+# def statements(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'statements')
+
+
+def get_pu(problem):
+ '''
+ returns:
+ - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor
+ - "PU_NOT_FOUND": for signed in users when no solution has been attempted.
+ - ProblemUser: for signed in users when a solution has been attempted
+
+ '''
+# user = users.get_current_user()
+# if not user:
+# return "USER_NOT_SIGNED_IN"
+ pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user())
+ pu_results = pu_query.fetch(1)
+ if pu_results:
+ return pu_results[0]
+ return "PU_NOT_FOUND"
+
+def is_solved(problem):
+ pu = get_pu(problem)
+ if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False
+ return pu.solved
+
+def problems(request, category=None):
+ user = request.user
+
+ # if category is None:
+ # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC')
+ # else:
+ # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category)
+
+
+
+
+ # entries = []
+ # for problem in problems:
+ # e = dict(problem=problem,
+ # username=problem.author.nickname().partition('@')[0],
+ # solved=is_solved(problem))
+ # entries.append(e)
+ # problems = entries
+ entries=[]
+ problems=Problem.objects.all()
+ for problem in problems:
+ e = dict(problem=problem.name,
+ username=user.username,
+ problem_id=problem.id
+ )
+ entries.append(e)
+
+# print entries
+
+
+
+ return respond(request, user, 'problems',{'entries' : entries } )
+
+def code(request, problem_id):
+
+ print problem_id
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+# pu = get_pu(problem)
+# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time
+# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False)
+# pu.put()
+# pu = None
+
+ return respond(request, request.user ,'code' , )
+
+def run(request):
+ user = request.user
+ problem_id = request.POST.get('problem_id')
+ if problem_id:
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+ user_code = request.POST.get('user_code')
+
+ if not user_code:
+ return http.HttpResponse('bad request')
+
+ # pu = get_pu(problem)
+ # # update ProblemUser object for this user
+ # if (pu.__class__ == models.ProblemUser):
+ # pu.solution = user_code
+ # pu.put()
+
+ user_code = user_code.replace('\r\n', '\n')
+ user_code += '\n\n'
+
+ errors = ''
+
+
+ try:
+ print user_code
+ compiled = compile(user_code, 'error_file', 'exec')
+ g = {}
+ exec compiled in g
+
+# s = problem.tests.replace('\r\n', '\n')
+# s += '\n\n'
+ # test_cases = doctest.DocTestParser().get_examples(s)
+ # results, solved = execute_test_cases(request, test_cases, g)
+ # if solved:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = True
+ # pu.put()
+ # else:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = False
+ # pu.put()
+ except:
+ errors = traceback.format_exc()
+ return respond(request, user, 'traceback', {'errors': errors})
+ results="solved"
+ return respond(request, request.user, 'run', {'results': results})
+
+def new_edit(request, problem_id=None, internal=False):
+ # internal indicates that it is being called internally by uploader
+ #
+ user = request.user
+ print user.username
+ if user.is_anonymous() :
+ return http.HttpResponseForbidden('You must be an signed in to create edit a problem.')
+
+ if problem_id is None:
+ creating_new = True
+ else:
+ creating_new = False
+
+ problem = None
+ # if problem_id:
+ # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id)))
+ # if problem.author != user and not users.is_current_user_admin():
+ # return http.HttpResponseForbidden('You can only edit your own problems.')
+ # if problem is None:
+ # return http.HttpResponseNotFound('No such problem.')
+
+ form = ProblemForm(data=request.POST or None, instance=problem)
+ upload_form = UploadForm(data=request.POST)
+
+ if not request.POST:
+ return respond(request, user, 'new_edit_problem', {'form':form, 'problem':problem, 'creating':creating_new , 'upload_form' : upload_form })
+
+
+ errors = form.errors
+ if not errors:
+ try:
+ problem = form.save(commit=False)
+ except ValueError, err:
+ errors['__all__'] = unicode(err)
+
+
+ if errors:
+ print "new world"
+ if internal:
+ return ('error',errors)
+ return respond(request, user, 'new_edit_problem',
+ {'form': form, 'problem':problem, 'creating':creating_new})
+
+ if creating_new:
+ # if internal:
+ # if len(request.POST['user_id'])>0:
+ # logging.info(request.POST)
+ # problem.author = users.User(request.POST['user_id'])
+ # else:
+ # problem.author = user
+ # else:
+
+
+
+
+ problem.author = user.username
+ problem.created = date.today()
+ problem. modified=date.today()
+
+ problem.save()
+# l = []
+ # for x in problem.categories:
+ # l.extend(x.split())
+ # problem.categories = l
+ # problem.put()
+
+ if internal:
+ return ('success','success')
+
+
+ return http.HttpResponseRedirect('/problems')
+
+def upload(request):
+ """ upload handler, validates the form and calls handle_uploaded_file
+ for processing further
+ """
+ user = request.user
+ if user is None:
+ return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.')
+
+ if request.method == 'POST':
+ form = UploadForm(request.POST, request.FILES)
+ if form.is_valid():
+ submission_report = handle_uploaded_file(request)
+ print "testing"
+ print submission_report
+
+ return respond(request, user, 'upload', {'report':submission_report})
+ else:
+ return http.HttpResponseForbidden('Oops something went wrong with the upload')
+
+def handle_uploaded_file(request):
+ """ Handles uploaded data, pushes it to existing problem creating code
+ TODO: 1. make efficient by putting actual database code Here
+ 2. Add more security and validation
+ """
+ submission_data = request.FILES['file'].read()
+ if '#---' in submission_data:
+ all_submissions = submission_data.split('#---')[1:-1]
+ # ^^ ignoring the first null and last __main__ code
+ all_submissions = [ pykataupload.Submission(x) for x in all_submissions ]
+ report = []
+
+ for key,each_submission in enumerate(all_submissions):
+ # TODO: handle these later by TaskQueues to avoid timeouts on big uploads
+ # a good way would be to have ajax based status coming back to this page
+ # about each problem in the uploaded file, their status, progress etc.
+ each_submission.parse()
+ request.POST.clear()
+ request.POST.update (each_submission.data_dict)
+ upload_status, upload_response = new_edit(request, internal=True)
+
+ report.append ({'status':upload_status, 'name':each_submission['name'],
+ 'upload_response':upload_response})
+
+ # Yay this hack works :D
+ return report
+ else:
+ return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.')
+
+def shell(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+ statement=request.GET.get('statement','')
+ if statement is not '':
+
+ # the python compiler doesn't like network line endings
+ statement = statement.replace('\r\n', '\n')
+
+ # add a couple newlines at the end of the statement. this makes
+ # single-line expressions such as 'class Foo: pass' evaluate happily.
+ statement += '\n\n'
+ print "statement"+statement
+ # log and compile the statement up front
+ try:
+ logging.info('Compiling and evaluating:\n%s' % statement)
+ compiled = compile(statement, '<string>', 'single')
+ except:
+ return HttpResponse(traceback.format_exc(),mimetype="text/plain")
+# pass
+ return HttpResponse("",mimetype="text/plain")
+ else:
+ return respond(request, user, 'shell')
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/views.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,439 @@
+# Python imports
+import doctest
+import logging
+import os
+import traceback
+import random
+
+
+# # AppEngine imports
+
+from django.contrib.auth.models import User
+
+from testappproj.testapp.models import *
+from django.http import HttpResponse
+
+# from google.appengine.api import users
+# from google.appengine.ext.webapp import template
+
+# from google.appengine.ext import db
+# from google.appengine.ext.db import djangoforms
+
+
+# Django imports
+#from django.conf import settings
+#settings._target = None
+#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
+#import django
+from django import http
+from django import shortcuts
+from django.template import Context ,RequestContext
+from django.template.loader import get_template
+
+# Local imports
+from forms import *
+import models
+from helpers import bulkuploader as pykataupload
+from datetime import date
+from django.contrib.auth.decorators import permission_required
+from models import Problem
+
+
+def respond(request, user,template, params=None):
+ """Helper to render a response, passing standard stuff to the response.
+
+ Args:
+ request: The request object.
+ user: The User object representing the current user; or None if nobody
+ is logged in.
+ template: The template name; '.html' is appended automatically.
+ params: A dict giving the template parameters; modified in-place.
+
+ Returns:
+ Whatever render_to_response(template, params) returns.
+
+ Raises:
+ Whatever render_to_response(template, params) raises.
+ """
+ if params is None:
+ params = {}
+ if user:
+ params['user'] = user
+ params['sign_out'] = 1
+ # params['is_admin'] = (users.is_current_user_admin())
+ else:
+ params['sign_in'] = 1
+ # if not template.endswith('.html'):
+ template += '.html'
+ return shortcuts.render_to_response(template, params)
+
+def execute_test_cases(request, test_cases, g):
+ li = []
+
+ solved = True
+ for e in test_cases:
+ if not e.want:
+ exec e.source in g
+ continue
+ call = e.source.strip()
+ got = eval(e.source.strip(), g)
+ expected = eval(e.want, g)
+
+ if got == expected:
+ status = 'pass'
+ else:
+ status = 'fail'
+ solved = False
+ li.append([call, expected, "%r" % got, status])
+
+ return li, solved
+
+
+
+
+def index(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+
+ return respond(request , user, 'index')
+
+# def contribution(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'contribution')
+
+# def help(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'help')
+
+# def about(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'about')
+
+# def vision(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'vision')
+
+# def statements(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'statements')
+
+
+def get_pu(problem):
+ '''
+ returns:
+ - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor
+ - "PU_NOT_FOUND": for signed in users when no solution has been attempted.
+ - ProblemUser: for signed in users when a solution has been attempted
+
+ '''
+# user = users.get_current_user()
+# if not user:
+# return "USER_NOT_SIGNED_IN"
+ pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user())
+ pu_results = pu_query.fetch(1)
+ if pu_results:
+ return pu_results[0]
+ return "PU_NOT_FOUND"
+
+# def is_solved(problem):
+# pu = get_pu(problem)
+# if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False
+# return pu.solved
+
+def problems(request, category=None):
+ user = request.user
+
+ # if category is None:
+ # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC')
+ # else:
+ # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category)
+
+
+
+
+ # entries = []
+ # for problem in problems:
+ # e = dict(problem=problem,
+ # username=problem.author.nickname().partition('@')[0],
+ # solved=is_solved(problem))
+ # entries.append(e)
+ # problems = entries
+ entries=[]
+ all_sessions=set([element.session for element in Problem.objects.all()])
+ print all_sessions
+
+ # for problem in problems:
+ # e = dict(problem=problem.description,
+ # username=user.username,
+ # problem_id=problem.id
+
+ # )
+ # entries.append(e)
+
+# print entries
+
+
+ #get problems to solve from each session.
+ for session in all_sessions:
+ get_problem=random.Random().choice(Problem.objects.filter(session=session))
+ e = dict(problem=get_problem.description,
+ username=user.username,
+ problem_id=get_problem.id,
+ session =get_problem.session
+ )
+ entries.append(e)
+
+
+ return respond(request, user, 'problems',{'entries' : entries } )
+
+def code(request, problem_id):
+
+ print problem_id
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+# pu = get_pu(problem)
+# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time
+# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False)
+# pu.put()
+# pu = None
+
+ return respond(request, request.user ,'code' , )
+
+def run(request):
+ user = request.user
+ problem_id = request.POST.get('problem_id')
+ if problem_id:
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+ user_code = request.POST.get('user_code')
+
+ if not user_code:
+ return http.HttpResponse('bad request')
+
+ # pu = get_pu(problem)
+ # # update ProblemUser object for this user
+ # if (pu.__class__ == models.ProblemUser):
+ # pu.solution = user_code
+ # pu.put()
+
+ user_code = user_code.replace('\r\n', '\n')
+ user_code += '\n\n'
+
+ errors = ''
+
+
+ try:
+ print user_code
+ compiled = compile(user_code, 'error_file', 'exec')
+ g = {}
+ exec compiled in g
+
+# s = problem.tests.replace('\r\n', '\n')
+# s += '\n\n'
+ # test_cases = doctest.DocTestParser().get_examples(s)
+ # results, solved = execute_test_cases(request, test_cases, g)
+ # if solved:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = True
+ # pu.put()
+ # else:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = False
+ # pu.put()
+ except:
+ errors = traceback.format_exc()
+ return respond(request, user, 'traceback', {'errors': errors})
+ results="solved"
+ return respond(request, request.user, 'run', {'results': results})
+
+
+@permission_required('testapp.add_problem' , login_url="/code/1234")
+def new_edit(request, problem_id=None, internal=False):
+
+
+
+ # internal indicates that it is being called internally by uploader
+ #
+ user = request.user
+# print user.get_all_permissions()
+ print user.username
+ if user.is_anonymous() :
+ return http.HttpResponseForbidden('You must be an signed in to create edit a problem.')
+
+ if problem_id is None:
+ creating_new = True
+ else:
+ creating_new = False
+
+# problem = None
+ # if problem_id:
+ # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id)))
+ # if problem.author != user and not users.is_current_user_admin():
+ # return http.HttpResponseForbidden('You can only edit your own problems.')
+ # if problem is None:
+ # return http.HttpResponseNotFound('No such problem.')
+
+# formset = ProblemForm(data=request.POST)
+# instance=formset.save()
+# # upload_form = UploadForm(data=request.POST)
+
+ if request.method == 'POST':
+ form = ProblemForm(request.POST)
+ else:
+ form = ProblemForm()
+
+
+
+ if not request.POST:
+ return respond(request, user, 'new_edit_problem', {'form':form, 'problem':None, 'creating':creating_new })
+
+# print form
+ #errors = form.errors
+ #print str(errors)+"errors"
+
+
+ #if not errors:
+ # try:
+
+ if form.is_valid():
+
+ description = form.cleaned_data['Description']
+ problem_type=form.cleaned_data['Problem_type']
+ solution=form.cleaned_data['Solution']
+ session=form.cleaned_data['Session']
+
+ author = user.username
+ created = date.today()
+ modified=date.today()
+
+ problem=Problem(description=description,problem_type=problem_type,solution=solution,session=session,author=author,created=created,modified=modified)
+
+ problem.save()
+ print "saved"
+ else:
+ print "form is valid"
+ print form.errors
+
+# print form.errors
+ # except ValueError, err:
+ # errors['__all__'] = unicode(err)
+
+
+ # if errors:
+ # print "new world"
+ # if internal:
+
+ # print errors
+ # return ('error',errors)
+ # return respond(request, user, 'new_edit_problem',
+ # {'form': form, 'problem':problem, 'creating':creating_new,'error':errors})
+
+ # if creating_new:
+ # # if internal:
+ # # if len(request.POST['user_id'])>0:
+ # # logging.info(request.POST)
+ # # problem.author = users.User(request.POST['user_id'])
+ # # else:
+ # # problem.author = user
+ # # else:
+
+
+
+
+
+
+# l = []
+ # for x in problem.categories:
+ # l.extend(x.split())
+ # problem.categories = l
+ # problem.put()
+
+ if internal:
+ return ('success','success')
+
+
+ return http.HttpResponseRedirect('/problems')
+
+def upload(request):
+ """ upload handler, validates the form and calls handle_uploaded_file
+ for processing further
+ """
+ user = request.user
+ if user is None:
+ return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.')
+
+ if request.method == 'POST':
+ form = UploadForm(request.POST, request.FILES)
+ if form.is_valid():
+ submission_report = handle_uploaded_file(request)
+ print "testing"
+ print submission_report
+
+ return respond(request, user, 'upload', {'report':submission_report})
+ else:
+ return http.HttpResponseForbidden('Oops something went wrong with the upload')
+
+def handle_uploaded_file(request):
+ """ Handles uploaded data, pushes it to existing problem creating code
+ TODO: 1. make efficient by putting actual database code Here
+ 2. Add more security and validation
+ """
+ submission_data = request.FILES['file'].read()
+ if '#---' in submission_data:
+ all_submissions = submission_data.split('#---')[1:-1]
+ # ^^ ignoring the first null and last __main__ code
+ all_submissions = [ pykataupload.Submission(x) for x in all_submissions ]
+ report = []
+
+ for key,each_submission in enumerate(all_submissions):
+ # TODO: handle these later by TaskQueues to avoid timeouts on big uploads
+ # a good way would be to have ajax based status coming back to this page
+ # about each problem in the uploaded file, their status, progress etc.
+ each_submission.parse()
+ request.POST.clear()
+ request.POST.update (each_submission.data_dict)
+ upload_status, upload_response = new_edit(request, internal=True)
+
+ report.append ({'status':upload_status, 'name':each_submission['name'],
+ 'upload_response':upload_response})
+
+ # Yay this hack works :D
+ return report
+ else:
+ return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.')
+
+def shell(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+ statement=request.GET.get('statement','')
+ if statement is not '':
+
+ # the python compiler doesn't like network line endings
+ statement = statement.replace('\r\n', '\n')
+
+ # add a couple newlines at the end of the statement. this makes
+ # single-line expressions such as 'class Foo: pass' evaluate happily.
+ statement += '\n\n'
+ print "statement"+statement
+ # log and compile the statement up front
+ try:
+ logging.info('Compiling and evaluating:\n%s' % statement)
+ compiled = compile(statement, '<string>', 'single')
+ except:
+ return HttpResponse(traceback.format_exc(),mimetype="text/plain")
+# pass
+ return HttpResponse("",mimetype="text/plain")
+ else:
+ return respond(request, user, 'shell')
+
+
Binary file testappproj/testapp/views.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/testapp/views.py~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,368 @@
+# Python imports
+import doctest
+import logging
+import os
+import traceback
+
+# # AppEngine imports
+
+from django.contrib.auth.models import User
+
+from testappproj.testapp.models import *
+from django.http import HttpResponse
+
+# from google.appengine.api import users
+# from google.appengine.ext.webapp import template
+
+# from google.appengine.ext import db
+# from google.appengine.ext.db import djangoforms
+
+
+# Django imports
+#from django.conf import settings
+#settings._target = None
+#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
+#import django
+from django import http
+from django import shortcuts
+from django.template import Context ,RequestContext
+from django.template.loader import get_template
+
+# Local imports
+from forms import *
+import models
+from helpers import bulkuploader as pykataupload
+from datetime import date
+
+
+def respond(request, user,template, params=None):
+ """Helper to render a response, passing standard stuff to the response.
+
+ Args:
+ request: The request object.
+ user: The User object representing the current user; or None if nobody
+ is logged in.
+ template: The template name; '.html' is appended automatically.
+ params: A dict giving the template parameters; modified in-place.
+
+ Returns:
+ Whatever render_to_response(template, params) returns.
+
+ Raises:
+ Whatever render_to_response(template, params) raises.
+ """
+ if params is None:
+ params = {}
+ if user:
+ params['user'] = user
+ params['sign_out'] = 1
+ # params['is_admin'] = (users.is_current_user_admin())
+ else:
+ params['sign_in'] = 1
+ # if not template.endswith('.html'):
+ template += '.html'
+ return shortcuts.render_to_response(template, params)
+
+def execute_test_cases(request, test_cases, g):
+ li = []
+
+ solved = True
+ for e in test_cases:
+ if not e.want:
+ exec e.source in g
+ continue
+ call = e.source.strip()
+ got = eval(e.source.strip(), g)
+ expected = eval(e.want, g)
+
+ if got == expected:
+ status = 'pass'
+ else:
+ status = 'fail'
+ solved = False
+ li.append([call, expected, "%r" % got, status])
+
+ return li, solved
+
+
+
+
+def index(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+
+ return respond(request , user, 'index')
+
+# def contribution(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'contribution')
+
+# def help(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'help')
+
+# def about(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'about')
+
+# def vision(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'vision')
+
+# def statements(request):
+# # user = users.get_current_user()
+# return respond(request, user, 'statements')
+
+
+def get_pu(problem):
+ '''
+ returns:
+ - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor
+ - "PU_NOT_FOUND": for signed in users when no solution has been attempted.
+ - ProblemUser: for signed in users when a solution has been attempted
+
+ '''
+# user = users.get_current_user()
+# if not user:
+# return "USER_NOT_SIGNED_IN"
+ pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user())
+ pu_results = pu_query.fetch(1)
+ if pu_results:
+ return pu_results[0]
+ return "PU_NOT_FOUND"
+
+def is_solved(problem):
+ pu = get_pu(problem)
+ if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False
+ return pu.solved
+
+def problems(request, category=None):
+ user = request.user
+
+ # if category is None:
+ # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC')
+ # else:
+ # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category)
+
+
+
+
+ # entries = []
+ # for problem in problems:
+ # e = dict(problem=problem,
+ # username=problem.author.nickname().partition('@')[0],
+ # solved=is_solved(problem))
+ # entries.append(e)
+ # problems = entries
+ entries=[]
+ problems=Problem.objects.all()
+ for problem in problems:
+ e = dict(problem=problem.name,
+ username=user.username,
+ problem_id=problem.id
+ )
+ entries.append(e)
+
+# print entries
+
+
+
+ return respond(request, user, 'problems',{'entries' : entries } )
+
+def code(request, problem_id):
+
+ print problem_id
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+# pu = get_pu(problem)
+# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time
+# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False)
+# pu.put()
+# pu = None
+
+ return respond(request, request.user ,'code' , )
+
+def run(request):
+ user = request.user
+ problem_id = request.POST.get('problem_id')
+ if problem_id:
+ problem = Problem.objects.get(id=int(problem_id))
+
+ if problem is None:
+ return http.HttpResponseNotFound('No such problem.')
+
+ user_code = request.POST.get('user_code')
+
+ if not user_code:
+ return http.HttpResponse('bad request')
+
+ # pu = get_pu(problem)
+ # # update ProblemUser object for this user
+ # if (pu.__class__ == models.ProblemUser):
+ # pu.solution = user_code
+ # pu.put()
+
+ user_code = user_code.replace('\r\n', '\n')
+ user_code += '\n\n'
+
+ errors = ''
+
+
+ try:
+ print user_code
+ compiled = compile(user_code, 'error_file', 'exec')
+ g = {}
+ exec compiled in g
+
+# s = problem.tests.replace('\r\n', '\n')
+# s += '\n\n'
+ # test_cases = doctest.DocTestParser().get_examples(s)
+ # results, solved = execute_test_cases(request, test_cases, g)
+ # if solved:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = True
+ # pu.put()
+ # else:
+ # pu = get_pu(problem)
+ # if pu.__class__ == models.ProblemUser:
+ # pu.solved = False
+ # pu.put()
+ except:
+ errors = traceback.format_exc()
+ return respond(request, user, 'traceback', {'errors': errors})
+ results="solved"
+ return respond(request, request.user, 'run', {'results': results})
+
+def new_edit(request, problem_id=None, internal=False):
+ # internal indicates that it is being called internally by uploader
+ #
+ user = request.user
+ print user.username
+ if user.is_anonymous() :
+ return http.HttpResponseForbidden('You must be an signed in to create edit a problem.')
+
+ if problem_id is None:
+ creating_new = True
+ else:
+ creating_new = False
+
+ problem = None
+ # if problem_id:
+ # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id)))
+ # if problem.author != user and not users.is_current_user_admin():
+ # return http.HttpResponseForbidden('You can only edit your own problems.')
+ # if problem is None:
+ # return http.HttpResponseNotFound('No such problem.')
+
+ form = ProblemForm(data=request.POST or None, instance=problem)
+ upload_form = UploadForm(data=request.POST)
+
+ if not request.POST:
+ return respond(request, user, 'new_edit_problem', {'form':form, 'problem':problem, 'creating':creating_new , 'upload_form' : upload_form })
+
+
+ errors = form.errors
+ if not errors:
+ try:
+ problem = form.save(commit=False)
+ except ValueError, err:
+ errors['__all__'] = unicode(err)
+
+
+ if errors:
+ print "new world"
+ if internal:
+ return ('error',errors)
+ return respond(request, user, 'new_edit_problem',
+ {'form': form, 'problem':problem, 'creating':creating_new})
+
+ if creating_new:
+ # if internal:
+ # if len(request.POST['user_id'])>0:
+ # logging.info(request.POST)
+ # problem.author = users.User(request.POST['user_id'])
+ # else:
+ # problem.author = user
+ # else:
+
+
+
+
+ problem.author = user.username
+ problem.created = date.today()
+ problem. modified=date.today()
+
+ problem.save()
+# l = []
+ # for x in problem.categories:
+ # l.extend(x.split())
+ # problem.categories = l
+ # problem.put()
+
+ if internal:
+ return ('success','success')
+
+
+ return http.HttpResponseRedirect('/problems')
+
+def upload(request):
+ """ upload handler, validates the form and calls handle_uploaded_file
+ for processing further
+ """
+ user = request.user
+ if user is None:
+ return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.')
+
+ if request.method == 'POST':
+ form = UploadForm(request.POST, request.FILES)
+ if form.is_valid():
+ submission_report = handle_uploaded_file(request)
+ print "testing"
+ print submission_report
+
+ return respond(request, user, 'upload', {'report':submission_report})
+ else:
+ return http.HttpResponseForbidden('Oops something went wrong with the upload')
+
+def handle_uploaded_file(request):
+ """ Handles uploaded data, pushes it to existing problem creating code
+ TODO: 1. make efficient by putting actual database code Here
+ 2. Add more security and validation
+ """
+ submission_data = request.FILES['file'].read()
+ if '#---' in submission_data:
+ all_submissions = submission_data.split('#---')[1:-1]
+ # ^^ ignoring the first null and last __main__ code
+ all_submissions = [ pykataupload.Submission(x) for x in all_submissions ]
+ report = []
+
+ for key,each_submission in enumerate(all_submissions):
+ # TODO: handle these later by TaskQueues to avoid timeouts on big uploads
+ # a good way would be to have ajax based status coming back to this page
+ # about each problem in the uploaded file, their status, progress etc.
+ each_submission.parse()
+ request.POST.clear()
+ request.POST.update (each_submission.data_dict)
+ upload_status, upload_response = new_edit(request, internal=True)
+
+ report.append ({'status':upload_status, 'name':each_submission['name'],
+ 'upload_response':upload_response})
+
+ # Yay this hack works :D
+ return report
+ else:
+ return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.')
+
+def shell(request):
+ """ need to change user in the django.contrib way"""
+
+ user = request.user
+ print request.GET.get('statement')
+ return respond(request , user, 'shell')
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/urls.py Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,44 @@
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Top-level URL mappings for Rietveld."""
+
+# NOTE: Must import *, since Django looks for things here, e.g. handler500.
+import os
+import sys
+from django.conf.urls.defaults import *
+from registration.views import register
+from testappproj.testapp.forms import Test_UserForm
+from django.contrib import admin
+admin.autodiscover()
+
+
+
+urlpatterns = patterns('',
+ (r'^$', 'testappproj.testapp.views.index'),
+ url(r'^accounts/register/$',register,{'form_class' : Test_UserForm},name='registration_register'),
+ (r'^accounts/', include('registration.urls')),
+ (r'^code/(\d+)/$', 'testappproj.testapp.views.code'),
+ (r'^admin/(.*)', admin.site.root),
+ (r'^new/$', 'testappproj.testapp.views.new_edit'),
+ (r'^problems/$', 'testappproj.testapp.views.problems'),
+ (r'^run/$', 'testappproj.testapp.views.run'),
+ (r'^upload/$', 'testappproj.testapp.views.upload'),
+ (r'^static/(?P<path>.*)$', 'django.views.static.serve',
+ {'document_root': os.path.realpath(os.path.dirname(
+ sys.modules[__name__].__file__) + '/static/')}),
+ (r'^shell/$', 'testappproj.testapp.views.shell')
+
+)
+
Binary file testappproj/urls.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testappproj/urls.py~ Mon May 17 22:33:59 2010 +0530
@@ -0,0 +1,44 @@
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Top-level URL mappings for Rietveld."""
+
+# NOTE: Must import *, since Django looks for things here, e.g. handler500.
+import os
+import sys
+from django.conf.urls.defaults import *
+from registration.views import register
+from testappproj.testapp.forms import Tets_UserForm
+from django.contrib import admin
+admin.autodiscover()
+
+
+
+urlpatterns = patterns('',
+ (r'^$', 'testappproj.testapp.views.index'),
+ url(r'^accounts/register/$',register,{'form_class' : Test_UserForm},name='registration_register'),
+ (r'^accounts/', include('registration.urls')),
+ (r'^code/(\d+)/$', 'testappproj.testapp.views.code'),
+ (r'^admin/(.*)', admin.site.root),
+ (r'^new/$', 'testappproj.testapp.views.new_edit'),
+ (r'^problems/$', 'testappproj.testapp.views.problems'),
+ (r'^run/$', 'testappproj.testapp.views.run'),
+ (r'^upload/$', 'testappproj.testapp.views.upload'),
+ (r'^static/(?P<path>.*)$', 'django.views.static.serve',
+ {'document_root': os.path.realpath(os.path.dirname(
+ sys.modules[__name__].__file__) + '/static/')}),
+ (r'^shell/$', 'testappproj.testapp.views.shell')
+
+)
+