flyout.js
10 KB
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
// ******* Flyout MANAGER ******** //
$axure.internal(function($ax) {
var _flyoutManager = $ax.flyoutManager = {};
var getFlyoutLabel = function(panelId) {
return panelId + '_flyout';
};
var _unregisterPanel = function(panelId, keepShown) {
$ax.geometry.unregister(getFlyoutLabel(panelId));
if(panelToSrc[panelId]) {
$ax.style.RemoveRolloverOverride(panelToSrc[panelId]);
delete panelToSrc[panelId];
}
if(!keepShown) {
$ax.action.addAnimation(panelId, $ax.action.queueTypes.fade, function() {
$ax('#' + panelId).hide();
});
}
};
_flyoutManager.unregisterPanel = _unregisterPanel;
var genPoint = $ax.geometry.genPoint;
var _updateFlyout = function(panelId) {
var label = getFlyoutLabel(panelId);
if(!$ax.geometry.polygonRegistered(label)) return;
var info = $ax.geometry.getPolygonInfo(label);
var rects = info && info.rects;
var targetWidget = $ax.getWidgetInfo(panelId);
rects.target = $ax.geometry.genRect(targetWidget);
// Src will stay the same, just updating
$ax.flyoutManager.registerFlyout(rects, panelId, panelToSrc[panelId]);
if(!$ax.geometry.checkInsideRegion(label)) _unregisterPanel(panelId);
};
_flyoutManager.updateFlyout = _updateFlyout;
var panelToSrc = {};
var _registerFlyout = function(rects, panelId, srcId) {
var label = _getFlyoutLabel(panelId);
var callback = function(info) {
// If leaving object or already outside it, then unregister, otherwise just return
if(!info.exiting && !info.outside) return;
_unregisterPanel(panelId);
};
var points = [];
var lastSrcId = panelToSrc[panelId];
if(lastSrcId != srcId) {
if(lastSrcId) $ax.style.RemoveRolloverOverride(lastSrcId);
if(srcId) {
$ax.style.AddRolloverOverride(srcId);
panelToSrc[panelId] = srcId;
} else delete panelToSrc[panelId];
}
// rects should be one or two rectangles
if(!rects.src) {
var rect = rects.target;
points.push(genPoint(rect.Left(), rect.Top()));
points.push(genPoint(rect.Right(), rect.Top()));
points.push(genPoint(rect.Right(), rect.Bottom()));
points.push(genPoint(rect.Left(), rect.Bottom()));
} else {
var r0 = rects.src;
var r1 = rects.target;
// Right left of right, left right of left, top below top, bottom above bottom
var rlr = r0.Right() <= r1.Right();
var lrl = r0.Left() >= r1.Left();
var tbt = r0.Top() >= r1.Top();
var bab = r0.Bottom() <= r1.Bottom();
var info = { rlr: rlr, lrl: lrl, tbt: tbt, bab: bab };
if((rlr && lrl) || (tbt && bab)) {
points = getSmallPolygon(r0, r1, info);
} else {
points = getLargePolygon(r0, r1, info);
}
}
$ax.geometry.registerPolygon(label, points, callback, { rects: rects });
};
_flyoutManager.registerFlyout = _registerFlyout;
var _getFlyoutLabel = function(panelId) {
return panelId + '_flyout';
};
var _reregisterAllFlyouts = function() {
for(var panelId in panelToSrc) _reregisterFlyout(panelId);
};
_flyoutManager.reregisterAllFlyouts = _reregisterAllFlyouts;
var _reregisterFlyout = function(panelId) {
var rects = $ax.geometry.getPolygonInfo(getFlyoutLabel(panelId)).rects;
_registerFlyout(rects, panelId, panelToSrc[panelId]);
};
// This is the reduced size polygon connecting r0 to r1 by means of horizontal or vertical lines.
var getSmallPolygon = function(r0, r1, info) {
var points = [];
// NOTE: currently I make the assumption that if horizontal/vertical connecting lines from the src hit the target
// Meaning if horizontal, rlr and lrl are true, and if vertical, tbt and bab are true.
var r0Left = r0.Left();
var r0Right = r0.Right();
var r0Top = r0.Top();
var r0Bottom = r0.Bottom();
var r1Left = r1.Left();
var r1Right = r1.Right();
var r1Top = r1.Top();
var r1Bottom = r1.Bottom();
points.push(genPoint(r1Left, r1Top));
if(!info.tbt) {
points.push(genPoint(r0Left, r1Top));
points.push(genPoint(r0Left, r0Top));
points.push(genPoint(r0Right, r0Top));
points.push(genPoint(r0Right, r1Top));
}
points.push(genPoint(r1Right, r1Top));
if(!info.rlr) {
points.push(genPoint(r1Right, r0Top));
points.push(genPoint(r0Right, r0Top));
points.push(genPoint(r0Right, r0Bottom));
points.push(genPoint(r1Right, r0Bottom));
}
points.push(genPoint(r1Right, r1Bottom));
if(!info.bab) {
points.push(genPoint(r0Right, r1Bottom));
points.push(genPoint(r0Right, r0Bottom));
points.push(genPoint(r0Left, r0Bottom));
points.push(genPoint(r0Left, r1Bottom));
}
points.push(genPoint(r1Left, r1Bottom));
if(!info.lrl) {
points.push(genPoint(r1Left, r0Bottom));
points.push(genPoint(r0Left, r0Bottom));
points.push(genPoint(r0Left, r0Top));
points.push(genPoint(r1Left, r0Top));
}
return points;
};
// This is the original algorithm that connects the most extream corners to make polygon
var getLargePolygon = function(r0, r1, info) {
var points = [];
var r0Left = r0.Left();
var r0Right = r0.Right();
var r0Top = r0.Top();
var r0Bottom = r0.Bottom();
var r1Left = r1.Left();
var r1Right = r1.Right();
var r1Top = r1.Top();
var r1Bottom = r1.Bottom();
// Top lefts
if(info.tbt) {
if(!info.lrl) points.push(genPoint(r0Left, r0Top));
points.push(genPoint(r1Left, r1Top));
} else {
if(info.lrl) points.push(genPoint(r1Left, r1Top));
points.push(genPoint(r0Left, r0Top));
}
// Top rights
if(info.tbt) {
points.push(genPoint(r1Right, r1Top));
if(!info.rlr) points.push(genPoint(r0Right, r0Top));
} else {
points.push(genPoint(r0Right, r0Top));
if(info.rlr) points.push(genPoint(r1Right, r1Top));
}
// Bottom rights
if(info.bab) {
if(!info.rlr) points.push(genPoint(r0Right, r0Bottom));
points.push(genPoint(r1Right, r1Bottom));
} else {
if(info.rlr) points.push(genPoint(r1Right, r1Bottom));
points.push(genPoint(r0Right, r0Bottom));
}
// Bottom Lefts
if(info.bab) {
points.push(genPoint(r1Left, r1Bottom));
if(!info.lrl) points.push(genPoint(r0Left, r0Bottom));
} else {
points.push(genPoint(r0Left, r0Bottom));
if(info.lrl) points.push(genPoint(r1Left, r1Bottom));
}
return points;
};
});
// ******* Placeholder Manager ********* //
$axure.internal(function($ax) {
var _placeholderManager = $ax.placeholderManager = {};
var idToPlaceholderInfo = {};
var _registerPlaceholder = function(elementId, text, password) {
idToPlaceholderInfo[elementId] = { text: text, password: password, active: false };
};
_placeholderManager.registerPlaceholder = _registerPlaceholder;
_placeholderManager.refreshPlaceholder = function (elementId) {
var info = idToPlaceholderInfo[elementId];
if (!info || !info.active) return;
$ax.style.SetWidgetPlaceholder(elementId, true, info.text, info.password);
}
var _updatePlaceholder = function(elementId, active, clearText) {
var inputId = $ax.repeater.applySuffixToElementId(elementId, '_input');
var info = idToPlaceholderInfo[elementId];
if(!info || info.active == active) return;
info.active = active;
if(active) var value = info.text;
else if(!ANDROID) value = clearText ? '' : document.getElementById(inputId).value;
else {
var currentText = document.getElementById(inputId).value;
if(!clearText) value = currentText;
else if(currentText == info.text) value = "";
else {
var lastIndex = currentText.lastIndexOf(info.text);
//here i am assuming the text is always inserted in front
value = currentText.substring(0, lastIndex);
}
}
$ax.style.SetWidgetPlaceholder(elementId, active, value, info.password);
};
_placeholderManager.updatePlaceholder = _updatePlaceholder;
var _isActive = function(elementId) {
var info = idToPlaceholderInfo[elementId];
return Boolean(info && info.active);
};
_placeholderManager.isActive = _isActive;
var _selectRange = function(elementId, start, end) {
$jobj(elementId).each(function() {
if(this.setSelectionRange) {
var validTypes = ["text", "search", "url", "tel", "password"];
if(this.tagName.toLowerCase() != "input" || validTypes.indexOf(this.type) > -1) {
this.focus();
this.setSelectionRange(start, end);
}
} else if(this.createTextRange) {
var range = this.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', start);
range.select();
}
});
};
_placeholderManager.selectRange = _selectRange;
var _moveCaret = function(id, index) {
var inputIndex = id.indexOf('_input');
if(inputIndex == -1) return;
var inputId = id.substring(0, inputIndex);
if(!_isActive(inputId)) return;
_selectRange(id, index, index);
};
_placeholderManager.moveCaret = _moveCaret;
});