Advertisement
Guest User

Untitled

a guest
Apr 20th, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class BluePrintInput {
  2.  
  3.   constructor(blueprint,settings) {
  4.  
  5.     settings = settings || {};
  6.  
  7.     this.blueprint = blueprint;
  8.     this.canvas = this.blueprint.canvas;
  9.     this.ctx = this.blueprint.ctx;
  10.  
  11.     // Like CSS Properties
  12.     this.top = settings.top || 0;
  13.     this.left = settings.left || 0;
  14.     this.width = settings.width || 150;
  15.     this.height = settings.height || 17;
  16.     this.paddingTop = settings.paddingTop || 0;
  17.     this.paddingLeft = settings.paddingLeft || 0;
  18.     this.paddingBottom = settings.paddingBottom || 0;
  19.     this.paddingRight = settings.paddingRight || 0;
  20.     this.marginTop = settings.marginTop || 0;
  21.     this.marginLeft = settings.marginLeft || 0;
  22.     this.marginBottom = settings.marginBottom || 0;
  23.     this.marginRight = settings.marginRight || 0;
  24.     this.background = settings.background || '#fff';
  25.     this.hover_background = settings.hover_background || '#00f';
  26.     this.focus_background = settings.focus_background || '#f00';
  27.     this.borderSize = settings.borderSize || 1;
  28.     this.borderColor = settings.borderColor || '#000';
  29.     this.hover_borderColor = settings.hover_borderColor || '#000';
  30.     this.focus_borderColor = settings.focus_borderColor || '#000';
  31.     this.radius = settings.radius || 0;
  32.     this.color = settings.color || '#000';
  33.     this.selectColor = settings.selectColor || '#08f';
  34.  
  35.     // Font
  36.     this.fontSize = 15;
  37.     this.fontFamily = 'Verdana';
  38.     this.font = this.fontSize+'px '+this.fontFamily;
  39.  
  40.     // Caret
  41.     this.caretX = 0;
  42.     this.caretY = 0;
  43.     this.caretWidth = settings.caretWidth || 1;
  44.     this.caretHeight = settings.caretHeight || this.fontSize;
  45.     this.caretColor = settings.caretColor || this.color;
  46.     this.caretTime = Date.now();
  47.     this.caretTick = settings.caretTick || 500;
  48.     this.caretIsVisible = false;
  49.     this.caretStart = 0;
  50.     this.caretEnd = 0;
  51.     this.caretSelection = false;
  52.  
  53.     // Focus & Blur event register
  54.     this.onfocus = typeof settings.onfocus === 'function' ? settings.onfocus : null;
  55.     this.onblur = typeof settings.onblur === 'function' ? settings.onblur : null;
  56.  
  57.     // Key Event
  58.     this.onkeydown  = typeof settings.onkeydown === 'function' ? settings.onkeydown : null;
  59.     this.onkeyup = typeof settings.onkeyup === 'function' ? settings.onkeyup : null;
  60.  
  61.     // Onchange Event
  62.     this.onchange = typeof settings.onchange === 'function' ? settings.onchange : null;
  63.  
  64.  
  65.     // overflow
  66.     this.overflowX = 0;
  67.  
  68.  
  69.     this.value = settings.value || '';
  70.     this.focusValue = this.value;
  71.  
  72.     this.isFocus = false;
  73.     this.canblur = false;
  74.     this.isMouseDown = false;
  75.  
  76.   }
  77.  
  78.  
  79.   /**
  80.   * Check if the control can be copy (CTRL + C)
  81.   * @return {Boolean} if the control can be copy
  82.   */
  83.   canCopy() {
  84.  
  85.     return this.caretEnd != this.caretStart;
  86.  
  87.   }
  88.  
  89.  
  90.   /**
  91.   * Check if the control can be cut (CTRL + X)
  92.   * @return {Boolean} if the control can be cut
  93.   */
  94.   canCut() {
  95.  
  96.     return this.caretEnd != this.caretStart;
  97.  
  98.   }
  99.  
  100.  
  101.   /**
  102.   * Copy Data from input (CTRL + C)
  103.   */
  104.   copy() {
  105.  
  106.     var caretStart = this.caretStart < this.caretEnd ? this.caretStart : this.caretEnd;
  107.     var caretEnd = this.caretStart < this.caretEnd ? this.caretEnd : this.caretStart;
  108.  
  109.     var value = this.value.slice(caretStart, caretEnd);
  110.  
  111.     var el = document.createElement('textarea');
  112.     el.value = value;
  113.     el.setAttribute('readonly', '');
  114.     el.style.position = 'fixed';
  115.     el.style.left = '-9999px';
  116.     document.body.appendChild(el);
  117.     el.select();
  118.     document.execCommand('copy');
  119.     document.body.removeChild(el);
  120.  
  121.   }
  122.  
  123.  
  124.   /**
  125.   * Cut Data from input (CTRL + X)
  126.   */
  127.   cut() {
  128.  
  129.     var caretStart = this.caretStart < this.caretEnd ? this.caretStart : this.caretEnd;
  130.     var caretEnd = this.caretStart < this.caretEnd ? this.caretEnd : this.caretStart;
  131.  
  132.     this.copy();
  133.  
  134.     var caretStart = this.caretStart < this.caretEnd ? this.caretStart : this.caretEnd;
  135.     var caretEnd = this.caretStart < this.caretEnd ? this.caretEnd : this.caretStart;
  136.     this.value = this.value.slice(0,caretStart) + this.value.substring(caretEnd);
  137.     if (this.caretStart > this.caretEnd) {
  138.       this.caretStart = this.caretEnd;
  139.     } else {
  140.       this.caretEnd = this.caretStart;
  141.     }
  142.  
  143.   }
  144.  
  145.  
  146.   /**
  147.   * Paste Data in input (CTRL + V) Event
  148.   * @param {String} clipboard
  149.   */
  150.   onPaste(text) {
  151.  
  152.     if (text == '') return;
  153.  
  154.     // replace with content already selected
  155.     if (this.canCopy()) {
  156.       var caretStart = this.caretStart < this.caretEnd ? this.caretStart : this.caretEnd;
  157.       var caretEnd = this.caretStart < this.caretEnd ? this.caretEnd : this.caretStart;
  158.       this.value = this.value.slice(0,caretStart) + this.value.substring(caretEnd);
  159.       if (this.caretStart > this.caretEnd) {
  160.         this.caretStart = this.caretEnd;
  161.       } else {
  162.         this.caretEnd = this.caretStart;
  163.       }
  164.     }
  165.  
  166.     this.value = this.value.slice(0,this.caretEnd) + text + this.value.substring(this.caretEnd);
  167.     this.caretEnd += text.length;
  168.     this.caretStart = this.caretEnd;
  169.  
  170.   }
  171.  
  172.  
  173.   /**
  174.   * Event: When the control has the focus
  175.   * @param {BluePrintInput} Event
  176.   */
  177.   onFocus(event) {
  178.  
  179.     this.isMouseDown = true;
  180.  
  181.     // Propagate the event
  182.     if (!this.isFocus) {
  183.  
  184.       this.isFocus = true;
  185.       this.focusValue = this.value;
  186.  
  187.       var _this = this;
  188.  
  189.       // extend the propagation outside
  190.       if (this.onfocus != null) this.onfocus(this);
  191.  
  192.       // register key event
  193.       this.blueprint.onkeydown = function(event){_this.onKeyDown(event);};
  194.       this.blueprint.onkeyup = function(event){_this.onKeyUp(event);};
  195.  
  196.       // register paste event
  197.       this.blueprint.onpaste = function(text){_this.onPaste(text);};
  198.  
  199.     }
  200.  
  201.   }
  202.  
  203.  
  204.   /**
  205.   * Event: When the control lost the focus
  206.   * @param {BluePrintInput} Event
  207.   */
  208.   onBlur(event) {
  209.  
  210.     // Propagate the event
  211.     if (this.isFocus) {
  212.  
  213.       this.isFocus = false;
  214.  
  215.       // extend the propagation outside
  216.       if (this.onblur != null) this.onblur(this);
  217.  
  218.       // if value change, fired the event onchange
  219.       if (this.focusValue != this.value) this.onChange(this);
  220.  
  221.       // unregister key event
  222.       this.blueprint.onkeydown = null;
  223.       this.blueprint.onkeyup = null;
  224.  
  225.       // unregister paste event
  226.       this.blueprint.onpaste = null;
  227.  
  228.     }
  229.  
  230.   }
  231.  
  232.  
  233.   /**
  234.   * Event: When the value is changed
  235.   * @param {BluePrintInput} Event
  236.   */
  237.   onChange(event) {
  238.  
  239.     if (this.onchange != null) this.onchange(event);
  240.  
  241.   }
  242.  
  243.  
  244.   /**
  245.   * Event: When user press down a key
  246.   * @param {KeyboardEvent} Event
  247.   */
  248.   onKeyDown(event) {
  249.  
  250.     var key = event.key;
  251.     var keyCode = event.keyCode;
  252.  
  253.     // CTRL + C
  254.     if ((event.ctrlKey || event.metaKey) && keyCode == 67 && this.canCopy()) {
  255.  
  256.       this.copy();
  257.  
  258.       return;
  259.     }
  260.  
  261.     // CTRL + X
  262.     if ((event.ctrlKey || event.metaKey) && keyCode == 88 && this.canCut()) {
  263.  
  264.       this.cut();
  265.  
  266.       return;
  267.     }
  268.  
  269.     if (event.ctrlKey || event.metaKey) return;
  270.  
  271.  
  272.     if (key.length == 1) {
  273.  
  274.       this.value = this.value.slice(0,this.caretEnd) + key + this.value.substring(this.caretEnd);
  275.       this.caretEnd++;
  276.       this.caretStart = this.caretEnd;
  277.  
  278.     } else {
  279.  
  280.       switch (keyCode) {
  281.         case 8: // Backspace
  282.           if (this.value.length > 0) {
  283.             if (this.caretStart == this.caretEnd) {
  284.               this.value = this.value.slice(0,this.caretEnd-1) + this.value.substring(this.caretEnd);
  285.               this.caretEnd--;
  286.               this.caretStart = this.caretEnd;
  287.             } else {
  288.               var caretStart = this.caretStart < this.caretEnd ? this.caretStart : this.caretEnd;
  289.               var caretEnd = this.caretStart < this.caretEnd ? this.caretEnd : this.caretStart;
  290.               this.value = this.value.slice(0,caretStart) + this.value.substring(caretEnd);
  291.               if (this.caretStart > this.caretEnd) {
  292.                 this.caretStart = this.caretEnd;
  293.               } else {
  294.                 this.caretEnd = this.caretStart;
  295.               }
  296.             }
  297.  
  298.           }
  299.           break;
  300.         case 37: // Arrow Left
  301.           if (this.caretEnd > 0) this.caretEnd--;
  302.           this.caretStart = this.caretEnd;
  303.           break;
  304.         case 39: // Arrow Right
  305.           if (this.caretEnd < this.value.length) this.caretEnd++;
  306.           this.caretStart = this.caretEnd;
  307.           break;
  308.         default:
  309.  
  310.       }
  311.  
  312.     }
  313.  
  314.  
  315.     if (this.onkeydown != null) this.onkeydown(event);
  316.  
  317.  
  318.   }
  319.  
  320.  
  321.   /**
  322.   * Event: When user press up a key
  323.   * @param {KeyboardEvent} Event
  324.   */
  325.   onKeyUp(event) {
  326.  
  327.     if (this.onkeyup != null) this.onkeyup(event);
  328.  
  329.   }
  330.  
  331.  
  332.   /**
  333.   * Overflow: translate
  334.   * @param {Boolean} apply a translate
  335.   * @return {Number} overflow translate
  336.   */
  337.   overflow(b) {
  338.  
  339.     if (BluePrintUtils.measureText(this.ctx,this.font,this.value.slice(0,this.caretEnd)) - this.overflowX > this.width) {
  340.       this.overflowX += this.width;
  341.     }
  342.  
  343.     if (BluePrintUtils.measureText(this.ctx,this.font,this.value.slice(0,this.caretEnd)) - this.overflowX < 0) {
  344.       this.overflowX -= this.width / 2;
  345.     }
  346.  
  347.     if (!b) this.ctx.translate(-this.overflowX,0);
  348.  
  349.     return this.overflowX;
  350.  
  351.   }
  352.  
  353.  
  354.   /**
  355.   * retrieve index of character in the whole string
  356.   * @return {Number} index of char
  357.   */
  358.   getStartMouse() {
  359.  
  360.     var x = ( this.blueprint.mouseX - this.canvas.width/2 ) / this.blueprint.zoom - (this.blueprint.x + this.blueprint.mx);
  361.  
  362.     var over = this.overflow(true);
  363.  
  364.     var index = null;
  365.     var value = this.value + " ";
  366.     for (var i = 0; i < value.length; i++) {
  367.       if (this.left + BluePrintUtils.measureText(this.ctx,this.font,value.slice(0,i)) > x + over) {
  368.         index = i;
  369.         break;
  370.       }
  371.     }
  372.  
  373.     return index == null ? this.value.length : index-1;
  374.  
  375.   }
  376.  
  377.  
  378.   /**
  379.   * draw Caret
  380.   */
  381.   drawCaret() {
  382.  
  383.     // blink the caret when focus
  384.     if (this.isFocus && Date.now() - this.caretTime > this.caretTick) {
  385.  
  386.       this.caretTime = Date.now();
  387.       this.caretIsVisible = this.caretIsVisible ? false : true;
  388.  
  389.     }
  390.  
  391.     // draw caret
  392.     if (this.caretIsVisible && this.isFocus) {
  393.  
  394.       // update caret position
  395.       this.caretX = BluePrintUtils.measureText(this.ctx, this.font, this.value.slice(0,this.caretEnd));
  396.  
  397.       this.caretIsVisible = true;
  398.  
  399.       this.ctx.save();
  400.  
  401.       this.blueprint.applyCamera(this.blueprint.x+this.blueprint.mx,this.blueprint.y+this.blueprint.my);
  402.  
  403.       this.ctx.translate(this.left,this.top);
  404.  
  405.       this.overflow();
  406.  
  407.       this.ctx.beginPath();
  408.       this.ctx.rect(this.caretX,this.caretY+1,this.caretWidth,this.caretHeight);
  409.       this.ctx.fillStyle = this.caretColor;
  410.       this.ctx.fill();
  411.  
  412.  
  413.       this.ctx.restore();
  414.  
  415.     }
  416.  
  417.  
  418.   }
  419.  
  420.  
  421.   /**
  422.   * Draw Method
  423.   * @param {Boolean} if a item is already overflown
  424.   * @param {Boolean} disable drawing
  425.   * @return {Boolean} return if mouse is overflown this item
  426.   */
  427.   draw(a,b) {
  428.  
  429.     var hover = false;
  430.  
  431.     this.ctx.save();
  432.  
  433.     this.blueprint.applyCamera(this.blueprint.x+this.blueprint.mx,this.blueprint.y+this.blueprint.my);
  434.  
  435.     // isHover ?
  436.     this.ctx.roundRect(
  437.       this.left-this.paddingLeft-this.borderSize,
  438.       this.top-this.paddingTop-this.borderSize,
  439.       this.width+this.paddingRight+this.paddingLeft+this.borderSize*2,
  440.       this.height+this.paddingBottom+this.paddingTop+this.borderSize*2,
  441.       this.radius
  442.     );
  443.     var hover = !a && this.ctx.isPointInPath(this.blueprint.mouseX,this.blueprint.mouseY);
  444.  
  445.     // Border
  446.     this.ctx.roundRect(
  447.       this.left-this.paddingLeft-this.borderSize,
  448.       this.top-this.paddingTop-this.borderSize,
  449.       this.width+this.paddingRight+this.paddingLeft+this.borderSize*2,
  450.       this.height+this.paddingBottom+this.paddingTop+this.borderSize*2,
  451.       this.radius
  452.     );
  453.     this.ctx.fillStyle = this.isFocus ? this.focus_borderColor : hover ? this.hover_borderColor : this.borderColor;
  454.     if (!b) this.ctx.fill();
  455.  
  456.     // Background
  457.     this.ctx.roundRect(
  458.       this.left-this.paddingLeft,
  459.       this.top-this.paddingTop,
  460.       this.width+this.paddingRight+this.paddingLeft,
  461.       this.height+this.paddingBottom+this.paddingTop,
  462.       this.radius
  463.     );
  464.     this.ctx.fillStyle = this.isFocus ? this.focus_background : hover ? this.hover_background : this.background;
  465.     if (!b) this.ctx.fill();
  466.  
  467.     // Overflow hidden
  468.     this.ctx.clip();
  469.  
  470.     // translate
  471.     this.overflow();
  472.  
  473.  
  474.     // draw selection
  475.     if (this.caretEnd != this.caretStart) {
  476.  
  477.       this.ctx.beginPath();
  478.       var color = BluePrintUtils.hexToRgb(this.selectColor);
  479.       var caretStart = this.caretStart < this.caretEnd ? this.caretStart : this.caretEnd;
  480.       var caretEnd = this.caretStart < this.caretEnd ? this.caretEnd : this.caretStart;
  481.       this.ctx.rect(this.left+BluePrintUtils.measureText(this.ctx,this.font,this.value.slice(0,caretStart)),this.top,BluePrintUtils.measureText(this.ctx,this.font,this.value.slice(caretStart,caretEnd)),this.fontSize+2);
  482.       this.ctx.fillStyle = 'rgba('+color.r+','+color.g+','+color.b+',0.8)';
  483.       if (!b) this.ctx.fill();
  484.  
  485.     }
  486.  
  487.  
  488.     // Remove Focus
  489.     if (!hover && !this.blueprint.mouseIsLeftDown && !this.canblur && this.isFocus) {
  490.       this.isMouseDown = false;
  491.       this.canblur = 1;
  492.     }
  493.     if (hover && !this.blueprint.mouseIsLeftDown) {
  494.       this.isMouseDown = false;
  495.     }
  496.     if (this.canblur == 1 && this.blueprint.mouseIsLeftDown) {
  497.       this.canblur = 2;
  498.     }
  499.     if (this.canblur == 2 && this.blueprint.mouseIsLeftDown) {
  500.       this.onBlur();
  501.       this.canblur = false;
  502.     }
  503.  
  504.  
  505.     // is Focused ?
  506.     if (hover && this.blueprint.mouseIsLeftDown) {
  507.       this.onFocus();
  508.     }
  509.     if (this.isFocus && this.isMouseDown) {
  510.  
  511.       var mouseX = (this.blueprint.mouseX - this.canvas.width/2) / this.blueprint.zoom - (this.blueprint.x+this.blueprint.mx);
  512.  
  513.       if (
  514.         mouseX > this.left &&
  515.         mouseX < this.left + this.width) {
  516.  
  517.           // retrieve the index of character in the string
  518.           this.caretEnd = this.getStartMouse();
  519.  
  520.           // show now the caret
  521.           this.caretTime = 0;
  522.           this.caretIsVisible = false;
  523.  
  524.           // starting selection
  525.           if (!this.caretSelection) {
  526.             this.caretStart = this.caretEnd;
  527.           }
  528.           this.caretSelection = true;
  529.  
  530.       } else {
  531.  
  532.         if (mouseX < this.left) {
  533.  
  534.           if (this.caretEnd > 0) {
  535.             this.caretEnd--;
  536.           }
  537.  
  538.         } else {
  539.  
  540.           if (this.caretEnd < this.value.length) {
  541.             this.caretEnd++;
  542.           }
  543.  
  544.         }
  545.  
  546.       }
  547.  
  548.  
  549.  
  550.     }
  551.  
  552.  
  553.     // Disable Selection
  554.     if (!this.blueprint.mouseIsLeftDown) {
  555.       this.caretSelection = false;
  556.     }
  557.  
  558.  
  559.     // Draw value
  560.     this.ctx.textBaseline = 'middle';
  561.     this.ctx.font = this.font;
  562.     this.ctx.fillStyle = this.color;
  563.     if (!b) this.ctx.fillText(this.value,this.left,this.top+this.height/2+2);
  564.  
  565.     // Draw caret
  566.     if (!b) this.drawCaret();
  567.  
  568.     this.ctx.restore();
  569.  
  570.     return hover || this.isFocus;
  571.  
  572.   }
  573.  
  574.  
  575.  
  576. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement