visualcaptcha 0.0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +52 -0
  4. data/lib/generators/templates/partial.erb +20 -0
  5. data/lib/generators/visual_captcha_generator.rb +13 -0
  6. data/lib/visualcaptcha.rb +111 -0
  7. data/lib/visualcaptcha/controller.rb +15 -0
  8. data/lib/visualcaptcha/engine.rb +10 -0
  9. data/lib/visualcaptcha/utils.rb +11 -0
  10. data/lib/visualcaptcha/version.rb +3 -0
  11. data/lib/visualcaptcha/view.rb +37 -0
  12. data/vendor/assets/images/accessibility.png +0 -0
  13. data/vendor/assets/images/accessibility@2x.png +0 -0
  14. data/vendor/assets/images/airplane.png +0 -0
  15. data/vendor/assets/images/airplane@2x.png +0 -0
  16. data/vendor/assets/images/balloons.png +0 -0
  17. data/vendor/assets/images/balloons@2x.png +0 -0
  18. data/vendor/assets/images/camera.png +0 -0
  19. data/vendor/assets/images/camera@2x.png +0 -0
  20. data/vendor/assets/images/car.png +0 -0
  21. data/vendor/assets/images/car@2x.png +0 -0
  22. data/vendor/assets/images/cat.png +0 -0
  23. data/vendor/assets/images/cat@2x.png +0 -0
  24. data/vendor/assets/images/chair.png +0 -0
  25. data/vendor/assets/images/chair@2x.png +0 -0
  26. data/vendor/assets/images/clip.png +0 -0
  27. data/vendor/assets/images/clip@2x.png +0 -0
  28. data/vendor/assets/images/clock.png +0 -0
  29. data/vendor/assets/images/clock@2x.png +0 -0
  30. data/vendor/assets/images/cloud.png +0 -0
  31. data/vendor/assets/images/cloud@2x.png +0 -0
  32. data/vendor/assets/images/computer.png +0 -0
  33. data/vendor/assets/images/computer@2x.png +0 -0
  34. data/vendor/assets/images/dropzone-edit.png +0 -0
  35. data/vendor/assets/images/dropzone.png +0 -0
  36. data/vendor/assets/images/dropzone@2x-edit.png +0 -0
  37. data/vendor/assets/images/dropzone@2x.png +0 -0
  38. data/vendor/assets/images/envelope.png +0 -0
  39. data/vendor/assets/images/envelope@2x.png +0 -0
  40. data/vendor/assets/images/eye.png +0 -0
  41. data/vendor/assets/images/eye@2x.png +0 -0
  42. data/vendor/assets/images/flag.png +0 -0
  43. data/vendor/assets/images/flag@2x.png +0 -0
  44. data/vendor/assets/images/folder.png +0 -0
  45. data/vendor/assets/images/folder@2x.png +0 -0
  46. data/vendor/assets/images/foot.png +0 -0
  47. data/vendor/assets/images/foot@2x.png +0 -0
  48. data/vendor/assets/images/graph.png +0 -0
  49. data/vendor/assets/images/graph@2x.png +0 -0
  50. data/vendor/assets/images/house.png +0 -0
  51. data/vendor/assets/images/house@2x.png +0 -0
  52. data/vendor/assets/images/key.png +0 -0
  53. data/vendor/assets/images/key@2x.png +0 -0
  54. data/vendor/assets/images/lamp.png +0 -0
  55. data/vendor/assets/images/lamp@2x.png +0 -0
  56. data/vendor/assets/images/leaf.png +0 -0
  57. data/vendor/assets/images/leaf@2x.png +0 -0
  58. data/vendor/assets/images/lock.png +0 -0
  59. data/vendor/assets/images/lock@2x.png +0 -0
  60. data/vendor/assets/images/magnifying-glass.png +0 -0
  61. data/vendor/assets/images/magnifying-glass@2x.png +0 -0
  62. data/vendor/assets/images/man.png +0 -0
  63. data/vendor/assets/images/man@2x.png +0 -0
  64. data/vendor/assets/images/music-note.png +0 -0
  65. data/vendor/assets/images/music-note@2x.png +0 -0
  66. data/vendor/assets/images/pants.png +0 -0
  67. data/vendor/assets/images/pants@2x.png +0 -0
  68. data/vendor/assets/images/pencil.png +0 -0
  69. data/vendor/assets/images/pencil@2x.png +0 -0
  70. data/vendor/assets/images/printer.png +0 -0
  71. data/vendor/assets/images/printer@2x.png +0 -0
  72. data/vendor/assets/images/robot.png +0 -0
  73. data/vendor/assets/images/robot@2x.png +0 -0
  74. data/vendor/assets/images/scissors.png +0 -0
  75. data/vendor/assets/images/scissors@2x.png +0 -0
  76. data/vendor/assets/images/sunglasses.png +0 -0
  77. data/vendor/assets/images/sunglasses@2x.png +0 -0
  78. data/vendor/assets/images/tag.png +0 -0
  79. data/vendor/assets/images/tag@2x.png +0 -0
  80. data/vendor/assets/images/tree.png +0 -0
  81. data/vendor/assets/images/tree@2x.png +0 -0
  82. data/vendor/assets/images/truck.png +0 -0
  83. data/vendor/assets/images/truck@2x.png +0 -0
  84. data/vendor/assets/images/tshirt.png +0 -0
  85. data/vendor/assets/images/tshirt@2x.png +0 -0
  86. data/vendor/assets/images/umbrella.png +0 -0
  87. data/vendor/assets/images/umbrella@2x.png +0 -0
  88. data/vendor/assets/images/woman.png +0 -0
  89. data/vendor/assets/images/woman@2x.png +0 -0
  90. data/vendor/assets/images/world.png +0 -0
  91. data/vendor/assets/images/world@2x.png +0 -0
  92. data/vendor/assets/javascripts/visualcaptcha.js +161 -0
  93. data/vendor/assets/stylesheets/visualcaptcha.css +128 -0
  94. metadata +163 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ODcyY2Q2MjhiOGJhMjY2YjZhZmU2ODc2NzY3YzE0NTk2OTAwYmYwNw==
5
+ data.tar.gz: !binary |-
6
+ MzFhZDZiNjg3ODRhYzQ3OTYxNDYzMTU1YzE2ODY4MzUyZGFiNjY5MA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ZmNiZTljYjdmMmE1ZTQyM2E3ZTk1YmRlMjk3Yzg4ZmNhYWVkODUxZjNkMDZh
10
+ YjcwYzA3ZTUzNmZkMThmYzUyOGIzZWJlYTQ4YjM5MzlmNWIyMDgyYjRkZWNh
11
+ ZDU5NTIxZDEwNzU1N2Y5NjE1ODQ3ZmIxNGUwZTBlOTQ1NzA4NzQ=
12
+ data.tar.gz: !binary |-
13
+ YzRiNTYwYmJkYjU0NzQ5YjAzZWIxNTQxMmI3OTIxNWJjZGNjYTkzZmYxNTM2
14
+ ZWU3MWU4MzY2MTdkODBhZThmNjBiZGI4YTU3YTQzYTY2ZTc3OWRlYWZiZTE0
15
+ MmI5ZjViMGZlMWJmYzE3MDlmZjM1NTU2MmMyZDM4Y2RlZGE0M2M=
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Trevor Kimenye
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # Visualcaptcha
2
+
3
+ This Gem is ruby version of emotionLoop's PHP Visual Captcha
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'visualcaptcha'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install visualcaptcha
18
+
19
+ ## Setup
20
+
21
+ After installation, follow these simple steps to setup the plugin. The setup will depend on the version of rails your application is using.
22
+
23
+ $ rails generate visual_captcha
24
+
25
+ This project requires jquery-ui so you should add it to the application.js
26
+
27
+ //= require jquery.ui.all
28
+
29
+ ## Usage
30
+
31
+ ###Controller Based
32
+
33
+ We have only enabled a controller based flow at the moment - as this is the simplest use case required
34
+
35
+ In the view file within the form tags add this code
36
+
37
+ <%= show_visual_captcha(:type => :vertical) %>
38
+
39
+ Add the following line in the file "app/controllers/application.rb"
40
+
41
+ ApplicationController < ActionController::Base
42
+ include VisualCaptcha::ControllerHelpers
43
+ end
44
+
45
+
46
+ ## Contributing
47
+
48
+ 1. Fork it
49
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
50
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
51
+ 4. Push to the branch (`git push origin my-new-feature`)
52
+ 5. Create new Pull Request
@@ -0,0 +1,20 @@
1
+ <link rel="stylesheet" href="/assets/visualcaptcha.css" />
2
+ <div class="eL-captcha clearfix <%%= captcha_options[:type] %>">
3
+ <p class="eL-explanation <%%= captcha_options[:type] %>">
4
+ Drag the <strong><%%= challenge.answer.title %></strong> to the circle on the side.
5
+ </p>
6
+ <div class="eL-possibilities <%%= captcha_options[:type] %> clearfix">
7
+ <%% challenge.options.each do |option| %>
8
+ <img src="/assets/<%%= option.image %>" class="vc-<%%= option.encrypted %>" data-value="<%%= option.encrypted %>" />
9
+ <%% end %>
10
+ </div>
11
+ <div class="eL-where2go <%%= captcha_options[:type] %> clearfix">
12
+ </div>
13
+ </div>
14
+ <script src="/assets/visualcaptcha.js"></script>
15
+ <script type="text/javascript">
16
+ window.vCVals = {
17
+ 'f' : $('.eL-captcha').closest('form').attr('id'),
18
+ 'n' : 'captcha-value'
19
+ }
20
+ </script>
@@ -0,0 +1,13 @@
1
+ require 'rails/generators'
2
+
3
+ class VisualCaptchaGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+
6
+ def self.source_root
7
+ @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates/'))
8
+ end
9
+
10
+ def create_partial
11
+ template "partial.erb", File.join('app/views', 'visual_captcha', "_visual_captcha.erb")
12
+ end
13
+ end
@@ -0,0 +1,111 @@
1
+ require "visualcaptcha/version"
2
+ require "visualcaptcha/engine"
3
+
4
+ module VisualCaptcha
5
+ autoload :ViewHelper, 'visualcaptcha/view'
6
+ autoload :ControllerHelpers, 'visualcaptcha/controller'
7
+ autoload :Utils, 'visualcaptcha/utils'
8
+
9
+ def self.setup
10
+ yield self
11
+ end
12
+
13
+ class Option
14
+
15
+ attr_accessor :id, :image, :title, :encrypted
16
+
17
+ def initialize(id, image, title)
18
+ @id = id
19
+ @image = image
20
+ @title = title
21
+ @encrypted = VisualCaptcha::Utils.generate_key(id)
22
+ end
23
+
24
+ end
25
+
26
+ class Challenge
27
+ attr_accessor :answer, :options
28
+
29
+ def initialize(answer, options=nil)
30
+ @answer = answer
31
+ @options = options
32
+ @options << answer
33
+ @options.shuffle!
34
+ end
35
+ end
36
+
37
+ class Captcha
38
+
39
+ attr_accessor :number
40
+
41
+ def initialize(number=4)
42
+ @number = number
43
+ @answers = [
44
+ Option.new('airplane', 'airplane.png', 'Airplane'),
45
+ Option.new('balloons', 'balloons.png', 'Balloons'),
46
+ Option.new('camera', 'camera.png', 'Camera'),
47
+ Option.new('car', 'car.png', 'Car'),
48
+ Option.new('cat', 'cat.png', 'Cat'),
49
+ Option.new('chair', 'chair.png', 'Chair'),
50
+ Option.new('clip', 'clip.png', 'Clip'),
51
+ Option.new('clock', 'clock.png', 'Clock'),
52
+ Option.new('cloud', 'cloud.png', 'Cloud'),
53
+ Option.new('computer', 'computer.png', 'Computer'),
54
+ Option.new('envelope', 'envelope.png', 'Envelope'),
55
+ Option.new('eye', 'eye.png', 'Eye'),
56
+ Option.new('flag', 'flag.png', 'Flag'),
57
+ Option.new('folder', 'folder.png', 'Folder'),
58
+ Option.new('foot', 'foot.png', 'Foot'),
59
+ Option.new('graph', 'graph.png', 'Graph'),
60
+ Option.new('house', 'house.png', 'House'),
61
+ Option.new('key', 'key.png', 'Key'),
62
+ Option.new('lamp', 'lamp.png', 'Lamp'),
63
+ Option.new('leaf', 'leaf.png', 'Leaf'),
64
+ Option.new('lock', 'lock.png', 'Lock'),
65
+ Option.new('magnifying-glass', 'magnifying-glass.png', 'Magnifying Glass'),
66
+ Option.new('man', 'man.png', 'Man'),
67
+ Option.new('music-note', 'music-note.png', 'Music Note'),
68
+ Option.new('pants', 'pants.png', 'Pants'),
69
+ Option.new('pencil', 'pencil.png', 'Pencil'),
70
+ Option.new('printer', 'printer.png', 'Printer'),
71
+ Option.new('robot', 'robot.png', 'Robot'),
72
+ Option.new('scissors', 'scissors.png', 'Scissors'),
73
+ Option.new('sunglasses', 'sunglasses.png', 'Sunglasses'),
74
+ Option.new('tag', 'tag.png', 'Tag'),
75
+ Option.new('tree', 'tree.png', 'Tree'),
76
+ Option.new('truck', 'truck.png', 'Truck'),
77
+ Option.new('tshirt', 'tshirt.png', 'T-Shirt'),
78
+ Option.new('umbrella', 'umbrella.png', 'Umbrella'),
79
+ Option.new('woman', 'woman.png', 'Woman'),
80
+ Option.new('world', 'world.png', 'World')
81
+ ]
82
+
83
+ #@$this->answers = array(
84
+ # 'tshirt' => array(self::$imagesPath . 'tshirt.png', 'T-Shirt'),
85
+ # 'umbrella' => array(self::$imagesPath . 'umbrella.png', 'Umbrella'),
86
+ # 'woman' => array(self::$imagesPath . 'woman.png', 'Woman'),
87
+ # 'world' => array(self::$imagesPath . 'world.png', 'World'),
88
+ #);
89
+ end
90
+
91
+ def build
92
+ #shuffle the options
93
+ opts = @answers.shuffle
94
+
95
+ #pick a random answer
96
+ answer = opts.sample
97
+ opts.reject! { |c| c.id == answer.id }
98
+ others = []
99
+
100
+ #pick the remaining clues
101
+ (1..@number-1).to_a.each_with_index do |c,i|
102
+
103
+ possible = opts.sample
104
+ others << possible
105
+ opts.reject! { |c| c.id == possible.id }
106
+ end
107
+ #return the challenge
108
+ Challenge.new(answer,others)
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,15 @@
1
+ module VisualCaptcha
2
+ module ControllerHelpers
3
+ def visual_captcha_valid?
4
+ return true if Rails.env.test?
5
+
6
+ if params["captcha-value"]
7
+ challenge = session[:captcha]
8
+ result = challenge.answer.encrypted == params["captcha-value"]
9
+ return result
10
+ else
11
+ return false
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ require 'rails'
2
+ require 'visualcaptcha'
3
+
4
+ module VisualCaptcha
5
+ class Engine < ::Rails::Engine
6
+ config.after_initialize do
7
+ ActionView::Base.send(:include, VisualCaptcha::ViewHelper)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ require 'digest/sha1'
2
+
3
+ module VisualCaptcha #:nodoc
4
+ module Utils #:nodoc
5
+ def self.generate_key(*args)
6
+ args << Time.now.to_s
7
+ Digest::SHA1.hexdigest(args.join)
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,3 @@
1
+ module VisualCaptcha
2
+ VERSION = "0.0.1.3"
3
+ end
@@ -0,0 +1,37 @@
1
+ module VisualCaptcha
2
+ module ViewHelper
3
+
4
+ def show_visual_captcha(options = {})
5
+ options = sanitize_options(options)
6
+
7
+ #key = visual_captcha_key('captcha')
8
+
9
+ number = options[:type] == "type-0" ? 5 : 4
10
+ captcha = VisualCaptcha::Captcha.new(number)
11
+ challenge = captcha.build
12
+
13
+ session[:captcha] = challenge
14
+
15
+ render :partial => 'visual_captcha/visual_captcha', :locals => { :captcha_options => options, :challenge => challenge }
16
+ end
17
+
18
+ private
19
+
20
+ def sanitize_options(options)
21
+ if options[:type] == :vertical
22
+ options[:type] = "type-1"
23
+ else
24
+ options[:type] = "type-0"
25
+ end
26
+ options
27
+ end
28
+
29
+ def visual_captcha_key(key_name = nil)
30
+ if key_name.nil?
31
+ session[:captcha] ||= VisualCaptcha::Utils.generate_key(session[:id].to_s, 'captcha')
32
+ else
33
+ VisualCaptcha::Utils.generate_key(session[:id].to_s, key_name)
34
+ end
35
+ end
36
+ end
37
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,161 @@
1
+ /**
2
+ * visualCaptchaHTML class by emotionLoop - 2013.03.28
3
+ *
4
+ * This file handles the JS for the main visualCaptcha class.
5
+ *
6
+ * This license applies to this file and others without reference to any other license.
7
+ *
8
+ * @author emotionLoop | http://emotionloop.com
9
+ * @link http://visualcaptcha.net
10
+ * @package visualCaptcha
11
+ * @license GNU GPL v3
12
+ * @version 4.0.3
13
+ */
14
+ $(document).ready(function() {
15
+ var isMobile = false;
16
+ var isRetina = false;
17
+ var supportsAudio = false;
18
+
19
+ var uAgent = navigator.userAgent.toLowerCase();
20
+
21
+ // Check if the user agent is a mobile one
22
+ if ( uAgent.indexOf('iphone') !== -1 || uAgent.indexOf('ipad') !== -1 || uAgent.indexOf('ipod') !== -1 ||
23
+ uAgent.indexOf('android') !== -1 ||
24
+ uAgent.indexOf('windows phone') !== -1 || uAgent.indexOf('windows ce') !== -1 ||
25
+ uAgent.indexOf('bada') !== -1 ||
26
+ uAgent.indexOf('meego') !== -1 ||
27
+ uAgent.indexOf('palm') !== -1 ||
28
+ uAgent.indexOf('blackberry') !== -1 ||
29
+ uAgent.indexOf('nokia') !== -1 || uAgent.indexOf('symbian') !== -1 ||
30
+ uAgent.indexOf('pocketpc') !== -1 ||
31
+ uAgent.indexOf('smartphone') !== -1 ||
32
+ uAgent.indexOf('mobile') !== -1 ) {
33
+ isMobile = true;
34
+ }
35
+
36
+ // Check if the device is retina-like
37
+ if ( window.devicePixelRatio && window.devicePixelRatio > 1 ) {
38
+ isRetina = true;
39
+ }
40
+
41
+ // Check if the device supports audio, for accessibility
42
+ try {
43
+ var audioElement = document.createElement('audio');
44
+ if ( audioElement.canPlayType ) {
45
+ supportsAudio = true;
46
+ }
47
+ } catch(e) {}
48
+
49
+ // If the device is retina-like, update the img src's and the dropzone class
50
+ if ( isRetina ) {
51
+ $('div.eL-captcha img').each(function(index, element) {
52
+ if ( ! $(element).attr('src') ) return;
53
+
54
+ var newImageSRC = $(element).attr('src').replace(/(.+)(\.\w{3,4})$/, "$1@2x$2");
55
+ $.ajax({
56
+ url: newImageSRC,
57
+ type: "HEAD",
58
+ success: function() {
59
+ $(element).attr('src', newImageSRC);
60
+ }
61
+ });
62
+ });
63
+
64
+ $('div.eL-captcha > div.eL-where2go').addClass('retina');
65
+ }
66
+
67
+ if ( ! supportsAudio ) {
68
+ $('div.eL-captcha > .eL-accessibility').hide();
69
+ } else {
70
+ $('div.eL-captcha > p.eL-accessibility a').on('click touchstart', function(event) {
71
+ event.preventDefault();
72
+
73
+ if ( ! $('div.eL-captcha > div.eL-accessibility').is(':visible') ) {
74
+ $('div.eL-captcha > div.eL-accessibility > audio').each(function() {
75
+ this.load();
76
+ this.play();
77
+ });
78
+
79
+ if ( ! $('#' + window.vCVals.a).length ) {
80
+ var validAccessibleElement = '<input type="text" name="' + window.vCVals.a + '" id="' + window.vCVals.a + '" value="">';
81
+ $('div.eL-captcha > div.eL-accessibility > p').after(validAccessibleElement);
82
+ }
83
+ }
84
+
85
+ $('div.eL-captcha > p.eL-explanation').stop().slideToggle('fast');
86
+ $('div.eL-captcha > div.eL-possibilities').stop().slideToggle('fast');
87
+ $('div.eL-captcha > div.eL-where2go').stop().slideToggle('fast');
88
+ $('div.eL-captcha > div.eL-accessibility').stop().slideToggle('fast');
89
+ });
90
+ }
91
+
92
+ if ( ! isMobile ) {// If it's not mobile, load normal drag/drop behavior
93
+ debugger;
94
+ $('div.eL-captcha > div.eL-possibilities > img').draggable({ opacity: 0.6, revert: 'invalid' });
95
+ $('div.eL-captcha > div.eL-possibilities').droppable({
96
+ drop: function(event, ui) {
97
+ if ( ! $('#' + window.vCVals.n).length ) {
98
+ return false;
99
+ }
100
+ if ( $('#' + window.vCVals.n).val() == $(ui.draggable).data('value') ) {
101
+ $('#' + window.vCVals.n).remove();
102
+ }
103
+ $('div.eL-captcha > div.eL-where2go').droppable('enable');
104
+ },
105
+ accept: 'div.eL-captcha > div.eL-possibilities > img'
106
+ });
107
+
108
+ $('div.eL-captcha > div.eL-where2go').droppable({
109
+ drop: function(event, ui) {
110
+ if ( $('#' + window.vCVals.n).length ) {
111
+ return false;
112
+ }
113
+ var validElement = '<input type="hidden" name="' + window.vCVals.n + '" id="' + window.vCVals.n + '" readonly="readonly" value="' + $(ui.draggable).data('value') + '">';
114
+ $('#' + window.vCVals.f).append(validElement);
115
+ $(this).droppable('disable');
116
+ },
117
+ accept: 'div.eL-captcha > div.eL-possibilities > img'
118
+ });
119
+ } else {// If it's mobile, we're going to make it possible to just tap an image and move it to the drop area automagically
120
+ $('div.eL-captcha > div.eL-possibilities > img').on('click touchstart', function() {// Add tap behavior, but keep click in case that also works. There is no "duplication" problem since this code won't run twice
121
+ var xPos = $('div.eL-captcha > div.eL-where2go').offset().left - 5;
122
+ var yPos = $('div.eL-captcha > div.eL-where2go').offset().top;
123
+ var wDim = $('div.eL-captcha > div.eL-where2go').width();
124
+ var hDim = $('div.eL-captcha > div.eL-where2go').height();
125
+ var iwDim = $(this).width();
126
+ var ihDim = $(this).height();
127
+
128
+ // If it was dragged already to the droppable zone, move it back to the beginning
129
+ if ($(this).css('position') == 'absolute') {
130
+ if ( ! $('#' + window.vCVals.n).length ) {
131
+ return false;
132
+ }
133
+ if ( $('#' + window.vCVals.n).val() == $(this).data('value') ) {
134
+ $('#' + window.vCVals.n).remove();
135
+ }
136
+
137
+ $(this).css({
138
+ 'position': 'relative',
139
+ 'left': 'auto',
140
+ 'top': 'auto'
141
+ });
142
+ } else {
143
+ if ( $('#' + window.vCVals.n).length ) {
144
+ return false;
145
+ }
146
+ var validElement = '<input type="hidden" name="' + window.vCVals.n + '" id="' + window.vCVals.n + '" readonly="readonly" value="' + $(this).data('value') + '">';
147
+ $('#' + window.vCVals.f).append(validElement);
148
+
149
+ // Calculate the middle of hte
150
+ var xPos2Go = Math.round(xPos + (wDim/2) - (iwDim/2));
151
+ var yPos2Go = Math.round(yPos + (hDim/2) - (ihDim/2));
152
+
153
+ $(this).css({
154
+ 'position': 'absolute',
155
+ 'left': xPos2Go,
156
+ 'top': yPos2Go
157
+ });
158
+ }
159
+ });
160
+ }
161
+ });
@@ -0,0 +1,128 @@
1
+ /**
2
+ * visualCaptchaHTML class by emotionLoop - 2013.03.28
3
+ *
4
+ * This file handles the CSS for the main wCaptcha class.
5
+ *
6
+ * This license applies to this file and others without reference to any other license.
7
+ *
8
+ * @author emotionLoop | http://emotionloop.com
9
+ * @link http://visualcaptcha.net
10
+ * @package visualCaptcha
11
+ * @license GNU GPL v3
12
+ * @version 4.0.3
13
+ */
14
+ div.eL-captcha.type-1 {
15
+ margin: 10px 0 10px 10px;
16
+ padding: 0;
17
+ display: block;
18
+ width: 200px;
19
+ }
20
+ div.eL-captcha > div.eL-possibilities.type-1 {
21
+ margin: 0;
22
+ padding: 14px 0 0 0;
23
+ display: block;
24
+ width: 100px;
25
+ float: left;
26
+ height: 46px;
27
+ }
28
+ div.eL-captcha > div.eL-possibilities.type-1 > img {
29
+ padding: 0 4px 4px 4px !important;
30
+ }
31
+ div.eL-captcha > div.eL-where2go.type-1 {
32
+ margin: 0 !important;
33
+ }
34
+
35
+ div.eL-captcha.type-0 {
36
+ margin: 0 0 10px 0;
37
+ padding: 0;
38
+ display: block;
39
+ width: 320px;
40
+ }
41
+ div.eL-captcha > div.eL-possibilities.type-0 {
42
+ margin: 0;
43
+ padding: 34px 0 0 0;
44
+ display: block;
45
+ width: 200px;
46
+ float: left;
47
+ height: 66px;
48
+ }
49
+
50
+ div.eL-captcha > div.eL-possibilities > img {
51
+ width: 32px;
52
+ height: 32px;
53
+ display: block;
54
+ float: left;
55
+ margin: 0;
56
+ padding: 0 4px;
57
+ z-index: 5;
58
+ }
59
+ div.eL-captcha > div.eL-where2go {
60
+ margin: 0 0 0 20px;
61
+ padding: 0;
62
+ display: block;
63
+ width: 100px;
64
+ background: transparent url('/assets/dropzone.png') center center no-repeat;
65
+ float: left;
66
+ height: 100px;
67
+ }
68
+ div.eL-captcha > div.eL-where2go.retina {
69
+ background-image: url('/assets/dropzone@2x.png');
70
+ background-size: 90px 90px;
71
+ }
72
+ div.eL-captcha > p.eL-accessibility {
73
+ font-size: 10px;
74
+ text-align: right;
75
+ display: block;
76
+ float: right;
77
+ clear: both;
78
+ }
79
+ div.eL-captcha > p.eL-accessibility img {
80
+ width: 16px;
81
+ height: 16px;
82
+ }
83
+ div.eL-captcha > div.eL-accessibility {
84
+ font-size: 12px;
85
+ text-align: left;
86
+ display: none;
87
+ clear: left;
88
+ float: left;
89
+ margin-bottom: 10px;
90
+ width: 300px;
91
+ overflow: auto;
92
+ }
93
+ div.eL-captcha > div.eL-accessibility.type-1 {
94
+ width: 180px;
95
+ }
96
+ div.eL-captcha > div.eL-accessibility > p {
97
+ width: 100%;
98
+ }
99
+ div.eL-captcha > div.eL-accessibility > input {
100
+ display: block;
101
+ padding: 5px;
102
+ width: 90%;
103
+ margin: 10px 0;
104
+ font-size: 1em;
105
+ border: 1px solid #CCC;
106
+ color: #333;
107
+ }
108
+ div.eL-captcha > div.eL-accessibility > audio {
109
+ visibility: hidden;
110
+ clear: both;
111
+ }
112
+
113
+ div.eL-captcha .clearfix,
114
+ div.eL-captcha.clearfix {
115
+ zoom: 1;
116
+ }
117
+ div.eL-captcha .clearfix:before,
118
+ div.eL-captcha .clearfix:after,
119
+ div.eL-captcha.clearfix:before,
120
+ div.eL-captcha.clearfix:after {
121
+ display: table;
122
+ line-height: 0;
123
+ content: "";
124
+ }
125
+ div.eL-captcha .clearfix:after,
126
+ div.eL-captcha.clearfix:after {
127
+ clear: both;
128
+ }
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: visualcaptcha
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Trevor Kimenye
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jquery-ui-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: A captcha that uses images instead of garbled text
42
+ email:
43
+ - trevor@sprout.co.ke
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/generators/templates/partial.erb
49
+ - lib/generators/visual_captcha_generator.rb
50
+ - lib/visualcaptcha/controller.rb
51
+ - lib/visualcaptcha/engine.rb
52
+ - lib/visualcaptcha/utils.rb
53
+ - lib/visualcaptcha/version.rb
54
+ - lib/visualcaptcha/view.rb
55
+ - lib/visualcaptcha.rb
56
+ - vendor/assets/images/accessibility.png
57
+ - vendor/assets/images/accessibility@2x.png
58
+ - vendor/assets/images/airplane.png
59
+ - vendor/assets/images/airplane@2x.png
60
+ - vendor/assets/images/balloons.png
61
+ - vendor/assets/images/balloons@2x.png
62
+ - vendor/assets/images/camera.png
63
+ - vendor/assets/images/camera@2x.png
64
+ - vendor/assets/images/car.png
65
+ - vendor/assets/images/car@2x.png
66
+ - vendor/assets/images/cat.png
67
+ - vendor/assets/images/cat@2x.png
68
+ - vendor/assets/images/chair.png
69
+ - vendor/assets/images/chair@2x.png
70
+ - vendor/assets/images/clip.png
71
+ - vendor/assets/images/clip@2x.png
72
+ - vendor/assets/images/clock.png
73
+ - vendor/assets/images/clock@2x.png
74
+ - vendor/assets/images/cloud.png
75
+ - vendor/assets/images/cloud@2x.png
76
+ - vendor/assets/images/computer.png
77
+ - vendor/assets/images/computer@2x.png
78
+ - vendor/assets/images/dropzone-edit.png
79
+ - vendor/assets/images/dropzone.png
80
+ - vendor/assets/images/dropzone@2x-edit.png
81
+ - vendor/assets/images/dropzone@2x.png
82
+ - vendor/assets/images/envelope.png
83
+ - vendor/assets/images/envelope@2x.png
84
+ - vendor/assets/images/eye.png
85
+ - vendor/assets/images/eye@2x.png
86
+ - vendor/assets/images/flag.png
87
+ - vendor/assets/images/flag@2x.png
88
+ - vendor/assets/images/folder.png
89
+ - vendor/assets/images/folder@2x.png
90
+ - vendor/assets/images/foot.png
91
+ - vendor/assets/images/foot@2x.png
92
+ - vendor/assets/images/graph.png
93
+ - vendor/assets/images/graph@2x.png
94
+ - vendor/assets/images/house.png
95
+ - vendor/assets/images/house@2x.png
96
+ - vendor/assets/images/key.png
97
+ - vendor/assets/images/key@2x.png
98
+ - vendor/assets/images/lamp.png
99
+ - vendor/assets/images/lamp@2x.png
100
+ - vendor/assets/images/leaf.png
101
+ - vendor/assets/images/leaf@2x.png
102
+ - vendor/assets/images/lock.png
103
+ - vendor/assets/images/lock@2x.png
104
+ - vendor/assets/images/magnifying-glass.png
105
+ - vendor/assets/images/magnifying-glass@2x.png
106
+ - vendor/assets/images/man.png
107
+ - vendor/assets/images/man@2x.png
108
+ - vendor/assets/images/music-note.png
109
+ - vendor/assets/images/music-note@2x.png
110
+ - vendor/assets/images/pants.png
111
+ - vendor/assets/images/pants@2x.png
112
+ - vendor/assets/images/pencil.png
113
+ - vendor/assets/images/pencil@2x.png
114
+ - vendor/assets/images/printer.png
115
+ - vendor/assets/images/printer@2x.png
116
+ - vendor/assets/images/robot.png
117
+ - vendor/assets/images/robot@2x.png
118
+ - vendor/assets/images/scissors.png
119
+ - vendor/assets/images/scissors@2x.png
120
+ - vendor/assets/images/sunglasses.png
121
+ - vendor/assets/images/sunglasses@2x.png
122
+ - vendor/assets/images/tag.png
123
+ - vendor/assets/images/tag@2x.png
124
+ - vendor/assets/images/tree.png
125
+ - vendor/assets/images/tree@2x.png
126
+ - vendor/assets/images/truck.png
127
+ - vendor/assets/images/truck@2x.png
128
+ - vendor/assets/images/tshirt.png
129
+ - vendor/assets/images/tshirt@2x.png
130
+ - vendor/assets/images/umbrella.png
131
+ - vendor/assets/images/umbrella@2x.png
132
+ - vendor/assets/images/woman.png
133
+ - vendor/assets/images/woman@2x.png
134
+ - vendor/assets/images/world.png
135
+ - vendor/assets/images/world@2x.png
136
+ - vendor/assets/javascripts/visualcaptcha.js
137
+ - vendor/assets/stylesheets/visualcaptcha.css
138
+ - LICENSE.txt
139
+ - README.md
140
+ homepage: https://github.com/kimenye/visualcaptcha
141
+ licenses: []
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ! '>='
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.0.3
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: A captcha that uses images instead of garbled text
163
+ test_files: []