diff options
Diffstat (limited to 'node_modules/labs/rich-text-editor.reel/rich-text-resizer.js')
-rw-r--r-- | node_modules/labs/rich-text-editor.reel/rich-text-resizer.js | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/node_modules/labs/rich-text-editor.reel/rich-text-resizer.js b/node_modules/labs/rich-text-editor.reel/rich-text-resizer.js new file mode 100644 index 00000000..5da834f4 --- /dev/null +++ b/node_modules/labs/rich-text-editor.reel/rich-text-resizer.js | |||
@@ -0,0 +1,349 @@ | |||
1 | /* <copyright> | ||
2 | This file contains proprietary software owned by Motorola Mobility, Inc.<br/> | ||
3 | No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> | ||
4 | (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. | ||
5 | </copyright> */ | ||
6 | /** | ||
7 | @module "montage/ui/rich-text-resizer.js" | ||
8 | @requires montage/core/core | ||
9 | */ | ||
10 | var Montage = require("montage/core/core").Montage, | ||
11 | dom = require("montage/ui/dom"), | ||
12 | Point = require("montage/core/geometry/point").Point; | ||
13 | |||
14 | /** | ||
15 | @class module:"montage/ui/rich-text-resizer.js".Resizer | ||
16 | @extends module:montage/core/core.Montage | ||
17 | */ | ||
18 | exports.Resizer = Montage.create(Montage,/** @lends module:"montage/ui/rich-text-resizer.js".Resizer# */ { | ||
19 | |||
20 | _editor: { | ||
21 | value: null | ||
22 | }, | ||
23 | |||
24 | _element: { | ||
25 | value: null | ||
26 | }, | ||
27 | |||
28 | element: { | ||
29 | get: function() { | ||
30 | return this._element; | ||
31 | } | ||
32 | }, | ||
33 | |||
34 | initialize: { | ||
35 | value: function(editor) { | ||
36 | this._editor = editor; | ||
37 | } | ||
38 | }, | ||
39 | |||
40 | show: { | ||
41 | value: function(element) { | ||
42 | // Remove the current resizer | ||
43 | if (this._element) { | ||
44 | this._removeResizer(element); | ||
45 | } | ||
46 | if (element) { | ||
47 | this._addResizer(element); | ||
48 | } | ||
49 | this._element = element; | ||
50 | } | ||
51 | }, | ||
52 | |||
53 | hide: { | ||
54 | value: function() { | ||
55 | this._removeResizer(this._element); | ||
56 | this._element = null; | ||
57 | } | ||
58 | }, | ||
59 | |||
60 | cleanup: { | ||
61 | value: function(contentNode) { | ||
62 | var cleanContentNode = contentNode, | ||
63 | resizers = contentNode.getElementsByClassName("montage-resizer"), | ||
64 | nbrResizers, | ||
65 | resizer, | ||
66 | i; | ||
67 | |||
68 | if (resizers) { | ||
69 | // We don't want to hide the resizer, just return a copy of the content without the resizer | ||
70 | cleanContentNode = contentNode.cloneNode(true); | ||
71 | resizers = cleanContentNode.getElementsByClassName("montage-resizer"); | ||
72 | nbrResizers = resizers.length; | ||
73 | |||
74 | // Note: We should not have more than one resizer, this is just in case... | ||
75 | for (i = 0; i < nbrResizers; i ++) { | ||
76 | resizer = resizers[0]; | ||
77 | resizer.parentNode.removeChild(resizer); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return cleanContentNode; | ||
82 | } | ||
83 | }, | ||
84 | |||
85 | draw : { | ||
86 | value: function() { | ||
87 | var thisRef = this; | ||
88 | |||
89 | if (this._draggedElement) { | ||
90 | // Resize the resizer frame | ||
91 | var frame = this._draggedElement.parentNode.firstChild, | ||
92 | zero = Point.create().init(0, 0), | ||
93 | framePosition = dom.convertPointFromNodeToPage(frame, zero), | ||
94 | cursor = this._cursorPosition, | ||
95 | direction = this._draggedElement.id.substring("editor-resizer-".length), | ||
96 | info = this._resizerFrameInfo, | ||
97 | ratio = info.ratio, | ||
98 | height = frame.clientHeight, | ||
99 | width = frame.clientWidth, | ||
100 | top = parseFloat(frame.style.top, 10), | ||
101 | left = parseFloat(frame.style.left, 10), | ||
102 | minSize = 15; | ||
103 | |||
104 | element = this._draggedElement.parentNode.previousSibling; | ||
105 | |||
106 | if (direction == "n") { | ||
107 | height += framePosition.y - cursor.y; | ||
108 | top = info.top - (height - info.height); | ||
109 | } else if (direction == "ne") { | ||
110 | height += framePosition.y - cursor.y; | ||
111 | width = Math.round(height * ratio); | ||
112 | if (cursor.x > (framePosition.x + width)) { | ||
113 | width = cursor.x - framePosition.x; | ||
114 | height = Math.round(width / ratio); | ||
115 | } | ||
116 | top = info.top - (height - info.height); | ||
117 | } else if (direction == "e") { | ||
118 | width = cursor.x - framePosition.x; | ||
119 | } else if (direction == "se") { | ||
120 | height = cursor.y - framePosition.y; | ||
121 | width = Math.round(height * ratio); | ||
122 | if (cursor.x > (framePosition.x + width)) { | ||
123 | width = cursor.x - framePosition.x; | ||
124 | height = Math.round(width / ratio); | ||
125 | } | ||
126 | } else if (direction == "s") { | ||
127 | height = cursor.y - framePosition.y; | ||
128 | } else if (direction == "sw") { | ||
129 | height = cursor.y - framePosition.y; | ||
130 | width = Math.round(height * ratio); | ||
131 | if (cursor.x <= framePosition.x - width + frame.clientWidth) { | ||
132 | width = frame.clientWidth + framePosition.x - cursor.x; | ||
133 | height = Math.round(width / ratio); | ||
134 | } | ||
135 | left = info.left - (width - info.width); | ||
136 | } else if (direction == "w") { | ||
137 | width += framePosition.x - cursor.x; | ||
138 | left = info.left - (width - info.width); | ||
139 | } else if (direction == "nw") { | ||
140 | height += framePosition.y - cursor.y; | ||
141 | width = Math.round(height * ratio); | ||
142 | if (cursor.x <= framePosition.x - width + frame.clientWidth) { | ||
143 | width = frame.clientWidth + framePosition.x - cursor.x; | ||
144 | height = Math.round(width / ratio); | ||
145 | } | ||
146 | top = info.top - (height - info.height); | ||
147 | left = info.left - (width - info.width); | ||
148 | } | ||
149 | |||
150 | //set the frame's new height and width | ||
151 | if (height > minSize && width > minSize) { | ||
152 | frame.style.height = height + "px"; | ||
153 | frame.style.width = width + "px"; | ||
154 | frame.style.top = top + "px"; | ||
155 | frame.style.left = left + "px"; | ||
156 | } | ||
157 | |||
158 | if (this._finalizeDrag) { | ||
159 | this._draggedElement.parentNode.classList.remove("dragged"); | ||
160 | delete this._finalizeDrag; | ||
161 | delete this._resizerFrameInfo; | ||
162 | delete this._draggedElement; | ||
163 | |||
164 | // Remove the resizer, we don't wont it in case of undo! | ||
165 | this._removeResizer(element); | ||
166 | |||
167 | // Prevent the editor to try to delete the resizer from now on due to a selection change | ||
168 | this._editor._selectingResizer = true; | ||
169 | |||
170 | // Take the element offline to modify it | ||
171 | var div = document.createElement("div"), | ||
172 | offlineElement, | ||
173 | savedID; | ||
174 | div.innerHTML = element ? element.outerHTML : ""; | ||
175 | offlineElement = div.firstChild; | ||
176 | |||
177 | // Resize the element now that it's offline | ||
178 | offlineElement.width = (width + 1); | ||
179 | offlineElement.height = (height + 1); | ||
180 | offlineElement.style.removeProperty("width"); | ||
181 | offlineElement.style.removeProperty("height"); | ||
182 | |||
183 | savedID = offlineElement.id; | ||
184 | offlineElement.id = "montage-editor-resized-image"; | ||
185 | |||
186 | // Inject the resized element into the contentEditable using execCommand in order to be in the browser undo queue | ||
187 | document.execCommand("inserthtml", false, div.innerHTML); | ||
188 | element = document.getElementById(offlineElement.id); | ||
189 | if (element && savedID !== undefined) { | ||
190 | element.id = savedID; | ||
191 | } | ||
192 | this._element = element; | ||
193 | |||
194 | // Add back the resizer | ||
195 | this._addResizer(element); | ||
196 | |||
197 | // Reset the selection (using the editor's internal | ||
198 | offset = this._editor._nodeOffset(element); | ||
199 | range = document.createRange(); | ||
200 | range.setStart(element.parentNode, offset); | ||
201 | range.setEnd(element.parentNode, offset + 1); | ||
202 | this._editor._selectedRange = range; | ||
203 | |||
204 | // Note: Chrome (and maybe other browsers) will fire 2 selectionchange event asynchronously, to work around it let's use a timer | ||
205 | setTimeout(function() {delete thisRef._editor._selectingResizer;}, 0); | ||
206 | } else { | ||
207 | this._draggedElement.parentNode.classList.add("dragged"); | ||