Feature #17436 » 0005899_v6.patch

Administrator Admin, 2007-07-14 15:59

View differences:

t3lib/class.t3lib_tceforms.php (Arbeitskopie)
283 283
	var $hiddenFieldListArr = array();			// This array of fields will be set as hidden-fields instead of rendered normally! For instance palette fields edited in the top frame are set as hidden fields since the main form has to submit the values. The top frame actually just sets the value in the main form!
284 284
	var $requiredFields=array();				// Used to register input-field names, which are required. (Done during rendering of the fields). This information is then used later when the JavaScript is made.
285 285
	var $requiredElements=array();				// Used to register the min and max number of elements for selectorboxes where that apply (in the "group" type for instance)
286
	var $requiredNested=array();				// Used to determine where $requiredFields or $requiredElements are nested (in Tabs or IRRE)
286 287
	var $renderDepth=0;							// Keeps track of the rendering depth of nested records.
287 288
	var $savedSchemes=array();					// Color scheme buffer.
288 289
	var $dynNestedStack = array();				// holds the path an element is nested in (e.g. required for RTEhtmlarea)
......
1064 1065
		}
1065 1066

  
1066 1067
		if (in_array('required',$evalList))	{
1067
			$this->requiredFields[$table.'_'.$row['uid'].'_'.$field]=$PA['itemFormElName'];
1068
			$this->registerRequiredProperty('field', $table.'_'.$row['uid'].'_'.$field, $PA['itemFormElName']);
1068 1069
		}
1069 1070

  
1070 1071
		$paramsList = "'".$PA['itemFormElName']."','".implode(',',$evalList)."','".trim($config['is_in'])."',".(isset($config['checkbox'])?1:0).",'".$config['checkbox']."'";
......
1798 1799
		$minitems = t3lib_div::intInRange($config['minitems'],0);
1799 1800

  
1800 1801
			// Register the required number of elements:
1801
		$this->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
1802
		$this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field));
1802 1803

  
1803 1804
			// Get "removeItems":
1804 1805
		$removeItems = t3lib_div::trimExplode(',',$PA['fieldTSConfig']['removeItems'],1);
......
1902 1903
		}
1903 1904

  
1904 1905
		$item.= '<input type="hidden" name="'.$PA['itemFormElName'].'_mul" value="'.($config['multiple']?1:0).'"'.$disabled.' />';
1905
		$this->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
1906
		$this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field));
1906 1907
		$info='';
1907 1908

  
1908 1909
			// "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. See http://typo3.org/documentation/document-library/doc_core_api/Wizards_Configuratio/.
......
4726 4727
			inline.addToDataArray('.$this->inline->getJSON($this->inline->inlineData).');
4727 4728
			';
4728 4729
		}
4730
			// Registered nested elements for tabs or inline levels:
4731
		if (count($this->requiredNested)) {
4732
			$out .= '
4733
			TBE_EDITOR.addNested('.$this->inline->getJSON($this->requiredNested).');
4734
			';
4735
		}
4729 4736
			// elements which are required or have a range definition:
4730 4737
		if (count($elements)) {
4731 4738
			$out .= '
......
4733 4740
			TBE_EDITOR.initRequired()
4734 4741
			';
4735 4742
		}
4736
			// $this->additionalJS_post:
4743
			// $this->additionalJS_submit:
4737 4744
		if ($this->additionalJS_submit) {
4738 4745
			$additionalJS_submit = implode('', $this->additionalJS_submit);
4739 4746
			$additionalJS_submit = str_replace("\r", '', $additionalJS_submit);
......
5489 5496
		}
5490 5497
		return ($json ? $this->inline->getJSON($result) : $result);
5491 5498
	}
5499

  
5500
	/**
5501
	 * Takes care of registering properties in requiredFields and requiredElements.
5502
	 * The current hierarchy of IRRE and/or Tabs is stored. Thus, it is possible to determine,
5503
	 * which required field/element was filled incorrectly and show it, even if the Tab or IRRE
5504
	 * level is hidden.
5505
	 *
5506
	 * @param	string		$type: Type of requirement ('field' or 'range')
5507
	 * @param	string		$name: The name of the form field
5508
	 * @param	mixed		$value: For type 'field' string, for type 'range' array
5509
	 * @return	void
5510
	 */
5511
	function registerRequiredProperty($type, $name, $value) {
5512
		if ($type == 'field' && is_string($value)) {
5513
			$this->requiredFields[$name] = $value;
5514
				// requiredFields have name/value swapped! For backward compatibility we keep this:
5515
			$itemName = $value;
5516
		} elseif ($type == 'range' && is_array($value)) {
5517
			$this->requiredElements[$name] = $value;
5518
			$itemName = $name;
5519
		}
5520
			// Set the situation of nesting for the current field:
5521
		$this->registerNestedElement($itemName);
5522
	}
5523

  
5524
	/**
5525
	 * Set the current situation of nested tabs and inline levels for a given element.
5526
	 *
5527
	 * @param	string		$itemName: The element the nesting should be stored for
5528
	 * @param	boolean		$setLevel: Set the reverse level lookup - default: true
5529
	 * @return	void
5530
	 */
5531
	function registerNestedElement($itemName, $setLevel=true) {
5532
		$dynNestedStack = $this->getDynNestedStack();
5533
		if (count($dynNestedStack) && preg_match('/^(.+\])\[(\w+)\]$/', $itemName, $match)) {
5534
			array_shift($match);
5535
			$this->requiredNested[$itemName] = array(
5536
				'parts' => $match,
5537
				'level' => $dynNestedStack,
5538
			);
5539
		}
5540
	}
5492 5541
}
5493 5542

  
5494 5543

  
t3lib/jsfunc.inline.js (Arbeitskopie)
511 511

  
512 512
			// Remove from TBE_EDITOR (required fields, required range, etc.):
513 513
		if (TBE_EDITOR && TBE_EDITOR.removeElement) {
514
			var removeStack = [];
514 515
			inlineRecords = document.getElementsByClassName('inlineRecord', objectId+'_div');
515 516
				// Remove nested child records from TBE_EDITOR required/range checks:
516 517
			for (i=inlineRecords.length-1; i>=0; i--) {
......
519 520
					childObjectId = this.data.map[inlineRecords[i].name];
520 521
					childTable = this.data.config[childObjectId].table;
521 522
					for (j=records.length-1; j>=0; j--) {
522
						TBE_EDITOR.removeElement(this.prependFormFieldNames+'['+childTable+']['+records[j]+']');
523
						removeStack.push(this.prependFormFieldNames+'['+childTable+']['+records[j]+']');
523 524
					}
524 525
				}
525 526
			}
526
			TBE_EDITOR.removeElement(this.prependFormFieldNames+shortName);
527
			removeStack.push(this.prependFormFieldNames+shortName);
528
			TBE_EDITOR.removeElementArray(removeStack);
527 529
		}
528 530

  
529 531
		var recordCount = this.memorizeRemoveRecord(
t3lib/class.t3lib_tceforms_inline.php (Arbeitskopie)
445 445
	 */
446 446
	function renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config = array()) {
447 447
			// Initialize:
448
		$cells=array();
448
		$cells = array();
449 449
		$isNewItem = substr($rec['uid'], 0, 3) == 'NEW';
450 450

  
451 451
		$tcaTableCtrl =& $GLOBALS['TCA'][$foreign_table]['ctrl'];
......
470 470
			// This expresses the edit permissions for this particular element:
471 471
		$permsEdit = ($isPagesTable && ($localCalcPerms&2)) || (!$isPagesTable && ($calcPerms&16));
472 472

  
473
			// Icon to visualize that a required field is nested in this inline level:
474
		$cells[] = '<img id="'.$nameObjectFtId.'_req" src="clear.gif" width="10" height="10" hspace="4" vspace="3" alt="" />';
475

  
473 476
			// "Info": (All records)
474 477
		if (!$isNewItem)
475 478
			$cells[]='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$foreign_table.'\', \''.$rec['uid'].'\'); return false;').'">'.
typo3/jsfunc.tbe_editor.js (Arbeitskopie)
44 44
					'requiredImg':	''
45 45
				}
46 46
			}
47
		
48 47
		},
49 48
	*/
50
	
49

  
51 50
	elements: {},
51
	nested: {'field':{}, 'level':{}},
52
	ignoreElements: [],
52 53
	recentUpdatedElements: {},
53 54
	actionChecks: { submit:	[] },
54
	
55

  
55 56
	formname: '',
56 57
	formnameUENC: '',
57 58
	loadTime: 0,
......
62 63
	prependFormFieldNames: 'data',
63 64
	prependFormFieldNamesUENC: 'data',
64 65
	prependFormFieldNamesCnt: 0,
65
	
66

  
66 67
	isPalettedoc: null,
67 68
	doSaveFieldName: 0,
68
	
69

  
69 70
	labels: {},
70 71
	images: {
71 72
		req: new Image(),
......
79 80
		TBE_EDITOR.recentUpdatedElements = elements;
80 81
		TBE_EDITOR.elements = $H(TBE_EDITOR.elements).merge(elements);
81 82
	},
83
	addNested: function(elements) {
84
		var name, nested, levelMax, i, currentLevel, subLevel;
85
		// Merge data structures:
86
		if (elements) {
87
			for (name in elements) {
88
				nested = elements[name];
89
				if (nested.level && nested.level.length) {
90
						// If the first level is of type 'inline', it could be created by a AJAX request to IRRE.
91
						// So, try to get the upper levels this dynamic level is nested in:
92
					if (nested.level[0][0]=='inline') {
93
						nested.level = inline.findContinuedNestedLevel(nested.level, nested.level[0][1]);
94
					}
95
					levelMax = nested.level.length-1;
96
					for (i=0; i<=levelMax; i++) {
97
						currentLevel = TBE_EDITOR.getNestedLevelIdent(nested.level[i]);
98
						if (typeof TBE_EDITOR.nested.level[currentLevel] == 'undefined') {
99
							TBE_EDITOR.nested.level[currentLevel] = { 'clean': true, 'item': {}, 'sub': {} };
100
						}
101
							// Add next sub level to the current level:
102
						if (i<levelMax) {
103
							subLevel = TBE_EDITOR.getNestedLevelIdent(nested.level[i+1]);
104
							TBE_EDITOR.nested.level[currentLevel].sub[subLevel] = true;
105
							// Add the current item to the last level in nesting:
106
						} else {
107
							TBE_EDITOR.nested.level[currentLevel].item[name] = nested.parts;
108
						}
109
					}
110
				}
111
			}
112
				// Merge the nested fields:
113
			TBE_EDITOR.nested.field = $H(TBE_EDITOR.nested.field).merge(elements);
114
		}
115
	},
82 116
	removeElement: function(record) {
83 117
		if (TBE_EDITOR.elements && TBE_EDITOR.elements[record]) {
118
			// Inform envolved levels the this record is removed and the missing requirements are resolved:
119
			$H(TBE_EDITOR.elements[record]).each(
120
				function(pair) {
121
					TBE_EDITOR.notifyNested(record+'['+pair.key+']', true);
122
				}
123
			);
84 124
			delete(TBE_EDITOR.elements[record]);
85 125
		}
86 126
	},
127
	removeElementArray: function(removeStack) {
128
		if (removeStack && removeStack.length) {
129
			TBE_EDITOR.ignoreElements = removeStack;
130
			for (var i=removeStack.length; i>=0; i--) {
131
				TBE_EDITOR.removeElement(removeStack[i]);
132
			}
133
			TBE_EDITOR.ignoreElements = [];
134
		}
135
	},
87 136
	getElement: function(record, field, type) {
88 137
		var result = null;
89 138
		var element;
90
		
139

  
91 140
		if (TBE_EDITOR.elements && TBE_EDITOR.elements[record] && TBE_EDITOR.elements[record][field]) {
92 141
			element = TBE_EDITOR.elements[record][field];
93 142
			if (type) {
......
96 145
				result = element;
97 146
			}
98 147
		}
99
		
148

  
100 149
		return result;
101 150
	},
102 151
	checkElements: function(type, recentUpdated, record, field) {
103 152
		var result = 1;
104 153
		var elementName, elementData, elementRecord, elementField;
105
		var source = recentUpdated ? TBE_EDITOR.recentUpdatedElements : TBE_EDITOR.elements;
154
		var source = (recentUpdated ? TBE_EDITOR.recentUpdatedElements : TBE_EDITOR.elements);
106 155

  
156
		if (TBE_EDITOR.ignoreElements.length && TBE_EDITOR.ignoreElements.indexOf(record)!=-1) {
157
			return result;
158
		}
159

  
107 160
		if (type) {
108 161
			if (record && field) {
109 162
				elementName = record+'['+field+']';
110 163
				elementData = TBE_EDITOR.getElement(record, field, type);
111 164
				if (elementData) {
112
					if (!TBE_EDITOR.checkElementByType(type, elementName, elementData)) result = 0;
165
					if (!TBE_EDITOR.checkElementByType(type, elementName, elementData, recentUpdated)) {
166
						result = 0;
167
					}
113 168
				}
114
				
169

  
115 170
			} else {
116 171
				var elementFieldList, elRecIndex, elRecCnt, elFldIndex, elFldCnt;
117 172
				var elementRecordList = $H(source).keys();
......
123 178
						elementData = TBE_EDITOR.getElement(elementRecord, elementField, type);
124 179
						if (elementData) {
125 180
							elementName = elementRecord+'['+elementField+']';
126
							if (!TBE_EDITOR.checkElementByType(type, elementName, elementData)) result = 0;
181
							if (!TBE_EDITOR.checkElementByType(type, elementName, elementData, recentUpdated)) {
182
								result = 0;
183
							}
127 184
						}
128 185
					}
129 186
				}
130 187
			}
131 188
		}
132
		
189

  
133 190
		return result;
134 191
	},
135
	checkElementByType: function(type, elementName, elementData) {
192
	checkElementByType: function(type, elementName, elementData, autoNotify) {
136 193
		var result = 1;
137
		
194

  
138 195
		if (type) {
139 196
			if (type == 'required') {
140 197
				if (!document[TBE_EDITOR.formname][elementName].value) {
141 198
					result = 0;
142
					TBE_EDITOR.setImage('req_'+elementData.requiredImg, TBE_EDITOR.images.req);
199
					if (autoNotify) {
200
						TBE_EDITOR.setImage('req_'+elementData.requiredImg, TBE_EDITOR.images.req);
201
						TBE_EDITOR.notifyNested(elementName, false);
202
					}
143 203
				}
144 204
			} else if (type == 'range' && elementData.range) {
145 205
				var formObj = document[TBE_EDITOR.formname][elementName+'_list'];
......
152 212
				}
153 213
				if (!TBE_EDITOR.checkRange(formObj, elementData.range[0], elementData.range[1])) {
154 214
					result = 0;
155
					TBE_EDITOR.setImage('req_'+elementData.rangeImg, TBE_EDITOR.images.req);
215
					if (autoNotify) {
216
						TBE_EDITOR.setImage('req_'+elementData.rangeImg, TBE_EDITOR.images.req);
217
						TBE_EDITOR.notifyNested(elementName, false);
218
					}
156 219
				}
157 220
			}
158 221
		}
159
		
222

  
160 223
		return result;
161 224
	},
225
	// Notify tabs and inline levels with nested requiredFields/requiredElements:
226
	notifyNested: function(elementName, resolved) {
227
		if (TBE_EDITOR.nested.field[elementName]) {
228
			var i, nested, element, fieldLevels, fieldLevelIdent, nestedLevelType, nestedLevelName;
229
			fieldLevels = TBE_EDITOR.nested.field[elementName].level;
230
			TBE_EDITOR.nestedCache = {};
231

  
232
			for (i=fieldLevels.length-1; i>=0; i--) {
233
				nestedLevelType = fieldLevels[i][0];
234
				nestedLevelName = fieldLevels[i][1];
235
				fieldLevelIdent = TBE_EDITOR.getNestedLevelIdent(fieldLevels[i]);
236
					// Construct the CSS id strings of the image/icon tags showing the notification:
237
				if (nestedLevelType == 'tab') {
238
					element = nestedLevelName+'-REQ';
239
				} else if (nestedLevelType == 'inline') {
240
					element = nestedLevelName+'_req';
241
				} else {
242
					continue;
243
				}
244
					// Set the icons:
245
				if (resolved) {
246
					if (TBE_EDITOR.checkNested(fieldLevelIdent)) {
247
						TBE_EDITOR.setImage(element, TBE_EDITOR.images.clear);
248
					} else {
249
						break;
250
					}
251
				} else {
252
					if (TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[fieldLevelIdent]) {
253
						TBE_EDITOR.nested.level[fieldLevelIdent].clean = false;
254
					}
255
					TBE_EDITOR.setImage(element, TBE_EDITOR.images.req);
256
				}
257
			}
258
		}
259
	},
260
	// Check all the input fields on a given level of nesting - if only on is unfilled, the whole level is marked as required:
261
	checkNested: function(nestedLevelIdent) {
262
		var nestedLevel, isClean;
263
		if (nestedLevelIdent && TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[nestedLevelIdent]) {
264
			nestedLevel = TBE_EDITOR.nested.level[nestedLevelIdent];
265
			if (!nestedLevel.clean) {
266
				if (typeof nestedLevel.item == 'object') {
267
					$H(nestedLevel.item).each(
268
						function(pair) {
269
							if (isClean || typeof isClean == 'undefined') {
270
								isClean = (
271
									TBE_EDITOR.checkElements('required', false, pair.value[0], pair.value[1]) &&
272
									TBE_EDITOR.checkElements('range', false, pair.value[0], pair.value[1])
273
								);
274
							}
275
						}
276
					);
277
					if (typeof isClean != 'undefined' && !isClean) {
278
						return false;
279
					}
280
				}
281
				if (typeof nestedLevel.sub == 'object') {
282
					$H(nestedLevel.sub).each(
283
						function(pair) {
284
							if (isClean || typeof isClean == 'undefined') {
285
								isClean = TBE_EDITOR.checkNested(pair.key);
286
							}
287
						}
288
					);
289
					if (typeof isClean != 'undefined' && !isClean) {
290
						return false;
291
					}
292
				}
293
					// Store the result, that this level (the fields on this and the sub levels) are clean:
294
				nestedLevel.clean = true;
295
			}
296
		}
297
		return true;
298
	},
299
	getNestedLevelIdent: function(level) {
300
		return level.join('::');
301
	},
162 302
	addActionChecks: function(type, checks) {
163 303
		TBE_EDITOR.actionChecks[type].push(checks);
164 304
	},
165
	
166 305
	// Regular TCEforms JSbottom scripts:
167 306
	loginRefreshed: function() {
168 307
		var date = new Date();
......
213 352
		if (TBE_EDITOR.getElement(theRecord,field,'required') && document[TBE_EDITOR.formname][theField])	{
214 353
			if (TBE_EDITOR.checkElements('required', false, theRecord, field)) {
215 354
				TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
355
				TBE_EDITOR.notifyNested(theField, true);
216 356
			} else {
217 357
				TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
358
				TBE_EDITOR.notifyNested(theField, false);
218 359
			}
219 360
		}
220 361
		if (TBE_EDITOR.getElement(theRecord,field,'range') && document[TBE_EDITOR.formname][theField]) {
221 362
			if (TBE_EDITOR.checkElements('range', false, theRecord, field))	{
222 363
				TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
364
				TBE_EDITOR.notifyNested(theField, true);
223 365
			} else {
224 366
				TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
367
				TBE_EDITOR.notifyNested(theField, false);
225 368
			}
226 369
		}
227
		
370

  
228 371
		if (TBE_EDITOR.isPalettedoc) { TBE_EDITOR.setOriginalFormFieldValue(theField) };
229 372
	},
230 373
	setOriginalFormFieldValue: function(theField) {
......
274 417
		if (!TBE_EDITOR.checkElements('required', false)) { OK = 0; }
275 418
		// $reqRangeCheck
276 419
		if (!TBE_EDITOR.checkElements('range', false)) { OK = 0; }
277
				
420

  
278 421
		if (OK || sendAlert==-1) {
279 422
			return true;
280 423
		} else {
......
297 440
		TBE_EDITOR.checkElements('range', true);
298 441
	},
299 442
	setImage: function(name,image) {
443
		var object;
300 444
		if (document[name]) {
445
			object = document[name];
446
		} else if (document.getElementById(name)) {
447
			object = document.getElementById(name);
448
		}
449
		if (object) {
301 450
			if (typeof image == 'object') {
302 451
				document[name].src = image.src;
303 452
			} else {
typo3/template.php (Arbeitskopie)
1707 1707
				$isActive = strcmp($def['content'],'');
1708 1708

  
1709 1709
				$mouseOverOut = ' onmouseover="DTM_mouseOver(this);" onmouseout="DTM_mouseOut(this);"';
1710
				$requiredIcon = '<img id="'.$id.'-'.$index.'-REQ" src="clear.gif" width="10" height="10" hspace="4" alt="" />';
1710 1711

  
1711 1712
				if (!$foldout)	{
1712 1713
						// Create TAB cell:
......
1715 1716
							($isActive ? '<a href="#" onclick="'.htmlspecialchars($onclick).'"'.($def['linkTitle'] ? ' title="'.htmlspecialchars($def['linkTitle']).'"':'').'>' : '').
1716 1717
							$def['icon'].
1717 1718
							($def['label'] ? htmlspecialchars($def['label']) : '&nbsp;').
1719
							$requiredIcon.
1718 1720
							$this->icons($def['stateIcon'],'margin-left: 10px;').
1719 1721
							($isActive ? '</a>' :'').
1720 1722
							'</td>';
......
1726 1728
							($isActive ? '<a href="#" onclick="'.htmlspecialchars($onclick).'"'.($def['linkTitle'] ? ' title="'.htmlspecialchars($def['linkTitle']).'"':'').'>' : '').
1727 1729
							$def['icon'].
1728 1730
							($def['label'] ? htmlspecialchars($def['label']) : '&nbsp;').
1731
							$requiredIcon.
1729 1732
							($isActive ? '</a>' : '').
1730 1733
							'</div>';
1731 1734
				}
(2-2/4)