/[suikacvs]/webroot/www/css/noderect/NodeRectViewer.js
Suika

Contents of /webroot/www/css/noderect/NodeRectViewer.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.34 - (hide annotations) (download) (as text)
Mon Jan 12 14:13:37 2009 UTC (15 years, 10 months ago) by wakaba
Branch: MAIN
Changes since 1.33: +70 -10 lines
File MIME type: application/javascript
License block and ref to wiki page added

1 wakaba 1.7 if (!window.NodeRectViewer) window.NodeRectViewer = {};
2    
3 wakaba 1.18 NodeRectViewer.Box = function (rect, coords, refBox) {
4 wakaba 1.8 var self = this;
5    
6 wakaba 1.1 var marker = document.createElement ('div');
7 wakaba 1.7 this.element = marker;
8    
9 wakaba 1.24 marker.style.margin = 0;
10     marker.style.borderWidth = 0;
11     marker.style.padding = 0;
12    
13 wakaba 1.18 var left = rect.getRenderedLeft ();
14     var top = rect.getRenderedTop ();
15    
16     if (refBox) {
17     left += refBox.getSourceLeft ();
18     top += refBox.getSourceTop ();
19     }
20    
21 wakaba 1.14 this.setPositionProperty (coords == 'viewport' ? 'fixed' : 'absolute');
22 wakaba 1.18 this.setInitialPosition (left, top);
23 wakaba 1.9 this.setMaxZIndex ();
24 wakaba 1.8
25 wakaba 1.25 if (rect instanceof NR.Vector) {
26     this.setBorder (rect.y < 0, rect.x < 0, rect.y >= 0, rect.x >= 0);
27 wakaba 1.11 } else {
28     this.setBorder (true, true, true, true);
29 wakaba 1.3 }
30 wakaba 1.10
31 wakaba 1.25 this.setDimension (rect.getRenderedWidth (), rect.getRenderedHeight ());
32 wakaba 1.11
33 wakaba 1.25 this.sourceLeft = this.left;
34     this.sourceTop = this.top;
35     this.destLeft = this.left + this.width;
36     this.destTop = this.top + this.height;
37    
38     if (rect instanceof NR.Vector) {
39     if (rect.x < 0) {
40     this.sourceLeft = this.left + this.width;
41     this.destLeft = this.left;
42     }
43     if (rect.y < 0) {
44     this.sourceTop = this.top + this.height;
45     this.destTop = this.top;
46     }
47 wakaba 1.24 this.addArrow (this.getSourceLeft (), this.getSourceTop (),
48     this.getDestinationLeft (), this.getDestinationTop ());
49     }
50    
51 wakaba 1.10 this.setColor (rect.index);
52     this.setOpacity (0.3);
53     this.setLabelColor ('black', 'transparent');
54    
55 wakaba 1.1 marker.onmouseover = function () {
56 wakaba 1.10 self.setOpacity (0.7);
57     self.setLabelColor ('black', 'white');
58 wakaba 1.1 };
59     marker.onmouseout = function () {
60 wakaba 1.10 self.setOpacity (0.3);
61     self.setLabelColor ('black', 'transparent');
62 wakaba 1.1 };
63     marker.onmousedown = function (event) {
64 wakaba 1.12 event = event || window.event;
65 wakaba 1.9 self.setMaxZIndex ();
66 wakaba 1.12 if (!self.isClickable (event.target || event.srcElement)) {
67     self.startDrag (event);
68     }
69 wakaba 1.1 };
70 wakaba 1.15 marker.ondblclick = function (event) {
71     event = event || window.event;
72 wakaba 1.12 if (!self.isClickable (event.target || event.srcElement)) {
73     self.setPosition (self.initialLeft, self.initialTop);
74     }
75 wakaba 1.1 };
76    
77     var label = rect.getFullLabel ? rect.getFullLabel () : '';
78 wakaba 1.8 this.setDescription (label, rect.toString ());
79     }; // Box
80 wakaba 1.1
81 wakaba 1.9 if (!NodeRectViewer.maxBoxZIndex) NodeRectViewer.maxZIndex = 9999;
82    
83     NodeRectViewer.Box.prototype.setMaxZIndex = function () {
84     this.element.style.zIndex = ++NodeRectViewer.maxZIndex;
85     }; // setMaxZIndex
86 wakaba 1.14
87     NodeRectViewer.Box.prototype.setPositionProperty = function (value) {
88     var style = this.element.style;
89     if (value == 'fixed') {
90     if (document.all && document.compatMode != 'CSS1Compat') {
91     style.position = 'absolute';
92     } else {
93     style.position = value;
94     }
95     } else {
96     style.position = value;
97     }
98     }; // setPositionProperty
99 wakaba 1.9
100 wakaba 1.13 NodeRectViewer.Box.prototype.setInitialPosition = function (left, top) {
101     this.initialLeft = left;
102     this.initialTop = top;
103     this.setPosition (this.initialLeft, this.initialTop);
104     }; // setInitialPosition
105    
106 wakaba 1.18 NodeRectViewer.Box.prototype.getSourceLeft = function () {
107 wakaba 1.25 return this.sourceLeft;
108 wakaba 1.18 }; // getSourceLeft
109    
110     NodeRectViewer.Box.prototype.getSourceTop = function () {
111 wakaba 1.25 return this.sourceTop;
112 wakaba 1.18 }; // getSourceTop
113    
114     NodeRectViewer.Box.prototype.getDestinationLeft = function () {
115 wakaba 1.25 return this.destLeft;
116 wakaba 1.18 }; // getDestinationLeft
117    
118     NodeRectViewer.Box.prototype.getDestinationTop = function () {
119 wakaba 1.25 return this.destTop;
120 wakaba 1.18 }; // getDestinationTop
121    
122 wakaba 1.8 NodeRectViewer.Box.prototype.setPosition = function (left, top) {
123     if (!isNaN (top + 0)) {
124     this.element.style.top = top + 'px';
125     this.top = top;
126     }
127     if (!isNaN (left + 0)) {
128     this.element.style.left = left + 'px';
129     this.left = left;
130     }
131     }; // setPosition
132 wakaba 1.10
133 wakaba 1.11 if (document.all && document.compatMode == 'CSS1Compat') {
134     NodeRectViewer.Box.boxSizing = 'content-box';
135     } else {
136     NodeRectViewer.Box.boxSizing = 'border-box';
137     }
138    
139     NodeRectViewer.Box.prototype.setDimension = function (w, h) {
140     if (w < 0 || (w + 0) != w) w = 0;
141     if (h < 0 || (h + 0) != h) h = 0;
142    
143 wakaba 1.13 this.width = w;
144     this.height = h;
145    
146 wakaba 1.11 var ww = w;
147     var hh = h;
148     if (ww < 20) ww = 20;
149     if (hh < 20) hh = 20;
150    
151     this.element.style.width = ww + 'px';
152     this.element.style.height = hh + 'px';
153    
154     var borderEl = this.borderElement;
155     if (borderEl) {
156     if (NodeRectViewer.Box.boxSizing === 'content-box') {
157     var mw = this.borderLeftWidth + this.borderRightWidth;
158     var mh = this.borderTopWidth + this.borderBottomWidth;
159     if (w < mw) w = mw; else w -= mw;
160     if (h < mh) h = mh; else h -= mh;
161     }
162    
163     borderEl.style.width = w + 'px';
164     borderEl.style.height = h + 'px';
165     }
166     }; // setDimension
167    
168     NodeRectViewer.Box.prototype.setBorder = function (t, r, b, l) {
169     var borderEl = this.borderElement;
170     if (!borderEl) {
171     borderEl = this.element.ownerDocument.createElement ('div');
172     borderEl.style.position = 'absolute';
173     borderEl.style.top = 0;
174     borderEl.style.left = 0;
175 wakaba 1.24 borderEl.style.margin = 0;
176     borderEl.style.padding = 0;
177 wakaba 1.11 borderEl.style.MozBoxSizing = 'border-box';
178     borderEl.style.WebkitBoxSizing = 'border-box';
179     borderEl.style.boxSizing = 'border-box';
180     this.borderElement = borderEl;
181     this.element.appendChild (borderEl);
182     }
183    
184     var bw = 1;
185     borderEl.style.border = bw + 'px red none';
186     if (t) {
187     borderEl.style.borderTopStyle = 'solid';
188     this.borderTopWidth = bw;
189     } else {
190     this.borderTopWidth = 0;
191     }
192     if (r) {
193     borderEl.style.borderRightStyle = 'solid';
194     this.borderRightWidth = bw;
195     } else {
196     this.borderRightWidth = 0;
197     }
198     if (b) {
199     borderEl.style.borderBottomStyle = 'solid';
200     this.borderBottomWidth = bw;
201     } else {
202     this.borderBottomWidth = 0;
203     }
204     if (l) {
205     borderEl.style.borderLeftStyle = 'solid';
206     this.borderLeftWidth = bw;
207     } else {
208     this.borderLeftWidth = 0;
209     }
210     }; // setBorder
211    
212 wakaba 1.10 NodeRectViewer.Box.colors = ['#FFFFCC', '#FFCCCC', '#CC99FF', '#99CCFF'];
213    
214     NodeRectViewer.Box.prototype.setColor = function (index) {
215     var colors = NodeRectViewer.Box.colors;
216     this.element.style.backgroundColor = colors[index % colors.length];
217     }; // setColor
218    
219     NodeRectViewer.Box.prototype.setOpacity = function (opacity) {
220     this.element.style.opacity = opacity;
221     this.element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';
222     }; // setOpacity
223    
224     NodeRectViewer.Box.prototype.setLabelColor = function (fg, bg) {
225 wakaba 1.11 var textEl = this.labelElement;
226 wakaba 1.10 if (!textEl) return;
227     textEl.style.color = fg;
228     textEl.style.backgroundColor = bg;
229     }; // setLabelColor
230 wakaba 1.1
231 wakaba 1.8 NodeRectViewer.Box.prototype.setDescription = function (label, desc) {
232     this.element.title = "*" + label + "* \n" + desc;
233    
234 wakaba 1.11 var textEl = this.labelElement;
235     if (textEl) {
236     textEl.innerHTML = '';
237     } else {
238     textEl = this.element.ownerDocument.createElement ('div');
239     this.labelElement = textEl;
240     }
241 wakaba 1.8 textEl.style.position = 'absolute';
242     if (!isNaN (this.width)) textEl.style.left = (this.width / 2) + 'px';
243     if (!isNaN (this.height)) textEl.style.top = (this.height / 2) + 'px';
244     textEl.style.fontSize = '20px';
245     textEl.appendChild (textEl.ownerDocument.createTextNode (label));
246    
247     this.element.appendChild (textEl);
248     }; // setDescription
249 wakaba 1.7
250 wakaba 1.9 NodeRectViewer.Box.dragging = null;
251    
252     if (!NodeRectViewer.Box.activeHandlers) NodeRectViewer.Box.activeHandlers = {};
253    
254     NodeRectViewer.Box.mousemoveHandler = function (event) {
255     if (NodeRectViewer.Box.dragging) {
256     NodeRectViewer.Box.dragging.handleDrag (event || window.event);
257     }
258     }; // mousemoveHandler
259    
260     NodeRectViewer.Box.mouseupHandler = function (event) {
261     if (NodeRectViewer.Box.dragging) {
262     NodeRectViewer.Box.dragging.endDrag (event || window.event);
263     }
264     }; // mouseupHandler
265    
266     NodeRectViewer.Box.addDragHandlers = function () {
267     if (window.addEventListener) {
268     if (!NodeRectViewer.Box.activeHandlers.mousemove) {
269     window.addEventListener
270     ('mousemove', NodeRectViewer.Box.mousemoveHandler, false);
271     NodeRectViewer.Box.activeHandlers.mousemove
272     = NodeRectViewer.Box.mousemoveHandler;
273     }
274     if (!NodeRectViewer.Box.activeHandlers.mouseup) {
275     window.addEventListener
276     ('mouseup', NodeRectViewer.Box.mouseupHandler, false);
277     NodeRectViewer.Box.activeHandlers.mouseup
278     = NodeRectViewer.Box.mouseupHandler;
279     }
280     } else if (document.attachEvent) {
281     if (!NodeRectViewer.Box.activeHandlers.mousemove) {
282     document.attachEvent ('onmousemove', NodeRectViewer.Box.mousemoveHandler);
283     NodeRectViewer.Box.activeHandlers.mousemove
284     = NodeRectViewer.Box.mousemoveHandler;
285     }
286     if (!NodeRectViewer.Box.activeHandlers.mouseup) {
287     document.attachEvent ('onmouseup', NodeRectViewer.Box.mouseupHandler);
288     NodeRectViewer.Box.activeHandlers.mouseup
289     = NodeRectViewer.Box.mouseupHandler;
290     }
291     }
292     }; // addDragHandlers
293    
294     NodeRectViewer.Box.removeDragHandlers = function () {
295     if (window.removeEventListener) {
296     if (NodeRectViewer.Box.activeHandlers.mousemove) {
297     window.removeEventListener
298     ('mousemove', NodeRectViewer.Box.activeHandlers.mousemove, false);
299     }
300     if (NodeRectViewer.Box.activeHandlers.mouseup) {
301     window.removeEventListener
302     ('mouseup', NodeRectViewer.Box.activeHandlers.mouseup, false);
303     }
304     } else if (document.detachEvent) {
305     if (NodeRectViewer.Box.activeHandlers.mousemove) {
306     document.detachEvent ('onmousemove', NodeRectViewer.Box.mousemoveHandler);
307     }
308     if (NodeRectViewer.Box.activeHandlers.mouseup) {
309     document.detachEvent ('onmouseup', NodeRectViewer.Box.mouseupHandler);
310     }
311     }
312     NodeRectViewer.Box.activeHandlers.mousemove = null;
313     NodeRectViewer.Box.activeHandlers.mouseup = null;
314     }; // removeDragHandlers
315    
316     NodeRectViewer.Box.removeDragHandlers ();
317    
318     NodeRectViewer.Box.prototype.startDrag = function (event) {
319     if (NodeRectViewer.Box.dragging) return;
320     NodeRectViewer.Box.dragging = this;
321     NodeRectViewer.Box.addDragHandlers ();
322    
323     this.element.style.cursor = 'move';
324    
325     this.dragStartLeft = this.left;
326     this.dragStartTop = this.top;
327     this.dragStartX = event.clientX;
328     this.dragStartY = event.clientY;
329    
330     if (event.preventDefault) {
331     event.preventDefault ();
332     } else {
333     event.returnValue = false;
334     }
335     }; // startDrag
336    
337     NodeRectViewer.Box.prototype.handleDrag = function (event) {
338     if (NodeRectViewer.Box.dragging != this) return;
339    
340     var diffX = event.clientX - this.dragStartX;
341     var diffY = event.clientY - this.dragStartY;
342     this.setPosition (this.dragStartLeft + diffX, this.dragStartTop + diffY);
343    
344     if (event.preventDefault) {
345     event.preventDefault ();
346     } else {
347     event.returnValue = false;
348     }
349     }; // handleDrag
350    
351     NodeRectViewer.Box.prototype.endDrag = function (event) {
352     if (NodeRectViewer.Box.dragging != this) return;
353    
354     NodeRectViewer.Box.dragging = null;
355     NodeRectViewer.Box.removeDragHandlers ();
356    
357     this.element.style.cursor = 'default';
358    
359     if (event.preventDefault) {
360     event.preventDefault ();
361     } else {
362     event.defaultValue = false;
363     }
364     }; // endDrag
365 wakaba 1.1
366 wakaba 1.12 NodeRectViewer.Box.prototype.isClickable = function (target) {
367     return false;
368     }; // isClickable
369    
370     NodeRectViewer.Box.prototype.remove = function () {
371     this.element.parentNode.removeChild (this.element);
372     }; // remove
373    
374 wakaba 1.1
375 wakaba 1.24 NodeRectViewer.Box.prototype._initCanvas = function () {
376     var canvas = this.element.ownerDocument.createElement ('canvas');
377     if (window.uuClass && uuClass.Canvas) {
378     // uuClass.Canvas (canvas);
379     }
380    
381     canvas.width = this.width + 20;
382     canvas.height = this.height + 20;
383     canvas.style.display = 'block';
384     canvas.style.position = 'absolute';
385     canvas.style.top = 0;
386     canvas.style.left = 0;
387     canvas.style.zIndex = 10;
388     if (!canvas.getContext) {
389     this.canvas = {notSupported: true};
390     return;
391     }
392     var ctx = canvas.getContext ('2d');
393     this.canvas = ctx;
394     this.element.appendChild (canvas);
395     }; // _initCanvas
396    
397     NodeRectViewer.Box.prototype.addArrow = function (x1, y1, x2, y2) {
398     if (!this.canvas) this._initCanvas ();
399     if (this.canvas.notSupported) return;
400     var ctx = this.canvas;
401    
402     ctx.beginPath ();
403    
404     ctx.moveTo (x1, y1);
405     ctx.lineTo (x2, y2);
406    
407     var arrowHeadAngle = Math.PI / 12;
408     var arrowHeadLength = 40;
409    
410     var t = Math.PI + Math.atan2 (y2 - y1, x2 - x1);
411    
412     var ax = Math.cos (arrowHeadAngle);
413     var ay = Math.sin (arrowHeadAngle);
414    
415     var ax_ = ax * Math.cos (t) - ay * Math.sin (t);
416     var ay_ = ax * Math.sin (t) + ay * Math.cos (t);
417    
418     ax_ *= arrowHeadLength;
419     ay_ *= arrowHeadLength;
420    
421     var bx = Math.cos (-arrowHeadAngle);
422     var by = Math.sin (-arrowHeadAngle);
423    
424     var bx_ = bx * Math.cos (t) - by * Math.sin (t);
425     var by_ = bx * Math.sin (t) + by * Math.cos (t);
426    
427     bx_ *= arrowHeadLength;
428     by_ *= arrowHeadLength;
429    
430     ctx.lineTo (x2 + ax_, y2 + ay_);
431    
432     ctx.moveTo (x2, y2);
433     ctx.lineTo (x2 + bx_, y2 + by_);
434    
435     ctx.stroke ();
436     }; // addArrow
437    
438    
439 wakaba 1.12
440 wakaba 1.15 NodeRectViewer.Controller = function () {
441 wakaba 1.21 var self = this;
442    
443 wakaba 1.25 var vpRects = NR.View.getViewportRects (window);
444 wakaba 1.12 var icb = vpRects.icb;
445 wakaba 1.13
446 wakaba 1.25 var wh = NR.Rect.whCSS (document.body, '20em', '11em');
447 wakaba 1.12 var controllerRect
448 wakaba 1.25 = new NR.Rect (0, icb.width, null, null, wh.width, wh.height);
449 wakaba 1.12 controllerRect.label = 'NodeRect viewer';
450 wakaba 1.13
451 wakaba 1.12 var controller = new NodeRectViewer.Box (controllerRect, 'viewport');
452 wakaba 1.15 this.box = controller;
453 wakaba 1.12 controller.element.style.backgroundColor = '#FFCCFF';
454     controller.element.style.whiteSpace = 'nowrap';
455     controller.isClickable = function (target) {
456 wakaba 1.21 return target !== self.box.element && target !== self.formElement;
457 wakaba 1.12 };
458     controller.setOpacity = function () {
459     this.constructor.prototype.setOpacity.apply (this, [1.0]);
460     };
461 wakaba 1.20 controller.setOpacity (1.0);
462 wakaba 1.12
463 wakaba 1.6 var cb = ' style="color: green" ';
464 wakaba 1.21 controller.element.innerHTML = '<form onsubmit="return false"><div \
465 wakaba 1.19 style="width:98%;height:8em; overflow: auto;\
466     border: groove 2px gray;\
467     background-color:white;color:black;\
468     line-height: 1.1;\
469     white-space: pre;\
470     white-space: -moz-pre-wrap;\
471     white-space: pre-wrap"></div>\
472 wakaba 1.12 \
473     \
474 wakaba 1.20 <input name=selector title="Target element selector" \
475 wakaba 1.19 onkeypress=commandInputChanged(event) \
476     style=width:70%>\
477 wakaba 1.12 <input type=checkbox name=trace title="Show box chain" onclick=update(form)>\
478 wakaba 1.1 <br>\
479 wakaba 1.12 \
480     <button type=button onclick=update(form)>Update</button>\
481     <select name=coords title="Layout box(es) with coordinate ..." \
482     onchange=update(form)>\
483 wakaba 1.20 <option value=canvas>Canvas\
484 wakaba 1.12 <option value=viewport>Viewport\
485     </select>\
486     \
487 wakaba 1.13 <select name=prop title="Show box(es) of ..." onchange=update(form)>\
488 wakaba 1.1 \
489 wakaba 1.31 <optgroup label="Mouse event">\
490 wakaba 1.33 <option value=ev.viewport' + cb + '>Viewport coordinate\
491     <option value=ev.canvas' + cb + '>Canvas coordinate\
492 wakaba 1.31 <option value=ev.client>Client\
493 wakaba 1.33 <option value=evx.xy>x, y\
494 wakaba 1.31 <option value=ev.offset>Offset\
495 wakaba 1.33 <option value=evx.layer>Layer\
496     <option value=evx.page>Page\
497     <option value=evx.wh>width, height\
498     <option value=evx.screen>Screen\
499 wakaba 1.31 \
500     \ </optgroup><option value>---------\
501     \
502 wakaba 1.6 <optgroup label="Element coordinate">\
503 wakaba 1.12 <option value=client title="client* attributes">client\
504     <option value=scrollableArea title="scroll* attributes">scroll (width/height)\
505     <option value=scrollState title="scroll* attributes">scroll (top/left)\
506 wakaba 1.6 \
507 wakaba 1.29 <optgroup label="Containing block coordinate">\
508 wakaba 1.30 <option value=offset title="offset* attributes">offset\
509 wakaba 1.29 <option value=x.px>style.pixel\
510     <option value=x.pos>style.pos\
511     <option value=x.currentPx>currentStyle.pixel\
512     <option value=x.currentPos>currentStyle.pos\
513     <option value=x.computedPx>getComputedStyle.pixel\
514     <option value=x.computedPos>getComputedStyle.pos\
515     \
516 wakaba 1.6 <optgroup label="Viewport coordinate">\
517     <option value="boundingClient">getBoundingClientRect</option>\
518 wakaba 1.1 \
519     <optgroup label="Canvas coordinate">\
520 wakaba 1.28 <option value=marginBox' + cb + '>Margin box\
521     <option value=borderBox' + cb + '>Border box\
522 wakaba 1.1 <option value="cumulativeOffset">Cumulative offset</option>\
523 wakaba 1.28 <option value=x.boxObject>getBoxObjectFor\
524     <option value=paddingBox' + cb + '>Padding box\
525 wakaba 1.27 <option value=clientAbs>Client (canvas coordinate)</option>\
526 wakaba 1.28 <option value=contentBox' + cb + '>Content box\
527 wakaba 1.29 <option value=x.textRangeBounding>createTextRange ().bounding\
528 wakaba 1.1 \
529 wakaba 1.6 <optgroup label="Screen coordinate">\
530 wakaba 1.26 <option value=x.boxObjectScreen>getBoxObjectFor.screen\
531 wakaba 1.1 \
532 wakaba 1.6 </optgroup><option value>----------\
533 wakaba 1.1 \
534     <optgroup label="Box">\
535     <option value="margin">margin</option>\
536     <option value="border">border</option>\
537     <option value="padding">padding</option>\
538     \
539 wakaba 1.5 <optgroup label=Canvas>\
540 wakaba 1.6 <option value=vp.canvasOrigin' + cb + '>Origin of canvas\
541 wakaba 1.5 \
542 wakaba 1.1 <optgroup label=Viewport>\
543 wakaba 1.6 <option value=vp.contentBox' + cb + '>Content box\
544     <option value=vp.icb' + cb + '>Initial containing block\
545     <option value=vp.scrollState' + cb + '>Scroll state\
546 wakaba 1.26 <option value=vpx.windowScrollXY>Scroll (x, y)\
547 wakaba 1.1 <option value=vp.windowPageOffset>Page offset\
548 wakaba 1.26 <option value=vpx.windowScrollMax>Scroll maximum\
549     <option value=vpx.windowInner>Window inner\
550 wakaba 1.27 <option value=vp.boundingClientOrigin' + cb + '>Origin of getBoundingClientRect (calc)\
551     <option value=boundingClientOrigin>Origin of getBoundingClientRect (element)\
552 wakaba 1.3 \
553 wakaba 1.26 <option value=vpx.document>Document\
554 wakaba 1.4 <option value=vp.deOffset>documentElement.offset\
555     <option value=vp.deClient>documentElement.client\
556     <option value=vp.deScrollableArea>documentElement.scroll (width, height)\
557     <option value=vp.deScrollState>documentElement.scroll (top, left)\
558     <option value=vp.bodyOffset>document.body.offset\
559     <option value=vp.bodyClient>document.body.client\
560     <option value=vp.bodyScrollableArea>document.body.scroll (width, height)\
561     <option value=vp.bodyScrollState>document.body.scroll (top, left)\
562 wakaba 1.3 \
563     <optgroup label=Window>\
564 wakaba 1.7 <option value=win.outer>Window outer\
565 wakaba 1.3 <option value=win.screenXY>Screen (x, y)\
566     <option value=win.screenTL>Screen (top, left)\
567 wakaba 1.1 \
568     <optgroup label=Screen>\
569 wakaba 1.6 <option value=screen.device' + cb + '>Device\
570     <option value=screen.avail' + cb + '>Available\
571 wakaba 1.1 \
572     </select>\
573     </form>';
574    
575 wakaba 1.13 controller.element.style.width = 'auto';
576     controller.element.style.height = 'auto';
577 wakaba 1.12 document.body.appendChild (controller.element);
578 wakaba 1.13
579     controller.setDimension
580     (controller.element.offsetWidth, controller.element.offsetHeight);
581     controller.setInitialPosition
582     (icb.width - controller.width, icb.height - controller.height);
583 wakaba 1.12
584 wakaba 1.20 this.formElement = controller.element.firstChild;
585    
586     this.logElement = this.formElement.firstChild;
587 wakaba 1.19
588 wakaba 1.20 this.formElement.update = function (form) {
589     self.updateProps (form);
590 wakaba 1.31 if (self.boxType.substring (0, 2) == 'ev') {
591 wakaba 1.32 setTimeout (function () {
592     self.startCapture ();
593     self.addInputLog ('startCapture');
594     }, 100); /* Wait a bit to avoid <option>.onclick being captured by IE */
595 wakaba 1.31 } else {
596     self.update ();
597     }
598 wakaba 1.15 };
599 wakaba 1.20 this.formElement.commandInputChanged = function (event) {
600 wakaba 1.19 if (event.keyCode == 13 || event.keyCode == 10) {
601 wakaba 1.20 self.invokeCommand (self.formElement.selector.value);
602     self.formElement.selector.value = '';
603 wakaba 1.22 if (event.preventDefault) event.preventDefault ();
604 wakaba 1.19 event.returnValue = false;
605     }
606     };
607 wakaba 1.20
608 wakaba 1.21
609     this.selectorIndex = 0;
610 wakaba 1.28 this.boxType = 'borderBox';
611 wakaba 1.21 this.boxCoord = 'canvas';
612     this.showChain = false;
613     this.selector = 'body';
614     this.addInputLog ('selector = body');
615 wakaba 1.20 this.updateForm ();
616     this.update ();
617    
618     this.formElement.selector.focus ();
619 wakaba 1.15 }; // Controller
620    
621     NodeRectViewer.Controller.prototype.remove = function () {
622 wakaba 1.17 this.clearHighlight ();
623 wakaba 1.15 this.box.remove ();
624     }; // remove
625    
626 wakaba 1.20 NodeRectViewer.Controller.prototype.updateForm = function () {
627     var form = this.formElement;
628     form.prop.value = this.boxType;
629     form.coords.value = this.boxCoord;
630     form.trace.checked = this.showChain;
631     }; // updateForm
632    
633     NodeRectViewer.Controller.prototype.updateProps = function (form) {
634     var newBoxType = form.prop.value;
635     if (newBoxType != this.boxType) {
636     this.boxType = newBoxType;
637     this.addInputLog ("boxType = " + newBoxType);
638     }
639    
640     var newShowChain = form.trace.checked;
641     if (this.showChain != newShowChain) {
642     this.showChain = newShowChain;
643     this.addInputLog ('showChain = ' + newShowChain);
644     }
645    
646     var newBoxCoord = form.coords.value;
647     if (newBoxCoord != this.boxCoord) {
648     this.boxCoord = newBoxCoord;
649     this.addInputLog ('boxCoord = ' + newBoxCoord);
650     }
651     }; // updateProps
652    
653     NodeRectViewer.Controller.prototype.update = function () {
654 wakaba 1.15 this.clearHighlight ();
655 wakaba 1.19
656 wakaba 1.31 var type = this.boxType;
657 wakaba 1.20 var el = uu.css (this.selector)[this.selectorIndex];
658 wakaba 1.31 if ((type.substring (0, 2) != 'ev' && el) ||
659     (type.substring (0, 2) == 'ev' && this.lastEvent)) {
660 wakaba 1.25 NR.resetIndex ();
661 wakaba 1.15 var rect;
662 wakaba 1.20 var position = this.boxCoord;
663 wakaba 1.15 if (type == '') {
664     return;
665     } else if (type == 'cumulativeOffset') {
666 wakaba 1.25 rect = NR.Element.getCumulativeOffsetRect (el, window);
667 wakaba 1.27 } else if (type == 'boundingClientOrigin') {
668     rect = NR.View.getBoundingClientRectOrigin (window, document);
669 wakaba 1.15 } else if (type.substring (0, 3) === 'vp.') {
670 wakaba 1.25 var rects = NR.View.getViewportRects (window);
671 wakaba 1.15 rect = rects[type.substring (3)];
672 wakaba 1.26 } else if (type.substring (0, 4) === 'vpx.') {
673     var rects = NR.View.getViewportRectsExtra (window);
674     rect = rects[type.substring (4)];
675 wakaba 1.15 } else if (type.substring (0, 4) === 'win.') {
676 wakaba 1.25 var rects = NR.View.getWindowRects (window);
677 wakaba 1.15 rect = rects[type.substring (4)];
678     } else if (type.substring (0, 7) === 'screen.') {
679 wakaba 1.25 var rects = NR.View.getScreenRects (window);
680 wakaba 1.15 rect = rects[type.substring (7)];
681 wakaba 1.26 } else if (type.substring (0, 2) === 'x.') {
682 wakaba 1.29 var rects = NR.Element.getRectsExtra (el, window);
683 wakaba 1.26 rect = rects[type.substring (2)];
684 wakaba 1.31 } else if (type.substring (0, 3) === 'ev.' || !el) {
685     var rects = NR.Event.getRects (this.lastEvent, window);
686     rect = rects[type.substring (3)];
687 wakaba 1.33 } else if (type.substring (0, 4) === 'evx.' || !el) {
688     var rects = NR.Event.getRectsExtra (this.lastEvent, window);
689     rect = rects[type.substring (4)];
690 wakaba 1.15 } else {
691 wakaba 1.25 var rects = NR.Element.getRects (el, window);
692 wakaba 1.15 rect = rects[type];
693     }
694 wakaba 1.20
695     if (!rect) {
696 wakaba 1.25 rect = NR.Rect.invalid;
697 wakaba 1.20 }
698    
699 wakaba 1.19 this.addOutputLog (rect.toString ());
700 wakaba 1.20
701     if (this.showChain) {
702 wakaba 1.15 this.showTrace (rect, position);
703     } else {
704     this.setHighlight (rect, position);
705     }
706    
707     this.box.setMaxZIndex ();
708     }
709     }; // update
710 wakaba 1.19
711 wakaba 1.20 NodeRectViewer.Controller.prototype.invokeCommand = function (commandStr) {
712     var command = {};
713     var m;
714 wakaba 1.23 if (m = commandStr.match (/^\s*([a-zA-Z0-9]+)\s*=\s*(\S+)\s*$/)) {
715 wakaba 1.20 command.type = m[1];
716     command.arg = m[2];
717 wakaba 1.31 } else if (m = commandStr.match (/^\s*(clear|startCapture|endCapture)\s*$/)) {
718     command.type = m[1];
719 wakaba 1.26 } else if (commandStr == '') {
720     return;
721 wakaba 1.20 } else {
722     command.type = 'selector';
723     command.arg = commandStr;
724     }
725    
726     if (command.type === 'boxType' ||
727     command.type === 'boxCoord') {
728     this[command.type] = command.arg;
729     this.addInputLog (command.type + ' = ' + this[command.type]);
730     this.updateForm ();
731     this.update (this.formElement);
732     } else if (command.type === 'selectorIndex') {
733     this[command.type] = parseInt (command.arg) || 0;
734     this.addInputLog (command.type + ' = ' + this[command.type]);
735     this.updateForm ();
736     this.update (this.formElement);
737     } else if (command.type === 'showChain') {
738     this[command.type] = command.arg && command.arg != "false" ? true : false;
739     this.addInputLog (command.type + ' = ' + this[command.type]);
740     this.updateForm ();
741     this.update (this.formElement);
742     } else if (command.type === 'selector') {
743     this.selector = command.arg;
744 wakaba 1.21 this.addInputLog (command.type + ' = ' + this[command.type]);
745 wakaba 1.20 this.update (this.formElement);
746 wakaba 1.31 } else if ({startCapture: true, endCapture: true}[command.type]) {
747     this.addInputLog (command.type);
748     this[command.type] ();
749 wakaba 1.21 } else if (command.type === 'clear') {
750     this.logElement.innerHTML = '';
751 wakaba 1.20 } else {
752     this.addOutputLog (command.type + ': Command not found');
753     }
754 wakaba 1.19 }; // invokeCommand
755    
756     NodeRectViewer.Controller.prototype.addInputLog = function (s) {
757     var doc = this.logElement.ownerDocument;
758     var entryEl = doc.createElement ('div');
759     entryEl.style.color = 'blue';
760     entryEl.appendChild (doc.createTextNode ('> ' + s));
761     this.logElement.appendChild (entryEl);
762     this.logElement.scrollTop = this.logElement.scrollHeight;
763     }; // addInputLog
764    
765     NodeRectViewer.Controller.prototype.addOutputLog = function (s) {
766     var doc = this.logElement.ownerDocument;
767     var entryEl = doc.createElement ('div');
768     var lines = s.split (/\r?\n/); // to avoid IE bug
769     for (var i = 0; i < lines.length; i++) {
770     entryEl.appendChild (doc.createTextNode (lines[i]));
771     entryEl.appendChild (doc.createElement ('br'));
772     }
773     this.logElement.appendChild (entryEl);
774     this.logElement.scrollTop = this.logElement.scrollHeight;
775     }; // addOutputLog
776 wakaba 1.15
777 wakaba 1.18 NodeRectViewer.Controller.prototype.showTrace =
778     function (rect, position, refBox) {
779 wakaba 1.15 if (rect.prevOp === 'add-offset') {
780 wakaba 1.18 var b1 = this.showTrace (rect.prev1, position);
781     this.showTrace (rect.prev2, position, b1);
782 wakaba 1.15 } else if (rect.prevOp === 'sub-offset') {
783 wakaba 1.18 var b1 = this.showTrace (rect.prev1, position);
784     this.showTrace (rect.prev2, position, b1);
785 wakaba 1.15 } else if (rect.prevOp === 'add-vector') {
786 wakaba 1.18 var b1 = this.showTrace (rect.prev1, position);
787     this.showTrace (rect.prev2, position, b1);
788 wakaba 1.15 } else if (rect.prevOp === 'sub-vector') {
789 wakaba 1.23 var b1 = this.showTrace (rect.prev1, position);
790     this.showTrace (rect.prev2, position, b1);
791     } else if (rect.prevOp === 'and') {
792 wakaba 1.18 var b1 = this.showTrace (rect.prev1, position);
793     this.showTrace (rect.prev2, position, b1);
794 wakaba 1.15 } else if (rect.prevOp === 'in-edge') {
795 wakaba 1.18 var b1 = this.showTrace (rect.prev1, position);
796     this.showTrace (rect.prev2, position, b1);
797 wakaba 1.15 } else if (rect.prevOp === 'out-edge') {
798 wakaba 1.18 var b1 = this.showTrace (rect.prev1, position);
799     this.showTrace (rect.prev2, position, b1);
800 wakaba 1.15 } else if (rect.prevOp === 'topleft') {
801     this.showTrace (rect.prev1, position);
802 wakaba 1.25 } else if (rect.prevOp === 'negate') {
803 wakaba 1.15 this.showTrace (rect.prev1, position);
804     }
805    
806 wakaba 1.18 return this.setHighlight (rect, position, refBox);
807 wakaba 1.15 }; // showTrace
808    
809 wakaba 1.18 NodeRectViewer.Controller.prototype.setHighlight =
810     function (rect, coords, refBox) {
811     var marker = new NodeRectViewer.Box (rect, coords, refBox);
812 wakaba 1.15
813     document.body.appendChild (marker.element);
814 wakaba 1.16 if (!this.highlightElements) this.highlightElements = [];
815     this.highlightElements.push (marker.element);
816 wakaba 1.18
817     return marker;
818 wakaba 1.15 }; // setHighlight
819    
820     NodeRectViewer.Controller.prototype.clearHighlight = function () {
821 wakaba 1.16 if (this.highlightElements) {
822     for (var i in this.highlightElements) {
823     var el = this.highlightElements[i];
824 wakaba 1.15 if (el.parentNode) el.parentNode.removeChild (el);
825     }
826 wakaba 1.16 this.highlightElements = [];
827 wakaba 1.15 }
828     }; // clearHighlight
829 wakaba 1.31
830     NodeRectViewer.Controller.prototype.startCapture = function () {
831     NodeRectViewer.addClickHandler ();
832     }; // startCapture
833    
834     NodeRectViewer.Controller.prototype.endCapture = function () {
835     NodeRectViewer.removeClickHandler ();
836     }; // endCapture
837    
838     NodeRectViewer.Controller.prototype.onclick = function (ev) {
839     var cbox = this.box.element;
840     var el = ev.target;
841     while (el) {
842     if (el == cbox) return;
843     el = el.parentNode;
844     }
845    
846     this.lastEvent = ev;
847     this.update ();
848    
849     this.endCapture ();
850     this.addInputLog ('endCapture');
851    
852 wakaba 1.32 ev.returnValue = false;
853     if (ev.stopPropagation) ev.stopPropagation ();
854     if (ev.preventDefault) ev.preventDefault ();
855 wakaba 1.31 }; // onclick
856    
857     if (!NodeRectViewer.activeHandlers) NodeRectViewer.activeHandlers = {};
858    
859     NodeRectViewer.removeClickHandler = function () {
860     if (NodeRectViewer.activeHandlers.clickHandler) {
861     if (window.removeEventListener) {
862     window.removeEventListener
863     ('click', NodeRectViewer.activeHandlers.clickHandler, true);
864     } else if (document.detachEvent) {
865     document.detachEvent
866     ('onclick', NodeRectViewer.activeHandlers.clickHandler);
867     }
868     delete NodeRectViewer.activeHandlers.clickHandler;
869     }
870     }; // removeClickHandler
871     NodeRectViewer.removeClickHandler ();
872    
873     NodeRectViewer.addClickHandler = function () {
874     if (NodeRectViewer.activeHandlers.clickHandler) {
875     NodeRectViewer.removeClickHandler ();
876     }
877     if (window.addEventListener) {
878     window.addEventListener ('click', NodeRectViewer.clickHandler, true);
879     NodeRectViewer.activeHandlers.clickHandler = NodeRectViewer.clickHandler;
880     } else if (document.attachEvent) {
881     document.attachEvent ('onclick', NodeRectViewer.clickHandler);
882     NodeRectViewer.activeHandlers.clickHandler = NodeRectViewer.clickHandler;
883     }
884     }; // addClickHandler
885    
886     NodeRectViewer.clickHandler = function (event) {
887     if (NodeRectViewer.controller) {
888     NodeRectViewer.controller.onclick (event || window.event);
889     }
890     }; // clickHandler
891    
892    
893 wakaba 1.15
894 wakaba 1.25 function NROnLoad () {
895 wakaba 1.15 if (NodeRectViewer.controller) {
896     NodeRectViewer.controller.remove ();
897     }
898    
899     NodeRectViewer.controller = new NodeRectViewer.Controller ();
900 wakaba 1.25 } // NROnLoad
901 wakaba 1.1
902     var s = document.createElement ('script');
903     s.src = "http://uupaa-js.googlecode.com/svn/trunk/uupaa.js";
904     document.body.appendChild (s);
905 wakaba 1.24
906 wakaba 1.34 var s = document.createElement ('script');
907     if (NodeRectViewer.DEBUG) {
908     s.src = "http://suika.fam.cx/www/css/noderect/NodeRect.js?" + Math.random ();
909     } else {
910     s.src = "http://suika.fam.cx/www/css/noderect/NodeRect.js";
911     }
912     document.body.appendChild (s);
913    
914 wakaba 1.24 /*
915    
916 wakaba 1.34 NodeRectViewer.js - Interactive user interface for NR.js
917    
918     Bookmarklets loading NodeRectViewer.js are available at
919     <http://suika.fam.cx/%7Ewakaba/wiki/sw/n/NodeRectViewer%2Ejs>.
920    
921     NR.js is available at
922     <http://suika.fam.cx/www/css/noderect/NodeRect.js>.
923    
924     Author: Wakaba <w@suika.fam.cx>.
925 wakaba 1.24
926     */
927 wakaba 1.1
928 wakaba 1.34 /* ***** BEGIN LICENSE BLOCK *****
929     * Copyright 2008-2009 Wakaba <w@suika.fam.cx>. All rights reserved.
930     *
931     * This program is free software; you can redistribute it and/or
932     * modify it under the same terms as Perl itself.
933     *
934     * Alternatively, the contents of this file may be used
935     * under the following terms (the "MPL/GPL/LGPL"),
936     * in which case the provisions of the MPL/GPL/LGPL are applicable instead
937     * of those above. If you wish to allow use of your version of this file only
938     * under the terms of the MPL/GPL/LGPL, and not to allow others to
939     * use your version of this file under the terms of the Perl, indicate your
940     * decision by deleting the provisions above and replace them with the notice
941     * and other provisions required by the MPL/GPL/LGPL. If you do not delete
942     * the provisions above, a recipient may use your version of this file under
943     * the terms of any one of the Perl or the MPL/GPL/LGPL.
944     *
945     * "MPL/GPL/LGPL":
946     *
947     * Version: MPL 1.1/GPL 2.0/LGPL 2.1
948     *
949     * The contents of this file are subject to the Mozilla Public License Version
950     * 1.1 (the "License"); you may not use this file except in compliance with
951     * the License. You may obtain a copy of the License at
952     * <http://www.mozilla.org/MPL/>
953     *
954     * Software distributed under the License is distributed on an "AS IS" basis,
955     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
956     * for the specific language governing rights and limitations under the
957     * License.
958     *
959     * The Original Code is NodeRect code.
960     *
961     * The Initial Developer of the Original Code is Wakaba.
962     * Portions created by the Initial Developer are Copyright (C) 2008
963     * the Initial Developer. All Rights Reserved.
964     *
965     * Contributor(s):
966     * Wakaba <w@suika.fam.cx>
967     *
968     * Alternatively, the contents of this file may be used under the terms of
969     * either the GNU General Public License Version 2 or later (the "GPL"), or
970     * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
971     * in which case the provisions of the GPL or the LGPL are applicable instead
972     * of those above. If you wish to allow use of your version of this file only
973     * under the terms of either the GPL or the LGPL, and not to allow others to
974     * use your version of this file under the terms of the MPL, indicate your
975     * decision by deleting the provisions above and replace them with the notice
976     * and other provisions required by the LGPL or the GPL. If you do not delete
977     * the provisions above, a recipient may use your version of this file under
978     * the terms of any one of the MPL, the GPL or the LGPL.
979     *
980     * ***** END LICENSE BLOCK ***** */

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24