1 /**
  2  * @file Add thanks
  3  *
  4  * @author Dominik Kocuj
  5  * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License v2 or later
  6  * @copyright Copyright (c) 2016-2018 kocuj.pl
  7  */
  8 
  9 (function() {})(); // empty function for correct minify with comments
 10 //'use strict'; // for jshint uncomment this and comment line above
 11 
 12 /* jshint strict: true */
 13 /* jshint -W034 */
 14 /* jshint -W107 */
 15 
 16 /* global document */
 17 /* global jQuery */
 18 /* global window */
 19 
 20 /* global ajaxurl */
 21 
 22 /* global kocujILV12aHelper */
 23 /* global kocujILV12aAllJsAjax */
 24 
 25 /* global kocujPLV12aBackendAddThanksVals */
 26 
 27 /**
 28  * Add thanks prototype constructor
 29  *
 30  * @constructs
 31  * @namespace kocujPLV12aCBackendAddThanks
 32  * @public
 33  * @return {void}
 34  */
 35 function kocujPLV12aCBackendAddThanks() {
 36 	'use strict';
 37 	/* jshint validthis: true */
 38 	// get this object
 39 	var self = this;
 40 	// initialize objects
 41 	self._objHelper = kocujILV12aHelper;
 42 	self._objAllJsAjax = kocujILV12aAllJsAjax;
 43 	// get current script filename
 44 	self._thisFilename = document.scripts[document.scripts.length-1].src;
 45 	// get settings
 46 	var vals = kocujPLV12aBackendAddThanksVals;
 47 	if (vals.throwErrors !== undefined) {
 48 		if (vals.throwErrors === '1') {
 49 			self._valsThrowErrors = true;
 50 		} else {
 51 			self._valsThrowErrors = false;
 52 		}
 53 	}
 54 	self._valsPrefix = vals.prefix;
 55 	self._valsPrefixKocujIL = vals.prefixKocujIL;
 56 	self._valsSecurity = vals.security;
 57 	self._valsWebsiteUrl = vals.websiteUrl;
 58 	self._valsWebsiteTitle = vals.websiteTitle;
 59 	self._valsWebsiteDescription = vals.websiteDescription;
 60 	self._valsTextMoreInfoLink = vals.textMoreInfoLink;
 61 	self._valsTextSending = vals.textSending;
 62 	self._valsTextError = vals.textError;
 63 	self._valsTextErrorNoRetries = vals.textErrorNoRetries;
 64 	self._valsTextErrorAlreadyExists = vals.textErrorAlreadyExists;
 65 	self._valsTextErrorWrongResponse1 = vals.textErrorWrongResponse1;
 66 	self._valsTextErrorWrongResponse2 = vals.textErrorWrongResponse2;
 67 	self._valsTextSuccess = vals.textSuccess;
 68 	self._valsImageLoadingUrl = vals.imageLoadingUrl;
 69 }
 70 
 71 /**
 72  * Add thanks prototype
 73  *
 74  * @namespace kocujPLV12aCBackendAddThanks
 75  * @public
 76  */
 77 kocujPLV12aCBackendAddThanks.prototype = {
 78 	/**
 79 	 * Object kocujILV12aHelper
 80 	 *
 81 	 * @private
 82 	 * @type {Object}
 83 	 */
 84 	_objHelper : null,
 85 
 86 	/**
 87 	 * Object kocujILV12aAllJsAjax
 88 	 *
 89 	 * @private
 90 	 * @type {Object}
 91 	 */
 92 	_objAllJsAjax : null,
 93 
 94 	/**
 95 	 * Current script filename
 96 	 *
 97 	 * @private
 98 	 * @type {string}
 99 	 */
100 	_thisFilename : '',
101 
102 	/**
103 	 * Projects list
104 	 *
105 	 * @private
106 	 * @type {Array}
107 	 */
108 	_prj : [],
109 
110 	/**
111 	 * Script settings - throw errors (true) or not (false)
112 	 *
113 	 * @private
114 	 * @type {string}
115 	 */
116 	_valsThrowErrors : false,
117 
118 	/**
119 	 * Script settings - prefix
120 	 *
121 	 * @private
122 	 * @type {string}
123 	 */
124 	_valsPrefix : '',
125 
126 	/**
127 	 * Script settings - prefix for Kocuj Internal Lib
128 	 *
129 	 * @private
130 	 * @type {string}
131 	 */
132 	_valsPrefixKocujIL : '',
133 
134 	/**
135 	 * Script settings - security string
136 	 *
137 	 * @private
138 	 * @type {string}
139 	 */
140 	_valsSecurity : '',
141 
142 	/**
143 	 * Script settings - website URL
144 	 *
145 	 * @private
146 	 * @type {string}
147 	 */
148 	_valsWebsiteUrl : '',
149 
150 	/**
151 	 * Script settings - website title
152 	 *
153 	 * @private
154 	 * @type {string}
155 	 */
156 	_valsWebsiteTitle : '',
157 
158 	/**
159 	 * Script settings - website description
160 	 *
161 	 * @private
162 	 * @type {string}
163 	 */
164 	_valsWebsiteDescription : '',
165 
166 	/**
167 	 * Script settings - text for more information link
168 	 *
169 	 * @private
170 	 * @type {string}
171 	 */
172 	_valsTextMoreInfoLink : '',
173 
174 	/**
175 	 * Script settings - text for sending
176 	 *
177 	 * @private
178 	 * @type {string}
179 	 */
180 	_valsTextSending : '',
181 
182 	/**
183 	 * Script settings - text for error
184 	 *
185 	 * @private
186 	 * @type {string}
187 	 */
188 	_valsTextError : '',
189 
190 	/**
191 	 * Script settings - text for error with no more retries
192 	 *
193 	 * @private
194 	 * @type {string}
195 	 */
196 	_valsTextErrorNoRetries : '',
197 
198 	/**
199 	 * Script settings - text for data which already exists
200 	 *
201 	 * @private
202 	 * @type {string}
203 	 */
204 	_valsTextErrorAlreadyExists : '',
205 
206 	/**
207 	 * Script settings - text for wrong response from server (line 1)
208 	 *
209 	 * @private
210 	 * @type {string}
211 	 */
212 	_valsTextErrorWrongResponse1 : '',
213 
214 	/**
215 	 * Script settings - text for wrong response from server (line 2)
216 	 *
217 	 * @private
218 	 * @type {string}
219 	 */
220 	_valsTextErrorWrongResponse2 : '',
221 
222 	/**
223 	 * Script settings - text for success
224 	 *
225 	 * @private
226 	 * @type {string}
227 	 */
228 	_valsTextSuccess : '',
229 
230 	/**
231 	 * Script settings - text for loading URL
232 	 *
233 	 * @private
234 	 * @type {string}
235 	 */
236 	_valsImageLoadingUrl : '',
237 
238 	/**
239 	 * Styles are saved (true) or not (false)
240 	 *
241 	 * @private
242 	 * @type {boolean}
243 	 */
244 	_stylesSaved : false,
245 
246 	/**
247 	 * Saved styles
248 	 *
249 	 * @private
250 	 * @type {string}
251 	 */
252 	_styles : '',
253 
254 	/**
255 	 * Add project
256 	 *
257 	 * @public
258 	 * @param {string} projectId Project identifier
259 	 * @param {string} windowFunction Function name for window
260 	 * @param {string} projectApiUrl Project API URL
261 	 * @param {string} projectApiLogin Project API login
262 	 * @param {string} [projectApiPassword] Project API password
263 	 * @return {void}
264 	 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.PROJECT_ALREADY_EXISTS if project identifier entered in projectId already exists
265 	 */
266 	addProject : function(projectId, windowFunction, projectApiUrl, projectApiLogin, projectApiPassword) {
267 		'use strict';
268 		// parse arguments
269 		var args = this._checkAddProject(projectId, windowFunction, projectApiUrl, projectApiLogin, projectApiPassword);
270 		// add project
271 		if (this._prj['prj_' + args.projectId] === undefined) {
272 			this.addProjectIfNotExists(args.projectId, args.windowFunction, args.projectApiUrl, args.projectApiLogin, args.projectApiPassword);
273 		} else {
274 			this._throwError('PROJECT_ALREADY_EXISTS', args.projectId);
275 			return;
276 		}
277 	},
278 
279 	/**
280 	 * Add project if not exists
281 	 *
282 	 * @public
283 	 * @param {string} projectId Project identifier
284 	 * @param {string} windowFunction Function name for window
285 	 * @param {string} projectApiUrl Project API URL
286 	 * @param {string} projectApiLogin Project API login
287 	 * @param {string} [projectApiPassword] Project API password
288 	 * @return {void}
289 	 */
290 	addProjectIfNotExists : function(projectId, windowFunction, projectApiUrl, projectApiLogin, projectApiPassword) {
291 		'use strict';
292 		// parse arguments
293 		var args = this._checkAddProject(projectId, windowFunction, projectApiUrl, projectApiLogin, projectApiPassword);
294 		// add project
295 		if (this._prj['prj_' + args.projectId] === undefined) {
296 			this._prj['prj_' + args.projectId] = {
297 				windowFunction     : args.windowFunction,
298 				projectApiUrl      : args.projectApiUrl,
299 				projectApiLogin    : args.projectApiLogin,
300 				projectApiPassword : args.projectApiPassword,
301 				timer              : null,
302 			};
303 		}
304 		this._objAllJsAjax.addProjectIfNotExists(args.projectId);
305 	},
306 
307 	/**
308 	 * Get HTML selector for review message
309 	 *
310 	 * @public
311 	 * @param {string} projectId Project identifier
312 	 * @return {string} HTML selector for review message
313 	 */
314 	getHTMLSelectorReviewMessageDiv : function(projectId) {
315 		'use strict';
316 		// parse arguments
317 		projectId = this._parseProjectId(projectId);
318 		// exit
319 		return '#' + this._getHTMLNameReviewMessageDiv(projectId);
320 	},
321 
322 	/**
323 	 * Get HTML selector for style
324 	 *
325 	 * @public
326 	 * @param {string} projectId Project identifier
327 	 * @return {string} HTML selector for style
328 	 */
329 	getHTMLSelectorAddThanksStyle : function(projectId) {
330 		'use strict';
331 		// parse arguments
332 		projectId = this._parseProjectId(projectId);
333 		// exit
334 		return '#' + this._getHTMLNameAddThanksStyle(projectId);
335 	},
336 
337 	/**
338 	 * Get HTML selector for more information link div in review message
339 	 *
340 	 * @public
341 	 * @param {string} projectId Project identifier
342 	 * @return {string} HTML selector for more information link div in review message
343 	 */
344 	getHTMLSelectorAddThanksReviewMessageMoreInfoLinkDiv : function(projectId) {
345 		'use strict';
346 		// parse arguments
347 		projectId = this._parseProjectId(projectId);
348 		// exit
349 		return '#' + this._getHTMLNameAddThanksReviewMessageMoreInfoLinkDiv(projectId);
350 	},
351 
352 	/**
353 	 * Get HTML selector for more information link in review message
354 	 *
355 	 * @public
356 	 * @param {string} projectId Project identifier
357 	 * @return {string} HTML selector for more information link in review message
358 	 */
359 	getHTMLSelectorAddThanksReviewMessageMoreInfoLink : function(projectId) {
360 		'use strict';
361 		// parse arguments
362 		projectId = this._parseProjectId(projectId);
363 		// exit
364 		return this.getHTMLSelectorAddThanksReviewMessageMoreInfoLinkDiv(projectId) + ' #' + this._getHTMLNameAddThanksReviewMessageMoreInfoLink(projectId);
365 	},
366 
367 	/**
368 	 * Get HTML selector for send button in review message
369 	 *
370 	 * @public
371 	 * @param {string} projectId Project identifier
372 	 * @return {string} HTML selector for send button in review message
373 	 */
374 	getHTMLSelectorAddThanksReviewMessageSend : function(projectId) {
375 		'use strict';
376 		// parse arguments
377 		projectId = this._parseProjectId(projectId);
378 		// exit
379 		return '#' + this._getHTMLNameAddThanksReviewMessageSend(projectId);
380 	},
381 
382 	/**
383 	 * Get HTML selector for close message in review message
384 	 *
385 	 * @public
386 	 * @param {string} projectId Project identifier
387 	 * @return {string} HTML selector for close message in review message
388 	 */
389 	getHTMLSelectorReviewMessageClose : function(projectId) {
390 		'use strict';
391 		// parse arguments
392 		projectId = this._parseProjectId(projectId);
393 		// exit
394 		return '#' + this._getHTMLNameReviewMessageClose(projectId);
395 	},
396 
397 	/**
398 	 * Get HTML selector for loading image in review message
399 	 *
400 	 * @public
401 	 * @param {string} projectId Project identifier
402 	 * @return {string} HTML selector for loading image in review message
403 	 */
404 	getHTMLSelectorAddThanksReviewMessageLoadingImage : function(projectId) {
405 		'use strict';
406 		// parse arguments
407 		projectId = this._parseProjectId(projectId);
408 		// exit
409 		return '#' + this._getHTMLNameAddThanksReviewMessageLoadingImage(projectId);
410 	},
411 
412 	/**
413 	 * Get HTML selector for adding thanks div in about page
414 	 *
415 	 * @public
416 	 * @param {string} projectId Project identifier
417 	 * @return {string} HTML selector for adding thanks div in about page
418 	 */
419 	getHTMLSelectorAddThanksPageAboutDiv : function(projectId) {
420 		'use strict';
421 		// parse arguments
422 		projectId = this._parseProjectId(projectId);
423 		// exit
424 		return '#' + this._getHTMLNameAddThanksPageAboutDiv(projectId);
425 	},
426 
427 	/**
428 	 * Get HTML selector for more information link in about page
429 	 *
430 	 * @public
431 	 * @param {string} projectId Project identifier
432 	 * @return {string} HTML selector for more information link in about page
433 	 */
434 	getHTMLSelectorAddThanksPageAboutMoreInfoLink : function(projectId) {
435 		'use strict';
436 		// parse arguments
437 		projectId = this._parseProjectId(projectId);
438 		// exit
439 		return this.getHTMLSelectorAddThanksPageAboutDiv(projectId) + ' #' + this._getHTMLNameAddThanksPageAboutMoreInfoLink(projectId);
440 	},
441 
442 	/**
443 	 * Get HTML selector for sending button in about page
444 	 *
445 	 * @public
446 	 * @param {string} projectId Project identifier
447 	 * @return {string} HTML selector for sending button in about page
448 	 */
449 	getHTMLSelectorAddThanksPageAboutSend : function(projectId) {
450 		'use strict';
451 		// parse arguments
452 		projectId = this._parseProjectId(projectId);
453 		// exit
454 		return this.getHTMLSelectorAddThanksPageAboutDiv(projectId) + ' #' + this._getHTMLNameAddThanksPageAboutSend(projectId);
455 	},
456 
457 	/**
458 	 * Get HTML selector for status div in about page
459 	 *
460 	 * @public
461 	 * @param {string} projectId Project identifier
462 	 * @return {string} HTML selector for status div in about page
463 	 */
464 	getHTMLSelectorAddThanksPageAboutStatusDiv : function(projectId) {
465 		'use strict';
466 		// parse arguments
467 		projectId = this._parseProjectId(projectId);
468 		// exit
469 		return this.getHTMLSelectorAddThanksPageAboutDiv(projectId) + ' #' + this._getHTMLNameAddThanksPageAboutStatusDiv(projectId);
470 	},
471 
472 	/**
473 	 * Get HTML selector for loading div in about page
474 	 *
475 	 * @public
476 	 * @param {string} projectId Project identifier
477 	 * @return {string} HTML selector for loading div in about page
478 	 */
479 	getHTMLSelectorAddThanksPageAboutLoadingDiv : function(projectId) {
480 		'use strict';
481 		// parse arguments
482 		projectId = this._parseProjectId(projectId);
483 		// exit
484 		return this.getHTMLSelectorAddThanksPageAboutDiv(projectId) + ' #' + this._getHTMLNameAddThanksPageAboutLoadingDiv(projectId);
485 	},
486 
487 	/**
488 	 * Set adding thanks for review message
489 	 *
490 	 * @public
491 	 * @param {string} projectId Project identifier
492 	 * @return {void}
493 	 */
494 	setReviewMessageAddThanks : function(projectId) {
495 		'use strict';
496 		// get this object
497 		var self = this;
498 		(function($) {
499 			// parse arguments
500 			projectId = self._parseProjectId(projectId);
501 			// add link to more information
502 			$(self.getHTMLSelectorAddThanksReviewMessageMoreInfoLinkDiv(projectId)).html('<a href="#" id="' + self._getHTMLNameAddThanksReviewMessageMoreInfoLink(projectId) + '">' + self._valsTextMoreInfoLink + '</a>');
503 			var selectorAddThanksReviewMessageMoreInfoLink = $(self.getHTMLSelectorAddThanksReviewMessageMoreInfoLink(projectId));
504 			selectorAddThanksReviewMessageMoreInfoLink.attr('href', 'javascript:void(0);');
505 			selectorAddThanksReviewMessageMoreInfoLink.bind('click', {
506 				self : self
507 			}, function(event) {
508 				// disable default event
509 				event.preventDefault();
510 				// show window with more information
511 				var fn = window[event.data.self._prj['prj_' + projectId].windowFunction];
512 				fn();
513 			});
514 			// set button event to add thanks
515 			$(self.getHTMLSelectorAddThanksReviewMessageSend(projectId)).bind('click', {
516 				self      : self,
517 				projectId : projectId
518 			}, function(event) {
519 				// disable default event
520 				event.preventDefault();
521 				// optionally restore original styles
522 				if (event.data.self._stylesSaved) {
523 					$(event.data.self.getHTMLSelectorAddThanksStyle(projectId)).html(event.data.self._styles);
524 				}
525 				// add thanks
526 				event.data.self._addThanks(event.data.projectId);
527 			});
528 		}(jQuery));
529 	},
530 
531 	/**
532 	 * Set adding thanks for about page
533 	 *
534 	 * @public
535 	 * @param {string} projectId Project identifier
536 	 * @return {void}
537 	 */
538 	setPageAboutAddThanks : function(projectId) {
539 		'use strict';
540 		// get this object
541 		var self = this;
542 		(function($) {
543 			// parse arguments
544 			projectId = self._parseProjectId(projectId);
545 			// get selectors
546 			var selectorAddThanksPageAboutMoreInfoLink = $(self.getHTMLSelectorAddThanksPageAboutMoreInfoLink(projectId));
547 			// add link to more information
548 			selectorAddThanksPageAboutMoreInfoLink.attr('href', 'javascript:void(0);');
549 			selectorAddThanksPageAboutMoreInfoLink.bind('click', {
550 				self : self
551 			}, function(event) {
552 				// disable default event
553 				event.preventDefault();
554 				// show window with more information
555 				var fn = window[event.data.self._prj['prj_' + projectId].windowFunction];
556 				fn();
557 			});
558 			// set button event to add thanks
559 			$(self.getHTMLSelectorAddThanksPageAboutSend(projectId)).bind('click', {
560 				self      : self,
561 				projectId : projectId
562 			}, function(event) {
563 				// disable default event
564 				event.preventDefault();
565 				// add thanks
566 				event.data.self._addThanks(event.data.projectId);
567 			});
568 		}(jQuery));
569 	},
570 
571 	/**
572 	 * AJAX loading success callback for adding thanks
573 	 *
574 	 * @public
575 	 * @param {string} projectId Project identifier
576 	 * @param {string} connectionId Connection identifier
577 	 * @param {anything} data Data
578 	 * @param {string} status Text status
579 	 * @param {Object} obj Request object
580 	 * @return {void}
581 	 */
582 	ajaxAddThanksSuccessCallback : function(projectId, connectionId, data, status, obj) {
583 		'use strict';
584 		// get this object
585 		var self = kocujPLV12aBackendAddThanks;
586 		(function($) {
587 			// prepare text to display
588 			var text = self._valsTextSuccess;
589 			// check results
590 			if ((data.status !== undefined) && (data.status.id !== undefined)) {
591 				if (data.status.id !== 'OK') {
592 					if (data.status.id === 'CT_ADD_THANKS_URLALREADYEXISTS') {
593 						text = self._valsTextErrorAlreadyExists;
594 					} else {
595 						self.ajaxAddThanksErrorCallback(projectId, connectionId, null, 'api_error', '');
596 						return;
597 					}
598 				}
599 			} else {
600 				self.ajaxAddThanksErrorCallback(projectId, connectionId, null, 'api_error', '');
601 				return;
602 			}
603 			// change HTML elements in review message
604 			self._removeReviewMessageLoadingImageElement(projectId);
605 			self._showReviewMessageCloseElement(projectId);
606 			// save information about added thanks
607 			self._objAllJsAjax.sendPost(projectId, 'add_thanks_finished', ajaxurl, 'text', {
608 				action   : self._valsPrefix + '_' + projectId + '__add_thanks_finished',
609 				security : self._valsSecurity
610 			});
611 			// get selectors
612 			var selectorAddThanksReviewMessageMoreInfoLinkDiv = $(self.getHTMLSelectorAddThanksReviewMessageMoreInfoLinkDiv(projectId));
613 			var selectorAddThanksPageAboutStatusDiv = $(self.getHTMLSelectorAddThanksPageAboutStatusDiv(projectId));
614 			// show information about success
615 			if (selectorAddThanksReviewMessageMoreInfoLinkDiv.length > 0) {
616 				selectorAddThanksReviewMessageMoreInfoLinkDiv.html('<strong>' + text + '</strong>');
617 			}
618 			if (selectorAddThanksPageAboutStatusDiv.length > 0) {
619 				selectorAddThanksPageAboutStatusDiv.html('<strong>' + text + '</strong>');
620 				selectorAddThanksPageAboutStatusDiv.show();
621 				$(self.getHTMLSelectorAddThanksPageAboutLoadingDiv(projectId)).hide();
622 			}
623 			// add timeout to remove adding thanks div
624 			if (($(self.getHTMLSelectorAddThanksReviewMessageSend(projectId)).length > 0) || ($(self.getHTMLSelectorAddThanksPageAboutDiv(projectId)).length > 0)) {
625 				self._prj['prj_' + projectId].timer = window.setTimeout(function() {
626 					// clear timer
627 					window.clearTimeout(self._prj['prj_' + projectId].timer);
628 					self._prj['prj_' + projectId].timer = null;
629 					// get selectors
630 					var selectorAddThanksReviewMessageSend = $(self.getHTMLSelectorAddThanksReviewMessageSend(projectId));
631 					var selectorAddThanksPageAboutDiv = $(self.getHTMLSelectorAddThanksPageAboutDiv(projectId));
632 					// remove adding thanks div
633 					if (selectorAddThanksReviewMessageSend.length > 0) {
634 						selectorAddThanksReviewMessageSend.parent().fadeOut('slow', function() {
635 							selectorAddThanksReviewMessageSend.parent().remove();
636 						});
637 					}
638 					if (selectorAddThanksPageAboutDiv.length > 0) {
639 						selectorAddThanksPageAboutDiv.fadeOut('slow', function() {
640 							selectorAddThanksPageAboutDiv.remove();
641 						});
642 					}
643 				}, 5000);
644 			}
645 		}(jQuery));
646 	},
647 
648 	/**
649 	 * AJAX loading error callback for adding thanks
650 	 *
651 	 * @public
652 	 * @param {string} projectId Project identifier
653 	 * @param {string} connectionId Connection identifier
654 	 * @param {Object} obj Request object
655 	 * @param {string} status Text status
656 	 * @param {string} err Error
657 	 * @return {void}
658 	 */
659 	ajaxAddThanksErrorCallback : function(projectId, connectionId, obj, status, err) {
660 		'use strict';
661 		// get this object
662 		var self = kocujPLV12aBackendAddThanks;
663 		(function($) {
664 			// change HTML elements in review message
665 			self._removeReviewMessageLoadingImageElement(projectId);
666 			self._showReviewMessageCloseElement(projectId);
667 			if ($(self.getHTMLSelectorAddThanksReviewMessageSend(projectId)).length > 0) {
668 				$(self.getHTMLSelectorAddThanksReviewMessageSend(projectId)).removeAttr('disabled');
669 			}
670 			if ($(self.getHTMLSelectorAddThanksPageAboutSend(projectId)).length > 0) {
671 				$(self.getHTMLSelectorAddThanksPageAboutSend(projectId)).removeAttr('disabled');
672 			}
673 			// get selectors
674 			var selectorAddThanksReviewMessageMoreInfoLinkDiv = $(self.getHTMLSelectorAddThanksReviewMessageMoreInfoLinkDiv(projectId));
675 			var selectorAddThanksPageAboutStatusDiv = $(self.getHTMLSelectorAddThanksPageAboutStatusDiv(projectId));
676 			// show information about error
677 			var infoReview = self._valsTextErrorNoRetries;
678 			var infoPageAbout = infoReview;
679 			if (status === 'api_error') {
680 				infoReview = self._valsTextErrorWrongResponse1 + '<br />' + self._valsTextErrorWrongResponse2;
681 				infoPageAbout = self._valsTextErrorWrongResponse1 + ' ' + self._valsTextErrorWrongResponse2;
682 			}
683 			if (selectorAddThanksReviewMessageMoreInfoLinkDiv.length > 0) {
684 				selectorAddThanksReviewMessageMoreInfoLinkDiv.html('<strong>' + infoReview + '</strong>');
685 				if (status === 'api_error') {
686 					self._styles = $(self.getHTMLSelectorAddThanksStyle(projectId)).html();
687 					$(self.getHTMLSelectorAddThanksStyle(projectId)).html(self._styles + "\n" +
688 						'.' + self._valsPrefix + '_' + projectId +  '__add_thanks_review_message_element_div {' + "\n" +
689 						'height:80px;' + "\n" +
690 						'}' + "\n" +
691 						'@media screen and (max-width: 782px) {' + "\n" +
692 						'.' + self._valsPrefix + '_' + projectId +  '__add_thanks_review_message_element_div {' + "\n" +
693 						'height:105px;' + "\n" +
694 						'}' + "\n" +
695 						'}'
696 					);
697 					self._stylesSaved = true;
698 				}
699 			}
700 			if (selectorAddThanksPageAboutStatusDiv.length > 0) {
701 				selectorAddThanksPageAboutStatusDiv.html('<strong>' + infoPageAbout + '</strong>');
702 				selectorAddThanksPageAboutStatusDiv.show();
703 				$(self.getHTMLSelectorAddThanksPageAboutLoadingDiv(projectId)).hide();
704 			}
705 		}(jQuery));
706 	},
707 
708 	/**
709 	 * Doing something before waiting for AJAX request retry callback for adding thanks
710 	 *
711 	 * @public
712 	 * @param {string} projectId Project identifier
713 	 * @param {string} connectionId Connection identifier
714 	 * @param {numeric} retries Connection retries
715 	 * @param {Object} obj Request object
716 	 * @param {string} status Text status
717 	 * @param {string} err Error
718 	 * @return {void}
719 	 */
720 	ajaxAddThanksRetryWaitCallback : function(projectId, connectionId, retries, obj, status, err) {
721 		'use strict';
722 		// get this object
723 		var self = kocujPLV12aBackendAddThanks;
724 		(function($) {
725 			// change HTML elements in review message
726 			self._removeReviewMessageLoadingImageElement(projectId);
727 			// get selectors
728 			var selectorAddThanksReviewMessageMoreInfoLinkDiv = $(self.getHTMLSelectorAddThanksReviewMessageMoreInfoLinkDiv(projectId));
729 			var selectorAddThanksPageAboutStatusDiv = $(self.getHTMLSelectorAddThanksPageAboutStatusDiv(projectId));
730 			// show information about error
731 			if (selectorAddThanksReviewMessageMoreInfoLinkDiv.length > 0) {
732 				selectorAddThanksReviewMessageMoreInfoLinkDiv.html('<strong>' + self._valsTextError + '</strong>');
733 			}
734 			if (selectorAddThanksPageAboutStatusDiv.length > 0) {
735 				selectorAddThanksPageAboutStatusDiv.html('<strong>' + self._valsTextError + '</strong>');
736 				selectorAddThanksPageAboutStatusDiv.show();
737 				$(self.getHTMLSelectorAddThanksPageAboutLoadingDiv(projectId)).hide();
738 			}
739 		}(jQuery));
740 	},
741 
742 	/**
743 	 * Doing something at the beginning of AJAX request retry callback for adding thanks
744 	 *
745 	 * @public
746 	 * @param {string} projectId Project identifier
747 	 * @param {string} connectionId Connection identifier
748 	 * @param {numeric} retries Connection retries
749 	 * @param {Object} obj Request object
750 	 * @param {string} status Text status
751 	 * @param {string} err Error
752 	 * @return {void}
753 	 */
754 	ajaxAddThanksRetryNowCallback : function(projectId, connectionId, retries, obj, status, err) {
755 		'use strict';
756 		// get this object
757 		var self = kocujPLV12aBackendAddThanks;
758 		(function($) {
759 			// change HTML elements
760 			self._changeElementsBeforeAddThanksAjaxSend(projectId);
761 		}(jQuery));
762 	},
763 
764 	/**
765 	 * Get HTML prefix
766 	 *
767 	 * @private
768 	 * @param {string} projectId Project identifier
769 	 * @return {string} HTML prefix
770 	 */
771 	_getHTMLPrefix : function(projectId) {
772 		'use strict';
773 		// exit
774 		return this._valsPrefix + '_' + projectId + '__';
775 	},
776 
777 	/**
778 	 * Get HTML prefix for Kocuj Internal Lib
779 	 *
780 	 * @private
781 	 * @param {string} projectId Project identifier
782 	 * @return {string} HTML prefix for Kocuj Internal Lib
783 	 */
784 	_getHTMLPrefixKocujIL : function(projectId) {
785 		'use strict';
786 		// exit
787 		return this._valsPrefixKocujIL + '_' + projectId + '__';
788 	},
789 
790 	/**
791 	 * Get HTML name for review message div
792 	 *
793 	 * @private
794 	 * @param {string} projectId Project identifier
795 	 * @return {string} HTML name for review message div
796 	 */
797 	_getHTMLNameReviewMessageDiv : function(projectId) {
798 		'use strict';
799 		// exit
800 		return this._getHTMLPrefixKocujIL(projectId) + 'message_review';
801 	},
802 
803 	/**
804 	 * Get HTML name for style
805 	 *
806 	 * @private
807 	 * @param {string} projectId Project identifier
808 	 * @return {string} HTML name for style
809 	 */
810 	_getHTMLNameAddThanksStyle : function(projectId) {
811 		'use strict';
812 		// exit
813 		return this._getHTMLPrefix(projectId) + 'add_thanks_review_message_style';
814 	},
815 
816 	/**
817 	 * Get HTML name for more information link div in review message
818 	 *
819 	 * @private
820 	 * @param {string} projectId Project identifier
821 	 * @return {string} HTML name for more information link div in review message
822 	 */
823 	_getHTMLNameAddThanksReviewMessageMoreInfoLinkDiv : function(projectId) {
824 		'use strict';
825 		// exit
826 		return this._getHTMLPrefix(projectId) + 'add_thanks_review_message_more_info_link_div';
827 	},
828 
829 	/**
830 	 * Get HTML name for more information link in review message
831 	 *
832 	 * @private
833 	 * @param {string} projectId Project identifier
834 	 * @return {string} HTML name for more information link in review message
835 	 */
836 	_getHTMLNameAddThanksReviewMessageMoreInfoLink : function(projectId) {
837 		'use strict';
838 		// exit
839 		return this._getHTMLPrefix(projectId) + 'add_thanks_review_message_more_info_link';
840 	},
841 
842 	/**
843 	 * Get HTML name for sending button in review message
844 	 *
845 	 * @private
846 	 * @param {string} projectId Project identifier
847 	 * @return {string} HTML name for sending button in review message
848 	 */
849 	_getHTMLNameAddThanksReviewMessageSend : function(projectId) {
850 		'use strict';
851 		// exit
852 		return this._getHTMLPrefix(projectId) + 'add_thanks_review_message_send';
853 	},
854 
855 	/**
856 	 * Get HTML name for close message in review message
857 	 *
858 	 * @private
859 	 * @param {string} projectId Project identifier
860 	 * @return {string} HTML name for close message in review message
861 	 */
862 	_getHTMLNameReviewMessageClose : function(projectId) {
863 		'use strict';
864 		// exit
865 		return this._getHTMLPrefixKocujIL(projectId) + 'review_message_close';
866 	},
867 
868 	/**
869 	 * Get HTML name for loading image in review message
870 	 *
871 	 * @private
872 	 * @param {string} projectId Project identifier
873 	 * @return {string} HTML name for loading image in review message
874 	 */
875 	_getHTMLNameAddThanksReviewMessageLoadingImage : function(projectId) {
876 		'use strict';
877 		// exit
878 		return this._getHTMLPrefixKocujIL(projectId) + 'add_thanks_review_message_loading_image';
879 	},
880 
881 	/**
882 	 * Get HTML name for adding thanks div in page about
883 	 *
884 	 * @private
885 	 * @param {string} projectId Project identifier
886 	 * @return {string} HTML name for adding thanks div in page about
887 	 */
888 	_getHTMLNameAddThanksPageAboutDiv : function(projectId) {
889 		'use strict';
890 		// exit
891 		return this._getHTMLPrefix(projectId) + 'add_thanks_page_about_div';
892 	},
893 
894 	/**
895 	 * Get HTML name for more information link in page about
896 	 *
897 	 * @private
898 	 * @param {string} projectId Project identifier
899 	 * @return {string} HTML name for more information link in page about
900 	 */
901 	_getHTMLNameAddThanksPageAboutMoreInfoLink : function(projectId) {
902 		'use strict';
903 		// exit
904 		return this._getHTMLPrefix(projectId) + 'add_thanks_page_about_more_info_link';
905 	},
906 
907 	/**
908 	 * Get HTML name for sending button in page about
909 	 *
910 	 * @private
911 	 * @param {string} projectId Project identifier
912 	 * @return {string} HTML name for sending button in page about
913 	 */
914 	_getHTMLNameAddThanksPageAboutSend : function(projectId) {
915 		'use strict';
916 		// exit
917 		return this._getHTMLPrefix(projectId) + 'add_thanks_page_about_send';
918 	},
919 
920 	/**
921 	 * Get HTML name for status div in page about
922 	 *
923 	 * @private
924 	 * @param {string} projectId Project identifier
925 	 * @return {string} HTML name for status div in page about
926 	 */
927 	_getHTMLNameAddThanksPageAboutStatusDiv : function(projectId) {
928 		'use strict';
929 		// exit
930 		return this._getHTMLPrefix(projectId) + 'add_thanks_page_about_status_div';
931 	},
932 
933 	/**
934 	 * Get HTML name for loading div in page about
935 	 *
936 	 * @private
937 	 * @param {string} projectId Project identifier
938 	 * @return {string} HTML name for loading div in page about
939 	 */
940 	_getHTMLNameAddThanksPageAboutLoadingDiv : function(projectId) {
941 		'use strict';
942 		// exit
943 		return this._getHTMLPrefix(projectId) + 'add_thanks_page_about_loading_div';
944 	},
945 
946 	/**
947 	 * Parse project identifier
948 	 *
949 	 * @private
950 	 * @param {string} projectId Project identifier
951 	 * @return {string} Parsed project identifier
952 	 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.EMPTY_PROJECT_ID if project identifier entered in projectId is empty
953 	 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.PROJECT_DOES_NOT_EXIST if project identifier entered in projectId does not exist
954 	 */
955 	_parseProjectId : function(projectId) {
956 		'use strict';
957 		// parse project identifier
958 		projectId = this._objHelper.initString(projectId);
959 		if (projectId === '') {
960 			this._throwError('EMPTY_PROJECT_ID');
961 			return;
962 		}
963 		// check if project exists
964 		if (this._prj['prj_' + projectId] === undefined) {
965 			this._throwError('PROJECT_DOES_NOT_EXIST', projectId);
966 			return;
967 		}
968 		// exit
969 		return projectId;
970 	},
971 
972 	/**
973 	 * Check arguments for adding project
974 	 *
975 	 * @private
976 	 * @param {string} projectId Project identifier
977 	 * @param {string} windowFunction Function name for window
978 	 * @param {string} projectApiUrl Project API URL
979 	 * @param {string} projectApiLogin Project API login
980 	 * @param {string} [projectApiPassword] Project API password
981 	 * @return {Object} Parsed arguments for adding project
982 	 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.EMPTY_PROJECT_ID if project identifier entered in projectId is empty
983 	 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.ADD_THANKS_EMPTY_API_URL if API URL entered in projectApiUrl is empty
984 	 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.ADD_THANKS_EMPTY_API_LOGIN if API login entered in projectApiLogin is empty
985 	 */
986 	_checkAddProject : function(projectId, windowFunction, projectApiUrl, projectApiLogin, projectApiPassword) {
987 		'use strict';
988 		// parse arguments
989 		projectId = this._objHelper.initString(projectId);
990 		if (projectId === '') {
991 			this._throwError('EMPTY_PROJECT_ID');
992 			return;
993 		}
994 		windowFunction = this._objHelper.initString(windowFunction);
995 		if (windowFunction === '') {
996 			this._throwError('ADD_THANKS_EMPTY_WINDOW_FUNCTION');
997 			return;
998 		}
999 		projectApiUrl = this._objHelper.initString(projectApiUrl);
1000 		if (projectApiUrl === '') {
1001 			this._throwError('ADD_THANKS_EMPTY_API_URL');
1002 			return;
1003 		}
1004 		projectApiLogin = this._objHelper.initString(projectApiLogin);
1005 		if (projectApiLogin === '') {
1006 			this._throwError('ADD_THANKS_EMPTY_API_LOGIN');
1007 			return;
1008 		}
1009 		projectApiPassword = this._objHelper.initString(projectApiPassword);
1010 		// exit
1011 		return {
1012 			projectId          : projectId,
1013 			windowFunction     : windowFunction,
1014 			projectApiUrl      : projectApiUrl,
1015 			projectApiLogin    : projectApiLogin,
1016 			projectApiPassword : projectApiPassword
1017 		};
1018 	},
1019 
1020 	/**
1021 	 * Throw an error if debugging is enabled
1022 	 *
1023 	 * @private
1024 	 * @param {string} codeString Error code in string format
1025 	 * @param {string} [param] Parameter for error information
1026 	 * @return {void}
1027 	 */
1028 	_throwError : function(codeString, param) {
1029 		'use strict';
1030 		// parse arguments
1031 		codeString = this._objHelper.initString(codeString);
1032 		if (codeString === '') {
1033 			return;
1034 		}
1035 		param = this._objHelper.initString(param);
1036 		// throw an error
1037 		if (this._valsThrowErrors) {
1038 			/* jshint evil: true */
1039 			eval('throw new kocujPLV12aCException(kocujPLV12aExceptionCode.' + codeString + ', this._thisFilename, param);');
1040 		}
1041 	},
1042 
1043 	/**
1044 	 * Add thanks
1045 	 *
1046 	 * @private
1047 	 * @param {string} projectId Project identifier
1048 	 * @return {void}
1049 	 */
1050 	_addThanks : function(projectId) {
1051 		'use strict';
1052 		// get this object
1053 		var self = this;
1054 		(function($) {
1055 			// parse arguments
1056 			projectId = self._parseProjectId(projectId);
1057 			// change HTML elements
1058 			self._changeElementsBeforeAddThanksAjaxSend(projectId);
1059 			// add thanks
1060 			self._objAllJsAjax.sendJson(projectId, 'add_thanks', self._prj['prj_' + projectId].projectApiUrl, {
1061 					'requestType'   : 'parameters',
1062 					'responseType'  : 'JSON',
1063 					'requestMethod' : 'GET',
1064 					'data'          : {
1065 						'PARAMETER_version' : 1,
1066 						'header'            : {
1067 							'login'    : self._prj['prj_' + projectId].projectApiLogin,
1068 							'password' : self._prj['prj_' + projectId].projectApiPassword
1069 						},
1070 						'request'           : {
1071 							'PARAMETER_command' : 'ADD_THANKS',
1072 							'url'               : self._valsWebsiteUrl,
1073 							'title'             : self._valsWebsiteTitle,
1074 							'description'       : self._valsWebsiteDescription
1075 						}
1076 					}
1077 				}, {
1078 					success   : self.ajaxAddThanksSuccessCallback,
1079 					error     : self.ajaxAddThanksErrorCallback,
1080 					retryWait : self.ajaxAddThanksRetryWaitCallback,
1081 					retryNow  : self.ajaxAddThanksRetryNowCallback
1082 				});
1083 		}(jQuery));
1084 	},
1085 
1086 	/**
1087 	 * Change HTML elements before sending AJAX for adding thanks
1088 	 *
1089 	 * @private
1090 	 * @param {string} projectId Project identifier
1091 	 * @return {void}
1092 	 */
1093 	_changeElementsBeforeAddThanksAjaxSend : function(projectId) {
1094 		'use strict';
1095 		// get this object
1096 		var self = this;
1097 		(function($) {
1098 			// get selectors
1099 			var selectorAddThanksReviewMessageSend = $(self.getHTMLSelectorAddThanksReviewMessageSend(projectId));
1100 			var selectorAddThanksPageAboutSend = $(self.getHTMLSelectorAddThanksPageAboutSend(projectId));
1101 			var selectorAddThanksReviewMessageMoreInfoLinkDiv = $(self.getHTMLSelectorAddThanksReviewMessageMoreInfoLinkDiv(projectId));
1102 			var selectorAddThanksPageAboutStatusDiv = $(self.getHTMLSelectorAddThanksPageAboutStatusDiv(projectId));
1103 			var selectorReviewMessageClose = $(self.getHTMLSelectorReviewMessageClose(projectId));
1104 			// show information about sending process
1105 			if (selectorAddThanksReviewMessageSend.length > 0) {
1106 				selectorAddThanksReviewMessageSend.attr('disabled', true);
1107 			}
1108 			if (selectorAddThanksPageAboutSend.length > 0) {
1109 				selectorAddThanksPageAboutSend.attr('disabled', true);
1110 			}
1111 			if (selectorAddThanksReviewMessageMoreInfoLinkDiv.length > 0) {
1112 				selectorAddThanksReviewMessageMoreInfoLinkDiv.html('<em>' + self._valsTextSending + '</em>');
1113 			}
1114 			if (selectorAddThanksPageAboutStatusDiv.length > 0) {
1115 				selectorAddThanksPageAboutStatusDiv.html('<em>' + self._valsTextSending + '</em>');
1116 				selectorAddThanksPageAboutStatusDiv.show();
1117 				$(self.getHTMLSelectorAddThanksPageAboutLoadingDiv(projectId)).show();
1118 			}
1119 			// disable closing review message
1120 			if (selectorReviewMessageClose.length > 0) {
1121 				selectorReviewMessageClose.hide();
1122 				$(self.getHTMLSelectorReviewMessageDiv(projectId)).append('<div id="' + self._getHTMLNameAddThanksReviewMessageLoadingImage(projectId) + '" style="margin-left:5px;margin-bottom:5px;"><img src="' + self._valsImageLoadingUrl + '" alt="" /></div>');
1123 			}
1124 		}(jQuery));
1125 	},
1126 
1127 	/**
1128 	 * Remove of loading image element from review message
1129 	 *
1130 	 * @private
1131 	 * @param {string} projectId Project identifier
1132 	 * @return {void}
1133 	 */
1134 	_removeReviewMessageLoadingImageElement : function(projectId) {
1135 		'use strict';
1136 		// get this object
1137 		var self = this;
1138 		(function($) {
1139 			// remove of loading image element
1140 			if ($(self.getHTMLSelectorAddThanksReviewMessageLoadingImage(projectId)).length > 0) {
1141 				$(self.getHTMLSelectorAddThanksReviewMessageLoadingImage(projectId)).remove();
1142 			}
1143 		}(jQuery));
1144 	},
1145 
1146 	/**
1147 	 * Show close element for review message
1148 	 *
1149 	 * @private
1150 	 * @param {string} projectId Project identifier
1151 	 * @return {void}
1152 	 */
1153 	_showReviewMessageCloseElement : function(projectId) {
1154 		'use strict';
1155 		// get this object
1156 		var self = this;
1157 		(function($) {
1158 			// show close element
1159 			if ($(self.getHTMLSelectorReviewMessageClose(projectId)).length > 0) {
1160 				$(self.getHTMLSelectorReviewMessageClose(projectId)).show();
1161 			}
1162 		}(jQuery));
1163 	}
1164 };
1165 
1166 // initialize
1167 var kocujPLV12aBackendAddThanks = new kocujPLV12aCBackendAddThanks();
1168