This repository has been archived by the owner on Feb 12, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jquery.alignwith.js
221 lines (220 loc) · 6.69 KB
/
jquery.alignwith.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
/*!
* jQuery alignWith plug-in v1.0.2
* Align two or more elements with each other
*
* @requires jQuery v1.2 or later
*
* Copyright (c) 2009 Gilmore Davidson
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*/
/**
* @param mixed elem - HTML element to align with
* @param string position (optional) - A 1-4 character string defining the points to match on each element
* @param object options (optional) - An options object (see below)
*
*
* Position:
*
* The position string can be 1-4 characters in length, made up of any of the following:
* 'b' = Bottom
* 'c' OR 'm' = Centre/Middle
* 'l' = Left
* 'r' = Right
* 't' = Top
*
* The positioning of the element depends on the length of the position string:
*
* Length = 0 (or missing):
* The centre points of both elements will be aligned.
*
* Length = 1:
* ('c' or 'm') The centre points of both elements will be aligned.
* ('b', 'l', 'r' or 't') The mid points of the defined SIDE will be matched (eg. For 't', the centres of the top edges will be aligned).
*
* Length = 2:
* The defined point on each element will be aligned.
* (eg. 'tl' = top left corner, 'rb' = bottom right corner, 'ml' = Left side mid-point)
*
* Length = 3:
* The first two characters define a point on the element to move.
* the third character defines a side (or the centre point) of the target element.
* (eg. 'tlr' = move the top left corner of the first element to the mid point of the right side on the second element)
*
* Length = 4:
* The first two characters define a point on the element to move.
* The last two characters define a point on the target element.
*
* This option provides the most control over positioning, allowing 81 different point-to-point combinations.
*
*
* Options:
*
* The options object can define some additional parameters:
*
* x: (integer, default 0) X offset, this value is added to the 'left' css property of the moving element.
* y: (integer, default 0) Y offset, this value is added to the 'top' css property of the moving element.
* appendToBody: (boolean, default false) If set to true, the moving element will be appended to the document body in the DOM.
* This is to overcome a situation where the moving element is a child of an element with 'position:relative;' and will not be positioned correctly otherwise.
*
* x and y can also be negative integers.
*
*
* Examples:
*
* Basic usage, only defining the two elements - will match the centres of each element:
*
* jQuery('.moveMe').alignWith('#stayput');
*
* Match the left mid points of each element:
*
* jQuery('.moveMe').alignWith('#stayput', 'l');
*
* Match the top left corners of each element:
*
* jQuery('.moveMe').alignWith('#stayput', 'tl');
*
* Match the top left corner of the moving element with the centre of the static element:
*
* jQuery('.moveMe').alignWith('#stayput', 'tlc');
*
* Match the top left corner of the moving element with the top right corner of the static element:
*
* jQuery('.moveMe').alignWith('#stayput', 'tltr');
*
* Match the top left corner of the moving element with the top right corner of the static element
* and add a 5px x/y offset:
*
* jQuery('.moveMe').alignWith('#stayput', 'tltr', {x:5,y:5});
*
* Match the top left corner of the moving element with the top right corner of the static element
* and append to the document body:
*
* jQuery('.moveMe').alignWith('#stayput', 'tltr', {appendToBody:true});
*
*
* Notes:
*
* alignWith includes element borders and padding in the width and height calculations, but excludes margins.
* This ensures that the entire visible element will be positioned correctly.
*
* Options to exclude borders/padding may come further down the track.
*
* There is a known bug in Internet Explorer where the positioning will be messed up if there's not a valid doctype declaration.
* I'm not going to try to fix this one as an HTML document should have a valid doctype to begin with.
*
*/
(function($){
$.fn.extend({
alignWith: function(elem, pos, options) {
// jQuery-fy elem
elem = $(elem);
// Setup initial position vars for elem
var eOff = elem.offset(),
eX = eOff.left,
eY = eOff.top,
eW = elem.outerWidth(),
eH = elem.outerHeight(),
// Position placeholders
pT = '',
pE = '',
args = [],
// Position matching regex patterns
rXM = /^([tbcm]{2}|lr|rl)$/i,
rXR = /^r?[rtbcm]r?$/i,
rYM = /^([lrcm]{2}|tb|bt)$/i,
rYB = /^b?[lrbcm]b?$/i,
// CSS rules
tCss = {
position: 'absolute',
left: eX,
top: eY
},
// Default options
op = {
x: 0,
y: 0,
appendToBody: false
};
if (undefined !== options) {
$.extend(op, options);
}
// Reset pos if it's invalid
if (!/^[tblrcm]{1,4}$/.test(pos)) {
pos = 'c';
}
// Flesh out 4-point position string
args = pos.split('');
switch (args.length) {
case 1:
pT = pE = '' + pos + pos;
break;
case 2:
pT = pE = pos;
break;
case 3:
pT = '' + args[0] + args[1];
pE = '' + args[2] + args[2];
break;
case 4:
pT = '' + args[0] + args[1];
pE = '' + args[2] + args[3];
break;
}
// Move the elements
return this.each(function(){
// Get dimensions for element to move
var t = $(this),
tX = eX,
tY = eY,
tW = t.outerWidth(),
tH = t.outerHeight();
// Test for X-points of this
if (rXM.test(pT)) {
tX -= (tW / 2);
} else if (rXR.test(pT)) {
tX -= tW;
}
// Test for X-points of elem
if (rXM.test(pE)) {
tX += (eW / 2);
} else if (rXR.test(pE)) {
tX += eW;
}
// Test for Y-points of this
if (rYM.test(pT)) {
tY -= (tH / 2);
} else if (rYB.test(pT)) {
tY -= tH;
}
// Test for Y-points of elem
if (rYM.test(pE)) {
tY += (eH / 2);
} else if (rYB.test(pE)) {
tY += eH;
}
// Account for margins pushing out the position
// Also account for NaN values since IE reads an unset margin as 'auto' instead of '0px'
// (http://plugins.jquery.com/node/10969)
tX -= parseInt(t.css('margin-left'), 10) || 0;
tY -= parseInt(t.css('margin-top'), 10) || 0;
// Add any offset specified in the options
if (0 !== op.x) {
tX += parseInt(op.x, 10);
}
if (0 !== op.y) {
tY += parseInt(op.y, 10);
}
// Apply css rules
tCss.left = tX;
tCss.top = tY;
t.css(tCss);
// Check for attachment option
if (op.appendToBody) {
t.appendTo('body');
}
});
}
});
})(jQuery);