问:
Two signature pads in one form
I want to implement two signature pads in ONE form. One signature is for the applicant and the other one is for the evaluator.
The first pad works but the second pad is unresponsive. I am using JavaScript for the signature pads but it only works for the first pad. The signature will be saved to the database when the submit button is clicked. That is why id="save-signature-btn" is together with the code for the 'Submit' button.

form.blade.php

```<code>@extends('layouts.app')

@section('content')

<!doctype html>
<html lang="en">
<head>

</head>
<body>

{!! Form::open(['url' => 'page3/submit']) !!}

<h4 style="text-decoration: underline; font-weight: bold">Approved By:</h4>
<table class="table table-bordered">
    <tr>
        <th colspan="3">Approved By:</th>
    </tr>
    <tr>
        <th colspan="1">Name</th>
        <th colspan="1">Signature</th>
        <th colspan="1">Date</th>
    </tr>
    <tr colspan=4>
        <td colspan="1">
            <div class="form-group">
            {{Form::text('Officer_Name', '', ['class' => 'form-control', 'placeholder' => 'John Smith'])}}
            </div>
        </td>
        <td colspan="1">
            <div class="form-group">

            <canvas id="signature-canvas" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>

            <div id="signature-message"></div>

            <div id="signature-buttons">
                <input type="button" id="clear-signature-btn" value="Clear">
            </div>

                <input type="hidden" name="officer_signature" id="signature-data" value="">

            </div>
        </td>

        <td>
            <div class="form-group">
            {{Form::date('Approval_Date', '', ['class' => 'form-control'])}}
            </div>
        </td>

    </tr>
</table>

<br/>

<h4 style="text-decoration: underline; font-weight: bold">Applicant Signature:</h4>

            <div class="form-group">

            <canvas id="signature-canvas2" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>

            <div id="signature-message2"></div>

            <div id="signature-buttons2">
                <input type="button" id="clear-signature-btn2" value="Clear">
            </div>

                <input type="hidden" name="applicant_signature" id="signature-data2" value="">

            </div>

<br>

            <div class="signature_pad_save">
                <button type="submit" class="btn btn-primary" id="save-signature-btn">Submit</button>
            </div>

<script src="js/signature_pad.js"></script>
<script src="js/signature_data.js"></script>

</body>
</html>

@endsection('content')
</code>```

signature data.js

```<code>var clearButton = document.getElementById('clear-signature-btn'),
    saveButton = document.getElementById('save-signature-btn'),
    canvas = document.getElementById('signature-canvas'),
    signaturePad;

function resizeCanvas() {
    var ratio =  Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = canvas.offsetWidth * ratio;
    canvas.height = canvas.offsetHeight * ratio;
    canvas.getContext("2d").scale(ratio, ratio);
}

window.onresize = resizeCanvas;
resizeCanvas();

signaturePad = new SignaturePad(canvas);

clearButton.addEventListener('click', function (event) {
    signaturePad.clear();
});

saveButton.addEventListener('click', function (event) {
    if (signaturePad.isEmpty()) {
        alert('Signature pad is blank. Please draw your signature.');
    } else {
        var sdata = signaturePad.toDataURL();
        document.getElementById('signature-data').value = sdata;
        document.getElementById('signature-form').submit();
    }
});
</code>```

signature pad.js

```<code>(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.SignaturePad = factory());
}(this, (function () { 'use strict';

function Point(x, y, time) {
  this.x = x;
  this.y = y;
  this.time = time || new Date().getTime();
}

Point.prototype.velocityFrom = function (start) {
  return this.time !== start.time ? this.distanceTo(start) / (this.time - start.time) : 1;
};

Point.prototype.distanceTo = function (start) {
  return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
};

Point.prototype.equals = function (other) {
  return this.x === other.x && this.y === other.y && this.time === other.time;
};

function Bezier(startPoint, control1, control2, endPoint) {
  this.startPoint = startPoint;
  this.control1 = control1;
  this.control2 = control2;
  this.endPoint = endPoint;
}

// Returns approximated length.
Bezier.prototype.length = function () {
  var steps = 10;
  var length = 0;
  var px = void 0;
  var py = void 0;

  for (var i = 0; i <= steps; i += 1) {
    var t = i / steps;
    var cx = this._point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
    var cy = this._point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
    if (i > 0) {
      var xdiff = cx - px;
      var ydiff = cy - py;
      length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);
    }
    px = cx;
    py = cy;
  }

  return length;
};

/* eslint-disable no-multi-spaces, space-in-parens */
Bezier.prototype._point = function (t, start, c1, c2, end) {
  return start * (1.0 - t) * (1.0 - t) * (1.0 - t) + 3.0 * c1 * (1.0 - t) * (1.0 - t) * t + 3.0 * c2 * (1.0 - t) * t * t + end * t * t * t;
};

/* eslint-disable */

// http://stackoverflow.com/a/27078401/815507
function throttle(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function later() {
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  return function () {
    var now = Date.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
}

function SignaturePad(canvas, options) {
  var self = this;
  var opts = options || {};

  this.velocityFilterWeight = opts.velocityFilterWeight || 0.7;
  this.minWidth = opts.minWidth || 0.5;
  this.maxWidth = opts.maxWidth || 2.5;
  this.throttle = 'throttle' in opts ? opts.throttle : 16; // in miliseconds
  this.minDistance = 'minDistance' in opts ? opts.minDistance : 5;

  if (this.throttle) {
    this._strokeMoveUpdate = throttle(SignaturePad.prototype._strokeUpdate, this.throttle);
  } else {
    this._strokeMoveUpdate = SignaturePad.prototype._strokeUpdate;
  }

  this.dotSize = opts.dotSize || function () {
    return (this.minWidth + this.maxWidth) / 2;
  };
  this.penColor = opts.penColor || 'black';
  this.backgroundColor = opts.backgroundColor || 'rgba(0,0,0,0)';
  this.onBegin = opts.onBegin;
  this.onEnd = opts.onEnd;

  this._canvas = canvas;
  this._ctx = canvas.getContext('2d');
  this.clear();

  // We need add these inline so they are available to unbind while still having
  // access to 'self' we could use _.bind but it's not worth adding a dependency.
  this._handleMouseDown = function (event) {
    if (event.which === 1) {
      self._mouseButtonDown = true;
      self._strokeBegin(event);
    }
  };

  this._handleMouseMove = function (event) {
    if (self._mouseButtonDown) {
      self._strokeMoveUpdate(event);
    }
  };

  this._handleMouseUp = function (event) {
    if (event.which === 1 && self._mouseButtonDown) {
      self._mouseButtonDown = false;
      self._strokeEnd(event);
    }
  };

  this._handleTouchStart = function (event) {
    if (event.targetTouches.length === 1) {
      var touch = event.changedTouches[0];
      self._strokeBegin(touch);
    }
  };

  this._handleTouchMove = function (event) {
    // Prevent scrolling.
    event.preventDefault();

    var touch = event.targetTouches[0];
    self._strokeMoveUpdate(touch);
  };

  this._handleTouchEnd = function (event) {
    var wasCanvasTouched = event.target === self._canvas;
    if (wasCanvasTouched) {
      event.preventDefault();
      self._strokeEnd(event);
    }
  };

  // Enable mouse and touch event handlers
  this.on();
}

// Public methods
SignaturePad.prototype.clear = function () {
  var ctx = this._ctx;
  var canvas = this._canvas;

  ctx.fillStyle = this.backgroundColor;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  this._data = [];
  this._reset();
  this._isEmpty = true;
};

SignaturePad.prototype.fromDataURL = function (dataUrl) {
  var _this = this;

  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  var image = new Image();
  var ratio = options.ratio || window.devicePixelRatio || 1;
  var width = options.width || this._canvas.width / ratio;
  var height = options.height || this._canvas.height / ratio;

  this._reset();
  image.src = dataUrl;
  image.onload = function () {
    _this._ctx.drawImage(image, 0, 0, width, height);
  };
  this._isEmpty = false;
};

SignaturePad.prototype.toDataURL = function (type) {
  var _canvas;

  switch (type) {
    case 'image/svg+xml':
      return this._toSVG();
    default:
      for (var _len = arguments.length, options = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        options[_key - 1] = arguments[_key];
      }

      return (_canvas = this._canvas).toDataURL.apply(_canvas, [type].concat(options));
  }
};

SignaturePad.prototype.on = function () {
  this._handleMouseEvents();
  this._handleTouchEvents();
};

SignaturePad.prototype.off = function () {
  this._canvas.removeEventListener('mousedown', this._handleMouseDown);
  this._canvas.removeEventListener('mousemove', this._handleMouseMove);
  document.removeEventListener('mouseup', this._handleMouseUp);

  this._canvas.removeEventListener('touchstart', this._handleTouchStart);
  this._canvas.removeEventListener('touchmove', this._handleTouchMove);
  this._canvas.removeEventListener('touchend', this._handleTouchEnd);
};

SignaturePad.prototype.isEmpty = function () {
  return this._isEmpty;
};

// Private methods
SignaturePad.prototype._strokeBegin = function (event) {
  this._data.push([]);
  this._reset();
  this._strokeUpdate(event);

  if (typeof this.onBegin === 'function') {
    this.onBegin(event);
  }
};

SignaturePad.prototype._strokeUpdate = function (event) {
  var x = event.clientX;
  var y = event.clientY;

  var point = this._createPoint(x, y);
  var lastPointGroup = this._data[this._data.length - 1];
  var lastPoint = lastPointGroup && lastPointGroup[lastPointGroup.length - 1];
  var isLastPointTooClose = lastPoint && point.distanceTo(lastPoint) < this.minDistance;

  // Skip this point if it's too close to the previous one
  if (!(lastPoint && isLastPointTooClose)) {
    var _addPoint = this._addPoint(point),
        curve = _addPoint.curve,
        widths = _addPoint.widths;

    if (curve && widths) {
      this._drawCurve(curve, widths.start, widths.end);
    }

    this._data[this._data.length - 1].push({
      x: point.x,
      y: point.y,
      time: point.time,
      color: this.penColor
    });
  }
};

SignaturePad.prototype._strokeEnd = function (event) {
  var canDrawCurve = this.points.length > 2;
  var point = this.points[0]; // Point instance

  if (!canDrawCurve && point) {
    this._drawDot(point);
  }

  if (point) {
    var lastPointGroup = this._data[this._data.length - 1];
    var lastPoint = lastPointGroup[lastPointGroup.length - 1]; // plain object

    // When drawing a dot, there's only one point in a group, so without this check
    // such group would end up with exactly the same 2 points.
    if (!point.equals(lastPoint)) {
      lastPointGroup.push({
        x: point.x,
        y: point.y,
        time: point.time,
        color: this.penColor
      });
    }
  }

  if (typeof this.onEnd === 'function') {
    this.onEnd(event);
  }
};

SignaturePad.prototype._handleMouseEvents = function () {
  this._mouseButtonDown = false;

  this._canvas.addEventListener('mousedown', this._handleMouseDown);
  this._canvas.addEventListener('mousemove', this._handleMouseMove);
  document.addEventListener('mouseup', this._handleMouseUp);
};

SignaturePad.prototype._handleTouchEvents = function () {
  // Pass touch events to canvas element on mobile IE11 and Edge.
  this._canvas.style.msTouchAction = 'none';
  this._canvas.style.touchAction = 'none';

  this._canvas.addEventListener('touchstart', this._handleTouchStart);
  this._canvas.addEventListener('touchmove', this._handleTouchMove);
  this._canvas.addEventListener('touchend', this._handleTouchEnd);
};

SignaturePad.prototype._reset = function () {
  this.points = [];
  this._lastVelocity = 0;
  this._lastWidth = (this.minWidth + this.maxWidth) / 2;
  this._ctx.fillStyle = this.penColor;
};

SignaturePad.prototype._createPoint = function (x, y, time) {
  var rect = this._canvas.getBoundingClientRect();

  return new Point(x - rect.left, y - rect.top, time || new Date().getTime());
};

SignaturePad.prototype._addPoint = function (point) {
  var points = this.points;
  var tmp = void 0;

  points.push(point);

  if (points.length > 2) {
    // To reduce the initial lag make it work with 3 points
    // by copying the first point to the beginning.
    if (points.length === 3) points.unshift(points[0]);

    tmp = this._calculateCurveControlPoints(points[0], points[1], points[2]);
    var c2 = tmp.c2;
    tmp = this._calculateCurveControlPoints(points[1], points[2], points[3]);
    var c3 = tmp.c1;
    var curve = new Bezier(points[1], c2, c3, points[2]);
    var widths = this._calculateCurveWidths(curve);

    // Remove the first element from the list,
    // so that we always have no more than 4 points in points array.
    points.shift();

    return { curve: curve, widths: widths };
  }

  return {};
};

SignaturePad.prototype._calculateCurveControlPoints = function (s1, s2, s3) {
  var dx1 = s1.x - s2.x;
  var dy1 = s1.y - s2.y;
  var dx2 = s2.x - s3.x;
  var dy2 = s2.y - s3.y;

  var m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
  var m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };

  var l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
  var l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);

  var dxm = m1.x - m2.x;
  var dym = m1.y - m2.y;

  var k = l2 / (l1 + l2);
  var cm = { x: m2.x + dxm * k, y: m2.y + dym * k };

  var tx = s2.x - cm.x;
  var ty = s2.y - cm.y;

  return {
    c1: new Point(m1.x + tx, m1.y + ty),
    c2: new Point(m2.x + tx, m2.y + ty)
  };
};

SignaturePad.prototype._calculateCurveWidths = function (curve) {
  var startPoint = curve.startPoint;
  var endPoint = curve.endPoint;
  var widths = { start: null, end: null };

  var velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) + (1 - this.velocityFilterWeight) * this._lastVelocity;

  var newWidth = this._strokeWidth(velocity);

  widths.start = this._lastWidth;
  widths.end = newWidth;

  this._lastVelocity = velocity;
  this._lastWidth = newWidth;

  return widths;
};

SignaturePad.prototype._strokeWidth = function (velocity) {
  return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
};

SignaturePad.prototype._drawPoint = function (x, y, size) {
  var ctx = this._ctx;

  ctx.moveTo(x, y);
  ctx.arc(x, y, size, 0, 2 * Math.PI, false);
  this._isEmpty = false;
};

SignaturePad.prototype._drawCurve = function (curve, startWidth, endWidth) {
  var ctx = this._ctx;
  var widthDelta = endWidth - startWidth;
  var drawSteps = Math.floor(curve.length());

  ctx.beginPath();

  for (var i = 0; i < drawSteps; i += 1) {
    // Calculate the Bezier (x, y) coordinate for this step.
    var t = i / drawSteps;
    var tt = t * t;
    var ttt = tt * t;
    var u = 1 - t;
    var uu = u * u;
    var uuu = uu * u;

    var x = uuu * curve.startPoint.x;
    x += 3 * uu * t * curve.control1.x;
    x += 3 * u * tt * curve.control2.x;
    x += ttt * curve.endPoint.x;

    var y = uuu * curve.startPoint.y;
    y += 3 * uu * t * curve.control1.y;
    y += 3 * u * tt * curve.control2.y;
    y += ttt * curve.endPoint.y;

    var width = startWidth + ttt * widthDelta;
    this._drawPoint(x, y, width);
  }

  ctx.closePath();
  ctx.fill();
};

SignaturePad.prototype._drawDot = function (point) {
  var ctx = this._ctx;
  var width = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;

  ctx.beginPath();
  this._drawPoint(point.x, point.y, width);
  ctx.closePath();
  ctx.fill();
};

SignaturePad.prototype._fromData = function (pointGroups, drawCurve, drawDot) {
  for (var i = 0; i < pointGroups.length; i += 1) {
    var group = pointGroups[i];

    if (group.length > 1) {
      for (var j = 0; j < group.length; j += 1) {
        var rawPoint = group[j];
        var point = new Point(rawPoint.x, rawPoint.y, rawPoint.time);
        var color = rawPoint.color;

        if (j === 0) {
          // First point in a group. Nothing to draw yet.

          // All points in the group have the same color, so it's enough to set
          // penColor just at the beginning.
          this.penColor = color;
          this._reset();

          this._addPoint(point);
        } else if (j !== group.length - 1) {
          // Middle point in a group.
          var _addPoint2 = this._addPoint(point),
              curve = _addPoint2.curve,
              widths = _addPoint2.widths;

          if (curve && widths) {
            drawCurve(curve, widths, color);
          }
        } else {
          // Last point in a group. Do nothing.
        }
      }
    } else {
      this._reset();
      var _rawPoint = group[0];
      drawDot(_rawPoint);
    }
  }
};

SignaturePad.prototype._toSVG = function () {
  var _this2 = this;

  var pointGroups = this._data;
  var canvas = this._canvas;
  var ratio = Math.max(window.devicePixelRatio || 1, 1);
  var minX = 0;
  var minY = 0;
  var maxX = canvas.width / ratio;
  var maxY = canvas.height / ratio;
  var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');

  svg.setAttributeNS(null, 'width', canvas.width);
  svg.setAttributeNS(null, 'height', canvas.height);

  this._fromData(pointGroups, function (curve, widths, color) {
    var path = document.createElement('path');

    // Need to check curve for NaN values, these pop up when drawing
    // lines on the canvas that are not continuous. E.g. Sharp corners
    // or stopping mid-stroke and than continuing without lifting mouse.
    if (!isNaN(curve.control1.x) && !isNaN(curve.control1.y) && !isNaN(curve.control2.x) && !isNaN(curve.control2.y)) {
      var attr = 'M ' + curve.startPoint.x.toFixed(3) + ',' + curve.startPoint.y.toFixed(3) + ' ' + ('C ' + curve.control1.x.toFixed(3) + ',' + curve.control1.y.toFixed(3) + ' ') + (curve.control2.x.toFixed(3) + ',' + curve.control2.y.toFixed(3) + ' ') + (curve.endPoint.x.toFixed(3) + ',' + curve.endPoint.y.toFixed(3));

      path.setAttribute('d', attr);
      path.setAttribute('stroke-width', (widths.end * 2.25).toFixed(3));
      path.setAttribute('stroke', color);
      path.setAttribute('fill', 'none');
      path.setAttribute('stroke-linecap', 'round');

      svg.appendChild(path);
    }
  }, function (rawPoint) {
    var circle = document.createElement('circle');
    var dotSize = typeof _this2.dotSize === 'function' ? _this2.dotSize() : _this2.dotSize;
    circle.setAttribute('r', dotSize);
    circle.setAttribute('cx', rawPoint.x);
    circle.setAttribute('cy', rawPoint.y);
    circle.setAttribute('fill', rawPoint.color);

    svg.appendChild(circle);
  });

  var prefix = 'data:image/svg+xml;base64,';
  var header = '<svg' + ' xmlns="http://www.w3.org/2000/svg"' + ' xmlns:xlink="http://www.w3.org/1999/xlink"' + (' viewBox="' + minX + ' ' + minY + ' ' + maxX + ' ' + maxY + '"') + (' width="' + maxX + '"') + (' height="' + maxY + '"') + '>';
  var body = svg.innerHTML;

  // IE hack for missing innerHTML property on SVGElement
  if (body === undefined) {
    var dummy = document.createElement('dummy');
    var nodes = svg.childNodes;
    dummy.innerHTML = '';

    for (var i = 0; i < nodes.length; i += 1) {
      dummy.appendChild(nodes[i].cloneNode(true));
    }

    body = dummy.innerHTML;
  }

  var footer = '</svg>';
  var data = header + body + footer;

  return prefix + btoa(data);
};

SignaturePad.prototype.fromData = function (pointGroups) {
  var _this3 = this;

  this.clear();

  this._fromData(pointGroups, function (curve, widths) {
    return _this3._drawCurve(curve, widths.start, widths.end);
  }, function (rawPoint) {
    return _this3._drawDot(rawPoint);
  });

  this._data = pointGroups;
};

SignaturePad.prototype.toData = function () {
  return this._data;
};

return SignaturePad;

})));
</code>```

答:
In your javascript code you are working only with

```<code>canvas = document.getElementById('signature-canvas')
</code>```

So that is the problem.

You should add a class on both signature canvases in html code for example signature like this:

```<code><canvas id="signature-canvas" class="signature" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>

<canvas id="signature-canvas2" class="signature" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>
</code>```

And then in javascript add one more pair of commands for second signature pad for control buttons (submit and reset) for second canvas.

Title: Two signature pads in one form

Body:
I want to implement two signature pads in ONE form. One signature is for the applicant and the other one is for the evaluator.
The first pad works but the second pad is unresponsive. I am using JavaScript for the signature pads but it only works for the first pad. The signature will be saved to the database when the submit button is clicked. That is why id="save-signature-btn" is together with the code for the 'Submit' button.

form.blade.php

@extends('layouts.app')

@section('content')

<!doctype html>

{!! Form::open(['url' => 'page3/submit']) !!}

Approved By:

        Approved By:

        Name
        Signature
        Date

            {{Form::text('Officer_Name', '', ['class' => 'form-control', 'placeholder' => 'John Smith'])}}

            <canvas id="signature-canvas" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>

                <input type="button" id="clear-signature-btn" value="Clear">

                <input type="hidden" name="officer_signature" id="signature-data" value="">

            {{Form::date('Approval_Date', '', ['class' => 'form-control'])}}

Applicant Signature:

            <canvas id="signature-canvas2" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>

                <input type="button" id="clear-signature-btn2" value="Clear">

                <input type="hidden" name="applicant_signature" id="signature-data2" value="">

                <button type="submit" class="btn btn-primary" id="save-signature-btn">Submit</button>

@endsection('content')

signature data.js

var clearButton = document.getElementById('clear-signature-btn'),
    saveButton = document.getElementById('save-signature-btn'),
    canvas = document.getElementById('signature-canvas'),
    signaturePad;

function resizeCanvas() {
    var ratio =  Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = canvas.offsetWidth * ratio;
    canvas.height = canvas.offsetHeight * ratio;
    canvas.getContext("2d").scale(ratio, ratio);
}

window.onresize = resizeCanvas;
resizeCanvas();

signaturePad = new SignaturePad(canvas);

clearButton.addEventListener('click', function (event) {
    signaturePad.clear();
});

saveButton.addEventListener('click', function (event) {
    if (signaturePad.isEmpty()) {
        alert('Signature pad is blank. Please draw your signature.');
    } else {
        var sdata = signaturePad.toDataURL();
        document.getElementById('signature-data').value = sdata;
        document.getElementById('signature-form').submit();
    }
});

signature pad.js

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.SignaturePad = factory());
}(this, (function () { 'use strict';

function Point(x, y, time) {
  this.x = x;
  this.y = y;
  this.time = time || new Date().getTime();
}

Point.prototype.velocityFrom = function (start) {
  return this.time !== start.time ? this.distanceTo(start) / (this.time - start.time) : 1;
};

Point.prototype.distanceTo = function (start) {
  return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
};

Point.prototype.equals = function (other) {
  return this.x === other.x && this.y === other.y && this.time === other.time;
};

function Bezier(startPoint, control1, control2, endPoint) {
  this.startPoint = startPoint;
  this.control1 = control1;
  this.control2 = control2;
  this.endPoint = endPoint;
}

// Returns approximated length.
Bezier.prototype.length = function () {
  var steps = 10;
  var length = 0;
  var px = void 0;
  var py = void 0;

  for (var i = 0; i <= steps; i += 1) {
    var t = i / steps;
    var cx = this._point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
    var cy = this._point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
    if (i > 0) {
      var xdiff = cx - px;
      var ydiff = cy - py;
      length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);
    }
    px = cx;
    py = cy;
  }

  return length;
};

/* eslint-disable no-multi-spaces, space-in-parens */
Bezier.prototype._point = function (t, start, c1, c2, end) {
  return start * (1.0 - t) * (1.0 - t) * (1.0 - t) + 3.0 * c1 * (1.0 - t) * (1.0 - t) * t + 3.0 * c2 * (1.0 - t) * t * t + end * t * t * t;
};

/* eslint-disable */

// http://stackoverflow.com/a/27078401/815507
function throttle(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function later() {
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  return function () {
    var now = Date.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
}

function SignaturePad(canvas, options) {
  var self = this;
  var opts = options || {};

  this.velocityFilterWeight = opts.velocityFilterWeight || 0.7;
  this.minWidth = opts.minWidth || 0.5;
  this.maxWidth = opts.maxWidth || 2.5;
  this.throttle = 'throttle' in opts ? opts.throttle : 16; // in miliseconds
  this.minDistance = 'minDistance' in opts ? opts.minDistance : 5;

  if (this.throttle) {
    this._strokeMoveUpdate = throttle(SignaturePad.prototype._strokeUpdate, this.throttle);
  } else {
    this._strokeMoveUpdate = SignaturePad.prototype._strokeUpdate;
  }

  this.dotSize = opts.dotSize || function () {
    return (this.minWidth + this.maxWidth) / 2;
  };
  this.penColor = opts.penColor || 'black';
  this.backgroundColor = opts.backgroundColor || 'rgba(0,0,0,0)';
  this.onBegin = opts.onBegin;
  this.onEnd = opts.onEnd;

  this._canvas = canvas;
  this._ctx = canvas.getContext('2d');
  this.clear();

  // We need add these inline so they are available to unbind while still having
  // access to 'self' we could use _.bind but it's not worth adding a dependency.
  this._handleMouseDown = function (event) {
    if (event.which === 1) {
      self._mouseButtonDown = true;
      self._strokeBegin(event);
    }
  };

  this._handleMouseMove = function (event) {
    if (self._mouseButtonDown) {
      self._strokeMoveUpdate(event);
    }
  };

  this._handleMouseUp = function (event) {
    if (event.which === 1 && self._mouseButtonDown) {
      self._mouseButtonDown = false;
      self._strokeEnd(event);
    }
  };

  this._handleTouchStart = function (event) {
    if (event.targetTouches.length === 1) {
      var touch = event.changedTouches[0];
      self._strokeBegin(touch);
    }
  };

  this._handleTouchMove = function (event) {
    // Prevent scrolling.
    event.preventDefault();

    var touch = event.targetTouches[0];
    self._strokeMoveUpdate(touch);
  };

  this._handleTouchEnd = function (event) {
    var wasCanvasTouched = event.target === self._canvas;
    if (wasCanvasTouched) {
      event.preventDefault();
      self._strokeEnd(event);
    }
  };

  // Enable mouse and touch event handlers
  this.on();
}

// Public methods
SignaturePad.prototype.clear = function () {
  var ctx = this._ctx;
  var canvas = this._canvas;

  ctx.fillStyle = this.backgroundColor;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  this._data = [];
  this._reset();
  this._isEmpty = true;
};

SignaturePad.prototype.fromDataURL = function (dataUrl) {
  var _this = this;

  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  var image = new Image();
  var ratio = options.ratio || window.devicePixelRatio || 1;
  var width = options.width || this._canvas.width / ratio;
  var height = options.height || this._canvas.height / ratio;

  this._reset();
  image.src = dataUrl;
  image.onload = function () {
    _this._ctx.drawImage(image, 0, 0, width, height);
  };
  this._isEmpty = false;
};

SignaturePad.prototype.toDataURL = function (type) {
  var _canvas;

  switch (type) {
    case 'image/svg+xml':
      return this._toSVG();
    default:
      for (var _len = arguments.length, options = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        options[_key - 1] = arguments[_key];
      }

      return (_canvas = this._canvas).toDataURL.apply(_canvas, [type].concat(options));
  }
};

SignaturePad.prototype.on = function () {
  this._handleMouseEvents();
  this._handleTouchEvents();
};

SignaturePad.prototype.off = function () {
  this._canvas.removeEventListener('mousedown', this._handleMouseDown);
  this._canvas.removeEventListener('mousemove', this._handleMouseMove);
  document.removeEventListener('mouseup', this._handleMouseUp);

  this._canvas.removeEventListener('touchstart', this._handleTouchStart);
  this._canvas.removeEventListener('touchmove', this._handleTouchMove);
  this._canvas.removeEventListener('touchend', this._handleTouchEnd);
};

SignaturePad.prototype.isEmpty = function () {
  return this._isEmpty;
};

// Private methods
SignaturePad.prototype._strokeBegin = function (event) {
  this._data.push([]);
  this._reset();
  this._strokeUpdate(event);

  if (typeof this.onBegin === 'function') {
    this.onBegin(event);
  }
};

SignaturePad.prototype._strokeUpdate = function (event) {
  var x = event.clientX;
  var y = event.clientY;

  var point = this._createPoint(x, y);
  var lastPointGroup = this._data[this._data.length - 1];
  var lastPoint = lastPointGroup && lastPointGroup[lastPointGroup.length - 1];
  var isLastPointTooClose = lastPoint && point.distanceTo(lastPoint) < this.minDistance;

  // Skip this point if it's too close to the previous one
  if (!(lastPoint && isLastPointTooClose)) {
    var _addPoint = this._addPoint(point),
        curve = _addPoint.curve,
        widths = _addPoint.widths;

    if (curve && widths) {
      this._drawCurve(curve, widths.start, widths.end);
    }

    this._data[this._data.length - 1].push({
      x: point.x,
      y: point.y,
      time: point.time,
      color: this.penColor
    });
  }
};

SignaturePad.prototype._strokeEnd = function (event) {
  var canDrawCurve = this.points.length > 2;
  var point = this.points[0]; // Point instance

  if (!canDrawCurve && point) {
    this._drawDot(point);
  }

  if (point) {
    var lastPointGroup = this._data[this._data.length - 1];
    var lastPoint = lastPointGroup[lastPointGroup.length - 1]; // plain object

    // When drawing a dot, there's only one point in a group, so without this check
    // such group would end up with exactly the same 2 points.
    if (!point.equals(lastPoint)) {
      lastPointGroup.push({
        x: point.x,
        y: point.y,
        time: point.time,
        color: this.penColor
      });
    }
  }

  if (typeof this.onEnd === 'function') {
    this.onEnd(event);
  }
};

SignaturePad.prototype._handleMouseEvents = function () {
  this._mouseButtonDown = false;

  this._canvas.addEventListener('mousedown', this._handleMouseDown);
  this._canvas.addEventListener('mousemove', this._handleMouseMove);
  document.addEventListener('mouseup', this._handleMouseUp);
};

SignaturePad.prototype._handleTouchEvents = function () {
  // Pass touch events to canvas element on mobile IE11 and Edge.
  this._canvas.style.msTouchAction = 'none';
  this._canvas.style.touchAction = 'none';

  this._canvas.addEventListener('touchstart', this._handleTouchStart);
  this._canvas.addEventListener('touchmove', this._handleTouchMove);
  this._canvas.addEventListener('touchend', this._handleTouchEnd);
};

SignaturePad.prototype._reset = function () {
  this.points = [];
  this._lastVelocity = 0;
  this._lastWidth = (this.minWidth + this.maxWidth) / 2;
  this._ctx.fillStyle = this.penColor;
};

SignaturePad.prototype._createPoint = function (x, y, time) {
  var rect = this._canvas.getBoundingClientRect();

  return new Point(x - rect.left, y - rect.top, time || new Date().getTime());
};

SignaturePad.prototype._addPoint = function (point) {
  var points = this.points;
  var tmp = void 0;

  points.push(point);

  if (points.length > 2) {
    // To reduce the initial lag make it work with 3 points
    // by copying the first point to the beginning.
    if (points.length === 3) points.unshift(points[0]);

    tmp = this._calculateCurveControlPoints(points[0], points[1], points[2]);
    var c2 = tmp.c2;
    tmp = this._calculateCurveControlPoints(points[1], points[2], points[3]);
    var c3 = tmp.c1;
    var curve = new Bezier(points[1], c2, c3, points[2]);
    var widths = this._calculateCurveWidths(curve);

    // Remove the first element from the list,
    // so that we always have no more than 4 points in points array.
    points.shift();

    return { curve: curve, widths: widths };
  }

  return {};
};

SignaturePad.prototype._calculateCurveControlPoints = function (s1, s2, s3) {
  var dx1 = s1.x - s2.x;
  var dy1 = s1.y - s2.y;
  var dx2 = s2.x - s3.x;
  var dy2 = s2.y - s3.y;

  var m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
  var m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };

  var l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
  var l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);

  var dxm = m1.x - m2.x;
  var dym = m1.y - m2.y;

  var k = l2 / (l1 + l2);
  var cm = { x: m2.x + dxm * k, y: m2.y + dym * k };

  var tx = s2.x - cm.x;
  var ty = s2.y - cm.y;

  return {
    c1: new Point(m1.x + tx, m1.y + ty),
    c2: new Point(m2.x + tx, m2.y + ty)
  };
};

SignaturePad.prototype._calculateCurveWidths = function (curve) {
  var startPoint = curve.startPoint;
  var endPoint = curve.endPoint;
  var widths = { start: null, end: null };

  var velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) + (1 - this.velocityFilterWeight) * this._lastVelocity;

  var newWidth = this._strokeWidth(velocity);

  widths.start = this._lastWidth;
  widths.end = newWidth;

  this._lastVelocity = velocity;
  this._lastWidth = newWidth;

  return widths;
};

SignaturePad.prototype._strokeWidth = function (velocity) {
  return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
};

SignaturePad.prototype._drawPoint = function (x, y, size) {
  var ctx = this._ctx;

  ctx.moveTo(x, y);
  ctx.arc(x, y, size, 0, 2 * Math.PI, false);
  this._isEmpty = false;
};

SignaturePad.prototype._drawCurve = function (curve, startWidth, endWidth) {
  var ctx = this._ctx;
  var widthDelta = endWidth - startWidth;
  var drawSteps = Math.floor(curve.length());

  ctx.beginPath();

  for (var i = 0; i < drawSteps; i += 1) {
    // Calculate the Bezier (x, y) coordinate for this step.
    var t = i / drawSteps;
    var tt = t * t;
    var ttt = tt * t;
    var u = 1 - t;
    var uu = u * u;
    var uuu = uu * u;

    var x = uuu * curve.startPoint.x;
    x += 3 * uu * t * curve.control1.x;
    x += 3 * u * tt * curve.control2.x;
    x += ttt * curve.endPoint.x;

    var y = uuu * curve.startPoint.y;
    y += 3 * uu * t * curve.control1.y;
    y += 3 * u * tt * curve.control2.y;
    y += ttt * curve.endPoint.y;

    var width = startWidth + ttt * widthDelta;
    this._drawPoint(x, y, width);
  }

  ctx.closePath();
  ctx.fill();
};

SignaturePad.prototype._drawDot = function (point) {
  var ctx = this._ctx;
  var width = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;

  ctx.beginPath();
  this._drawPoint(point.x, point.y, width);
  ctx.closePath();
  ctx.fill();
};

SignaturePad.prototype._fromData = function (pointGroups, drawCurve, drawDot) {
  for (var i = 0; i < pointGroups.length; i += 1) {
    var group = pointGroups[i];

    if (group.length > 1) {
      for (var j = 0; j < group.length; j += 1) {
        var rawPoint = group[j];
        var point = new Point(rawPoint.x, rawPoint.y, rawPoint.time);
        var color = rawPoint.color;

        if (j === 0) {
          // First point in a group. Nothing to draw yet.

          // All points in the group have the same color, so it's enough to set
          // penColor just at the beginning.
          this.penColor = color;
          this._reset();

          this._addPoint(point);
        } else if (j !== group.length - 1) {
          // Middle point in a group.
          var _addPoint2 = this._addPoint(point),
              curve = _addPoint2.curve,
              widths = _addPoint2.widths;

          if (curve && widths) {
            drawCurve(curve, widths, color);
          }
        } else {
          // Last point in a group. Do nothing.
        }
      }
    } else {
      this._reset();
      var _rawPoint = group[0];
      drawDot(_rawPoint);
    }
  }
};

SignaturePad.prototype._toSVG = function () {
  var _this2 = this;

  var pointGroups = this._data;
  var canvas = this._canvas;
  var ratio = Math.max(window.devicePixelRatio || 1, 1);
  var minX = 0;
  var minY = 0;
  var maxX = canvas.width / ratio;
  var maxY = canvas.height / ratio;
  var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');

  svg.setAttributeNS(null, 'width', canvas.width);
  svg.setAttributeNS(null, 'height', canvas.height);

  this._fromData(pointGroups, function (curve, widths, color) {
    var path = document.createElement('path');

    // Need to check curve for NaN values, these pop up when drawing
    // lines on the canvas that are not continuous. E.g. Sharp corners
    // or stopping mid-stroke and than continuing without lifting mouse.
    if (!isNaN(curve.control1.x) && !isNaN(curve.control1.y) && !isNaN(curve.control2.x) && !isNaN(curve.control2.y)) {
      var attr = 'M ' + curve.startPoint.x.toFixed(3) + ',' + curve.startPoint.y.toFixed(3) + ' ' + ('C ' + curve.control1.x.toFixed(3) + ',' + curve.control1.y.toFixed(3) + ' ') + (curve.control2.x.toFixed(3) + ',' + curve.control2.y.toFixed(3) + ' ') + (curve.endPoint.x.toFixed(3) + ',' + curve.endPoint.y.toFixed(3));

      path.setAttribute('d', attr);
      path.setAttribute('stroke-width', (widths.end * 2.25).toFixed(3));
      path.setAttribute('stroke', color);
      path.setAttribute('fill', 'none');
      path.setAttribute('stroke-linecap', 'round');

      svg.appendChild(path);
    }
  }, function (rawPoint) {
    var circle = document.createElement('circle');
    var dotSize = typeof _this2.dotSize === 'function' ? _this2.dotSize() : _this2.dotSize;
    circle.setAttribute('r', dotSize);
    circle.setAttribute('cx', rawPoint.x);
    circle.setAttribute('cy', rawPoint.y);
    circle.setAttribute('fill', rawPoint.color);

    svg.appendChild(circle);
  });

  var prefix = 'data:image/svg+xml;base64,';
  var header = '<svg' + ' xmlns="http://www.w3.org/2000/svg"' + ' xmlns:xlink="http://www.w3.org/1999/xlink"' + (' viewBox="' + minX + ' ' + minY + ' ' + maxX + ' ' + maxY + '"') + (' width="' + maxX + '"') + (' height="' + maxY + '"') + '>';
  var body = svg.innerHTML;

  // IE hack for missing innerHTML property on SVGElement
  if (body === undefined) {
    var dummy = document.createElement('dummy');
    var nodes = svg.childNodes;
    dummy.innerHTML = '';

    for (var i = 0; i < nodes.length; i += 1) {
      dummy.appendChild(nodes[i].cloneNode(true));
    }

    body = dummy.innerHTML;
  }

  var footer = '</svg>';
  var data = header + body + footer;

  return prefix + btoa(data);
};

SignaturePad.prototype.fromData = function (pointGroups) {
  var _this3 = this;

  this.clear();

  this._fromData(pointGroups, function (curve, widths) {
    return _this3._drawCurve(curve, widths.start, widths.end);
  }, function (rawPoint) {
    return _this3._drawDot(rawPoint);
  });

  this._data = pointGroups;
};

SignaturePad.prototype.toData = function () {
  return this._data;
};

return SignaturePad;

})));

Body:
In your javascript code you are working only with

canvas = document.getElementById('signature-canvas')

So that is the problem.

You should add a class on both signature canvases in html code for example signature like this:

<canvas id="signature-canvas" class="signature" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>

<canvas id="signature-canvas2" class="signature" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>

And then in javascript add one more pair of commands for second signature pad for control buttons (submit and reset) for second canvas.


来源: stackexchange

问:
How to populate Pandas dataframe as function of index and columns
I have a dataframe where the index and column are both numbers--i.e.

```<code>rng = np.arange(2,51)
box = pd.DataFrame(index = rng, columns = rng)
</code>```

I want the values of the dataframe to be a function of the index and column--so for instance box[2][2] should equal 4.

Currently I have it in

```<code>for x in range(2,len(box)+2):
    for y in range(2,len(box)+2):
        box[x][y] = x*y
box
</code>```

but I feel like there should be a more elegant solution. Is there a way to do this purely with slicing/dataframe assignment methods?

答:
Here's what I think you should be doing with numpy broadcasting:

```<code>import numpy
import pandas

rng = numpy.arange(2, 51)
box = pandas.DataFrame(index=rng, columns=rng, data=rng*rng[:, None])
</code>```

In the case that knowing all of the value ahead of time isn't feasible, you could assign them later:

```<code>box = pandas.DataFrame(index=rng, columns=rng)
box.iloc[:, :] = some_other_array
</code>```

And if you really are assigning small subsets at a time, you'd do:

```<code>box.iloc[row_positions, column_positions] = values
</code>```

or

```<code>box.loc[row_labels, column_labels] = values
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have a dataframe where the index and column are both numbers--i.e.

rng = np.arange(2,51)
box = pd.DataFrame(index = rng, columns = rng)

I want the values of the dataframe to be a function of the index and column--so for instance box[2][2] should equal 4.

Currently I have it in

for x in range(2,len(box)+2):
    for y in range(2,len(box)+2):
        box[x][y] = x*y
box

but I feel like there should be a more elegant solution. Is there a way to do this purely with slicing/dataframe assignment methods?

Body:
Here's what I think you should be doing with numpy broadcasting:

import numpy
import pandas

rng = numpy.arange(2, 51)
box = pandas.DataFrame(index=rng, columns=rng, data=rng*rng[:, None])

In the case that knowing all of the value ahead of time isn't feasible, you could assign them later:

box = pandas.DataFrame(index=rng, columns=rng)
box.iloc[:, :] = some_other_array

And if you really are assigning small subsets at a time, you'd do:

box.iloc[row_positions, column_positions] = values

or

box.loc[row_labels, column_labels] = values


问:
Macro to loop through all sheets in the workbook, test if a cell has a certain value. If yes, copy the sheet and exit the loop
```<code>Dim j As Double
For j = 1 To Worksheets.Count
        If Sheets(j).Range("E4").Value Like "Filters" Then
            ActiveSheet.Copy before:=Worksheets(1)
              ActiveSheet.Name = "data"
        End If
 Next j
</code>```

This is my code... when i run the code worksheet is created as "Data" but it is not exiting the loop... it is creating duplication of "data" worksheet and getting debug.. im missing very small thing  and i dont know what it is.. can anybody help.. thanks

答:
Consider:</p>

```<code>Sub poiuyt()
Dim j As Long
For j = 1 To Worksheets.Count
    With Sheets(j)
        If  .Range("E4").Value Like "Filters" Then
            .Copy before:=Worksheets(1)
            .Name = "data"
            Exit Sub
        End If
    End With
 Next j
End Sub
</code>```

Body:
Dim j As Double
For j = 1 To Worksheets.Count
        If Sheets(j).Range("E4").Value Like "Filters" Then
            ActiveSheet.Copy before:=Worksheets(1)
              ActiveSheet.Name = "data"
        End If
 Next j

This is my code... when i run the code worksheet is created as "Data" but it is not exiting the loop... it is creating duplication of "data" worksheet and getting debug.. im missing very small thing  and i dont know what it is.. can anybody help.. thanks

Body:
Consider:

Sub poiuyt()
Dim j As Long
For j = 1 To Worksheets.Count
    With Sheets(j)
        If  .Range("E4").Value Like "Filters" Then
            .Copy before:=Worksheets(1)
            .Name = "data"
            Exit Sub
        End If
    End With
 Next j
End Sub


问:
Angular 4 Multiple Guards - Execution Sequence
I have 2 guards, AuthGuard and AccessGuard in the application.
AuthGuard protects all the pages as the name suggests and stores the session object in the GlobalService and AccessGuard depends on the some access data in session object stored by AuthGuard in GlobalService.

Problem arises when AuthGuard returns an Observable and then simultaneously AccessGuard executes to check for session object which has not yet arrived and the code breaks. Is there any other way I can restrict the execution of AccessGuard until the session object arrives or any other work around to break this race condition?

#Note I have not merged the AccessGuard logic to AuthGuard as only some of the routes need to be checked for access while all other needs authentication. For example, Accounts page and DB page are accessible to all but User Managements and Dashboard need external access parameters that come from session object

```<code>export const routes: Routes = [
  {
    path: 'login',
    loadChildren: 'app/login/login.module#LoginModule',
  },
  {
    path: 'logout',
    loadChildren: 'app/logout/logout.module#LogoutModule',
  },
  {
    path: 'forget',
    loadChildren: 'app/forget/forget.module#ForgetModule',
  },{
    path: 'reset',
    loadChildren: 'app/reset/reset.module#ResetModule',
  },

    path: 'pages',
    component: Pages,
    children: [
      { path: '', redirectTo: 'db', pathMatch: 'full' },
      { path: 'db', loadChildren: 'app/pages/db/db.module#DbModule' },
      { path: 'bi', loadChildren: 'app/pages/dashboard/dashboard.module#DashboardModule', canActivate:[AccessableGuard] },
      { path: 'account', loadChildren: 'app/pages/account/account.module#AccountModule' },
      { path: 'um', loadChildren: 'app/pages/um/um.module#UserManagementModule', canActivate:[AccessableGuard] },
    ],
    canActivate: [AuthGuard]
  }
];

export const routing: ModuleWithProviders = RouterModule.forChild(routes);
</code>```

#EDIT: Adding the Guard Codes

AuthGuard:

```<code>canActivate(route:ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean{
  return new Observable<boolean>( observer => {
    this._dataService.callRestful('POST', params.SERVER.AUTH_URL + urls.AUTH.GET_SESSION).subscribe(
        (accessData) => {
          if (accessData['successful']) {
            observer.next(true);
            observer.complete();
            console.log("done");
          }
          else {
            observer.next(false);
            observer.complete();
          }
        });
  });
}
</code>```

AccessableGuard:

```<code>canActivate(route:ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean{
if(this._dataService.getModulePermission(route.routeConfig.path.toUpperCase()) < 2){
        return false;
      }
      return true;
    }
</code>```

#NOTE: _dataService is GlobalService that stores the Access Permissions from AuthGuard.

答:
Using a Master Guard to fire application guards can do the trick.

EDIT : Adding the code snippet for better understanding.

I faced the similar problem and this is how I solved it -

Solution

The idea is to create a master guard and let the master guard handle the execution of other guards.

The routing configuration in this case, will contain master guard as the only guard.

To let master guard know about the guards to be triggered for specific routes, add a data property in Route.

The data property is a key value pair that allows us to attach data with the routes.

The data can then be accessed in the guards using ActivatedRouteSnapshot parameter of canActivate method in the guard.

The solution looks complicated but it will assure proper working of guards once it is integrated in the application.

Following example explains this approach -

Example

1. Constants Object to map all application guards -

```<code>export const GUARDS = {
    GUARD1: "GUARD1",
    GUARD2: "GUARD2",
    GUARD3: "GUARD3",
    GUARD4: "GUARD4",
}
</code>```

2. Application Guard -

```<code>import { Injectable } from "@angular/core";
import { Guard4DependencyService } from "./guard4dependency";

@Injectable()
export class Guard4 implements CanActivate {
    //A  guard with dependency
    constructor(private _Guard4DependencyService:  Guard4DependencyService) {}

    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
        return new Promise((resolve: Function, reject: Function) => {
            //logic of guard 4 here
            if (this._Guard4DependencyService.valid()) {
                resolve(true);
            } else {
                reject(false);
            }
        });
    }
}
</code>```

3. Routing Configuration -

```<code>import { Route } from "@angular/router";
import { View1Component } from "./view1";
import { View2Component } from "./view2";
import { MasterGuard, GUARDS } from "./master-guard";
export const routes: Route[] = [
    {
        path: "view1",
        component: View1Component,
        //attach master guard here
        canActivate: [MasterGuard],
        //this is the data object which will be used by
        //masteer guard to execute guard1 and guard 2
        data: {
            guards: [
                GUARDS.GUARD1,
                GUARDS.GUARD2
            ]
        }
    },
    {
        path: "view2",
        component: View2Component,
        //attach master guard here
        canActivate: [MasterGuard],
        //this is the data object which will be used by
        //masteer guard to execute guard1, guard 2, guard 3 & guard 4
        data: {
            guards: [
                GUARDS.GUARD1,
                GUARDS.GUARD2,
                GUARDS.GUARD3,
                GUARDS.GUARD4
            ]
        }
    }
];
</code>```

4. Master Guard -

```<code>import { Injectable } from "@angular/core";
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from "@angular/router";

//import all the guards in the application
import { Guard1 } from "./guard1";
import { Guard2 } from "./guard2";
import { Guard3 } from "./guard3";
import { Guard4 } from "./guard4";

import { Guard4DependencyService } from "./guard4dependency";

@Injectable()
export class MasterGuard implements CanActivate {

    //you may need to include dependencies of individual guards if specified in guard constructor
    constructor(private _Guard4DependencyService:  Guard4DependencyService) {}

    private route: ActivatedRouteSnapshot;
    private state: RouterStateSnapshot;

    //This method gets triggered when the route is hit
    public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {

        this.route = route;
        this.state = state;

        if (!route.data) {
            Promise.resolve(true);
            return;
        }

        //this.route.data.guards is an array of strings set in routing configuration

        if (!this.route.data.guards || !this.route.data.guards.length) {
            Promise.resolve(true);
            return;
        }
        return this.executeGuards();
    }

    //Execute the guards sent in the route data
    private executeGuards(guardIndex: number = 0): Promise<boolean> {
        return this.activateGuard(this.route.data.guards[guardIndex])
            .then(() => {
                if (guardIndex < this.route.data.guards.length - 1) {
                    return this.executeGuards(guardIndex + 1);
                } else {
                    return Promise.resolve(true);
                }
            })
            .catch(() => {
                return Promise.reject(false);
            });
    }

    //Create an instance of the guard and fire canActivate method returning a promise
    private activateGuard(guardKey: string): Promise<boolean> {

        let guard: Guard1 | Guard2 | Guard3 | Guard4;

        switch (guardKey) {
            case GUARDS.GUARD1:
                guard = new Guard1();
                break;
            case GUARDS.GUARD2:
                guard = new Guard2();
                break;
            case GUARDS.GUARD3:
                guard = new Guard3();
                break;
            case GUARDS.GUARD4:
                guard = new Guard4(this._Guard4DependencyService);
                break;
            default:
                break;
        }
        return guard.canActivate(this.route, this.state);
    }
}
</code>```

Challenges

One of the challenges  in this  approach is refactoring of existing routing model. However, it can be done in parts as the changes are non-breaking.

I hope this helps.

Body:
I have 2 guards, AuthGuard and AccessGuard in the application.
AuthGuard protects all the pages as the name suggests and stores the session object in the GlobalService and AccessGuard depends on the some access data in session object stored by AuthGuard in GlobalService.

Problem arises when AuthGuard returns an Observable and then simultaneously AccessGuard executes to check for session object which has not yet arrived and the code breaks. Is there any other way I can restrict the execution of AccessGuard until the session object arrives or any other work around to break this race condition?

#Note I have not merged the AccessGuard logic to AuthGuard as only some of the routes need to be checked for access while all other needs authentication. For example, Accounts page and DB page are accessible to all but User Managements and Dashboard need external access parameters that come from session object

export const routes: Routes = [
  {
    path: 'login',
    loadChildren: 'app/login/login.module#LoginModule',
  },
  {
    path: 'logout',
    loadChildren: 'app/logout/logout.module#LogoutModule',
  },
  {
    path: 'forget',
    loadChildren: 'app/forget/forget.module#ForgetModule',
  },{
    path: 'reset',
    loadChildren: 'app/reset/reset.module#ResetModule',
  },

    path: 'pages',
    component: Pages,
    children: [
      { path: '', redirectTo: 'db', pathMatch: 'full' },
      { path: 'db', loadChildren: 'app/pages/db/db.module#DbModule' },
      { path: 'bi', loadChildren: 'app/pages/dashboard/dashboard.module#DashboardModule', canActivate:[AccessableGuard] },
      { path: 'account', loadChildren: 'app/pages/account/account.module#AccountModule' },
      { path: 'um', loadChildren: 'app/pages/um/um.module#UserManagementModule', canActivate:[AccessableGuard] },
    ],
    canActivate: [AuthGuard]
  }
];

export const routing: ModuleWithProviders = RouterModule.forChild(routes);

#EDIT: Adding the Guard Codes

AuthGuard:

canActivate(route:ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean{
  return new Observable<boolean>( observer => {
    this._dataService.callRestful('POST', params.SERVER.AUTH_URL + urls.AUTH.GET_SESSION).subscribe(
        (accessData) => {
          if (accessData['successful']) {
            observer.next(true);
            observer.complete();
            console.log("done");
          }
          else {
            observer.next(false);
            observer.complete();
          }
        });
  });
}

AccessableGuard:

canActivate(route:ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean{
if(this._dataService.getModulePermission(route.routeConfig.path.toUpperCase()) < 2){
        return false;
      }
      return true;
    }

#NOTE: _dataService is GlobalService that stores the Access Permissions from AuthGuard.

Body:
Using a Master Guard to fire application guards can do the trick.

EDIT : Adding the code snippet for better understanding.

I faced the similar problem and this is how I solved it -

Solution

The idea is to create a master guard and let the master guard handle the execution of other guards.

The routing configuration in this case, will contain master guard as the only guard.

To let master guard know about the guards to be triggered for specific routes, add a data property in Route.

The data property is a key value pair that allows us to attach data with the routes.

The data can then be accessed in the guards using ActivatedRouteSnapshot parameter of canActivate method in the guard.

The solution looks complicated but it will assure proper working of guards once it is integrated in the application.

Following example explains this approach -

Example

1. Constants Object to map all application guards -

export const GUARDS = {
    GUARD1: "GUARD1",
    GUARD2: "GUARD2",
    GUARD3: "GUARD3",
    GUARD4: "GUARD4",
}

2. Application Guard -

import { Injectable } from "@angular/core";
import { Guard4DependencyService } from "./guard4dependency";

@Injectable()
export class Guard4 implements CanActivate {
    //A  guard with dependency
    constructor(private _Guard4DependencyService:  Guard4DependencyService) {}

    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
        return new Promise((resolve: Function, reject: Function) => {
            //logic of guard 4 here
            if (this._Guard4DependencyService.valid()) {
                resolve(true);
            } else {
                reject(false);
            }
        });
    }
}

3. Routing Configuration -

import { Route } from "@angular/router";
import { View1Component } from "./view1";
import { View2Component } from "./view2";
import { MasterGuard, GUARDS } from "./master-guard";
export const routes: Route[] = [
    {
        path: "view1",
        component: View1Component,
        //attach master guard here
        canActivate: [MasterGuard],
        //this is the data object which will be used by
        //masteer guard to execute guard1 and guard 2
        data: {
            guards: [
                GUARDS.GUARD1,
                GUARDS.GUARD2
            ]
        }
    },
    {
        path: "view2",
        component: View2Component,
        //attach master guard here
        canActivate: [MasterGuard],
        //this is the data object which will be used by
        //masteer guard to execute guard1, guard 2, guard 3 & guard 4
        data: {
            guards: [
                GUARDS.GUARD1,
                GUARDS.GUARD2,
                GUARDS.GUARD3,
                GUARDS.GUARD4
            ]
        }
    }
];

4. Master Guard -

import { Injectable } from "@angular/core";
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from "@angular/router";

//import all the guards in the application
import { Guard1 } from "./guard1";
import { Guard2 } from "./guard2";
import { Guard3 } from "./guard3";
import { Guard4 } from "./guard4";

import { Guard4DependencyService } from "./guard4dependency";

@Injectable()
export class MasterGuard implements CanActivate {

    //you may need to include dependencies of individual guards if specified in guard constructor
    constructor(private _Guard4DependencyService:  Guard4DependencyService) {}

    private route: ActivatedRouteSnapshot;
    private state: RouterStateSnapshot;

    //This method gets triggered when the route is hit
    public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {

        this.route = route;
        this.state = state;

        if (!route.data) {
            Promise.resolve(true);
            return;
        }

        //this.route.data.guards is an array of strings set in routing configuration

        if (!this.route.data.guards || !this.route.data.guards.length) {
            Promise.resolve(true);
            return;
        }
        return this.executeGuards();
    }

    //Execute the guards sent in the route data
    private executeGuards(guardIndex: number = 0): Promise<boolean> {
        return this.activateGuard(this.route.data.guards[guardIndex])
            .then(() => {
                if (guardIndex < this.route.data.guards.length - 1) {
                    return this.executeGuards(guardIndex + 1);
                } else {
                    return Promise.resolve(true);
                }
            })
            .catch(() => {
                return Promise.reject(false);
            });
    }

    //Create an instance of the guard and fire canActivate method returning a promise
    private activateGuard(guardKey: string): Promise<boolean> {

        let guard: Guard1 | Guard2 | Guard3 | Guard4;

        switch (guardKey) {
            case GUARDS.GUARD1:
                guard = new Guard1();
                break;
            case GUARDS.GUARD2:
                guard = new Guard2();
                break;
            case GUARDS.GUARD3:
                guard = new Guard3();
                break;
            case GUARDS.GUARD4:
                guard = new Guard4(this._Guard4DependencyService);
                break;
            default:
                break;
        }
        return guard.canActivate(this.route, this.state);
    }
}

Challenges

One of the challenges  in this  approach is refactoring of existing routing model. However, it can be done in parts as the changes are non-breaking.

I hope this helps.


问:
perl user input into a data structure

I am trying to take user input such as 4 2 1 4 and store that into an array. Then loop through the array looking for duplicates to store into a hash table.

```<code>#!/usr/bin/perl -w
print "Enter numbers into hash table :";

my @num = <STDIN>;
my %hash;

foreach $x (@num){
    my $count =1;
    foreach $y(@num){

        if($x == $y){
        my $count++;
        $hash{'$x'} = $count;
        }
    }

}

map{print "$_\t$hash{$_}\n"}keys %hash;
</code>```

I expect the result to be:
1 1
2 1
4 2

The actual result, I just continue to enter digits, after I hit enter the program continues to ask for more input. I hit CTRL D and nothing happens.

答:
There are a great many problems with your code and I don't have time to explore them all

I hope it helps to offer you a working solution

#!/usr/bin/perl

use strict;
use warnings 'all';

my %counts;

print "Enter numbers into counts table: ";

++$counts{$_} for split ' ', <STDIN>;

print "$_\t$counts{$_}\n" for keys %counts;
```

<h3>output</h3>

<pre class="lang-none prettyprint-override"><code>E:\Perl\source>count.pl
Enter numbers into counts table: 4 2 1 4
1       1
2       1
4       2
</code>```

Title: perl user input into a data structure

Body:
I am trying to take user input such as 4 2 1 4 and store that into an array. Then loop through the array looking for duplicates to store into a hash table.

#!/usr/bin/perl -w
print "Enter numbers into hash table :";

my @num = <STDIN>;
my %hash;

foreach $x (@num){
    my $count =1;
    foreach $y(@num){

        if($x == $y){
        my $count++;
        $hash{'$x'} = $count;
        }
    }

}

map{print "$_\t$hash{$_}\n"}keys %hash;

I expect the result to be:
1 1
2 1
4 2

The actual result, I just continue to enter digits, after I hit enter the program continues to ask for more input. I hit CTRL D and nothing happens.

Body:
There are a great many problems with your code and I don't have time to explore them all

I hope it helps to offer you a working solution

#!/usr/bin/perl

use strict;
use warnings 'all';

my %counts;

print "Enter numbers into counts table: ";

++$counts{$_} for split ' ', <STDIN>;

print "$_\t$counts{$_}\n" for keys %counts;

output

E:\Perl\source>count.pl
Enter numbers into counts table: 4 2 1 4
1       1
2       1
4       2


问:
How do I align icons from the start of a line to the end of a line which is evenly distributed horizontally?
How can I have the icon display from the beginning of the line to the end of the line and and have it evenly distributed?  The icons should be evenly distributed and an icon should be at the start and end of the line.  I can't figure out how to get it to the end.

Thanks for any help!

.steps {
    width: 100%;
    display: -webkit-flex;
    display: flex;
    -webkit-justify-content: space-between;
    justify-content: space-between;
    align-items: stretch;
}

.steps div {
    line-height: 3em;
    display: flex;
    justify-content: space-between;
    flex: 1 1 auto;
    align-items: stretch;
}

.steps .complete-step {
    border-bottom: 4px solid #95CA3E;
}

.steps .incomplete-step {
    border-bottom: 4px solid #0369B3;
}

.steps div:after {
    content: "\00a0\00a0";
}

.steps div:before {
    position: relative;
    bottom: -2.5em;
    float: none;
    line-height: 1em;
}

.steps .complete-step:before {
    font-family: 'FontAwesome';
    content: "\f111";
    color: #95CA3E;
    background-color: #95CA3E;
    height: 1.2em;
    width: 1.2em;
    border-radius: 1.2em;
}

.steps .incomplete-step:before {
    font-family: 'FontAwesome';
    content: "\f192";
    font-size: 1.5em;
    bottom: -1.6em;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet"/>

<div class="steps">
    <div class="complete-step"></div>
    <div class="complete-step"></div>
    <div class="incomplete-step"></div>
    <div class="incomplete-step"></div>
    <div class="incomplete-step"></div>
    <div class="incomplete-step"></div>
    <div class="incomplete-step"></div>
</div></code>```

答:
To avoid a line at the end is easily done use the :not() selector, combined with :last-child, where all but the last child will get a line

```<code>.steps .complete-step:not(:last-child) {
  border-bottom: 4px solid #95CA3E;
}
</code>```

When it comes to the line shining through, as the pseudo are a part of the items, its border will be beneath it. You can either move the pseudo outside, using e.g. a negative margin, and then resize the items so they match the space between, or simply give the incomplete pseudo a background color, as I did in below sample.

Stack snippet

.steps {
  width: 100%;
  display: -webkit-flex;
  display: flex;
  -webkit-justify-content: space-between;
  justify-content: space-between;
  align-items: stretch;
}

.steps div {
  line-height: 3em;
  display: flex;
  justify-content: space-between;
  flex: 1 1 auto;
  align-items: stretch;
}

.steps .complete-step:not(:last-child) {       /*  changed  */
  border-bottom: 4px solid #95CA3E;
}

.steps .incomplete-step:not(:last-child) {     /*  changed  */
  border-bottom: 4px solid #0369B3;
}

.steps div:after {
  content: "\00a0\00a0";
}

.steps div:before {
  position: relative;
  bottom: -2.5em;
  float: none;
  line-height: 1em;
}

.steps .complete-step:before {
  font-family: 'FontAwesome';
  content: "\f111";
  color: #95CA3E;
  background-color: #95CA3E;
  height: 1.2em;
  width: 1.2em;
  border-radius: 1.2em;
}

.steps .incomplete-step:before {
  font-family: 'FontAwesome';
  content: "\f192";
  background-color: white;                     /*  added  */
  font-size: 1.5em;
  bottom: -1.6em;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />

<div class="steps">
  <div class="complete-step"></div>
  <div class="complete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
</div></code>```

Body:
How can I have the icon display from the beginning of the line to the end of the line and and have it evenly distributed?  The icons should be evenly distributed and an icon should be at the start and end of the line.  I can't figure out how to get it to the end.

Thanks for any help!

.steps {
    width: 100%;
    display: -webkit-flex;
    display: flex;
    -webkit-justify-content: space-between;
    justify-content: space-between;
    align-items: stretch;
}

.steps div {
    line-height: 3em;
    display: flex;
    justify-content: space-between;
    flex: 1 1 auto;
    align-items: stretch;
}

.steps .complete-step {
    border-bottom: 4px solid #95CA3E;
}

.steps .incomplete-step {
    border-bottom: 4px solid #0369B3;
}

.steps div:after {
    content: "\00a0\00a0";
}

.steps div:before {
    position: relative;
    bottom: -2.5em;
    float: none;
    line-height: 1em;
}

.steps .complete-step:before {
    font-family: 'FontAwesome';
    content: "\f111";
    color: #95CA3E;
    background-color: #95CA3E;
    height: 1.2em;
    width: 1.2em;
    border-radius: 1.2em;
}

.steps .incomplete-step:before {
    font-family: 'FontAwesome';
    content: "\f192";
    font-size: 1.5em;
    bottom: -1.6em;
}

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet"/>

Body:
To avoid a line at the end is easily done use the :not() selector, combined with :last-child, where all but the last child will get a line

.steps .complete-step:not(:last-child) {
  border-bottom: 4px solid #95CA3E;
}

When it comes to the line shining through, as the pseudo are a part of the items, its border will be beneath it. You can either move the pseudo outside, using e.g. a negative margin, and then resize the items so they match the space between, or simply give the incomplete pseudo a background color, as I did in below sample.

Stack snippet

.steps {
  width: 100%;
  display: -webkit-flex;
  display: flex;
  -webkit-justify-content: space-between;
  justify-content: space-between;
  align-items: stretch;
}

.steps div {
  line-height: 3em;
  display: flex;
  justify-content: space-between;
  flex: 1 1 auto;
  align-items: stretch;
}

.steps .complete-step:not(:last-child) {       /*  changed  */
  border-bottom: 4px solid #95CA3E;
}

.steps .incomplete-step:not(:last-child) {     /*  changed  */
  border-bottom: 4px solid #0369B3;
}

.steps div:after {
  content: "\00a0\00a0";
}

.steps div:before {
  position: relative;
  bottom: -2.5em;
  float: none;
  line-height: 1em;
}

.steps .complete-step:before {
  font-family: 'FontAwesome';
  content: "\f111";
  color: #95CA3E;
  background-color: #95CA3E;
  height: 1.2em;
  width: 1.2em;
  border-radius: 1.2em;
}

.steps .incomplete-step:before {
  font-family: 'FontAwesome';
  content: "\f192";
  background-color: white;                     /*  added  */
  font-size: 1.5em;
  bottom: -1.6em;
}

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />

<div class="steps">
  <div class="complete-step"></div>
  <div class="complete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
  <div class="incomplete-step"></div>
</div>


问:
How to create share folder between Host and Docker container via docker API
How can I create a share folder between Host and Docker container via docker API?

I am able to do it via CLI:

```<code>docker run -v folder on host:folder on container -d --privileged image name".
</code>```

How can I achieve the same thing with the help of Docker API? I am using Docker Python SDK.

答:
Below link might help you in creating / sharing volume using docker api. An example using curl:

```<code>curl -X POST -H "Content-Type: application/json" \
    -d '{ "Binds": ["/home/user/folder/:/opt/folder:rw"] }' \
    http://127.0.0.1:{port}/containers/[id]/start
</code>```

For detailed info, see Docker API docs.

For docker python SDK

```<code>container_id = cli.create_container(
    'busybox', 'ls', volumes=['/mnt/vol1', '/mnt/vol2'],
    host_config=cli.create_host_config(binds={
        '/home/user1/': {
            'bind': '/mnt/vol2',
            'mode': 'rw',
        },
        '/var/www': {
            'bind': '/mnt/vol1',
            'mode': 'ro',
        }
    })
)
</code>```

See create containers section in below link

http://docker-py.readthedocs.io/en/stable/api.html

Body:
How can I create a share folder between Host and Docker container via docker API?

I am able to do it via CLI:

docker run -v folder on host:folder on container -d --privileged image name".

How can I achieve the same thing with the help of Docker API? I am using Docker Python SDK.

Body:
Below link might help you in creating / sharing volume using docker api. An example using curl:

curl -X POST -H "Content-Type: application/json" \
    -d '{ "Binds": ["/home/user/folder/:/opt/folder:rw"] }' \
    http://127.0.0.1:{port}/containers/[id]/start

For detailed info, see Docker API docs.

For docker python SDK

container_id = cli.create_container(
    'busybox', 'ls', volumes=['/mnt/vol1', '/mnt/vol2'],
    host_config=cli.create_host_config(binds={
        '/home/user1/': {
            'bind': '/mnt/vol2',
            'mode': 'rw',
        },
        '/var/www': {
            'bind': '/mnt/vol1',
            'mode': 'ro',
        }
    })
)

See create containers section in below link

http://docker-py.readthedocs.io/en/stable/api.html


问:
How to prevent my ASP.NET app from processing same request from an email hyperlink a second time?
Here's the problem...

My backend software sends user an email with a hyperlink that contains data (ie. "?dataName=dataYadaYada").

User receives email and clicks hyperlink

My ASP.NET app gets the request, processes data in queryString, and sends back response page with "THANK YOU" plus links to other pages.

PROBLEM:  If user re-posts the page or clicks one of the page links, my ASP.NET gets same request again with same queryString, and mistakenly processes it.

How can my ASP.NET app recognize and skip a request that it has already processed?

The only solution I can think of is backend putting unique sequential number into the email hyperlink, and then ASP.NET storing this into session variable for detection of 2nd request of same queryString.

Is there better way?

答:
Fairly simple - when you receive the request, record in your database that the dataname has been used, and check for it every time you receive a request.

If the dataname on its own is not unique enough then yeah append another parameter containing something which (in combination with the dataname if that makes sense) allows you to identify the specific email from which it originated.

P.S. using session is no good because it's temporary and lost when the browser closes. If the user clicks the email again in a new browser session it won't detect it. You need permanent storage like a database


问:
Selectize.js how does getAdjacentOption() work?
I've been using selectize.js, but I'm a bit stuck at the usage of getAdjacentValue().

In the API one finds:

getAdjacentOption(value, direction)` Retrieves the jQuery element for the previous or next option, relative to the currently highlighted option. The "direction" argument should be 1 for "next" or -1 for "previous".

Minimal working example, jsFiddle.

```<code><select id='car' name='car'>
  <option value='1'>Mercedes</option>
  <option value='2' selected>BMW</option>
  <option value='3'>Volvo</option>
</select>
</code>```

And .js

```<code>$('select').selectize();
var obj = $('select')[0].selectize;
</code>```

But how can I get the next and prev value of the current selected item?
I don't get how to implement the API help.

答:
To improve what DavidDomain said, I have a button to go to the next value in the select, so I did this:

```<code>$('#btnNext').click(function(){
    var $select = $('#ddlClients').selectize();
    var obj = $select[0].selectize;
    obj.refreshOptions(false);

    var crnt = obj.getOption(obj.getValue());
    var next = obj.getAdjacentOption(crnt, 1).data("value");
    obj.setValue(next); //here is where the value is setted as selected
});
</code>```

This way, when I click the button "Next", the next item in the dropdown is set as selected.

Body:
I've been using selectize.js, but I'm a bit stuck at the usage of getAdjacentValue().

In the API one finds:

getAdjacentOption(value, direction)` Retrieves the jQuery element for the previous or next option, relative to the currently highlighted option. The "direction" argument should be 1 for "next" or -1 for "previous".

Minimal working example, jsFiddle.

<select id='car' name='car'>
  <option value='1'>Mercedes</option>
  <option value='2' selected>BMW</option>
  <option value='3'>Volvo</option>
</select>

And .js

$('select').selectize();
var obj = $('select')[0].selectize;

But how can I get the next and prev value of the current selected item?
I don't get how to implement the API help.

Body:
To improve what DavidDomain said, I have a button to go to the next value in the select, so I did this:

$('#btnNext').click(function(){
    var $select = $('#ddlClients').selectize();
    var obj = $select[0].selectize;
    obj.refreshOptions(false);

    var crnt = obj.getOption(obj.getValue());
    var next = obj.getAdjacentOption(crnt, 1).data("value");
    obj.setValue(next); //here is where the value is setted as selected
});

This way, when I click the button "Next", the next item in the dropdown is set as selected.


问:
What's the issue with this code?
This is my part of the code:

```<code>import functions
def assign_tasks(operators, requests, current_time):
    sort_requests(requests)
    print(requests)
</code>```

The error is:

```<code>NameError: name 'sort_requests' is not defined
</code>```

The function module has the following functions:

```<code>def sort_requests(requests):
   requests.sort(key=operator.itemgetter(3),reverse=True)
   return requests
def sort_operators_hours(operators):
   operators.sort(key=operator.itemgetter(4))
   return operators
</code>```

答:
First :  Check your import statement.
Is it function or functions.IT should be the name of your python file name.

Second  : your function sort_requests has a return statement. U need to store the returned output.Try this

```<code>import functions
def assign_tasks(operators, requests, current_time):
    requests = sort_requests(requests)
    print(requests)
</code>```

Title: What's the issue with this code?

Body:
This is my part of the code:

import functions
def assign_tasks(operators, requests, current_time):
    sort_requests(requests)
    print(requests)

The error is:

NameError: name 'sort_requests' is not defined

The function module has the following functions:

def sort_requests(requests):
   requests.sort(key=operator.itemgetter(3),reverse=True)
   return requests
def sort_operators_hours(operators):
   operators.sort(key=operator.itemgetter(4))
   return operators

Body:
First :  Check your import statement.
Is it function or functions.IT should be the name of your python file name.

Second  : your function sort_requests has a return statement. U need to store the returned output.Try this

import functions
def assign_tasks(operators, requests, current_time):
    requests = sort_requests(requests)
    print(requests)


问:
TableAdapter Fill doesn't update database
I want to insert data into MS Access using a DataSet and TableAdapters, but unfortunately it doesn't update the table in MS Access when I run this code:

```<code>DataSet2TableAdapters.Tabelle1TableAdapter tabelle1TableAdapter = new DataSet2TableAdapters.Tabelle1TableAdapter();

DataSet2 dataSet2 = new DataSet2();
dataSet2.Tabelle1.Insert("hallo", 1);
tabelle1TableAdapter.Update(dataSet2.Tabelle1);
</code>```

This is just a test file in my actual MS Access file the table has a lot of columns so I really like to use the "Insert" method or something similiar because it's easy to write.

Some suggestions how I can accomplish this?

答:
One common pitfall in this situation is that your database file may get overwritten in your compile/execute cycle. Everything you added in one execution may get lost next time you compile your project, with the database file being reset to its initial state. VS stores the original DB file in your project root folder. Your application uses its own copy stored in the bin folder (or somewhere else).

There's a few troubleshooting steps you can take in order to establish if this is actually your problem and eventually solve it: 1) in the solution explorer window, right-click your database and select Properties. Change Copy to Output Directory to Do not copy. 2) After compiling your application, run it a couple of times outside VS and the debugging environment and verify if the problem goes away. 3) Modify your existing code to reload your data, from the database, right after an insertion or deletion has been successfully executed and verify if the problem goes away.

Or, if you know exactly where the file is located, simply verify that the records were actually properly stored.

Body:
I want to insert data into MS Access using a DataSet and TableAdapters, but unfortunately it doesn't update the table in MS Access when I run this code:

DataSet2TableAdapters.Tabelle1TableAdapter tabelle1TableAdapter = new DataSet2TableAdapters.Tabelle1TableAdapter();

DataSet2 dataSet2 = new DataSet2();
dataSet2.Tabelle1.Insert("hallo", 1);
tabelle1TableAdapter.Update(dataSet2.Tabelle1);

This is just a test file in my actual MS Access file the table has a lot of columns so I really like to use the "Insert" method or something similiar because it's easy to write.

Some suggestions how I can accomplish this?


问:
Cannot find symbol : when compiling java code
I am writing some Java classes to implement RMI. I wrote all the classes and the program worked fine. But from the very next day I am getting a compiler error indicating that the absence of files:

Filename: ServerInterface.java

```<code>import java.rmi.*;

public interface ServerInterface extends Remote
{
  public double sum(double[] temp) throws RemoteException;
};
</code>```

Filename: ServerImplement.java

```<code>import java.rmi.*;
import java.rmi.server.*;

public class ServerImplement extends UnicastRemoteObject implements ServerInterface
{

 public ServerImplement() throws RemoteException
 {
 }

 public double sum(double[] temp) throws RemoteException
 {
   double sum=0;
   int len=temp.length;
   for(int i=0;i<len;i++)
     sum+=temp[i];

   return sum;
 }
};
</code>```

Even to prove that its not any filename errors:

```<code>F:\E\java\rmi final>dir
 Volume in drive F is My Volume
 Volume Serial Number is E0F9-4F89

 Directory of F:\E\java\rmi final

22-01-2011  23:23    <DIR>          .
22-01-2011  23:23    <DIR>          ..
22-12-2009  13:09             1,849 additionImplementer_Stub.class
21-01-2011  21:52             1,076 Client.class
18-01-2011  02:54               649 Client.java
21-01-2011  21:52             1,847 ClientTry.class
18-01-2011  02:54             1,268 ClientTry.java
21-01-2011  21:52               444 ServerImplement.class
18-01-2011  02:30               386 ServerImplement.java
18-01-2011  02:54             1,783 ServerImplement_Stub.class
21-01-2011  21:54               209 ServerInterface.class
22-12-2009  12:07               132 ServerInterface.java
21-01-2011  21:52               919 ServerMain.class
18-01-2011  02:36               409 ServerMain.java
          12 File(s)         10,971 bytes
</code>```

If I try: javac *.java , it works fine (but trying java on any of the .class files leads to error : Exception in thread "main" java.lang.NoClassDefFoundError: ServerMain

If I try javac ServerImplement.java I get an error (in fact none of my java programs are able to link):
(I am in the same directory)

E:\java\rmi final>javac  ServerMain.java

  ServerImplement.java:4: cannot find symbol

  symbol: class ServerInterface

  public class ServerImplement extends UnicastRemoteObject implements ServerInterface

  ^

  1 error

The program is even working fine at my college lab. Should I reinstall JDK? Or is there any way to provide linking explicitly?

答:
Sounds like you don't have "." on the classpath. Try to run it like this:

```<code>java -classpath . ServerMain
</code>```

Have a look at your CLASSPATH environment variable to see if that's getting in the way - these days I typically find it's easiest not to have one, to be honest.

ContentLicense: CC BY-SA 2.5

Body:
I am writing some Java classes to implement RMI. I wrote all the classes and the program worked fine. But from the very next day I am getting a compiler error indicating that the absence of files:

Filename: ServerInterface.java

import java.rmi.*;

public interface ServerInterface extends Remote
{
  public double sum(double[] temp) throws RemoteException;
};

Filename: ServerImplement.java

import java.rmi.*;
import java.rmi.server.*;

public class ServerImplement extends UnicastRemoteObject implements ServerInterface
{

 public ServerImplement() throws RemoteException
 {
 }

 public double sum(double[] temp) throws RemoteException
 {
   double sum=0;
   int len=temp.length;
   for(int i=0;i<len;i++)
     sum+=temp[i];

   return sum;
 }
};

Even to prove that its not any filename errors:

F:\E\java\rmi final>dir
 Volume in drive F is My Volume
 Volume Serial Number is E0F9-4F89

 Directory of F:\E\java\rmi final

22-01-2011  23:23    <DIR>          .
22-01-2011  23:23    <DIR>          ..
22-12-2009  13:09             1,849 additionImplementer_Stub.class
21-01-2011  21:52             1,076 Client.class
18-01-2011  02:54               649 Client.java
21-01-2011  21:52             1,847 ClientTry.class
18-01-2011  02:54             1,268 ClientTry.java
21-01-2011  21:52               444 ServerImplement.class
18-01-2011  02:30               386 ServerImplement.java
18-01-2011  02:54             1,783 ServerImplement_Stub.class
21-01-2011  21:54               209 ServerInterface.class
22-12-2009  12:07               132 ServerInterface.java
21-01-2011  21:52               919 ServerMain.class
18-01-2011  02:36               409 ServerMain.java
          12 File(s)         10,971 bytes

If I try: javac *.java , it works fine (but trying java on any of the .class files leads to error : Exception in thread "main" java.lang.NoClassDefFoundError: ServerMain

If I try javac ServerImplement.java I get an error (in fact none of my java programs are able to link):
(I am in the same directory)

E:\java\rmi final>javac  ServerMain.java

  ServerImplement.java:4: cannot find symbol

  symbol: class ServerInterface

  public class ServerImplement extends UnicastRemoteObject implements ServerInterface

  ^

  1 error

The program is even working fine at my college lab. Should I reinstall JDK? Or is there any way to provide linking explicitly?

Body:
Sounds like you don't have "." on the classpath. Try to run it like this:

java -classpath . ServerMain

Have a look at your CLASSPATH environment variable to see if that's getting in the way - these days I typically find it's easiest not to have one, to be honest.


问:
How to reconnect with Rabbit MQ after server goes down?
I have a spring-boot application that uses Rabbit RPC.
The problem is that if the app starts, then Rabbit server goes down, the application doesn't reconnect with the server. And if the app starts while the rabbit server is down, it fails and doesn't attempt to reconnect to Rabbit after the Rabbit goes up again.
Here is code of configuration

```<code>@Configuration
public class RabbitConfiguration {

@Value("${spring.rabbitmq.host}")
private String rabbitmqHost;

@Value("${spring.rabbitmq.queue}")
private String rabbitmqQueue;

@Value("${spring.rabbitmq.username}")
private String rabbitmqUsername;

@Value("${spring.rabbitmq.password}")
private String rabbitmqPassword;

private final CommentsServiceRpc commentsServiceRpc;

public RabbitConfiguration(final CommentsServiceRpc commentsServiceRpc) {
    this.commentsServiceRpc = commentsServiceRpc;
}

@Bean
public Connection rabbitmqConnection() throws IOException, TimeoutException {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost(rabbitmqHost);
    factory.setUsername(rabbitmqUsername);
    factory.setPassword(rabbitmqPassword);
    return factory.newConnection();
}

@Bean
public Channel rpcChanel() throws IOException, TimeoutException {
    Connection connection = rabbitmqConnection();
    Channel channel = connection.createChannel();
    channel.queueDeclare(rabbitmqQueue, false, false, false, null);
    return channel;
}

@Bean("commentsJsonRpcServer")
@Lazy(false)
public JsonRpcServer commentsJsonRpcServer() throws IOException, TimeoutException {
    JsonRpcServer jsonRpcServer = new JsonRpcServer(rpcChanel(), rabbitmqQueue, CommentsServiceRpc.class,
            commentsServiceRpc);
    new Thread(() -> {
        try {
            jsonRpcServer.mainloop();
        } catch (Exception e) {
            System.out.println(e);
        }
    }).start();
    return jsonRpcServer;
}
}
</code>```

How can I tell Spring-boot to try to reconnect, if Rabbit server fails and restarts?

答:
I don't know the first thing about Spring Boot, but this answer looks promising -

I've had a similar issue, you just have to put a property on the connection factory configuration.

As per the article here set factory.setAutomaticRecoveryEnabled(true); and factory.setNetworkRecoveryInterval(10000); on the factory and the rabbit client will try to reconnect when the rabbit server is down or the connection is lost.

Because you are using spring configuration for the connection factory your connection factory will be like the following

```<code><bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
    <constructor-arg value="somehost"/>
    <property name="username" value="guest"/>
    <property name="password" value="guest"/>
    <property name="automaticRecoveryEnabled" value="true"/>
    <property name="networkRecoveryInterval" value="100000"/>
</bean>
</code>```

Connection factory reference here

Body:
I have a spring-boot application that uses Rabbit RPC.
The problem is that if the app starts, then Rabbit server goes down, the application doesn't reconnect with the server. And if the app starts while the rabbit server is down, it fails and doesn't attempt to reconnect to Rabbit after the Rabbit goes up again.
Here is code of configuration

@Configuration
public class RabbitConfiguration {

@Value("${spring.rabbitmq.host}")
private String rabbitmqHost;

@Value("${spring.rabbitmq.queue}")
private String rabbitmqQueue;

@Value("${spring.rabbitmq.username}")
private String rabbitmqUsername;

@Value("${spring.rabbitmq.password}")
private String rabbitmqPassword;

private final CommentsServiceRpc commentsServiceRpc;

public RabbitConfiguration(final CommentsServiceRpc commentsServiceRpc) {
    this.commentsServiceRpc = commentsServiceRpc;
}

@Bean
public Connection rabbitmqConnection() throws IOException, TimeoutException {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost(rabbitmqHost);
    factory.setUsername(rabbitmqUsername);
    factory.setPassword(rabbitmqPassword);
    return factory.newConnection();
}

@Bean
public Channel rpcChanel() throws IOException, TimeoutException {
    Connection connection = rabbitmqConnection();
    Channel channel = connection.createChannel();
    channel.queueDeclare(rabbitmqQueue, false, false, false, null);
    return channel;
}

@Bean("commentsJsonRpcServer")
@Lazy(false)
public JsonRpcServer commentsJsonRpcServer() throws IOException, TimeoutException {
    JsonRpcServer jsonRpcServer = new JsonRpcServer(rpcChanel(), rabbitmqQueue, CommentsServiceRpc.class,
            commentsServiceRpc);
    new Thread(() -> {
        try {
            jsonRpcServer.mainloop();
        } catch (Exception e) {
            System.out.println(e);
        }
    }).start();
    return jsonRpcServer;
}
}

How can I tell Spring-boot to try to reconnect, if Rabbit server fails and restarts?

Body:
I don't know the first thing about Spring Boot, but this answer looks promising -

I've had a similar issue, you just have to put a property on the connection factory configuration.

As per the article here set factory.setAutomaticRecoveryEnabled(true); and factory.setNetworkRecoveryInterval(10000); on the factory and the rabbit client will try to reconnect when the rabbit server is down or the connection is lost.

Because you are using spring configuration for the connection factory your connection factory will be like the following

<bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
    <constructor-arg value="somehost"/>
    <property name="username" value="guest"/>
    <property name="password" value="guest"/>
    <property name="automaticRecoveryEnabled" value="true"/>
    <property name="networkRecoveryInterval" value="100000"/>
</bean>

Connection factory reference here


答:
Using apply

```<code>box=box.apply(lambda x : x.name*x.index)
</code>```

Or we recreate the dataframe box

```<code>box=pd.DataFrame(box.index.values[:,None]*box.columns.values,index=box.index,columns=box.columns)
</code>```

Title: How to populate Pandas dataframe as function of index and columns

Body:
I have a dataframe where the index and column are both numbers--i.e.

rng = np.arange(2,51)
box = pd.DataFrame(index = rng, columns = rng)

I want the values of the dataframe to be a function of the index and column--so for instance box[2][2] should equal 4.

Currently I have it in

for x in range(2,len(box)+2):
    for y in range(2,len(box)+2):
        box[x][y] = x*y
box

but I feel like there should be a more elegant solution. Is there a way to do this purely with slicing/dataframe assignment methods?

Body:
Using apply

box=box.apply(lambda x : x.name*x.index)

Or we recreate the dataframe box

box=pd.DataFrame(box.index.values[:,None]*box.columns.values,index=box.index,columns=box.columns)


问:
Ansible iterate over hosts in inventory group set by variable
I have the next snippet in my role template:

```<code>upstream portal {
 {% set nodes = groups["my_dev_cluster"] %}
 {% for node in nodes %}
 ...do something with nodes...
 {% endfor %}
}
</code>```

And it works well.

But when I try to parametrize inventory group name like this:

```<code>upstream portal {
 {% set nodes = groups["{{cluster_name}}"] %}
 {% for node in nodes %}
 ...do something with nodes...
 {% endfor %}
}
</code>```

I get an exception like:

```<code> FAILED! => {"changed": false, "failed": true, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute '{{cluster_name}}'"}
</code>```

Here, cluster_name - is a simple string variable defined in defaults section.

Is it possible to parametrize it at all?

Thanks in advance!

答:
You don't need {{...}} because you're already inside a jinja context (in this case, the {% set ... %} block.  Just write:

```<code>{% set nodes = groups[cluster_name] %}
</code>```

Body:
I have the next snippet in my role template:

upstream portal {
 {% set nodes = groups["my_dev_cluster"] %}
 {% for node in nodes %}
 ...do something with nodes...
 {% endfor %}
}

And it works well.

But when I try to parametrize inventory group name like this:

upstream portal {
 {% set nodes = groups["{{cluster_name}}"] %}
 {% for node in nodes %}
 ...do something with nodes...
 {% endfor %}
}

I get an exception like:

 FAILED! => {"changed": false, "failed": true, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute '{{cluster_name}}'"}

Here, cluster_name - is a simple string variable defined in defaults section.

Is it possible to parametrize it at all?

Thanks in advance!

Body:
You don't need {{...}} because you're already inside a jinja context (in this case, the {% set ... %} block.  Just write:

{% set nodes = groups[cluster_name] %}


问:
Configuration Membership on localhost and real hosting
On localhost use SQLServer Express Edition. When I upload file to real hosting,my hosting use Full SQL Server 2005. How to config the ConnectionString of Membership(aspnetdb.mdf) </p>

答: connectionstrings should stay the same. if db and app is same machine and u set location to localhost.</p>