rsence 2.0.9.23 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/INSTALL.rdoc +61 -49
  2. data/README.rdoc +20 -4
  3. data/VERSION +1 -1
  4. data/conf/default_conf.yaml +8 -0
  5. data/conf/rsence_command_strings.yaml +31 -20
  6. data/docs/ExampleGuiPlugin.rdoc +2 -2
  7. data/js/comm/comm.js +27 -5
  8. data/js/comm/transporter/transporter.js +1 -1
  9. data/js/comm/values/values.js +12 -5
  10. data/js/controls/button/button.js +12 -2
  11. data/js/controls/dialogs/alert_sheet/alert_sheet.js +13 -1
  12. data/js/controls/dialogs/confirm_sheet/confirm_sheet.js +13 -2
  13. data/js/controls/dialogs/sheet/sheet.js +35 -28
  14. data/js/controls/imageview/imageview.js +13 -13
  15. data/js/controls/progress/progressindicator/progressindicator.js +5 -5
  16. data/js/controls/sliders/slider/slider.js +4 -31
  17. data/js/controls/stepper/stepper.js +12 -19
  18. data/js/controls/textcontrol/textcontrol.js +0 -50
  19. data/js/controls/textcontrol/themes/default/textcontrol.html +1 -1
  20. data/js/controls/window/window.js +1 -1
  21. data/js/core/elem/elem.js +146 -160
  22. data/js/core/rsence_ns/rsence_ns.js +7 -0
  23. data/js/foundation/control/eventresponder/eventresponder.js +8 -7
  24. data/js/foundation/eventmanager/eventmanager.js +81 -48
  25. data/js/foundation/geom/rect/rect.js +1 -1
  26. data/js/foundation/json_renderer/json_renderer.js +4 -1
  27. data/js/foundation/system/system.js +37 -34
  28. data/js/foundation/view/morphanimation/morphanimation.js +53 -43
  29. data/js/foundation/view/view.js +119 -118
  30. data/js/lists/listitems/listitems.js +10 -10
  31. data/js/lists/propertylist/js.inc +0 -0
  32. data/js/lists/propertylist/propertylist.js +574 -0
  33. data/js/lists/propertylist/propertylisteditor/js.inc +0 -0
  34. data/js/lists/propertylist/propertylisteditor/propertylisteditor.js +233 -0
  35. data/js/lists/radiobuttonlist/radiobuttonlist.js +15 -8
  36. data/js/menus/minimenu/js.inc +0 -0
  37. data/js/menus/minimenu/minimenu.js +139 -0
  38. data/js/menus/minimenu/minimenuitem/js.inc +0 -0
  39. data/js/menus/minimenu/minimenuitem/minimenuitem.js +33 -0
  40. data/js/menus/minimenu/minimenuitem/themes/default/minimenuitem.css +45 -0
  41. data/js/menus/minimenu/minimenuitem/themes/default/minimenuitem.html +4 -0
  42. data/js/menus/minimenu/minimenuitem/themes/default/minimenuitem_checkmark.png +0 -0
  43. data/js/menus/minimenu/themes/default/minimenu.css +63 -0
  44. data/js/menus/minimenu/themes/default/minimenu.html +7 -0
  45. data/js/menus/minimenu/themes/default/minimenu.png +0 -0
  46. data/js/util/reloadapp/reloadapp.js +1 -1
  47. data/lib/conf/argv.rb +40 -11
  48. data/lib/daemon/daemon.rb +63 -22
  49. data/lib/plugins/gui_plugin.rb +28 -31
  50. data/lib/plugins/guiparser.rb +37 -7
  51. data/lib/plugins/plugin.rb +260 -28
  52. data/lib/plugins/plugin_base.rb +14 -0
  53. data/lib/plugins/plugin_plugins.rb +11 -1
  54. data/lib/plugins/pluginmanager.rb +127 -44
  55. data/lib/plugins/plugins.rb +10 -1
  56. data/lib/session/msg.rb +25 -1
  57. data/lib/session/sessionmanager.rb +11 -2
  58. data/lib/session/sessionstorage.rb +14 -14
  59. data/lib/transporter/transporter.rb +29 -13
  60. data/lib/values/hvalue.rb +30 -0
  61. data/plugins/client_pkg/info.yaml +2 -2
  62. data/plugins/{index_html → main}/img/loading.gif +0 -0
  63. data/plugins/{index_html → main}/img/riassence.gif +0 -0
  64. data/plugins/main/info.yaml +5 -4
  65. data/plugins/main/main.rb +180 -24
  66. data/plugins/{index_html → main}/tmpl/index.html +4 -2
  67. data/plugins/ticket/info.yaml +2 -2
  68. data/plugins/ticket/lib/upload.rb +57 -5
  69. data/plugins/ticket/ticket.rb +10 -4
  70. data/setup/welcome/info.yaml +2 -2
  71. data/setup/welcome/text/welcome.html +1 -1
  72. metadata +22 -11
  73. data/plugins/index_html/index_html.rb +0 -120
  74. data/plugins/index_html/info.yaml +0 -18
@@ -552,7 +552,7 @@ HView = HClass.extend({
552
552
  * ++
553
553
  **/
554
554
  _setCSS: function(_additional){
555
- var _cssStyle = 'display:none;overflow:hidden;visibility:hidden;';
555
+ var _cssStyle = 'overflow:hidden;visibility:hidden;';
556
556
  if(this.isAbsolute){
557
557
  _cssStyle += 'position:absolute;';
558
558
  } else {
@@ -568,20 +568,18 @@ HView = HClass.extend({
568
568
  * ++
569
569
  **/
570
570
  _getParentElemId: function(){
571
- var _parentElemId;
572
- // if the parent does not have an element:
573
- if(this.parent.elemId === undefined) {
574
- _parentElemId = 0;
575
- }
576
- // if a subview element is defined in the template, use it:
577
- else if(this.parent.markupElemIds&&this.parent.markupElemIds['subview']){
578
- _parentElemId = this.parent.markupElemIds['subview'];
571
+ var _parent = this.parent;
572
+ return ((_parent.elemId === undefined)?0:((_parent._getSubviewId===undefined)?0:_parent._getSubviewId()));
573
+ },
574
+
575
+ _getSubviewId: function(){
576
+ if(this.markupElemIds&&this.markupElemIds.subview!==undefined){
577
+ return this.markupElemIds.subview;
579
578
  }
580
- // otherwise, use main elemId
581
- else {
582
- _parentElemId = this.parent.elemId;
579
+ else if(this.elemId !== undefined) {
580
+ return this.elemId;
583
581
  }
584
- return _parentElemId;
582
+ return 0;
585
583
  },
586
584
 
587
585
  /** --
@@ -616,30 +614,52 @@ HView = HClass.extend({
616
614
  *
617
615
  **/
618
616
  drawRect: function() {
617
+ if(!this.rect.isValid){
618
+ console.log('invalid rect:',this.rect);//,ELEM.get(this.elemId));
619
+ }
620
+ if(!this.parent){
621
+ console.log('no parent:',ELEM.get(this.elemId));
622
+ }
619
623
  if (this.parent && this.rect.isValid) {
620
- var _this = this,
621
- _elemId = _this.elemId,
622
- _styl = ELEM.setStyle,
623
- _rect = _this.rect;
624
-
625
- _styl( _elemId, 'left', _this.flexLeft?(_rect.left+'px'):'auto', true);
626
- _styl( _elemId, 'top', _this.flexTop?(_rect.top+'px'):'auto', true);
627
- _styl( _elemId, 'right', _this.flexRight?(_this.flexRightOffset+'px'):'auto', true);
628
- _styl( _elemId, 'bottom', _this.flexBottom?(_this.flexBottomOffset+'px'):'auto', true);
629
- _styl( _elemId, 'width', (_this.flexLeft&&_this.flexRight)?'auto':(_rect.width+'px'), true);
630
- _styl( _elemId, 'height', (_this.flexTop&&_this.flexBottom)?'auto':(_rect.height+'px'), true);
631
-
624
+ var
625
+ i = 0,
626
+ _this = this,
627
+ _elemId = _this.elemId,
628
+ _styl = ELEM.setStyle,
629
+ _rect = _this.rect,
630
+ _auto = 'auto',
631
+ _left = _this.flexLeft?_rect.left:_auto,
632
+ _top = _this.flexTop?_rect.top:_auto,
633
+ _right = _this.flexRight?_this.flexRightOffset:_auto,
634
+ _bottom = _this.flexBottom?_this.flexBottomOffset:_auto,
635
+ _width = (_this.flexLeft&&_this.flexRight)?_auto:_rect.width,
636
+ _height = (_this.flexTop&&_this.flexBottom)?_auto:_rect.height,
637
+ _styles = [
638
+ [ 'left', _left ],
639
+ [ 'top', _top ],
640
+ [ 'right', _right ],
641
+ [ 'bottom', _bottom ],
642
+ [ 'width', _width ],
643
+ [ 'height', _height ],
644
+ [ 'display', _this.displayMode ]
645
+ ],
646
+ _key, _value;
632
647
  // Show the rectangle once it gets created, unless visibility was set to
633
648
  // hidden in the constructor.
634
- if(_this.isHidden === undefined || _this.isHidden === false) {
635
- _styl( _elemId, 'visibility', 'inherit', true);
649
+ if(!_this.isHidden) {
650
+ _styles.push( [ 'visibility', 'inherit' ] );
636
651
  }
637
-
638
- _styl( _elemId, 'display', _this.displayMode, true);
639
-
640
- _this._updateZIndex();
641
-
642
- if (_this._cachedLeft !== _rect.left || _this._cachedTop !== _rect.top) {
652
+ for(;i<_styles.length;i++){
653
+ _key = _styles[i][0];
654
+ _value = _styles[i][1];
655
+ if( i < 6 && _value !== _auto ){
656
+ _value += 'px';
657
+ }
658
+ _styl(_elemId,_key,_value,true);
659
+ }
660
+ (this.drown === false) && _this._updateZIndex();
661
+
662
+ if ( _this._cachedLeft !== _rect.left || _this._cachedTop !== _rect.top) {
643
663
  _this.invalidatePositionCache();
644
664
  _this._cachedLeft = _rect.left;
645
665
  _this._cachedTop = _rect.top;
@@ -688,15 +708,7 @@ HView = HClass.extend({
688
708
  }
689
709
  this.drawSubviews();
690
710
  if(this.options.style){
691
- var
692
- _style = this.options.style,
693
- _styleItem, _styleKey, _styleValue, i = 0;
694
- for(;i<_style.length;i++){
695
- _styleItem = _style[i];
696
- _styleKey = _styleItem[0];
697
- _styleValue = _styleItem[1];
698
- this.setStyle(_styleKey,_styleValue);
699
- }
711
+ this.setStyles( this.options.style );
700
712
  }
701
713
  if(this.options.html){
702
714
  this.setHTML(this.options.html);
@@ -756,7 +768,7 @@ HView = HClass.extend({
756
768
  **/
757
769
  markupElemNames: ['bg', 'label', 'state', 'control', 'value', 'subview'],
758
770
  drawMarkup: function() {
759
- ELEM.setStyle(this.elemId, 'display', 'none', true);
771
+ // ELEM.setStyle(this.elemId, 'display', 'none', true);
760
772
 
761
773
  // continue processing from here on:
762
774
  var _markupStatus = this._loadMarkup();
@@ -774,7 +786,7 @@ HView = HClass.extend({
774
786
  }
775
787
  }
776
788
 
777
- ELEM.setStyle(this.elemId, 'display', this.displayMode );
789
+ // ELEM.setStyle(this.elemId, 'display', this.displayMode );
778
790
  return this;
779
791
  },
780
792
 
@@ -818,8 +830,22 @@ HView = HClass.extend({
818
830
  * A string with the html escaped.
819
831
  **/
820
832
  escapeHTML: function( _html ) {
821
- return _html.replace(/&/gmi, '&amp;').replace(/>/gmi, '&gt;').replace(/</gmi, '&lt;');
822
- },
833
+ if( typeof _html !== 'string' ) {
834
+ return _html.toString();
835
+ }
836
+ for( var i=0, _reFrom, _reTo, _reArr = this._escapeHTMLArr; i < _reArr.length; i++ ){
837
+ _reFrom = _reArr[i][0];
838
+ _reTo = _reArr[i][1];
839
+ _html = _html.replace( _reFrom, _reTo );
840
+ }
841
+ return _html;
842
+ },
843
+ _escapeHTMLArr: [
844
+ [ new RegExp( /&/gmi ), '&amp;' ],
845
+ [ new RegExp( />/gmi ), '&gt;' ],
846
+ [ new RegExp( /</gmi ), '&lt;' ],
847
+ [ new RegExp( /\n/gmi ), '<br>' ]
848
+ ],
823
849
 
824
850
  /** = Description
825
851
  *
@@ -853,9 +879,18 @@ HView = HClass.extend({
853
879
  var _winSize = ELEM.windowSize();
854
880
  return [ _winSize[0], _winSize[1] ];
855
881
  }
856
- else{
857
- var _rect = this.parent.rect;
858
- return [ _rect.width, _rect.height ];
882
+ else {
883
+ var
884
+ _rect = this.parent.rect,
885
+ _width = _rect.width,
886
+ _height = _rect.height;
887
+ if (this.parent.flexLeft && this.parent.flexRight){
888
+ _width = parseInt( ELEM.getStyle(this.parent.elemId,'width',true), 10 );
889
+ }
890
+ if (this.parent.flexBottom && this.parent.flexTop){
891
+ _height = parseInt( ELEM.getStyle(this.parent.elemId,'height',true), 10 );
892
+ }
893
+ return [ _width, _height ];
859
894
  }
860
895
  },
861
896
 
@@ -866,17 +901,6 @@ HView = HClass.extend({
866
901
  return [ 0, 0, _parentSize[0], _parentSize[1] ];
867
902
  },
868
903
 
869
- parentSize: function(){
870
- var _parentElemId = this.parent.elemId;
871
- if ( _parentElemId === 0 ) {
872
- return ELEM.windowSize();
873
- }
874
- else {
875
- ELEM.flushLoop();
876
- return ELEM.getSize( _parentElemId );
877
- }
878
- },
879
-
880
904
  minWidth: 0,
881
905
  setMinWidth: function(_minWidth){
882
906
  this.minWidth = _minWidth;
@@ -926,7 +950,6 @@ HView = HClass.extend({
926
950
  _validHeight = (typeof _height === 'number'),
927
951
  _right,
928
952
  _bottom;
929
-
930
953
  if(_arrLen === 6){
931
954
  var
932
955
  _parentSize = this.parentSize(),
@@ -973,8 +996,8 @@ HView = HClass.extend({
973
996
  _validHeight && this.setMinHeight( _height );
974
997
  _bottom = _parentHeight - _bottomOffset;
975
998
  }
976
-
977
999
  this.rect = HRect.nu(_leftOffset,_topOffset,_right,_bottom);
1000
+
978
1001
  }
979
1002
  else {
980
1003
  console.log(_throwPrefix + 'the length has to be either 4 or 6.');
@@ -1007,7 +1030,19 @@ HView = HClass.extend({
1007
1030
  }
1008
1031
  return this;
1009
1032
  },
1010
-
1033
+
1034
+ setStyles: function(_styles){
1035
+ var
1036
+ _styleItem, _styleKey, _styleValue, i = 0;
1037
+ for(;i<_styles.length;i++){
1038
+ _styleItem = _styles[i];
1039
+ _styleKey = _styleItem[0];
1040
+ _styleValue = _styleItem[1];
1041
+ this.setStyle(_styleKey,_styleValue);
1042
+ }
1043
+ return this;
1044
+ },
1045
+
1011
1046
  /** = Description
1012
1047
  * Returns a style of the main DOM element of the component.
1013
1048
  * Utilizes +ELEM+ cache to perform the action.
@@ -1043,7 +1078,7 @@ HView = HClass.extend({
1043
1078
  if (!this['markupElemIds']){
1044
1079
  console.log('Warning, setStyleOfPart: no markupElemIds');
1045
1080
  }
1046
- else if (!this.markupElemIds[_partName]) {
1081
+ else if (this.markupElemIds[_partName]===undefined) {
1047
1082
  console.log('Warning, setStyleOfPart: partName "'+_partName+'" does not exist for viewId '+this.viewId+'.');
1048
1083
  }
1049
1084
  else {
@@ -1065,7 +1100,7 @@ HView = HClass.extend({
1065
1100
  *
1066
1101
  **/
1067
1102
  styleOfPart: function(_partName, _name) {
1068
- if (!this.markupElemIds[_partName]) {
1103
+ if (this.markupElemIds[_partName]===undefined) {
1069
1104
  console.log('Warning, styleOfPart: partName "'+_partName+'" does not exist for viewId '+this.viewId+'.');
1070
1105
  return '';
1071
1106
  }
@@ -1085,7 +1120,7 @@ HView = HClass.extend({
1085
1120
  *
1086
1121
  **/
1087
1122
  setMarkupOfPart: function( _partName, _value ) {
1088
- if (!this.markupElemIds[_partName]) {
1123
+ if (this.markupElemIds[_partName]===undefined) {
1089
1124
  console.log('Warning, setMarkupOfPart: partName "'+_partName+'" does not exist for viewId '+this.viewId+'.');
1090
1125
  }
1091
1126
  else {
@@ -1106,7 +1141,7 @@ HView = HClass.extend({
1106
1141
  *
1107
1142
  **/
1108
1143
  markupOfPart: function(_partName) {
1109
- if (!this.markupElemIds[_partName]) {
1144
+ if (this.markupElemIds[_partName]===undefined) {
1110
1145
  console.log('Warning, markupOfPart: partName "'+_partName+'" does not exist for viewId '+this.viewId+'.');
1111
1146
  return '';
1112
1147
  }
@@ -1121,16 +1156,12 @@ HView = HClass.extend({
1121
1156
  *
1122
1157
  **/
1123
1158
  hide: function() {
1124
- if(!this.isHidden) {
1125
- var _setStyl = ELEM.setStyle,
1126
- _elemId = this.elemId;
1127
- _setStyl(_elemId,'visibility', 'hidden');
1128
- // Required for the old, buggy Mozilla engines ( Firefox versions below 3.0 )
1129
- // At least text fields would show through from hidden parent elements.
1130
- // Disabled, because keeping the display as none causes hidden views to have no dimensions at all.
1131
- // _setStyl(_elemId,'display', 'none');
1132
- this.isHidden = true;
1133
- }
1159
+ ELEM.setStyle(this.elemId,'visibility', 'hidden', true);
1160
+ // Required for the old, buggy Mozilla engines ( Firefox versions below 3.0 )
1161
+ // At least text fields would show through from hidden parent elements.
1162
+ // Disabled, because keeping the display as none causes hidden views to have no dimensions at all.
1163
+ // ELEM.setStyle(this.elemId,'display', 'none');
1164
+ this.isHidden = true;
1134
1165
  return this;
1135
1166
  },
1136
1167
 
@@ -1142,13 +1173,9 @@ HView = HClass.extend({
1142
1173
  *
1143
1174
  **/
1144
1175
  show: function() {
1145
- if(this.isHidden) {
1146
- var _setStyl = ELEM.setStyle,
1147
- _elemId = this.elemId;
1148
- _setStyl(_elemId,'visibility', 'inherit');
1149
- _setStyl(_elemId,'display', this.displayMode);
1150
- this.isHidden = false;
1151
- }
1176
+ ELEM.setStyle(this.elemId,'display', this.displayMode, true);
1177
+ ELEM.setStyle(this.elemId,'visibility', 'inherit', true);
1178
+ this.isHidden = false;
1152
1179
  return this;
1153
1180
  },
1154
1181
 
@@ -1628,7 +1655,7 @@ HView = HClass.extend({
1628
1655
  ELEM.setCSS(_stringElem, "visibility:hidden;"+_extraCss);
1629
1656
  ELEM.setHTML(_stringElem, _string);
1630
1657
  // ELEM.flushLoop();
1631
- var _visibleSize=ELEM.getVisibleSize(_stringElem);
1658
+ var _visibleSize=ELEM.getSize(_stringElem);
1632
1659
  // console.log('visibleSize',_visibleSize);
1633
1660
  ELEM.del(_stringElem);
1634
1661
  return [_visibleSize[0]+_visibleSize[0]%2,_visibleSize[1]+_visibleSize[1]%2];
@@ -1649,20 +1676,13 @@ HView = HClass.extend({
1649
1676
  /** Returns the X coordinate that has the scrolled position calculated.
1650
1677
  **/
1651
1678
  pageX: function() {
1652
- var _x = 0,
1653
- _elem = this;
1654
- while(_elem) {
1655
- if(_elem.elemId && _elem.rect) {
1656
- _x += ELEM.get(_elem.elemId).offsetLeft;
1657
- _x -= ELEM.get(_elem.elemId).scrollLeft;
1658
- }
1659
- if(_elem.markupElemIds&&_elem.markupElemIds.subview){
1660
- _x += ELEM.get(_elem.markupElemIds.subview).offsetLeft;
1661
- _x -= ELEM.get(_elem.markupElemIds.subview).scrollLeft;
1662
- }
1663
- _elem = _elem.parent;
1664
- }
1665
- return _x;
1679
+ return ELEM._getVisibleLeftPosition( this.elemId );
1680
+ },
1681
+
1682
+ /** Returns the Y coordinate that has the scrolled position calculated.
1683
+ **/
1684
+ pageY: function() {
1685
+ return ELEM._getVisibleTopPosition( this.elemId );
1666
1686
  },
1667
1687
 
1668
1688
  /** = Description
@@ -1712,25 +1732,6 @@ HView = HClass.extend({
1712
1732
  return this;
1713
1733
  },
1714
1734
 
1715
- /** Returns the Y coordinate that has the scrolled position calculated.
1716
- **/
1717
- pageY: function() {
1718
- var _y = 0,
1719
- _elem = this;
1720
- while(_elem) {
1721
- if(_elem.elemId && _elem.rect) {
1722
- _y += ELEM.get(_elem.elemId).offsetTop;
1723
- _y -= ELEM.get(_elem.elemId).scrollTop;
1724
- }
1725
- if(_elem.markupElemIds&&_elem.markupElemIds.subview){
1726
- _y += ELEM.get(_elem.markupElemIds.subview).offsetTop;
1727
- _y -= ELEM.get(_elem.markupElemIds.subview).scrollTop;
1728
- }
1729
- _elem = _elem.parent;
1730
- }
1731
- return _y;
1732
- },
1733
-
1734
1735
  /** Returns the HPoint that has the scrolled position calculated.
1735
1736
  **/
1736
1737
  pageLocation: function() {
@@ -9,19 +9,19 @@
9
9
 
10
10
  /*** = Description
11
11
  ** HListItems is uses an array-packed list of hash objects as its value.
12
- ##
13
- ## == Value as Array of Hashes:
12
+ **
13
+ ** == Value as Array of Hashes:
14
14
  ** Each item in the array should have a 'label' and a 'value' key.
15
15
  ** The 'label' key of each item is used as the label for the HRadiobutton in the list.
16
16
  ** The 'value' key of each item is the value used for the output.
17
- ##
18
- ## == Value as Array of strings or numerals
19
- ## Each Item like with hash, except the item is both label and value. Each item should
20
- ## be unique.
21
- ##
22
- ## == Important
23
- ** The parent object of a HListItem needs to be a compatible hash, like HRadiobuttonList.
24
- ##
17
+ **
18
+ ** == Value as Array of strings or numerals
19
+ ** Each Item like with hash, except the item is both label and value. Each item should
20
+ ** be unique.
21
+ **
22
+ ** == Important
23
+ ** The parent object of a HListItem needs to be a compatible component, like HRadioButtonList.
24
+ **
25
25
  ***/
26
26
  var//RSence.Lists
27
27
  HListItems = HValueResponder.extend({
File without changes
@@ -0,0 +1,574 @@
1
+ /* RSence
2
+ * Copyright 2010 Riassence Inc.
3
+ * http://riassence.com/
4
+ *
5
+ * You should have received a copy of the GNU General Public License along
6
+ * with this software package. If not, contact licensing@riassence.com
7
+ */
8
+
9
+ /*** = Description
10
+ ** HPropertyList uses any JSON-compliant structure as its value and displays
11
+ ** its content hierarchically in three columns:
12
+ ** - Key
13
+ ** - Type
14
+ ** - Value
15
+ **
16
+ ** Its current purpose is to view JSON data in a structured way. I'll be
17
+ ** extended later as a full, generic JSON data editor.
18
+ **
19
+ ** NOTE: HPropertyList does not work in any version of Internet Explorer yet.
20
+ **
21
+ ***/
22
+ var//RSence.Lists
23
+ HPropertyList = HControl.extend({
24
+
25
+ defaultEvents: {
26
+ click: true
27
+ },
28
+
29
+ controlDefaults: HControlDefaults.extend({
30
+ keyColumnWidth: 100,
31
+ hideTypeColumn: false,
32
+ useEditor: false,
33
+ rowHeight: 15,
34
+ keyIndent: 8
35
+ }),
36
+
37
+ click: function(x,y){
38
+ if(this.options.useEditor){
39
+ var
40
+ clickY = y-this.contentView.pageY(),
41
+ itemNum = Math.floor(clickY/this.options.rowHeight);
42
+ if((clickY < 0) || (itemNum > this.valueTokens.length-1)){
43
+ this.editor.hide();
44
+ return;
45
+ }
46
+ this.editItem( itemNum );
47
+ }
48
+ },
49
+
50
+ keyColumnRight: function(){
51
+ return this.options.keyColumnWidth;
52
+ },
53
+ typeColumnLeft: function(){
54
+ return this.keyColumnRight();
55
+ },
56
+ typeColumnRight: function(){
57
+ return this.options.keyColumnWidth + 60;
58
+ },
59
+
60
+ valueColumnLeft: function(){
61
+ if(this.options.hideTypeColumn){
62
+ return this.keyColumnRight();
63
+ }
64
+ else {
65
+ return this.typeColumnRight();
66
+ }
67
+ },
68
+
69
+ drawSubviews: function(){
70
+
71
+ var borderAndBg = ELEM.make(this.elemId);
72
+ ELEM.setCSS(borderAndBg,'position:absolute;left:0;top:0;right:0;bottom:0;background-color:#e6e6e6;border:1px solid #999;');
73
+
74
+ this.markupElemIds = {
75
+ bg: borderAndBg
76
+ };
77
+
78
+ this.contentView = HScrollView.extend({
79
+ click: function(x,y){
80
+ this.parent.click(x,y);
81
+ return true;
82
+ }
83
+ }).nu(
84
+ [ 1, 25, null, null, 1, 1 ],
85
+ this, {
86
+ scrollY: 'auto',
87
+ scrollX: false,
88
+ events: {
89
+ click: true
90
+ }
91
+ }
92
+ );
93
+
94
+ var separatorParentElemId = ELEM.make(this.contentView.elemId);
95
+ ELEM.setCSS( separatorParentElemId, 'position:absolute;left:0;top:0;right:0;' );
96
+ this.separatortParentElemId = separatorParentElemId;
97
+
98
+ this.propertyItems = [];
99
+ // Editor initialization
100
+ if(this.options.useEditor){
101
+ this.editorValue = HValue.nu(
102
+ false, {
103
+ top: 0,
104
+ left: 0,
105
+ type: 'h',
106
+ name: '--',
107
+ value: {}
108
+ }
109
+ );
110
+ this.editor = HPropertyListEditor.nu(
111
+ [0,0,null,this.options.rowHeight+2,0,null],
112
+ this.contentView, {
113
+ propertyItems: this.propertyItems,
114
+ visible: false,
115
+ valueObj: this.editorValue
116
+ }
117
+ );
118
+ }
119
+
120
+ // Set row style heights from options
121
+ var rowHeightStyle = 'height:'+this.options.rowHeight+'px;';
122
+ this.keyRowStyle += rowHeightStyle;
123
+ this.typeRowStyle += rowHeightStyle;
124
+ this.valueRowStyle += rowHeightStyle;
125
+ this.rowSeparatorStyle += rowHeightStyle;
126
+
127
+ // Style common font style
128
+ this.contentView.setStyle('font-size','11px');
129
+
130
+ // Create the key column
131
+ this.keyColumn = HView.nu(
132
+ [ 0, 0, this.keyColumnRight(), 24 ],
133
+ this.contentView, {
134
+ style: [ [ 'border-right', '1px solid #999' ] ]
135
+ }
136
+ );
137
+
138
+ // Create the type column
139
+ if(!this.options.hideTypeColumn){
140
+ this.typeColumn = HView.nu(
141
+ [ this.typeColumnLeft(), 0, 60, 24 ],
142
+ this.contentView, {
143
+ style: [ [ 'border-right', '1px solid #999' ] ]
144
+ }
145
+ );
146
+ }
147
+
148
+ // Create the value column
149
+ this.valueColumn = HView.nu(
150
+ [ this.valueColumnLeft(), 0, 0, 24, 0, null ],
151
+ this.contentView
152
+ );
153
+
154
+ // Create the column headers
155
+ this.header = HView.extend({
156
+ drawSubviews: function(){
157
+ var
158
+ keyColumnWidth = this.parent.options.keyColumnWidth;
159
+ this.keyLabel = HView.nu(
160
+ [ 0, 0, this.parent.keyColumnRight(), 24 ],
161
+ this, {
162
+ html: '<b>Key</b>',
163
+ style: [
164
+ [ 'text-align', 'middle' ],
165
+ [ 'text-indent', '16px' ],
166
+ [ 'line-height', '24px' ],
167
+ [ 'font-size', '13px' ],
168
+ [ 'border-right', '3px double #999' ]
169
+ ]
170
+ }
171
+ );
172
+ if(!this.parent.options.hideTypeColumn){
173
+ this.typeLabel = HView.nu(
174
+ [ this.parent.typeColumnLeft(), 0, 60, 24 ],
175
+ this, {
176
+ html: '<b>Type</b>',
177
+ style: [
178
+ [ 'text-align', 'middle' ],
179
+ [ 'text-indent', '8px' ],
180
+ [ 'line-height', '24px' ],
181
+ [ 'font-size', '13px' ],
182
+ [ 'padding-right', '1px' ],
183
+ [ 'border-right', '1px solid #999' ]
184
+ ]
185
+ }
186
+ );
187
+ }
188
+ this.valueLabel = HView.nu(
189
+ [ this.parent.valueColumnLeft(), 0, 80, 24, 0, null ],
190
+ this, {
191
+ html: '<b>Value</b>',
192
+ style: [
193
+ [ 'text-align', 'middle' ],
194
+ [ 'text-indent', '8px' ],
195
+ [ 'line-height', '24px' ],
196
+ [ 'font-size', '13px' ]
197
+ ]
198
+ }
199
+ );
200
+ }
201
+ }).nu(
202
+ [ 0, 0, null, 24, 0, null ],
203
+ this, {
204
+ style: [ [ 'border-bottom', '1px solid #999' ] ]
205
+ }
206
+ );
207
+
208
+ // Create the resize control (invisible, just above the first column separator)
209
+ this.resizeColumns = HControl.extend({
210
+ drag: function(x,y){
211
+ var
212
+ parent = this.parent,
213
+ options = parent.options,
214
+ keyColumnWidth = x - parent.pageX(),
215
+ parentWidth = parent.rect.width;
216
+
217
+ if(keyColumnWidth < 80){
218
+ keyColumnWidth = 80;
219
+ }
220
+ else if ( keyColumnWidth > parentWidth-140 ){
221
+ keyColumnWidth = parentWidth - 140;
222
+ }
223
+
224
+ // Set the dragger itself
225
+ this.rect.offsetTo( keyColumnWidth-1, 0 ); this.drawRect();
226
+
227
+ // Resize the key column
228
+ options.keyColumnWidth = keyColumnWidth;
229
+
230
+ var
231
+ keyColumn = parent.keyColumn,
232
+ keyLabel = parent.header.keyLabel,
233
+ keyRight = parent.keyColumnRight();
234
+ keyColumn.rect.setRight( keyRight );
235
+ keyLabel.rect.setRight( keyRight );
236
+
237
+ var
238
+ valueColumn = parent.valueColumn,
239
+ valueLabel = parent.header.valueLabel,
240
+ valueLeft = parent.valueColumnLeft();
241
+
242
+ valueColumn.rect.setLeft( valueLeft );
243
+ valueLabel.rect.setLeft( valueLeft );
244
+
245
+ // Redraw the rects
246
+ keyColumn.drawRect();
247
+ keyLabel.drawRect();
248
+ valueColumn.drawRect();
249
+ valueLabel.drawRect();
250
+
251
+ // Resize the type column
252
+ if(!options.hideTypeColumn){
253
+ var
254
+ typeColumn = parent.typeColumn,
255
+ typeLabel = parent.header.typeLabel,
256
+ typeLeft = parent.typeColumnLeft(),
257
+ typeRight = parent.typeColumnRight();
258
+
259
+ typeColumn.rect.setLeft( typeLeft );
260
+ typeColumn.rect.setRight( typeRight );
261
+
262
+ typeLabel.rect.setLeft( typeLeft, 0 );
263
+ typeLabel.rect.setRight( typeRight, 0 );
264
+
265
+ typeColumn.drawRect();
266
+ typeLabel.drawRect();
267
+ }
268
+
269
+ if(options.useEditor){
270
+ parent.editor.resizeKeyColumn();
271
+ }
272
+
273
+ }
274
+ }).nu(
275
+ [ this.keyColumnRight(), 0, 5, 25 ],
276
+ this, {
277
+ events: { draggable: true },
278
+ style: [
279
+ [ 'cursor', 'ew-resize' ]
280
+ ]
281
+ }
282
+ );
283
+
284
+ },
285
+
286
+ // Tokenize arrays
287
+ arrayTokens: function( arr, name ){
288
+ this.addToken( 'a', name, '('+arr.length+' items)' );
289
+ this.nodeProperties.left += this.options.keyIndent;
290
+ var i = 0, val, type;
291
+ for( ; i < arr.length; i++ ){
292
+ val = arr[i];
293
+ type = this.itemType( val );
294
+ if( type == 'h' ){
295
+ this.hashTokens( val, i );
296
+ }
297
+ else if ( type == 'a' ){
298
+ this.arrayTokens( val, i );
299
+ }
300
+ else {
301
+ this.addToken( type, i, val );
302
+ }
303
+ }
304
+ this.nodeProperties.left -= this.options.keyIndent;
305
+ },
306
+
307
+ // Get length of hash
308
+ hashLen: function( hash ){
309
+ var count = 0;
310
+ for( var item in hash ){
311
+ count += 1;
312
+ }
313
+ return count;
314
+ },
315
+
316
+ // Sort hash keys
317
+ hashSortedKeys: function( hash ){
318
+ var
319
+ keys = [],
320
+ key;
321
+ for( key in hash ){
322
+ keys.push( key );
323
+ }
324
+ return keys.sort();
325
+ },
326
+
327
+ // Tokenize hashes
328
+ hashTokens: function( hash, name ){
329
+ this.addToken( 'h', name, '('+this.hashLen( hash )+' items)' );
330
+ this.nodeProperties.left += this.options.keyIndent;
331
+ var key, val, type, i = 0, keys = this.hashSortedKeys( hash );
332
+ for( ; i < keys.length; i++ ){
333
+ key = keys[i];
334
+ val = hash[key];
335
+ type = this.itemType( val );
336
+ if( type == 'h' ){
337
+ this.hashTokens( val, key );
338
+ }
339
+ else if ( type == 'a' ){
340
+ this.arrayTokens( val, key );
341
+ }
342
+ else {
343
+ this.addToken( type, key, val );
344
+ }
345
+ }
346
+ this.nodeProperties.left -= this.options.keyIndent;
347
+ },
348
+
349
+ // Adds a taken
350
+ addToken: function( type, name, value ){
351
+ this.valueTokens.push( {
352
+ top: this.nodeProperties.top,
353
+ left: this.nodeProperties.left,
354
+ type: type,
355
+ name: name,
356
+ value: value
357
+ } );
358
+ this.nodeProperties.top += this.options.rowHeight;
359
+ },
360
+
361
+ // Returns type of item
362
+ itemType: function( item ){
363
+ return COMM.Values.type( item );
364
+ },
365
+
366
+ // Translation from type code to type name
367
+ typeNames: {
368
+ h: 'Hash',
369
+ a: 'Array',
370
+ s: 'String',
371
+ n: 'Number',
372
+ b: 'Boolean',
373
+ '~': 'Null',
374
+ '-': 'Undefined'
375
+ },
376
+
377
+ // Style for the key rows
378
+ keyRowStyle: "position:absolute;padding-top:2px;right:0px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;",
379
+
380
+ // Creates row in key column
381
+ addKeyColumnControl: function( token, i ){
382
+ var elemId;
383
+ if( i >= this.propertyItems.length ){
384
+ elemId = ELEM.make( this.keyColumn.elemId );
385
+ this.propertyItems.push( elemId );
386
+ ELEM.setCSS( elemId, 'top:'+token.top+'px;'+this.keyRowStyle );
387
+ }
388
+ else {
389
+ elemId = this.propertyItems[i];
390
+ }
391
+ ELEM.setStyle( elemId, 'left', (token.left+10)+'px' );
392
+ if( token.type === 'h' || token.type === 'a' ){
393
+ ELEM.setStyle( elemId, 'font-weight', 'bold' );
394
+ }
395
+ else {
396
+ ELEM.setStyle( elemId, 'font-weight', 'inherit' );
397
+ }
398
+ ELEM.setHTML( elemId, token.name );
399
+ },
400
+
401
+ // Style for the type rows
402
+ typeRowStyle: "position:absolute;padding-top:2px;left:8px;width:72px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;",
403
+
404
+ // Creates row in the type column
405
+ addTypeColumnControl: function( token, i ){
406
+ var elemId;
407
+ if( i >= this.propertyItems.length ){
408
+ elemId = ELEM.make( this.typeColumn.elemId );
409
+ this.propertyItems.push( elemId );
410
+ ELEM.setCSS( elemId, 'top:'+token.top+'px;'+this.typeRowStyle );
411
+ }
412
+ else {
413
+ elemId = this.propertyItems[i];
414
+ }
415
+ ELEM.setHTML( elemId, this.typeNames[token.type] );
416
+ },
417
+
418
+ // Style for the value rows
419
+ valueRowStyle: "position:absolute;padding-top:2px;left:8px;right:0px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;",
420
+
421
+ // Creates row in the value column
422
+ addValueColumnControl: function( token, i ){
423
+ var elemId, value;
424
+ if( i >= this.propertyItems.length ){
425
+ elemId = ELEM.make( this.valueColumn.elemId );
426
+ this.propertyItems.push( elemId );
427
+ ELEM.setCSS( elemId, 'top:'+token.top+'px;'+this.valueRowStyle );
428
+ }
429
+ else {
430
+ elemId = this.propertyItems[i];
431
+ }
432
+ if( token.type === 'h' || token.type === 'a' ){
433
+ ELEM.setStyle( elemId, 'font-style', 'italic' );
434
+ }
435
+ else {
436
+ ELEM.setStyle( elemId, 'font-style', 'inherit' );
437
+ }
438
+ value = token.value;
439
+ if(value===true){
440
+ value = 'true';
441
+ }
442
+ else if(value===false){
443
+ value = 'false';
444
+ }
445
+ else if(value===undefined){
446
+ value = 'undefined';
447
+ }
448
+ else if(value===null){
449
+ value = 'null';
450
+ }
451
+ ELEM.setHTML( elemId, value );
452
+ },
453
+
454
+ // Row separator style
455
+ rowSeparatorStyle: "position:absolute;left:1px;right:1px;font-size:0px;height:1px;overflow:hidden;border-bottom:1px solid #999;",
456
+
457
+ // Adds row separator
458
+ addRowSeparator: function( token, i, even ){
459
+ if( i >= this.propertyItems.length ){
460
+ var elemId = ELEM.make( this.separatortParentElemId );
461
+ this.propertyItems.push( elemId );
462
+ ELEM.setCSS( elemId, 'top:'+token.top+'px;'+this.rowSeparatorStyle+'background-color:'+(even?'#f6f6f6':'#e6e6e6')+';' );
463
+ }
464
+ },
465
+
466
+ // Destructor, deletes extra elements created
467
+ die: function(){
468
+ var
469
+ i=0,
470
+ propLen = this.propertyItems.length,
471
+ elemId;
472
+ for(;i<propLen;i++){
473
+ elemId = this.propertyItems.pop();
474
+ ELEM.del( elemId );
475
+ }
476
+ this.base();
477
+ },
478
+
479
+ // Currently selected item
480
+ selectedItem: 0,
481
+ editNextItem: function(){
482
+ this.editItem(this.selectedItem+1);
483
+ },
484
+ editPrevItem: function(){
485
+ this.editItem(this.selectedItem-1);
486
+ },
487
+ editItem: function(itemNum){
488
+
489
+ if(itemNum>this.valueTokens.length-1){
490
+ itemNum = this.valueTokens.length-1;
491
+ }
492
+ else if(itemNum < 0){
493
+ itemNum = 0;
494
+ }
495
+
496
+ var
497
+ targetY = (itemNum*this.options.rowHeight)-1,
498
+ elem = ELEM.get( this.contentView.elemId ),
499
+ scrollTop = elem.scrollTop,
500
+ contentHeight = this.contentView.rect.height;
501
+
502
+ if(targetY > (scrollTop+contentHeight-45)){
503
+ elem.scrollTop = scrollTop+45;
504
+ }
505
+ else if(targetY < scrollTop+45){
506
+ elem.scrollTop = scrollTop-45;
507
+ }
508
+
509
+ this.selectedItem = itemNum;
510
+ this.editorValue.set( COMM.Values.clone(this.valueTokens[itemNum]) );
511
+ this.editor.show();
512
+ EVENT.changeActiveControl(this.editor);
513
+ this.editor.offsetTo( 0, targetY );
514
+ this.editor.bringToFront();
515
+ },
516
+
517
+ // Starts tokenizing, when the value is changed.
518
+ refreshValue: function(){
519
+ if(this['propertyItems']===undefined){
520
+ return;
521
+ }
522
+ this.valueTokens = [];
523
+ this.nodeProperties = {
524
+ top: 0,
525
+ left: 8
526
+ };
527
+ var rootType = this.itemType( this.value );
528
+ if( rootType == 'h' ){
529
+ this.hashTokens( this.value, 'Root' );
530
+ }
531
+ else if( rootType == 'a' ){
532
+ this.arrayTokens( this.value, 'Root' );
533
+ }
534
+ else {
535
+ this.addToken( rootType, 'Root', this.value );
536
+ }
537
+
538
+ var i, token;
539
+ if(this['propertyItems'] === undefined){
540
+ this.propertyItems = [];
541
+ }
542
+ var colHeight = 0, colId = 0;
543
+ for( i = 0; i < this.valueTokens.length; i ++ ) {
544
+ token = this.valueTokens[i];
545
+ this.addRowSeparator( token, colId, (i%2===0) ); colId++;
546
+ this.addKeyColumnControl( token, colId ); colId++;
547
+ if(!this.options.hideTypeColumn){
548
+ this.addTypeColumnControl( token, colId ); colId++;
549
+ }
550
+ this.addValueColumnControl( token, colId ); colId++;
551
+ colHeight = token.top+this.options.rowHeight;
552
+ }
553
+ var propItemsLen = this.propertyItems.length, elemId;
554
+ for( i = colId; i < propItemsLen; i++ ){
555
+ elemId = this.propertyItems.pop();
556
+ ELEM.del( elemId );
557
+ }
558
+ this.keyColumn.bringToFront();
559
+ if(!this.options.hideTypeColumn){
560
+ this.typeColumn.bringToFront();
561
+ }
562
+ this.valueColumn.bringToFront();
563
+ this.resizeColumns.bringToFront();
564
+ this.keyColumn.rect.setHeight( colHeight );
565
+ this.keyColumn.drawRect();
566
+ if(!this.options.hideTypeColumn){
567
+ this.typeColumn.rect.setHeight( colHeight );
568
+ this.typeColumn.drawRect();
569
+ }
570
+ this.valueColumn.rect.setHeight( colHeight );
571
+ this.valueColumn.drawRect();
572
+ ELEM.setStyle(this.separatortParentElemId,'height',(colHeight+25)+'px');
573
+ }
574
+ });