[6779] | 1 | /** This file is derived from PopupDiv, developed by Mihai Bazon for |
---|
| 2 | * SamWare.net. Modifications were needed to make it usable in HTMLArea. |
---|
| 3 | * HTMLArea is a free WYSIWYG online HTML editor from InteractiveTools.com. |
---|
| 4 | * |
---|
| 5 | * This file does not function standalone. It is dependent of global functions |
---|
| 6 | * defined in HTMLArea-3.0 (htmlarea.js). |
---|
| 7 | * |
---|
| 8 | * Please see file htmlarea.js for further details. |
---|
| 9 | **/ |
---|
| 10 | |
---|
| 11 | var is_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) && |
---|
| 12 | (navigator.userAgent.toLowerCase().indexOf("opera") == -1) ); |
---|
| 13 | var is_compat = (document.compatMode == "BackCompat"); |
---|
| 14 | |
---|
| 15 | function PopupDiv(editor, titleText, handler, initFunction) { |
---|
| 16 | var self = this; |
---|
| 17 | |
---|
| 18 | this.editor = editor; |
---|
| 19 | this.doc = editor._mdoc; |
---|
| 20 | this.handler = handler; |
---|
| 21 | |
---|
| 22 | var el = this.doc.createElement("div"); |
---|
| 23 | el.className = "content"; |
---|
| 24 | |
---|
| 25 | var popup = this.doc.createElement("div"); |
---|
| 26 | popup.className = "dialog popupdiv"; |
---|
| 27 | this.element = popup; |
---|
| 28 | var s = popup.style; |
---|
| 29 | s.position = "absolute"; |
---|
| 30 | s.left = "0px"; |
---|
| 31 | s.top = "0px"; |
---|
| 32 | |
---|
| 33 | var title = this.doc.createElement("div"); |
---|
| 34 | title.className = "title"; |
---|
| 35 | this.title = title; |
---|
| 36 | popup.appendChild(title); |
---|
| 37 | |
---|
| 38 | HTMLArea._addEvent(title, "mousedown", function(ev) { |
---|
| 39 | self._dragStart(is_ie ? window.event : ev); |
---|
| 40 | }); |
---|
| 41 | |
---|
| 42 | var button = this.doc.createElement("div"); |
---|
| 43 | button.className = "button"; |
---|
| 44 | title.appendChild(button); |
---|
| 45 | button.innerHTML = "×"; |
---|
| 46 | title.appendChild(this.doc.createTextNode(titleText)); |
---|
| 47 | this.titleText = titleText; |
---|
| 48 | |
---|
| 49 | button.onmouseover = function() { |
---|
| 50 | this.className += " button-hilite"; |
---|
| 51 | }; |
---|
| 52 | button.onmouseout = function() { |
---|
| 53 | this.className = this.className.replace(/\s*button-hilite\s*/g, " "); |
---|
| 54 | }; |
---|
| 55 | button.onclick = function() { |
---|
| 56 | this.className = this.className.replace(/\s*button-hilite\s*/g, " "); |
---|
| 57 | self.close(); |
---|
| 58 | }; |
---|
| 59 | |
---|
| 60 | popup.appendChild(el); |
---|
| 61 | this.content = el; |
---|
| 62 | |
---|
| 63 | this.doc.body.appendChild(popup); |
---|
| 64 | |
---|
| 65 | this.dragging = false; |
---|
| 66 | this.onShow = null; |
---|
| 67 | this.onClose = null; |
---|
| 68 | this.modal = false; |
---|
| 69 | |
---|
| 70 | initFunction(this); |
---|
| 71 | }; |
---|
| 72 | |
---|
| 73 | PopupDiv.currentPopup = null; |
---|
| 74 | |
---|
| 75 | PopupDiv.prototype.showAtElement = function(el, mode) { |
---|
| 76 | this.defaultSize(); |
---|
| 77 | var pos, ew, eh; |
---|
| 78 | var popup = this.element; |
---|
| 79 | popup.style.display = "block"; |
---|
| 80 | var w = popup.offsetWidth; |
---|
| 81 | var h = popup.offsetHeight; |
---|
| 82 | popup.style.display = "none"; |
---|
| 83 | if (el != window) { |
---|
| 84 | pos = PopupDiv.getAbsolutePos(el); |
---|
| 85 | ew = el.offsetWidth; |
---|
| 86 | eh = el.offsetHeight; |
---|
| 87 | } else { |
---|
| 88 | pos = {x:0, y:0}; |
---|
| 89 | var size = PopupDiv.getWindowSize(); |
---|
| 90 | ew = size.x; |
---|
| 91 | eh = size.y; |
---|
| 92 | } |
---|
| 93 | var FX = false, FY = false; |
---|
| 94 | if (mode.indexOf("l") != -1) { |
---|
| 95 | pos.x -= w; |
---|
| 96 | FX = true; |
---|
| 97 | } |
---|
| 98 | if (mode.indexOf("r") != -1) { |
---|
| 99 | pos.x += ew; |
---|
| 100 | FX = true; |
---|
| 101 | } |
---|
| 102 | if (mode.indexOf("t") != -1) { |
---|
| 103 | pos.y -= h; |
---|
| 104 | FY = true; |
---|
| 105 | } |
---|
| 106 | if (mode.indexOf("b") != -1) { |
---|
| 107 | pos.y += eh; |
---|
| 108 | FY = true; |
---|
| 109 | } |
---|
| 110 | if (mode.indexOf("c") != -1) { |
---|
| 111 | FX || (pos.x += Math.round((ew - w) / 2)); |
---|
| 112 | FY || (pos.y += Math.round((eh - h) / 2)); |
---|
| 113 | } |
---|
| 114 | this.showAt(pos.x, pos.y); |
---|
| 115 | }; |
---|
| 116 | |
---|
| 117 | PopupDiv.prototype.defaultSize = function() { |
---|
| 118 | var s = this.element.style; |
---|
| 119 | var cs = this.element.currentStyle; |
---|
| 120 | var addX = (is_ie && is_compat) ? (parseInt(cs.borderLeftWidth) + |
---|
| 121 | parseInt(cs.borderRightWidth) + |
---|
| 122 | parseInt(cs.paddingLeft) + |
---|
| 123 | parseInt(cs.paddingRight)) : 0; |
---|
| 124 | var addY = (is_ie && is_compat) ? (parseInt(cs.borderTopWidth) + |
---|
| 125 | parseInt(cs.borderBottomWidth) + |
---|
| 126 | parseInt(cs.paddingTop) + |
---|
| 127 | parseInt(cs.paddingBottom)) : 0; |
---|
| 128 | s.display = "block"; |
---|
| 129 | s.width = (this.content.offsetWidth + addX) + "px"; |
---|
| 130 | s.height = (this.content.offsetHeight + this.title.offsetHeight) + "px"; |
---|
| 131 | s.display = "none"; |
---|
| 132 | }; |
---|
| 133 | |
---|
| 134 | PopupDiv.prototype.showAt = function(x, y) { |
---|
| 135 | this.defaultSize(); |
---|
| 136 | var s = this.element.style; |
---|
| 137 | s.display = "block"; |
---|
| 138 | s.left = x + "px"; |
---|
| 139 | s.top = y + "px"; |
---|
| 140 | this.hideShowCovered(); |
---|
| 141 | |
---|
| 142 | PopupDiv.currentPopup = this; |
---|
| 143 | HTMLArea._addEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup); |
---|
| 144 | HTMLArea._addEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup); |
---|
| 145 | if (is_ie && this.modal) { |
---|
| 146 | this.doc.body.setCapture(false); |
---|
| 147 | this.doc.body.onlosecapture = function() { |
---|
| 148 | (PopupDiv.currentPopup) && (this.doc.body.setCapture(false)); |
---|
| 149 | }; |
---|
| 150 | } |
---|
| 151 | window.event && HTMLArea._stopEvent(window.event); |
---|
| 152 | |
---|
| 153 | if (typeof this.onShow == "function") { |
---|
| 154 | this.onShow(); |
---|
| 155 | } else if (typeof this.onShow == "string") { |
---|
| 156 | eval(this.onShow); |
---|
| 157 | } |
---|
| 158 | |
---|
| 159 | var field = this.element.getElementsByTagName("input")[0]; |
---|
| 160 | if (!field) { |
---|
| 161 | field = this.element.getElementsByTagName("select")[0]; |
---|
| 162 | } |
---|
| 163 | if (!field) { |
---|
| 164 | field = this.element.getElementsByTagName("textarea")[0]; |
---|
| 165 | } |
---|
| 166 | if (field) { |
---|
| 167 | field.focus(); |
---|
| 168 | } |
---|
| 169 | }; |
---|
| 170 | |
---|
| 171 | PopupDiv.prototype.close = function() { |
---|
| 172 | this.element.style.display = "none"; |
---|
| 173 | PopupDiv.currentPopup = null; |
---|
| 174 | this.hideShowCovered(); |
---|
| 175 | HTMLArea._removeEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup); |
---|
| 176 | HTMLArea._removeEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup); |
---|
| 177 | is_ie && this.modal && this.doc.body.releaseCapture(); |
---|
| 178 | if (typeof this.onClose == "function") { |
---|
| 179 | this.onClose(); |
---|
| 180 | } else if (typeof this.onClose == "string") { |
---|
| 181 | eval(this.onClose); |
---|
| 182 | } |
---|
| 183 | this.element.parentNode.removeChild(this.element); |
---|
| 184 | }; |
---|
| 185 | |
---|
| 186 | PopupDiv.prototype.getForm = function() { |
---|
| 187 | var forms = this.content.getElementsByTagName("form"); |
---|
| 188 | return (forms.length > 0) ? forms[0] : null; |
---|
| 189 | }; |
---|
| 190 | |
---|
| 191 | PopupDiv.prototype.callHandler = function() { |
---|
| 192 | var tags = ["input", "textarea", "select"]; |
---|
| 193 | var params = new Object(); |
---|
| 194 | for (var ti in tags) { |
---|
| 195 | var tag = tags[ti]; |
---|
| 196 | var els = this.content.getElementsByTagName(tag); |
---|
| 197 | for (var j = 0; j < els.length; ++j) { |
---|
| 198 | var el = els[j]; |
---|
| 199 | params[el.name] = el.value; |
---|
| 200 | } |
---|
| 201 | } |
---|
| 202 | this.handler(this, params); |
---|
| 203 | return false; |
---|
| 204 | }; |
---|
| 205 | |
---|
| 206 | PopupDiv.getAbsolutePos = function(el) { |
---|
| 207 | var r = { x: el.offsetLeft, y: el.offsetTop }; |
---|
| 208 | if (el.offsetParent) { |
---|
| 209 | var tmp = PopupDiv.getAbsolutePos(el.offsetParent); |
---|
| 210 | r.x += tmp.x; |
---|
| 211 | r.y += tmp.y; |
---|
| 212 | } |
---|
| 213 | return r; |
---|
| 214 | }; |
---|
| 215 | |
---|
| 216 | PopupDiv.getWindowSize = function() { |
---|
| 217 | if (window.innerHeight) { |
---|
| 218 | return { y: window.innerHeight, x: window.innerWidth }; |
---|
| 219 | } |
---|
| 220 | if (this.doc.body.clientHeight) { |
---|
| 221 | return { y: this.doc.body.clientHeight, x: this.doc.body.clientWidth }; |
---|
| 222 | } |
---|
| 223 | return { y: this.doc.documentElement.clientHeight, x: this.doc.documentElement.clientWidth }; |
---|
| 224 | }; |
---|
| 225 | |
---|
| 226 | PopupDiv.prototype.hideShowCovered = function () { |
---|
| 227 | var self = this; |
---|
| 228 | function isContained(el) { |
---|
| 229 | while (el) { |
---|
| 230 | if (el == self.element) { |
---|
| 231 | return true; |
---|
| 232 | } |
---|
| 233 | el = el.parentNode; |
---|
| 234 | } |
---|
| 235 | return false; |
---|
| 236 | }; |
---|
| 237 | var tags = new Array("applet", "select"); |
---|
| 238 | var el = this.element; |
---|
| 239 | |
---|
| 240 | var p = PopupDiv.getAbsolutePos(el); |
---|
| 241 | var EX1 = p.x; |
---|
| 242 | var EX2 = el.offsetWidth + EX1; |
---|
| 243 | var EY1 = p.y; |
---|
| 244 | var EY2 = el.offsetHeight + EY1; |
---|
| 245 | |
---|
| 246 | if (el.style.display == "none") { |
---|
| 247 | EX1 = EX2 = EY1 = EY2 = 0; |
---|
| 248 | } |
---|
| 249 | |
---|
| 250 | for (var k = tags.length; k > 0; ) { |
---|
| 251 | var ar = this.doc.getElementsByTagName(tags[--k]); |
---|
| 252 | var cc = null; |
---|
| 253 | |
---|
| 254 | for (var i = ar.length; i > 0;) { |
---|
| 255 | cc = ar[--i]; |
---|
| 256 | if (isContained(cc)) { |
---|
| 257 | cc.style.visibility = "visible"; |
---|
| 258 | continue; |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | p = PopupDiv.getAbsolutePos(cc); |
---|
| 262 | var CX1 = p.x; |
---|
| 263 | var CX2 = cc.offsetWidth + CX1; |
---|
| 264 | var CY1 = p.y; |
---|
| 265 | var CY2 = cc.offsetHeight + CY1; |
---|
| 266 | |
---|
| 267 | if ((CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { |
---|
| 268 | cc.style.visibility = "visible"; |
---|
| 269 | } else { |
---|
| 270 | cc.style.visibility = "hidden"; |
---|
| 271 | } |
---|
| 272 | } |
---|
| 273 | } |
---|
| 274 | }; |
---|
| 275 | |
---|
| 276 | PopupDiv.prototype._dragStart = function (ev) { |
---|
| 277 | if (this.dragging) { |
---|
| 278 | return false; |
---|
| 279 | } |
---|
| 280 | this.dragging = true; |
---|
| 281 | PopupDiv.currentPopup = this; |
---|
| 282 | var posX = ev.clientX; |
---|
| 283 | var posY = ev.clientY; |
---|
| 284 | if (is_ie) { |
---|
| 285 | posY += this.doc.body.scrollTop; |
---|
| 286 | posX += this.doc.body.scrollLeft; |
---|
| 287 | } else { |
---|
| 288 | posY += window.scrollY; |
---|
| 289 | posX += window.scrollX; |
---|
| 290 | } |
---|
| 291 | var st = this.element.style; |
---|
| 292 | this.xOffs = posX - parseInt(st.left); |
---|
| 293 | this.yOffs = posY - parseInt(st.top); |
---|
| 294 | HTMLArea._addEvent(this.doc, "mousemove", PopupDiv.dragIt); |
---|
| 295 | HTMLArea._addEvent(this.doc, "mouseover", HTMLArea._stopEvent); |
---|
| 296 | HTMLArea._addEvent(this.doc, "mouseup", PopupDiv.dragEnd); |
---|
| 297 | HTMLArea._stopEvent(ev); |
---|
| 298 | }; |
---|
| 299 | |
---|
| 300 | PopupDiv.dragIt = function (ev) { |
---|
| 301 | var popup = PopupDiv.currentPopup; |
---|
| 302 | if (!(popup && popup.dragging)) { |
---|
| 303 | return false; |
---|
| 304 | } |
---|
| 305 | is_ie && (ev = window.event); |
---|
| 306 | var posX = ev.clientX; |
---|
| 307 | var posY = ev.clientY; |
---|
| 308 | if (is_ie) { |
---|
| 309 | posY += this.doc.body.scrollTop; |
---|
| 310 | posX += this.doc.body.scrollLeft; |
---|
| 311 | } else { |
---|
| 312 | posY += window.scrollY; |
---|
| 313 | posX += window.scrollX; |
---|
| 314 | } |
---|
| 315 | popup.hideShowCovered(); |
---|
| 316 | var st = popup.element.style; |
---|
| 317 | st.left = (posX - popup.xOffs) + "px"; |
---|
| 318 | st.top = (posY - popup.yOffs) + "px"; |
---|
| 319 | HTMLArea._stopEvent(ev); |
---|
| 320 | }; |
---|
| 321 | |
---|
| 322 | PopupDiv.dragEnd = function () { |
---|
| 323 | var popup = PopupDiv.currentPopup; |
---|
| 324 | if (!popup) { |
---|
| 325 | return false; |
---|
| 326 | } |
---|
| 327 | popup.dragging = false; |
---|
| 328 | HTMLArea._removeEvent(popup.doc, "mouseup", PopupDiv.dragEnd); |
---|
| 329 | HTMLArea._removeEvent(popup.doc, "mouseover", HTMLArea._stopEvent); |
---|
| 330 | HTMLArea._removeEvent(popup.doc, "mousemove", PopupDiv.dragIt); |
---|
| 331 | popup.hideShowCovered(); |
---|
| 332 | }; |
---|
| 333 | |
---|
| 334 | PopupDiv.checkPopup = function (ev) { |
---|
| 335 | is_ie && (ev = window.event); |
---|
| 336 | var el = is_ie ? ev.srcElement : ev.target; |
---|
| 337 | var cp = PopupDiv.currentPopup; |
---|
| 338 | for (; (el != null) && (el != cp.element); el = el.parentNode); |
---|
| 339 | if (el == null) { |
---|
| 340 | cp.modal || ev.type == "mouseover" || cp.close(); |
---|
| 341 | HTMLArea._stopEvent(ev); |
---|
| 342 | } |
---|
| 343 | }; |
---|
| 344 | |
---|
| 345 | PopupDiv.prototype.addButtons = function() { |
---|
| 346 | var self = this; |
---|
| 347 | var div = this.doc.createElement("div"); |
---|
| 348 | this.content.appendChild(div); |
---|
| 349 | div.className = "buttons"; |
---|
| 350 | for (var i = 0; i < arguments.length; ++i) { |
---|
| 351 | var btn = arguments[i]; |
---|
| 352 | var button = this.doc.createElement("button"); |
---|
| 353 | div.appendChild(button); |
---|
| 354 | button.innerHTML = HTMLArea.I18N.buttons[btn]; |
---|
| 355 | switch (btn) { |
---|
| 356 | case "ok": |
---|
| 357 | button.onclick = function() { |
---|
| 358 | self.callHandler(); |
---|
| 359 | self.close(); |
---|
| 360 | }; |
---|
| 361 | break; |
---|
| 362 | case "cancel": |
---|
| 363 | button.onclick = function() { |
---|
| 364 | self.close(); |
---|
| 365 | }; |
---|
| 366 | break; |
---|
| 367 | } |
---|
| 368 | } |
---|
| 369 | }; |
---|