source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web/mrdoob-three.js-4862f5f/editor/js/libs/ui.js@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 15.7 KB
Line 
1var UI = {};
2
3UI.Element = function () {};
4
5UI.Element.prototype = {
6
7 setId: function ( id ) {
8
9 this.dom.id = id;
10
11 return this;
12
13 },
14
15 setClass: function ( name ) {
16
17 this.dom.className = name;
18
19 return this;
20
21 },
22
23 setStyle: function ( style, array ) {
24
25 for ( var i = 0; i < array.length; i ++ ) {
26
27 this.dom.style[ style ] = array[ i ];
28
29 }
30
31 },
32
33 setDisabled: function ( value ) {
34
35 this.dom.disabled = value;
36
37 return this;
38
39 },
40
41 setTextContent: function ( value ) {
42
43 this.dom.textContent = value;
44
45 return this;
46
47 }
48
49}
50
51// properties
52
53var properties = [ 'position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', 'borderLeft',
54'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'color',
55'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textTransform', 'cursor' ];
56
57properties.forEach( function ( property ) {
58
59 var method = 'set' + property.substr( 0, 1 ).toUpperCase() + property.substr( 1, property.length );
60
61 UI.Element.prototype[ method ] = function () {
62
63 this.setStyle( property, arguments );
64 return this;
65
66 };
67
68} );
69
70// events
71
72var events = [ 'KeyUp', 'KeyDown', 'MouseOver', 'MouseOut', 'Click', 'Change' ];
73
74events.forEach( function ( event ) {
75
76 var method = 'on' + event;
77
78 UI.Element.prototype[ method ] = function ( callback ) {
79
80 this.dom.addEventListener( event.toLowerCase(), callback.bind( this ), false );
81
82 return this;
83
84 };
85
86} );
87
88
89// Panel
90
91UI.Panel = function () {
92
93 UI.Element.call( this );
94
95 var dom = document.createElement( 'div' );
96 dom.className = 'Panel';
97
98 this.dom = dom;
99
100 return this;
101};
102
103UI.Panel.prototype = Object.create( UI.Element.prototype );
104
105UI.Panel.prototype.add = function () {
106
107 for ( var i = 0; i < arguments.length; i ++ ) {
108
109 this.dom.appendChild( arguments[ i ].dom );
110
111 }
112
113 return this;
114
115};
116
117
118UI.Panel.prototype.remove = function () {
119
120 for ( var i = 0; i < arguments.length; i ++ ) {
121
122 this.dom.removeChild( arguments[ i ].dom );
123
124 }
125
126 return this;
127
128};
129
130UI.Panel.prototype.clear = function () {
131
132 while ( this.dom.children.length ) {
133
134 this.dom.removeChild( this.dom.lastChild );
135
136 }
137
138};
139
140// Text
141
142UI.Text = function ( text ) {
143
144 UI.Element.call( this );
145
146 var dom = document.createElement( 'span' );
147 dom.className = 'Text';
148 dom.style.cursor = 'default';
149 dom.style.display = 'inline-block';
150 dom.style.verticalAlign = 'middle';
151
152 this.dom = dom;
153 this.setValue( text );
154
155 return this;
156
157};
158
159UI.Text.prototype = Object.create( UI.Element.prototype );
160
161UI.Text.prototype.setValue = function ( value ) {
162
163 if ( value !== undefined ) {
164
165 this.dom.textContent = value;
166
167 }
168
169 return this;
170
171};
172
173
174// Input
175
176UI.Input = function () {
177
178 UI.Element.call( this );
179
180 var scope = this;
181
182 var dom = document.createElement( 'input' );
183 dom.className = 'Input';
184 dom.style.padding = '2px';
185 dom.style.border = '1px solid #ccc';
186
187 dom.addEventListener( 'keydown', function ( event ) {
188
189 event.stopPropagation();
190
191 }, false );
192
193 this.dom = dom;
194
195 return this;
196
197};
198
199UI.Input.prototype = Object.create( UI.Element.prototype );
200
201UI.Input.prototype.getValue = function () {
202
203 return this.dom.value;
204
205};
206
207UI.Input.prototype.setValue = function ( value ) {
208
209 this.dom.value = value;
210
211 return this;
212
213};
214
215
216// TextArea
217
218UI.TextArea = function () {
219
220 UI.Element.call( this );
221
222 var scope = this;
223
224 var dom = document.createElement( 'textarea' );
225 dom.className = 'TextArea';
226 dom.style.padding = '2px';
227 dom.style.border = '1px solid #ccc';
228
229 dom.addEventListener( 'keydown', function ( event ) {
230
231 event.stopPropagation();
232
233 }, false );
234
235 this.dom = dom;
236
237 return this;
238
239};
240
241UI.TextArea.prototype = Object.create( UI.Element.prototype );
242
243UI.TextArea.prototype.getValue = function () {
244
245 return this.dom.value;
246
247};
248
249UI.TextArea.prototype.setValue = function ( value ) {
250
251 this.dom.value = value;
252
253 return this;
254
255};
256
257
258// Select
259
260UI.Select = function () {
261
262 UI.Element.call( this );
263
264 var scope = this;
265
266 var dom = document.createElement( 'select' );
267 dom.className = 'Select';
268 dom.style.width = '64px';
269 dom.style.height = '16px';
270 dom.style.border = '0px';
271 dom.style.padding = '0px';
272
273 this.dom = dom;
274
275 return this;
276
277};
278
279UI.Select.prototype = Object.create( UI.Element.prototype );
280
281UI.Select.prototype.setMultiple = function ( boolean ) {
282
283 this.dom.multiple = boolean;
284
285 return this;
286
287};
288
289UI.Select.prototype.setOptions = function ( options ) {
290
291 var selected = this.dom.value;
292
293 while ( this.dom.children.length > 0 ) {
294
295 this.dom.removeChild( this.dom.firstChild );
296
297 }
298
299 for ( var key in options ) {
300
301 var option = document.createElement( 'option' );
302 option.value = key;
303 option.innerHTML = options[ key ];
304 this.dom.appendChild( option );
305
306 }
307
308 this.dom.value = selected;
309
310 return this;
311
312};
313
314UI.Select.prototype.getValue = function () {
315
316 return this.dom.value;
317
318};
319
320UI.Select.prototype.setValue = function ( value ) {
321
322 this.dom.value = value;
323
324 return this;
325
326};
327
328// FancySelect
329
330UI.FancySelect = function () {
331
332 UI.Element.call( this );
333
334 var scope = this;
335
336 var dom = document.createElement( 'div' );
337 dom.className = 'FancySelect';
338 dom.tabIndex = 0; // keyup event is ignored without setting tabIndex
339
340 // Broadcast for object selection after arrow navigation
341 var changeEvent = document.createEvent('HTMLEvents');
342 changeEvent.initEvent( 'change', true, true );
343
344 // Prevent native scroll behavior
345 dom.addEventListener( 'keydown', function (event) {
346
347 switch ( event.keyCode ) {
348 case 38: // up
349 case 40: // down
350 event.preventDefault();
351 event.stopPropagation();
352 break;
353 }
354
355 }, false);
356
357 // Keybindings to support arrow navigation
358 dom.addEventListener( 'keyup', function (event) {
359
360 switch ( event.keyCode ) {
361 case 38: // up
362 case 40: // down
363 scope.selectedIndex += ( event.keyCode == 38 ) ? -1 : 1;
364
365 if ( scope.selectedIndex >= 0 && scope.selectedIndex < scope.options.length ) {
366
367 // Highlight selected dom elem and scroll parent if needed
368 scope.setValue( scope.options[ scope.selectedIndex ].value );
369
370 // Invoke object/helper/mesh selection logic
371 scope.dom.dispatchEvent( changeEvent );
372
373 }
374
375 break;
376 }
377 }, false);
378
379 this.dom = dom;
380
381 this.options = [];
382 this.selectedIndex = -1;
383 this.selectedValue = null;
384
385 return this;
386
387};
388
389UI.FancySelect.prototype = Object.create( UI.Element.prototype );
390
391UI.FancySelect.prototype.setOptions = function ( options ) {
392
393 var scope = this;
394
395 var changeEvent = document.createEvent( 'HTMLEvents' );
396 changeEvent.initEvent( 'change', true, true );
397
398 while ( scope.dom.children.length > 0 ) {
399
400 scope.dom.removeChild( scope.dom.firstChild );
401
402 }
403
404 scope.options = [];
405
406 for ( var key in options ) {
407
408 var option = document.createElement('div');
409 option.className = 'option';
410 option.innerHTML = options[ key ];
411 option.value = key;
412 scope.dom.appendChild( option );
413
414 scope.options.push( option );
415
416 option.addEventListener( 'click', function ( event ) {
417
418 scope.setValue( this.value );
419 scope.dom.dispatchEvent( changeEvent );
420
421 }, false );
422
423 }
424
425 return scope;
426
427};
428
429UI.FancySelect.prototype.getValue = function () {
430
431 return this.selectedValue;
432
433};
434
435UI.FancySelect.prototype.setValue = function ( value ) {
436
437 if ( typeof value === 'number' ) value = value.toString();
438
439 for ( var i = 0; i < this.options.length; i ++ ) {
440
441 var element = this.options[ i ];
442
443 if ( element.value === value ) {
444
445 element.classList.add( 'active' );
446
447 // scroll into view
448
449 var y = element.offsetTop - this.dom.offsetTop;
450 var bottomY = y + element.offsetHeight;
451 var minScroll = bottomY - this.dom.offsetHeight;
452
453 if ( this.dom.scrollTop > y ) {
454
455 this.dom.scrollTop = y
456
457 } else if ( this.dom.scrollTop < minScroll ) {
458
459 this.dom.scrollTop = minScroll;
460
461 }
462
463 this.selectedIndex = i;
464
465 } else {
466
467 element.classList.remove( 'active' );
468
469 }
470
471 }
472
473 this.selectedValue = value;
474
475 return this;
476
477};
478
479
480// Checkbox
481
482UI.Checkbox = function ( boolean ) {
483
484 UI.Element.call( this );
485
486 var scope = this;
487
488 var dom = document.createElement( 'input' );
489 dom.className = 'Checkbox';
490 dom.type = 'checkbox';
491
492 this.dom = dom;
493 this.setValue( boolean );
494
495 return this;
496
497};
498
499UI.Checkbox.prototype = Object.create( UI.Element.prototype );
500
501UI.Checkbox.prototype.getValue = function () {
502
503 return this.dom.checked;
504
505};
506
507UI.Checkbox.prototype.setValue = function ( value ) {
508
509 if ( value !== undefined ) {
510
511 this.dom.checked = value;
512
513 }
514
515 return this;
516
517};
518
519
520// Color
521
522UI.Color = function () {
523
524 UI.Element.call( this );
525
526 var scope = this;
527
528 var dom = document.createElement( 'input' );
529 dom.className = 'Color';
530 dom.style.width = '64px';
531 dom.style.height = '16px';
532 dom.style.border = '0px';
533 dom.style.padding = '0px';
534 dom.style.backgroundColor = 'transparent';
535
536 try {
537
538 dom.type = 'color';
539 dom.value = '#ffffff';
540
541 } catch ( exception ) {}
542
543 this.dom = dom;
544
545 return this;
546
547};
548
549UI.Color.prototype = Object.create( UI.Element.prototype );
550
551UI.Color.prototype.getValue = function () {
552
553 return this.dom.value;
554
555};
556
557UI.Color.prototype.getHexValue = function () {
558
559 return parseInt( this.dom.value.substr( 1 ), 16 );
560
561};
562
563UI.Color.prototype.setValue = function ( value ) {
564
565 this.dom.value = value;
566
567 return this;
568
569};
570
571UI.Color.prototype.setHexValue = function ( hex ) {
572
573 this.dom.value = "#" + ( '000000' + hex.toString( 16 ) ).slice( -6 );
574
575 return this;
576
577};
578
579
580// Number
581
582UI.Number = function ( number ) {
583
584 UI.Element.call( this );
585
586 var scope = this;
587
588 var dom = document.createElement( 'input' );
589 dom.className = 'Number';
590 dom.value = '0.00';
591
592 dom.addEventListener( 'keydown', function ( event ) {
593
594 event.stopPropagation();
595
596 if ( event.keyCode === 13 ) dom.blur();
597
598 }, false );
599
600 this.min = - Infinity;
601 this.max = Infinity;
602
603 this.precision = 2;
604 this.step = 1;
605
606 this.dom = dom;
607 this.setValue( number );
608
609 var changeEvent = document.createEvent( 'HTMLEvents' );
610 changeEvent.initEvent( 'change', true, true );
611
612 var distance = 0;
613 var onMouseDownValue = 0;
614
615 var pointer = new THREE.Vector2();
616 var prevPointer = new THREE.Vector2();
617
618 var onMouseDown = function ( event ) {
619
620 event.preventDefault();
621
622 distance = 0;
623
624 onMouseDownValue = parseFloat( dom.value );
625
626 prevPointer.set( event.clientX, event.clientY );
627
628 document.addEventListener( 'mousemove', onMouseMove, false );
629 document.addEventListener( 'mouseup', onMouseUp, false );
630
631 };
632
633 var onMouseMove = function ( event ) {
634
635 var currentValue = dom.value;
636
637 pointer.set( event.clientX, event.clientY );
638
639 distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
640
641 var number = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
642
643 dom.value = Math.min( scope.max, Math.max( scope.min, number ) ).toFixed( scope.precision );
644
645 if ( currentValue !== dom.value ) dom.dispatchEvent( changeEvent );
646
647 prevPointer.set( event.clientX, event.clientY );
648
649 };
650
651 var onMouseUp = function ( event ) {
652
653 document.removeEventListener( 'mousemove', onMouseMove, false );
654 document.removeEventListener( 'mouseup', onMouseUp, false );
655
656 if ( Math.abs( distance ) < 2 ) {
657
658 dom.focus();
659 dom.select();
660
661 }
662
663 };
664
665 var onChange = function ( event ) {
666
667 var number = parseFloat( dom.value );
668
669 dom.value = isNaN( number ) === false ? number : 0;
670
671 };
672
673 var onFocus = function ( event ) {
674
675 dom.style.backgroundColor = '';
676 dom.style.borderColor = '#ccc';
677 dom.style.cursor = '';
678
679 };
680
681 var onBlur = function ( event ) {
682
683 dom.style.backgroundColor = 'transparent';
684 dom.style.borderColor = 'transparent';
685 dom.style.cursor = 'col-resize';
686
687 };
688
689 dom.addEventListener( 'mousedown', onMouseDown, false );
690 dom.addEventListener( 'change', onChange, false );
691 dom.addEventListener( 'focus', onFocus, false );
692 dom.addEventListener( 'blur', onBlur, false );
693
694 return this;
695
696};
697
698UI.Number.prototype = Object.create( UI.Element.prototype );
699
700UI.Number.prototype.getValue = function () {
701
702 return parseFloat( this.dom.value );
703
704};
705
706UI.Number.prototype.setValue = function ( value ) {
707
708 if ( value !== undefined ) {
709
710 this.dom.value = value.toFixed( this.precision );
711
712 }
713
714 return this;
715
716};
717
718UI.Number.prototype.setRange = function ( min, max ) {
719
720 this.min = min;
721 this.max = max;
722
723 return this;
724
725};
726
727UI.Number.prototype.setPrecision = function ( precision ) {
728
729 this.precision = precision;
730
731 return this;
732
733};
734
735
736// Integer
737
738UI.Integer = function ( number ) {
739
740 UI.Element.call( this );
741
742 var scope = this;
743
744 var dom = document.createElement( 'input' );
745 dom.className = 'Number';
746 dom.value = '0.00';
747
748 dom.addEventListener( 'keydown', function ( event ) {
749
750 event.stopPropagation();
751
752 }, false );
753
754 this.min = - Infinity;
755 this.max = Infinity;
756
757 this.step = 1;
758
759 this.dom = dom;
760 this.setValue( number );
761
762 var changeEvent = document.createEvent( 'HTMLEvents' );
763 changeEvent.initEvent( 'change', true, true );
764
765 var distance = 0;
766 var onMouseDownValue = 0;
767
768 var pointer = new THREE.Vector2();
769 var prevPointer = new THREE.Vector2();
770
771 var onMouseDown = function ( event ) {
772
773 event.preventDefault();
774
775 distance = 0;
776
777 onMouseDownValue = parseFloat( dom.value );
778
779 prevPointer.set( event.clientX, event.clientY );
780
781 document.addEventListener( 'mousemove', onMouseMove, false );
782 document.addEventListener( 'mouseup', onMouseUp, false );
783
784 };
785
786 var onMouseMove = function ( event ) {
787
788 var currentValue = dom.value;
789
790 pointer.set( event.clientX, event.clientY );
791
792 distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
793
794 var number = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
795
796 dom.value = Math.min( scope.max, Math.max( scope.min, number ) ) | 0;
797
798 if ( currentValue !== dom.value ) dom.dispatchEvent( changeEvent );
799
800 prevPointer.set( event.clientX, event.clientY );
801
802 };
803
804 var onMouseUp = function ( event ) {
805
806 document.removeEventListener( 'mousemove', onMouseMove, false );
807 document.removeEventListener( 'mouseup', onMouseUp, false );
808
809 if ( Math.abs( distance ) < 2 ) {
810
811 dom.focus();
812 dom.select();
813
814 }
815
816 };
817
818 var onChange = function ( event ) {
819
820 var number = parseInt( dom.value );
821
822 if ( isNaN( number ) === false ) {
823
824 dom.value = number;
825
826 }
827
828 };
829
830 var onFocus = function ( event ) {
831
832 dom.style.backgroundColor = '';
833 dom.style.borderColor = '#ccc';
834 dom.style.cursor = '';
835
836 };
837
838 var onBlur = function ( event ) {
839
840 dom.style.backgroundColor = 'transparent';
841 dom.style.borderColor = 'transparent';
842 dom.style.cursor = 'col-resize';
843
844 };
845
846 dom.addEventListener( 'mousedown', onMouseDown, false );
847 dom.addEventListener( 'change', onChange, false );
848 dom.addEventListener( 'focus', onFocus, false );
849 dom.addEventListener( 'blur', onBlur, false );
850
851 return this;
852
853};
854
855UI.Integer.prototype = Object.create( UI.Element.prototype );
856
857UI.Integer.prototype.getValue = function () {
858
859 return parseInt( this.dom.value );
860
861};
862
863UI.Integer.prototype.setValue = function ( value ) {
864
865 if ( value !== undefined ) {
866
867 this.dom.value = value | 0;
868
869 }
870
871 return this;
872
873};
874
875UI.Integer.prototype.setRange = function ( min, max ) {
876
877 this.min = min;
878 this.max = max;
879
880 return this;
881
882};
883
884
885// Break
886
887UI.Break = function () {
888
889 UI.Element.call( this );
890
891 var dom = document.createElement( 'br' );
892 dom.className = 'Break';
893
894 this.dom = dom;
895
896 return this;
897
898};
899
900UI.Break.prototype = Object.create( UI.Element.prototype );
901
902
903// HorizontalRule
904
905UI.HorizontalRule = function () {
906
907 UI.Element.call( this );
908
909 var dom = document.createElement( 'hr' );
910 dom.className = 'HorizontalRule';
911
912 this.dom = dom;
913
914 return this;
915
916};
917
918UI.HorizontalRule.prototype = Object.create( UI.Element.prototype );
919
920
921// Button
922
923UI.Button = function ( value ) {
924
925 UI.Element.call( this );
926
927 var scope = this;
928
929 var dom = document.createElement( 'button' );
930 dom.className = 'Button';
931
932 this.dom = dom;
933 this.dom.textContent = value;
934
935 return this;
936
937};
938
939UI.Button.prototype = Object.create( UI.Element.prototype );
940
941UI.Button.prototype.setLabel = function ( value ) {
942
943 this.dom.textContent = value;
944
945 return this;
946
947};
Note: See TracBrowser for help on using the repository browser.