Index: trunk/extensions/SemanticForms/SemanticForms.php |
— | — | @@ -348,3 +348,5 @@ |
349 | 349 | # ## |
350 | 350 | $sfgShowOnSelect = array(); |
351 | 351 | $sfgAutocompleteValues = array(); |
| 352 | +$sfgFieldProperties = array(); |
| 353 | +$sfgDependentFields = array(); |
Index: trunk/extensions/SemanticForms/includes/SF_FormField.php |
— | — | @@ -48,11 +48,11 @@ |
49 | 49 | } |
50 | 50 | |
51 | 51 | static function createFromDefinition( $fieldName, $inputName, $isMandatory, $isHidden, $isUploadable, $possibleValues, $isDisabled, $isList, $inputType, $fieldArgs, $allFields, $strictParsing ) { |
52 | | - // see if this field matches one of the fields defined for this |
| 52 | + // See if this field matches one of the fields defined for this |
53 | 53 | // template - if it is, use all available information about |
54 | 54 | // that field; if it's not, either include it in the form or |
55 | 55 | // not, depending on whether the template has a 'strict' |
56 | | - // setting in the form definition |
| 56 | + // setting in the form definition. |
57 | 57 | $the_field = null; |
58 | 58 | foreach ( $allFields as $cur_field ) { |
59 | 59 | if ( $fieldName == $cur_field->getFieldName() ) { |
— | — | @@ -333,10 +333,10 @@ |
334 | 334 | if ( ! array_key_exists( 'autocompletion source', $other_args ) ) { |
335 | 335 | if ( $this->template_field->getPropertyType() == '_wpg' ) { |
336 | 336 | $other_args['autocompletion source'] = $this->template_field->getSemanticProperty(); |
337 | | - $other_args['autocomplete field type'] = 'relation'; |
| 337 | + $other_args['autocomplete field type'] = 'property'; |
338 | 338 | } elseif ( array_key_exists( 'autocomplete', $other_args ) || array_key_exists( 'remote autocompletion', $other_args ) ) { |
339 | 339 | $other_args['autocompletion source'] = $this->template_field->getSemanticProperty(); |
340 | | - $other_args['autocomplete field type'] = 'attribute'; |
| 340 | + $other_args['autocomplete field type'] = 'property'; |
341 | 341 | } |
342 | 342 | } |
343 | 343 | // Now merge in the default values set by SFFormPrinter, if |
Index: trunk/extensions/SemanticForms/includes/SF_FormPrinter.php |
— | — | @@ -734,6 +734,7 @@ |
735 | 735 | // ===================================================== |
736 | 736 | } elseif ( $tag_title == 'field' ) { |
737 | 737 | $field_name = trim( $tag_components[1] ); |
| 738 | + $fullFieldName = $template_name . '[' . $field_name . ']'; |
738 | 739 | // cycle through the other components |
739 | 740 | $is_mandatory = false; |
740 | 741 | $is_hidden = false; |
— | — | @@ -853,6 +854,9 @@ |
854 | 855 | $possible_values = SFUtils::getAllPagesForConcept( $sub_components[1] ); |
855 | 856 | } elseif ( $sub_components[0] == 'values from namespace' ) { |
856 | 857 | $possible_values = SFUtils::getAllPagesForNamespace( $sub_components[1] ); |
| 858 | + } elseif ( $sub_components[0] == 'values dependent on' ) { |
| 859 | + global $sfgDependentFields; |
| 860 | + $sfgDependentFields[$sub_components[1]] = $fullFieldName; |
857 | 861 | } elseif ( $sub_components[0] == 'property' ) { |
858 | 862 | $semantic_property = $sub_components[1]; |
859 | 863 | } elseif ( $sub_components[0] == 'default filename' ) { |
— | — | @@ -862,7 +866,7 @@ |
863 | 867 | $field_args['default filename'] = $default_filename; |
864 | 868 | } elseif ( $sub_components[0] == 'restricted' ) { |
865 | 869 | $is_restricted = !array_intersect( |
866 | | - $wgUser->getEffectiveGroups(), array_map( 'trim', explode( ',', $sub_components[1] ) ) |
| 870 | + $wgUser->getEffectiveGroups(), array_map( 'trim', explode( ',', $sub_components[1] ) ) |
867 | 871 | ); |
868 | 872 | } |
869 | 873 | } |
— | — | @@ -1070,6 +1074,7 @@ |
1071 | 1075 | // 'num' will get replaced by an actual index, either in PHP |
1072 | 1076 | // or in Javascript, later on |
1073 | 1077 | $input_name = $template_name . '[num][' . $field_name . ']'; |
| 1078 | + $field_args['origName'] = $template_name . '[' . $field_name . ']'; |
1074 | 1079 | } else { |
1075 | 1080 | $input_name = $template_name . '[' . $field_name . ']'; |
1076 | 1081 | } |
— | — | @@ -1120,7 +1125,13 @@ |
1121 | 1126 | if ( $semantic_property != null ) { |
1122 | 1127 | $form_field->template_field->setSemanticProperty( $semantic_property ); |
1123 | 1128 | } |
| 1129 | + $semantic_property = $form_field->template_field->getSemanticProperty(); |
| 1130 | + if ( !is_null( $semantic_property ) ) { |
| 1131 | + global $sfgFieldProperties; |
| 1132 | + $sfgFieldProperties[$fullFieldName] = $semantic_property; |
| 1133 | + } |
1124 | 1134 | |
| 1135 | + |
1125 | 1136 | // call hooks - unfortunately this has to be split into two |
1126 | 1137 | // separate calls, because of the different variable names in |
1127 | 1138 | // each case |
Index: trunk/extensions/SemanticForms/includes/SF_FormUtils.php |
— | — | @@ -13,6 +13,7 @@ |
14 | 14 | class SFFormUtils { |
15 | 15 | static function setGlobalJSVariables( &$vars ) { |
16 | 16 | global $sfgAutocompleteValues, $sfgAutocompleteOnAllChars; |
| 17 | + global $sfgFieldProperties, $sfgDependentFields; |
17 | 18 | global $sfgScriptPath; |
18 | 19 | // global $sfgInitJSFunctions, $sfgValidationJSFunctions; |
19 | 20 | global $sfgShowOnSelect; |
— | — | @@ -21,6 +22,8 @@ |
22 | 23 | $vars['sfgScriptPath'] = $sfgScriptPath; |
23 | 24 | $vars['sfgAutocompleteValues'] = $sfgAutocompleteValues; |
24 | 25 | $vars['sfgShowOnSelect'] = $sfgShowOnSelect; |
| 26 | + $vars['sfgFieldProperties'] = $sfgFieldProperties; |
| 27 | + $vars['sfgDependentFields'] = $sfgDependentFields; |
25 | 28 | // $vars['sfgInitJSFunctions'] = $sfgInitJSFunctions; |
26 | 29 | // $vars['sfgValidationJSFunctions'] = $sfgValidationJSFunctions; |
27 | 30 | $vars['sfgFormErrorsHeader'] = wfMsg( 'sf_formerrors_header' ); |
Index: trunk/extensions/SemanticForms/includes/forminputs/SF_TextAreaWithAutocompleteInput.php |
— | — | @@ -113,6 +113,9 @@ |
114 | 114 | $textarea_attrs['style'] = 'width: 100%'; |
115 | 115 | } |
116 | 116 | |
| 117 | + if ( array_key_exists( 'origName', $other_args ) ) { |
| 118 | + $inputAttrs['origName'] = $other_args['origName']; |
| 119 | + } |
117 | 120 | if ( !is_null( $remoteDataType ) ) { |
118 | 121 | $textarea_attrs['autocompletedatatype'] = $remoteDataType; |
119 | 122 | } |
Index: trunk/extensions/SemanticForms/includes/forminputs/SF_TextWithAutocompleteInput.php |
— | — | @@ -39,12 +39,7 @@ |
40 | 40 | public static function getAutocompletionTypeAndSource( &$field_args ) { |
41 | 41 | if ( array_key_exists( 'values from property', $field_args ) ) { |
42 | 42 | $autocompletionSource = $field_args['values from property']; |
43 | | - $propValue = SMWPropertyValue::makeUserProperty( $autocompletionSource ); |
44 | | - if ( $propValue->getPropertyTypeID() == '_wpg' ) { |
45 | | - $autocompleteFieldType = 'relation'; |
46 | | - } else { |
47 | | - $autocompleteFieldType = 'attribute'; |
48 | | - } |
| 43 | + $autocompleteFieldType = 'property'; |
49 | 44 | } elseif ( array_key_exists( 'values from category', $field_args ) ) { |
50 | 45 | $autocompleteFieldType = 'category'; |
51 | 46 | $autocompletionSource = $field_args['values from category']; |
— | — | @@ -68,12 +63,7 @@ |
69 | 64 | $autocompletionSource = $field_args['autocompletion source']; |
70 | 65 | } elseif ( array_key_exists( 'semantic_property', $field_args ) ) { |
71 | 66 | $autocompletionSource = $field_args['semantic_property']; |
72 | | - $propValue = SMWPropertyValue::makeUserProperty( $autocompletionSource ); |
73 | | - if ( $propValue->getPropertyTypeID() == '_wpg' ) { |
74 | | - $autocompleteFieldType = 'relation'; |
75 | | - } else { |
76 | | - $autocompleteFieldType = 'attribute'; |
77 | | - } |
| 67 | + $autocompleteFieldType = 'property'; |
78 | 68 | } else { |
79 | 69 | $autocompleteFieldType = null; |
80 | 70 | $autocompletionSource = null; |
— | — | @@ -164,6 +154,9 @@ |
165 | 155 | 'tabindex' => $sfgTabIndex, |
166 | 156 | 'autocompletesettings' => $autocompleteSettings, |
167 | 157 | ); |
| 158 | + if ( array_key_exists( 'origName', $other_args ) ) { |
| 159 | + $inputAttrs['origName'] = $other_args['origName']; |
| 160 | + } |
168 | 161 | if ( !is_null( $remoteDataType ) ) { |
169 | 162 | $inputAttrs['autocompletedatatype'] = $remoteDataType; |
170 | 163 | } |
Index: trunk/extensions/SemanticForms/includes/forminputs/SF_ComboBoxInput.php |
— | — | @@ -76,6 +76,9 @@ |
77 | 77 | 'autocompletesettings' => $autocompletionSource, |
78 | 78 | 'comboboxwidth' => $pixel_width, |
79 | 79 | ); |
| 80 | + if ( array_key_exists( 'origName', $other_args ) ) { |
| 81 | + $selectAttrs['origname'] = $other_args['origName']; |
| 82 | + } |
80 | 83 | if ( array_key_exists( 'existing values only', $other_args ) ) { |
81 | 84 | $selectAttrs['existingvaluesonly'] = 'true'; |
82 | 85 | } |
Index: trunk/extensions/SemanticForms/includes/SF_AutocompleteAPI.php |
— | — | @@ -22,20 +22,24 @@ |
23 | 23 | $params = $this->extractRequestParams(); |
24 | 24 | $substr = $params['substr']; |
25 | 25 | $namespace = $params['namespace']; |
26 | | - $attribute = $params['attribute']; |
27 | | - $relation = $params['relation']; |
| 26 | + $property = $params['property']; |
28 | 27 | $category = $params['category']; |
29 | 28 | $concept = $params['concept']; |
30 | 29 | $external_url = $params['external_url']; |
| 30 | + $baseprop = $params['baseprop']; |
| 31 | + $basevalue = $params['basevalue']; |
| 32 | + //$limit = $params['limit']; |
31 | 33 | |
32 | | - if ( strlen( $substr ) == 0 ) { |
| 34 | + if ( is_null( $baseprop ) && strlen( $substr ) == 0 ) { |
33 | 35 | $this->dieUsage( 'The substring must be specified', 'param_substr' ); |
34 | 36 | } |
35 | 37 | |
36 | | - if ( !is_null( $attribute ) ) { |
37 | | - $data = self::getAllValuesForProperty( false, $attribute, $substr ); |
38 | | - } elseif ( !is_null( $relation ) ) { |
39 | | - $data = self::getAllValuesForProperty( true, $relation, $substr ); |
| 38 | + if ( !is_null( $baseprop ) ) { |
| 39 | + if ( !is_null( $property ) ) { |
| 40 | + $data = self::getAllValuesForProperty( $property, null, $baseprop, $basevalue ); |
| 41 | + } |
| 42 | + } elseif ( !is_null( $property ) ) { |
| 43 | + $data = self::getAllValuesForProperty( $property, $substr ); |
40 | 44 | } elseif ( !is_null( $category ) ) { |
41 | 45 | $data = SFUtils::getAllPagesForCategory( $category, 3, $substr ); |
42 | 46 | } elseif ( !is_null( $concept ) ) { |
— | — | @@ -78,25 +82,27 @@ |
79 | 83 | ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 |
80 | 84 | ), |
81 | 85 | 'substr' => null, // Once 1.17 becomes acceptable as dependency, use ApiBase::PARAM_REQUIRED |
82 | | - 'attribute' => null, |
83 | | - 'relation' => null, |
| 86 | + 'property' => null, |
84 | 87 | 'category' => null, |
85 | 88 | 'concept' => null, |
86 | 89 | 'namespace' => null, |
87 | 90 | 'external_url' => null, |
| 91 | + 'baseprop' => null, |
| 92 | + 'basevalue' => null, |
88 | 93 | ); |
89 | 94 | } |
90 | 95 | |
91 | 96 | protected function getParamDescription() { |
92 | 97 | return array ( |
93 | 98 | 'substr' => 'Search substring', |
94 | | - 'attribute' => 'Attribute (non-page property) for which to search values', |
95 | | - 'relation' => 'Relation (page property) for which to search values', |
| 99 | + 'property' => 'Semantic property for which to search values', |
96 | 100 | 'category' => 'Category for which to search values', |
97 | 101 | 'concept' => 'Concept for which to search values', |
98 | 102 | 'namespace' => 'Namespace for which to search values', |
99 | 103 | 'external_url' => 'Alias for external URL from which to get values', |
100 | | - 'limit' => 'Limit how many entries to return', |
| 104 | + 'baseprop' => 'A previous property in the form to check against', |
| 105 | + 'basevalue' => 'The value to check for the previous property', |
| 106 | + //'limit' => 'Limit how many entries to return', |
101 | 107 | ); |
102 | 108 | } |
103 | 109 | |
— | — | @@ -107,7 +113,7 @@ |
108 | 114 | protected function getExamples() { |
109 | 115 | return array ( |
110 | 116 | 'api.php?action=sfautocomplete&substr=te', |
111 | | - 'api.php?action=sfautocomplete&substr=te&relation=Has_author', |
| 117 | + 'api.php?action=sfautocomplete&substr=te&property=Has_author', |
112 | 118 | 'api.php?action=sfautocomplete&substr=te&category=Authors', |
113 | 119 | ); |
114 | 120 | } |
— | — | @@ -116,7 +122,7 @@ |
117 | 123 | return __CLASS__ . ': $Id$'; |
118 | 124 | } |
119 | 125 | |
120 | | - public static function getAllValuesForProperty( $is_relation, $property_name, $substring = null ) { |
| 126 | + private static function getAllValuesForProperty( $property_name, $substring, $base_property_name = null, $base_value = null ) { |
121 | 127 | global $sfgMaxAutocompleteValues; |
122 | 128 | |
123 | 129 | $values = array(); |
— | — | @@ -124,6 +130,11 @@ |
125 | 131 | $sql_options = array(); |
126 | 132 | $sql_options['LIMIT'] = $sfgMaxAutocompleteValues; |
127 | 133 | |
| 134 | + $property = SMWPropertyValue::makeUserProperty( $property_name ); |
| 135 | + $is_relation = ( $property->getPropertyTypeID() == '_wpg' ); |
| 136 | + $property_name = str_replace( ' ', '_', $property_name ); |
| 137 | + $conditions = array( 'p_ids.smw_title' => $property_name ); |
| 138 | + |
128 | 139 | if ( $is_relation ) { |
129 | 140 | $value_field = 'o_ids.smw_title'; |
130 | 141 | $from_clause = $db->tableName( 'smw_rels2' ) . " r JOIN " . $db->tableName( 'smw_ids' ) . " p_ids ON r.p_id = p_ids.smw_id JOIN " . $db->tableName( 'smw_ids' ) . " o_ids ON r.o_id = o_ids.smw_id"; |
— | — | @@ -132,14 +143,30 @@ |
133 | 144 | $from_clause = $db->tableName( 'smw_atts2' ) . " a JOIN " . $db->tableName( 'smw_ids' ) . " p_ids ON a.p_id = p_ids.smw_id"; |
134 | 145 | } |
135 | 146 | |
136 | | - $property_name = str_replace( ' ', '_', $property_name ); |
137 | | - $conditions = "p_ids.smw_title = '$property_name'"; |
| 147 | + if ( !is_null( $base_property_name ) ) { |
| 148 | + $base_property = SMWPropertyValue::makeUserProperty( $base_property_name ); |
| 149 | + $base_is_relation = ( $base_property->getPropertyTypeID() == '_wpg' ); |
138 | 150 | |
139 | | - if ( $substring != null ) { |
| 151 | + $base_property_name = str_replace( ' ', '_', $base_property_name ); |
| 152 | + $conditions['base_p_ids.smw_title'] = $base_property_name; |
| 153 | + $main_prop_alias = ( $is_relation ) ? 'r' : 'a'; |
| 154 | + if ( $base_is_relation ) { |
| 155 | + $from_clause .= " JOIN " . $db->tableName( 'smw_rels2' ) . " r_base ON $main_prop_alias.s_id = r_base.s_id"; |
| 156 | + $from_clause .= " JOIN " . $db->tableName( 'smw_ids' ) . " base_p_ids ON r_base.p_id = base_p_ids.smw_id JOIN " . $db->tableName( 'smw_ids' ) . " base_o_ids ON r_base.o_id = base_o_ids.smw_id"; |
| 157 | + $base_value = str_replace( ' ', '_', $base_value ); |
| 158 | + $conditions['base_o_ids.smw_title'] = $base_value; |
| 159 | + } else { |
| 160 | + $from_clause .= " JOIN " . $db->tableName( 'smw_atts2' ) . " a_base ON $main_prop_alias.s_id = a_base.s_id"; |
| 161 | + $from_clause .= " JOIN " . $db->tableName( 'smw_ids' ) . " base_p_ids ON a_base.p_id = base_p_ids.smw_id"; |
| 162 | + $conditions['a_base.value_xsd'] = $base_value; |
| 163 | + } |
| 164 | + } |
| 165 | + |
| 166 | + if ( !is_null( $substring ) ) { |
140 | 167 | $substring = str_replace( "'", "\'", strtolower( $substring ) ); |
141 | | - // utf8 conversion is needed in case MediaWiki is using |
142 | | - // binary data storage |
143 | | - $conditions .= " AND (REPLACE(LOWER(CONVERT($value_field USING utf8)),'_',' ') LIKE '" . $substring . "%' OR REPLACE(LOWER(CONVERT($value_field USING utf8)),'_',' ') LIKE '% " . $substring . "%')"; |
| 168 | + // UTF-8 conversion is needed in case MediaWiki is using |
| 169 | + // binary data storage. |
| 170 | + $conditions[] = "REPLACE(LOWER(CONVERT($value_field USING utf8)),'_',' ') LIKE '" . $substring . "%' OR REPLACE(LOWER(CONVERT($value_field USING utf8)),'_',' ') LIKE '% " . $substring . "%'"; |
144 | 171 | } |
145 | 172 | |
146 | 173 | $sql_options['ORDER BY'] = $value_field; |
— | — | @@ -147,12 +174,7 @@ |
148 | 175 | $conditions, __METHOD__, $sql_options ); |
149 | 176 | |
150 | 177 | while ( $row = $db->fetchRow( $res ) ) { |
151 | | - if ( $substring != null ) { |
152 | | - $values[] = str_replace( '_', ' ', $row[0] ); |
153 | | - } else { |
154 | | - $cur_value = str_replace( "'", "\'", $row[0] ); |
155 | | - $values[] = str_replace( '_', ' ', $cur_value ); |
156 | | - } |
| 178 | + $values[] = str_replace( '_', ' ', $row[0] ); |
157 | 179 | } |
158 | 180 | $db->freeResult( $res ); |
159 | 181 | |
Index: trunk/extensions/SemanticForms/libs/SemanticForms.js |
— | — | @@ -82,7 +82,10 @@ |
83 | 83 | } |
84 | 84 | }); |
85 | 85 | |
86 | | - values = sfgAutocompleteValues[field_string]; |
| 86 | + values = jQuery(this).data('autocompletevalues'); |
| 87 | + if ( !values ) { |
| 88 | + values = sfgAutocompleteValues[field_string]; |
| 89 | + } |
87 | 90 | if (values != null) { |
88 | 91 | // Local autocompletion |
89 | 92 | |
— | — | @@ -96,12 +99,17 @@ |
97 | 100 | return split(term).pop(); |
98 | 101 | } |
99 | 102 | |
| 103 | + var thisInput = jQuery(this); |
| 104 | + |
100 | 105 | jQuery(this).autocomplete({ |
101 | 106 | minLength: 0, |
102 | 107 | source: function(request, response) { |
103 | 108 | // We need to re-get the set of values, since |
104 | 109 | // the "values" variable gets overwritten. |
105 | | - values = sfgAutocompleteValues[field_string]; |
| 110 | + values = thisInput.data( 'autocompletevalues' ); |
| 111 | + if ( !values ) { |
| 112 | + values = sfgAutocompleteValues[field_string]; |
| 113 | + } |
106 | 114 | response(jQuery.ui.autocomplete.filter(values, extractLast(request.term))); |
107 | 115 | }, |
108 | 116 | focus: function() { |
— | — | @@ -681,8 +689,11 @@ |
682 | 690 | function() { |
683 | 691 | // Add in a 'b' at the end of the name to reduce the |
684 | 692 | // chance of name collision with another field |
685 | | - if (this.name) |
| 693 | + if (this.name) { |
| 694 | + var old_name = this.name.replace(/\[num\]/g, ''); |
| 695 | + jQuery(this).attr('origName', old_name); |
686 | 696 | this.name = this.name.replace(/\[num\]/g, '[' + num_elements + 'b]'); |
| 697 | + } |
687 | 698 | |
688 | 699 | if (this.id) { |
689 | 700 | |
— | — | @@ -767,7 +778,7 @@ |
768 | 779 | // that doesn't involve removing and then recreating divs. |
769 | 780 | new_div.find('.sfComboBoxActual').remove(); |
770 | 781 | |
771 | | - new_div.initializeJSElements(); |
| 782 | + new_div.initializeJSElements(true); |
772 | 783 | |
773 | 784 | // Initialize new inputs |
774 | 785 | new_div.find("input, select, textarea").each( |
— | — | @@ -792,12 +803,76 @@ |
793 | 804 | |
794 | 805 | } |
795 | 806 | |
| 807 | +// The first argument is needed, even though it's an attribute of the element |
| 808 | +// on which this function is called, because it's the 'name' attribute for |
| 809 | +// regular inputs, and the 'origName' attribute for inputs in multiple-instance |
| 810 | +// templates. |
| 811 | +jQuery.fn.setDependentAutocompletion = function( dependentField, baseField, baseValue ) { |
| 812 | + propName = sfgFieldProperties[dependentField]; |
| 813 | + baseProp = sfgFieldProperties[baseField]; |
| 814 | + var myServer = wgScriptPath + "/api.php"; |
| 815 | + myServer += "?action=sfautocomplete&format=json&property=" + propName + "&baseprop=" + baseProp + "&basevalue=" + baseValue; |
| 816 | + var dependentValues = []; |
| 817 | + var thisInput = jQuery(this); |
| 818 | + // We use jQuery.ajax() here instead of jQuery.getJSON() so that the |
| 819 | + // 'async' parameter can be set. That, in turn, is set because |
| 820 | + // if the 2nd, "dependent" field is a combo box, it can have weird |
| 821 | + // behavior: clicking on the down arrow for the combo box leads to a |
| 822 | + // "blur" event for the base field, which causes the possible |
| 823 | + // values to get recalculated, but not in time for the dropdown to |
| 824 | + // change values - it still shows the old values. By setting |
| 825 | + // "async: false", we guarantee that old values won't be shown - if |
| 826 | + // the values haven't been recalculated yet, the dropdown won't |
| 827 | + // appear at all. |
| 828 | + // @TODO - handle this the right way, by having special behavior for |
| 829 | + // the dropdown - it should get delayed until the values are |
| 830 | + // calculated, then appear. |
| 831 | + jQuery.ajax({ |
| 832 | + url: myServer, |
| 833 | + dataType: 'json', |
| 834 | + async: false, |
| 835 | + success: function(data) { |
| 836 | + realData = data.sfautocomplete; |
| 837 | + jQuery.each(realData, function(key, val) { |
| 838 | + dependentValues.push(val.title); |
| 839 | + }); |
| 840 | + thisInput.data('autocompletevalues', dependentValues); |
| 841 | + thisInput.attachAutocomplete(); |
| 842 | + } |
| 843 | + }); |
| 844 | +} |
| 845 | + |
796 | 846 | /** |
| 847 | + * Called on a 'base' field (e.g., for a country) - sets the autocompletion |
| 848 | + * for its 'dependent' field (e.g., for a city). |
| 849 | + */ |
| 850 | +jQuery.fn.setAutocompleteForDependentField = function( partOfMultiple ) { |
| 851 | + curValue = jQuery(this).val(); |
| 852 | + if ( curValue == null ) { return this; } |
| 853 | + |
| 854 | + nameAttr = partOfMultiple ? 'origName' : 'name'; |
| 855 | + name = jQuery(this).attr(nameAttr); |
| 856 | + dependentField = sfgDependentFields[name]; |
| 857 | + if ( dependentField != null ) { |
| 858 | + if ( partOfMultiple ) { |
| 859 | + jQuery(this).closest(".multipleTemplateInstance") |
| 860 | + .find('[origName="' + dependentField + '"]') |
| 861 | + .setDependentAutocompletion(dependentField, name, curValue); |
| 862 | + } else { |
| 863 | + jQuery('[name="' + dependentField + '"]') |
| 864 | + .setDependentAutocompletion(dependentField, name, curValue); |
| 865 | + } |
| 866 | + } |
| 867 | + |
| 868 | + return this; |
| 869 | +} |
| 870 | + |
| 871 | +/** |
797 | 872 | * Initialize all the JS-using elements contained within this block - can be |
798 | 873 | * called for either the entire HTML body, or for a div representing an |
799 | 874 | * instance of a multiple-instance template. |
800 | 875 | */ |
801 | | -jQuery.fn.initializeJSElements = function() { |
| 876 | +jQuery.fn.initializeJSElements = function( partOfMultiple ) { |
802 | 877 | this.find(".sfShowIfSelected").each( function() { |
803 | 878 | jQuery(this) |
804 | 879 | .showIfSelected(true) |
— | — | @@ -845,6 +920,20 @@ |
846 | 921 | 'overlayColor' : '#222', |
847 | 922 | 'overlayOpacity' : '0.8' |
848 | 923 | }); |
| 924 | + |
| 925 | + this.find('input, select') |
| 926 | + .setAutocompleteForDependentField( partOfMultiple ) |
| 927 | + .blur( function() { |
| 928 | + jQuery(this).setAutocompleteForDependentField( partOfMultiple ); |
| 929 | + }); |
| 930 | + // The 'blur' event doesn't get triggered for radio buttons for |
| 931 | + // Chrome and Safari (the WebKit-based browsers) so use the 'change' |
| 932 | + // event in addition. |
| 933 | + // @TODO - blur() shuldn't be called at all for radio buttons. |
| 934 | + this.find('input:radio') |
| 935 | + .change( function() { |
| 936 | + jQuery(this).setAutocompleteForDependentField( partOfMultiple ); |
| 937 | + }); |
849 | 938 | } |
850 | 939 | |
851 | 940 | var num_elements = 0; |
— | — | @@ -876,7 +965,7 @@ |
877 | 966 | var id = select[0].id; |
878 | 967 | var curval = select[0].options[0].value; |
879 | 968 | curval = curval.replace('"', '"' ); |
880 | | - var input = jQuery("<input id=\"" + id + "\" type=\"text\" name=\" " + name + " \" value=\"" + curval + "\">") |
| 969 | + var input = jQuery("<input id=\"" + id + "\" type=\"text\" name=\"" + name + "\" value=\"" + curval + "\">") |
881 | 970 | .insertAfter(select) |
882 | 971 | .attr("tabIndex", select.attr("tabIndex")) |
883 | 972 | .attr("autocompletesettings", select.attr("autocompletesettings")) |
— | — | @@ -917,6 +1006,7 @@ |
918 | 1007 | minLength: 0 |
919 | 1008 | }) |
920 | 1009 | .addClass("ui-widget ui-widget-content ui-corner-left sfComboBoxActual"); |
| 1010 | + input.attr("origname", select.attr("origname")); |
921 | 1011 | jQuery('<button type="button"> </button>') |
922 | 1012 | .attr("tabIndex", -1) |
923 | 1013 | .attr("title", "Show All Items") |