33

ImageInspector

Objective
  • Responder
    • View
      • Inspector
        • ImageInspector

Cliquez dans l'image. Sélectionnez un fichier JPG, PNG, GIF ou SVG. NOTE : La taille maximum du fichier est configurée à 1 Mo et la largeur maximum de l'affichage à 320 px. Replacez la souris sur l'image pour afficher ses dimensions. Ouvrez un dossier contenant des images avec l'explorateur de votre système de fichiers. Faites glisser et déposer un fichier JPG, PNG, GIF ou SVG sur l'image.

Essayez d'enregistrer sur votre disque et de charger le logo de Chrome, de Firefox ou le sigle en SVG. NOTE : Un SVG n'a pas de taille maximum et ses dimensions dépendent de la largeur maximum de l'affichage (320 px).

Pour lancer le chargement d'une image à partir d'un fichier avec un bouton, le code peut exécuter la méthode loadImage de l'inspecteur quand le bouton est cliqué. IMPORTANT : Pour des raisons de sécurité, loadImage doit être appelée en réponse à une interaction de l'utilisateur.

<p class="noprint"><button id="btn_load_image" type="submit" class="narrow" title=""><i class="fa fa-upload"></i></button></p>

Et en JavaScript :

document.getElementById('btn_load_image').onclick = () => inspector.loadImage();
  1. function ImageInspector(value = null, options = false) {
  2.     options = options || {};
  3.  
  4.     let filetypes = options.filetypes;
  5.     let maxsize = options.maxsize;
  6.  
  7.     let draganddrop = options.draganddrop === undefined ? true : (options.draganddrop ? true : false);
  8.     let loadonclick = options.loadonclick === undefined ? true : (options.loadonclick ? true : false);
  9.  
  10.     if (!this.validate(value))
  11.         throw new TypeError();
  12.  
  13.     if (filetypes === undefined)
  14.         filetypes = ImageInspector.defaultFileTypes;
  15.     else if (! (Array.isArray(filetypes) && filetypes.length > 0 && filetypes.every((e) => typeof e === 'string')))
  16.         throw new TypeError();
  17.  
  18.     if (maxsize === undefined)
  19.         maxsize = 0;
  20.     else if (typeof maxsize !== 'number')
  21.         throw new TypeError();
  22.     else if (maxsize < 0)
  23.         throw new RangeError();
  24.  
  25.     Inspector.call(this);
  26.  
  27.     if (value !== null) {
  28.         const [data, width, height] = value;
  29.  
  30.         this._value = data;
  31.         this._width = width;
  32.         this._height = height;
  33.     }
  34.  
  35.     this._type = undefined;
  36.     this._size = 0;
  37.  
  38.     this._filetypes = filetypes;
  39.     this._maxsize = maxsize;
  40.  
  41.     this._draganddrop = draganddrop;
  42.     this._loadonclick = loadonclick;
  43.  
  44.     this._imageWidget = null;
  45.     this._imageWidgetSrc = null;
  46. }
  47.  
  48. ImageInspector.prototype = Object.create(Inspector.prototype);
  49.  
  50. Object.defineProperty(ImageInspector.prototype, 'constructor', { value: ImageInspector, enumerable: false, writable: true });
  51.  
  52. ImageInspector.defaultFileTypes = ['image/jpeg', 'image/png', 'image/gif'];
  53.  
  54. Object.defineProperty(ImageInspector.prototype, 'width', {
  55.     get:    function() {
  56.         return this._width;
  57.     }
  58. });
  59.  
  60. Object.defineProperty(ImageInspector.prototype, 'height', {
  61.     get:    function() {
  62.         return this._height;
  63.     }
  64. });
  65.  
  66. Object.defineProperty(ImageInspector.prototype, 'type', {
  67.     get:    function() {
  68.         if (!this._value)
  69.             return undefined;
  70.  
  71.         if (this._type === undefined)
  72.             this._type = /^data:(image\/[-.+0-9a-zA-Z]+);base64,/.exec(this._value)[1];
  73.  
  74.         return this._type;
  75.     }
  76. });
  77.  
  78. Object.defineProperty(ImageInspector.prototype, 'size', {
  79.     get:    function() {
  80.         if (!this._value)
  81.             return 0;
  82.  
  83.         if (!this._size)
  84.             this._size = atob(this._value.substring(this._value.indexOf(',')+1)).length;
  85.  
  86.         return this._size;
  87.     }
  88. });
  89.  
  90. ImageInspector.prototype.validate = function(val) {
  91.     return val === null || (Array.isArray(val) && Validator.validateImageDataURL(val[0]) && Number.isInteger(val[1]) && Number.isInteger(val[2]) && val[1] >= 0 && val[2] >= 0);
  92. };
  93.  
  94. ImageInspector.prototype.get = function() {
  95.     return this._value ? [this._value, this._width, this._height] : null;
  96. };
  97.  
  98. ImageInspector.prototype.set = function(val) {
  99.     if (!this.validate(val))
  100.         return false;
  101.  
  102.     const [data, width, height] = val === null ? [null, 0, 0] : val;
  103.  
  104.     if (this._value !== data) {
  105.         this._value = data;
  106.  
  107.         this._width = width;
  108.         this._height = height;
  109.         this._type = undefined;
  110.         this._size = 0;
  111.  
  112.         if (this.interfaced())
  113.             this.resetWidget();
  114.     }
  115.  
  116.     return true;
  117. };
  118.  
  119. ImageInspector.prototype.loadImage = function() {
  120.     if (this._widget)
  121.         this._widget.click();
  122.  
  123.     return this;
  124. };
  125.  
  126. ImageInspector.prototype.reset = function() {
  127.     if (!this._widget)
  128.         return false;
  129.  
  130.     if (!this._imageWidget.src)
  131.         return false;
  132.  
  133.     this._loadurl(this._imageWidget.src);
  134.  
  135.     return true;
  136. };
  137.  
  138. ImageInspector.prototype.disable = function() {
  139.     Inspector.prototype.disable.call(this);
  140.  
  141.     if (this._imageWidget && this._loadonclick)
  142.         this._imageWidget.style.cursor = 'default';
  143.  
  144.     return this;
  145. };
  146.  
  147. ImageInspector.prototype.enable = function() {
  148.     Inspector.prototype.enable.call(this);
  149.  
  150.     if (this._imageWidget && this._loadonclick)
  151.         this._imageWidget.style.cursor = 'pointer';
  152.  
  153.     return this;
  154. };
  155.  
  156. ImageInspector.prototype.changeCallback = function(e) {
  157.     let val = e.target.value ? e.target.files[0] : false;
  158.  
  159.     if (val)
  160.         this._loadblob(e.target.files[0]);
  161. };
  162.  
  163. ImageInspector.prototype.resetWidget = function() {
  164.     if (this._imageWidget) {
  165.         this._imageWidget.src = this._value || this._imageWidgetSrc;
  166.  
  167.         this._imageWidget.setAttribute('title', this._value ? `${this._width}x${this._height}` : '');
  168.     }
  169.  
  170.     return this;
  171. };
  172.  
  173. ImageInspector.prototype.setWidget = function(w) {
  174.     if (w.tagName != 'IMG')
  175.         throw new TypeError();
  176.  
  177.     let input = document.createElement('input');
  178.  
  179.     input.type = 'file';
  180.     input.accept = this._filetypes.join(',');
  181.  
  182.     input.style.display = 'none';
  183.  
  184.     Inspector.prototype.setWidget.call(this, input);
  185.  
  186.     if (this._loadonclick) {
  187.         w.addEventListener('click', () => this.loadImage());
  188.         w.style.cursor = this.isEnabled() ? 'pointer' : 'default';
  189.     }
  190.  
  191.     if (this._draganddrop) {
  192.         w.addEventListener('drop', (e) => {
  193.             const dt = e.dataTransfer;
  194.  
  195.             e.preventDefault();
  196.  
  197.             if (dt.types.indexOf('Files') != -1) {
  198.                 this._loadblob(dt.files[0]);
  199.             }
  200.         });
  201.  
  202.         w.addEventListener('dragenter', (e) => {
  203.             const dt = e.dataTransfer;
  204.  
  205.             if (dt.types.indexOf('Files') != -1) {
  206.                 e.preventDefault();
  207.             }
  208.         });
  209.  
  210.         w.addEventListener('dragleave', (e) => {
  211.             e.preventDefault();
  212.         });
  213.  
  214.         w.addEventListener('dragover', (e) => {
  215.             const dt = e.dataTransfer;
  216.  
  217.             e.preventDefault();
  218.  
  219.             dt.dropEffect = dt.types.indexOf('Files') != -1 ? 'copy' : 'none';
  220.         });
  221.     }
  222.  
  223.     w.removeAttribute('width');
  224.     w.removeAttribute('height');
  225.  
  226.     w.after(input);
  227.  
  228.     this._imageWidget = w;
  229.     this._imageWidgetSrc = w.src;
  230.  
  231.     return this;
  232. };
  233.  
  234. ImageInspector.prototype.manageWidget = function(parent = null) {
  235.     Inspector.prototype.manageWidget.call(this, parent);
  236.  
  237.     if (this._parent && this._imageWidget)
  238.         this._parent.appendChild(this._imageWidget);
  239.  
  240.     return this;
  241. };
  242.  
  243. ImageInspector.prototype.unmanageWidget = function() {
  244.     Inspector.prototype.unmanageWidget.call(this);
  245.  
  246.     if (this._parent && this._imageWidget)
  247.         this._parent.removeChild(this._imageWidget);
  248.  
  249.     return this;
  250. };
  251.  
  252. ImageInspector.prototype.createWidget = function() {
  253.     const html = `<img src="${this._imageWidgetSrc}" alt="" title="" />`;
  254.  
  255.     let template = document.createElement('template');
  256.  
  257.     template.innerHTML = html;
  258.  
  259.     let widget = template.content.children[0];
  260.  
  261.     this.setWidget(widget);
  262.  
  263.     return this;
  264. };
  265.  
  266. ImageInspector.prototype.destroyWidget = function() {
  267.     Inspector.prototype.destroyWidget.call(this);
  268.  
  269.     this._imageWwidget = null;
  270.  
  271.     return this;
  272. };
  273.  
  274. ImageInspector.prototype._loadurl = function(url) {
  275.     const req = new XMLHttpRequest();
  276.  
  277.     req.open('GET', url);
  278.     req.responseType = 'blob';
  279.     req.setRequestHeader = this._filetypes.join(',');
  280.  
  281.     req.onload = () => this._loadblob(req.response);
  282.  
  283.     req.send();
  284. };
  285.  
  286. ImageInspector.prototype._loadblob = function(blob) {
  287.     if (this._maxsize > 0 && blob.size > this._maxsize)
  288.         return;
  289.  
  290.     if (this._filetypes.indexOf(blob.type) == -1)
  291.         return;
  292.  
  293.     const reader = new FileReader();
  294.  
  295.     reader.onload = (e) => {
  296.         let data = e.target.result;
  297.  
  298.         if (this._value !== data) {
  299.             this._value = data;
  300.             this._width = this._height = 0;
  301.             this._type = undefined;
  302.             this._size = blob.size;
  303.  
  304.             if (this._imageWidget) {
  305.                 this._imageWidget.addEventListener('load', (e) => this._onloadsrc(e), { once: true });
  306.                 this._imageWidget.src = data;
  307.             }
  308.         }
  309.     };
  310.  
  311.     reader.readAsDataURL(blob);
  312. };
  313.  
  314. ImageInspector.prototype._onloadsrc = function(e) {
  315.     const data = e.target.src;
  316.     const r = /^data:(image\/[-.+0-9a-zA-Z]+);base64,/.exec(data);
  317.  
  318.     if (r) {
  319.         const type = r[1];
  320.         const svg = type == 'image/svg+xml';
  321.  
  322.         const w = svg ? e.target.width : e.target.naturalWidth;
  323.         const h = svg ? e.target.height : e.target.naturalHeight;
  324.  
  325.         this._width = w;
  326.         this._height = h;
  327.         this._type = type;
  328.  
  329.         this._imageWidget.setAttribute('title', `${w}x${h}`);
  330.  
  331.         this.respondTo('inspectorValueChanged', this);
  332.     }
  333.     else
  334.         this._imageWidget.setAttribute('title', '');
  335. };
Test
  1. <?php $filetypes=array('image/jpeg', 'image/png', 'image/gif', 'image/svg+xml'); ?>
  2. <?php $maxsize=1000000; ?>
  3. <?php $width=320; ?>
  1. <?php $id=uniqid('id'); ?>
  1. .test_display img {
  2.     max-width: <?php echo $width; ?>px;
  3. }
  1. <div id="<?php echo $id; ?>" class="noprint">
  2. <div class="test_display"><img src="/files/images/htmlcssjs.jpg" alt=""/></div>
  3. </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/ImageInspector.js'); ?>
  6. <?php head('javascript', '/objectivejs/Validator.js'); ?>
  1. const filetypes = [<?php echo implode(',', array_map(function($s) { return "'$s'"; }, $filetypes)); ?>];
  2.  
  3. const inspector = new ImageInspector(null, { filetypes: filetypes, maxsize: <?php echo $maxsize; ?> });
  4.  
  5. const container = document.querySelector('#<?php echo $id; ?>');
  6.  
  7. inspector.setManagedWidget(container.querySelector('img'));
  1. inspector.reset();
VOIR AUSSI

Inspector, BooleanInspector, NumberInspector, StringInspector, SelectInspector, OptionInspector, SelectionInspector, ColorInspector, Validator

Commentaires

Votre commentaire :
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip aide 2000

Entrez un maximum de 2000 caractères.
Améliorez la présentation de votre texte avec les balises de formatage suivantes :
[p]paragraphe[/p], [b]gras[/b], [i]italique[/i], [u]souligné[/u], [s]barré[/s], [quote]citation[/quote], [pre]tel quel[/pre], [br]à la ligne,
[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]commande[/code], [code=langage]code source en c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].