1 | // This is an extension to jQuery UI draggable |
---|
2 | // When dragging move the parent element ("panel") relative to its parent |
---|
3 | // ("viewport") so that the draggable is always visible. |
---|
4 | |
---|
5 | $.ui.plugin.add("draggable", "scrollPanel", { |
---|
6 | drag: function(e, ui) { |
---|
7 | var instance = $(this).data("draggable"); |
---|
8 | clearTimeout( instance.timeout ); |
---|
9 | var o = ui.options, |
---|
10 | element = instance.element, |
---|
11 | panel = o.panel, |
---|
12 | panel_pos = panel.position(), |
---|
13 | panel_w = panel.width(), |
---|
14 | panel_h = panel.height() |
---|
15 | viewport = panel.parent(); |
---|
16 | viewport_w = viewport.width(), |
---|
17 | viewport_h = viewport.height(), |
---|
18 | element_w = element.width(), |
---|
19 | element_h = element.height(), |
---|
20 | moved = false, |
---|
21 | close_dist = 5, |
---|
22 | nudge = 23, |
---|
23 | // Legal panel range |
---|
24 | p_min_x = - ( panel_w - viewport_w ), |
---|
25 | p_min_y = - ( panel_h - viewport_h ), |
---|
26 | p_max_x = 0, |
---|
27 | p_max_y = 0, |
---|
28 | // Visible |
---|
29 | min_vis_x = - panel_pos.left, |
---|
30 | max_vis_x = min_vis_x + viewport_w, |
---|
31 | min_vis_y = - panel_pos.top, |
---|
32 | max_vis_y = min_vis_y + viewport_h, |
---|
33 | // Mouse |
---|
34 | mouse_x = ui.position.left + instance.offset.click.left; |
---|
35 | mouse_y = ui.position.top + instance.offset.click.top; |
---|
36 | // Move it |
---|
37 | if ( ( panel_pos.left < p_max_x ) && ( mouse_x - close_dist < min_vis_x ) ) { |
---|
38 | var t = Math.min( nudge, p_max_x - panel_pos.left ); |
---|
39 | panel.css( "left", panel_pos.left + t ); |
---|
40 | moved = true; |
---|
41 | instance.offset.parent.left += t; |
---|
42 | ui.position.left -= t |
---|
43 | } |
---|
44 | if ( ( ! moved ) && ( panel_pos.left > p_min_x ) && ( mouse_x + close_dist > max_vis_x ) ) { |
---|
45 | var t = Math.min( nudge, panel_pos.left - p_min_x ); |
---|
46 | panel.css( "left", panel_pos.left - t ); |
---|
47 | moved = true; |
---|
48 | instance.offset.parent.left -= t; |
---|
49 | ui.position.left += t; |
---|
50 | } |
---|
51 | if ( ( ! moved ) && ( panel_pos.top < p_max_y ) && ( mouse_y - close_dist < min_vis_y ) ) { |
---|
52 | var t = Math.min( nudge, p_max_y - panel_pos.top ); |
---|
53 | panel.css( "top", panel_pos.top + t ); |
---|
54 | // Firefox sometimes moves by less, so we need to check. Yuck. |
---|
55 | var amount_moved = panel.position().top - panel_pos.top; |
---|
56 | instance.offset.parent.top += amount_moved; |
---|
57 | ui.position.top -= amount_moved; |
---|
58 | moved = true; |
---|
59 | } |
---|
60 | if ( ( ! moved ) && ( panel_pos.top > p_min_y ) && ( mouse_y + close_dist > max_vis_y ) ) { |
---|
61 | var t = Math.min( nudge, panel_pos.top - p_min_x ); |
---|
62 | panel.css( "top", ( panel_pos.top - t ) + "px" ); |
---|
63 | // Firefox sometimes moves by less, so we need to check. Yuck. |
---|
64 | var amount_moved = panel_pos.top - panel.position().top; |
---|
65 | instance.offset.parent.top -= amount_moved; |
---|
66 | ui.position.top += amount_moved; |
---|
67 | moved = true; |
---|
68 | } |
---|
69 | // Still contain in panel |
---|
70 | ui.position.left = Math.max( ui.position.left, 0 ); |
---|
71 | ui.position.top = Math.max( ui.position.top, 0 ); |
---|
72 | ui.position.left = Math.min( ui.position.left, panel_w - element_w ); |
---|
73 | ui.position.top = Math.min( ui.position.top, panel_h - element_h ); |
---|
74 | // Update offsets |
---|
75 | if ( moved ) { |
---|
76 | $.ui.ddmanager.prepareOffsets( instance, e ); |
---|
77 | } |
---|
78 | // Keep moving even if mouse doesn't move |
---|
79 | if ( moved ) { |
---|
80 | instance.old_e = e; |
---|
81 | instance.timeout = setTimeout( function() { instance.mouseMove( e ) }, 50 ); |
---|
82 | } |
---|
83 | }, |
---|
84 | stop: function( e, ui ) { |
---|
85 | var instance = $(this).data("draggable"); |
---|
86 | clearTimeout( instance.timeout ); |
---|
87 | } |
---|
88 | }); |
---|