Skip to content

Instantly share code, notes, and snippets.

@pingpoli
Last active June 3, 2022 15:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pingpoli/022d9b48d9474808b6b8b6fe56b0eb9b to your computer and use it in GitHub Desktop.
Save pingpoli/022d9b48d9474808b6b8b6fe56b0eb9b to your computer and use it in GitHub Desktop.
function pingpoliSliderCaptcha()
{
this.container = null;
this.context = null;
this.onsuccess = () => {
console.log( "pingpoliSliderCaptcha > default onsuccess callback" );
};
this.onfail = () => {
console.log( "pingpoliSliderCaptcha > default onfail callback" );
};
this.errorMargin = 5;
}
pingpoliSliderCaptcha.prototype.show = function( xPercent , yPercent )
{
var captchaX = 50+xPercent*300;
var captchaY = 5+yPercent*250;
// pick a random position if no position was specified
if ( xPercent === undefined )
{
captchaX = 50+Math.random()*300;
}
if ( yPercent === undefined )
{
captchaY = 5+Math.random()*250;
}
// create the container
this.container = document.createElement( "div" );
this.container.style.cssText = "box-sizing:border-box;position:absolute;top:100px;left:50%;width:420px;margin-left:-200px;background-color:#eeeeee;border:1px solid #dddddd;box-shadow:0px 0px 10px #555555;text-align:center;z-index:999;";
// top bar
var topBar = document.createElement( "div" );
topBar.style.cssText = "box-sizing:border-box;width:100%;padding:5px;background-color:#dddddd;";
topBar.textContent = "Verification";
var topBarCloseButton = document.createElement( "button" );
topBarCloseButton.style.cssText = "box-sizing:border-box;float:right;width:20px;height:20px;background-color:#cccccc;border:1px solid #bbbbbb;border-radius:0px;color:#555555;text-align:center;font-weight:normal;line-height:20px;";
topBarCloseButton.textContent = "x";
topBarCloseButton.onclick = () => {
this.hide();
};
topBar.appendChild( topBarCloseButton );
this.container.appendChild( topBar );
// canvas
var canvas = document.createElement( "canvas" );
canvas.width = 400;
canvas.height = 300;
canvas.style.cssText = "touch-action:none;box-sizing:border-box;width:400px;height:300px;margin:10px 0px;";
this.container.appendChild( canvas );
this.context = canvas.getContext( "2d" );
this.context.lineWidth = 3;
// load and draw the image
var image = new Image();
image.src = "/img/captcha.png";
image.onload = () => {
this.context.drawImage( image , 0 , 0 , 400 , 300 );
this.context.fillStyle = "#ffffff55";
this.context.fillRect( captchaX , captchaY , 40 , 40 );
this.context.strokeStyle = "#ffffff";
this.context.beginPath();
this.context.rect( captchaX , captchaY , 40 , 40 );
this.context.stroke();
// target
this.context.drawImage( image , captchaX , captchaY , 40 , 40 , 0 , captchaY , 40 , 40 );
this.context.strokeStyle = "#ff0000";
this.context.beginPath();
this.context.rect( 0 , captchaY , 40 , 40 );
this.context.stroke();
};
// slider background
var sliderBackground = document.createElement( "div" );
sliderBackground.style.cssText = "box-sizing:border-box;position:relative;display:inline-block;width:400px;height:40px;margin-bottom:8px;background-color:#ffffff;border:1px solid #dddddd;";
var slider = document.createElement( "div" );
slider.style.cssText = "box-sizing:border-box;position:absolute;left:0px;width:38px;height:38px;background-color:#cccccc;border:1px solid #bbbbbb;font-size:24px;color:#555555;text-align:center;line-height:38px;cursor:grab;user-select:none;";
slider.textContent = "➔";
var b_sliderIsDragging = false;
var sliderDragStartX = 0;
var sliderDragStartLeft = 0;
var sliderLeft = 0;
slider.onmousedown = ( e ) => {
b_sliderIsDragging = true;
sliderDragStartX = e.clientX;
sliderDragStartLeft = parseInt( slider.style.left.substring( 0 , slider.style.left.indexOf( "px" ) ) );
};
this.container.onmousemove = ( e ) => {
if ( b_sliderIsDragging )
{
var dx = e.clientX - sliderDragStartX;
sliderLeft = sliderDragStartLeft+dx;
if ( sliderLeft < 0 ) sliderLeft = 0;
if ( sliderLeft > 360 ) sliderLeft = 360;
slider.style.left = sliderLeft+"px";
// redraw canvas
this.context.clearRect( 0 , 0 , 400 , 300 );
this.context.drawImage( image , 0 , 0 , 400 , 300 );
this.context.fillStyle = "#ffffff55";
this.context.fillRect( captchaX , captchaY , 40 , 40 );
this.context.strokeStyle = "#ffffff";
this.context.beginPath();
this.context.rect( captchaX , captchaY , 40 , 40 );
this.context.stroke();
// target
this.context.drawImage( image , captchaX , captchaY , 40 , 40 , sliderLeft , captchaY , 40 , 40 );
if ( Math.abs( sliderLeft - captchaX ) < this.errorMargin )
{
this.context.strokeStyle = "#00ff00";
}
else
{
this.context.strokeStyle = "#ff0000";
}
this.context.beginPath();
this.context.rect( sliderLeft , captchaY , 40 , 40 );
this.context.stroke();
}
};
this.container.onmouseup = () => {
b_sliderIsDragging = false;
// check whether it was correct
if ( Math.abs( sliderLeft - captchaX ) < this.errorMargin )
{
this.onsuccess();
}
else
{
this.onfail();
}
};
sliderBackground.appendChild( slider );
this.container.appendChild( sliderBackground );
// add the container to the body
document.body.appendChild( this.container );
}
pingpoliSliderCaptcha.prototype.hide = function()
{
document.body.removeChild( this.container );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment