1 /*global window: true, GCN: true, jQuery: true */
  2 
  3 /**
  4  * IMPORTANT NOTE CONCERNING JSDOC-TOOLKIT WORKAROUNDS:
  5  *
  6  * It is necessary to define a local function and then write extra code to
  7  * expose it in the TagParts object rather than just doing it directy. Thi is
  8  * because of a bug in JsDoc-Toolkit prevents the function documentation from
  9  * being parsed correctly otherwise.
 10  *
 11  * function MULTISELECT(part, value) {
 12  *     return TagParts.SELECT(part, value);
 13  * }
 14  * TagParts.MULTISELECT = MULTISELECT;
 15  */
 16 
 17 (function (GCN) {
 18 	'use strict';
 19 
 20 	/**
 21 	 * Retrieves a copy of the properties of the select options which
 22 	 * corresponds to the given value.
 23 	 *
 24 	 * @ignore
 25 	 * @private
 26 	 * @param {string} value Search for property of this value
 27 	 * @param {object} part The part inwhich to search for select options.
 28 	 * @return {object|null} A copy of properties or null if none is found for
 29 	 *                       `value'.
 30 	 * @throws VALUE_DOES_NOT_EXIST
 31 	 */
 32 	function getSelectPartOption(value, part) {
 33 		var options = part.options;
 34 		var i;
 35 		for (i = 0; i < options.length; i++) {
 36 			if (options[i].value === value) {
 37 				return jQuery.extend({}, options[i]);
 38 			}
 39 		}
 40 		GCN.error(
 41 			'VALUE_DOES_NOT_EXIST',
 42 			'The value `' + value + '\' does not exist in this part',
 43 			part
 44 		);
 45 		return null;
 46 	}
 47 
 48 	/**
 49 	 * Creates a basic getter/setter function for the given field.
 50 	 *
 51 	 * @private
 52 	 * @ignore
 53 	 * @param {string} field;
 54 	 * @return {function(object, *=)} A getter/setter function.
 55 	 */
 56 	function createGetterSetter(field) {
 57 		return function () {
 58 			var args = Array.prototype.slice.call(arguments);
 59 			var obj = args[0];
 60 			if (args.length > 1) {
 61 				obj[field] = args[1];
 62 			}
 63 			return obj[field];
 64 		};
 65 	}
 66 
 67 	/**
 68 	 * <p>
 69 	 * Functions to access and modify various tag part types.
 70 	 *
 71 	 * <p>
 72 	 * <b>IMPORTANT</b>: Getter and setters for the various part types should
 73 	 * never be accessed directly.  If absolutely necessary it should be done
 74 	 * via {@link TagParts.get} and {@link TagParts.set}.
 75 	 *
 76 	 * @public
 77 	 * @namespace
 78 	 * @name TagParts
 79 	 * @type {object<string, function(object, (number|string|boolean|object)=)>}
 80 	 */
 81 	var TagParts = {};
 82 
 83 	/**
 84 	 * Gets or sets the value of a STRING tag part.
 85 	 *
 86 	 * @public
 87 	 * @function
 88 	 * @memberOf TagParts
 89 	 * @name STRING
 90 	 * @param {object} part The part whose value is to be accessed.
 91 	 * @param {string=} value Optional. The value to set for this part.
 92 	 * @return {string} The value held by this part.
 93 	 */
 94 	TagParts.STRING = createGetterSetter('stringValue');
 95 
 96 	/**
 97 	 * Gets or sets the value of a RICHTEXT tag part.
 98 	 *
 99 	 * @public
100 	 * @function
101 	 * @memberOf TagParts
102 	 * @name RICHTEXT
103 	 * @param {object} part The part whose value is to be accessed.
104 	 * @param {string=} value Optional. The value to set for this part.
105 	 * @return {string} The value held by this part.
106 	 */
107 	TagParts.RICHTEXT = createGetterSetter('stringValue');
108 
109 	/**
110 	 * Gets or sets the value of a BOOLEAN tag part.
111 	 *
112 	 * @public
113 	 * @function
114 	 * @memberOf TagParts
115 	 * @name BOOLEAN
116 	 * @param {object} part The part whose value is to be accessed.
117 	 * @param {boolean=} value Optional. The value to set for this part.
118 	 * @return {boolean} The value held by this part.
119 	 */
120 	TagParts.BOOLEAN = createGetterSetter('booleanValue');
121 
122 	/**
123 	 * Gets or sets the value of an IMAGE tag part.
124 	 *
125 	 * @public
126 	 * @function
127 	 * @memberOf TagParts
128 	 * @name IMAGE
129 	 * @param {object} part The part whose value is to be accessed.
130 	 * @param {number=} value Optional. The value to set for this part.
131 	 * @return {number} The value held by this part.
132 	 */
133 	TagParts.IMAGE = function (part, value) {
134 		if (jQuery.type(value) === 'object') {
135 			if (value.imageId) {
136 				part.imageId = value.imageId;
137 			} else {
138 				delete part.imageId;
139 			}
140 			if (value.nodeId) {
141 				part.nodeId = value.nodeId;
142 			} else {
143 				delete part.nodeId;
144 			}
145 			return value;
146 		}
147 
148 		if (typeof value !== 'undefined' && value !== null) {
149 			part.imageId = value;
150 			delete part.nodeId;
151 			return value;
152 		}
153 
154 		return part.imageId;
155 	};
156 
157 	/**
158 	 * Gets or sets the value of a FILE tag part.
159 	 *
160 	 * @public
161 	 * @function
162 	 * @memberOf TagParts
163 	 * @name FILE
164 	 * @param {object} part The part whose value is to be accessed.
165 	 * @param {number=} value Optional. The value to set for this part.
166 	 * @return {number} The value held by this part.
167 	 */
168 	// (URL) file is the same as File (upload).
169 	TagParts.FILE = function (part, value) {
170 		if (jQuery.type(value) === 'object') {
171 			if (value.fileId) {
172 				part.fileId = value.fileId;
173 			} else {
174 				delete part.fileId;
175 			}
176 			if (value.nodeId) {
177 				part.nodeId = value.nodeId;
178 			} else {
179 				delete part.nodeId;
180 			}
181 			return value;
182 		}
183 
184 		if (typeof value !== 'undefined' && value !== null) {
185 			part.fileId = value;
186 			delete part.nodeId;
187 			return value;
188 		}
189 
190 		return part.fileId;
191 	};
192 
193 	/**
194 	 * Gets or sets the value of a FOLDER tag part.
195 	 *
196 	 * @public
197 	 * @function
198 	 * @memberOf TagParts
199 	 * @name FOLDER
200 	 * @param {object} part The part whose value is to be accessed.
201 	 * @param {number=} value Optional. The value to set for this part.
202 	 * @return {number} The value held by this part.
203 	 */
204 	// (URL) folder is the same as Folder (upload).
205 	TagParts.FOLDER = function (part, value) {
206 		if (jQuery.type(value) === 'object') {
207 			if (value.folderId) {
208 				part.folderId = value.folderId;
209 			} else {
210 				delete part.folderId;
211 			}
212 			if (value.nodeId) {
213 				part.nodeId = value.nodeId;
214 			} else {
215 				delete part.nodeId;
216 			}
217 			return value;
218 		}
219 
220 		if (typeof value !== 'undefined' && value !== null) {
221 			part.folderId = value;
222 			delete part.nodeId;
223 			return value;
224 		}
225 
226 		return part.folderId;
227 	};
228 
229 	/**
230 	 * Gets or sets the value of a NODE tag part.
231 	 * 
232 	 * @public
233 	 * @function
234 	 * @memberOf TagParts
235 	 * @name NODE
236 	 * @param {object} part The part whose value is to be accessed.
237 	 * @param {number=} value Optional. The value to set for this part.
238 	 * @return {number} The value held by this part.
239 	 */
240 	TagParts.NODE = createGetterSetter('nodeId');
241 
242 	/**
243 	 * Gets or sets the value of an OVERVIEW tag part.
244 	 *
245 	 * @public
246 	 * @function
247 	 * @memberOf TagParts
248 	 * @name OVERVIEW
249 	 * @param {object} part The part whose value is to be accessed.
250 	 * @param {object=} value Optional. The value to set for this part.
251 	 * @return {object} The value held by this part.
252 	 */
253 	TagParts.OVERVIEW = createGetterSetter('overview');
254 
255 	/**
256 	 * Gets or sets the value of a PAGE tag part.
257 	 *
258 	 * @public
259 	 * @function
260 	 * @memberOf TagParts
261 	 * @name PAGE
262 	 * @param {object} part The part whose value is to be accessed.
263 	 * @param {(number|string)=} value Optional.  A number denotes and internal
264 	 *                                 page within Content.Node, whereas a
265 	 *                                 string denotes an external url.
266 	 * @return {number|string} The value held by this part.
267 	 */
268 	function PAGE(part, value) {
269 		if (jQuery.type(value) === 'number') {
270 			part.pageId = value;
271 			delete part.stringValue;
272 			delete part.nodeId;
273 			return value;
274 		}
275 
276 		if (jQuery.type(value) === 'string') {
277 			part.stringValue = value;
278 			delete part.pageId;
279 			delete part.nodeId;
280 			return value;
281 		}
282 
283 		if (jQuery.type(value) === 'object') {
284 			if (value.pageId) {
285 				part.pageId = value.pageId;
286 			} else {
287 				delete part.pageId;
288 			}
289 			if (value.nodeId) {
290 				part.nodeId = value.nodeId;
291 			} else {
292 				delete part.nodeId;
293 			}
294 			delete part.stringValue;
295 			return value;
296 		}
297 
298 		return part[
299 			jQuery.type(part.pageId) === 'number' && part.pageId !== 0 ? 'pageId' : 'stringValue'
300 		];
301 	}
302 	TagParts.PAGE = PAGE;
303 
304 	/**
305 	 * <p>
306 	 * Gets or sets the value of a SELECT tag part.
307 	 *
308 	 * <p>
309 	 * There are several possible values that can be passed to this function:
310 	 *
311 	 * <pre>
312 	 *      undefined : When value arguments is not provided, then none of this
313 	 *                  part's data is changed.
314 	 *
315 	 *           null : selectedOptions will set to an empty array.
316 	 *
317 	 *         object : selectedOptions will be set to contain a single select
318 	 *                  option that corresponds with that of the
319 	 *                  `selectedOptions' property in the given object.  This
320 	 *                  allowance exists for backwards compatibility, and is not
321 	 *                  recommended.
322 	 *
323 	 *         string : selectedOptions will be set to contain a single select
324 	 *                  option whose `value' property corresponds with that of
325 	 *                  the argument.
326 	 *
327 	 *       string[] : selectedOptions will be set to contain zero or more
328 	 *                  select option whose `value' property corresponds with
329 	 *                  that of those in the given array.
330 	 * </pre>
331 	 *
332 	 * @public
333 	 * @function
334 	 * @memberOf TagParts
335 	 * @name SELECT
336 	 * @param {object} part The part whose value is to be accessed.
337 	 * @param {(string|string[]|object|null)=} value The values with which to
338 	 *                                         determined what this part's
339 	 *                                         `selectedOptions' property should
340 	 *                                         hold.
341 	 * @return {object} An object containing a copy of the value of this part.
342 	 * @throws VALUE_DOES_NOT_EXIST
343 	 */
344 	function SELECT(part, value) {
345 		var options = [];
346 		var option;
347 		var i;
348 		switch (jQuery.type(value)) {
349 		case 'string':
350 			option = getSelectPartOption(value, part);
351 			if (option) {
352 				options.push(option);
353 			} else {
354 				return part;
355 			}
356 			break;
357 		case 'array':
358 			for (i = 0; i < value.length; i++) {
359 				option = getSelectPartOption(value[i], part);
360 				if (option) {
361 					options.push(option);
362 				} else {
363 					return part;
364 				}
365 			}
366 			break;
367 		case 'object':
368 			for (i = 0; i < value.selectedOptions.length; i++) {
369 				option = getSelectPartOption(value.selectedOptions[i].value,
370 				                             part);
371 				if (option) {
372 					options.push(option);
373 				} else {
374 					return part;
375 				}
376 			}
377 			break;
378 		case 'undefined':
379 			options = part.selectedOptions;
380 			break;
381 		}
382 
383 		part.selectedOptions = options;
384 
385 		return {
386 			datasourceId: part.datasourceId,
387 			options: part.options,
388 			selectedOptions: part.selectedOptions
389 		};
390 	}
391 	TagParts.SELECT = SELECT;
392 
393 	/**
394 	 * Gets or sets the value of a MULTISELECT tag part.
395 	 * Operates in the same was as {@link TagParts.SELECT}.
396 	 *
397 	 * @public
398 	 * @function
399 	 * @memberOf TagParts
400 	 * @name MULTISELECT
401 	 * @param {object} part The part whose value is to be accessed.
402 	 * @param {(string|string[]|object|null)=} value The values with which to
403 	 *                                         determined what this part's
404 	 *                                         `selectedOptions' property should
405 	 *                                         hold.
406 	 * @return {object} An object containing a copy of the value of this part.
407 	 */
408 	function MULTISELECT(part, value) {
409 		return TagParts.SELECT(part, value);
410 	}
411 	TagParts.MULTISELECT = MULTISELECT;
412 
413 	/**
414 	 * Gets or sets the value of a TEMPLATETAG tag part.
415 	 *
416 	 * @public
417 	 * @function
418 	 * @memberOf TagParts
419 	 * @name TEMPLATETAG
420 	 * @param {object} part The part whose value is to be accessed.
421 	 * @param {object=} value An object with the either the property `templateId'
422 	 *                        or `templateTagId'.
423 	 * @return {object} An object containing a copy of the value of this part.
424 	 *
425 	 */
426 	function TEMPLATETAG(part, value) {
427 		if (value) {
428 			if (typeof value.templateId !== 'undefined') {
429 				part.templateId = value.templateId;
430 			}
431 
432 			if (typeof value.templateTagId !== 'undefined') {
433 				part.templateTagId = value.templateTagId;
434 			}
435 		}
436 
437 		return {
438 			templateId: part.templateId,
439 			templateTagId: part.templateTagId
440 		};
441 	}
442 	TagParts.TEMPLATETAG = TEMPLATETAG;
443 
444 	/**
445 	 * Gets or sets the value of a PAGETAG tag part.
446 	 *
447 	 * @public
448 	 * @function
449 	 * @memberOf TagParts
450 	 * @name PAGETAG
451 	 * @param {object} part The part whose value is to be accessed.
452 	 * @param {object=} value An object with the the property `pageId'
453 	 *                        and/or one of `contentTagId' or `templateTagId'.
454 	 * @return {object} An object containing a copy of the value of this
455 	 *                  part.
456 	 */
457 	function PAGETAG(part, value) {
458 		if (value) {
459 			if (typeof value.pageId !== 'undefined') {
460 				part.pageId = value.pageId;
461 			}
462 
463 			var newContentTagIdValue;
464 			// support wrongly named 'pageTagId' property for backwards compatibility
465 			if (typeof value.pageTagId !== 'undefined') {
466 				newContentTagIdValue = value.pageTagId;
467 			} else if (typeof value.contentTagId !== 'undefined') {
468 				newContentTagIdValue = value.contentTagId;
469 			}
470 
471 			// either a contenttag OR a templatetag must be specified
472 			if (typeof newContentTagIdValue !== 'undefined') {
473 				part.contentTagId = newContentTagIdValue;
474 				delete part.templateTagId;
475 			} else if (typeof value.templateTagId !== 'undefined') {
476 				part.templateTagId = value.templateTagId;
477 				delete part.contentTagId;
478 			}
479 		}
480 
481 		var result = { pageId: part.pageId };
482 
483 		if (typeof part.contentTagId !== 'undefined') {
484 			result.contentTagId = part.contentTagId;
485 		} else if (typeof part.templateTagId !== 'undefined') {
486 			result.templateTagId = part.templateTagId;
487 		}
488 
489 		return result;
490 	}
491 	TagParts.PAGETAG = PAGETAG;
492 
493 	/**
494 	 * Gets or sets the value of a LIST tag part.
495 	 * 
496 	 * @public
497 	 * @function
498 	 * @memberOf TagParts
499 	 * @name LIST
500 	 * @param {object} part The part whose value is to be accessed.
501 	 * @param {(string|string[]|object|boolean|null)=} value A string or string[] to set the listed values,
502 	 *                                                 or a boolean to set the 'ordered' flag or an object with the properties
503 	 *                                                 'booleanValue' and/or 'stringValues'
504 	 * @return {object} An object containing a copy of the value of this part.
505 	 */
506 	function LIST(part, value) {
507 		switch (jQuery.type(value)) {
508 		case 'array':
509 			part.stringValues = value;
510 			break;
511 		case 'string':
512 			part.stringValues = [value];
513 			break;
514 		case 'object':
515 			if (typeof value.stringValues !== 'undefined') {
516 				part.stringValues = value.stringValues;
517 			}
518 			if (typeof value.booleanValue !== 'undefined') {
519 				part.booleanValue = value.booleanValue;
520 			}
521 			break;
522 		case 'boolean':
523 			part.booleanValue = value;
524 			break;
525 		}
526 
527 		var result = {
528 			booleanValue: part.booleanValue,
529 			stringValues: part.stringValues
530 		};
531 		return result;
532 	}
533 	TagParts.LIST = LIST;
534 
535 	/**
536 	 * Gets or sets the value of a ORDEREDLIST tag part.
537 	 * 
538 	 * @public
539 	 * @function
540 	 * @memberOf TagParts
541 	 * @name ORDEREDLIST
542 	 * @param {object} part The part whose value is to be accessed.
543 	 * @param {object=} value A string or string[] to set the listed values
544 	 *                        or an object with the property 'stringValues'
545 	 * @return {object} An object containing a copy of the value of this part.
546 	 */
547 	function ORDEREDLIST(part, value) {
548 		switch (jQuery.type(value)) {
549 		case 'array':
550 			part.stringValues = value;
551 			break;
552 		case 'string':
553 			part.stringValues = [value];
554 			break;
555 		case 'object':
556 			if (typeof value.stringValues !== 'undefined') {
557 				part.stringValues = value.stringValues;
558 			}
559 			break;
560 		}
561 
562 		var result = { stringValues: part.stringValues };
563 		return result;
564 	}
565 	TagParts.ORDEREDLIST = ORDEREDLIST;
566 
567 	/**
568 	 * Gets or sets the value of a UNORDEREDLIST tag part.
569 	 * 
570 	 * @public
571 	 * @function
572 	 * @memberOf TagParts
573 	 * @name UNORDEREDLIST
574 	 * @param {object} part The part whose value is to be accessed.
575 	 * @param {object=} value A string or string[] to set the listed values
576 	 *                        or an object with the property 'stringValues'
577 	 * @return {object} An object containing a copy of the value of this part.
578 	 */
579 	function UNORDEREDLIST(part, value) {
580 		return TagParts.ORDEREDLIST(part, value);
581 	}
582 	TagParts.UNORDEREDLIST = UNORDEREDLIST;
583 
584 	/**
585 	 * Gets or sets the value of a DATASOURCE tag part.
586 	 * 
587 	 * @public
588 	 * @function
589 	 * @memberOf TagParts
590 	 * @name DATASOURCE
591 	 * @param {object} part The part whose value is to be accessed.
592 	 * @param {object=} value An object containing the property 'options'
593 	 * @return {object} An object containing a copy of the value of this part.
594 	 */
595 	function DATASOURCE(part, value) {
596 		if (jQuery.type(value) === 'object') {
597 			part.options = value.options;
598 		}
599 
600 		return { options: part.options };
601 	}
602 	TagParts.DATASOURCE = DATASOURCE;
603 
604 	/**
605 	 * Gets or sets the value of a FORM tag part.
606 	 *
607 	 * @public
608 	 * @function
609 	 * @memberOf TagParts
610 	 * @name FORM
611 	 * @param {object} part The part whose value is to be accessed.
612 	 * @param {string=} value Optional. The value to set for this part.
613 	 * @return {string} The value held by this part.
614 	 */
615 	TagParts.FORM = createGetterSetter('stringValue');
616 
617 	/**
618 	 * Gets or sets the value of a CMSFORM tag part.
619 	 *
620 	 * @public
621 	 * @function
622 	 * @memberOf TagParts
623 	 * @name CMSFORM
624 	 * @param {object} part The part whose value is to be accessed.
625 	 * @param {number=} value Optional. The value to set for this part.
626 	 * @return {number} The value held by this part.
627 	 */
628 	TagParts.CMSFORM = createGetterSetter('formId');
629 
630 	/**
631 	 * Gets or sets the value of the given tag part.
632 	 *
633 	 * @private
634 	 * @ignore
635 	 * @param {object} part The part whose value is to be accessed.
636 	 * @param {*=} value The value to set the part to.
637 	 * @throws CANNOT_READ_TAG_PART
638 	 */
639 	function accessor() {
640 		var args = Array.prototype.slice.call(arguments);
641 		var part = args[0];
642 		if (!TagParts[part.type]) {
643 			GCN.error(
644 				'CANNOT_READ_TAG_PART',
645 				'Cannot read or write to tag part',
646 				part
647 			);
648 			return null;
649 		}
650 		return (
651 			args.length > 1
652 				? TagParts[part.type](part, args[1])
653 				: TagParts[part.type](part)
654 		);
655 	}
656 
657 	/**
658 	 * Gets the value of the given tag part.
659 	 *
660 	 * @param {object} part The part whose value is to be retrieved.
661 	 * @param {*=} value The value to set the part to.
662 	 * @return {*} The value held in the given part.
663 	 * @throws CANNOT_READ_TAG_PART
664 	 */
665 	TagParts.get = function (part) {
666 		return accessor(part);
667 	};
668 
669 	/**
670 	 * Sets the value of the given tag part.
671 	 *
672 	 * @param {object} part The part whose value is to be set.
673 	 * @param {*=} value The value to set the part to.
674 	 * @return {*} The value set to the given part.
675 	 * @throws CANNOT_READ_TAG_PART
676 	 */
677 	TagParts.set = function (part, value) {
678 		return accessor(part, value);
679 	};
680 
681 	GCN.TagParts = TagParts;
682 
683 }(GCN));
684