Skip to content

Instantly share code, notes, and snippets.

@jacobfogg
Forked from apipkin/gist:521143
Created August 12, 2010 15:43
Show Gist options
  • Save jacobfogg/521174 to your computer and use it in GitHub Desktop.
Save jacobfogg/521174 to your computer and use it in GitHub Desktop.
<!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 &quot;Slide To Submit&quot;
*/
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 &quot;Submitting!&quot;
*/
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