forked from cowboy/jquery-outside-events
-
Notifications
You must be signed in to change notification settings - Fork 1
/
jquery.ba-outside-events.js
235 lines (207 loc) · 8.66 KB
/
jquery.ba-outside-events.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*!
* jQuery outside events - v1.1 - 3/16/2010
* http://benalman.com/projects/jquery-outside-events-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
// Script: jQuery outside events
//
// *Version: 1.1, Last updated: 3/16/2010*
//
// Project Home - http://benalman.com/projects/jquery-outside-events-plugin/
// GitHub - http://github.com/cowboy/jquery-outside-events/
// Source - http://github.com/cowboy/jquery-outside-events/raw/master/jquery.ba-outside-events.js
// (Minified) - http://github.com/cowboy/jquery-outside-events/raw/master/jquery.ba-outside-events.min.js (0.9kb)
//
// About: License
//
// Copyright (c) 2010 "Cowboy" Ben Alman,
// Dual licensed under the MIT and GPL licenses.
// http://benalman.com/about/license/
//
// About: Examples
//
// These working examples, complete with fully commented code, illustrate a few
// ways in which this plugin can be used.
//
// clickoutside - http://benalman.com/code/projects/jquery-outside-events/examples/clickoutside/
// dblclickoutside - http://benalman.com/code/projects/jquery-outside-events/examples/dblclickoutside/
// mouseoveroutside - http://benalman.com/code/projects/jquery-outside-events/examples/mouseoveroutside/
// focusoutside - http://benalman.com/code/projects/jquery-outside-events/examples/focusoutside/
//
// About: Support and Testing
//
// Information about what version or versions of jQuery this plugin has been
// tested with, what browsers it has been tested in, and where the unit tests
// reside (so you can test it yourself).
//
// jQuery Versions - 1.4.2
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.1.
// Unit Tests - http://benalman.com/code/projects/jquery-outside-events/unit/
//
// About: Release History
//
// 1.1 - (3/16/2010) Made "clickoutside" plugin more general, resulting in a
// whole new plugin with more than a dozen default "outside" events and
// a method that can be used to add new ones.
// 1.0 - (2/27/2010) Initial release
//
// Topic: Default "outside" events
//
// Note that each "outside" event is powered by an "originating" event. Only
// when the originating event is triggered on an element outside the element
// to which that outside event is bound will the bound event be triggered.
//
// Because each outside event is powered by a separate originating event,
// stopping propagation of that originating event will prevent its related
// outside event from triggering.
//
// OUTSIDE EVENT - ORIGINATING EVENT
// clickoutside - click
// dblclickoutside - dblclick
// focusoutside - focusin
// bluroutside - focusout
// mousemoveoutside - mousemove
// mousedownoutside - mousedown
// mouseupoutside - mouseup
// mouseoveroutside - mouseover
// mouseoutoutside - mouseout
// keydownoutside - keydown
// keypressoutside - keypress
// keyupoutside - keyup
// changeoutside - change
// selectoutside - select
// submitoutside - submit
(function($,doc,outside){
'$:nomunge'; // Used by YUI compressor.
$.map(
// All these events will get an "outside" event counterpart by default.
'click dblclick mousemove mousedown mouseup mouseover mouseout change select submit keydown keypress keyup'.split(' '),
function( event_name ) { jq_addOutsideEvent( event_name ); }
);
// The focus and blur events are really focusin and focusout when it comes
// to delegation, so they are a special case.
jq_addOutsideEvent( 'focusin', 'focus' + outside );
jq_addOutsideEvent( 'focusout', 'blur' + outside );
// Method: jQuery.addOutsideEvent
//
// Register a new "outside" event to be with this method. Adding an outside
// event that already exists will probably blow things up, so check the
// <Default "outside" events> list before trying to add a new one.
//
// Usage:
//
// > jQuery.addOutsideEvent( event_name [, outside_event_name ] );
//
// Arguments:
//
// event_name - (String) The name of the originating event that the new
// "outside" event will be powered by. This event can be a native or
// custom event, as long as it bubbles up the DOM tree.
// outside_event_name - (String) An optional name for the new "outside"
// event. If omitted, the outside event will be named whatever the
// value of `event_name` is plus the "outside" suffix.
//
// Returns:
//
// Nothing.
$.addOutsideEvent = jq_addOutsideEvent;
function jq_addOutsideEvent( event_name, outside_event_name ) {
// The "outside" event name.
outside_event_name = outside_event_name || event_name + outside;
// A jQuery object containing all elements to which the "outside" event is
// bound.
var elems = $(),
// The "originating" event, namespaced for easy unbinding.
event_namespaced = event_name + '.' + outside_event_name + '-special-event';
// Event: outside events
//
// An "outside" event is triggered on an element when its corresponding
// "originating" event is triggered on an element outside the element in
// question. See the <Default "outside" events> list for more information.
//
// Usage:
//
// > jQuery('selector').bind( 'clickoutside', function(event) {
// > var clicked_elem = $(event.target);
// > ...
// > });
//
// > jQuery('selector').bind( 'dblclickoutside', function(event) {
// > var double_clicked_elem = $(event.target);
// > ...
// > });
//
// > jQuery('selector').bind( 'mouseoveroutside', function(event) {
// > var moused_over_elem = $(event.target);
// > ...
// > });
//
// > jQuery('selector').bind( 'focusoutside', function(event) {
// > var focused_elem = $(event.target);
// > ...
// > });
//
// You get the idea, right?
$.event.special[ outside_event_name ] = {
// Called only when the first "outside" event callback is bound per
// element.
setup: function(){
// Add this element to the list of elements to which this "outside"
// event is bound.
elems = elems.add( this );
// If this is the first element getting the event bound, bind a handler
// to document to catch all corresponding "originating" events.
if ( elems.length === 1 ) {
$(doc).bind( event_namespaced, handle_event );
}
},
// Called only when the last "outside" event callback is unbound per
// element.
teardown: function(){
// Remove this element from the list of elements to which this
// "outside" event is bound.
elems = elems.not( this );
// If this is the last element removed, remove the "originating" event
// handler on document that powers this "outside" event.
if ( elems.length === 0 ) {
$(doc).unbind( event_namespaced );
}
},
// Called every time a "outside" event callback is bound to an element.
add: function( handleObj ) {
var old_handler = handleObj.handler;
// This function is executed every time the event is triggered. This is
// used to override the default event.target reference with one that is
// more useful.
handleObj.handler = function( event, elem ) {
// Set the event object's .target property to the element that the
// user interacted with, not the element that the "outside" event was
// was triggered on.
event.target = elem;
// Execute the actual bound handler.
old_handler.apply( this, arguments );
};
}
};
// When the "originating" event is triggered..
function handle_event( event ) {
// Iterate over all elements to which this "outside" event is bound.
$(elems).each(function(){
var elem = $(this);
// If this element isn't the element on which the event was triggered,
// and this element doesn't contain said element, then said element is
// considered to be outside, and the "outside" event will be triggered!
if ( this !== event.target && !elem.has(event.target).length ) {
// Use triggerHandler instead of trigger so that the "outside" event
// doesn't bubble. Pass in the "originating" event's .target so that
// the "outside" event.target can be overridden with something more
// meaningful.
elem.triggerHandler( outside_event_name, [ event.target ] );
}
});
};
};
})(jQuery,document,"outside");