[Rt-commit] rt branch, 4.4/drop-cf-self-category-select, created. rt-4.2.9-114-g08cfcf3

? sunnavy sunnavy at bestpractical.com
Thu Jan 15 12:37:17 EST 2015


The branch, 4.4/drop-cf-self-category-select has been created
        at  08cfcf31b2c348e032c1384ad561226ca3aff1f6 (commit)

- Log -----------------------------------------------------------------
commit 78ba58c4499d126daed805a4047704a75a164215
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Oct 22 07:00:21 2014 +0800

    drop cf's own category select
    
    previously, if a select cf's "categories are based on" is empty, we will show
    an extra <select> to let user filter values by category, which is kinda
    misleading as the extra select is not a real cf(so it's not searchable).
    
    if user wants to use the category select, there is an upgrade step to turn
    categories into real cfs.
    
    this function was supplied by etc/upgrade/split-out-cf-categories before, now
    it's a mandatory upgrade step.
    
    Fixes: I#30426

diff --git a/configure.ac b/configure.ac
index 26fb8e9..0d72a06 100755
--- a/configure.ac
+++ b/configure.ac
@@ -433,7 +433,6 @@ AC_CONFIG_FILES([
                  etc/upgrade/sanity-check-stylesheets
                  etc/upgrade/shrink-cgm-table
                  etc/upgrade/shrink-transactions-table
-                 etc/upgrade/split-out-cf-categories
                  etc/upgrade/switch-templates-to
                  etc/upgrade/time-worked-history
                  etc/upgrade/upgrade-articles
diff --git a/docs/UPGRADING-3.8 b/docs/UPGRADING-3.8
index 9c3f93f..f6df198 100644
--- a/docs/UPGRADING-3.8
+++ b/docs/UPGRADING-3.8
@@ -59,15 +59,6 @@ You can now forward an entire Ticket history (in addition to specific
 transactions) but this requires a new Template called "Forward Ticket".  This
 template will be added as part of the standard database upgrade step.
 
-Custom fields with categories can optionally be split out into hierarchical
-custom fields.  If you wish to convert your old category-based custom fields,
-run:
-
-    /opt/rt4/etc/upgrade/split-out-cf-categories
-
-It will prompt you for each custom field with categories that it finds, and
-the name of the custom field to create to store the categories.
-
 If you were using the LocalizedDateTime RT::Date formatter from custom code,
 and passing a DateFormat or TimeFormat argument, you need to switch from the
 strftime methods to the cldr methods; that is,
diff --git a/docs/UPGRADING-4.4 b/docs/UPGRADING-4.4
index 5d75727..bf96bec 100644
--- a/docs/UPGRADING-4.4
+++ b/docs/UPGRADING-4.4
@@ -26,6 +26,11 @@ When creating linked tickets from the Links box, Time Worked, Time
 Estimated, and Time Left will no longer be copied.  This simplifies time
 reporting.
 
+=item *
+
+Custom fields with categories will be split out into hierarchical custom
+fields.
+
 =back
 
 =cut
diff --git a/etc/upgrade/4.3.4/content b/etc/upgrade/4.3.4/content
new file mode 100644
index 0000000..3346e16
--- /dev/null
+++ b/etc/upgrade/4.3.4/content
@@ -0,0 +1,109 @@
+use strict;
+use warnings;
+
+our @Initial = (
+    sub {
+        use RT::CustomFields;
+        my $CFs = RT::CustomFields->new( RT->SystemUser );
+        $CFs->UnLimit;
+        $CFs->Limit( FIELD => 'Type', VALUE => 'Select' );
+
+        my $seen;
+        while (my $cf  = $CFs->Next ) {
+            next if $cf->BasedOnObj->Id;
+            my @categories;
+            my %mapping;
+            my $values = $cf->Values;
+            while (my $value = $values->Next) {
+                next unless defined $value->Category and length $value->Category;
+                push @categories, $value->Category unless grep {$_ eq $value->Category} @categories;
+                $mapping{$value->Name} = $value->Category;
+            }
+            next unless @categories;
+
+            $seen++;
+            RT->Logger->warn("Found CF '@{[$cf->Name]}' with categories: " .  join ", ", @categories);
+            my $newname = $cf->Name . " category";
+            RT->Logger->warn("Going to create CF $newname for it");
+
+            # bump the CF's sort oder up by one
+            $cf->SetSortOrder( ($cf->SortOrder || 0) + 1 );
+
+            # ..and add a new CF before it
+            my $new = RT::CustomField->new( RT->SystemUser );
+            my ($id, $msg) = $new->Create(
+                Name => $newname,
+                Type => 'Select',
+                MaxValues => 1,
+                LookupType => $cf->LookupType,
+                SortOrder => $cf->SortOrder - 1,
+            );
+            if ( $id ) {
+
+                # Set the CF to be based on what we just made
+                $cf->SetBasedOn( $new->Id );
+
+                # Apply it to all of the same things
+                {
+                    my $ocfs = RT::ObjectCustomFields->new( RT->SystemUser );
+                    $ocfs->LimitToCustomField( $cf->Id );
+                    while (my $ocf = $ocfs->Next) {
+                        my $newocf = RT::ObjectCustomField->new( RT->SystemUser );
+                        ($id, $msg) = $newocf->Create(
+                            SortOrder => $ocf->SortOrder,
+                            CustomField => $new->Id,
+                            ObjectId => $ocf->ObjectId,
+                        );
+                        RT->Logger->error("Can't create ObjectCustomField: $msg") unless $id;
+                    }
+                }
+
+                # Copy over all of the rights
+                {
+                    my $acl = RT::ACL->new( RT->SystemUser );
+                    $acl->LimitToObject( $cf );
+                    while (my $ace = $acl->Next) {
+                        my $newace = RT::ACE->new( RT->SystemUser );
+                        ($id, $msg) = $newace->Create(
+                            PrincipalId => $ace->PrincipalId,
+                            PrincipalType => $ace->PrincipalType,
+                            RightName => $ace->RightName,
+                            Object => $new,
+                        );
+                        RT->Logger->error("Can't assign rights: $msg") unless $id;
+                    }
+                }
+
+                # Add values for all of the categories
+                for my $i (0..$#categories) {
+                    ($id, $msg) = $new->AddValue(
+                        Name => $categories[$i],
+                        SortOrder => $i + 1,
+                    );
+                    RT->Logger->error("Can't create CustomFieldValue: $msg") unless $id;
+                }
+
+                # Grovel through all ObjectCustomFieldValues, and add the
+                # appropriate category
+                {
+                    my $ocfvs = RT::ObjectCustomFieldValues->new( RT->SystemUser );
+                    $ocfvs->LimitToCustomField( $cf->Id );
+                    while (my $ocfv = $ocfvs->Next) {
+                        next unless exists $mapping{$ocfv->Content};
+                        my $newocfv = RT::ObjectCustomFieldValue->new( RT->SystemUser );
+                        ($id, $msg) = $newocfv->Create(
+                            CustomField => $new->Id,
+                            ObjectType => $ocfv->ObjectType,
+                            ObjectId   => $ocfv->ObjectId,
+                            Content    => $mapping{$ocfv->Content},
+                        );
+                        RT->Logger->error("Can't create ObjectCustomFieldValue: $msg") unless $id;
+                    }
+                }
+            }
+            else {
+                RT->Logger->error("Can't create custom field '$newname': $msg");
+            }
+        }
+    },
+);
diff --git a/etc/upgrade/split-out-cf-categories.in b/etc/upgrade/split-out-cf-categories.in
deleted file mode 100644
index 12ce5ee..0000000
--- a/etc/upgrade/split-out-cf-categories.in
+++ /dev/null
@@ -1,170 +0,0 @@
-#!@PERL@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
-#                                          <sales at bestpractical.com>
-#
-# (Except where explicitly superseded by other copyright notices)
-#
-#
-# LICENSE:
-#
-# This work is made available to you under the terms of Version 2 of
-# the GNU General Public License. A copy of that license should have
-# been provided with this software, but in any event can be snarfed
-# from www.gnu.org.
-#
-# This work is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301 or visit their web page on the internet at
-# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
-#
-#
-# CONTRIBUTION SUBMISSION POLICY:
-#
-# (The following paragraph is not intended to limit the rights granted
-# to you to modify and distribute this software under the terms of
-# the GNU General Public License and is only of importance to you if
-# you choose to contribute your changes and enhancements to the
-# community by submitting them to Best Practical Solutions, LLC.)
-#
-# By intentionally submitting any modifications, corrections or
-# derivatives to this work, or any other work intended for use with
-# Request Tracker, to Best Practical Solutions, LLC, you confirm that
-# you are the copyright holder for those contributions and you grant
-# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
-# royalty-free, perpetual, license to use, copy, create derivative
-# works based on those contributions, and sublicense and distribute
-# those contributions and any derivatives thereof.
-#
-# END BPS TAGGED BLOCK }}}
-use 5.10.1;
-use strict;
-use warnings;
-
-use lib "@LOCAL_LIB_PATH@";
-use lib "@RT_LIB_PATH@";
-
-use RT -init;
-RT->Config->Set('LogToSTDERR' => 'debug');
-
-$| = 1;
-
-$RT::Handle->BeginTransaction();
-
-use RT::CustomFields;
-my $CFs = RT::CustomFields->new( RT->SystemUser );
-$CFs->UnLimit;
-$CFs->Limit( FIELD => 'Type', VALUE => 'Select' );
-
-my $seen;
-while (my $cf  = $CFs->Next ) {
-    next if $cf->BasedOnObj->Id;
-    my @categories;
-    my %mapping;
-    my $values = $cf->Values;
-    while (my $value = $values->Next) {
-        next unless defined $value->Category and length $value->Category;
-        push @categories, $value->Category unless grep {$_ eq $value->Category} @categories;
-        $mapping{$value->Name} = $value->Category;
-    }
-    next unless @categories;
-
-    $seen++;
-    print "Found CF '@{[$cf->Name]}' with categories:\n";
-    print "  $_\n" for @categories;
-
-    print "Split this CF's categories into a hierarchical custom field (Y/n)? ";
-    my $dothis = <>;
-    next if $dothis =~ /n/i;
-
-    print "Enter name of CF to create as category ('@{[$cf->Name]} category'): ";
-    my $newname = <>;
-    chomp $newname;
-    $newname = $cf->Name . " category" unless length $newname;
-
-    # bump the CF's sort oder up by one
-    $cf->SetSortOrder( ($cf->SortOrder || 0) + 1 );
-
-    # ..and add a new CF before it
-    my $new = RT::CustomField->new( RT->SystemUser );
-    my ($id, $msg) = $new->Create(
-        Name => $newname,
-        Type => 'Select',
-        MaxValues => 1,
-        LookupType => $cf->LookupType,
-        SortOrder => $cf->SortOrder - 1,
-    );
-    die "Can't create custom field '$newname': $msg" unless $id;
-
-    # Set the CF to be based on what we just made
-    $cf->SetBasedOn( $new->Id );
-
-    # Apply it to all of the same things
-    {
-        my $ocfs = RT::ObjectCustomFields->new( RT->SystemUser );
-        $ocfs->LimitToCustomField( $cf->Id );
-        while (my $ocf = $ocfs->Next) {
-            my $newocf = RT::ObjectCustomField->new( RT->SystemUser );
-            ($id, $msg) = $newocf->Create(
-                SortOrder => $ocf->SortOrder,
-                CustomField => $new->Id,
-                ObjectId => $ocf->ObjectId,
-            );
-            die "Can't create ObjectCustomField: $msg" unless $id;
-        }
-    }
-
-    # Copy over all of the rights
-    {
-        my $acl = RT::ACL->new( RT->SystemUser );
-        $acl->LimitToObject( $cf );
-        while (my $ace = $acl->Next) {
-            my $newace = RT::ACE->new( RT->SystemUser );
-            ($id, $msg) = $newace->Create(
-                PrincipalId => $ace->PrincipalId,
-                PrincipalType => $ace->PrincipalType,
-                RightName => $ace->RightName,
-                Object => $new,
-            );
-            die "Can't assign rights: $msg" unless $id;
-        }
-    }
-
-    # Add values for all of the categories
-    for my $i (0..$#categories) {
-        ($id, $msg) = $new->AddValue(
-            Name => $categories[$i],
-            SortOrder => $i + 1,
-        );
-        die "Can't create custom field value: $msg" unless $id;
-    }
-
-    # Grovel through all ObjectCustomFieldValues, and add the
-    # appropriate category
-    {
-        my $ocfvs = RT::ObjectCustomFieldValues->new( RT->SystemUser );
-        $ocfvs->LimitToCustomField( $cf->Id );
-        while (my $ocfv = $ocfvs->Next) {
-            next unless exists $mapping{$ocfv->Content};
-            my $newocfv = RT::ObjectCustomFieldValue->new( RT->SystemUser );
-            ($id, $msg) = $newocfv->Create(
-                CustomField => $new->Id,
-                ObjectType => $ocfv->ObjectType,
-                ObjectId   => $ocfv->ObjectId,
-                Content    => $mapping{$ocfv->Content},
-            );
-        }
-    }
-}
-
-$RT::Handle->Commit;
-print "No custom fields with categories found\n" unless $seen;
diff --git a/share/html/Admin/CustomFields/Modify.html b/share/html/Admin/CustomFields/Modify.html
index 8610cec..221a089 100644
--- a/share/html/Admin/CustomFields/Modify.html
+++ b/share/html/Admin/CustomFields/Modify.html
@@ -314,7 +314,7 @@ if ( $ARGS{'Update'} && $id ne 'new' ) {
             map { 
                 $ARGS{$paramtag."-new-$_"} =~ s/^\s+//;
                 $ARGS{$paramtag."-new-$_"} =~ s/\s+$//;
-                $_ => $ARGS{ $paramtag ."-new-$_" } } qw/ Name Description SortOrder Category/
+                $_ => $ARGS{ $paramtag ."-new-$_" } } grep { defined $ARGS{ $paramtag ."-new-$_" } } qw/ Name Description SortOrder Category/
         );
         push (@results, $msg);
         $added_cfv = 1 if $id;
diff --git a/share/html/Admin/Elements/AddCustomFieldValue b/share/html/Admin/Elements/AddCustomFieldValue
index ec1a34b..4ac648c 100644
--- a/share/html/Admin/Elements/AddCustomFieldValue
+++ b/share/html/Admin/Elements/AddCustomFieldValue
@@ -53,7 +53,7 @@
 <th><&|/l&>Sort</&></th>
 <th><&|/l&>Name</&></th>
 <th><&|/l&>Description</&></th>
-% if ( $CustomField->Type ne 'Combobox' ) {
+% if ( $CustomField->Type ne 'Combobox' && $Categories ) {
 <th class="categoryheader"><&|/l&>Category</&></th>
 % }
 </tr>
@@ -63,18 +63,12 @@
 <td><input type="text" size="3"  name="<% $paramtag %>-SortOrder"   /></td>
 <td><input type="text" size="25" name="<% $paramtag %>-Name"        /></td>
 <td><input type="text" size="45" name="<% $paramtag %>-Description" /></td>
-% if ( $CustomField->Type ne 'Combobox' ) {
+% if ( $CustomField->Type ne 'Combobox' && $Categories ) {
 <td>
-% my $BasedOnObj = $CustomField->BasedOnObj;
-% if ( $BasedOnObj and $BasedOnObj->id ) {
-% my $Categories = $BasedOnObj->Values;
 <select class="editcategory" name="<% $paramtag %>-Category" size="1">
 <option value=""><&|/l&>(no value)</&></option>
 % while (my $Value = $Categories->Next) {
 <option value="<% $Value->Name %>"><% $Value->Name %></option>
-% }
-%   } else {
-<input type="text" size="10" class="editcategory" name="<% $paramtag %>-Category" value="" />
 %   }
 </td>
 % }
@@ -83,6 +77,15 @@
 </tr>
 
 </table>
+
+<%init>
+my $BasedOnObj = $CustomField->BasedOnObj;
+my $Categories;
+if ($BasedOnObj and $BasedOnObj->Id) {
+    $Categories = $BasedOnObj->Values;
+}
+</%init>
+
 <%args>
 $CustomField => undef
 </%args>
diff --git a/share/html/Admin/Elements/EditCustomFieldValues b/share/html/Admin/Elements/EditCustomFieldValues
index 5a81ec7..6ff2380 100644
--- a/share/html/Admin/Elements/EditCustomFieldValues
+++ b/share/html/Admin/Elements/EditCustomFieldValues
@@ -57,7 +57,7 @@
 <th><&|/l&>Sort</&></th>
 <th><&|/l&>Name</&></th>
 <th><&|/l&>Description</&></th>
-% if ($CustomField->Type ne 'Combobox') {
+% if ( $CustomField->Type ne 'Combobox' && $Categories ) {
 <th class="categoryheader"><&|/l&>Category</&></th>
 % }
 </tr>
@@ -69,18 +69,14 @@
 <td><input type="text" size="3" name="<% $paramtag %>-SortOrder" value="<% $value->SortOrder %>" /></td>
 <td><input type="text" size="25" name="<% $paramtag %>-Name" value="<% $value->Name %>" /></td>
 <td><input type="text" size="45" name="<% $paramtag %>-Description" value="<% $value->Description || '' %>" /></td>
-% if ( $CustomField->Type ne 'Combobox' ) {
+% if ( $CustomField->Type ne 'Combobox' && $Categories ) {
 <td>
-%   if ( $Categories ) {
 % my $selected = $value->Category;
 % $selected = '' unless defined $selected;
 <select class="editcategory" name="<% $paramtag %>-Category" size="1">
 <option value=""<% $selected eq '' ? q[ selected="selected"] : "" |n%>><&|/l&>(no value)</&></option>
 % while (my $Value = $Categories->Next) {
 <option value="<% $Value->Name %>"<% $selected eq $Value->Name ? q[ selected="selected"] : "" |n%>><% $Value->Name %></option>
-% }
-%   } else {
-<input type="text" size="10" class="editcategory" name="<% $paramtag %>-Category" value="<% $value->Category || '' %>" />
 %   }
 </td>
 % }
diff --git a/share/html/Elements/EditCustomFieldSelect b/share/html/Elements/EditCustomFieldSelect
index cd9a4e6..0611ccc 100644
--- a/share/html/Elements/EditCustomFieldSelect
+++ b/share/html/Elements/EditCustomFieldSelect
@@ -51,16 +51,7 @@
 % my $selected = 0;
 % my @category;
 % my $out = $m->scomp('SELF:options', %ARGS, SelectedRef => \$selected, CategoryRef => \@category);
-% if (!$HideCategory and @category and not $CustomField->BasedOnObj->id) {
-%# XXX - Hide this select from w3m?
-  <select onchange="filter_cascade_by_id(<% $name |n,j %>, this.value)" name="<% $name %>-Category" class="CF-<%$CustomField->id%>-Edit">
-    <option value=""<% !$selected && qq[ selected="selected"] |n %>><&|/l&>-</&></option>
-%   foreach my $cat (@category) {
-%     my ($depth, $name) = @$cat;
-      <option value="<% $name %>"><% ' ' x $depth |n %><% $name %></option>
-%   }
-    </select><br />
-% } elsif ($CustomField->BasedOnObj->id) {
+% if ($CustomField->BasedOnObj->id) {
 
 <script type="text/javascript"><!--
 jQuery(  function () {

commit bbd3a18c084b83fe787858dbd79a5277cd2c624e
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Tue Jan 13 23:09:44 2015 +0800

    is_hierarchical and complete_select are always true now
    
    so it's not necessary to keep is_hierarchical as an argument and check the
    complete_select's trueness

diff --git a/share/html/Elements/EditCustomFieldSelect b/share/html/Elements/EditCustomFieldSelect
index 0611ccc..2ec417f 100644
--- a/share/html/Elements/EditCustomFieldSelect
+++ b/share/html/Elements/EditCustomFieldSelect
@@ -73,8 +73,7 @@ jQuery(  function () {
             }
             filter_cascade_by_id(
                 <% $name |n,j%>,
-                vals,
-                true
+                vals
             );
             if (oldchange != null)
                 oldchange();
diff --git a/share/static/js/cascaded.js b/share/static/js/cascaded.js
index 0593466..1f78074 100644
--- a/share/static/js/cascaded.js
+++ b/share/static/js/cascaded.js
@@ -1,19 +1,18 @@
-function filter_cascade_by_id (id, vals, is_hierarchical) {
+function filter_cascade_by_id (id, vals) {
     var element = document.getElementById(id);
     if (!element) { return };
 
     if ( element.tagName == 'SELECT' ) {
         var complete_select = document.getElementById(id + "-Complete" );
-        return filter_cascade_select(element, complete_select, vals, is_hierarchical);
+        return filter_cascade_select(element, complete_select, vals );
     }
     else {
         if ( !( vals instanceof Array ) ) {
             vals = [vals];
         }
 
-        if ( is_hierarchical && (vals.length == 0 || (vals.length == 1 && vals[0] == '')) ) {
-            // no category, and the category is from a hierchical cf;
-            // leave it empty
+        if ( vals.length == 0 || (vals.length == 1 && vals[0] == '') ) {
+            // no category, leave it empty
             jQuery(element).find('div').hide();
         }
         else {
@@ -30,7 +29,7 @@ function filter_cascade_by_id (id, vals, is_hierarchical) {
     }
 }
 
-function filter_cascade_select (select, complete_select, vals, is_hierarchical) {
+function filter_cascade_select (select, complete_select, vals) {
     if ( !( vals instanceof Array ) ) {
         vals = [vals];
     }
@@ -39,69 +38,47 @@ function filter_cascade_select (select, complete_select, vals, is_hierarchical)
     var i;
     var children = select.childNodes;
 
-    if ( complete_select ) {
-        jQuery(select).children().remove();
+    jQuery(select).children().remove();
 
-        var complete_children = complete_select.childNodes;
+    var complete_children = complete_select.childNodes;
 
-        var cloned_labels = {};
-        var cloned_empty_label;
-        for ( var j = 0; j < vals.length; j++ ) {
-            var val = vals[j];
-            if ( val == '' && is_hierarchical ) {
-                // no category, and the category is from a hierchical cf;
-                // leave this set of options empty
-            } else if ( val == '' ) {
-                // no category, let's clone all node
-                jQuery(select).append(jQuery(complete_children).clone());
-                break;
-            }
-            else {
-                var labels_to_clone = {};
-                for (i = 0; i < complete_children.length; i++) {
-                    if (!complete_children[i].label ||
-                          (complete_children[i].hasAttribute &&
-                                !complete_children[i].hasAttribute('label') ) ) {
-                        if ( cloned_empty_label ) {
-                            continue;
-                        }
-                    }
-                    else if ( complete_children[i].label == val ) {
-                        if ( cloned_labels[complete_children[i].label] ) {
-                            continue;
-                        }
-                        labels_to_clone[complete_children[i].label] = true;
+    var cloned_labels = {};
+    var cloned_empty_label;
+    for ( var j = 0; j < vals.length; j++ ) {
+        var val = vals[j];
+        if ( val == '' ) {
+            // no category, leave this set of options empty
+        }
+        else {
+            var labels_to_clone = {};
+            for (i = 0; i < complete_children.length; i++) {
+                if (!complete_children[i].label ||
+                      (complete_children[i].hasAttribute &&
+                            !complete_children[i].hasAttribute('label') ) ) {
+                    if ( cloned_empty_label ) {
+                        continue;
                     }
-                    else {
+                }
+                else if ( complete_children[i].label == val ) {
+                    if ( cloned_labels[complete_children[i].label] ) {
                         continue;
                     }
-
-                    jQuery(select).append(jQuery(complete_children[i]).clone());
+                    labels_to_clone[complete_children[i].label] = true;
                 }
-
-                if ( !cloned_empty_label )
-                    cloned_empty_label = true;
-
-                for ( label in labels_to_clone ) {
-                    if ( !cloned_labels[label] )
-                        cloned_labels[label] = true;
+                else {
+                    continue;
                 }
+
+                jQuery(select).append(jQuery(complete_children[i]).clone());
             }
-        }
-    }
-    else {
-// for back compatibility
-        for (i = 0; i < children.length; i++) {
-            if (!children[i].label) { continue };
-            if ( val == '' && is_hierarchical ) {
-                hide(children[i]);
-                continue;
-            }
-            if ( val == '' || children[i].label.substr(0, val.length) == val) {
-                show(children[i]);
-                continue;
+
+            if ( !cloned_empty_label )
+                cloned_empty_label = true;
+
+            for ( label in labels_to_clone ) {
+                if ( !cloned_labels[label] )
+                    cloned_labels[label] = true;
             }
-            hide(children[i]);
         }
     }
 }
diff --git a/share/static/js/event-registration.js b/share/static/js/event-registration.js
index aec1742..9d984d4 100644
--- a/share/static/js/event-registration.js
+++ b/share/static/js/event-registration.js
@@ -76,7 +76,7 @@ jQuery(function() {
             var subfield = field.next("select[name=" + name + "]");
             var complete = subfield.next("select[name=" + name + "-Complete]");
             var value    = field.val();
-            filter_cascade_select( subfield[0], complete[0], value, true );
+            filter_cascade_select( subfield[0], complete[0], value );
         }).change();
     });
 });

commit 4aaa5f27074233c585b2f4a5bce96cb94c0e32da
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Jan 15 01:56:37 2015 +0800

    move cascade select event code to event-registration.js
    
    aim to avoid inline javascript

diff --git a/share/html/Elements/EditCustomFieldSelect b/share/html/Elements/EditCustomFieldSelect
index 2ec417f..4221e32 100644
--- a/share/html/Elements/EditCustomFieldSelect
+++ b/share/html/Elements/EditCustomFieldSelect
@@ -51,48 +51,14 @@
 % my $selected = 0;
 % my @category;
 % my $out = $m->scomp('SELF:options', %ARGS, SelectedRef => \$selected, CategoryRef => \@category);
-% if ($CustomField->BasedOnObj->id) {
-
-<script type="text/javascript"><!--
-jQuery(  function () {
-    var basedon = jQuery('[name^="'+<% $BasedOnName || $NamePrefix . $CustomField->BasedOnObj->id . '-Value' |n,j %>+'"][type!="hidden"]:input:not(.hidden)');
-    basedon.each( function() {
-        var oldchange = jQuery(this).onchange;
-        jQuery(this).change( function () {
-            var vals;
-            if ( jQuery(this).is('select') ) {
-                vals = basedon.first().val();
-            }
-            else {
-                vals = [];
-                jQuery(basedon).each( function() {
-                    if ( jQuery(this).is(':checked') ) {
-                        vals.push(jQuery(this).val());
-                    }
-                });
-            }
-            filter_cascade_by_id(
-                <% $name |n,j%>,
-                vals
-            );
-            if (oldchange != null)
-                oldchange();
-        });
-    });
-
-    if ( basedon.is('select') ) {
-        basedon.change();
-    }
-    else {
-        basedon.first().change();
-    }
-});
---></script>
-% }
 
 % if ( $RenderType eq 'List' ) {
 <fieldset class="cfedit">
-<div data-name="<%$name%>" id="<%$name%>">
+<div data-name="<%$name%>" id="<%$name%>"
+% if ($CustomField->BasedOnObj->id) {
+  data-cascade-based-on-name="<% $BasedOnName || $NamePrefix . $CustomField->BasedOnObj->id . '-Value' |n %>"
+% }
+>
 %   if ( $checktype eq 'radio' ) {
 % if ( $show_empty_option ) {
   <div class="none">
@@ -125,6 +91,9 @@ jQuery(  function () {
 % }
 <select
   name="<%$name%>" id="<%$name%>" class="CF-<%$CustomField->id%>-Edit"
+% if ($CustomField->BasedOnObj->id) {
+  data-cascade-based-on-name="<% $BasedOnName || $NamePrefix . $CustomField->BasedOnObj->id . '-Value' |n %>"
+% }
 % if ( $Rows && ( $Multiple || !@category || $RenderType eq 'Select box') ) {
   size="<% $Rows %>"
 % }
diff --git a/share/static/js/event-registration.js b/share/static/js/event-registration.js
index 9d984d4..f694382 100644
--- a/share/static/js/event-registration.js
+++ b/share/static/js/event-registration.js
@@ -79,6 +79,39 @@ jQuery(function() {
             filter_cascade_select( subfield[0], complete[0], value );
         }).change();
     });
+
+    jQuery('[data-cascade-based-on-name]').each( function() {
+        var based_on_name = jQuery(this).attr('data-cascade-based-on-name');
+        var based_on = jQuery('[name^="' + based_on_name + '"][type!="hidden"]:input:not(.hidden)');
+        var id = jQuery(this).attr('id');
+        based_on.each( function() {
+            var oldchange = jQuery(this).onchange;
+            jQuery(this).change( function () {
+                var vals;
+                if ( jQuery(this).is('select') ) {
+                    vals = based_on.first().val();
+                }
+                else {
+                    vals = [];
+                    jQuery(based_on).each( function() {
+                        if ( jQuery(this).is(':checked') ) {
+                            vals.push(jQuery(this).val());
+                        }
+                    });
+                }
+                filter_cascade_by_id( id, vals );
+                if (oldchange != null)
+                    oldchange();
+            });
+        });
+
+        if ( based_on.is('select') ) {
+            based_on.change();
+        }
+        else {
+            based_on.first().change();
+        }
+    });
 });
 
 jQuery( function() {

commit 08cfcf31b2c348e032c1384ad561226ca3aff1f6
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Jan 15 02:41:27 2015 +0800

    simplify filter_cascade_select by using jQuery functions
    
    no functions are changed

diff --git a/share/static/js/cascaded.js b/share/static/js/cascaded.js
index 1f78074..5ce33b4 100644
--- a/share/static/js/cascaded.js
+++ b/share/static/js/cascaded.js
@@ -40,7 +40,7 @@ function filter_cascade_select (select, complete_select, vals) {
 
     jQuery(select).children().remove();
 
-    var complete_children = complete_select.childNodes;
+    var complete_children = jQuery(complete_select).children();
 
     var cloned_labels = {};
     var cloned_empty_label;
@@ -51,34 +51,28 @@ function filter_cascade_select (select, complete_select, vals) {
         }
         else {
             var labels_to_clone = {};
-            for (i = 0; i < complete_children.length; i++) {
-                if (!complete_children[i].label ||
-                      (complete_children[i].hasAttribute &&
-                            !complete_children[i].hasAttribute('label') ) ) {
-                    if ( cloned_empty_label ) {
-                        continue;
+            complete_children.each( function() {
+                var label = jQuery(this).attr('label');
+                var need_clone;
+                if ( !label ) {
+                    if ( !cloned_empty_label ) {
+                        need_clone = true;
                     }
                 }
-                else if ( complete_children[i].label == val ) {
-                    if ( cloned_labels[complete_children[i].label] ) {
-                        continue;
+                else if ( label == val ) {
+                    if ( !cloned_labels[label] ) {
+                        need_clone = true;
                     }
-                    labels_to_clone[complete_children[i].label] = true;
-                }
-                else {
-                    continue;
                 }
 
-                jQuery(select).append(jQuery(complete_children[i]).clone());
-            }
+                if ( need_clone ) {
+                    jQuery(select).append(jQuery(this).clone());
+                    cloned_labels[label] = true;
+                }
+            });
 
             if ( !cloned_empty_label )
                 cloned_empty_label = true;
-
-            for ( label in labels_to_clone ) {
-                if ( !cloned_labels[label] )
-                    cloned_labels[label] = true;
-            }
         }
     }
 }

-----------------------------------------------------------------------


More information about the rt-commit mailing list