JsUtilsAjaxTrait::_ajax()   F
last analyzed

Complexity

Conditions 20
Paths 13824

Size

Total Lines 61
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 13
Bugs 1 Features 5
Metric Value
cc 20
eloc 48
c 13
b 1
f 5
nc 13824
nop 4
dl 0
loc 61
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 .= "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 .= "let xhr = $.ajaxSettings.xhr();function xhrProvider() {return xhr;};xhr.onreadystatechange = function (e) { if (3==e.target.readyState){let response=e.target.responseText;" . $partial . ";}; };";
70
		} elseif (isset($upload)) {
71
			$ajaxParameters["xhr"] = "xhrProvider";
72
			$retour .= 'let xhr = $.ajaxSettings.xhr();function xhrProvider() {return xhr;};xhr.upload.addEventListener("progress", function(event) {if (event.lengthComputable) {' . $upload . '}}, false);';
73
		}
74
		$this->createAjaxParameters($ajaxParameters, $parameters);
75
		$retour .= "$.ajax({" . $this->implodeAjaxParameters($ajaxParameters) . "}).done(function( data, textStatus, jqXHR ) {\n";
76
		$retour .= $this->_getOnAjaxDone($responseElement, $jqueryDone, $ajaxTransition, $jsCallback, ($historize ? $originalSelector : null)) . "})";
77
		if (isset($error)) {
78
			$retour .= '.fail(function( jqXHR, textStatus, errorThrown ){' . $error . '})';
79
		}
80
		$retour .= '.always(function( dataOrjqXHR, textStatus, jqXHROrerrorThrown ) {' . ($always ?? '') . $this->removeLoader($hasLoader) . '})';
81
		$retour .= ";\n";
82
		$retour = $this->_addJsCondition($jsCondition, $retour);
83
		if ($immediatly) {
84
			$this->jquery_code_for_compile[] = $retour;
85
		}
86
		return $retour;
87
	}
88
89
	protected function createAjaxParameters(&$original, $parameters) {
90
		$validParameters = [
91
			"contentType" => "%value%",
92
			"dataType" => "'%value%'",
93
			"beforeSend" => "function(jqXHR,settings){%value%}",
94
			"complete" => "function(jqXHR){%value%}",
95
			"processData" => "%value%"
96
		];
97
		foreach ($validParameters as $param => $mask) {
98
			if (isset($parameters[$param])) {
99
				$original[$param] = \str_replace("%value%", $parameters[$param], $mask);
100
			}
101
		}
102
	}
103
104
	protected function implodeAjaxParameters($ajaxParameters) {
105
		$s = '';
106
		foreach ($ajaxParameters as $k => $v) {
107
			if ($s !== '') {
108
				$s .= ',';
109
			}
110
			if (is_array($v)) {
111
				$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

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