js/notify/pnotify.nonblock.js   A
last analyzed

Complexity

Total Complexity 40
Complexity/F 2.67

Size

Lines of Code 149
Function Count 15

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
eloc 97
nc 32
dl 0
loc 149
rs 9.2
c 0
b 0
f 0
wmc 40
mnd 4
bc 30
fnc 15
bpm 2
cpm 2.6666
noi 7

1 Function

Rating   Name   Duplication   Size   Complexity  
B pnotify.nonblock.js ➔ ?!? 0 141 1

How to fix   Complexity   

Complexity

Complex classes like js/notify/pnotify.nonblock.js 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.

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.

1
// Nonblock
2
// Uses AMD or browser globals for jQuery.
3
(function (factory) {
4
    if (typeof define === 'function' && define.amd) {
5
        // AMD. Register as a module.
6
        define('pnotify.nonblock', ['jquery', 'pnotify'], factory);
7
    } else {
8
        // Browser globals
9
        factory(jQuery, PNotify);
10
    }
11
}(function($, PNotify){
12
	// Some useful regexes.
13
	var re_on = /^on/,
14
		re_mouse_events = /^(dbl)?click$|^mouse(move|down|up|over|out|enter|leave)$|^contextmenu$/,
15
		re_ui_events = /^(focus|blur|select|change|reset)$|^key(press|down|up)$/,
16
		re_html_events = /^(scroll|resize|(un)?load|abort|error)$/;
17
	// Fire a DOM event.
18
	var dom_event = function(e, orig_e){
19
		var event_object;
20
		e = e.toLowerCase();
21
		if (document.createEvent && this.dispatchEvent) {
22
			// FireFox, Opera, Safari, Chrome
23
			e = e.replace(re_on, '');
24
			if (e.match(re_mouse_events)) {
25
				// This allows the click event to fire on the notice. There is
26
				// probably a much better way to do it.
27
				$(this).offset();
28
				event_object = document.createEvent("MouseEvents");
29
				event_object.initMouseEvent(
30
					e, orig_e.bubbles, orig_e.cancelable, orig_e.view, orig_e.detail,
31
					orig_e.screenX, orig_e.screenY, orig_e.clientX, orig_e.clientY,
32
					orig_e.ctrlKey, orig_e.altKey, orig_e.shiftKey, orig_e.metaKey, orig_e.button, orig_e.relatedTarget
33
				);
34
			} else if (e.match(re_ui_events)) {
35
				event_object = document.createEvent("UIEvents");
36
				event_object.initUIEvent(e, orig_e.bubbles, orig_e.cancelable, orig_e.view, orig_e.detail);
37
			} else if (e.match(re_html_events)) {
38
				event_object = document.createEvent("HTMLEvents");
39
				event_object.initEvent(e, orig_e.bubbles, orig_e.cancelable);
40
			}
41
			if (!event_object) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
42
			this.dispatchEvent(event_object);
43
		} else {
44
			// Internet Explorer
45
			if (!e.match(re_on)) e = "on"+e;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
46
			event_object = document.createEventObject(orig_e);
47
			this.fireEvent(e, event_object);
48
		}
49
	};
50
51
52
	// This keeps track of the last element the mouse was over, so
53
	// mouseleave, mouseenter, etc can be called.
54
	var nonblock_last_elem;
55
	// This is used to pass events through the notice if it is non-blocking.
56
	var nonblock_pass = function(notice, e, e_name){
57
		notice.elem.css("display", "none");
58
		var element_below = document.elementFromPoint(e.clientX, e.clientY);
59
		notice.elem.css("display", "block");
60
		var jelement_below = $(element_below);
61
		var cursor_style = jelement_below.css("cursor");
62
		notice.elem.css("cursor", cursor_style !== "auto" ? cursor_style : "default");
63
		// If the element changed, call mouseenter, mouseleave, etc.
64
		if (!nonblock_last_elem || nonblock_last_elem.get(0) != element_below) {
65
			if (nonblock_last_elem) {
66
				dom_event.call(nonblock_last_elem.get(0), "mouseleave", e.originalEvent);
67
				dom_event.call(nonblock_last_elem.get(0), "mouseout", e.originalEvent);
68
			}
69
			dom_event.call(element_below, "mouseenter", e.originalEvent);
70
			dom_event.call(element_below, "mouseover", e.originalEvent);
71
		}
72
		dom_event.call(element_below, e_name, e.originalEvent);
73
		// Remember the latest element the mouse was over.
74
		nonblock_last_elem = jelement_below;
75
	};
76
77
78
	PNotify.prototype.options.nonblock = {
79
		// Create a non-blocking notice. It lets the user click elements underneath it.
80
		nonblock: false,
81
		// The opacity of the notice (if it's non-blocking) when the mouse is over it.
82
		nonblock_opacity: .2
83
	};
84
	PNotify.prototype.modules.nonblock = {
85
		// This lets us update the options available in the closures.
86
		myOptions: null,
87
88
		init: function(notice, options){
89
			var that = this;
90
			this.myOptions = options;
91
			notice.elem.on({
92
				"mouseenter": function(e){
93
					if (that.myOptions.nonblock) e.stopPropagation();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
94
					if (that.myOptions.nonblock) {
95
						// If it's non-blocking, animate to the other opacity.
96
						notice.elem.stop().animate({"opacity": that.myOptions.nonblock_opacity}, "fast");
97
					}
98
				},
99
				"mouseleave": function(e){
100
					if (that.myOptions.nonblock) e.stopPropagation();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
101
					nonblock_last_elem = null;
102
					notice.elem.css("cursor", "auto");
103
					// Animate back to the normal opacity.
104
					if (that.myOptions.nonblock && notice.animating !== "out")
105
						notice.elem.stop().animate({"opacity": notice.options.opacity}, "fast");
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
106
				},
107
				"mouseover": function(e){
108
					if (that.myOptions.nonblock) e.stopPropagation();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
109
				},
110
				"mouseout": function(e){
111
					if (that.myOptions.nonblock) e.stopPropagation();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
112
				},
113
				"mousemove": function(e){
114
					if (that.myOptions.nonblock) {
115
						e.stopPropagation();
116
						nonblock_pass(notice, e, "onmousemove");
117
					}
118
				},
119
				"mousedown": function(e){
120
					if (that.myOptions.nonblock) {
121
						e.stopPropagation();
122
						e.preventDefault();
123
						nonblock_pass(notice, e, "onmousedown");
124
					}
125
				},
126
				"mouseup": function(e){
127
					if (that.myOptions.nonblock) {
128
						e.stopPropagation();
129
						e.preventDefault();
130
						nonblock_pass(notice, e, "onmouseup");
131
					}
132
				},
133
				"click": function(e){
134
					if (that.myOptions.nonblock) {
135
						e.stopPropagation();
136
						nonblock_pass(notice, e, "onclick");
137
					}
138
				},
139
				"dblclick": function(e){
140
					if (that.myOptions.nonblock) {
141
						e.stopPropagation();
142
						nonblock_pass(notice, e, "ondblclick");
143
					}
144
				}
145
			});
146
		},
147
		update: function(notice, options){
148
			this.myOptions = options;
149
		}
150
	};
151
}));
152