Passed
Push — master ( b78fd8...b91ed8 )
by Jean-Christophe
02:07
created

JsUtilsAjaxTrait::removeLoader()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 5
c 1
b 0
f 1
nc 3
nop 1
dl 0
loc 8
rs 10
1
<?php
2
namespace Ajax\common\traits;
3
4
use Ajax\service\AjaxTransition;
5
use Ajax\service\JString;
6
use Ajax\service\Javascript;
7
8
/**
9
 *
10
 * @author jc
11
 * @property array $jquery_code_for_compile
12
 * @property array $params
13
 */
14
trait JsUtilsAjaxTrait {
15
16
	protected $ajaxTransition;
17
18
	protected $ajaxLoader = "<div class=\"ui active centered inline text loader\">Loading</div>";
19
20
	abstract public function getUrl($url);
21
22
	abstract public function _add_event($element, $js, $event, $preventDefault = false, $stopPropagation = false, $immediatly = true, $listenerOn = false);
23
24
	abstract public function interval($jsCode, $time, $globalName = null, $immediatly = true);
25
26
	protected function _ajax($method, $url, $responseElement = '', $parameters = []) {
27
		if (isset($this->params['ajax'])) {
28
			extract($this->params['ajax']);
29
		}
30
		extract($parameters);
31
32
		$jsCallback = isset($jsCallback) ? $jsCallback : '';
33
		$retour = $this->_getAjaxUrl($url, $attr);
34
		$originalSelector = $responseElement;
35
		$responseElement = $this->_getResponseElement($responseElement);
36
		$retour .= "var self=this;\n";
37
		$before = isset($before) ? $before : "";
38
		$retour .= $before;
39
		if ($hasLoader === true && JString::isNotNull($responseElement)) {
40
			$this->addLoading($retour, $responseElement, $ajaxLoader);
41
		} elseif ($hasLoader === 'response') {
42
			$this->addResponseLoading($retour, $responseElement, $ajaxLoader);
43
		} elseif ($hasLoader === 'internal-x') {
44
			$this->addLoading($retour, '$(this).closest(".item, .step")', $ajaxLoader);
45
		} elseif ($hasLoader === 'internal') {
46
			$retour .= "\n$(this).addClass('loading');";
47
		} elseif (\is_string($hasLoader)) {
48
			$this->addLoading($retour, $hasLoader, $ajaxLoader);
49
		}
50
		$ajaxParameters = [
51
			"url" => "url",
52
			"method" => "'" . \strtoupper($method) . "'"
53
		];
54
55
		$ajaxParameters["async"] = ($async ? "true" : "false");
56
57
		if (isset($params)) {
58
			$ajaxParameters["data"] = self::_correctParams($params, $parameters);
59
		}
60
		if (isset($headers)) {
61
			$ajaxParameters["headers"] = $headers;
62
		}
63
		if ($csrf) {
64
			$csrf = (is_string($csrf)) ? $csrf : 'csrf-token';
65
			$parameters["beforeSend"] = "jqXHR.setRequestHeader('{$csrf}', $('meta[name=\"{$csrf}\"]').attr('content'));";
66
		}
67
		if (isset($partial)) {
68
			$ajaxParameters["xhr"] = "xhrProvider";
69
			$retour .= "var xhr = $.ajaxSettings.xhr();function xhrProvider() {return xhr;};xhr.onreadystatechange = function (e) { if (3==e.target.readyState){let response=e.target.responseText;" . $partial . ";}; };";
70
		}
71
		$this->createAjaxParameters($ajaxParameters, $parameters);
72
		$retour .= "$.ajax({" . $this->implodeAjaxParameters($ajaxParameters) . "}).done(function( data, textStatus, jqXHR ) {\n";
73
		$retour .= $this->_getOnAjaxDone($responseElement, $jqueryDone, $ajaxTransition, $jsCallback, ($historize ? $originalSelector : null)) . "})";
74
		if (isset($error)) {
75
			$retour .= '.fail(function( jqXHR, textStatus, errorThrown ){' . $error . '})';
76
		}
77
		$retour .= '.always(function( data|jqXHR, textStatus, jqXHR|errorThrown ) {' . ($always ?? '') . $this->removeLoader($hasLoader) . '})';
78
		$retour .= ";\n";
79
		$retour = $this->_addJsCondition($jsCondition, $retour);
80
		if ($immediatly) {
81
			$this->jquery_code_for_compile[] = $retour;
82
		}
83
		return $retour;
84
	}
85
86
	protected function createAjaxParameters(&$original, $parameters) {
87
		$validParameters = [
88
			"contentType" => "%value%",
89
			"dataType" => "'%value%'",
90
			"beforeSend" => "function(jqXHR,settings){%value%}",
91
			"complete" => "function(jqXHR){%value%}",
92
			"processData" => "%value%"
93
		];
94
		foreach ($validParameters as $param => $mask) {
95
			if (isset($parameters[$param])) {
96
				$original[$param] = \str_replace("%value%", $parameters[$param], $mask);
97
			}
98
		}
99
	}
100
101
	protected function implodeAjaxParameters($ajaxParameters) {
102
		$s = '';
103
		foreach ($ajaxParameters as $k => $v) {
104
			if ($s !== '') {
105
				$s .= ',';
106
			}
107
			if (is_array($v)) {
108
				$s .= "'{$k}':{" . self::implodeAjaxParameters($v) . "}";
0 ignored issues
show
Bug Best Practice introduced by
The method Ajax\common\traits\JsUti...implodeAjaxParameters() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
				$s .= "'{$k}':{" . self::/** @scrutinizer ignore-call */ implodeAjaxParameters($v) . "}";
Loading history...
109
			} else {
110
				$s .= "'{$k}':{$v}";
111
			}
112
		}
113
		return $s;
114
	}
115
116
	protected function _addJsCondition($jsCondition, $jsSource) {
117
		if (isset($jsCondition)) {
118
			return "if(" . $jsCondition . "){\n" . $jsSource . "\n}";
119
		}
120
		return $jsSource;
121
	}
122
123
	protected function _getAjaxUrl($url, $attr) {
124
		$url = $this->_correctAjaxUrl($url);
125
		$retour = "url='" . $url . "';";
126
		$slash = "/";
127
		if (JString::endswith($url, "/") === true) {
128
			$slash = "";
129
		}
130
131
		if (JString::isNotNull($attr)) {
132
			if ($attr === "value") {
133
				$retour .= "url=url+'" . $slash . "'+$(this).val();\n";
134
			} elseif ($attr === "html") {
135
				$retour .= "url=url+'" . $slash . "'+$(this).html();\n";
136
			} elseif (\substr($attr, 0, 3) === "js:") {
137
				$retour .= "url=url+'" . $slash . "'+" . \substr($attr, 3) . ";\n";
138
			} elseif ($attr !== null && $attr !== "") {
139
				$retour .= "let elmUrl=$(this).attr('" . $attr . "')||'';";
140
				$retour .= "url=(!/^((http|https|ftp):\/\/)/.test(elmUrl))?url+'" . $slash . "'+elmUrl:elmUrl;\n";
141
			}
142
		}
143
		return $retour;
144
	}
145
146
	protected function onPopstate() {
147
		return "window.onpopstate = function(e){if(e.state){var target=e.state.jqueryDone;$(e.state.selector)[target](e.state.html);}};";
148
	}
149
150
	protected function autoActiveLinks($previousURL = "window.location.href") {
151
		$result = "\nfunction getHref(url) { return \$('a').filter(function(){return \$(this).prop('href') == url; });}";
152
		$result .= "\nvar myurl={$previousURL};if(window._previousURL) getHref(window._previousURL).removeClass('active');getHref(myurl).addClass('active');window._previousURL=myurl;";
153
		return $result;
154
	}
155
156
	protected function _getOnAjaxDone($responseElement, $jqueryDone, $ajaxTransition, $jsCallback, $history = null) {
157
		$retour = "";
158
		$call = null;
159
		if (JString::isNotNull($responseElement)) {
160
			if (isset($ajaxTransition)) {
161
				$call = $this->setAjaxDataCall($ajaxTransition);
162
			} elseif (isset($this->ajaxTransition)) {
163
				$call = $this->ajaxTransition;
164
			}
165
			if (\is_callable($call))
166
				$retour = "\t" . $call($responseElement, $jqueryDone) . ";\n";
167
			else
168
				$retour = "\t{$responseElement}.{$jqueryDone}( data );\n";
169
		}
170
		if (isset($history)) {
171
			if ($this->params["autoActiveLinks"]) {
172
				$retour .= $this->autoActiveLinks("url");
173
			}
174
			$retour .= "\nwindow.history.pushState({'html':data,'selector':" . Javascript::prep_value($history) . ",'jqueryDone':'{$jqueryDone}'},'', url);";
175
		}
176
		$retour .= "\t" . $jsCallback . "\n";
177
		return $retour;
178
	}
179
180
	protected function removeLoader($hasLoader) {
181
		if ($hasLoader === 'internal') {
182
			return "\n$(self).removeClass('loading');";
183
		}
184
		if ($hasLoader === 'internal-x') {
185
			return "\n$(self).children('.ajax-loader').remove();";
186
		}
187
		return "\n$(self).find('.loading').removeClass('loading');";
188
	}
189
190
	protected function _getResponseElement($responseElement) {
191
		if (JString::isNotNull($responseElement)) {
192
			$responseElement = Javascript::prep_jquery_selector($responseElement);
193
		}
194
		return $responseElement;
195
	}
196
197
	protected function _getFormElement($formElement) {
198
		if (JString::isNotNull($formElement)) {
199
			$formElement = Javascript::prep_value($formElement);
200
		}
201
		return $formElement;
202
	}
203
204
	protected function _correctAjaxUrl($url) {
205
		if ($url !== "/" && JString::endsWith($url, "/") === true)
206
			$url = substr($url, 0, strlen($url) - 1);
207
		if (strncmp($url, 'http://', 7) != 0 && strncmp($url, 'https://', 8) != 0) {
208
			$url = $this->getUrl($url);
209
		}
210
		return $url;
211
	}
212
213
	public static function _correctParams($params, $ajaxParameters = []) {
214
		if (JString::isNull($params)) {
215
			return "";
216
		}
217
		if (\preg_match("@^\{.*?\}$@", $params)) {
218
			if (! isset($ajaxParameters['contentType']) || ! JString::contains($ajaxParameters['contentType'], 'json')) {
219
				return '$.param(' . $params . ')';
220
			} else {
221
				return 'JSON.stringify(' . $params . ')';
222
			}
223
		}
224
		return $params;
225
	}
226
227
	public static function _implodeParams($parameters) {
228
		$allParameters = [];
229
		foreach ($parameters as $params) {
230
			if (isset($params))
231
				$allParameters[] = self::_correctParams($params);
232
		}
233
		return \implode("+'&'+", $allParameters);
234
	}
235
236
	protected function addLoading(&$retour, $responseElement, $ajaxLoader = null) {
237
		if (! isset($ajaxLoader)) {
238
			$ajaxLoader = $this->ajaxLoader;
239
		}
240
		$loading_notifier = '<div class="ajax-loader ui active inverted dimmer">' . $ajaxLoader . '</div>';
241
		$retour .= "\t\t{$responseElement}.append('{$loading_notifier}');\n";
242
	}
243
244
	protected function addResponseLoading(&$retour, $responseElement, $ajaxLoader = null) {
245
		if (! isset($ajaxLoader)) {
246
			$ajaxLoader = $this->ajaxLoader;
247
		}
248
		$loading_notifier = '<div class="ajax-loader">' . $ajaxLoader . '</div>';
249
		$retour .= "{$responseElement}.empty();\n";
250
		$retour .= "\t\t{$responseElement}.prepend('{$loading_notifier}');\n";
251
	}
252
253
	protected function setAjaxDataCall($params) {
254
		$result = null;
255
		if (! \is_callable($params)) {
256
			$result = function ($responseElement, $jqueryDone = 'html') use ($params) {
257
				return AjaxTransition::{$params}($responseElement, $jqueryDone);
258
			};
259
		}
260
		return $result;
261
	}
262
263
	protected function setDefaultParameters(&$parameters, $default) {
264
		foreach ($default as $k => $v) {
265
			if (! isset($parameters[$k]))
266
				$parameters[$k] = $v;
267
		}
268
	}
269
270
	public function setAjaxLoader($loader) {
271
		$this->ajaxLoader = $loader;
272
	}
273
274
	/**
275
	 * Performs an ajax GET request
276
	 *
277
	 * @param string $url
278
	 *        	The url of the request
279
	 * @param string $responseElement
280
	 *        	selector of the HTML element displaying the answer
281
	 */
282
	private function _get($url, $responseElement = '', $parameters = []) {
283
		return $this->_ajax('get', $url, $responseElement, $parameters);
284
	}
285
286
	/**
287
	 * Performs an ajax GET request
288
	 *
289
	 * @param string $url
290
	 *        	The url of the request
291
	 * @param string $responseElement
292
	 *        	selector of the HTML element displaying the answer
293
	 * @param array $parameters
294
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
295
	 */
296
	public function get($url, $responseElement = '', $parameters = []) {
297
		$parameters['immediatly'] = true;
298
		return $this->_get($url, $responseElement, $parameters);
299
	}
300
301
	/**
302
	 * Performs an ajax request
303
	 *
304
	 * @param string $method
305
	 *        	The http method (get, post, delete, put, head)
306
	 * @param string $url
307
	 *        	The url of the request
308
	 * @param string $responseElement
309
	 *        	selector of the HTML element displaying the answer
310
	 * @param array $parameters
311
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
312
	 */
313
	public function ajax($method, $url, $responseElement = '', $parameters = []) {
314
		$parameters['immediatly'] = true;
315
		return $this->_ajax($method, $url, $responseElement, $parameters);
316
	}
317
318
	/**
319
	 * Executes an ajax query at regular intervals
320
	 *
321
	 * @param string $method
322
	 *        	The http method (post, get...)
323
	 * @param string $url
324
	 *        	The url of the request
325
	 * @param int $interval
326
	 *        	The interval in milliseconds
327
	 * @param string $globalName
328
	 *        	The interval name, for clear it
329
	 * @param string $responseElement
330
	 * @param array $parameters
331
	 *        	The ajax parameters, default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
332
	 * @param
333
	 *        	$immediatly
334
	 * @return string
335
	 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $immediatly at position 0 could not be parsed: Unknown type name '$immediatly' at position 0 in $immediatly.
Loading history...
336
	public function ajaxInterval($method, $url, $interval, $globalName = null, $responseElement = '', $parameters = [], $immediatly = true) {
337
		return $this->interval($this->ajaxDeferred($method, $url, $responseElement, $parameters), $interval, $globalName, $immediatly);
338
	}
339
340
	/**
341
	 * Performs a deferred ajax request
342
	 *
343
	 * @param string $method
344
	 *        	The http method (get, post, delete, put, head)
345
	 * @param string $url
346
	 *        	The url of the request
347
	 * @param string $responseElement
348
	 *        	selector of the HTML element displaying the answer
349
	 * @param array $parameters
350
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
351
	 */
352
	public function ajaxDeferred($method, $url, $responseElement = '', $parameters = []) {
353
		$parameters['immediatly'] = false;
354
		return $this->_ajax($method, $url, $responseElement, $parameters);
355
	}
356
357
	/**
358
	 * Performs an ajax request and receives the JSON data types by assigning DOM elements with the same name
359
	 *
360
	 * @param string $url
361
	 *        	the request url
362
	 * @param string $method
363
	 *        	Method used
364
	 * @param array $parameters
365
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","context"=>"document","jsCondition"=>NULL,"headers"=>null,"immediatly"=>false,"before"=>null)
366
	 */
367
	private function _json($url, $method = "get", $parameters = []) {
368
		$parameters = \array_merge($parameters, [
369
			"hasLoader" => false
370
		]);
371
		$jsCallback = isset($parameters['jsCallback']) ? $parameters['jsCallback'] : "";
372
		$context = isset($parameters['context']) ? $parameters['context'] : "document";
373
		$retour = "\tdata=($.isPlainObject(data))?data:JSON.parse(data);\t" . $jsCallback . ";" . "\n\tfor(var key in data){" . "if($('#'+key," . $context . ").length){ if($('#'+key," . $context . ").is('[value]')) { $('#'+key," . $context . ").val(data[key]);} else { $('#'+key," . $context . ").html(data[key]); }}};\n";
374
		$retour .= "\t$(document).trigger('jsonReady',[data]);\n";
375
		$parameters["jsCallback"] = $retour;
376
		return $this->_ajax($method, $url, null, $parameters);
377
	}
378
379
	/**
380
	 * Performs an ajax request and receives the JSON data types by assigning DOM elements with the same name
381
	 *
382
	 * @param string $url
383
	 *        	the request url
384
	 * @param string $method
385
	 *        	Method used
386
	 * @param array $parameters
387
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","context"=>"document","jsCondition"=>NULL,"headers"=>null,"immediatly"=>false,"before"=>null)
388
	 */
389
	public function json($url, $method = "get", $parameters = []) {
390
		return $this->_json($url, $method, $parameters);
391
	}
392
393
	/**
394
	 * Makes an ajax request and receives the JSON data types by assigning DOM elements with the same name when $event fired on $element
395
	 *
396
	 * @param string $element
397
	 * @param string $event
398
	 * @param string $url
399
	 *        	the request address
400
	 * @param string $method
401
	 *        	default get
402
	 * @param array $parameters
403
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"jsCallback"=>NULL,"attr"=>"id","params"=>"{}","method"=>"get","immediatly"=>true,"before"=>null,"listenerOn"=>false)
404
	 */
405
	public function jsonOn($event, $element, $url, $method = 'get', $parameters = array()) {
406
		$this->setDefaultParameters($parameters, [
407
			'preventDefault' => true,
408
			'stopPropagation' => true,
409
			'immediatly' => true,
410
			'listenerOn' => false
411
		]);
412
		return $this->_add_event($element, $this->jsonDeferred($url, $method, $parameters), $event, $parameters["preventDefault"], $parameters["stopPropagation"], $parameters["immediatly"], $parameters['listenerOn']);
413
	}
414
415
	/**
416
	 * Prepares an ajax request delayed and receives the JSON data types by assigning DOM elements with the same name
417
	 *
418
	 * @param string $url
419
	 *        	the request url
420
	 * @param string $method
421
	 *        	Method used
422
	 * @param array $parameters
423
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","context"=>"document","jsCondition"=>NULL,"headers"=>null,"immediatly"=>false,"before"=>null)
424
	 */
425
	public function jsonDeferred($url, $method = 'get', $parameters = []) {
426
		$parameters['immediatly'] = false;
427
		return $this->_json($url, $method, $parameters);
428
	}
429
430
	/**
431
	 * Performs an ajax request and receives the JSON array data types by assigning DOM elements with the same name
432
	 *
433
	 * @param string $maskSelector
434
	 * @param string $url
435
	 *        	the request url
436
	 * @param string $method
437
	 *        	Method used, default : get
438
	 * @param array $parameters
439
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","context"=>null,"jsCondition"=>NULL,"headers"=>null,"immediatly"=>false,"rowClass"=>"_json","before"=>null)
440
	 */
441
	private function _jsonArray($maskSelector, $url, $method = 'get', $parameters = []) {
442
		$parameters = \array_merge($parameters, [
443
			"hasLoader" => false
444
		]);
445
		$rowClass = isset($parameters['rowClass']) ? $parameters['rowClass'] : "_json";
446
		$jsCallback = isset($parameters['jsCallback']) ? $parameters['jsCallback'] : "";
447
		$context = isset($parameters['context']) ? $parameters['context'] : null;
448
		if ($context === null) {
449
			$parent = "$('" . $maskSelector . "').parent()";
450
			$newElm = "$('#'+newId)";
451
		} else {
452
			$parent = $context;
453
			$newElm = $context . ".find('#'+newId)";
454
		}
455
		$appendTo = "\t\tnewElm.appendTo(" . $parent . ");\n";
456
		$retour = $parent . ".find('.{$rowClass}').remove();";
457
		$retour .= "\tdata=($.isPlainObject(data)||$.isArray(data))?data:JSON.parse(data);\n$.each(data, function(index, value) {\n" . "\tvar created=false;var maskElm=$('" . $maskSelector . "').first();maskElm.hide();" . "\tvar newId=(maskElm.attr('id') || 'mask')+'-'+index;" . "\tvar newElm=" . $newElm . ";\n" . "\tif(!newElm.length){\n" . "\t\tnewElm=maskElm.clone();
458
		newElm.attr('id',newId);\n;newElm.addClass('{$rowClass}').removeClass('_jsonArrayModel');\nnewElm.find('[id]').each(function(){ var newId=$(this).attr('id')+'-'+index;$(this).attr('id',newId).removeClass('_jsonArrayChecked');});\n";
459
		$retour .= $appendTo;
460
		$retour .= "\t}\n" . "\tfor(var key in value){\n" . "\t\t\tvar html = $('<div />').append($(newElm).clone()).html();\n" . "\t\t\tif(html.indexOf('__'+key+'__')>-1){\n" . "\t\t\t\tcontent=$(html.split('__'+key+'__').join(value[key]));\n" . "\t\t\t\t$(newElm).replaceWith(content);newElm=content;\n" . "\t\t\t}\n" . "\t\tvar sel='[data-id=\"'+key+'\"]';if($(sel,newElm).length){\n" . "\t\t\tvar selElm=$(sel,newElm);\n" . "\t\t\t if(selElm.is('[value]')) { selElm.attr('value',value[key]);selElm.val(value[key]);} else { selElm.html(value[key]); }\n" . "\t\t}\n" . "}\n" . "\t$(newElm).show(true);" . "\n" . "\t$(newElm).removeClass('hide');" . "});\n";
461
		$retour .= "\t$(document).trigger('jsonReady',[data]);\n";
462
		$retour .= "\t" . $jsCallback;
463
		$parameters["jsCallback"] = $retour;
464
		return $this->_ajax($method, $url, null, $parameters);
465
	}
466
467
	/**
468
	 * Performs an ajax request and receives the JSON array data types by assigning DOM elements with the same name
469
	 *
470
	 * @param string $maskSelector
471
	 * @param string $url
472
	 *        	the request url
473
	 * @param string $method
474
	 *        	Method used, default : get
475
	 * @param array $parameters
476
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","context"=>null,"jsCondition"=>NULL,"headers"=>null,"immediatly"=>false,"rowClass"=>"_json","before"=>null)
477
	 */
478
	public function jsonArray($maskSelector, $url, $method = 'get', $parameters = []) {
479
		return $this->_jsonArray($maskSelector, $url, $method, $parameters);
480
	}
481
482
	/**
483
	 * Peforms an ajax request delayed and receives a JSON array data types by copying and assigning them to the DOM elements with the same name
484
	 *
485
	 * @param string $maskSelector
486
	 * @param string $url
487
	 *        	the request url
488
	 * @param string $method
489
	 *        	Method used, default : get
490
	 * @param array $parameters
491
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","context"=>null,"jsCondition"=>NULL,"headers"=>null,"rowClass"=>"_json","before"=>null)
492
	 */
493
	public function jsonArrayDeferred($maskSelector, $url, $method = 'get', $parameters = []) {
494
		$parameters['immediatly'] = false;
495
		return $this->jsonArray($maskSelector, $url, $method, $parameters);
496
	}
497
498
	/**
499
	 * Performs an ajax request and receives the JSON array data types by assigning DOM elements with the same name when $event fired on $element
500
	 *
501
	 * @param string $element
502
	 * @param string $event
503
	 * @param string $url
504
	 *        	the request url
505
	 * @param string $method
506
	 *        	Method used, default : get
507
	 * @param array $parameters
508
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"jsCallback"=>NULL,"attr"=>"id","params"=>"{}","method"=>"get","rowClass"=>"_json","immediatly"=>true,"before"=>null,"listenerOn"=>false)
509
	 */
510
	public function jsonArrayOn($event, $element, $maskSelector, $url, $method = 'get', $parameters = array()) {
511
		$this->setDefaultParameters($parameters, [
512
			'preventDefault' => true,
513
			'stopPropagation' => true,
514
			'immediatly' => true,
515
			'listenerOn' => false
516
		]);
517
		return $this->_add_event($element, $this->jsonArrayDeferred($maskSelector, $url, $method, $parameters), $event, $parameters["preventDefault"], $parameters["stopPropagation"], $parameters["immediatly"], $parameters['listenerOn']);
518
	}
519
520
	/**
521
	 * Prepares a Get ajax request
522
	 * for using on an event
523
	 *
524
	 * @param string $url
525
	 *        	The url of the request
526
	 * @param string $responseElement
527
	 *        	selector of the HTML element displaying the answer
528
	 * @param array $parameters
529
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
530
	 */
531
	public function getDeferred($url, $responseElement = "", $parameters = []) {
532
		$parameters['immediatly'] = false;
533
		return $this->_get($url, $responseElement, $parameters);
534
	}
535
536
	/**
537
	 * Performs a get to $url on the event $event on $element
538
	 * and display it in $responseElement
539
	 *
540
	 * @param string $event
541
	 *        	the event
542
	 * @param string $element
543
	 *        	the element on which event is observed
544
	 * @param string $url
545
	 *        	The url of the request
546
	 * @param string $responseElement
547
	 *        	The selector of the HTML element displaying the answer
548
	 * @param array $parameters
549
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>null,"headers"=>null,"historize"=>false,"before"=>null,"listenerOn"=>false)
550
	 */
551
	public function getOn($event, $element, $url, $responseElement = "", $parameters = array()) {
552
		$parameters['method'] = 'get';
553
		return $this->ajaxOn($event, $element, $url, $responseElement, $parameters);
554
	}
555
556
	/**
557
	 * Performs an ajax request to $url on the event $event on $element
558
	 * and display it in $responseElement
559
	 *
560
	 * @param string $event
561
	 *        	the event observed
562
	 * @param string $element
563
	 *        	the element on which event is observed
564
	 * @param string $url
565
	 *        	The url of the request
566
	 * @param string $responseElement
567
	 *        	The selector of the HTML element displaying the answer
568
	 * @param array $parameters
569
	 *        	default : array("method"=>"get","preventDefault"=>true,"stopPropagation"=>true,"params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null,"listenerOn"=>false)
570
	 */
571
	public function ajaxOn($event, $element, $url, $responseElement = '', $parameters = array()) {
572
		$this->setDefaultParameters($parameters, [
573
			'preventDefault' => true,
574
			'stopPropagation' => true,
575
			'immediatly' => true,
576
			'method' => 'get',
577
			'listenerOn' => false
578
		]);
579
		return $this->_add_event($element, $this->ajaxDeferred($parameters['method'], $url, $responseElement, $parameters), $event, $parameters["preventDefault"], $parameters["stopPropagation"], $parameters["immediatly"], $parameters['listenerOn']);
580
	}
581
582
	/**
583
	 * Performs a get to $url on the click event on $element
584
	 * and display it in $responseElement
585
	 *
586
	 * @param string $element
587
	 *        	the element on which event is observed
588
	 * @param string $url
589
	 *        	The url of the request
590
	 * @param string $responseElement
591
	 *        	The selector of the HTML element displaying the answer
592
	 * @param array $parameters
593
	 *        	default : array("method"=>"get","preventDefault"=>true,"stopPropagation"=>true,"params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null,"listenerOn"=>false)
594
	 */
595
	public function ajaxOnClick($element, $url, $responseElement = '', $parameters = array()) {
596
		return $this->ajaxOn('click', $element, $url, $responseElement, $parameters);
597
	}
598
599
	/**
600
	 * Performs a get to $url on the click event on $element
601
	 * and display it in $responseElement
602
	 *
603
	 * @param string $element
604
	 *        	the element on which click is observed
605
	 * @param string $url
606
	 *        	The url of the request
607
	 * @param string $responseElement
608
	 *        	The selector of the HTML element displaying the answer
609
	 * @param array $parameters
610
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null,"listenerOn"=>false)
611
	 */
612
	public function getOnClick($element, $url, $responseElement = '', $parameters = array()) {
613
		return $this->getOn('click', $element, $url, $responseElement, $parameters);
614
	}
615
616
	/**
617
	 * Uses an hyperlink to make an ajax get request
618
	 *
619
	 * @param string $element
620
	 *        	an hyperlink selector
621
	 * @param string $responseElement
622
	 *        	the target of the ajax request (data-target attribute of the element is used if responseElement is omited)
623
	 * @param array $parameters
624
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"params"=>"{}","jsCallback"=>NULL,"attr"=>"href","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","jsCondition"=>NULL,"headers"=>null,"historize"=>true,"before"=>null,"listenerOn"=>false)
625
	 * @return $this
626
	 */
627
	public function getHref($element, $responseElement = "", $parameters = array()) {
628
		$parameters['attr'] = 'href';
629
		if (JString::isNull($responseElement)) {
630
			$responseElement = '%$(self).attr("data-target")%';
631
		} else {
632
			$responseElement = '%$(self).attr("data-target") || "' . $responseElement . '"%';
633
		}
634
		if (! isset($parameters['historize'])) {
635
			$parameters['historize'] = true;
636
		}
637
		if (! isset($parameters['jsCallback'])) {
638
			$parameters['jsCallback'] = 'var event = jQuery.Event( "getHref" );event.url = url;$(self).trigger(event);';
639
		}
640
		return $this->getOnClick($element, "", $responseElement, $parameters);
641
	}
642
643
	/**
644
	 * Uses an hyperlink to make an ajax get request
645
	 *
646
	 * @param string $element
647
	 *        	an hyperlink selector
648
	 * @param string $responseElement
649
	 *        	the target of the ajax request (data-target attribute of the element is used if responseElement is omited)
650
	 * @param array $parameters
651
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"params"=>"{}","jsCallback"=>NULL,"attr"=>"href","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","jsCondition"=>NULL,"headers"=>null,"historize"=>true,"before"=>null,"listenerOn"=>false)
652
	 * @return $this
653
	 */
654
	public function postHref($element, $responseElement = "", $parameters = array()) {
655
		$parameters['attr'] = 'href';
656
		if (JString::isNull($responseElement)) {
657
			$responseElement = '%$(this).attr("data-target")%';
658
		} else {
659
			$responseElement = '%$(self).attr("data-target") || "' . $responseElement . '"%';
660
		}
661
		if (! isset($parameters['historize'])) {
662
			$parameters['historize'] = true;
663
		}
664
		return $this->postOnClick($element, '', '{}', $responseElement, $parameters);
665
	}
666
667
	/**
668
	 * Uses a form action to make an ajax post request
669
	 *
670
	 * @param string $element
671
	 *        	a form selector
672
	 * @param string $responseElement
673
	 *        	the target of the ajax request (data-target attribute of the element is used if responseElement is omited)
674
	 * @param array $parameters
675
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"params"=>"{}","jsCallback"=>NULL,"attr"=>"href","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","jsCondition"=>NULL,"headers"=>null,"historize"=>true,"before"=>null,"listenerOn"=>false)
676
	 * @return $this
677
	 */
678
	public function postFormAction($element, $responseElement = "", $parameters = array()) {
679
		$parameters['attr'] = 'action';
680
		if (JString::isNull($responseElement)) {
681
			$responseElement = '%$(self).attr("data-target")%';
682
		} else {
683
			$responseElement = '%$(self).attr("data-target") || "' . $responseElement . '"%';
684
		}
685
		$formId = '%$(this).attr("id")%';
686
		if (! isset($parameters['historize'])) {
687
			$parameters['historize'] = true;
688
		}
689
		$parameters['preventDefault'] = true;
690
		if (! isset($parameters['hasLoader'])) {
691
			$parameters['hasLoader'] = '$(self).find("button, input[type=submit], input[type=button]")';
692
		}
693
		if (! isset($parameters['jsCallback'])) {
694
			$parameters['jsCallback'] = 'var event = jQuery.Event( "postFormAction" );event.params = Object.fromEntries(new URLSearchParams(params));$(self).trigger(event);';
695
		}
696
		return $this->postFormOn('submit', $element, '', $formId, $responseElement, $parameters);
697
	}
698
699
	private function _post($url, $params = '{}', $responseElement = '', $parameters = []) {
700
		$parameters['params'] = $params;
701
		return $this->_ajax('POST', $url, $responseElement, $parameters);
702
	}
703
704
	/**
705
	 * Makes an ajax post
706
	 *
707
	 * @param string $url
708
	 *        	the request url
709
	 * @param string $responseElement
710
	 *        	selector of the HTML element displaying the answer
711
	 * @param string $params
712
	 *        	JSON parameters
713
	 * @param array $parameters
714
	 *        	default : array("jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
715
	 */
716
	public function post($url, $params = "{}", $responseElement = "", $parameters = []) {
717
		$parameters['immediatly'] = true;
718
		return $this->_post($url, $params, $responseElement, $parameters);
719
	}
720
721
	/**
722
	 * Prepares a delayed ajax POST
723
	 * to use on an event
724
	 *
725
	 * @param string $url
726
	 *        	the request url
727
	 * @param string $params
728
	 *        	JSON parameters
729
	 * @param string $responseElement
730
	 *        	selector of the HTML element displaying the answer
731
	 * @param array $parameters
732
	 *        	default : array("jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
733
	 */
734
	public function postDeferred($url, $params = "{}", $responseElement = "", $parameters = []) {
735
		$parameters['immediatly'] = false;
736
		return $this->_post($url, $params, $responseElement, $parameters);
737
	}
738
739
	/**
740
	 * Performs a post to $url on the event $event fired on $element and pass the parameters $params
741
	 * Display the result in $responseElement
742
	 *
743
	 * @param string $event
744
	 * @param string $element
745
	 * @param string $url
746
	 *        	The url of the request
747
	 * @param string $params
748
	 *        	The parameters to send
749
	 * @param string $responseElement
750
	 *        	selector of the HTML element displaying the answer
751
	 * @param array $parameters
752
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null,"listenerOn"=>false)
753
	 */
754
	public function postOn($event, $element, $url, $params = "{}", $responseElement = "", $parameters = array()) {
755
		$parameters['method'] = 'post';
756
		$parameters['params'] = $params;
757
		return $this->ajaxOn($event, $element, $url, $responseElement, $parameters);
758
	}
759
760
	/**
761
	 * Performs a post to $url on the click event fired on $element and pass the parameters $params
762
	 * Display the result in $responseElement
763
	 *
764
	 * @param string $element
765
	 * @param string $url
766
	 *        	The url of the request
767
	 * @param string $params
768
	 *        	The parameters to send
769
	 * @param string $responseElement
770
	 *        	selector of the HTML element displaying the answer
771
	 * @param array $parameters
772
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null,"before"=>null,"listenerOn"=>false)
773
	 */
774
	public function postOnClick($element, $url, $params = '{}', $responseElement = '', $parameters = array()) {
775
		return $this->postOn('click', $element, $url, $params, $responseElement, $parameters);
776
	}
777
778
	private function _postForm($url, $form, $responseElement, $parameters = []) {
779
		if (isset($this->params['ajax'])) {
780
			extract($this->params['ajax']);
781
		}
782
		$params = '{}';
783
		$validation = false;
784
		\extract($parameters);
785
		$async = ($async) ? 'true' : 'false';
786
		$jsCallback = isset($jsCallback) ? $jsCallback : "";
787
		$retour = $this->_getAjaxUrl($url, $attr);
788
		$form = $this->_getFormElement($form);
789
		$retour .= "\n$('#'+" . $form . ").trigger('ajaxSubmit');";
790
		if (! isset($contentType) || $contentType != 'false') {
791
			$retour .= "\nvar params=$('#'+" . $form . ").serialize();\n";
792
			if (isset($params)) {
793
				$retour .= "params+='&'+" . self::_correctParams($params) . ";\n";
794
			}
795
		} else {
796
			$retour .= "\nvar params=new FormData($('#'+" . $form . ")[0]);\n";
797
		}
798
		$responseElement = $this->_getResponseElement($responseElement);
799
		$retour .= "var self=this;\n";
800
		$before = isset($before) ? $before : "";
801
		$retour .= $before;
802
		if ($hasLoader === true) {
803
			$this->addLoading($retour, $responseElement, $ajaxLoader);
804
		} elseif ($hasLoader === 'response') {
805
			$this->addResponseLoading($retour, $responseElement, $ajaxLoader);
806
		} elseif ($hasLoader === 'internal-x') {
807
			$this->addLoading($retour, '$(this).closest(".item, .step")', $ajaxLoader);
808
		} elseif ($hasLoader === 'internal') {
809
			$retour .= "\n$(this).addClass('loading');";
810
		} elseif (\is_string($hasLoader)) {
811
			$retour .= "\n$hasLoader.addClass('loading');";
812
		}
813
		$ajaxParameters = [
814
			"url" => "url",
815
			"method" => "'POST'",
816
			"data" => "params",
817
			"async" => $async
818
		];
819
		if (isset($headers)) {
820
			$ajaxParameters["headers"] = $headers;
821
		}
822
		if (isset($partial)) {
823
			$ajaxParameters["xhr"] = "xhrProvider";
824
			$retour .= "var xhr = $.ajaxSettings.xhr();function xhrProvider() {return xhr;};xhr.onreadystatechange = function (e) { if (3==e.target.readyState){let response=e.target.responseText;" . $partial . ";}; };";
825
		}
826
		$this->createAjaxParameters($ajaxParameters, $parameters);
827
		$retour .= "$.ajax({" . $this->implodeAjaxParameters($ajaxParameters) . "}).done(function( data ) {\n";
828
		$retour .= $this->_getOnAjaxDone($responseElement, $jqueryDone, $ajaxTransition, $jsCallback) . "})";
829
		if (isset($error)) {
830
			$retour .= '.fail(function( jqXHR, textStatus, errorThrown ){' . $error . '})';
831
		}
832
		$retour .= '.always(function( data|jqXHR, textStatus, jqXHR|errorThrown ) {' . ($always ?? '') . $this->removeLoader($hasLoader) . '})';
833
		$retour .= ";\n";
834
		if ($validation) {
0 ignored issues
show
introduced by
The condition $validation is always false.
Loading history...
835
			$retour = "$('#'+" . $form . ").validate({submitHandler: function(form) {
836
			" . $retour . "
837
			}});\n";
838
			$retour .= "$('#'+" . $form . ").submit();\n";
839
		}
840
		$retour = $this->_addJsCondition($jsCondition, $retour);
841
		if ($immediatly)
842
			$this->jquery_code_for_compile[] = $retour;
843
		return $retour;
844
	}
845
846
	/**
847
	 * Performs a post form with ajax
848
	 *
849
	 * @param string $url
850
	 *        	The url of the request
851
	 * @param string $form
852
	 *        	The form HTML id
853
	 * @param string $responseElement
854
	 *        	selector of the HTML element displaying the answer
855
	 * @param array $parameters
856
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
857
	 */
858
	public function postForm($url, $form, $responseElement, $parameters = []) {
859
		$parameters['immediatly'] = true;
860
		return $this->_postForm($url, $form, $responseElement, $parameters);
861
	}
862
863
	/**
864
	 * Performs a delayed post form with ajax
865
	 * For use on an event
866
	 *
867
	 * @param string $url
868
	 *        	The url of the request
869
	 * @param string $form
870
	 *        	The form HTML id
871
	 * @param string $responseElement
872
	 *        	selector of the HTML element displaying the answer
873
	 * @param array $parameters
874
	 *        	default : array("params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>NULL,"headers"=>null,"historize"=>false,"before"=>null)
875
	 */
876
	public function postFormDeferred($url, $form, $responseElement, $parameters = []) {
877
		$parameters['immediatly'] = false;
878
		return $this->_postForm($url, $form, $responseElement, $parameters);
879
	}
880
881
	/**
882
	 * Performs a post form with ajax in response to an event $event on $element
883
	 * display the result in $responseElement
884
	 *
885
	 * @param string $event
886
	 * @param string $element
887
	 * @param string $url
888
	 * @param string $form
889
	 * @param string $responseElement
890
	 *        	selector of the HTML element displaying the answer
891
	 * @param array $parameters
892
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"validation"=>false,"params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>null,"headers"=>null,"historize"=>false,"before"=>null,"listenerOn"=>false)
893
	 */
894
	public function postFormOn($event, $element, $url, $form, $responseElement = "", $parameters = array()) {
895
		$this->setDefaultParameters($parameters, [
896
			'preventDefault' => true,
897
			'stopPropagation' => true,
898
			'immediatly' => true,
899
			'listenerOn' => false
900
		]);
901
		return $this->_add_event($element, $this->postFormDeferred($url, $form, $responseElement, $parameters), $event, $parameters["preventDefault"], $parameters["stopPropagation"], $parameters["immediatly"], $parameters['listenerOn']);
902
	}
903
904
	/**
905
	 * Performs a post form with ajax in response to the click event on $element
906
	 * display the result in $responseElement
907
	 *
908
	 * @param string $element
909
	 * @param string $url
910
	 * @param string $form
911
	 * @param string $responseElement
912
	 *        	selector of the HTML element displaying the answer
913
	 * @param array $parameters
914
	 *        	default : array("preventDefault"=>true,"stopPropagation"=>true,"validation"=>false,"params"=>"{}","jsCallback"=>NULL,"attr"=>"id","hasLoader"=>true,"ajaxLoader"=>null,"immediatly"=>true,"jqueryDone"=>"html","ajaxTransition"=>null,"jsCondition"=>null,"headers"=>null,"historize"=>false,"before"=>null,"listenerOn"=>false)
915
	 */
916
	public function postFormOnClick($element, $url, $form, $responseElement = "", $parameters = array()) {
917
		return $this->postFormOn("click", $element, $url, $form, $responseElement, $parameters);
918
	}
919
920
	public function addCsrf($name = 'csrf-token') {
921
		return "
922
		$.ajaxSetup({
923
			beforeSend: function(xhr, settings) {
924
				let csrfSafeMethod=function(method) { return (/^(GET|HEAD|OPTIONS)$/.test(method));};
925
				if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
926
					xhr.setRequestHeader('{$name}', $('meta[name=\"{$name}\"]').attr('content'));
927
				}
928
			}
929
		});";
930
	}
931
}
932