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 = createGetterSetter('imageId');
134 
135 	/**
136 	 * Gets or sets the value of a FILE tag part.
137 	 *
138 	 * @public
139 	 * @function
140 	 * @memberOf TagParts
141 	 * @name FILE
142 	 * @param {object} part The part whose value is to be accessed.
143 	 * @param {number=} value Optional. The value to set for this part.
144 	 * @return {number} The value held by this part.
145 	 */
146 	// (URL) file is the same as File (upload).
147 	TagParts.FILE = createGetterSetter('fileId');
148 
149 	/**
150 	 * Gets or sets the value of a FOLDER tag part.
151 	 *
152 	 * @public
153 	 * @function
154 	 * @memberOf TagParts
155 	 * @name FOLDER
156 	 * @param {object} part The part whose value is to be accessed.
157 	 * @param {number=} value Optional. The value to set for this part.
158 	 * @return {number} The value held by this part.
159 	 */
160 	// (URL) folder is the same as Folder (upload).
161 	TagParts.FOLDER = createGetterSetter('folderId');
162 
163 	/**
164 	 * Gets or sets the value of a NODE tag part.
165 	 * 
166 	 * @public
167 	 * @function
168 	 * @memberOf TagParts
169 	 * @name NODE
170 	 * @param {object} part The part whose value is to be accessed.
171 	 * @param {number=} value Optional. The value to set for this part.
172 	 * @return {number} The value held by this part.
173 	 */
174 	TagParts.NODE = createGetterSetter('nodeId');
175 
176 	/**
177 	 * Gets or sets the value of an OVERVIEW tag part.
178 	 *
179 	 * @public
180 	 * @function
181 	 * @memberOf TagParts
182 	 * @name OVERVIEW
183 	 * @param {object} part The part whose value is to be accessed.
184 	 * @param {object=} value Optional. The value to set for this part.
185 	 * @return {object} The value held by this part.
186 	 */
187 	TagParts.OVERVIEW = createGetterSetter('overview');
188 
189 	/**
190 	 * Gets or sets the value of a PAGE tag part.
191 	 *
192 	 * @public
193 	 * @function
194 	 * @memberOf TagParts
195 	 * @name PAGE
196 	 * @param {object} part The part whose value is to be accessed.
197 	 * @param {(number|string)=} value Optional.  A number denotes and internal
198 	 *                                 page within Content.Node, whereas a
199 	 *                                 string denotes an external url.
200 	 * @return {number|string} The value held by this part.
201 	 */
202 	function PAGE(part, value) {
203 		if (jQuery.type(value) === 'number') {
204 			part.pageId = value;
205 			delete part.stringValue;
206 			return value;
207 		}
208 
209 		if (typeof value !== 'undefined' && value !== null) {
210 			part.stringValue = value.toString();
211 			delete part.pageId;
212 			return value;
213 		}
214 
215 		return part[
216 			jQuery.type(part.stringValue) === 'string' ? 'stringValue'
217 			                                           : 'pageId'
218 		];
219 	}
220 	TagParts.PAGE = PAGE;
221 
222 	/**
223 	 * <p>
224 	 * Gets or sets the value of a SELECT tag part.
225 	 *
226 	 * <p>
227 	 * There are several possible values that can be passed to this function:
228 	 *
229 	 * <pre>
230 	 *      undefined : When value arguments is not provided, then none of this
231 	 *                  part's data is changed.
232 	 *
233 	 *           null : selectedOptions will set to an empty array.
234 	 *
235 	 *         object : selectedOptions will be set to contain a single select
236 	 *                  option that corresponds with that of the
237 	 *                  `selectedOptions' property in the given object.  This
238 	 *                  allowance exists for backwards compatibility, and is not
239 	 *                  recommended.
240 	 *
241 	 *         string : selectedOptions will be set to contain a single select
242 	 *                  option whose `value' property corresponds with that of
243 	 *                  the argument.
244 	 *
245 	 *       string[] : selectedOptions will be set to contain zero or more
246 	 *                  select option whose `value' property corresponds with
247 	 *                  that of those in the given array.
248 	 * </pre>
249 	 *
250 	 * @public
251 	 * @function
252 	 * @memberOf TagParts
253 	 * @name SELECT
254 	 * @param {object} part The part whose value is to be accessed.
255 	 * @param {(string|string[]|object|null)=} value The values with which to
256 	 *                                         determined what this part's
257 	 *                                         `selectedOptions' property should
258 	 *                                         hold.
259 	 * @return {object} An object containing a copy of the value of this part.
260 	 * @throws VALUE_DOES_NOT_EXIST
261 	 */
262 	function SELECT(part, value) {
263 		var options = [];
264 		var option;
265 		var i;
266 		switch (jQuery.type(value)) {
267 		case 'string':
268 			option = getSelectPartOption(value, part);
269 			if (option) {
270 				options.push(option);
271 			} else {
272 				return part;
273 			}
274 			break;
275 		case 'array':
276 			for (i = 0; i < value.length; i++) {
277 				option = getSelectPartOption(value[i], part);
278 				if (option) {
279 					options.push(option);
280 				} else {
281 					return part;
282 				}
283 			}
284 			break;
285 		case 'object':
286 			for (i = 0; i < value.selectedOptions.length; i++) {
287 				option = getSelectPartOption(value.selectedOptions[i].value,
288 				                             part);
289 				if (option) {
290 					options.push(option);
291 				} else {
292 					return part;
293 				}
294 			}
295 			break;
296 		case 'undefined':
297 			options = part.selectedOptions;
298 			break;
299 		}
300 
301 		part.selectedOptions = options;
302 
303 		return {
304 			datasourceId: part.datasourceId,
305 			options: part.options,
306 			selectedOptions: part.selectedOptions
307 		};
308 	}
309 	TagParts.SELECT = SELECT;
310 
311 	/**
312 	 * Gets or sets the value of a MULTISELECT tag part.
313 	 * Operates in the same was as {@link TagParts.SELECT}.
314 	 *
315 	 * @public
316 	 * @function
317 	 * @memberOf TagParts
318 	 * @name MULTISELECT
319 	 * @param {object} part The part whose value is to be accessed.
320 	 * @param {(string|string[]|object|null)=} value The values with which to
321 	 *                                         determined what this part's
322 	 *                                         `selectedOptions' property should
323 	 *                                         hold.
324 	 * @return {object} An object containing a copy of the value of this part.
325 	 */
326 	function MULTISELECT(part, value) {
327 		return TagParts.SELECT(part, value);
328 	}
329 	TagParts.MULTISELECT = MULTISELECT;
330 
331 	/**
332 	 * Gets or sets the value of a TEMPLATETAG tag part.
333 	 *
334 	 * @public
335 	 * @function
336 	 * @memberOf TagParts
337 	 * @name TEMPLATETAG
338 	 * @param {object} part The part whose value is to be accessed.
339 	 * @param {object=} value An object with the either the property `templateId'
340 	 *                        or `templateTagId'.
341 	 * @return {object} An object containing a copy of the value of this part.
342 	 *
343 	 */
344 	function TEMPLATETAG(part, value) {
345 		if (value) {
346 			if (typeof value.templateId !== 'undefined') {
347 				part.templateId = value.templateId;
348 			}
349 
350 			if (typeof value.templateTagId !== 'undefined') {
351 				part.templateTagId = value.templateTagId;
352 			}
353 		}
354 
355 		return {
356 			templateId: part.templateId,
357 			templateTagId: part.templateTagId
358 		};
359 	}
360 	TagParts.TEMPLATETAG = TEMPLATETAG;
361 
362 	/**
363 	 * Gets or sets the value of a PAGETAG tag part.
364 	 *
365 	 * @public
366 	 * @function
367 	 * @memberOf TagParts
368 	 * @name PAGETAG
369 	 * @param {object} part The part whose value is to be accessed.
370 	 * @param {object=} value An object with the the property `pageId'
371 	 *                        and/or one of `contentTagId' or `templateTagId'.
372 	 * @return {object} An object containing a copy of the value of this
373 	 *                  part.
374 	 */
375 	function PAGETAG(part, value) {
376 		if (value) {
377 			if (typeof value.pageId !== 'undefined') {
378 				part.pageId = value.pageId;
379 			}
380 
381 			var newContentTagIdValue;
382 			// support wrongly named 'pageTagId' property for backwards compatibility
383 			if (typeof value.pageTagId !== 'undefined') {
384 				newContentTagIdValue = value.pageTagId;
385 			} else if (typeof value.contentTagId !== 'undefined') {
386 				newContentTagIdValue = value.contentTagId;
387 			}
388 
389 			// either a contenttag OR a templatetag must be specified
390 			if (typeof newContentTagIdValue !== 'undefined') {
391 				part.contentTagId = newContentTagIdValue;
392 				delete part.templateTagId;
393 			} else if (typeof value.templateTagId !== 'undefined') {
394 				part.templateTagId = value.templateTagId;
395 				delete part.contentTagId;
396 			}
397 		}
398 
399 		var result = { pageId: part.pageId };
400 
401 		if (typeof part.contentTagId !== 'undefined') {
402 			result.contentTagId = part.contentTagId;
403 		} else if (typeof part.templateTagId !== 'undefined') {
404 			result.templateTagId = part.templateTagId;
405 		}
406 
407 		return result;
408 	}
409 	TagParts.PAGETAG = PAGETAG;
410 
411 	/**
412 	 * Gets or sets the value of the given tag part.
413 	 *
414 	 * @private
415 	 * @ignore
416 	 * @param {object} part The part whose value is to be accessed.
417 	 * @param {*=} value The value to set the part to.
418 	 * @throws CANNOT_READ_TAG_PART
419 	 */
420 	function accessor() {
421 		var args = Array.prototype.slice.call(arguments);
422 		var part = args[0];
423 		if (!TagParts[part.type]) {
424 			GCN.error(
425 				'CANNOT_READ_TAG_PART',
426 				'Cannot read or write to tag part',
427 				part
428 			);
429 			return null;
430 		}
431 		return (
432 			args.length > 1
433 				? TagParts[part.type](part, args[1])
434 				: TagParts[part.type](part)
435 		);
436 	}
437 
438 	/**
439 	 * Gets the value of the given tag part.
440 	 *
441 	 * @param {object} part The part whose value is to be retrieved.
442 	 * @param {*=} value The value to set the part to.
443 	 * @return {*} The value held in the given part.
444 	 * @throws CANNOT_READ_TAG_PART
445 	 */
446 	TagParts.get = function (part) {
447 		return accessor(part);
448 	};
449 
450 	/**
451 	 * Sets the value of the given tag part.
452 	 *
453 	 * @param {object} part The part whose value is to be set.
454 	 * @param {*=} value The value to set the part to.
455 	 * @return {*} The value set to the given part.
456 	 * @throws CANNOT_READ_TAG_PART
457 	 */
458 	TagParts.set = function (part, value) {
459 		return accessor(part, value);
460 	};
461 
462 	GCN.TagParts = TagParts;
463 
464 }(GCN));
465