[Jifty-commit] r590 - in jifty/trunk: lib/Jifty lib/Jifty/Web lib/Jifty/Web/Form share/web/static/js

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Thu Feb 16 15:32:38 EST 2006


Author: alexmv
Date: Thu Feb 16 15:32:37 2006
New Revision: 590

Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/lib/Jifty/Request.pm
   jifty/trunk/lib/Jifty/Web.pm
   jifty/trunk/lib/Jifty/Web/Form/Element.pm
   jifty/trunk/lib/Jifty/Web/PageRegion.pm
   jifty/trunk/share/web/static/js/jifty.js

Log:
 r9111 at zoq-fot-pik:  chmrr | 2006-02-16 15:31:18 -0500
  * Fragments in JS land now know about their parents, and pass their
    superstructure in the fragment request.  This lets $region->parent
    have full information.
  * Compute replacement element earlier in js
  * 'refresh => region' mode for replacement
  * Better docs on region replacement
  * add_* calls on Jifty::Request now return the object added, not the
    request


Modified: jifty/trunk/lib/Jifty/Request.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Request.pm	(original)
+++ jifty/trunk/lib/Jifty/Request.pm	Thu Feb 16 15:32:37 2006
@@ -158,11 +158,20 @@
 
     my %fragments = %{$data->{fragments} || {}};
     for my $f (values %fragments) {
-        $self->add_fragment(name      => $f->{name},
-                            path      => $f->{path},
-                            arguments => $f->{args},
-                            wrapper   => $f->{wrapper} || 0,
-                           );
+        my $current = $self->add_fragment(
+            name      => $f->{name},
+            path      => $f->{path},
+            arguments => $f->{args},
+            wrapper   => $f->{wrapper} || 0,
+        );
+        while ($f->{parent}) {
+            $f = $f->{parent};
+            $current = $current->parent(Jifty::Request::Fragment->new({
+                name => $f->{name},
+                path => $f->{path},
+                arguments => $f->{args},
+            }));
+        }
     }
 
     return $self;
@@ -468,7 +477,8 @@
 =head2 add_state_variable PARAMHASH
 
 Adds a state variable to this request's internal representation.
-Takes a C<key> and a C<value>.
+Takes a C<key> and a C<value>; returns the newly-added
+L<Jifty::Request::StateVariable>.
 
 =cut
 
@@ -485,6 +495,8 @@
         $state_var->$k($args{$k}) if defined $args{$k};
     } 
     $self->{'state_variables'}{$args{'key'}} = $state_var;
+
+    return $state_var;
 }
 
 =head2 remove_state_variable KEY
@@ -533,10 +545,12 @@
 Optional arguments: C<class>, C<order>, C<active>, C<arguments>.
 
 Adds a L<Jifty::Request::Action> with the given
-L<moniker|Jifty::Manual::Glossary/moniker> to the request.  If the request
-already contains an action with that moniker, it merges it in,
+L<moniker|Jifty::Manual::Glossary/moniker> to the request.  If the
+request already contains an action with that moniker, it merges it in,
 overriding the implementation class, active state, and B<individual>
-arguments.  See L<Jifty::Action>.
+arguments.  Returns the newly added L<Jifty::Request::Action>.
+
+See L<Jifty::Action>.
 
 =cut
 
@@ -592,6 +606,18 @@
     return values %{$self->{'fragments'}}
 }
 
+=head2 fragment NAME
+
+Returns the requested fragment with that name
+
+=cut
+
+sub fragment {
+    my $self = shift;
+    my $name = shift;
+    return $self->{'fragments'}{$name};
+}
+
 =head2 add_fragment PARAMHASH
 
 Required arguments: C<name>, C<path>
@@ -600,7 +626,9 @@
 
 Adds a L<Jifty::Request::Fragment> with the given name to the request.
 If the request already contains a fragment with that name, it merges
-it in.  See L<Jifty::PageRegion>.
+it in.  Returns the newly added L<Jifty::Request::Fragment>.
+
+See L<Jifty::PageRegion>.
 
 =cut
 
@@ -717,7 +745,7 @@
 
 package Jifty::Request::Fragment;
 use base 'Class::Accessor';
-__PACKAGE__->mk_accessors( qw/name path wrapper arguments/ );
+__PACKAGE__->mk_accessors( qw/name path wrapper arguments parent/ );
 
 =head2 Jifty::Request::Fragment
 

Modified: jifty/trunk/lib/Jifty/Web.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web.pm	(original)
+++ jifty/trunk/lib/Jifty/Web.pm	Thu Feb 16 15:32:37 2006
@@ -1090,30 +1090,27 @@
     $writer->xmlDecl( "UTF-8", "yes" );
     $writer->startTag("response");
     for my $f ( $self->request->fragments ) {
-        $writer->startTag( "fragment", id => $f->name );
-        my @names = split '-', $f->name;
-
         # Set up the region stack
         local Jifty->web->{'region_stack'} = [];
-        while ( my $region = shift @names ) {
-            my $new = @names
-                ? Jifty::Web::PageRegion->new(
-                name       => $region,
-                _bootstrap => 1,
-                parent     => Jifty->web->current_region
-                )
-                : Jifty::Web::PageRegion->new(
-                name           => $region,
+        my @regions;
+        do {
+            push @regions, $f;
+        } while ($f = $f->parent);
+        
+        for $f (reverse @regions) {
+            my $new = Jifty::Web::PageRegion->new(
+                name           => $f->name,
                 path           => $f->path,
                 region_wrapper => $f->wrapper,
                 parent         => Jifty->web->current_region,
                 defaults       => $f->arguments,
-                );
+            );
             push @{ Jifty->web->{'region_stack'} }, $new;
             $new->enter;
         }
 
         # Stuff the rendered region into the XML
+        $writer->startTag( "fragment", id => Jifty->web->current_region->qualified_name );
         $writer->cdata( Jifty->web->current_region->render );
         $writer->endTag();
     }

Modified: jifty/trunk/lib/Jifty/Web/Form/Element.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Form/Element.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/Form/Element.pm	Thu Feb 16 15:32:37 2006
@@ -16,29 +16,78 @@
 the name of the javascript event handler, such as C<onclick>, with a
 set of arguments.
 
-The format of the arguments passed to C<onclick> (or any similar method)
-is a hash reference, with the following possible keys:
+The format of the arguments passed to C<onclick> (or any similar
+method) is a hash reference.  It takes a number of possible keys.  The
+most important is the mode of the fragment replacement, if any; it is
+specified by providing at most one of the following keys:
 
 =over
 
-=item submit (optional)
+=item append => PATH
 
-An action (or moniker of an action) to be submitted when the event is fired.
+Add the given C<PATH> as a new fragment, just before the close of the
+CSS selector given by C<element>, which defaults to the end of the
+current region.
 
-=item region (optional)
+=item prepend => PATH
+
+Add the given C<PATH> as a new fragment, just aftger the start of the
+CSS selector given by C<element>, which defaults to the start of the
+current region.
+
+=item replace_with => PATH
+
+Replaces the region specified by the C<region> parameter (which
+defaults to the current region) with the fragment located at the given
+C<PATH>.
+
+=item refresh => REGION
+
+Refreshes the given C<REGION>, which should be a
+L<Jifty::Web::PageRegion> object, or the fully qualified name of such.
+
+=item refresh_self => 1
+
+Refreshes the current region; this is the default action, if C<args>
+are supplied, but no other mode is given.
+
+=back
+
+The following options are also supported:
+
+=over
+
+=item region => REGION
 
 The region that should be updated.  This defaults to the current
 region.
 
-=item args (optional)
+=item element => CSS SELECTOR
+
+A css selector specifying where the new region should be placed; used
+with C<append> and C<prepend>, above.  The
+L<Jifty::Web::PageRegion/get_element> method may be useful in
+specifying elements of parent page regions.
+
+=item submit => MONIKER
+
+An action, moniker of an action, or array reference to such; these
+actions are submitted when the event is fired.
+
+=item args => HASHREF
 
-Arguments to the region.  These will override the default arguments to
-the region.
+Arguments to the region.  These will override the arguments to the
+region that the region was given when it was last rendered.
 
-=item fragment (optional)
+=item effect => STRING
 
-The fragment that should go into the region.  The default is whatever
-fragment the region was originally rendered with.
+The Prototype visual effect to use when updating or creating the
+fragment.
+
+=item effect_args => HASHREF
+
+A hashref of arguments to pass to the effect when it is creted.  These
+can be used to change the duration of the effect, for instance.
 
 =back
 
@@ -92,27 +141,34 @@
                 push @actions, map { ref $_ ? $_->moniker : $_ } @{ $hook->{submit} };
             }
 
+            $hook->{region} ||= Jifty->web->qualified_region;
+
             # Placement
-            if (exists $hook->{replace_with}) {
-                @args{qw/mode path/} = ('Replace', $hook->{replace_with});
-            } elsif (exists $hook->{append}) {
+            if (exists $hook->{append}) {
                 @args{qw/mode path/} = ('Bottom', $hook->{append});
+                $hook->{element} ||= "#region-".$hook->{region};
             } elsif (exists $hook->{prepend}) {
                 @args{qw/mode path/} = ('Top', $hook->{prepend});
+                $hook->{element} ||= "#region-".$hook->{region};
+            } elsif (exists $hook->{replace_with}) {
+                @args{qw/mode path region/} = ('Replace', $hook->{replace_with}, $hook->{region});
+            } elsif (exists $hook->{refresh}) {
+                @args{qw/mode path region/} = ('Replace', $hook->{refresh}->path, $hook->{refresh});
             } elsif ((exists $hook->{refresh_self} and Jifty->web->current_region) or $hook->{args}) {
                 # If we just pass arguments, treat as a refresh_self
-                 @args{qw/mode path/} = ('Replace', Jifty->web->current_region->path);
+                @args{qw/mode path region/} = ('Replace', Jifty->web->current_region->path, Jifty->web->current_region);
             } else {
                 # If we're not doing any of the above, skip this one
                 next;
             }
 
+            # Qualified name if we have a ref
+            $args{region} = $args{region}->qualified_name if ref $args{region};
+
             # What element we're replacing.
             if ($hook->{element}) {
-                $args{element} = $hook->{element};
+                $args{element} = ref $hook->{element} ? "#region-".$hook->{element}->qualified_name : $hook->{element};
                 $args{region}  = $args{element} =~ /^#region-(\S+)/ ? "$1-".Jifty->web->serial : Jifty->web->serial;
-            } else {
-                $args{region}  = $hook->{region} || Jifty->web->qualified_region;
             }
 
             # Arguments

Modified: jifty/trunk/lib/Jifty/Web/PageRegion.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/PageRegion.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/PageRegion.pm	Thu Feb 16 15:32:37 2006
@@ -230,9 +230,11 @@
     # We only render the region wrapper if we're asked to (which is true by default)
     if ($self->region_wrapper) {
         $result .= qq|<script type="text/javascript">\n|;
-        $result .= qq|new Region('|. $self->qualified_name .qq|',|;
-        $result .= Jifty::JSON::objToJson(\%arguments, {singlequote => 1});
-        $result .= qq|,'|. $self->path . qq|');\n|;
+        $result .= qq|new Region('|. $self->qualified_name . qq|',|;
+        $result .= Jifty::JSON::objToJson(\%arguments, {singlequote => 1}) . qq|,|;
+        $result .= qq|'| . $self->path . qq|',|;
+        $result .= $self->parent ? qq|'| . $self->parent->qualified_name . qq|'| : q|null|;
+        $result .= qq|);\n|;
         $result .= qq|</script>|;
         $result .= qq|<div id="region-| . $self->qualified_name . qq|">|;
     }

Modified: jifty/trunk/share/web/static/js/jifty.js
==============================================================================
--- jifty/trunk/share/web/static/js/jifty.js	(original)
+++ jifty/trunk/share/web/static/js/jifty.js	Thu Feb 16 15:32:37 2006
@@ -241,10 +241,11 @@
 
 var Region = Class.create();
 Region.prototype = {
-    initialize: function(name, args, path) {
+    initialize: function(name, args, path, parent) {
         this.name = name;
         this.args = $H(args);
         this.path = path;
+        this.parent = parent ? fragments[parent] : null;
         if (fragments[name]) {
             // If this fragment already existed, we want to wipe out
             // whatever evil lies we might have said earlier; do this
@@ -311,10 +312,24 @@
     },
 
     data_structure: function(path, args) {
+        // Set the path and args, if given
+        if (path)
+            this.setPath(path);
+        if (args)
+            this.setArgs(args);
+
+        // If we have a parent, find our not-qualified name
+        var shortname = this.name;
+        if (this.parent) {
+            shortname = this.name.substr(this.parent.name.length + 1);
+        }
+
+        // Return a nummy data structure
         return {
-            name: this.name,
-            path: this.setPath(path),
-            args: this.setArgs(args)
+            name: shortname,
+            path: this.path,
+            args: this.args,
+            parent: this.parent ? this.parent.data_structure(null,null) : null
         }
     }
 };
@@ -357,17 +372,44 @@
         var f = named_args['fragments'][i];
 
         var name = f['region'];
+
+        // Find where we are going to go
+        var element = $('region-' + f['region']);
+        if (f['element']) {
+            var possible = document.getElementsBySelector(f['element']);
+            if (possible.length == 0)
+                element = null;
+            else
+                element = possible[0];
+        }
+        f['element'] = element;
+
+        // If we can't find out where we're going, bail
+        if (element == null)
+            continue;
+
         f['is_new'] = (fragments[name] ? false : true);
-        
         // If it's new, we need to create it so we can dump it
-        if (f['is_new'])
-            new Region(name, f['args'], f['path']);
+        if (f['is_new']) {
+            // Find what region we're inside
+            f['parent'] = null;
+            if (f['mode'] && ((f['mode'] == "Before") || (f['mode'] == "After")))
+                element = element.parentNode;
+            while ((element != null) && (f['parent'] == null)) {
+                if (/^region-/.test(element.getAttribute("id")))
+                    f['parent'] = element.getAttribute("id").replace(/^region-/,"");
+                element = element.parentNode;
+            }
+
+            // Make the region (for now)
+            new Region(name, f['args'], f['path'], f['parent']);
+        }
 
         // Update with all new values
         var fragment_request = fragments[name].data_structure(f['path'], f['args']);
 
-        // Ask for the wrapper if we are making a new region
         if (f['is_new'])
+            // Ask for the wrapper if we are making a new region
             fragment_request['wrapper'] = 1;
 
         // Push it onto the request stack
@@ -384,54 +426,43 @@
             // For each fragment we requested
             for (var i = 0; i < named_args['fragments'].length; i++) {
                 var f = named_args['fragments'][i];
+                var element = f['element'];
 
-                // Find the element that is getting dealt with
-                var element = $('region-' + f['region']);
-                if (f['element']) {
-                    var possible = document.getElementsBySelector(f['element']);
-                    if (possible.length == 0)
-                        element = null;
-                    else
-                        element = possible[0];
-                }
                 // Change insertion mode if need be
                 var insertion = null;
                 if (f['mode'] && (f['mode'] != 'Replace')) {
                     insertion = eval('Insertion.'+f['mode']);
                 }
 
-                // If we found something to replace
-                if (element) {
-                    // Loop through the result looking for it
-                    for (var response_fragment = response.firstChild;
-                         response_fragment != null;
-                         response_fragment = response_fragment.nextSibling) {
-                        if (response_fragment.getAttribute("id") == f['region']) {
-                            var textContent;
-                            if (response_fragment.textContent) {
-                                textContent = response_fragment.textContent;
-                            } else {
-                                textContent = response_fragment.firstChild.nodeValue;
-                            }
-                            // Once we find it, do the insertion
-                            if (insertion) {
-                                new insertion(element, textContent.stripScripts());
-                            } else {
-                                Element.update(element, textContent.stripScripts());
-                            }
-                            // We need to give the browser some "settle" time before we eval scripts in the body
-                            setTimeout((function() { this.evalScripts() }).bind(textContent), 10);
+                // Loop through the result looking for it
+                for (var response_fragment = response.firstChild;
+                     response_fragment != null;
+                     response_fragment = response_fragment.nextSibling) {
+                    if (response_fragment.getAttribute("id") == f['region']) {
+                        var textContent;
+                        if (response_fragment.textContent) {
+                            textContent = response_fragment.textContent;
+                        } else {
+                            textContent = response_fragment.firstChild.nodeValue;
                         }
+                        // Once we find it, do the insertion
+                        if (insertion) {
+                            new insertion(element, textContent.stripScripts());
+                        } else {
+                            Element.update(element, textContent.stripScripts());
+                        }
+                        // We need to give the browser some "settle" time before we eval scripts in the body
+                        setTimeout((function() { this.evalScripts() }).bind(textContent), 10);
                     }
+                }
 
-                    // Also, set us up the effect
-                    if (f['effect']) {
-                        var effect = eval('Effect.'+f['effect']);
-                        var effect_args  = f['effect_args'] || {};
-                        if (f['is_new'])
-                            Element.hide($('region-'+f['region']));
-                        (effect)($('region-'+f['region']), effect_args);
-                    }
+                // Also, set us up the effect
+                if (f['effect']) {
+                    var effect = eval('Effect.'+f['effect']);
+                    var effect_args  = f['effect_args'] || {};
+                    if (f['is_new'])
+                        Element.hide($('region-'+f['region']));
+                    (effect)($('region-'+f['region']), effect_args);
                 }
             }
         } finally {


More information about the Jifty-commit mailing list