forked from yui/yui3-gallery
/
gallery-stalker.js
158 lines (135 loc) · 3.9 KB
/
gallery-stalker.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
/**
* <p>Stalker plugin will allow you to keep elements at a fixed position "floating" but at
* the same time, keeping those elements embeded to the layout of the page. The general idea
* is that an element can control it's own position within the layout in order to keep its
* area within the viewport boundaries.
*
* <p>To use the Stalker Plugin, simply pass a reference to the plugin to a
* Node instance's <code>plug</code> method.</p>
*
* <p>
* <code>
* <script type="text/javascript"> <br>
* <br>
* // Call the "use" method, passing in "gallery-stalker". This will <br>
* // load the script for the Stalker Plugin and all of <br>
* // the required dependencies. <br>
* <br>
* YUI().use("gallery-stalker", function(Y) { <br>
* <br>
* Y.one('#mytarget').plug(Y.Plugin.Stalker); <br>
* <br>
* }); <br>
* <br>
* </script> <br>
* </code>
* </p>
* @module gallery-stalker
*/
// Util shortcuts
var UA = Y.UA,
getClassName = Y.ClassNameManager.getClassName,
// Frequently used strings
STALKER = "stalker",
HOST = "host",
PX = 'px',
// CSS class names
CLASS_STALKER = getClassName(STALKER),
// Utility functions
/**
* The NodeStalker class is a plugin for a Node instance.The class is used via
* the <a href="Node.html#method_plug"><code>plug</code></a> method of Node and
* should not be instantiated directly.
* @namespace Y.Plugin
* @class NodeStalker
*/
NodeStalker = function() {
NodeStalker.superclass.constructor.apply(this, arguments);
};
NodeStalker.NAME = "NodeStalker";
NodeStalker.NS = STALKER;
NodeStalker.ATTRS = {};
Y.extend(NodeStalker, Y.Plugin.Base, {
// Protected properties
/**
* @property _root
* @description Node instance representing the target node to follow.
* @default null
* @protected
* @type Node
*/
_root: null,
_eventHandlers: [],
// Public methods
initializer: function(config) {
var fn = Y.bind(this.refresh, this);
if ((this._root = this.get(HOST))) {
this._root.addClass(CLASS_STALKER);
// Wire up all event handlers
this._eventHandlers.push(Y.on('scroll', fn));
this._eventHandlers.push(Y.on('windowresize', fn));
}
},
destructor: function() {
if (this._root) {
this._root.removeClass(CLASS_STALKER);
}
Y.Array.each(this._eventHandlers,
function(handle) {
handle.detach();
});
},
/**
* @method refresh
* @description Refreshing the position of the element in every scroll/resize event
* @public
*/
refresh: function() {
Y.log ('Refreshing the target', 'info', STALKER);
var top = Y.DOM.docScrollY(),
left = Y.DOM.docScrollX(),
n = this._root,
r = n.get('parentNode').getXY(),
c = ["marginTop", "marginLeft", "borderLeftWidth", "borderTopWidth"];
// viewport computations
r[1] = Math.max(0, r[1] - top);
r[0] = r[0] - left;
// node size computation
Y.Array.each(c,
function(v) {
r[v] = parseInt(n.getStyle(v), 10) || 0;
});
n.setStyles({
top: r[1] - r.borderTopWidth - r.marginTop,
left: r[0] - r.borderLeftWidth - r.marginLeft,
position: 'fixed'
});
},
// Protected methods
/**
* @method _IE6Fix
* @description Adding a CSS expression to workaround the lack of "position:fixed" in IE6
* @protected
* @return {boolean} whether or not is this fix needed
*/
_IE6Fix: function() {
var targetID,
parentID,
css;
if (UA.ie == 6) {
Y.log('Appliying IE6 fix for static position.', 'info', STALKER);
targetID = this._root.get('id');
parentID = this._root.get('parentNode').get('id');
css = "#" + targetID + " {top:expression((ignore = document.documentElement.scrollTop>document.getElementById('" + parentID + "').offsetTop) ? document.documentElement.scrollTop : document.getElementById('" + parentID + "').offsetTop + 'px' );}";
// adding CSS to the page
Y.on('domready',
function(e) {
Y.log('Inserting IE6 fix in the page: ' + css, 'info', STALKER);
// TODO
});
return true;
}
}
});
Y.namespace('Plugin');
Y.Plugin.NodeStalker = NodeStalker;