-
-
Save jacobfogg/521174 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="chrome=1"> | |
<meta name="description" content="Sliding CAPTCHA example"> | |
<title>Sliding CAPTCHA Example</title> | |
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?3.1.1/build/cssreset/reset-min.css&3.1.1/build/cssbase/base- | |
min.css&3.1.1/build/cssfonts/fonts-min.css"> | |
<style> | |
body{ | |
margin:30px; | |
} | |
.yui3-slider-captcha{ | |
-moz-border-radius:10px 10px 10px 10px; | |
-webkit-border-radius:10px; | |
border-radius:10px; | |
background-color:#1D1D1D; | |
background-image:-moz-linear-gradient(center top , #1D1D1D, #717171); | |
background-image:-webkit-gradient(linear, left top, left bottom, from(#1D1D1D), to(#717171)); | |
-webkit-user-select:none; | |
-moz-user-select:none; | |
height:30px; | |
padding:2px; | |
width:204px; | |
} | |
.yui3-slider-captcha .yui3-slider-captcha-content{ | |
position:relative; | |
} | |
.yui3-slider-captcha .yui3-slider-captcha-message{ | |
color:white; | |
font-size:116%; | |
font-weight:bold; | |
padding-top:6px; | |
text-align:center; | |
} | |
.yui3-slider-captcha .yui3-slider-captcha-handle{ | |
-moz-border-radius:8px 8px 8px 8px; | |
-webkit-border-radius:8px; | |
border-radius:8px; | |
background-color:#EAEAEA; | |
background-image:-moz-linear-gradient(center top , #EAEAEA, #FBFBFB); | |
background-image:-webkit-gradient(linear, left top, left bottom, from(#EAEAEA), to(#FBFBFB)); | |
color:#BBBBBB; | |
cursor:pointer; | |
font-size:167%; | |
font-weight:bold; | |
height:25px; | |
left:0; | |
line-height:8px; | |
padding-top:5px; | |
position:absolute; | |
text-align:center; | |
top:0; | |
width:30px; | |
} | |
.chrome .yui3-slider-captcha .yui3-slider-captcha-handle{ | |
height:21px; | |
line-height:0; | |
padding-top:9px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="captcha"></div> | |
<script src="http://yui.yahooapis.com/3.1.1/build/yui/yui-min.js"></script> | |
<script> | |
//add .chrome to html to fix css issue with line-height in chrome | |
if( navigator.userAgent.toLowerCase().indexOf( 'chrome' ) != -1 ) { | |
document.documentElement.className += ' chrome'; | |
} | |
var myCaptcha; | |
Y = YUI().use('gallery-slider-captcha',function(Y){ | |
myCaptcha = new Y.SliderCaptcha(); | |
myCaptcha.on(myCaptcha.EVENTS.RELEASE_SUCCESS,function(){alert('success');});//test listening to release success | |
myCaptcha.render(); | |
}); | |
YUI.add('gallery-slider-captcha', function(Y){ | |
var isString = Y.Lang.isString, | |
isBoolean = Y.Lang.isBoolean | |
EVENTS = { | |
RELEASE_SUCCESS: 'releaseSuccess', | |
RELEASE_FAILURE: 'releaseFailure' | |
}, | |
CLASSES = { | |
CONTENT: 'content', | |
MESSAGE: 'message', | |
HANDLE: 'handle', | |
}; | |
Y.SliderCaptcha = Y.Base.create('slider-captcha', Y.Widget, [], { | |
/** | |
* A reference to the message node | |
* | |
* @property message | |
*/ | |
message: null, | |
/** | |
* A reference to the handle node | |
* | |
* @property handle | |
*/ | |
handle: null, | |
/** | |
* A reference to the max number of pixles the handle can be dragged | |
* | |
* @property maxLeft | |
*/ | |
maxLeft: null, | |
/** | |
* A constant of event name constants, designed so the addressing of events could be handled consistantly | |
* | |
* @property EVENTS | |
*/ | |
EVENTS: { | |
RELEASE_SUCCESS: 'releaseSuccess', | |
RELEASE_FAILURE: 'releaseFailure' | |
}, | |
// P U B L I C // | |
/** | |
* Initalizes the module | |
* | |
* @method initializer | |
*/ | |
initializer: function() { | |
Y.log( 'initializer', 'info', 'gallery-slider-captcha.js' ); | |
// publish releaseSuccess event | |
this.publish( this.EVENTS.RELEASE_SUCCESS, { defaultFn: this._defReleaseSuccessFn }, this, true ); | |
// publish releaseFailure event | |
this.publish( this.EVENTS.RELEASE_FAILURE, { defaultFn: this._defReleaseFailureFn }, this, true ); | |
}, | |
/** | |
* Creates the structure for the module | |
* | |
* @method renderUI | |
*/ | |
renderUI: function() { | |
Y.log( 'renderUI', 'info', 'gallery-slider-captcha.js' ); | |
// build message container | |
this.message = Y.Node.create( '<div class="' + this.getClassName( CLASSES.MESSAGE ) + '">' + this.get( 'startText' ) + '</div>' ); | |
// build handle | |
this.handle = Y.Node.create( '<div class="' + this.getClassName( CLASSES.HANDLE ) + '">.... ....</div>' ); | |
// append to content box | |
this.get( 'contentBox' ).append( this.message ).append( this.handle ); | |
this.maxLeft = this.get( 'contentBox' ).get( 'offsetWidth' ) - this.handle.get( 'offsetWidth' ); | |
}, | |
/** | |
* Binds the events to the structure | |
* | |
* @method bindUI | |
*/ | |
bindUI: function() { | |
Y.log( 'bindUI', 'info', 'gallery-slider-captcha.js' ); | |
// add dd to handle and constrain to content box | |
var handleDD = new Y.DD.Drag( { node: this.handle } ).plug( Y.Plugin.DDConstrained, { constrain2node: this.get( 'contentBox' ) } ); | |
// add opacity change to text while dragging based on percentage to end. 100% - 10%? | |
handleDD.on( 'drag:drag', this._onHandleDrag, this, true ); | |
// add animation to spring back on release if not at the edge of the container | |
handleDD.on( 'drag:end', this._onHandleDrop, this, true ); | |
// add release callback to fire success or failure event | |
}, | |
// S U G A R // | |
/** | |
* A sugar method for detecting if the CAPTCHA isHuman | |
* | |
* @method isHuman | |
*/ | |
isHuman: function() { | |
Y.log( 'isHuman', 'info', 'gallery-slider-captcha.js' ); | |
return this.get( 'isHuman' ); | |
}, | |
// P R O T E C T E D // | |
/** | |
* Method that executes if the release was a success | |
* | |
* @method _defReleaseSuccessFn | |
*/ | |
_defReleaseSuccessFn: function( e ) { | |
Y.log( '_defReleaseSuccessFn', 'info', 'gallery-slider-captcha.js' ); | |
var form = this.get( 'form' ), | |
submit = this.get( 'submitOnSuccess' ); | |
this.message.set( 'text', this.get( 'successText' ) );// update text | |
this.message.setStyle( 'opacity', 1); | |
this.handle.setStyle( 'left', this.maxLeft + 'px' ); | |
this.set( 'isHuman', true );// set isHuman to true | |
if( form && submit ) { | |
form.submit(); | |
} | |
}, | |
/** | |
* Method that executes if the release was not a success | |
* | |
* @method _defReleaseFailureFn | |
*/ | |
_defReleaseFailureFn: function( e ) { | |
Y.log( '_defReleaseFailureFn', 'info', 'gallery-slider-captcha.js' ); | |
this.set( 'isHuman', false );// set isHuman to false | |
this.message.set( 'text', this.get( 'startText' ) ); | |
var releaseAnim = new Y.Anim({ | |
node: this.handle, | |
duration: .2, | |
to: { | |
left: 0 | |
} | |
}); | |
releaseAnim.on('tween', this._onHandleDrag, this, true, true); | |
releaseAnim.run(); | |
}, | |
/** | |
* Event callback for the DD on:Drag event, as well as the Anim on:tween | |
* | |
* @method _onHandleDrag | |
*/ | |
_onHandleDrag: function( e ) { | |
// Y.log( '_onHandleDrag', 'info', 'gallery-slider-captcha.js' ); | |
//adjust opacity of text based on position from 100% - 10% | |
var left = this.handle.getStyle('left').replace(/[^0-9]/g,''), | |
opacity = ( ( this.maxLeft - left ) / this.maxLeft ) + .2; | |
opacity = opacity > 1 ? 1 : opacity;//limit opacity to 1 | |
this.message.setStyle( 'opacity', opacity ); | |
}, | |
/** | |
* Event callback for DD on:Drop event | |
* | |
* @method _onHandleDrop | |
*/ | |
_onHandleDrop: function( e ) { | |
Y.log( '_onHandleDrop', 'info', 'gallery-slider-captcha.js' ); | |
//if droped near edge, fire success, else fire failure | |
var left = this.handle.getStyle('left').replace(/[^0-9]/g,''); | |
if( ( this.maxLeft - left ) < 10 ){// if you are within 10px of the end | |
this.fire( this.EVENTS.RELEASE_SUCCESS ); | |
}else{ | |
this.fire( this.EVENTS.RELEASE_FAILURE ); | |
} | |
} | |
}, { | |
ATTRS: { | |
/** | |
* Stores the node for the form to be submitted on successful release drop | |
* | |
* @attribute form | |
* @type | |
* @default | |
*/ | |
form: { | |
}, | |
/** | |
* The start text to display to the user prior to the successful on:drop event is fired | |
* | |
* @attribute startText | |
* @type {string} | |
* @default "Slide To Submit" | |
*/ | |
startText: { | |
value: 'Slide To Submit', | |
validator: isString | |
}, | |
/** | |
* The end text to be displayed as soon as the releaseSuccess event is fired | |
* | |
* @attribute successText | |
* @type {string} | |
* @default "Submitting!" | |
*/ | |
successText: { | |
value: 'Submitting!', | |
validator: isString | |
}, | |
/** | |
* Attribute to determine if the user has been validated as human | |
* | |
* @attribute isHuman | |
* @type {boolean} | |
* @default false | |
*/ | |
isHuman: { | |
value: false, | |
validator: isBoolean | |
}, | |
/** | |
* Determines if we should submit the form or not | |
* | |
* @attribute submitOnSuccess | |
* @type {boolean} | |
* @default true | |
*/ | |
submitOnSuccess: { | |
value: true, | |
validator: isBoolean | |
} | |
} | |
}); | |
}, '@VERSION@', { requires: [ 'widget', 'dd-constrain', 'anim' ] } ); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment