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.stringValue) === 'string' ? 'stringValue'
300 			                                           : 'pageId'
301 		];
302 	}
303 	TagParts.PAGE = PAGE;
304 
305 	/**
306 	 * <p>
307 	 * Gets or sets the value of a SELECT tag part.
308 	 *
309 	 * <p>
310 	 * There are several possible values that can be passed to this function:
311 	 *
312 	 * <pre>
313 	 *      undefined : When value arguments is not provided, then none of this
314 	 *                  part's data is changed.
315 	 *
316 	 *           null : selectedOptions will set to an empty array.
317 	 *
318 	 *         object : selectedOptions will be set to contain a single select
319 	 *                  option that corresponds with that of the
320 	 *                  `selectedOptions' property in the given object.  This
321 	 *                  allowance exists for backwards compatibility, and is not
322 	 *                  recommended.
323 	 *
324 	 *         string : selectedOptions will be set to contain a single select
325 	 *                  option whose `value' property corresponds with that of
326 	 *                  the argument.
327 	 *
328 	 *       string[] : selectedOptions will be set to contain zero or more
329 	 *                  select option whose `value' property corresponds with
330 	 *                  that of those in the given array.
331 	 * </pre>
332 	 *
333 	 * @public
334 	 * @function
335 	 * @memberOf TagParts
336 	 * @name SELECT
337 	 * @param {object} part The part whose value is to be accessed.
338 	 * @param {(string|string[]|object|null)=} value The values with which to
339 	 *                                         determined what this part's
340 	 *                                         `selectedOptions' property should
341 	 *                                         hold.
342 	 * @return {object} An object containing a copy of the value of this part.
343 	 * @throws VALUE_DOES_NOT_EXIST
344 	 */
345 	function SELECT(part, value) {
346 		var options = [];
347 		var option;
348 		var i;
349 		switch (jQuery.type(value)) {
350 		case 'string':
351 			option = getSelectPartOption(value, part);
352 			if (option) {
353 				options.push(option);
354 			} else {
355 				return part;
356 			}
357 			break;
358 		case 'array':
359 			for (i = 0; i < value.length; i++) {
360 				option = getSelectPartOption(value[i], part);
361 				if (option) {
362 					options.push(option);
363 				} else {
364 					return part;
365 				}
366 			}
367 			break;
368 		case 'object':
369 			for (i = 0; i < value.selectedOptions.length; i++) {
370 				option = getSelectPartOption(value.selectedOptions[i].value,
371 				                             part);
372 				if (option) {
373 					options.push(option);
374 				} else {
375 					return part;
376 				}
377 			}
378 			break;
379 		case 'undefined':
380 			options = part.selectedOptions;
381 			break;
382 		}
383 
384 		part.selectedOptions = options;
385 
386 		return {
387 			datasourceId: part.datasourceId,
388 			options: part.options,
389 			selectedOptions: part.selectedOptions
390 		};
391 	}
392 	TagParts.SELECT = SELECT;
393 
394 	/**
395 	 * Gets or sets the value of a MULTISELECT tag part.
396 	 * Operates in the same was as {@link TagParts.SELECT}.
397 	 *
398 	 * @public
399 	 * @function
400 	 * @memberOf TagParts
401 	 * @name MULTISELECT
402 	 * @param {object} part The part whose value is to be accessed.
403 	 * @param {(string|string[]|object|null)=} value The values with which to
404 	 *                                         determined what this part's
405 	 *                                         `selectedOptions' property should
406 	 *                                         hold.
407 	 * @return {object} An object containing a copy of the value of this part.
408 	 */
409 	function MULTISELECT(part, value) {
410 		return TagParts.SELECT(part, value);
411 	}
412 	TagParts.MULTISELECT = MULTISELECT;
413 
414 	/**
415 	 * Gets or sets the value of a TEMPLATETAG tag part.
416 	 *
417 	 * @public
418 	 * @function
419 	 * @memberOf TagParts
420 	 * @name TEMPLATETAG
421 	 * @param {object} part The part whose value is to be accessed.
422 	 * @param {object=} value An object with the either the property `templateId'
423 	 *                        or `templateTagId'.
424 	 * @return {object} An object containing a copy of the value of this part.
425 	 *
426 	 */
427 	function TEMPLATETAG(part, value) {
428 		if (value) {
429 			if (typeof value.templateId !== 'undefined') {
430 				part.templateId = value.templateId;
431 			}
432 
433 			if (typeof value.templateTagId !== 'undefined') {
434 				part.templateTagId = value.templateTagId;
435 			}
436 		}
437 
438 		return {
439 			templateId: part.templateId,
440 			templateTagId: part.templateTagId
441 		};
442 	}
443 	TagParts.TEMPLATETAG = TEMPLATETAG;
444 
445 	/**
446 	 * Gets or sets the value of a PAGETAG tag part.
447 	 *
448 	 * @public
449 	 * @function
450 	 * @memberOf TagParts
451 	 * @name PAGETAG
452 	 * @param {object} part The part whose value is to be accessed.
453 	 * @param {object=} value An object with the the property `pageId'
454 	 *                        and/or one of `contentTagId' or `templateTagId'.
455 	 * @return {object} An object containing a copy of the value of this
456 	 *                  part.
457 	 */
458 	function PAGETAG(part, value) {
459 		if (value) {
460 			if (typeof value.pageId !== 'undefined') {
461 				part.pageId = value.pageId;
462 			}
463 
464 			var newContentTagIdValue;
465 			// support wrongly named 'pageTagId' property for backwards compatibility
466 			if (typeof value.pageTagId !== 'undefined') {
467 				newContentTagIdValue = value.pageTagId;
468 			} else if (typeof value.contentTagId !== 'undefined') {
469 				newContentTagIdValue = value.contentTagId;
470 			}
471 
472 			// either a contenttag OR a templatetag must be specified
473 			if (typeof newContentTagIdValue !== 'undefined') {
474 				part.contentTagId = newContentTagIdValue;
475 				delete part.templateTagId;
476 			} else if (typeof value.templateTagId !== 'undefined') {
477 				part.templateTagId = value.templateTagId;
478 				delete part.contentTagId;
479 			}
480 		}
481 
482 		var result = { pageId: part.pageId };
483 
484 		if (typeof part.contentTagId !== 'undefined') {
485 			result.contentTagId = part.contentTagId;
486 		} else if (typeof part.templateTagId !== 'undefined') {
487 			result.templateTagId = part.templateTagId;
488 		}
489 
490 		return result;
491 	}
492 	TagParts.PAGETAG = PAGETAG;
493 
494 	/**
495 	 * Gets or sets the value of a LIST tag part.
496 	 * 
497 	 * @public
498 	 * @function
499 	 * @memberOf TagParts
500 	 * @name LIST
501 	 * @param {object} part The part whose value is to be accessed.
502 	 * @param {(string|string[]|object|boolean|null)=} value A string or string[] to set the listed values,
503 	 *                                                 or a boolean to set the 'ordered' flag or an object with the properties
504 	 *                                                 'booleanValue' and/or 'stringValues'
505 	 * @return {object} An object containing a copy of the value of this part.
506 	 */
507 	function LIST(part, value) {
508 		switch (jQuery.type(value)) {
509 		case 'array':
510 			part.stringValues = value;
511 			break;
512 		case 'string':
513 			part.stringValues = [value];
514 			break;
515 		case 'object':
516 			if (typeof value.stringValues !== 'undefined') {
517 				part.stringValues = value.stringValues;
518 			}
519 			if (typeof value.booleanValue !== 'undefined') {
520 				part.booleanValue = value.booleanValue;
521 			}
522 			break;
523 		case 'boolean':
524 			part.booleanValue = value;
525 			break;
526 		}
527 
528 		var result = {
529 			booleanValue: part.booleanValue,
530 			stringValues: part.stringValues
531 		};
532 		return result;
533 	}
534 	TagParts.LIST = LIST;
535 
536 	/**
537 	 * Gets or sets the value of a ORDEREDLIST tag part.
538 	 * 
539 	 * @public
540 	 * @function
541 	 * @memberOf TagParts
542 	 * @name ORDEREDLIST
543 	 * @param {object} part The part whose value is to be accessed.
544 	 * @param {object=} value A string or string[] to set the listed values
545 	 *                        or an object with the property 'stringValues'
546 	 * @return {object} An object containing a copy of the value of this part.
547 	 */
548 	function ORDEREDLIST(part, value) {
549 		switch (jQuery.type(value)) {
550 		case 'array':
551 			part.stringValues = value;
552 			break;
553 		case 'string':
554 			part.stringValues = [value];
555 			break;
556 		case 'object':
557 			if (typeof value.stringValues !== 'undefined') {
558 				part.stringValues = value.stringValues;
559 			}
560 			break;
561 		}
562 
563 		var result = { stringValues: part.stringValues };
564 		return result;
565 	}
566 	TagParts.ORDEREDLIST = ORDEREDLIST;
567 
568 	/**
569 	 * Gets or sets the value of a UNORDEREDLIST tag part.
570 	 * 
571 	 * @public
572 	 * @function
573 	 * @memberOf TagParts
574 	 * @name UNORDEREDLIST
575 	 * @param {object} part The part whose value is to be accessed.
576 	 * @param {object=} value A string or string[] to set the listed values
577 	 *                        or an object with the property 'stringValues'
578 	 * @return {object} An object containing a copy of the value of this part.
579 	 */
580 	function UNORDEREDLIST(part, value) {
581 		return TagParts.ORDEREDLIST(part, value);
582 	}
583 	TagParts.UNORDEREDLIST = UNORDEREDLIST;
584 
585 	/**
586 	 * Gets or sets the value of a DATASOURCE tag part.
587 	 * 
588 	 * @public
589 	 * @function
590 	 * @memberOf TagParts
591 	 * @name DATASOURCE
592 	 * @param {object} part The part whose value is to be accessed.
593 	 * @param {object=} value An object containing the property 'options'
594 	 * @return {object} An object containing a copy of the value of this part.
595 	 */
596 	function DATASOURCE(part, value) {
597 		if (jQuery.type(value) === 'object') {
598 			part.options = value.options;
599 		}
600 
601 		return { options: part.options };
602 	}
603 	TagParts.DATASOURCE = DATASOURCE;
604 
605 	/**
606 	 * Gets or sets the value of the given tag part.
607 	 *
608 	 * @private
609 	 * @ignore
610 	 * @param {object} part The part whose value is to be accessed.
611 	 * @param {*=} value The value to set the part to.
612 	 * @throws CANNOT_READ_TAG_PART
613 	 */
614 	function accessor() {
615 		var args = Array.prototype.slice.call(arguments);
616 		var part = args[0];
617 		if (!TagParts[part.type]) {
618 			GCN.error(
619 				'CANNOT_READ_TAG_PART',
620 				'Cannot read or write to tag part',
621 				part
622 			);
623 			return null;
624 		}
625 		return (
626 			args.length > 1
627 				? TagParts[part.type](part, args[1])
628 				: TagParts[part.type](part)
629 		);
630 	}
631 
632 	/**
633 	 * Gets the value of the given tag part.
634 	 *
635 	 * @param {object} part The part whose value is to be retrieved.
636 	 * @param {*=} value The value to set the part to.
637 	 * @return {*} The value held in the given part.
638 	 * @throws CANNOT_READ_TAG_PART
639 	 */
640 	TagParts.get = function (part) {
641 		return accessor(part);
642 	};
643 
644 	/**
645 	 * Sets the value of the given tag part.
646 	 *
647 	 * @param {object} part The part whose value is to be set.
648 	 * @param {*=} value The value to set the part to.
649 	 * @return {*} The value set to the given part.
650 	 * @throws CANNOT_READ_TAG_PART
651 	 */
652 	TagParts.set = function (part, value) {
653 		return accessor(part, value);
654 	};
655 
656 	GCN.TagParts = TagParts;
657 
658 }(GCN));
659