6

DimensionInspector

Objective
  • Responder
    • View
      • Inspector
        • DimensionInspector
   

Change the width or the height of the display. The other value is automatically computed to preserve the 4:3 aspect ratio of the display. NOTE: The dimension is constrained between 120x90 and 480x360.

  1. function DimensionInspector(width = 0, height = 0, options = false) {
  2.     if (!Number.isInteger(width))
  3.         throw new TypeError();
  4.  
  5.     if (!Number.isInteger(height))
  6.         throw new TypeError();
  7.  
  8.     options = options || {};
  9.  
  10.     let ratio = this.validateOptions(width, height, options);
  11.  
  12.     let minWidth = options.minWidth;
  13.     let maxWidth = options.maxWidth;
  14.     let minHeight = options.minHeight;
  15.     let maxHeight = options.maxHeight;
  16.  
  17.     if (width < minWidth || (maxWidth !== 'undefined' && width > maxWidth))
  18.         throw new RangeError();
  19.  
  20.     if (height < minHeight || (maxHeight !== 'undefined' && height > maxHeight))
  21.         throw new RangeError();
  22.  
  23.     Inspector.call(this);
  24.  
  25.     const widthInspector = new NumberInspector(width, {min: minWidth, max: maxWidth});
  26.     const heightInspector = new NumberInspector(height, {min: minHeight, max: maxHeight});
  27.  
  28.     this._widthInspector = widthInspector.addNextResponder(this);
  29.     this._heightInspector = heightInspector.addNextResponder(this);
  30.  
  31.     this._ratio = ratio;
  32. }
  33.  
  34. DimensionInspector.prototype = Object.create(Inspector.prototype);
  35.  
  36. Object.defineProperty(DimensionInspector.prototype, 'constructor', { value: DimensionInspector, enumerable: false, writable: true });
  37.  
  38. Object.defineProperty(DimensionInspector.prototype, 'ratio', {
  39.     get:    function() {
  40.         return this._ratio;
  41.     }
  42. });
  43.  
  44. Object.defineProperty(DimensionInspector.prototype, 'minWidth', {
  45.     get:    function() {
  46.         return this._widthInspector.min;
  47.     }
  48. });
  49.  
  50. Object.defineProperty(DimensionInspector.prototype, 'maxWidth', {
  51.     get:    function() {
  52.         return this._widthInspector.max;
  53.     }
  54. });
  55.  
  56. Object.defineProperty(DimensionInspector.prototype, 'minHeight', {
  57.     get:    function() {
  58.         return this._heightInspector.min;
  59.     }
  60. });
  61.  
  62. Object.defineProperty(DimensionInspector.prototype, 'maxHeight', {
  63.     get:    function() {
  64.         return this._heightInspector.max;
  65.     }
  66. });
  67.  
  68. DimensionInspector.prototype.validate = function(val) {
  69.     return Array.isArray(val) && val.length == 2 && this._widthInspector.validate(val[0]) && this._heightInspector.validate(val[1]);
  70. };
  71.  
  72. DimensionInspector.prototype.get = function() {
  73.     return [this._widthInspector.get(), this._heightInspector.get()];
  74. };
  75.  
  76. DimensionInspector.prototype.set = function(val) {
  77.     if (!this.validate(val))
  78.         return false;
  79.  
  80.     const [width, height] = val;
  81.  
  82.     if (this._ratio != DimensionInspector._computeRatio(width, height))
  83.         return false;
  84.  
  85.     if (this._minWidth !== 'undefined' && width < this._minWidth)
  86.         return false;
  87.  
  88.     if (this._maxWidth !== 'undefined' && width > this._maxWidth)
  89.         return false;
  90.  
  91.     if (this._minHeight !== 'undefined' && height < this._minHeight)
  92.         return false;
  93.  
  94.     if (this._maxHeight !== 'undefined' && height > this._maxHeight)
  95.         return false;
  96.  
  97.     this._widthInspector.set(width);
  98.     this._heightInspector.set(height);
  99.  
  100.     if (this.interfaced())
  101.         this.resetWidget();
  102.  
  103.     return true;
  104. };
  105.  
  106. DimensionInspector.prototype.setOptions = function(width, height, options) {
  107.     options = options || {};
  108.  
  109.     let ratio = this.validateOptions(width, height, options);
  110.  
  111.     this._widthInspector.min = options.minWidth;
  112.     this._widthInspector.max = options.maxWidth;
  113.     this._heightInspector.min = options.minHeight;
  114.     this._heightInspector.max = options.maxHeight;
  115.  
  116.     if (this._ratio !== ratio) {
  117.         this._ratio = ratio;
  118.  
  119.         if (ratio !== 0) {
  120.             if (width >= height)
  121.                 this.adjustHeight();
  122.             else
  123.                 this.adjustWidth();
  124.         }
  125.     }
  126.  
  127.     return this;
  128. };
  129.  
  130. DimensionInspector.prototype.validateOptions = function(width, height, options) {
  131.     let ratio = DimensionInspector._computeRatio(width, height);
  132.  
  133.     let minWidth = options.minWidth;
  134.     let maxWidth = options.maxWidth;
  135.     let minHeight = options.minHeight;
  136.     let maxHeight = options.maxHeight;
  137.  
  138.     if (typeof minWidth === 'undefined')
  139.         minWidth = 0;
  140.     else if (!Number.isInteger(minWidth))
  141.         throw new TypeError();
  142.  
  143.     if (typeof minHeight === 'undefined')
  144.         minHeight = 0;
  145.     else if (!Number.isInteger(minHeight))
  146.         throw new TypeError();
  147.  
  148.     if (! (typeof maxWidth === 'undefined' || Number.isInteger(maxWidth)))
  149.         throw new TypeError();
  150.  
  151.     if (! (typeof maxHeight === 'undefined' || Number.isInteger(maxHeight)))
  152.         throw new TypeError();
  153.  
  154.     if (maxWidth !== 'undefined' && minWidth > maxWidth)
  155.         throw new RangeError();
  156.  
  157.     if (maxHeight !== 'undefined' && minHeight > maxHeight)
  158.         throw new RangeError();
  159.  
  160.     if (ratio) {
  161.         if (maxWidth && maxHeight) {
  162.             if (ratio != DimensionInspector._computeRatio(maxWidth, maxHeight))
  163.                 throw new RangeError();
  164.         }
  165.         else if (maxWidth)
  166.             maxHeight = maxWidth / ratio;
  167.         else if (maxHeight)
  168.             maxWidth = maxHeight * ratio;
  169.  
  170.         if (minWidth && minHeight) {
  171.             if (ratio != DimensionInspector._computeRatio(minWidth, minHeight))
  172.                 throw new RangeError();
  173.         }
  174.         else if (minWidth)
  175.             minHeight = minWidth / ratio;
  176.         else if (minHeight)
  177.             minWidth = minHeight * ratio;
  178.     }
  179.  
  180.     options.minWidth = minWidth;
  181.     options.maxWidth = maxWidth;
  182.     options.minHeight = minHeight;
  183.     options.maxHeight = maxHeight;
  184.  
  185.     return ratio;
  186. };
  187.  
  188. DimensionInspector.prototype.adjustWidth = function() {
  189.     if (this._ratio)
  190.         this._widthInspector.set(2 * Math.round(this._heightInspector.get() * this._ratio / 2));
  191. };
  192.  
  193. DimensionInspector.prototype.adjustHeight = function() {
  194.     if (this._ratio)
  195.         this._heightInspector.set(2 * Math.round(this._widthInspector.get() / this._ratio / 2));
  196. };
  197.  
  198. DimensionInspector.prototype.inspectorValueChanged = function(sender) {
  199.     if (sender === this._widthInspector)
  200.         this.adjustHeight();
  201.     else if (sender === this._heightInspector)
  202.         this.adjustWidth();
  203.  
  204.     this.nextRespondTo('inspectorValueChanged', this);
  205.  
  206.     return true;
  207. };
  208.  
  209. DimensionInspector.prototype.resetWidget = function() {
  210.     this._widthInspector.resetWidget();
  211.     this._heightInspector.resetWidget();
  212.  
  213.     return true;
  214. };
  215.  
  216. DimensionInspector.prototype.setWidget = function(w) {
  217.     let wlist = w.querySelectorAll('input[type=number]');
  218.  
  219.     if (wlist.length != 2)
  220.         throw new TypeError();
  221.  
  222.     this._widthInspector.setWidget(wlist[0]);
  223.     this._heightInspector.setWidget(wlist[1]);
  224.  
  225.     View.prototype.setWidget.call(this, w);
  226.  
  227.     return this;
  228. };
  229.  
  230. DimensionInspector._computeRatio = (w, h) => w !== 0 && h !== 0 ? Math.round(w / h * 100) / 100 : 0;
Test
  1. <?php $bg='#fd1'; ?>
  2. <?php $width=240; ?>
  3. <?php $height=180; ?>
  4. <?php $minWidth=120; ?>
  5. <?php $maxWidth=480; ?>
  6. <?php $minHeight=90; ?>
  7. <?php $maxHeight=360; ?>
  1. <?php $id=uniqid('id'); ?>
  1. .test_display {
  2.     width: <?php echo $width; ?>px;
  3.     height: <?php echo $height; ?>px;
  4.     background: <?php echo $bg; ?>;
  5.     margin-bottom: 10px;
  6.     border-radius: 3px;
  7. }
  8. .size_panel > input {
  9.     width: 4em;
  10. }
  1. <div id="<?php echo $id; ?>" class="noprint">
  2. <div class="test_display"></div>
  3. <div class="ojs">
  4. <div>
  5. <span class="size_panel">
  6. <input type="number" step="40"/>&nbsp;<i class="fas fa-arrows-alt-h small"></i>
  7. <input type="number" step="30"/>&nbsp;<i class="fas fa-arrows-alt-v small"></i>
  8. </span>
  9. </div>
  10. </div>
  11. </div>
  1. <?php head('javascript', '/objectivejs/Objective.js'); ?>
  2. <?php head('javascript', '/objectivejs/Responder.js'); ?>
  3. <?php head('javascript', '/objectivejs/View.js'); ?>
  4. <?php head('javascript', '/objectivejs/Inspector.js'); ?>
  5. <?php head('javascript', '/objectivejs/NumberInspector.js'); ?>
  6. <?php head('javascript', '/objectivejs/DimensionInspector.js'); ?>
  1. function Tester(display, inspector) {
  2.     Responder.call(this);
  3.  
  4.     this._display = display;
  5.  
  6.     inspector.addNextResponder(this);
  7.  
  8.     this._inspector = inspector;
  9. }
  10.  
  11. Tester.prototype = Object.create(Responder.prototype);
  12.  
  13. Object.defineProperty(Tester.prototype, 'constructor', { value: Tester, enumerable: false, writable: true });
  14.  
  15. Tester.prototype.inspectorValueChanged = function(sender) {
  16.     if (sender === this._inspector) {
  17.         let [w, h] = sender.get();
  18.  
  19.         this._display.style.width = `${w}px`;
  20.         this._display.style.height = `${h}px`;
  21.     }
  22.  
  23.     return true;
  24. }
  1. const inspector = new DimensionInspector(<?php echo $width; ?>, <?php echo $height; ?>, {minWidth: <?php echo $minWidth; ?>, maxWidth: <?php echo $maxWidth; ?>, minHeight: <?php echo $minHeight; ?>, maxHeight: <?php echo $maxHeight; ?>});
  2.  
  3. const container = document.querySelector('#<?php echo $id; ?>');
  4.  
  5. const display = container.querySelector('.test_display');
  6.  
  7. inspector.setManagedWidget(container.querySelector('.size_panel')).resetWidget();
  8.  
  9. const tester = new Tester(display, inspector);
SEE ALSO

Inspector, NumberInspector

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].