-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclass.js
150 lines (123 loc) · 4.76 KB
/
class.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
// Class of one drop. Building automatically in the template.
// new Drop(data?: Data)
Drop = function(data) {
if (!(this instanceof Drop))
return new Drop(data);
// Default data
this.data = new Drop.Data();
// Reset data.
this.tick(data);
};
// Default values
Drop._theme = 'DropDefault';
Drop._template = 'DropDefaultTemplate';
Drop._momentum = 'dimentum';
Drop._reinit = ['template', 'theme', 'placement', 'direction', 'layer', 'location', 'arrow'];
// It recalculates the position of drop, and merge old data with new data.
// drop.tick(data?: Data) => Drop
Drop.prototype.tick = function(data) {
if (data) {
lodash.mergeWith(this.data, data, function(dst, src, key) {
if (key in ['instance', 'anchor', '_anchor']) return src;
});
}
// If anchor sended.
if (this.data.anchor) {
// Recalculate anchor coordinates.
this.data._anchor = Drop.coordinates(this.data.anchor, this.data.placement);
// Apply recalculated position to instance.
if (this.data._instance) {
Drop.instances.update(
this.data._instance,
{ $set: this.generateInstance() }
);
}
}
return this;
};
// It shows drop if hidden, and merge old data with new data.
// Need for this.data.anchor field.
// drop.show(data?: Data) => Drop
Drop.prototype.show = function(data) {
if (!this.data.anchor)
throw new Meteor.Error('Anchor is not defined.');
// Reset data.
this.tick(data);
if (!this.data._instance) {
// Pregenerated id for prepare _instances storage.
var _id = Random.id();
Drop._instances[_id] = this;
// Put instance into data context.
this.data._instance = Drop.instances.insert(
lodash.merge({
_id: _id
}, this.generateInstance())
);
if (this.data.parent && this.data.parent._instance) {
Drop.nesting.link.insert(
Drop.instances.findOne(this.data.parent._instance),
Drop.instances.findOne(this.data._instance)
);
}
}
// Reset data.
this.tick(data);
return this;
};
// It hides drop if shown.
// drop.hide() => Drop
Drop.prototype.hide = function() {
if (this.data._instance) {
Drop.instances.remove(this.data._instance);
}
return this;
};
// Construct and return trigger by name of trigger in `Drop.triggers` object.
// drop.trigger(name: String) => Trigger
Drop.prototype.trigger = function(name) {
if (Drop.triggers[name])
return new Drop.triggers[name](this);
}
// Generate instance keys and values.
// Need for this.data._anchor field.
// drop.generateInstance() => Object
Drop.prototype.generateInstance = function() {
var instance = this.data.instance();
var result = {};
// Reactive drop states
lodash.each(Drop._reinit, (key) => {
if (key in this.data) {
result[key] = this.data[key];
if (instance && result[key] != instance[key]) result.prepare = true;
}
});
// Positioning of drop instance without knowledge about size of drop.
// Only one of two axis.
if (this.data.location == 'outside') {
result.directionKey = Drop.invert(result.direction);
result.directionValue = this.data._anchor[result.directionKey] + this.data._anchor[Drop.insize(result.directionKey)];
} else if (this.data.location == 'inside') {
result.directionKey = result.direction;
result.directionValue = this.data._anchor[result.directionKey];
}
// Direction of second axis.
result.additionalKey = Drop.rotate(result.directionKey);
// For example if direction is top then additional is left.
// It is important! On first calling for instance, template is not yet rendered.
// Should be safe to display drop but not show it.
if (this.data._instance) {
// Instance already rendered.
result.positionValue = typeof(this.data.position) == 'number'?this.data.position:0.5;
result.alignmentValue = typeof(this.data.alignment) == 'number'?this.data.alignment:0.5;
result.width = $('[data-templ-drop='+this.data._instance+']').width();
result.height = $('[data-templ-drop='+this.data._instance+']').height();
// Calculate currect drop coordinates seeing position and alignment.
result.additionalValue =
this.data._anchor[result.additionalKey] + (
this.data._anchor[Drop.insize(result.additionalKey)] * result.positionValue
) - (
result[Drop.insize(result.additionalKey)] * result.alignmentValue
);
}
return result;
};