annyang-rails 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ README.md
2
+ Rakefile
3
+ app/helpers/annyang_helper.rb
4
+ init.rb
5
+ lib/annyang-rails.rb
6
+ lib/annyang-rails/version.rb
7
+ vendor/assets/javascripts/annyang.js
8
+ vendor/assets/javascripts/annyang.min.js
9
+ Manifest
@@ -0,0 +1,92 @@
1
+ # annyang for Rails Asset Pipeline
2
+
3
+ [annyang](https://github.com/TalAter/annyang) is a tiny javascript SpeechRecognition library that lets your users control your site with voice commands. ([documentation](https://www.talater.com/annyang/)).
4
+
5
+ This gem makes it easy to use it with Rails Asset Pipeline.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem "annyang-rails"
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ ## Usage
18
+
19
+ Add the following to your `app/assets/javascripts/application.js`:
20
+
21
+ //= require annyang
22
+
23
+ To use minified version use this:
24
+
25
+ //= require annyang.min
26
+
27
+ We have created a helper function to make it easy.
28
+
29
+ init_annyang
30
+
31
+ If you want to use voice navigation in complete application then call helper function in application layout or if you want to use voice navigation in some specific pages then call helper function in your specific views.
32
+
33
+ <%= init_annyang %>
34
+
35
+ This helper will generate javascript which will redirect you to specified link for that keyword. You have to speak in microphone with prefix `go to <keyword>` and system will redirect to link which is associated with that keyword.
36
+
37
+ We have 3 different ways to define voice navigation commands:
38
+
39
+ 1 - YAML File
40
+ 2 - Function Parameters
41
+ 3 - HTML Attribute
42
+
43
+ #### 1 - YAML File
44
+
45
+ You can create file annyang.yml in config directory (config/annyang.yml) where you can define keywords and there links:
46
+
47
+ "ruby": "https://www.ruby-lang.org"
48
+ "rubygems": "http://rubygems.org"
49
+
50
+ You can also define options for keywords like if you want to open same link for rubygem and rubygems then you can write it OR (|) operator:
51
+
52
+ "rubygem|rubygems": "http://rubygems.org"
53
+
54
+ In case `rubygem|rubygems` both voice commands `go to rubygem` and `go to rubygems` will take you to `http://rubygems.org`
55
+
56
+ #### 2 - Function Parameters
57
+
58
+ You can pass keywords in helper function's parameters:
59
+
60
+ <%= init_annyang({"ruby" => "https://www.ruby-lang.org", "rubygem|rubygems" => "http://rubygems.org"}) %>
61
+
62
+ #### 3 - HTML Attribute
63
+
64
+ You can specify your keywords in HTML tags with `data-annyang` attribute name.
65
+ You have to specify keyword in `data-annyang` attribute in anchor tag and when someone will speak specified word then system will open href link.
66
+
67
+ <a href="https://www.ruby-lang.org" data-annyang="ruby">Ruby</a>
68
+ <a href="http://rubygems.org" data-annyang="rubygem|rubygems">Ruby Gems</a>
69
+
70
+
71
+
72
+ If you want to use this by your own then try it like this:
73
+
74
+ ````html
75
+ <script>
76
+ if (annyang) {
77
+ // Let's define a command.
78
+ var commands = {
79
+ 'show tps report': function() { $('#tpsreport').show(); }
80
+ };
81
+
82
+ // Initialize annyang with our commands
83
+ annyang.init(commands);
84
+
85
+ // Start listening.
86
+ annyang.start();
87
+ }
88
+ </script>
89
+
90
+ ````
91
+
92
+ **For more details, [visit the demo and docs site](https://www.talater.com/annyang).**
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('annyang-rails', '0.2.0') do |p|
6
+ p.description = "A tiny javascript SpeechRecognition library that lets your users control your site with voice commands."
7
+ p.url = "http://github.com/confiz/annyang-rails"
8
+ p.author = "Confiz Limited"
9
+ p.email = "opensource@confiz.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "annyang-rails"
5
+ s.version = "0.2.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Confiz Limited"]
9
+ s.date = "2013-12-09"
10
+ s.description = "A tiny javascript SpeechRecognition library that lets your users control your site with voice commands."
11
+ s.email = "opensource@confiz.com"
12
+ s.extra_rdoc_files = ["README.md", "lib/annyang-rails.rb", "lib/annyang-rails/version.rb"]
13
+ s.files = ["README.md", "Rakefile", "app/helpers/annyang_helper.rb", "init.rb", "lib/annyang-rails.rb", "lib/annyang-rails/version.rb", "vendor/assets/javascripts/annyang.js", "vendor/assets/javascripts/annyang.min.js", "Manifest", "annyang-rails.gemspec"]
14
+ s.homepage = "http://github.com/confiz/annyang-rails"
15
+ s.rdoc_options = ["--line-numbers", "--title", "Annyang-rails", "--main", "README.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = "annyang-rails"
18
+ s.rubygems_version = "1.8.24"
19
+ s.summary = "A tiny javascript SpeechRecognition library that lets your users control your site with voice commands."
20
+
21
+ if s.respond_to? :specification_version then
22
+ s.specification_version = 3
23
+
24
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
+ else
26
+ end
27
+ else
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ module AnnyangHelper
2
+ def init_annyang(commands = {})
3
+ commands = commands.merge(get_annyang_commands)
4
+ javascript_tag do
5
+ raw("var annyang_commands={};
6
+ var linkAnnyang = function(term){
7
+ if(annyang_commands[term]){
8
+ window.location = annyang_commands[term];
9
+ }
10
+ }
11
+ function initAnnyang(){
12
+ if (annyang) {
13
+ annyang_commands = {#{commands.collect{|k,v| k.split('|').collect {|key| "'#{key}': '#{v}'"} }.join(', ')}};
14
+ if($('a[data-annyang]').length > 0){
15
+ $('a[data-annyang]').each(function( index ) {
16
+ var link = $(this).attr('href');
17
+ var split_arr = $(this).attr('data-annyang').split('|');
18
+ for (var i=0; i < split_arr.length; i++)
19
+ annyang_commands[split_arr[i]] = link;
20
+ });
21
+ }
22
+ annyang.init({'go to *term': linkAnnyang});
23
+ annyang.start();
24
+ }
25
+ }
26
+ $(document).ready(initAnnyang);")
27
+ end
28
+ end
29
+ def get_annyang_commands
30
+ yml_path = File.join(Rails.root,"config/annyang.yml")
31
+ commands_hash = YAML.load_file(yml_path) if yml_path && File.exist?(yml_path)
32
+ commands_hash||{}
33
+ end
34
+ end
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'annyang'
2
+ ActionController::Base.helper AnnyangHelper
3
+
@@ -0,0 +1,8 @@
1
+ require "annyang-rails/version"
2
+
3
+ module Annyang
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Annyang
2
+ module Rails
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
@@ -0,0 +1,229 @@
1
+ //! annyang
2
+ //! version : 0.2.0
3
+ //! author : Tal Ater @TalAter
4
+ //! license : MIT
5
+ //! https://www.TalAter.com/annyang/
6
+ (function () {
7
+ "use strict";
8
+
9
+ // Save a reference to the global object (window in the browser)
10
+ var root = this;
11
+
12
+ // Get the SpeechRecognition object, while handling browser prefixes
13
+ var SpeechRecognition = root.webkitSpeechRecognition ||
14
+ root.mozSpeechRecognition ||
15
+ root.msSpeechRecognition ||
16
+ root.oSpeechRecognition ||
17
+ root.SpeechRecognition;
18
+
19
+ // Check browser support
20
+ // This is done as early as possible, to make it as fast as possible for unsupported browsers
21
+ if ( !SpeechRecognition ) {
22
+ root.annyang = null;
23
+ return null;
24
+ }
25
+
26
+ var commandsList;
27
+ var recognition;
28
+ var lang = 'en-US';
29
+ var callbacks = { start: [], error: [], end: [], result: [], resultMatch: [], resultNoMatch: [], errorNetwork: [], errorPermissionBlocked: [], errorPermissionDenied: [] };
30
+ var autoRestart;
31
+ var lastStartedAt = 0;
32
+ var debugState = false;
33
+ var debugStyle = 'font-weight: bold; color: #00f;';
34
+
35
+ // The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license.
36
+ var optionalParam = /\s*\((.*?)\)\s*/g;
37
+ var optionalRegex = /(\(\?:[^)]+\))\?/g;
38
+ var namedParam = /(\(\?)?:\w+/g;
39
+ var splatParam = /\*\w+/g;
40
+ var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#]/g;
41
+ var commandToRegExp = function(command) {
42
+ command = command.replace(escapeRegExp, '\\$&')
43
+ .replace(optionalParam, '(?:$1)?')
44
+ .replace(namedParam, function(match, optional) {
45
+ return optional ? match : '([^\\s]+)';
46
+ })
47
+ .replace(splatParam, '(.*?)')
48
+ .replace(optionalRegex, '\\s*$1?\\s*');
49
+ return new RegExp('^' + command + '$', 'i');
50
+ };
51
+
52
+ // This method receives an array of callbacks to iterate over, and invokes each of them
53
+ var invokeCallbacks = function(callbacks) {
54
+ for (var j = 0, l = callbacks.length; j < l; j++) {
55
+ callbacks[j].callback.apply(callbacks[j].context);
56
+ }
57
+ };
58
+
59
+ root.annyang = {
60
+ // Initialize annyang with a list of commands to recognize.
61
+ // e.g. annyang.init({'hello :name': helloFunction})
62
+ // annyang understands commands with named variables, splats, and optional words.
63
+ init: function(commands) {
64
+
65
+ // Abort previous instances of recognition already running
66
+ if (recognition && recognition.abort) {
67
+ recognition.abort();
68
+ }
69
+
70
+ // initiate SpeechRecognition
71
+ recognition = new SpeechRecognition();
72
+
73
+ // Set the max number of alternative transcripts to try and match with a command
74
+ recognition.maxAlternatives = 5;
75
+ recognition.continuous = true;
76
+ // Sets the language to the default 'en-US'. This can be changed with annyang.setLanguage()
77
+ recognition.lang = lang;
78
+
79
+ recognition.onstart = function() { invokeCallbacks(callbacks.start); };
80
+
81
+ recognition.onerror = function(event) {
82
+ invokeCallbacks(callbacks.error);
83
+ switch (event.error) {
84
+ case 'network':
85
+ invokeCallbacks(callbacks.errorNetwork);
86
+ break;
87
+ case 'not-allowed':
88
+ case 'service-not-allowed':
89
+ // if permission to use the mic is denied, turn off auto-restart
90
+ autoRestart = false;
91
+ // determine if permission was denied by user or automatically.
92
+ if (new Date().getTime()-lastStartedAt < 200) {
93
+ invokeCallbacks(callbacks.errorPermissionBlocked);
94
+ } else {
95
+ invokeCallbacks(callbacks.errorPermissionDenied);
96
+ }
97
+ break;
98
+ }
99
+ };
100
+
101
+ recognition.onend = function() {
102
+ invokeCallbacks(callbacks.end);
103
+ // annyang will auto restart if it is closed automatically and not by user action.
104
+ if (autoRestart) {
105
+ // play nicely with the browser, and never restart annyang automatically more than once per second
106
+ var timeSinceLastStart = new Date().getTime()-lastStartedAt;
107
+ if (timeSinceLastStart < 1000) {
108
+ setTimeout(root.annyang.start, 1000-timeSinceLastStart);
109
+ } else {
110
+ root.annyang.start();
111
+ }
112
+ }
113
+ };
114
+
115
+ recognition.onresult = function(event) {
116
+ invokeCallbacks(callbacks.result);
117
+ var results = event.results[event.resultIndex];
118
+ var commandText;
119
+ // go over each of the 5 results and alternative results received (we've set maxAlternatives to 5 above)
120
+ for (var i = 0; i<results.length; i++) {
121
+ // the text recognized
122
+ commandText = results[i].transcript.trim();
123
+ if (debugState) {
124
+ root.console.log('Speech recognized: %c'+commandText, debugStyle);
125
+ }
126
+
127
+ // try and match recognized text to one of the commands on the list
128
+ for (var j = 0, l = commandsList.length; j < l; j++) {
129
+ var result = commandsList[j].command.exec(commandText);
130
+ if (result) {
131
+ var parameters = result.slice(1);
132
+ if (debugState) {
133
+ root.console.log('command matched: %c'+commandsList[j].originalPhrase, debugStyle);
134
+ if (parameters.length) {
135
+ root.console.log('with parameters', parameters);
136
+ }
137
+ }
138
+ // execute the matched command
139
+ commandsList[j].callback.apply(this, parameters);
140
+ invokeCallbacks(callbacks.resultMatch);
141
+ return true;
142
+ }
143
+ }
144
+ }
145
+ invokeCallbacks(callbacks.resultNoMatch);
146
+ return false;
147
+ };
148
+
149
+ // build commands list
150
+ commandsList = [];
151
+ this.addCommands(commands);
152
+ },
153
+
154
+ // Start listening (asking for permission first, if needed).
155
+ // Call this after you've initialized annyang with commands.
156
+ // Receives an optional options object:
157
+ // { autoRestart: true }
158
+ start: function(options) {
159
+ options = options || {};
160
+ if (options.autoRestart !== void 0) {
161
+ autoRestart = !!options.autoRestart;
162
+ } else {
163
+ autoRestart = true;
164
+ }
165
+ lastStartedAt = new Date().getTime();
166
+ recognition.start();
167
+ },
168
+
169
+ // abort the listening session (aka stop)
170
+ abort: function() {
171
+ autoRestart = false;
172
+ recognition.abort();
173
+ },
174
+
175
+ // Turn on output of debug messages to the console. Ugly, but super-handy!
176
+ debug: function(newState) {
177
+ if (arguments.length > 0) {
178
+ debugState = !!newState;
179
+ } else {
180
+ debugState = true;
181
+ }
182
+ },
183
+
184
+ // Set the language the user will speak in. If not called, defaults to 'en-US'.
185
+ // e.g. 'fr-FR' (French-France), 'es-CR' (Español-Costa Rica)
186
+ setLanguage: function(language) {
187
+ lang = language;
188
+ if (recognition && recognition.abort) {
189
+ recognition.lang = language;
190
+ }
191
+ },
192
+
193
+ // Add additional commands that annyang will respond to. Similar in syntax to annyang.init()
194
+ addCommands: function(commands) {
195
+ var cb,
196
+ command;
197
+ for (var phrase in commands) {
198
+ if (commands.hasOwnProperty(phrase)) {
199
+ cb = root[commands[phrase]] || commands[phrase];
200
+ if (typeof cb !== 'function') {
201
+ continue;
202
+ }
203
+ //convert command to regex
204
+ command = commandToRegExp(phrase);
205
+
206
+ commandsList.push({ command: command, callback: cb, originalPhrase: phrase });
207
+ }
208
+ }
209
+ if (debugState) {
210
+ root.console.log('Commands successfully loaded: %c'+commandsList.length, debugStyle);
211
+ }
212
+ },
213
+
214
+ // Lets the user add a callback of one of 9 types:
215
+ // start, error, end, result, resultMatch, resultNoMatch, errorNetwork, errorPermissionBlocked, errorPermissionDenied
216
+ // Can also optionally receive a context for the callback function as the third argument
217
+ addCallback: function(type, callback, context) {
218
+ if (callbacks[type] === void 0) {
219
+ return;
220
+ }
221
+ var cb = root[callback] || callback;
222
+ if (typeof cb !== 'function') {
223
+ return;
224
+ }
225
+ callbacks[type].push({callback: cb, context: context || this});
226
+ }
227
+ };
228
+
229
+ }).call(this);
@@ -0,0 +1,6 @@
1
+ //! annyang
2
+ //! version : 0.2.0
3
+ //! author : Tal Ater @TalAter
4
+ //! license : MIT
5
+ //! https://www.TalAter.com/annyang/
6
+ (function(){"use strict";var a=this,b=a.webkitSpeechRecognition||a.mozSpeechRecognition||a.msSpeechRecognition||a.oSpeechRecognition||a.SpeechRecognition;if(!b)return a.annyang=null,null;var c,d,e,f="en-US",g={start:[],error:[],end:[],result:[],resultMatch:[],resultNoMatch:[],errorNetwork:[],errorPermissionBlocked:[],errorPermissionDenied:[]},h=0,i=!1,j="font-weight: bold; color: #00f;",k=/\s*\((.*?)\)\s*/g,l=/(\(\?:[^)]+\))\?/g,m=/(\(\?)?:\w+/g,n=/\*\w+/g,o=/[\-{}\[\]+?.,\\\^$|#]/g,p=function(a){return a=a.replace(o,"\\$&").replace(k,"(?:$1)?").replace(m,function(a,b){return b?a:"([^\\s]+)"}).replace(n,"(.*?)").replace(l,"\\s*$1?\\s*"),new RegExp("^"+a+"$","i")},q=function(a){for(var b=0,c=a.length;c>b;b++)a[b].callback.apply(a[b].context)};a.annyang={init:function(k){d&&d.abort&&d.abort(),d=new b,d.maxAlternatives=5,d.continuous=!0,d.lang=f,d.onstart=function(){q(g.start)},d.onerror=function(a){switch(q(g.error),a.error){case"network":q(g.errorNetwork);break;case"not-allowed":case"service-not-allowed":e=!1,(new Date).getTime()-h<200?q(g.errorPermissionBlocked):q(g.errorPermissionDenied)}},d.onend=function(){if(q(g.end),e){var b=(new Date).getTime()-h;1e3>b?setTimeout(a.annyang.start,1e3-b):a.annyang.start()}},d.onresult=function(b){q(g.result);for(var d,e=b.results[b.resultIndex],f=0;f<e.length;f++){d=e[f].transcript.trim(),i&&a.console.log("Speech recognized: %c"+d,j);for(var h=0,k=c.length;k>h;h++){var l=c[h].command.exec(d);if(l){var m=l.slice(1);return i&&(a.console.log("command matched: %c"+c[h].originalPhrase,j),m.length&&a.console.log("with parameters",m)),c[h].callback.apply(this,m),q(g.resultMatch),!0}}}return q(g.resultNoMatch),!1},c=[],this.addCommands(k)},start:function(a){a=a||{},e=void 0!==a.autoRestart?!!a.autoRestart:!0,h=(new Date).getTime(),d.start()},abort:function(){e=!1,d.abort()},debug:function(a){i=arguments.length>0?!!a:!0},setLanguage:function(a){f=a,d&&d.abort&&(d.lang=a)},addCommands:function(b){var d,e;for(var f in b)if(b.hasOwnProperty(f)){if(d=a[b[f]]||b[f],"function"!=typeof d)continue;e=p(f),c.push({command:e,callback:d,originalPhrase:f})}i&&a.console.log("Commands successfully loaded: %c"+c.length,j)},addCallback:function(b,c,d){if(void 0!==g[b]){var e=a[c]||c;"function"==typeof e&&g[b].push({callback:e,context:d||this})}}}}).call(this);
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: annyang-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Confiz Limited
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-09 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A tiny javascript SpeechRecognition library that lets your users control
15
+ your site with voice commands.
16
+ email: opensource@confiz.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files:
20
+ - README.md
21
+ - lib/annyang-rails.rb
22
+ - lib/annyang-rails/version.rb
23
+ files:
24
+ - README.md
25
+ - Rakefile
26
+ - app/helpers/annyang_helper.rb
27
+ - init.rb
28
+ - lib/annyang-rails.rb
29
+ - lib/annyang-rails/version.rb
30
+ - vendor/assets/javascripts/annyang.js
31
+ - vendor/assets/javascripts/annyang.min.js
32
+ - Manifest
33
+ - annyang-rails.gemspec
34
+ homepage: http://github.com/confiz/annyang-rails
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --line-numbers
39
+ - --title
40
+ - Annyang-rails
41
+ - --main
42
+ - README.md
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '1.2'
57
+ requirements: []
58
+ rubyforge_project: annyang-rails
59
+ rubygems_version: 1.8.24
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: A tiny javascript SpeechRecognition library that lets your users control
63
+ your site with voice commands.
64
+ test_files: []