Completed
Push — master ( f99fed...57dceb )
by Jean-Christophe
03:29
created

Jquery   B

Complexity

Total Complexity 53

Size/Duplication

Total Lines 324
Duplicated Lines 5.86 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
wmc 53
lcom 2
cbo 4
dl 19
loc 324
rs 7.4757
c 0
b 0
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A ui() 0 6 2
A bootstrap() 0 6 2
A semantic() 0 6 2
A __construct() 0 9 3
A inline() 0 7 2
A _open_script() 0 5 2
A _close_script() 0 3 1
A _setAjaxLoader() 0 3 1
A _output() 0 11 3
A _genericCallValue() 11 11 3
A _genericCallElement() 8 8 2
A sortable() 0 13 3
A tablesorter() 0 3 1
B _add_event() 0 18 6
B _compile() 0 28 6
A getScript() 0 6 2
A scriptCount() 0 3 1
A defer() 0 5 1
A _compileLibrary() 0 7 3
A _addToCompile() 0 3 1
A _clear_compile() 0 3 1
A _document_ready() 0 11 3
B minify() 0 24 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Jquery often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Jquery, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Ajax;
4
5
use Ajax\common\traits\JqueryEventsTrait;
6
use Ajax\common\traits\JqueryAjaxTrait;
7
use Ajax\common\traits\JqueryActionsTrait;
8
use Ajax\service\Javascript;
9
10
/**
11
 * jQuery Class
12
 *
13
 * @author jcheron
14
 * @version 1.002
15
 * @license Apache 2 http://www.apache.org/licenses/
16
 **/
17
class Jquery {
18
	use JqueryEventsTrait,JqueryAjaxTrait,JqueryActionsTrait;
19
	protected $_ui;
20
	protected $_bootstrap;
21
	protected $_semantic;
22
	protected $jquery_code_for_compile=array ();
23
	protected $jsUtils;
24
	protected $params;
25
26
	protected $jquery_events=array (
27
			"bind","blur","change","click","dblclick","delegate","die","error","focus","focusin","focusout","hover","keydown","keypress","keyup","live","load","mousedown","mousseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","off","on","one","ready","resize","scroll","select","submit","toggle","trigger","triggerHandler","undind","undelegate","unload"
28
	);
29
30
	public function ui($ui=NULL) {
31
		if ($ui!==NULL) {
32
			$this->_ui=$ui;
33
		}
34
		return $this->_ui;
35
	}
36
37
	public function bootstrap($bootstrap=NULL) {
38
		if ($bootstrap!==NULL) {
39
			$this->_bootstrap=$bootstrap;
40
		}
41
		return $this->_bootstrap;
42
	}
43
44
	public function semantic($semantic=NULL) {
45
		if ($semantic!==NULL) {
46
			$this->_semantic=$semantic;
47
		}
48
		return $this->_semantic;
49
	}
50
51
	public function __construct($params,$jsUtils) {
52
		$this->params=array();
53
		foreach ( $params as $key => $val ) {
54
				$this->params[$key]=$params[$key];
55
		}
56
		$this->jsUtils=$jsUtils;
57
		if(isset($params["ajaxTransition"]))
58
			$this->ajaxTransition=$this->setAjaxDataCall($params["ajaxTransition"]);
59
	}
60
61
	/**
62
	 * Inline
63
	 *
64
	 * Outputs a <script> tag
65
	 *
66
	 * @access public
67
	 * @param string $script
68
	 * @param boolean $cdata a CDATA section should be added
69
	 * @return string
70
	 */
71
	public function inline($script, $cdata=TRUE) {
72
		$str=$this->_open_script();
73
		$str.=($cdata) ? "\n// <![CDATA[\n{$script}\n// ]]>\n" : "\n{$script}\n";
74
		$str.=$this->_close_script();
75
76
		return $str;
77
	}
78
79
	/**
80
	 * Open Script
81
	 *
82
	 * Outputs an opening <script>
83
	 *
84
	 * @access private
85
	 * @param string $src
86
	 * @return string
87
	 */
88
	private function _open_script($src='') {
89
		$str='<script type="text/javascript" ';
90
		$str.=($src=='') ? '>' : ' src="'.$src.'">';
91
		return $str;
92
	}
93
94
	/**
95
	 * Close Script
96
	 *
97
	 * Outputs an closing </script>
98
	 *
99
	 * @param string
100
	 * @return string
101
	 */
102
	private function _close_script($extra="\n") {
103
		return "</script>{$extra}";
104
	}
105
106
	public function _setAjaxLoader($loader) {
107
		$this->ajaxLoader=$loader;
108
	}
109
110
	/**
111
	 * Outputs script directly
112
	 *
113
	 * @param string The element to attach the event to
114
	 * @param string The code to execute
115
	 * @return string
116
	 */
117
	public function _output($array_js='') {
118
		if (!is_array($array_js)) {
119
			$array_js=array (
120
					$array_js
121
			);
122
		}
123
124
		foreach ( $array_js as $js ) {
125
			$this->jquery_code_for_compile[]="\t$js\n";
126
		}
127
	}
128
129
	/**
130
	 * Execute a generic jQuery call with a value.
131
	 * @param string $jQueryCall
132
	 * @param string $element
133
	 * @param string $param
134
	 * @param boolean $immediatly delayed if false
135
	 */
136 View Code Duplication
	public function _genericCallValue($jQueryCall,$element='this', $param="", $immediatly=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
137
		$element=Javascript::prep_element($element);
138
		if (isset($param)) {
139
			$param=Javascript::prep_value($param);
140
			$str="$({$element}).{$jQueryCall}({$param});";
141
		} else
142
			$str="$({$element}).{$jQueryCall}();";
143
			if ($immediatly)
144
				$this->jquery_code_for_compile[]=$str;
145
			return $str;
146
	}
147
	/**
148
	 * Execute a generic jQuery call with 2 elements.
149
	 * @param string $jQueryCall
150
	 * @param string $to
151
	 * @param string $element
152
	 * @param boolean $immediatly delayed if false
153
	 * @return string
154
	 */
155 View Code Duplication
	public function _genericCallElement($jQueryCall,$to='this', $element, $immediatly=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
156
		$to=Javascript::prep_element($to);
157
		$element=Javascript::prep_element($element);
158
		$str="$({$to}).{$jQueryCall}({$element});";
159
		if ($immediatly)
160
			$this->jquery_code_for_compile[]=$str;
161
			return $str;
162
	}
163
164
	/**
165
	 * Creates a jQuery sortable
166
	 *
167
	 * @param string $element
168
	 * @param array $options
169
	 * @return void
170
	 */
171
	public function sortable($element, $options=array()) {
172
		if (count($options)>0) {
173
			$sort_options=array ();
174
			foreach ( $options as $k => $v ) {
175
				$sort_options[]="\n\t\t".$k.': '.$v."";
176
			}
177
			$sort_options=implode(",", $sort_options);
178
		} else {
179
			$sort_options='';
180
		}
181
182
		return "$(".Javascript::prep_element($element).").sortable({".$sort_options."\n\t});";
183
	}
184
185
	/**
186
	 * Table Sorter Plugin
187
	 *
188
	 * @param string $table table name
189
	 * @param string $options plugin location
190
	 * @return string
191
	 */
192
	public function tablesorter($table='', $options='') {
193
		$this->jquery_code_for_compile[]="\t$(".Javascript::prep_element($table).").tablesorter($options);\n";
194
	}
195
196
	/**
197
	 * Constructs the syntax for an event, and adds to into the array for compilation
198
	 *
199
	 * @param string $element The element to attach the event to
200
	 * @param string $js The code to execute
201
	 * @param string $event The event to pass
202
	 * @param boolean $preventDefault If set to true, the default action of the event will not be triggered.
203
	 * @param boolean $stopPropagation Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
204
	 * @return string
205
	 */
206
	public function _add_event($element, $js, $event, $preventDefault=false, $stopPropagation=false,$immediatly=true) {
207
		if (\is_array($js)) {
208
			$js=implode("\n\t\t", $js);
209
		}
210
		if ($preventDefault===true) {
211
			$js=Javascript::$preventDefault.$js;
212
		}
213
		if ($stopPropagation===true) {
214
			$js=Javascript::$stopPropagation.$js;
215
		}
216
		if (array_search($event, $this->jquery_events)===false)
217
			$event="\n\t$(".Javascript::prep_element($element).").bind('{$event}',function(event){\n\t\t{$js}\n\t});\n";
218
		else
219
			$event="\n\t$(".Javascript::prep_element($element).").{$event}(function(event){\n\t\t{$js}\n\t});\n";
220
		if($immediatly)
221
			$this->jquery_code_for_compile[]=$event;
222
		return $event;
223
	}
224
225
	/**
226
	 * As events are specified, they are stored in an array
227
	 * This function compiles them all for output on a page
228
	 * @param view $view
229
	 * @param string $view_var
230
	 * @param boolean $script_tags
231
	 * @return string
232
	 */
233
	public function _compile(&$view=NULL, $view_var='script_foot', $script_tags=TRUE) {
234
		$this->_compileLibrary($this->ui());
235
		$this->_compileLibrary($this->bootstrap());
236
		$this->_compileLibrary($this->semantic());
237
238
		if (\sizeof($this->jquery_code_for_compile)==0) {
239
			return;
240
		}
241
242
		// Inline references
243
		$script='$(document).ready(function() {'."\n";
244
		$script.=implode('', $this->jquery_code_for_compile);
245
		$script.='})';
246
		if($this->params["defer"]){
247
			$script=$this->defer($script);
248
		}
249
		$script.=";";
250
		$this->jquery_code_for_compile=array();
251
		if($this->params["debug"]===false){
252
			$script=$this->minify($script);
253
		}
254
		$output=($script_tags===FALSE) ? $script : $this->inline($script);
255
256
		if ($view!==NULL){
257
			$this->jsUtils->createScriptVariable($view,$view_var, $output);
258
		}
259
		return $output;
260
	}
261
262
	public function getScript($offset=0){
263
		$code=$this->jquery_code_for_compile;
264
		if($offset>0)
265
			$code=\array_slice($code, $offset);
266
		return implode('', $code);
267
	}
268
269
	public function scriptCount(){
270
		return \sizeof($this->jquery_code_for_compile);
271
	}
272
273
	private function defer($script){
274
		$result="window.defer=function (method) {if (window.jQuery) method(); else setTimeout(function() { defer(method) }, 50);};";
275
		$result.="window.defer(function(){".$script."})";
276
		return $result;
277
	}
278
279
	private function _compileLibrary($library){
280
		if ($library!=NULL) {
281
			if ($library->isAutoCompile()) {
282
				$library->compile(true);
283
			}
284
		}
285
	}
286
287
	public function _addToCompile($jsScript) {
288
		$this->jquery_code_for_compile[]=$jsScript;
289
	}
290
291
	/**
292
	 * Clears the array of script events collected for output
293
	 *
294
	 * @return void
295
	 */
296
	public function _clear_compile() {
297
		$this->jquery_code_for_compile=array ();
298
	}
299
300
	/**
301
	 * A wrapper for writing document.ready()
302
	 * @return string
303
	 */
304
	public function _document_ready($js) {
305
		if (!is_array($js)) {
306
			$js=array (
307
					$js
308
			);
309
		}
310
311
		foreach ( $js as $script ) {
312
			$this->jquery_code_for_compile[]=$script;
313
		}
314
	}
315
316
	private function minify($input) {
317
	if(trim($input) === "") return $input;
318
	return preg_replace(
319
			array(
320
					// Remove comment(s)
321
					'#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*\/\*(?!\!|@cc_on)(?>[\s\S]*?\*\/)\s*|\s*(?<![\:\=])\/\/.*(?=[\n\r]|$)|^\s*|\s*$#',
322
					// Remove white-space(s) outside the string and regex
323
					'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/)|\/(?!\/)[^\n\r]*?\/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#s',
324
					// Remove the last semicolon
325
					'#;+\}#',
326
					// Minify object attribute(s) except JSON attribute(s). From `{'foo':'bar'}` to `{foo:'bar'}`
327
					'#([\{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=\:)#i',
328
					// --ibid. From `foo['bar']` to `foo.bar`
329
					'#([a-z0-9_\)\]])\[([\'"])([a-z_][a-z0-9_]*)\2\]#i'
330
			),
331
			array(
332
					'$1',
333
					'$1$2',
334
					'}',
335
					'$1$3',
336
					'$1.$3'
337
			),
338
			$input);
339
	}
340
}
341