source: gs3-extensions/overlay-notes/trunk/src/PhotoNotes-1.5.js@ 26826

Last change on this file since 26826 was 26826, checked in by davidb, 11 years ago

Javascript and CSS files that provide overlay/photo notes. Originally developed for the Pei Jones collection

File size: 28.5 KB
Line 
1/*
2Copyright (c) 2006 Dusty Davidson - http://www.dustyd.net
3(portions Copyright (c) 2005 Angus Turnbull http://www.twinhelix.come)
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the "Software"),
7to deal in the Software without restriction, including without limitation
8the rights to use, copy, modify, merge, publish, distribute, sublicense,
9and/or sell copies of the Software, and to permit persons to whom the Software
10is furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
20IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21*/
22
23
24
25/*********************************************************/
26/*** Photo Notes Container *******************************/
27/*********************************************************/
28
29// Modified version derived from:
30// http://www.takaitra.com/files/photonotes-1.5.zip
31//
32
33function PhotoNoteContainer(id, config)
34{
35 var element = document.getElementById(id);
36
37 var props = {
38 id: id,
39 element: element,
40 dragresize: null,
41 notes: new Array(),
42 editing: false
43 };
44
45 for (var p in props)
46 {
47 this[p] = (!config || typeof config[p] == 'undefined') ? props[p] : config[p];
48 }
49
50};
51
52PhotoNoteContainer.prototype.DeleteNote = function(note)
53{
54 note.UnSelect();
55
56 /* remove from the DOM */
57 this.element.removeChild(note.gui.ElementRect);
58 this.element.removeChild(note.gui.ElementNote);
59
60 /* remove from the array... */
61 //this.notes.remove2(note);
62 removeFromArray(this.notes,note);
63}
64
65PhotoNoteContainer.prototype.AddNote = function(note)
66{
67 if(!this.editing)
68 {
69 /* add the note to the array of notes, and set its container */
70 this.notes[this.notes.length] = note;
71 note.container = this;
72
73 /* add the note to the DOM */
74 this.element.appendChild(note.gui.ElementRect);
75 this.element.appendChild(note.gui.ElementNote);
76 }
77};
78
79/* hide all of the "text" parts of the notes. Primarily called when hovering a note, at which
80 point we want to hide all of the other note texts */
81PhotoNoteContainer.prototype.HideAllNoteTexts = function()
82{
83 for (var i = 0;i<this.notes.length;i++)
84 this.notes[i].HideNoteText();
85};
86
87
88PhotoNoteContainer.prototype.DisableAllNotes = function()
89{
90 for (var i = 0;i<this.notes.length;i++)
91 this.notes[i].DisableNote();
92};
93
94PhotoNoteContainer.prototype.HideAllNotes = function()
95{
96 for (var i = 0;i<this.notes.length;i++)
97 this.notes[i].HideNote();
98};
99
100PhotoNoteContainer.prototype.ShowAllNotes = function()
101{
102 for (var i = 0;i<this.notes.length;i++)
103 this.notes[i].ShowNote();
104};
105
106PhotoNoteContainer.prototype.EnableAllNotes = function()
107{
108 for (var i = 0;i<this.notes.length;i++)
109 this.notes[i].EnableNote();
110};
111
112/*** Photo Note ******************************************/
113
114function PhotoNote(text,containerId,id,rect)
115{
116 var props = {
117 text: text,
118 containerId: containerId,
119 id: id,
120 rect: rect,
121 selected: false,
122 container: null,
123 dragresize: null,
124 oldRect: null,
125 YOffset: 10,
126 XOffset: 0,
127 onsave: null,
128 ondelete: null,
129 gui: null
130
131 };
132
133 for (var p in props)
134 {
135 this[p] = props[p];
136 }
137
138 this.CreateElements();
139}
140
141PhotoNote.prototype.Select = function()
142{
143 //window.status = 'container: ' + this.container;
144 if(!this.container.editing)
145 {
146 this.ShowNoteText();
147 this.dragresize.select(this.gui.ElementRect);
148 this.selected = true;
149 this.SetEditable(true);
150 }
151}
152
153PhotoNote.prototype.UnSelect = function()
154{
155 this.dragresize.deselect(false);
156 this.selected = false;
157 this.SetEditable(false);
158 this.HideNoteText();
159}
160
161PhotoNote.prototype.Save = function()
162{
163 this.oldRect = null;
164 this.gui.TextTitle.innerHTML = this.gui.TextBox.value;
165 this.text = this.gui.TextBox.value
166 this.UnSelect();
167}
168
169PhotoNote.prototype.Cancel = function()
170{
171 //if the note is still new, then we actually want to delete it, not cancel it..
172 if(this.id < 0)
173 {
174 this.container.DeleteNote(this)
175 }
176 else
177 {
178 //reset the node to it's old position
179 if(this.oldRect != null)
180 {
181 this.rect = this.oldRect;
182 }
183 this.oldRect = null;
184 this.gui.TextBox.value = this.text;
185 this.PositionNote();
186 this.UnSelect();
187 }
188}
189
190PhotoNote.prototype.ShowNoteText = function()
191{
192 if(!this.container.editing)
193 {
194 this.container.HideAllNoteTexts();
195 this.container.DisableAllNotes();
196 this.EnableNote();
197
198 this.gui.ElementNote.style.display='block';
199 if(BrowserDetect.browser == 'Explorer')
200 {
201 this.gui.ElementRect.firstChild.filters.alpha.opacity = '85';
202 this.gui.ElementRect.firstChild.firstChild.filters.alpha.opacity = '85';
203 } else {
204 this.gui.ElementRect.firstChild.firstChild.style.opacity = '.85';
205 this.gui.ElementRect.firstChild.style.opacity = '.85';
206 }
207
208 }
209}
210
211PhotoNote.prototype.DisableNote = function ()
212{
213 this.dragresize.enabled=false;
214}
215
216PhotoNote.prototype.EnableNote = function ()
217{
218 this.dragresize.enabled=true;
219}
220
221PhotoNote.prototype.HideNoteText = function ()
222{
223 this.gui.ElementNote.style.display='none';
224 if(BrowserDetect.browser == 'Explorer')
225 {
226 this.gui.ElementRect.firstChild.firstChild.filters.alpha.opacity = '40';
227 this.gui.ElementRect.firstChild.filters.alpha.opacity = '40';
228 } else {
229 this.gui.ElementRect.firstChild.style.opacity = '0.4';
230 this.gui.ElementRect.firstChild.firstChild.style.opacity = '0.4';
231 }
232}
233
234PhotoNote.prototype.HideNote = function ()
235{
236 this.gui.ElementRect.style.display='none';
237 this.gui.ElementNote.style.display='none';
238}
239
240PhotoNote.prototype.ShowNote = function ()
241{
242 this.gui.ElementRect.style.display='block';
243 this.gui.ElementNote.style.display='none';
244}
245
246PhotoNote.prototype.SetEditable = function(editable)
247{
248 this.container.editing = editable;
249
250 if(editable)
251 {
252 //the first child of the note is the text
253 this.gui.TextTitle.style.display = 'none';
254
255 //the second child is the edit area...
256 this.gui.EditArea.style.display = 'block';
257
258 //if this is a "new" note, then hide the delete button
259 if(this.id <= 0)
260 this.gui.DeleteButton.style.display = 'none';
261 else
262 this.gui.DeleteButton.style.display = '';
263
264 // get the textarea and select the text...
265 this.HighlightTextbox();
266 }
267 else
268 {
269 //the first child of the note is the text
270 this.gui.TextTitle.style.display = 'block';
271
272 //the second child is the edit area...
273 this.gui.EditArea.style.display = 'none';
274 }
275}
276
277PhotoNote.prototype.HighlightTextbox = function ()
278{
279 // get the textarea and select the text...
280 if(this.gui.EditArea.style.display=='block')
281 {
282 var textfield = this.gui.TextBox;
283 setTimeout(function() {
284 try
285 {
286 textfield.focus();
287 //textfield.select();
288 }
289 catch(e) {}
290 }, 200);
291 }
292
293}
294
295PhotoNote.prototype.CreateElements = function()
296{
297 this.gui = new PhotoNoteGUI();
298
299 var newArea = document.createElement('div');
300 this.dragresize = new DragResize(this.containerId,'dragresize', { allowBlur: false });
301 newArea.className = 'fn-area';
302 newArea.id = 'fn-area-new';
303
304 var newAreaBlack = document.createElement('div');
305 newAreaBlack.className = 'fn-area-blackborder';
306 var newAreaWhite = document.createElement('div');
307 newAreaWhite.className = 'fn-area-whiteborder';
308
309 var currentNote = this;
310
311 var newAreaInner = document.createElement('div');
312 newAreaInner.className = 'fn-area-inner';
313 newAreaWhite.appendChild(newAreaInner);
314
315 //attach mouse events to this element...
316 _PN_addEvent(newAreaInner, 'mouseover', function() {
317 currentNote.ShowNoteText();
318 });
319 _PN_addEvent(newAreaInner, 'mouseout', function() {
320
321 if(!currentNote.selected)
322 {
323 setTimeout(function () {
324 currentNote.HideNoteText();
325 }, 250);
326
327 }
328 });
329
330 _PN_addEvent(newAreaInner, 'mousedown', function() {
331 if(!currentNote.selected)
332 {
333 //window.status = 'mouseDown2!';
334 currentNote.Select();
335 }
336 });
337
338 newAreaBlack.appendChild(newAreaWhite);
339 newArea.appendChild(newAreaBlack);
340
341 // add the notes area
342 var noteArea = document.createElement('div');
343 noteArea.className = 'fn-note';
344 noteArea.onmouseover = function(){_zoomEnabled = false;};
345 noteArea.onmouseout = function(){_zoomEnabled = true;};
346 var titleArea = document.createElement('div');
347 titleArea.className = 'fn-note-text';
348 var t = document.createTextNode(this.text);
349 titleArea.appendChild(t);
350 noteArea.appendChild(titleArea);
351
352 var editArea = document.createElement('div');
353 editArea.className = 'fn-note-edit';
354
355 var editAreaText = document.createElement('div');
356 editAreaText.className = 'fn-note-edit-text';
357
358 var newTextbox = document.createElement('textarea');
359 newTextbox.value = this.text;
360 editAreaText.appendChild(newTextbox);
361 editArea.appendChild(editAreaText);
362
363 var buttonsDiv = document.createElement('div');
364 buttonsDiv.setAttribute("class", "annotator-editor");
365
366 var newButtonOK = document.createElement('a');
367 newButtonOK.setAttribute("class", "annotator-save annotator-inline");
368 newButtonOK.innerHTML='Save';
369 newButtonOK.onmouseover = function(){_zoomEnabled = false;};
370 newButtonOK.onmouseout = function(){_zoomEnabled = true;};
371 newButtonOK.onclick = function() {
372 if(currentNote.onsave)
373 {
374 currentNote.text = newTextbox.value;
375 var res = currentNote.onsave(currentNote);
376 if(res > 0)
377 {
378 //window.status = '';
379 currentNote.id = res;
380 currentNote.Save();
381 }
382 else
383 {
384 alert("error saving note");
385 currentNote.Cancel();
386 }
387 }
388 else
389 {
390 alert("onsave must be implemented in order to *actually* save");
391 currentNote.Cancel();
392 }
393 };
394 buttonsDiv.appendChild(newButtonOK);
395
396 var newButtonCancel = document.createElement('a');
397 newButtonCancel.setAttribute("class", "annotator-cancel annotator-inline");
398 newButtonCancel.innerHTML='Cancel';
399 newButtonCancel.onmouseover = function(){_zoomEnabled = false;};
400 newButtonCancel.onmouseout = function(){_zoomEnabled = true;};
401 newButtonCancel.onclick = function() {
402 currentNote.Cancel();
403 };
404 buttonsDiv.appendChild(newButtonCancel);
405
406 var newButtonDelete = document.createElement('a');
407 newButtonDelete.setAttribute("class", "annotator-cancel annotator-inline");
408 newButtonDelete.innerHTML='Delete';
409 newButtonDelete.onmouseover = function(){_zoomEnabled = false;};
410 newButtonDelete.onmouseout = function(){_zoomEnabled = true;};
411 newButtonDelete.onclick = function() {
412
413 if(currentNote.ondelete)
414 {
415 var res = currentNote.ondelete(currentNote);
416 if(res)
417 {
418 currentNote.container.DeleteNote(currentNote);
419 }
420 else
421 {
422 alert("error deleting note");
423 }
424 }
425 else
426 {
427 alert("ondelete must be implemented in order to *actually* delete");
428 }
429 setTimeout(function(){_zoomEnabled = true;}, 100);
430 };
431 buttonsDiv.appendChild(newButtonDelete);
432
433 editArea.appendChild(buttonsDiv);
434 noteArea.appendChild(editArea);
435
436 this.buttonsDiv = buttonsDiv;
437 this.editArea = editArea;
438 this.noteArea = noteArea;
439
440 /********* DRAG & RESIZE EVENTS **********************/
441 this.dragresize.isElement = function(elm)
442 {
443 if(elm.className == 'fn-area')
444 {
445 this.maxRight = currentNote.container.element.offsetWidth;
446 this.maxBottom = currentNote.container.element.offsetHeight + $("#"+this.containerId).position().top - 3;
447 return true;
448 }
449 };
450 this.dragresize.isHandle = function(elm)
451 {
452 if(elm.className == 'fn-area')
453 return true;
454 };
455 this.dragresize.ondragfocus = function()
456 {
457 currentNote.gui.ElementRect.style.cursor = 'move';
458 };
459 this.dragresize.ondragblur = function()
460 {
461 currentNote.gui.ElementRect.style.cursor = 'pointer';
462 };
463 this.dragresize.ondragstart = function()
464 {
465 if(currentNote.oldRect == null)
466 {
467 var r = currentNote.rect;
468 currentNote.oldRect = new PhotoNoteRect(r.left,r.top,r.width,r.height);
469 }
470 };
471 this.dragresize.ondragend = function()
472 {
473 //window.status = 'LKSFDLKJDFSLKJFDLKJ';
474 currentNote.HighlightTextbox();
475 };
476 this.dragresize.ondragmove = function()
477 {
478 currentNote.rect.left = parseInt(this.element.style.left);
479 currentNote.rect.top = parseInt(this.element.style.top) - $("#"+this.containerId).position().top;
480 currentNote.rect.width = parseInt(this.element.style.width);
481 currentNote.rect.height = parseInt(this.element.style.height);
482 currentNote.PositionNote();
483 };
484
485 this.dragresize.apply(document);
486
487 /* setup the GUI object */
488 this.gui.ElementRect = newArea;
489 this.gui.ElementNote = noteArea;
490 this.gui.EditArea = editArea;
491 this.gui.TextBox = newTextbox;
492 this.gui.TextTitle = titleArea;
493 this.gui.DeleteButton = newButtonDelete;
494
495 /* position the note text below the note area */
496 this.PositionNote();
497}
498
499PhotoNote.prototype.PositionNote = function()
500{
501 /* outer most box */
502 this.gui.ElementRect.style.left = this.rect.left + 'px';
503 this.gui.ElementRect.style.top = this.rect.top + $("#"+this.containerId).position().top + 'px';
504 this.gui.ElementRect.style.width = this.rect.width + 'px';
505 this.gui.ElementRect.style.height = this.rect.height + 'px';
506
507 // black border
508 this.gui.ElementRect.firstChild.style.width = parseInt(this.gui.ElementRect.style.width) - 2 + 'px';
509 this.gui.ElementRect.firstChild.style.height = parseInt(this.gui.ElementRect.style.height) - 2 + 'px';
510
511 // white border
512 this.gui.ElementRect.firstChild.firstChild.style.width = parseInt(this.gui.ElementRect.style.width) - 4 + 'px';
513 this.gui.ElementRect.firstChild.firstChild.style.height = parseInt(this.gui.ElementRect.style.height) - 4 + 'px';
514
515 // inner box
516 this.gui.ElementRect.firstChild.firstChild.firstChild.style.width = parseInt(this.gui.ElementRect.style.width) - 6 + 'px';
517 this.gui.ElementRect.firstChild.firstChild.firstChild.style.height = parseInt(this.gui.ElementRect.style.height) - 6 + 'px';
518
519 this.gui.ElementNote.style.left = this.rect.left + this.XOffset + 'px';
520 this.gui.ElementNote.style.top = this.rect.top + this.YOffset + this.rect.height + $("#"+this.containerId).position().top + 'px';
521
522}
523
524/*********************************************************/
525/*** Photo Note GUI Object *******************************/
526/*********************************************************/
527function PhotoNoteGUI()
528{
529 this.ElementRect = null;
530
531 // the note text area...
532 this.ElementNote = null;
533 this.TextTitle = null;
534 this.EditArea = null;
535 this.TextBox = null;
536
537 // buttons
538 this.DeleteButton = null;
539}
540
541
542
543/*********************************************************/
544/*** Rectangle *******************************************/
545/*********************************************************/
546function PhotoNoteRect(left,top,width,height)
547{
548 this.left = left;
549 this.top = top;
550 this.width = width;
551 this.height = height;
552}
553
554/* for debugging purposes */
555PhotoNoteRect.prototype.toString = function()
556{
557 return 'left: ' + this.left + ', top: ' + this.top + ', width: ' + this.width + ', height: ' + this.height;
558}
559
560
561// *** Common API Code ***
562// (c) 2005 Angus Turnbull http://www.twinhelix.com
563
564var aeOL = [];
565function _PN_addEvent(o, n, f, l)
566{
567 var a = 'addEventListener', h = 'on'+n, b = '', s = '';
568 if (o[a] && !l) return o[a](n, f, false);
569 o._c |= 0;
570 if (o[h])
571 {
572 b = '_f' + o._c++;
573 o[b] = o[h];
574 }
575 s = '_f' + o._c++;
576 o[s] = f;
577 o[h] = function(e)
578 {
579 e = e || window.event;
580 var r = true;
581 if (b) r = o[b](e) != false && r;
582 r = o[s](e) != false && r;
583 return r;
584 };
585 aeOL[aeOL.length] = { o: o, h: h };
586};
587_PN_addEvent(window, 'unload', function() {
588 for (var i = 0; i < aeOL.length; i++) with (aeOL[i])
589 {
590 o[h] = null;
591 for (var c = 0; o['_f' + c]; c++) o['_f' + c] = null;
592 }
593});
594
595function cancelEvent2(e, c)
596{
597 e.returnValue = false;
598 if (e.preventDefault) e.preventDefault();
599 if (c)
600 {
601 e.cancelBubble = true;
602 if (e.stopPropagation) e.stopPropagation();
603 }
604};
605
606function addLoadEvent2(func) {
607 var oldonload = window.onload;
608 if (typeof window.onload != 'function') {
609 window.onload = func;
610 } else {
611 window.onload = function() {
612 oldonload();
613 func();
614 }
615 }
616}
617
618
619/* Extend the Array object with some useful features
620 http://www.ditchnet.org/wp/?p=8
621*/
622
623/*
624
625Causes problem with Seaweed/Direct Edit's dynamic loader
626
627Array.prototype.clear2 = function () {
628 this.length = 0;
629};
630
631
632
633Array.prototype.remove2 = function (element) {
634 var result = false;
635 var array = [];
636 for (var i = 0; i < this.length; i++) {
637 if (this[i] == element) {
638 result = true;
639 } else {
640 array.push(this[i]);
641 }
642 }
643 this.clear2();
644 for (var i = 0; i < array.length; i++) {
645 this.push(array[i]);
646 }
647 array = null;
648 return result;
649};
650*/
651
652function removeFromArray(that,element) {
653 var result = false;
654 var array = [];
655 for (var i = 0; i < that.length; i++) {
656 if (that[i] == element) {
657 result = true;
658 } else {
659 array.push(that[i]);
660 }
661 }
662 that.length = 0;
663
664 for (var i = 0; i < array.length; i++) {
665 that.push(array[i]);
666 }
667 array = null;
668 return result;
669}
670
671
672// *** Drag and Resize Library Code ***
673// (c) 2005 Angus Turnbull http://www.twinhelix.come
674
675function DragResize(containerId, myName, config)
676{
677 var props = {
678 containerId: containerId,
679 myName: myName, // Name of the object.
680 enabled: true, // Global toggle of drag/resize.
681 handles: ['tl', 'tm', 'tr',
682 'ml', 'mr', 'bl', 'bm', 'br'], // Array of drag handles: top/mid/.
683 isElement: null, // Function ref to test for an element.
684 isHandle: null, // Function ref to test for move handle.
685 element: null, // The currently selected element.
686 dragging: null, // Active handle reference of the element.
687 minWidth: 10, minHeight: 10, // Minimum pixel size of elements.
688 minLeft: 0, maxRight: 9999, // Bounding box area.
689 minTop: $("#"+containerId).position().top, maxBottom: 9999,
690 zIndex: 1, // The highest Z-Index yet allocated.
691 mouseX: 0, mouseY: 0, // Current mouse position, recorded live.
692 lastMouseX: 0, lastMouseY: 0, // Last processed mouse positions.
693 mOffX: 0, mOffY: 0, // A known offset between position & mouse.
694 elmX: 0, elmY: 0, // Element position.
695 elmW: 0, elmH: 0, // Element size.
696 allowBlur: true, // Whether to allow automatic blur onclick.
697 ondragfocus: null, // Event handler functions.
698 ondragstart: null,
699 ondragmove: null,
700 ondragend: null,
701 ondragblur: null
702 };
703
704 for (var p in props)
705 {
706 this[p] = (typeof config[p] == 'undefined') ? props[p] : config[p];
707 }
708};
709
710DragResize.prototype.apply = function(node)
711{
712 // Adds object event handlers to the specified DOM node.
713
714 var obj = this;
715 _PN_addEvent(node, 'mousedown', function(e) { obj.mouseDown(e) } );
716 _PN_addEvent(node, 'mousemove', function(e) { obj.mouseMove(e) } );
717 _PN_addEvent(node, 'mouseup', function(e) { obj.mouseUp(e) } );
718};
719
720DragResize.prototype.handleSet = function(elm, show) { with (this)
721{
722 // Either creates, shows or hides the resize handles within an element.
723
724 // If we're showing them, and no handles have been created, create 4 new ones.
725 if (!elm._handle_tr)
726 {
727 for (var h = 0; h < handles.length; h++)
728 {
729 // Create 4 news divs, assign each a generic + specific class.
730 var hDiv = document.createElement('div');
731 hDiv.className = myName + ' ' + myName + '-' + handles[h];
732 elm['_handle_' + handles[h]] = elm.appendChild(hDiv);
733 }
734 }
735
736 // We now have handles. Find them all and show/hide.
737 for (var h = 0; h < handles.length; h++)
738 {
739 elm['_handle_' + handles[h]].style.visibility = show ? 'inherit' : 'hidden';
740 }
741}};
742
743
744DragResize.prototype.select = function(newElement) { with (this)
745{
746 // Selects an element for dragging.
747
748 if (!document.getElementById || !enabled) return;
749
750 // Activate and record our new dragging element.
751 if (newElement && (newElement != element) && enabled)
752 {
753 element = newElement;
754 // Elevate it and give it resize handles.
755 element.style.zIndex = ++zIndex;
756 handleSet(element, true);
757 // Record element attributes for mouseMove().
758 elmX = parseInt(element.style.left);
759 elmY = parseInt(element.style.top + $("#"+this.containerId).position().top);
760 elmW = element.offsetWidth;
761 elmH = element.offsetHeight;
762 if (ondragfocus) this.ondragfocus();
763 //window.status = 'start elmX=' + element.className;
764
765 }
766}};
767
768
769DragResize.prototype.deselect = function(keepHandles) { with (this)
770{
771 // Immediately stops dragging an element. If 'keepHandles' is false, this
772 // remove the handles from the element and clears the element flag,
773 // completely resetting the .
774
775 if (!document.getElementById || !enabled) return;
776
777 if (!keepHandles)
778 {
779 if (ondragblur) this.ondragblur();
780 handleSet(element, false);
781 element = null;
782 }
783
784 dragging = null;
785 mOffX = 0;
786 mOffY = 0;
787}};
788
789
790DragResize.prototype.mouseDown = function(e) { with (this)
791{
792 //window.status = 'mouseDown!';
793 // Suitable elements are selected for drag/resize on mousedown.
794 // We also initialise the resize boxes, and drag parameters like mouse position etc.
795 if (!document.getElementById || !enabled) return true;
796
797 var elm = e.target || e.srcElement,
798 newElement = null,
799 newHandle = null,
800 hRE = new RegExp(myName + '-([trmbl]{2})', '');
801
802 while (elm)
803 {
804 // Loop up the DOM looking for matching elements. Remember one if found.
805 if (elm.className)
806 {
807 if (!newHandle && (hRE.test(elm.className) || isHandle(elm))) newHandle = elm;
808 if (isElement(elm)) { newElement = elm; break }
809 }
810 elm = elm.parentNode;
811 }
812
813 // If this isn't on the last dragged element, call deselect(false),
814 // which will hide its handles and clear element.
815 if (element && (element != newElement) && allowBlur) deselect(false);
816
817 // If we have a new matching element, call select().
818 if (newElement && (!element || (newElement == element)))
819 {
820 // Stop mouse selections.
821 cancelEvent2(e);
822 select(newElement, newHandle);
823 dragging = newHandle;
824 if (dragging && ondragstart) this.ondragstart();
825 }
826}};
827
828
829DragResize.prototype.mouseMove = function(e) { with (this)
830{
831 // This continually offsets the dragged element by the difference between the
832 // last recorded mouse position (mouseX/Y) and the current mouse position.
833 if (!document.getElementById || !enabled) return true;
834
835 // We always record the current mouse position.
836 mouseX = e.pageX || e.clientX + document.documentElement.scrollLeft;
837 mouseY = e.pageY || e.clientY + document.documentElement.scrollTop;
838 // Record the relative mouse movement, in case we're dragging.
839 // Add any previously stored&ignored offset to the calculations.
840 var diffX = mouseX - lastMouseX + mOffX;
841 var diffY = mouseY - lastMouseY + mOffY;
842 mOffX = mOffY = 0;
843 // Update last processed mouse positions.
844 lastMouseX = mouseX;
845 lastMouseY = mouseY;
846
847 // That's all we do if we're not dragging anything.
848 if (!dragging) return true;
849
850 // Establish which handle is being dragged -- retrieve handle name from className.
851 var hClass = dragging && dragging.className &&
852 dragging.className.match(new RegExp(myName + '-([tmblr]{2})')) ? RegExp.$1 : '';
853
854 // If the hClass is one of the resize handles, resize one or two dimensions.
855 // Bounds checking is the hard bit -- basically for each edge, check that the
856 // element doesn't go under minimum size, and doesn't go beyond its boundary.
857 var rs = 0, dY = diffY, dX = diffX;
858 if (hClass.indexOf('t') >= 0)
859 {
860 rs = 1;
861 if (elmH - dY < minHeight) mOffY = (dY - (diffY = elmH - minHeight));
862 else if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
863 elmY += diffY;
864 elmH -= diffY;
865 }
866 if (hClass.indexOf('b') >= 0)
867 {
868 rs = 1;
869 if (elmH + dY < minHeight) mOffY = (dY - (diffY = minHeight - elmH));
870 else if (elmY + elmH + dY > maxBottom) mOffY = (dY - (diffY = maxBottom - elmY - elmH));
871 elmH += diffY;
872 }
873 if (hClass.indexOf('l') >= 0)
874 {
875 rs = 1;
876 if (elmW - dX < minWidth) mOffX = (dX - (diffX = elmW - minWidth));
877 else if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
878 elmX += diffX;
879 elmW -= diffX;
880 }
881 if (hClass.indexOf('r') >= 0)
882 {
883 rs = 1;
884 if (elmW + dX < minWidth) mOffX = (dX - (diffX = minWidth - elmW));
885 else if (elmX + elmW + dX > maxRight) mOffX = (dX - (diffX = maxRight - elmX - elmW));
886 elmW += diffX;
887 window.status = 'diffX:' + diffX;
888 }
889 // If 'rs' isn't set, we must be dragging the whole element, so move that.
890 if (dragging && !rs)
891 {
892 // Bounds check left-right...
893 if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
894 else if (elmX + elmW + dX > maxRight) mOffX = (dX - (diffX = maxRight - elmX - elmW));
895 // ...and up-down.
896 if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
897 else if (elmY + elmH + dY > maxBottom) mOffY = (dY - (diffY = maxBottom - elmY - elmH));
898 //window.status = 'diffX-' + diffX + ' , elmX-' + elmX;
899 elmX += diffX;
900 elmY += diffY;
901 }
902
903 //window.status = 'elmX=' + elmX;
904 // Assign new info back to the element, with minimum dimensions.
905 with (element.style)
906 {
907 left = elmX + 'px';
908 width = elmW + 'px';
909 top = elmY + 'px';
910 height = elmH + 'px';
911 }
912
913 // Evil, dirty, hackish Opera select-as-you-drag fix.
914 if (window.opera && document.documentElement)
915 {
916 var oDF = document.getElementById('op-drag-fix');
917 if (!oDF)
918 {
919 var oDF = document.createElement('input');
920 oDF.id = 'op-drag-fix';
921 oDF.style.display = 'none';
922 document.body.appendChild(oDF);
923 }
924 oDF.focus();
925 }
926
927 if (ondragmove) this.ondragmove();
928
929 // Stop a normal drag event.
930 cancelEvent2(e);
931}};
932
933
934DragResize.prototype.mouseUp = function(e) { with (this)
935{
936 // On mouseup, stop dragging, but don't reset handler visibility.
937 if (!document.getElementById || !enabled) return;
938
939 if (ondragend) this.ondragend();
940 deselect(true);
941}};
942
943
944
Note: See TracBrowser for help on using the repository browser.