",
+ options: {
+ disabled: false,
+
+ // callbacks
+ create: null
+ },
+ _createWidget: function( options, element ) {
+ element = $( element || this.defaultElement || this )[ 0 ];
+ this.element = $( element );
+ this.uuid = uuid++;
+ this.eventNamespace = "." + this.widgetName + this.uuid;
+ this.options = $.widget.extend( {},
+ this.options,
+ this._getCreateOptions(),
+ options );
+
+ this.bindings = $();
+ this.hoverable = $();
+ this.focusable = $();
+
+ if ( element !== this ) {
+ $.data( element, this.widgetFullName, this );
+ this._on( true, this.element, {
+ remove: function( event ) {
+ if ( event.target === element ) {
+ this.destroy();
+ }
+ }
+ });
+ this.document = $( element.style ?
+ // element within the document
+ element.ownerDocument :
+ // element is window or document
+ element.document || element );
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
+ }
+
+ this._create();
+ this._trigger( "create", null, this._getCreateEventData() );
+ this._init();
+ },
+ _getCreateOptions: $.noop,
+ _getCreateEventData: $.noop,
+ _create: $.noop,
+ _init: $.noop,
+
+ destroy: function() {
+ this._destroy();
+ // we can probably remove the unbind calls in 2.0
+ // all event bindings should go through this._on()
+ this.element
+ .unbind( this.eventNamespace )
+ // 1.9 BC for #7810
+ // TODO remove dual storage
+ .removeData( this.widgetName )
+ .removeData( this.widgetFullName )
+ // support: jquery <1.6.3
+ // http://bugs.jquery.com/ticket/9413
+ .removeData( $.camelCase( this.widgetFullName ) );
+ this.widget()
+ .unbind( this.eventNamespace )
+ .removeAttr( "aria-disabled" )
+ .removeClass(
+ this.widgetFullName + "-disabled " +
+ "ui-state-disabled" );
+
+ // clean up events and states
+ this.bindings.unbind( this.eventNamespace );
+ this.hoverable.removeClass( "ui-state-hover" );
+ this.focusable.removeClass( "ui-state-focus" );
+ },
+ _destroy: $.noop,
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key,
+ parts,
+ curOption,
+ i;
+
+ if ( arguments.length === 0 ) {
+ // don't return a reference to the internal hash
+ return $.widget.extend( {}, this.options );
+ }
+
+ if ( typeof key === "string" ) {
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+ options = {};
+ parts = key.split( "." );
+ key = parts.shift();
+ if ( parts.length ) {
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
+ for ( i = 0; i < parts.length - 1; i++ ) {
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
+ curOption = curOption[ parts[ i ] ];
+ }
+ key = parts.pop();
+ if ( value === undefined ) {
+ return curOption[ key ] === undefined ? null : curOption[ key ];
+ }
+ curOption[ key ] = value;
+ } else {
+ if ( value === undefined ) {
+ return this.options[ key ] === undefined ? null : this.options[ key ];
+ }
+ options[ key ] = value;
+ }
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+ _setOptions: function( options ) {
+ var key;
+
+ for ( key in options ) {
+ this._setOption( key, options[ key ] );
+ }
+
+ return this;
+ },
+ _setOption: function( key, value ) {
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this.widget()
+ .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
+ .attr( "aria-disabled", value );
+ this.hoverable.removeClass( "ui-state-hover" );
+ this.focusable.removeClass( "ui-state-focus" );
+ }
+
+ return this;
+ },
+
+ enable: function() {
+ return this._setOption( "disabled", false );
+ },
+ disable: function() {
+ return this._setOption( "disabled", true );
+ },
+
+ _on: function( suppressDisabledCheck, element, handlers ) {
+ var delegateElement,
+ instance = this;
+
+ // no suppressDisabledCheck flag, shuffle arguments
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
+ handlers = element;
+ element = suppressDisabledCheck;
+ suppressDisabledCheck = false;
+ }
+
+ // no element argument, shuffle and use this.element
+ if ( !handlers ) {
+ handlers = element;
+ element = this.element;
+ delegateElement = this.widget();
+ } else {
+ // accept selectors, DOM elements
+ element = delegateElement = $( element );
+ this.bindings = this.bindings.add( element );
+ }
+
+ $.each( handlers, function( event, handler ) {
+ function handlerProxy() {
+ // allow widgets to customize the disabled handling
+ // - disabled as an array instead of boolean
+ // - disabled class as method for disabling individual parts
+ if ( !suppressDisabledCheck &&
+ ( instance.options.disabled === true ||
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
+ return;
+ }
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+
+ // copy the guid so direct unbinding works
+ if ( typeof handler !== "string" ) {
+ handlerProxy.guid = handler.guid =
+ handler.guid || handlerProxy.guid || $.guid++;
+ }
+
+ var match = event.match( /^(\w+)\s*(.*)$/ ),
+ eventName = match[1] + instance.eventNamespace,
+ selector = match[2];
+ if ( selector ) {
+ delegateElement.delegate( selector, eventName, handlerProxy );
+ } else {
+ element.bind( eventName, handlerProxy );
+ }
+ });
+ },
+
+ _off: function( element, eventName ) {
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
+ element.unbind( eventName ).undelegate( eventName );
+ },
+
+ _delay: function( handler, delay ) {
+ function handlerProxy() {
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+ var instance = this;
+ return setTimeout( handlerProxy, delay || 0 );
+ },
+
+ _hoverable: function( element ) {
+ this.hoverable = this.hoverable.add( element );
+ this._on( element, {
+ mouseenter: function( event ) {
+ $( event.currentTarget ).addClass( "ui-state-hover" );
+ },
+ mouseleave: function( event ) {
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
+ }
+ });
+ },
+
+ _focusable: function( element ) {
+ this.focusable = this.focusable.add( element );
+ this._on( element, {
+ focusin: function( event ) {
+ $( event.currentTarget ).addClass( "ui-state-focus" );
+ },
+ focusout: function( event ) {
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
+ }
+ });
+ },
+
+ _trigger: function( type, event, data ) {
+ var prop, orig,
+ callback = this.options[ type ];
+
+ data = data || {};
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ // the original event may come from any element
+ // so we need to reset the target on the new event
+ event.target = this.element[ 0 ];
+
+ // copy original event properties over to the new event
+ orig = event.originalEvent;
+ if ( orig ) {
+ for ( prop in orig ) {
+ if ( !( prop in event ) ) {
+ event[ prop ] = orig[ prop ];
+ }
+ }
+ }
+
+ this.element.trigger( event, data );
+ return !( $.isFunction( callback ) &&
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
+ if ( typeof options === "string" ) {
+ options = { effect: options };
+ }
+ var hasOptions,
+ effectName = !options ?
+ method :
+ options === true || typeof options === "number" ?
+ defaultEffect :
+ options.effect || defaultEffect;
+ options = options || {};
+ if ( typeof options === "number" ) {
+ options = { duration: options };
+ }
+ hasOptions = !$.isEmptyObject( options );
+ options.complete = callback;
+ if ( options.delay ) {
+ element.delay( options.delay );
+ }
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
+ element[ method ]( options );
+ } else if ( effectName !== method && element[ effectName ] ) {
+ element[ effectName ]( options.duration, options.easing, callback );
+ } else {
+ element.queue(function( next ) {
+ $( this )[ method ]();
+ if ( callback ) {
+ callback.call( element[ 0 ] );
+ }
+ next();
+ });
+ }
+ };
+});
+
+}));
diff --git a/templates/client/base_catalog.html b/templates/client/base_catalog.html
index 42d7fcaa..47a3ad79 100644
--- a/templates/client/base_catalog.html
+++ b/templates/client/base_catalog.html
@@ -1,4 +1,4 @@
-{% extends 'blank.html' %}
+{% extends 'client/blank.html' %}
{% load static %}
{% load i18n %}
diff --git a/templates/client/fileupload/fileupload/picture_angular_form.html b/templates/client/fileupload/fileupload/picture_angular_form.html
new file mode 100644
index 00000000..a5ac9c09
--- /dev/null
+++ b/templates/client/fileupload/fileupload/picture_angular_form.html
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
jQuery File Upload Demo - AngularJS version
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Django jQuery File Upload Demo
+
AngularJS version
+
+
+
+ File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS.
+ Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/client/fileupload/fileupload/picture_basic_form.html b/templates/client/fileupload/fileupload/picture_basic_form.html
new file mode 100644
index 00000000..6bd17a40
--- /dev/null
+++ b/templates/client/fileupload/fileupload/picture_basic_form.html
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
Django jQuery File Upload Demo - Basic version
+
+
+
+
+
+
+
+
+
+
+
+
+
Django jQuery File Upload Demo
+
Basic version
+
+
+
+ File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
+ Supports cross-domain, chunked and resumable file uploads.
+
+
+
+
+
+ Select files...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/client/fileupload/fileupload/picture_basicplus_form.html b/templates/client/fileupload/fileupload/picture_basicplus_form.html
new file mode 100644
index 00000000..eb1cc1c5
--- /dev/null
+++ b/templates/client/fileupload/fileupload/picture_basicplus_form.html
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
jQuery File Upload Demo - Basic Plus version
+
+
+
+
+
+
+
+
+
+
+
+
+
Django jQuery File Upload Demo
+
Basic Plus version
+
+
+
+ File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.
+ Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
+
+
+
+
+
+ Add files...
+
+
+
+
+
+
+
+
+
+
+
+
+
Demo Notes
+
+
+
+ The maximum file size for uploads in this demo is 5 MB (default file size is unlimited).
+ Only image files (JPG, GIF, PNG ) are allowed in this demo (by default there is no file type restriction).
+ You can drag & drop files from your desktop on this webpage (see Browser support ).
+ Please refer to the project website and documentation for more information.
+ Built with Twitter's Bootstrap CSS framework and Icons from Glyphicons .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/client/fileupload/fileupload/picture_form.html b/templates/client/fileupload/fileupload/picture_form.html
new file mode 100644
index 00000000..a3cb5767
--- /dev/null
+++ b/templates/client/fileupload/fileupload/picture_form.html
@@ -0,0 +1,102 @@
+{% extends "client/fileupload/upload_base.html" %}
+{% load upload_tags %}
+{% load staticfiles %}
+
+{% block content %}
+
+
+
+{% upload_js %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/client/fileupload/fileupload/picture_jquery_form.html b/templates/client/fileupload/fileupload/picture_jquery_form.html
new file mode 100644
index 00000000..cf0ed04c
--- /dev/null
+++ b/templates/client/fileupload/fileupload/picture_jquery_form.html
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+
+
Django jQuery File Upload Demo - jQuery UI version
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Django jQuery File Upload Demo
+
jQuery UI version
+
+
+
+ File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery UI.
+ Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
+
+
+
+
+
Demo Notes
+
+ The maximum file size for uploads in this demo is 5 MB (default file size is unlimited).
+ Only image files (JPG, GIF, PNG ) are allowed in this demo (by default there is no file type restriction).
+ Uploaded files will be deleted automatically after 5 minutes (demo setting).
+ You can drag & drop files from your desktop on this webpage (see Browser support ).
+ Please refer to the project website and documentation for more information.
+ Built with jQuery UI .
+
+
+
+{% verbatim %}
+
+
+
+
+{% endverbatim %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/client/fileupload/upload_base.html b/templates/client/fileupload/upload_base.html
new file mode 100644
index 00000000..1700c17b
--- /dev/null
+++ b/templates/client/fileupload/upload_base.html
@@ -0,0 +1,52 @@
+
+{% load staticfiles %}
+
+
+
+
+
+
Django Jquery file upload demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% block content %}
+
No content set
+{% endblock %}
+
+
+
diff --git a/wizard/urls.py b/wizard/urls.py
index 188c3901..d04ce133 100644
--- a/wizard/urls.py
+++ b/wizard/urls.py
@@ -1,8 +1,9 @@
-from django.conf.urls import patterns
+from django.conf.urls import patterns, url, include
from wizard.forms import ExpoForm1, ExpoForm2
from wizard.views import ExpoWizard
urlpatterns = patterns('',
- (r'^$', ExpoWizard.as_view([ExpoForm1, ExpoForm2]))
+ url(r'^add-photo/', include('fileupload.urls')),
+ url(r'^$', ExpoWizard.as_view([ExpoForm1, ExpoForm2]))
)
\ No newline at end of file