smartvoice.bundle.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /*
  2. * VOICE COMMAND CONFIG
  3. * dependency: js/speech/voicecommand.js
  4. */
  5. voice_command = true,
  6. /*
  7. * Turns on speech as soon as the page is loaded
  8. */
  9. voice_command_auto = false,
  10. /*
  11. * Sets the language to the default 'en-US'. (supports over 50 languages
  12. * by google)
  13. *
  14. * Afrikaans ['af-ZA']
  15. * Bahasa Indonesia ['id-ID']
  16. * Bahasa Melayu ['ms-MY']
  17. * Català ['ca-ES']
  18. * Čeština ['cs-CZ']
  19. * Deutsch ['de-DE']
  20. * English ['en-AU', 'Australia']
  21. * ['en-CA', 'Canada']
  22. * ['en-IN', 'India']
  23. * ['en-NZ', 'New Zealand']
  24. * ['en-ZA', 'South Africa']
  25. * ['en-GB', 'United Kingdom']
  26. * ['en-US', 'United States']
  27. * Español ['es-AR', 'Argentina']
  28. * ['es-BO', 'Bolivia']
  29. * ['es-CL', 'Chile']
  30. * ['es-CO', 'Colombia']
  31. * ['es-CR', 'Costa Rica']
  32. * ['es-EC', 'Ecuador']
  33. * ['es-SV', 'El Salvador']
  34. * ['es-ES', 'España']
  35. * ['es-US', 'Estados Unidos']
  36. * ['es-GT', 'Guatemala']
  37. * ['es-HN', 'Honduras']
  38. * ['es-MX', 'México']
  39. * ['es-NI', 'Nicaragua']
  40. * ['es-PA', 'Panamá']
  41. * ['es-PY', 'Paraguay']
  42. * ['es-PE', 'Perú']
  43. * ['es-PR', 'Puerto Rico']
  44. * ['es-DO', 'República Dominicana']
  45. * ['es-UY', 'Uruguay']
  46. * ['es-VE', 'Venezuela']
  47. * Euskara ['eu-ES']
  48. * Français ['fr-FR']
  49. * Galego ['gl-ES']
  50. * Hrvatski ['hr_HR']
  51. * IsiZulu ['zu-ZA']
  52. * Íslenska ['is-IS']
  53. * Italiano ['it-IT', 'Italia']
  54. * ['it-CH', 'Svizzera']
  55. * Magyar ['hu-HU']
  56. * Nederlands ['nl-NL']
  57. * Norsk bokmål ['nb-NO']
  58. * Polski ['pl-PL']
  59. * Português ['pt-BR', 'Brasil']
  60. * ['pt-PT', 'Portugal']
  61. * Română ['ro-RO']
  62. * Slovenčina ['sk-SK']
  63. * Suomi ['fi-FI']
  64. * Svenska ['sv-SE']
  65. * Türkçe ['tr-TR']
  66. * български ['bg-BG']
  67. * Pусский ['ru-RU']
  68. * Српски ['sr-RS']
  69. * 한국어 ['ko-KR']
  70. * 中文 ['cmn-Hans-CN', '普通话 (中国大陆)']
  71. * ['cmn-Hans-HK', '普通话 (香港)']
  72. * ['cmn-Hant-TW', '中文 (台灣)']
  73. * ['yue-Hant-HK', '粵語 (香港)']
  74. * 日本語 ['ja-JP']
  75. * Lingua latīna ['la']
  76. */
  77. voice_command_lang = 'en-US',
  78. /*
  79. * Use localstorage to remember on/off (best used with HTML Version
  80. * when going from one page to the next)
  81. */
  82. voice_localStorage = false;
  83. /*
  84. * Voice Commands
  85. * Defines voice command variables and functions
  86. */
  87. if (voice_command) {
  88. var commands = {
  89. 'show dashboard' : function() { $('nav a[href="ajax/dashboard.html"]').trigger("click"); },
  90. 'show inbox' : function() { $('nav a[href="ajax/inbox.html"]').trigger("click"); },
  91. 'show graphs' : function() { $('nav a[href="ajax/flot.html"]').trigger("click"); },
  92. 'show flotchart' : function() { $('nav a[href="ajax/flot.html"]').trigger("click"); },
  93. 'show morris chart' : function() { $('nav a[href="ajax/morris.html"]').trigger("click"); },
  94. 'show inline chart' : function() { $('nav a[href="ajax/inline-charts.html"]').trigger("click"); },
  95. 'show dygraphs' : function() { $('nav a[href="ajax/dygraphs.html"]').trigger("click"); },
  96. 'show tables' : function() { $('nav a[href="ajax/table.html"]').trigger("click"); },
  97. 'show data table' : function() { $('nav a[href="ajax/datatables.html"]').trigger("click"); },
  98. 'show jquery grid' : function() { $('nav a[href="ajax/jqgrid.html"]').trigger("click"); },
  99. 'show form' : function() { $('nav a[href="ajax/form-elements.html"]').trigger("click"); },
  100. 'show form layouts' : function() { $('nav a[href="ajax/form-templates.html"]').trigger("click"); },
  101. 'show form validation' : function() { $('nav a[href="ajax/validation.html"]').trigger("click"); },
  102. 'show form elements' : function() { $('nav a[href="ajax/bootstrap-forms.html"]').trigger("click"); },
  103. 'show form plugins' : function() { $('nav a[href="ajax/plugins.html"]').trigger("click"); },
  104. 'show form wizards' : function() { $('nav a[href="ajax/wizards.html"]').trigger("click"); },
  105. 'show bootstrap editor' : function() { $('nav a[href="ajax/other-editors.html"]').trigger("click"); },
  106. 'show dropzone' : function() { $('nav a[href="ajax/dropzone.html"]').trigger("click"); },
  107. 'show image cropping' : function() { $('nav a[href="ajax/image-editor.html"]').trigger("click"); },
  108. 'show general elements' : function() { $('nav a[href="ajax/general-elements.html"]').trigger("click"); },
  109. 'show buttons' : function() { $('nav a[href="ajax/buttons.html"]').trigger("click"); },
  110. 'show fontawesome' : function() { $('nav a[href="ajax/fa.html"]').trigger("click"); },
  111. 'show glyph icons' : function() { $('nav a[href="ajax/glyph.html"]').trigger("click"); },
  112. 'show flags' : function() { $('nav a[href="ajax/flags.html"]').trigger("click"); },
  113. 'show grid' : function() { $('nav a[href="ajax/grid.html"]').trigger("click"); },
  114. 'show tree view' : function() { $('nav a[href="ajax/treeview.html"]').trigger("click"); },
  115. 'show nestable lists' : function() { $('nav a[href="ajax/nestable-list.html"]').trigger("click"); },
  116. 'show jquery U I' : function() { $('nav a[href="ajax/jqui.html"]').trigger("click"); },
  117. 'show typography' : function() { $('nav a[href="ajax/typography.html"]').trigger("click"); },
  118. 'show calendar' : function() { $('nav a[href="ajax/calendar.html"]').trigger("click"); },
  119. 'show widgets' : function() { $('nav a[href="ajax/widgets.html"]').trigger("click"); },
  120. 'show gallery' : function() { $('nav a[href="ajax/gallery.html"]').trigger("click"); },
  121. 'show maps' : function() { $('nav a[href="ajax/gmap-xml.html"]').trigger("click"); },
  122. 'show pricing tables' : function() { $('nav a[href="ajax/pricing-table.html"]').trigger("click"); },
  123. 'show invoice' : function() { $('nav a[href="ajax/invoice.html"]').trigger("click"); },
  124. 'show search' : function() { $('nav a[href="ajax/search.html"]').trigger("click"); },
  125. 'go back' : function() { history.back(1); },
  126. 'scroll up' : function () { $('html, body').animate({ scrollTop: 0 }, 100); },
  127. 'scroll down' : function () { $('html, body').animate({ scrollTop: $(document).height() }, 100);},
  128. 'hide navigation' : function() {
  129. if ($.root_.hasClass("container") && !$.root_.hasClass("menu-on-top")){
  130. $('span.minifyme').trigger("click");
  131. } else {
  132. $('#hide-menu > span > a').trigger("click");
  133. }
  134. },
  135. 'show navigation' : function() {
  136. if ($.root_.hasClass("container") && !$.root_.hasClass("menu-on-top")){
  137. $('span.minifyme').trigger("click");
  138. } else {
  139. $('#hide-menu > span > a').trigger("click");
  140. }
  141. },
  142. 'mute' : function() {
  143. $.sound_on = false;
  144. $.smallBox({
  145. title : "MUTE",
  146. content : "All sounds have been muted!",
  147. color : "#a90329",
  148. timeout: 4000,
  149. icon : "fa fa-volume-off"
  150. });
  151. },
  152. 'sound on' : function() {
  153. $.sound_on = true;
  154. $.speechApp.playConfirmation();
  155. $.smallBox({
  156. title : "UNMUTE",
  157. content : "All sounds have been turned on!",
  158. color : "#40ac2b",
  159. sound_file: 'voice_alert',
  160. timeout: 5000,
  161. icon : "fa fa-volume-up"
  162. });
  163. },
  164. 'stop' : function() {
  165. smartSpeechRecognition.abort();
  166. $.root_.removeClass("voice-command-active");
  167. $.smallBox({
  168. title : "VOICE COMMAND OFF",
  169. content : "Your voice commands has been successfully turned off. Click on the <i class='fa fa-microphone fa-lg fa-fw'></i> icon to turn it back on.",
  170. color : "#40ac2b",
  171. sound_file: 'voice_off',
  172. timeout: 8000,
  173. icon : "fa fa-microphone-slash"
  174. });
  175. if ($('#speech-btn .popover').is(':visible')) {
  176. $('#speech-btn .popover').fadeOut(250);
  177. }
  178. },
  179. 'help' : function() {
  180. $('#voiceModal').removeData('modal').modal( { remote: "ajax/modal-content/modal-voicecommand.html", show: true } );
  181. if ($('#speech-btn .popover').is(':visible')) {
  182. $('#speech-btn .popover').fadeOut(250);
  183. }
  184. },
  185. 'got it' : function() {
  186. $('#voiceModal').modal('hide');
  187. },
  188. 'logout' : function() {
  189. $.speechApp.stop();
  190. window.location = $('#logout > span > a').attr("href");
  191. }
  192. };
  193. };
  194. /*
  195. * SMART VOICE
  196. * Author: MyOrange | @bootstraphunt
  197. * http://www.myorange.ca
  198. */
  199. SpeechRecognition = root.SpeechRecognition || root.webkitSpeechRecognition || root.mozSpeechRecognition || root.msSpeechRecognition || root.oSpeechRecognition;
  200. // ref: http://updates.html5rocks.com/2013/01/Voice-Driven-Web-Apps-Introduction-to-the-Web-Speech-API
  201. if (SpeechRecognition && voice_command) {
  202. // commands are pulled from app.config file
  203. // add function to button
  204. $.root_.on('click', '[data-action="voiceCommand"]', function(e) {
  205. if ($.root_.hasClass("voice-command-active")) {
  206. $.speechApp.stop();
  207. //$('#speech-btn > span > a > i').removeClass().addClass('fa fa-microphone-slash');
  208. } else {
  209. $.speechApp.start();
  210. //add popover
  211. $('#speech-btn .popover').fadeIn(350);
  212. //$('#speech-btn > span > a > i').removeClass().addClass('fa fa-microphone')
  213. }
  214. e.preventDefault();
  215. });
  216. //remove popover
  217. $(document).mouseup(function(e) {
  218. if (!$('#speech-btn .popover').is(e.target) && $('#speech-btn .popover').has(e.target).length === 0) {
  219. $('#speech-btn .popover').fadeOut(250);
  220. }
  221. });
  222. // create dynamic modal instance
  223. var modal = $('<div class="modal fade" id="voiceModal" tabindex="-1" role="dialog" aria-labelledby="remoteModalLabel" aria-hidden="true"><div class="modal-dialog"><div class="modal-content"></div></div></div>');
  224. // attach to body
  225. modal.appendTo("body");
  226. //debugState
  227. if (debugState) {
  228. root.console.log("This browser supports Voice Command");
  229. }
  230. // function
  231. $.speechApp = (function(speech) {
  232. speech.start = function() {
  233. // Add our commands to smartSpeechRecognition
  234. smartSpeechRecognition.addCommands(commands);
  235. if (smartSpeechRecognition) {
  236. // activate plugin
  237. smartSpeechRecognition.start();
  238. // add btn class
  239. $.root_.addClass("voice-command-active");
  240. // play sound
  241. $.speechApp.playON();
  242. // set localStorage when switch is on manually
  243. if (voice_localStorage) {
  244. localStorage.setItem('sm-setautovoice', 'true');
  245. }
  246. } else {
  247. // if plugin not found
  248. alert("speech plugin not loaded");
  249. }
  250. };
  251. speech.stop = function() {
  252. if (smartSpeechRecognition) {
  253. // deactivate plugin
  254. smartSpeechRecognition.abort();
  255. // remove btn class
  256. $.root_.removeClass("voice-command-active");
  257. // sound
  258. $.speechApp.playOFF();
  259. // del localStorage when switch if off manually
  260. if (voice_localStorage) {
  261. localStorage.setItem('sm-setautovoice', 'false');
  262. }
  263. // remove popover if visible
  264. if ($('#speech-btn .popover').is(':visible')) {
  265. $('#speech-btn .popover').fadeOut(250);
  266. }
  267. }
  268. };
  269. // play sound
  270. speech.playON = function() {
  271. var audioElement = document.createElement('audio');
  272. if (navigator.userAgent.match('Firefox/'))
  273. audioElement.setAttribute('src', $.sound_path + 'voice_on' + ".ogg");
  274. else
  275. audioElement.setAttribute('src', $.sound_path + 'voice_on' + ".mp3");
  276. //$.get();
  277. audioElement.addEventListener("load", function() {
  278. audioElement.play();
  279. }, true);
  280. if ($.sound_on) {
  281. audioElement.pause();
  282. audioElement.play();
  283. }
  284. };
  285. speech.playOFF = function() {
  286. var audioElement = document.createElement('audio');
  287. if (navigator.userAgent.match('Firefox/'))
  288. audioElement.setAttribute('src', $.sound_path + 'voice_off' + ".ogg");
  289. else
  290. audioElement.setAttribute('src', $.sound_path + 'voice_off' + ".mp3");
  291. $.get();
  292. audioElement.addEventListener("load", function() {
  293. audioElement.play();
  294. }, true);
  295. if ($.sound_on) {
  296. audioElement.pause();
  297. audioElement.play();
  298. }
  299. };
  300. speech.playConfirmation = function() {
  301. var audioElement = document.createElement('audio');
  302. if (navigator.userAgent.match('Firefox/'))
  303. audioElement.setAttribute('src', $.sound_path + 'voice_alert' + ".ogg");
  304. else
  305. audioElement.setAttribute('src', $.sound_path + 'voice_alert' + ".mp3");
  306. $.get();
  307. audioElement.addEventListener("load", function() {
  308. audioElement.play();
  309. }, true);
  310. if ($.sound_on) {
  311. audioElement.pause();
  312. audioElement.play();
  313. }
  314. };
  315. return speech;
  316. })({});
  317. } else {
  318. $("#speech-btn").addClass("display-none");
  319. }
  320. /*
  321. * SPEECH RECOGNITION ENGINE
  322. * Copyright (c) 2013 Tal Ater
  323. * Modified by MyOrange
  324. * All modifications made are hereby copyright (c) 2014 MyOrange
  325. */
  326. (function(undefined) {"use strict";
  327. // Check browser support
  328. // This is done as early as possible, to make it as fast as possible for unsupported browsers
  329. if (!SpeechRecognition) {
  330. root.smartSpeechRecognition = null;
  331. return undefined;
  332. }
  333. var commandsList = [], recognition, callbacks = {
  334. start : [],
  335. error : [],
  336. end : [],
  337. result : [],
  338. resultMatch : [],
  339. resultNoMatch : [],
  340. errorNetwork : [],
  341. errorPermissionBlocked : [],
  342. errorPermissionDenied : []
  343. }, autoRestart, lastStartedAt = 0,
  344. //debugState = false, // decleared in app.config.js
  345. //debugStyle = 'font-weight: bold; color: #00f;', // decleared in app.config.js
  346. // The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license.
  347. optionalParam = /\s*\((.*?)\)\s*/g, optionalRegex = /(\(\?:[^)]+\))\?/g, namedParam = /(\(\?)?:\w+/g, splatParam = /\*\w+/g, escapeRegExp = /[\-{}\[\]+?.,\\\^$|#]/g, commandToRegExp = function(command) {
  348. command = command.replace(escapeRegExp, '\\$&').replace(optionalParam, '(?:$1)?').replace(namedParam, function(match, optional) {
  349. return optional ? match : '([^\\s]+)';
  350. }).replace(splatParam, '(.*?)').replace(optionalRegex, '\\s*$1?\\s*');
  351. return new RegExp('^' + command + '$', 'i');
  352. };
  353. // This method receives an array of callbacks to iterate over, and invokes each of them
  354. var invokeCallbacks = function(callbacks) {
  355. callbacks.forEach(function(callback) {
  356. callback.callback.apply(callback.context);
  357. });
  358. };
  359. var initIfNeeded = function() {
  360. if (!isInitialized()) {
  361. root.smartSpeechRecognition.init({}, false);
  362. }
  363. };
  364. var isInitialized = function() {
  365. return recognition !== undefined;
  366. };
  367. root.smartSpeechRecognition = {
  368. // Initialize smartSpeechRecognition with a list of commands to recognize.
  369. // e.g. smartSpeechRecognition.init({'hello :name': helloFunction})
  370. // smartSpeechRecognition understands commands with named variables, splats, and optional words.
  371. init : function(commands, resetCommands) {
  372. // resetCommands defaults to true
  373. if (resetCommands === undefined) {
  374. resetCommands = true;
  375. } else {
  376. resetCommands = !!resetCommands;
  377. }
  378. // Abort previous instances of recognition already running
  379. if (recognition && recognition.abort) {
  380. recognition.abort();
  381. }
  382. // initiate SpeechRecognition
  383. recognition = new SpeechRecognition();
  384. // Set the max number of alternative transcripts to try and match with a command
  385. recognition.maxAlternatives = 5;
  386. recognition.continuous = true;
  387. // Sets the language to the default 'en-US'. This can be changed with smartSpeechRecognition.setLanguage()
  388. recognition.lang = voice_command_lang || 'en-US';
  389. recognition.onstart = function() {
  390. invokeCallbacks(callbacks.start);
  391. //debugState
  392. if (debugState) {
  393. root.console.log('%c ✔ SUCCESS: User allowed access the microphone service to start ', debugStyle_success);
  394. root.console.log('Language setting is set to: ' + recognition.lang, debugStyle);
  395. }
  396. $.root_.removeClass("service-not-allowed");
  397. $.root_.addClass("service-allowed");
  398. };
  399. recognition.onerror = function(event) {
  400. invokeCallbacks(callbacks.error);
  401. switch (event.error) {
  402. case 'network':
  403. invokeCallbacks(callbacks.errorNetwork);
  404. break;
  405. case 'not-allowed':
  406. case 'service-not-allowed':
  407. // if permission to use the mic is denied, turn off auto-restart
  408. autoRestart = false;
  409. $.root_.removeClass("service-allowed");
  410. $.root_.addClass("service-not-allowed");
  411. //debugState
  412. if (debugState) {
  413. root.console.log('%c WARNING: Microphone was not detected (either user denied access or it is not installed properly) ', debugStyle_warning);
  414. }
  415. // determine if permission was denied by user or automatically.
  416. if (new Date().getTime() - lastStartedAt < 200) {
  417. invokeCallbacks(callbacks.errorPermissionBlocked);
  418. } else {
  419. invokeCallbacks(callbacks.errorPermissionDenied);
  420. //console.log("You need your mic to be active")
  421. }
  422. break;
  423. }
  424. };
  425. recognition.onend = function() {
  426. invokeCallbacks(callbacks.end);
  427. // smartSpeechRecognition will auto restart if it is closed automatically and not by user action.
  428. if (autoRestart) {
  429. // play nicely with the browser, and never restart smartSpeechRecognition automatically more than once per second
  430. var timeSinceLastStart = new Date().getTime() - lastStartedAt;
  431. if (timeSinceLastStart < 1000) {
  432. setTimeout(root.smartSpeechRecognition.start, 1000 - timeSinceLastStart);
  433. } else {
  434. root.smartSpeechRecognition.start();
  435. }
  436. }
  437. };
  438. recognition.onresult = function(event) {
  439. invokeCallbacks(callbacks.result);
  440. var results = event.results[event.resultIndex], commandText;
  441. // go over each of the 5 results and alternative results received (we've set maxAlternatives to 5 above)
  442. for (var i = 0; i < results.length; i++) {
  443. // the text recognized
  444. commandText = results[i].transcript.trim();
  445. if (debugState) {
  446. root.console.log('Speech recognized: %c' + commandText, debugStyle);
  447. }
  448. // try and match recognized text to one of the commands on the list
  449. for (var j = 0, l = commandsList.length; j < l; j++) {
  450. var result = commandsList[j].command.exec(commandText);
  451. if (result) {
  452. var parameters = result.slice(1);
  453. if (debugState) {
  454. root.console.log('command matched: %c' + commandsList[j].originalPhrase, debugStyle);
  455. if (parameters.length) {
  456. root.console.log('with parameters', parameters);
  457. }
  458. }
  459. // execute the matched command
  460. commandsList[j].callback.apply(this, parameters);
  461. invokeCallbacks(callbacks.resultMatch);
  462. // for commands "sound on", "stop" and "mute" do not play sound or display message
  463. //var myMatchedCommand = commandsList[j].originalPhrase;
  464. var ignoreCallsFor = ["sound on", "mute", "stop"];
  465. if (ignoreCallsFor.indexOf(commandsList[j].originalPhrase) < 0) {
  466. // play sound when match found
  467. $.smallBox({
  468. title : (commandsList[j].originalPhrase),
  469. content : "loading...",
  470. color : "#333",
  471. sound_file : 'voice_alert',
  472. timeout : 2000
  473. });
  474. if ($('#speech-btn .popover').is(':visible')) {
  475. $('#speech-btn .popover').fadeOut(250);
  476. }
  477. }// end if
  478. return true;
  479. }
  480. } // end for
  481. }// end for
  482. invokeCallbacks(callbacks.resultNoMatch);
  483. //console.log("no match found for: " + commandText)
  484. $.smallBox({
  485. title : "Error: <strong>" + ' " ' + commandText + ' " ' + "</strong> no match found!",
  486. content : "Please speak clearly into the microphone",
  487. color : "#a90329",
  488. timeout : 5000,
  489. icon : "fa fa-microphone"
  490. });
  491. if ($('#speech-btn .popover').is(':visible')) {
  492. $('#speech-btn .popover').fadeOut(250);
  493. }
  494. return false;
  495. };
  496. // build commands list
  497. if (resetCommands) {
  498. commandsList = [];
  499. }
  500. if (commands.length) {
  501. this.addCommands(commands);
  502. }
  503. },
  504. // Start listening (asking for permission first, if needed).
  505. // Call this after you've initialized smartSpeechRecognition with commands.
  506. // Receives an optional options object:
  507. // { autoRestart: true }
  508. start : function(options) {
  509. initIfNeeded();
  510. options = options || {};
  511. if (options.autoRestart !== undefined) {
  512. autoRestart = !!options.autoRestart;
  513. } else {
  514. autoRestart = true;
  515. }
  516. lastStartedAt = new Date().getTime();
  517. recognition.start();
  518. },
  519. // abort the listening session (aka stop)
  520. abort : function() {
  521. autoRestart = false;
  522. if (isInitialized) {
  523. recognition.abort();
  524. }
  525. },
  526. // Turn on output of debug messages to the console. Ugly, but super-handy!
  527. debug : function(newState) {
  528. if (arguments.length > 0) {
  529. debugState = !!newState;
  530. } else {
  531. debugState = true;
  532. }
  533. },
  534. // Set the language the user will speak in. If not called, defaults to 'en-US'.
  535. // e.g. 'fr-FR' (French-France), 'es-CR' (Español-Costa Rica)
  536. setLanguage : function(language) {
  537. initIfNeeded();
  538. recognition.lang = language;
  539. },
  540. // Add additional commands that smartSpeechRecognition will respond to. Similar in syntax to smartSpeechRecognition.init()
  541. addCommands : function(commands) {
  542. var cb, command;
  543. initIfNeeded();
  544. for (var phrase in commands) {
  545. if (commands.hasOwnProperty(phrase)) {
  546. cb = root[commands[phrase]] || commands[phrase];
  547. if ( typeof cb !== 'function') {
  548. continue;
  549. }
  550. //convert command to regex
  551. command = commandToRegExp(phrase);
  552. commandsList.push({
  553. command : command,
  554. callback : cb,
  555. originalPhrase : phrase
  556. });
  557. }
  558. }
  559. if (debugState) {
  560. root.console.log('Commands successfully loaded: %c' + commandsList.length, debugStyle);
  561. }
  562. },
  563. // Remove existing commands. Called with a single phrase, array of phrases, or methodically. Pass no params to remove all commands.
  564. removeCommands : function(commandsToRemove) {
  565. if (commandsToRemove === undefined) {
  566. commandsList = [];
  567. return;
  568. }
  569. commandsToRemove = Array.isArray(commandsToRemove) ? commandsToRemove : [commandsToRemove];
  570. commandsList = commandsList.filter(function(command) {
  571. for (var i = 0; i < commandsToRemove.length; i++) {
  572. if (commandsToRemove[i] === command.originalPhrase) {
  573. return false;
  574. }
  575. }
  576. return true;
  577. });
  578. },
  579. // Lets the user add a callback of one of 9 types:
  580. // start, error, end, result, resultMatch, resultNoMatch, errorNetwork, errorPermissionBlocked, errorPermissionDenied
  581. // Can also optionally receive a context for the callback function as the third argument
  582. addCallback : function(type, callback, context) {
  583. if (callbacks[type] === undefined) {
  584. return;
  585. }
  586. var cb = root[callback] || callback;
  587. if ( typeof cb !== 'function') {
  588. return;
  589. }
  590. callbacks[type].push({
  591. callback : cb,
  592. context : context || this
  593. });
  594. }
  595. };
  596. }).call(this);
  597. var autoStart = function() {
  598. smartSpeechRecognition.addCommands(commands);
  599. if (smartSpeechRecognition) {
  600. // activate plugin
  601. smartSpeechRecognition.start();
  602. // add btn class
  603. $.root_.addClass("voice-command-active");
  604. // set localStorage when switch is on manually
  605. if (voice_localStorage) {
  606. localStorage.setItem('sm-setautovoice', 'true');
  607. }
  608. } else {
  609. // if plugin not found
  610. alert("speech plugin not loaded");
  611. }
  612. }
  613. // if already running with localstorage
  614. if (SpeechRecognition && voice_command && localStorage.getItem('sm-setautovoice') == 'true') {
  615. autoStart();
  616. }
  617. // auto start
  618. if (SpeechRecognition && voice_command_auto && voice_command) {
  619. autoStart();
  620. }