From d35201b1420dea25c6d02a573f8d342ba7c8c97f Mon Sep 17 00:00:00 2001 From: Wonnam Jang Date: Wed, 15 Feb 2017 11:26:12 +0900 Subject: [PATCH 2/3] Init version Change-Id: Ia882e01e6283761b018a5b104653d2f44bc4f746 Signed-off-by: Wonnam Jang --- AUTHORS | 4 + CMakeLists.txt | 67 ++ LICENSE | 206 +++++ NOTICE | 3 + js/vc-webview-en_US.js | 335 +++++++ js/vc-webview-ko_KR.js | 491 ++++++++++ js/vc-webview.js | 1646 ++++++++++++++++++++++++++++++++++ js_custom/www.youtube.com.js | 20 + js_custom/www.youtube.com.tv.js | 39 + js_custom/www.youtube.com.tv_kids.js | 39 + packaging/vc-webview-js.manifest | 5 + packaging/vc-webview-js.spec | 45 + 12 files changed, 2900 insertions(+) create mode 100644 AUTHORS create mode 100755 CMakeLists.txt create mode 100644 LICENSE create mode 100644 NOTICE create mode 100755 js/vc-webview-en_US.js create mode 100755 js/vc-webview-ko_KR.js create mode 100755 js/vc-webview.js create mode 100755 js_custom/www.youtube.com.js create mode 100755 js_custom/www.youtube.com.tv.js create mode 100755 js_custom/www.youtube.com.tv_kids.js create mode 100755 packaging/vc-webview-js.manifest create mode 100755 packaging/vc-webview-js.spec diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b5fa653 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Wonnam Jang +Kwangyoun Kim +Sooyeon Kim +Suyeon Hwang \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..6887347 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,67 @@ +# Check minimum CMake version +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +# Project name +PROJECT(vc-webview-js) + +# pkg config tool +INCLUDE(FindPkgConfig) + +# Build type +SET(CMAKE_BUILD_TYPE "Release") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fprofile-arcs -ftest-coverage -D_GNU_SOURCE") + +# CMake settings +MESSAGE(STATUS "========================================") +MESSAGE(STATUS "CMAKE_BINARY_DIR: " ${CMAKE_BINARY_DIR}) +MESSAGE(STATUS "CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR}) +MESSAGE(STATUS "CMAKE_SOURCE_DIR: " ${CMAKE_SOURCE_DIR}) +MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR}) +MESSAGE(STATUS "PROJECT_BINARY_DIR: " ${PROJECT_BINARY_DIR}) +MESSAGE(STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR}) +MESSAGE(STATUS "EXECUTABLE_OUTPUT_PATH: " ${EXECUTABLE_OUTPUT_PATH}) +MESSAGE(STATUS "LIBRARY_OUTPUT_PATH: " ${LIBRARY_OUTPUT_PATH}) +MESSAGE(STATUS "CMAKE_MODULE_PATH: " ${CMAKE_MODULE_PATH}) +MESSAGE(STATUS "CMAKE_COMMAND: " ${CMAKE_COMMAND}) +MESSAGE(STATUS "CMAKE_ROOT: " ${CMAKE_ROOT}) +MESSAGE(STATUS "CMAKE_CURRENT_LIST_FILE: " ${CMAKE_CURRENT_LIST_FILE}) +MESSAGE(STATUS "CMAKE_CURRENT_LIST_LINE: " ${CMAKE_CURRENT_LIST_LINE}) +MESSAGE(STATUS "CMAKE_INCLUDE_PATH: " ${CMAKE_INCLUDE_PATH}) +MESSAGE(STATUS "CMAKE_LIBRARY_PATH: " ${CMAKE_LIBRARY_PATH}) +MESSAGE(STATUS "CMAKE_SYSTEM: " ${CMAKE_SYSTEM}) +MESSAGE(STATUS "CMAKE_SYSTEM_NAME: " ${CMAKE_SYSTEM_NAME}) +MESSAGE(STATUS "CMAKE_SYSTEM_VERSION: " ${CMAKE_SYSTEM_VERSION}) +MESSAGE(STATUS "CMAKE_SYSTEM_PROCESSOR: " ${CMAKE_SYSTEM_PROCESSOR}) +MESSAGE(STATUS "UNIX: " ${UNIX}) +MESSAGE(STATUS "WIN32: " ${WIN32}) +MESSAGE(STATUS "APPLE: " ${APPLE}) +MESSAGE(STATUS "MINGW: " ${MINGW}) +MESSAGE(STATUS "CYGWIN: " ${CYGWIN}) +MESSAGE(STATUS "BORLAND: " ${BORLAND}) +MESSAGE(STATUS "MSVC: " ${MSVC}) +MESSAGE(STATUS "MSVC_IDE: " ${MSVC_IDE}) +MESSAGE(STATUS "MSVC60: " ${MSVC60}) +MESSAGE(STATUS "MSVC70: " ${MSVC70}) +MESSAGE(STATUS "MSVC71: " ${MSVC71}) +MESSAGE(STATUS "MSVC80: " ${MSVC80}) +MESSAGE(STATUS "CMAKE_COMPILER_2005: " ${CMAKE_COMPILER_2005}) +MESSAGE(STATUS "CMAKE_SKIP_RULE_DEPENDENCY: " ${CMAKE_SKIP_RULE_DEPENDENCY}) +MESSAGE(STATUS "CMAKE_SKIP_INSTALL_ALL_DEPENDENCY: " ${CMAKE_SKIP_INSTALL_ALL_DEPENDENCY}) +MESSAGE(STATUS "CMAKE_SKIP_RPATH: " ${CMAKE_SKIP_RPATH}) +MESSAGE(STATUS "CMAKE_VERBOSE_MAKEFILE: " ${CMAKE_VERBOSE_MAKEFILE}) +MESSAGE(STATUS "CMAKE_SUPPRESS_REGENERATION: " ${CMAKE_SUPPRESS_REGENERATION}) +MESSAGE(STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS}) +MESSAGE(STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS}) +MESSAGE(STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE}) +MESSAGE(STATUS "BUILD_SHARED_LIBS: " ${BUILD_SHARED_LIBS}) +MESSAGE(STATUS "CMAKE_C_COMPILER: " ${CMAKE_C_COMPILER}) +MESSAGE(STATUS "CMAKE_CXX_COMPILER: " ${CMAKE_CXX_COMPILER}) +MESSAGE(STATUS "CMAKE_COMPILER_IS_GNUCC: " ${CMAKE_COMPILER_IS_GNUCC}) +MESSAGE(STATUS "CMAKE_COMPILER_IS_GNUCXX : " ${CMAKE_COMPILER_IS_GNUCXX}) +MESSAGE(STATUS "CMAKE_AR: " ${CMAKE_AR}) +MESSAGE(STATUS "CMAKE_RANLIB: " ${CMAKE_RANLIB}) +MESSAGE(STATUS "========================================") +# Warning flags + +INSTALL(DIRECTORY js DESTINATION ${TZ_SYS_RO_SHARE}/voice/vc-webview/res/) +INSTALL(DIRECTORY js_custom DESTINATION ${TZ_SYS_RO_SHARE}/voice/vc-webview/res/) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..571fe79 --- /dev/null +++ b/LICENSE @@ -0,0 +1,206 @@ +Flora License + +Version 1.1, April, 2013 + +http://floralicense.org/license/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and +all other entities that control, are controlled by, or are +under common control with that entity. For the purposes of +this definition, "control" means (i) the power, direct or indirect, +to cause the direction or management of such entity, +whether by contract or otherwise, or (ii) ownership of fifty percent (50%) +or more of the outstanding shares, or (iii) beneficial ownership of +such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice +that is included in or attached to the work (an example is provided +in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, +as a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, +or merely link (or bind by name) to the interfaces of, the Work and +Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor +for inclusion in the Work by the copyright owner or by an individual or +Legal Entity authorized to submit on behalf of the copyright owner. +For the purposes of this definition, "submitted" means any form of +electronic, verbal, or written communication sent to the Licensor or +its representatives, including but not limited to communication on +electronic mailing lists, source code control systems, and issue +tracking systems that are managed by, or on behalf of, the Licensor +for the purpose of discussing and improving the Work, but excluding +communication that is conspicuously marked or otherwise designated +in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +"Tizen Certified Platform" shall mean a software platform that complies +with the standards set forth in the Tizen Compliance Specification +and passes the Tizen Compliance Tests as defined from time to time +by the Tizen Technical Steering Group and certified by the Tizen +Association or its designated agent. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work +solely as incorporated into a Tizen Certified Platform, where such +license applies only to those patent claims licensable by such +Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work solely +as incorporated into a Tizen Certified Platform to which such +Contribution(s) was submitted. If You institute patent litigation +against any entity (including a cross-claim or counterclaim +in a lawsuit) alleging that the Work or a Contribution incorporated +within the Work constitutes direct or contributory patent infringement, +then any patent licenses granted to You under this License for that +Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof pursuant to the copyright license +above, in any medium, with or without modifications, and in Source or +Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works + a copy of this License; and + 2. You must cause any modified files to carry prominent notices stating + that You changed the files; and + 3. You must retain, in the Source form of any Derivative Works that + You distribute, all copyright, patent, trademark, and attribution + notices from the Source form of the Work, excluding those notices + that do not pertain to any part of the Derivative Works; and + 4. If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable + copy of the attribution notices contained within such NOTICE file, + excluding those notices that do not pertain to any part of + the Derivative Works, in at least one of the following places: + within a NOTICE text file distributed as part of the Derivative Works; + within the Source form or documentation, if provided along with the + Derivative Works; or, within a display generated by the Derivative Works, + if and wherever such third-party notices normally appear. + The contents of the NOTICE file are for informational purposes only + and do not modify the License. You may add Your own attribution notices + within Derivative Works that You distribute, alongside or as an addendum + to the NOTICE text from the Work, provided that such additional attribution + notices cannot be construed as modifying the License. You may add Your own + copyright statement to Your modifications and may provide additional or + different license terms and conditions for use, reproduction, or + distribution of Your modifications, or for any such Derivative Works + as a whole, provided Your use, reproduction, and distribution of + the Work otherwise complies with the conditions stated in this License + and your own copyright statement or terms and conditions do not conflict + the conditions stated in the License including section 3. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Flora License to your work + +To apply the Flora License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets "[]" +replaced with your own identifying information. (Don't include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Flora License, Version 1.1 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://floralicense.org/license/ + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..205e4cf --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Flora License, Version 1.1 +Please, see the LICENSE.Flora file for Flora License, Version 1.1 terms and conditions. \ No newline at end of file diff --git a/js/vc-webview-en_US.js b/js/vc-webview-en_US.js new file mode 100755 index 0000000..fe01a8b --- /dev/null +++ b/js/vc-webview-en_US.js @@ -0,0 +1,335 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-en_US.js + * + * This source code is a language specified script for English(en_US). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* second, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* first, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + if (true == convert.startsWith('to') && (' ' == text[2] || text.length == 2)) { + if (vc_visible_hints[1].type == 'input' || text.length == 2) { + result = { + cmd : 2, + param : text.substr(3).trim() + }; + return result; + } + } else if (true == convert.startsWith('for') && (' ' == text[3] || text.length == 3)) { + if (vc_visible_hints[3].type == 'input' || text.length == 3) { + result = { + cmd : 4, + param : text.substr(4).trim() + }; + return result; + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'google search'; + var youtubeSearch = 'youtube search'; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.co.kr/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (convert == 'refresh') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.co.kr/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'scrolldown') { + vc_scroll_event_firing('DOWN'); + } else if (convert == 'scrollup') { + vc_scroll_event_firing('UP'); + } else if (convert == 'tothetop') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'showsourcecode') { + vc_print_html(); + } else if (convert == 'next' || convert == 'forward') { + history.forward(); + } else if (convert == 'before' || convert == 'back' || convert == 'previous') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-ko_KR.js b/js/vc-webview-ko_KR.js new file mode 100755 index 0000000..25c4cdd --- /dev/null +++ b/js/vc-webview-ko_KR.js @@ -0,0 +1,491 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-ko_KR.js + * + * This source code is a language specified script for Korean(ko_KR). + * If there is no script for some language, this script is loaded as default. + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* second, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < document.links.length; ++i) { + var text = document.links[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); + text = text.replace(/ /g, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(document.links[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < document.links.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = document.links[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* first, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + if (replace == true) { + var rep = param.replace('이 ', '의 '); + el = vc_search_word(rep, false); + if (el != undefined) return el; + + rep = param.replace('으 ', '이 '); + el = vc_search_word(rep, false); + if (el != undefined) return el; + + rep = param.replace('에 ', '의 '); + el = vc_search_word(rep, false); + if (el != undefined) return el; + + rep = param.replace('의 ', '에 '); + el = vc_search_word(rep, false); + if (el != undefined) return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return vc_search_pronunciation(param); +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_convert_to_syllable(param) { + var korUnicodeStart = 44032; + var korUnicodeNum = 11172; + var korUnicodeEnd = 55204; + var korChoCnt = 19; + var korJungCnt = 21; + var korJongCnt = 28; + + var result = []; + + for (var i = 0; i < param.length; i++) { + var c = param.charCodeAt(i); + + if (korUnicodeStart > c || korUnicodeEnd < c) { + continue; + } + + var jongIdx = (c - korUnicodeStart) % korJongCnt; + var jungIdx = (((c - korUnicodeStart) - jongIdx) / korJongCnt) % korJungCnt; + var choIdx = ((((c - korUnicodeStart) - jongIdx) / korJongCnt) - jungIdx) / korJungCnt; + + result.push(choIdx, jungIdx, jongIdx); + } + + return result; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(220, 0, 0, 1)'; + } + if (param.length > 1) { + return undefined; + } + + vc_print_log('=== start searching(pronuciation level)'); + param = param[0]; + + var sylla = vc_convert_to_syllable(param); + var threshold = sylla.length * 0.5; + var el = undefined; + var elScore = 2147483247; + + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 2147483247; + + for (var j = 0; j < text.length; j++) { + if (param.length > text[j].length) { + continue; + } + var min = 2147483247; + + for (var s = 0; s <= text[j].length - param.length; s++) { + var temp = vc_convert_to_syllable(text[j].substr(s, param.length)); + var cnt = 0; + + for (var k = 0; k < sylla.length; k++) { + if (sylla[k] != temp[k]) { + cnt++; + } + + if (cnt == threshold) { + cnt++; + break; + } + } + + if (min > cnt) { + min = cnt; + } + } + + if (score > min) { + score = min; + } + } + + if (threshold > score && elScore > score) { + el = vc_all_elem[i]; + elScore = score; + } + } + } + + vc_print_log('=== finish searching(pronuciation level)'); + + if (el != undefined) { + return el; + } + + return undefined; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['일', '이', '삼', '사', '오', '육', '칠', '팔', '구', '십', + '십일', '십이', '십삼', '십사', '십오', '십육', '십칠', '십팔', '십구', '이십', + '이십일', '이십이', '이십삼', '이십사', '이십오', '이십육', '이십칠', '이십팔', '이십구', '삼십', + '삼십일', '삼십이', '삼십삼', '삼십사', '삼십오', '삼십육', '삼십칠', '삼십팔', '삼십구', '사십', + '사십일', '사십이', '사십삼', '사십사', '사십오', '사십육', '사십칠', '사십팔', '사십구', '오십', + '오십일', '오십이', '오십삼', '오십사', '오십오', '오십육', '오십칠', '오십팔', '오십구', '육십', + '육십일', '육십이', '육십삼', '육십사', '육십오', '육십육', '육십칠', '육십팔', '육십구', '칠십', + '칠십일', '칠십이', '칠십삼', '칠십사', '칠십오', '칠십육', '칠십칠', '칠십팔', '칠십구', '팔십', + '팔십일', '팔십이', '팔십삼', '팔십사', '팔십오', '팔십육', '팔십칠', '팔십팔', '팔십구', '구십', + '구십일', '구십이', '구십삼', '구십사', '구십오', '구십육', '구십칠', '구십팔', '구십구', '백']; + var seven = ['채널', '질']; + var eight = ['발', '달']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length + 1); + i = i + 1; + + for (var j = 0; 9 > j; j++) { + if (true == partial.toLowerCase().startsWith(numbers[j]) && (' ' == partial[numbers[j].length] || partial.length == numbers[j].length)) { + partial = partial.substr(numbers[j].length + 1); + i = i + j + 1; + break; + } + } + + if (vc_visible_hints[i - 1].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : i, + param : partial.trim() + }; + return result; + } + } + } + + for (var i = 0; seven.length > i; i++) { + if (true == convert.startsWith(seven[i]) && (' ' == text[seven[i].length] || text.length == seven[i].length) && (vc_visible_hints[6].type == 'input' || text.length == seven[i].length)) { + result = { + cmd : 7, + param : text.substr(seven[i].length + 1).trim() + }; + return result; + } + } + + for (var i = 0; eight.length > i; i++) { + if (true == convert.startsWith(eight[i]) && (' ' == text[eight[i].length] || text.length == eight[i].length) && (vc_visible_hints[7].type == 'input' || text.length == eight[i].length)) { + result = { + cmd : 8, + param : text.substr(eight[i].length + 1).trim() + }; + return result; + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text); + + /* if param is a number, move the value in param to cmd */ + var words = result.param.split(' '); + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + var idx_sep = result.param.indexOf('번 '); + if (isNaN(result.cmd) == true && 0 < idx_sep) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = '구글 검색'; + var naverSearch = '네이버 검색'; + var youtubeSearch = '유튜브 검색'; + var googleSearch2 = '구글 '; + var naverSearch2 = '네이버 '; + var youtubeSearch2 = '유튜브 '; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.co.kr/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(naverSearch) == true) { + location.href = 'https://search.naver.com/search.naver?where=nexearch&query=' + (text.substr(naverSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (convert == '유튜브TV') { + location.href = 'https://www.youtube.com/tv'; + } else if (text.startsWith(googleSearch2) == true) { + location.href = 'https://www.google.co.kr/search?q=' + (text.substr(googleSearch2.length)).trim(); + } else if (text.startsWith(naverSearch2) == true) { + location.href = 'https://search.naver.com/search.naver?where=nexearch&query=' + (text.substr(naverSearch2.length)).trim(); + } else if (text.startsWith(youtubeSearch2) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch2.length)).trim(); + } else if (convert.startsWith('구글') == true) { + location.href = 'https://www.google.co.kr/'; + } else if (convert.startsWith('네이버') == true) { + location.href = 'http://www.naver.com/'; + } else if (convert.startsWith('유튜브') == true) { + location.href = 'https://www.youtube.com/'; + } else if (convert == '취소') { + vc_remove_hints(); + } else if (convert == '리프레쉬' || convert == '새로고침') { + location.reload(); + } else if (convert == '아래로' || convert == '내려' || convert == '내려봐' || convert == '내려줘') { + vc_scroll_event_firing('DOWN'); + } else if (convert == '위로' || convert == '올려' || convert == '올려봐' || convert == '올려줘') { + vc_scroll_event_firing('UP'); + } else if (convert == '맨위로' || convert == '처음으로') { + vc_scroll_event_firing('TOP'); + } else if (convert == '광고닫기' || convert == '광고찾기') { + document.querySelector('.videoAdUiSkipButton').click(); + } else if (convert == '소스보기') { + vc_print_html(); + } else if (convert == '다음페이지' || convert == '다음으로' || convert == '앞으로가기' || convert == '앞으로') { + history.forward(); + } else if (convert == '이전페이지' || convert == '이전으로' || convert == '뒤로가기' || convert == '뒤로' || convert == '백' || convert == '벡') { + history.back(); + } else if (convert == '로그보기' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview.js b/js/vc-webview.js new file mode 100755 index 0000000..8c785df --- /dev/null +++ b/js/vc-webview.js @@ -0,0 +1,1646 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview.js + * + * This source code is a base script of web voice touch. + */ + + /** + * vc_docs holds analysed documents' first hint number and last hint number + * @member doc document elements. + * @member start the first tooltip number in @doc. + * @member end the last tooltip number in @doc. + */ +var vc_docs = [], + +vc_conflict_timer = null, + +/** + * vc_conflict_links holds references to links that match the same keyword + */ +vc_conflict_links = []; + +/** + * vc_scr holds info about screen and website + * @member top coordinate of the top boundary. + * @member left coordinate of the left boundary. + * @member bottom coordinate of the bottom boundary. + * @member right coordinate of the right boundary. + */ +var vc_scr = { + top : 0, + left : 0, + bottom : window.innerHeight, + right : window.innerWidth +}, + +/** + * vc_xpath_query is a query that processes DOM tree to get clickable objects. + * It analyses HTML tree as it is XML and returns matching objects in one of selected forms. + */ +vc_xpath_query = ".//xhtml:input[not(@type='hidden')] | .//xhtml:a | .//xhtml:area | .//xhtml:textarea | .//xhtml:button | .//xhtml:*[" + + "@role='link' or @role='button' or @role='checkbox' or @role='combobox' or @role='radio'] |" + + " .//xhtml:div[contains(@class, 'ui-btn')] | .//xhtml:div[contains(@class, 'sideBarButton')] | .//xhtml:div[contains(@class, 'buttonCaption')]", + +/** + * vc_page_hints holds all hints on website + */ +vc_page_hints = [], + +/** + * vc_hint_div is a DIV that gathers all hints + */ +vc_hint_div, + +/** + * vc_high_div is a DIV that gathers red highlight boxes + */ +vc_high_div, + +/** + * vc_hint_num is used to numerate hints from 1 on every screen they're displayed + */ +vc_hint_num, + +/** + * vc_visible_hints holds all hints that are currently visible + */ +vc_visible_hints = [], + +/** + * vc_bad_iframes holds iframes that should be highlighted with red color + */ +vc_bad_iframes = [], + +/** + * vc_log_area is a textarea element for log texts. + */ +vc_log_area = document.createElement('textarea'), + +/** + * vc_html_area is a textarea element to read raw source code of html document in TV. + */ +vc_html_area = undefined, + +/** + * vc_asr_result is a div element shows the asr result for debugging. + */ +vc_asr_result = undefined, + +/** + * vc_rec_result is a div element shows the recognition result of document searching for debugging. + */ +vc_rec_result = undefined, + +/** + * vc_flag_log is a flag variable. If it is true, vc_log_area is created. Otherwise, vc_log_area is nothing. + */ +vc_flag_log = false, + +/** + * vc_all_elem is a array that includes whole element in html document for text searching. + */ +vc_all_elem = undefined, + +/** + * vc_flag_conflict is a flag variable. When multiple elements are selected, it is true. Otherwise, it is false. + */ +vc_flag_conflict = false, + +/** + * vc_flag_hint_exist is a flag variable. When tooltips are already exist, it is true. Otherwise, it is false. + */ +vc_flag_hint_exist = false, + +/** + * vc_text_indicators is an array that contains text indicator elements + */ +vc_text_indicators = [], + +/** + * vc_made_hint shows the state tooltip making. + */ +vc_made_hint = false, + +/** + * vc_tag_index stores index number of the set of tooltips in web page. + * this variable prevents making duplicated tooltips. + */ +vc_tag_index = 0; + +/** + * prototypes of overridable custom function + */ +function vc_custom_pre_generate_hints() { + vc_print_log('No custom script'); +} + +function vc_custom_pre_show_hints() { + vc_print_log('No custom script'); +} + +function vc_custom_pre_remove_hints() { + vc_print_log('No custom script'); +} + +function vc_custom_pre_hide_hints() { + vc_print_log('No custom script'); +} +/* ======================== */ + +/** + * vc_custom_add_xpath_query functino adds given condition to xpath query + * + * @param className the name of the class of DOM elements + * @param DOMtype(optional) the type name of DOM element + * + * @remind this function must be called in page specific script + */ +function vc_custom_add_xpath_query(className, DOMtype) { + if (undefined == DOMtype) { + DOMtype = 'div'; + } + + vc_xpath_query += " | .//xhtml:" + DOMtype + "[contains(@class, '" + className + "')]"; +} + +/** + * vc_is_child check if element is a child of other element + * + * @param child child to check the parent of + * @param parent to test to + * + * @return true if elements are related, false otherwise + */ +function vc_is_child(child, parent) { + var node = child.parentNode; + while (node && node != document.body) { + if (node === parent) { + return true; + } + node = node.parentNode; + } + return false; +} + +/** + * vc_is_hidden function checks if the element given as parameter is hidden due to its CSS style + * + * @param elem element to be checked + * @param predecessor predecessor of elem to check visibility if elementFromPoint doesn't return elem + * + * @return true if element is invisible, false otherwise + */ +function vc_is_hidden(elem, predecessor) { + if (elem == undefined) { + return true; + } + + /* if predecesor is no found assume parent is one */ + if (!predecessor && elem.parentNode) { + predecessor = elem.parentNode; + } + /* check visibility in css style */ + var doc = elem.ownerDocument, + win = doc.defaultView, + computedStyle = win.getComputedStyle(elem, null); + + if (computedStyle.getPropertyValue('visibility') !== 'visible' || computedStyle.getPropertyValue('display') === 'none') { + return true; + } + + /* object is visible check if it is on current screen */ + var rect = elem.getBoundingClientRect(), + x = rect.left + (rect.width / 2), + y = rect.top + (rect.height / 2), + point; + + if (y < 0 && x >= 0) { + y = 0; + } else if (y < 0 && x < 0) { + x = y = 0; + } else if (y >= 0 && x < 0) { + x = 0; + } + + point = doc.elementFromPoint(x, y); + /* if elementFromPoint returns HTMLBodyElement it probably is a scroll left/right list and it is hidden */ + if (point === doc.body) { + return true; + } + /* if elementFromPoint returns predecessor it is visible */ + if (point && predecessor && vc_is_child(point, predecessor)) { + return false; + } + + return true; +} + +/** + * vc_is_visible function checks if the element provided as argument is currently visible on screen + * + * @param elem element to be checked + * @param scr screen information + * @param isTextLink determines if the element is text link + * + * @return true if visible false otherwise + */ +function vc_is_visible(elem, scr, isTextLink) { + if (elem == undefined) { + return false; + } + + if (!scr) { + scr = { + top : 0, + left : 0, + bottom : window.innerHeight, + right : window.innerWidth + }; + } + // if only two parameters passed to function assume isTextLink is false + isTextLink = typeof isTextLink !== 'undefined' ? isTextLink : false; + + var docy = elem.ownerDocument, + win = docy.defaultView, + computedStyle = win.getComputedStyle(elem, null); + + /* element is not visible if it is fully transparent except select box */ + if (parseFloat(computedStyle.getPropertyValue('opacity')) === 0.0) { + return false; + } + + var rect = elem.getBoundingClientRect(); + + /* element is not visible if it is not on screen */ + if (!rect || rect.top >= scr.bottom || rect.bottom <= scr.top || rect.left >= scr.right || + rect.right <= scr.left) { + return false; + } + + /* element is not visible if it is hidden and it is not a text hyperlink */ + if (!isTextLink && vc_is_hidden(elem, null)) { + return false; + } + + return true; +} + +/** + * vc_make_hint procedure creates invisible hint for element provided as argument + * + * @param elem element for which hint is to be created + * @param child if child is passed, the hint will be positioned according to position of child + */ +function vc_make_hint(elem, child) { + // vc_print_log(elem); + var rect; + + rect = child.getBoundingClientRect(); + + if (!rect || elem.vc_tag_index == vc_tag_index) { + return; + } + + elem.vc_tag_index = vc_tag_index; + + var doc = elem.ownerDocument; + + /** hint object holds clickable element, type of element and created hint (HTMLSpanElement) + * @member elem clickable target element. + * @member type the type of @elem. + * @member child child element of @elem + * @member span tooltip element of @elem + */ + var hint = { + elem : elem, + type : 'normal', + child : child, + span : null + }; + + if(elem instanceof HTMLAreaElement){ + hint.type = 'area'; + } + + /* not all input objects are supported */ + if (elem instanceof HTMLInputElement) { + if (elem.type === 'text' || elem.type === 'password' || elem.type === 'datetime' || elem.type === 'email' || + elem.type === 'search' || elem.type === 'number' || elem.type === 'url') { + hint.type = 'input'; + } else if (elem.type !== 'button' && elem.type !== 'submit' && elem.type !== 'color' && elem.type !== 'radio' && + elem.type !== 'checkbox' && elem.type !== 'file' && elem.type !== 'submit' && elem.type !== 'image') { + return; + } + /* consider TextArea element as input element */ + } else if (elem instanceof HTMLTextAreaElement) { + hint.type = 'input'; + } + + /** span object is the visual representation of hint */ + var span = doc.createElement('span'); + span.id = 'vc_tooltip'; + span.className = 'vc_number_tag_normal vc_tooltip_' + hint.type; + + if (hint.type == 'input') { + span.classList.add('vc_tip_tier_first'); + } else if (rect.height > 30) { + span.classList.add('vc_tip_tier_second'); + } else { + span.classList.add('vc_tip_tier_third'); + } + + hint.span = span; + + /* appends hint to vc_hint_div container */ + vc_hint_div.appendChild(hint.span); + vc_page_hints.push(hint); +} + +/** + * nsResolver function that is used for resolving namespace in webpage document + * + * @param prefix prefix of the namespace + * + * @return namespace url + */ +function nsResolver(prefix) { + var namespace = { + 'xhtml' : 'http://www.w3.org/1999/xhtml' //add other namespaces if needed + }; + return namespace[prefix] || null; +} + +/** + * vc_generate_hints function creates hints for all clickable elements on web page + * + * @param win window element (can be different if we analyse iframe) + */ +function vc_generate_hints(win) { + vc_print_log('== start generate hints' + win); + vc_tag_index++; + + /* if win is not passed assume the global window variable */ + if (!win) { + win = window; + } + + var doc; + + try { + doc = win.document; + } catch (e) { + vc_print_log('== some error occured in win.document' + e); + return; + } + + /* Custom pre process to generate hints */ + vc_custom_pre_generate_hints(); + + var start = vc_page_hints.length; + + vc_hint_div = doc.createElement('div'); + vc_hint_div.id = 'vc_tooltip_area'; + vc_hint_div.style.display = 'block'; + + vc_text_indicators = []; + + /* return result as snapshot not iterator, due to problems with undefined objects */ + vc_print_log('== start doc.evaluate'); + var snapshot = doc.evaluate(vc_xpath_query, doc.body, nsResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + vc_print_log('== snapshot length : ' + snapshot.snapshotLength); + + /* set current screen dimensions */ + vc_scr = { + top : 0, + left : 0, + bottom : win.innerHeight, + right : win.innerWidth + }; + + /* analyse if a hint is needed for each returned object */ + for (var i = 0; i < snapshot.snapshotLength; i++) { + var element = snapshot.snapshotItem(i), + rect = element.getBoundingClientRect(); + + vc_made_hint = false; + /* executed very rarely */ + if (rect.width === 0 || rect.height === 0) { + for (var j = 0; j < element.childNodes.length; j++) { + if (element.childNodes[j].nodeType !== 1) { + continue; + } + + var style = doc.defaultView.getComputedStyle(element.childNodes[j], null); + if (style && style.getPropertyValue('float') !== 'none' && vc_is_visible(element.childNodes[j], vc_scr)) { + vc_make_hint(element, element.childNodes[j]); + vc_made_hint = true; + break; + } + } + + if (vc_made_hint) { + continue; + } + } + + if (vc_is_visible(element, vc_scr) && !element.attributes.disabled) { + if ((element instanceof HTMLButtonElement || element.classList.contains('ui-btn') || element.getAttribute('role') == 'button')) { + if (element.textContent.trim().replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').length > 0) { + vc_text_indicators[vc_text_indicators.length] = element; + } else { + vc_make_hint(element, element); + vc_made_hint = true; + } + } else if (element.getAttribute('role') == 'radio' || element.getAttribute('role') == 'checkbox' || element.getAttribute('role') == 'combobox') { + vc_make_hint(element, element); + vc_made_hint = true; + /* if the element is an anchor without text, make hint */ + } else if (element instanceof HTMLAnchorElement) { + if (element.textContent.trim().length > 0) { + vc_text_indicators[vc_text_indicators.length] = element; + } + + var cStyle = window.getComputedStyle(element, false); + if (cStyle.backgroundImage !== 'none' && cStyle.backgroundImage !== 'inherit') { + vc_make_hint(element, element); + vc_made_hint = true; + } else if (element.textContent.trim().length == 0) { + /* if element has child with background or image element*/ + if (!vc_made_hint) { + var childs = element.querySelectorAll('*'); + for (var sp = 0; sp < childs.length; ++sp) { + if (vc_is_visible(childs[sp], vc_scr)) { + var cstyle = win.getComputedStyle(childs[sp], false); + if (childs[sp].nodeName == 'IMG' || cstyle.overflow == 'hidden' + || (cstyle.backgroundImage !== 'none' && cstyle.backgroundImage !== 'inherit')) { + vc_make_hint(element, childs[sp]); + vc_made_hint = true; + break; + } + } + } + } + + if (!vc_made_hint) { + vc_make_hint(element, element); + vc_made_hint = true; + continue; + } + } else { + if (isNaN(element.textContent.trim())) { + vc_find_img_element(element, null, element); + } + } + } else if (element instanceof HTMLAreaElement || element.nodeName == 'INPUT') { + vc_make_hint(element, element); + } else { + vc_find_img_element(element, null, element); + if (vc_made_hint == false) { + vc_make_hint(element, element); + } + } + } + } + + /* append whole div with hints to body */ + if (doc.body) { + doc.body.insertBefore(vc_hint_div, doc.body.firstChild); + + //append all text indicators to body + vc_docs.push({ + doc : doc, + start : start, + end : vc_page_hints.length - 1 + }); + } + + /* analyse iframes of the website */ + if (win === window) { + var frames = document.querySelectorAll('iframe'); + for (var f = 0; f < frames.length; f++) { + var elem; + try { + elem = frames[f].contentWindow.document; + } catch (e) { + vc_bad_iframes.push(frames[f]); + continue; + } + vc_scr = { + top : 0, + left : 0, + bottom : win.innerHeight, + right : win.innerWidth + }; + if (elem == undefined) { + vc_bad_iframes.push(frames[f]); + continue; + } + if (elem != undefined && !vc_is_visible(frames[f], vc_scr)) { + continue; + } + // vc_generate_hints(frames[f].contentWindow); + } + } + + vc_flag_hint_exist = true; + vc_print_log('== end'); +} + +/** + * vc_find_img_element function find element containing image. if found then call a function to make a tooltip. + * + * @param elem element to search for text + * @param parent parent element of the @elem + * @param snapshotElem the first @elem when vc_generate_hints calls this function + */ +function vc_find_img_element(elem, parent, snapshotElem) { + if (!vc_made_hint) { + if (elem.nodeType == 1) { + var cStyle = document.defaultView.getComputedStyle(elem, false); + if ((vc_is_visible(elem, vc_scr) && cStyle && cStyle.backgroundImage != 'none' && cStyle.backgroundImage != 'inherit' || elem.nodeName == 'IMG')) { + vc_make_hint(snapshotElem, elem); + vc_made_hint = true; + return; + } + } + + var children = elem.childNodes; + for (var ch = 0; !vc_made_hint && ch < children.length; ch++) { + vc_find_img_element(children[ch], elem, snapshotElem); + } + } + +} + +/** + * vc_show_hints function displays hints numbering from 1 + */ +function vc_show_hints() { + /* Custom pre process to show hints */ + vc_custom_pre_show_hints(); + + if (vc_flag_log == true) { + if (vc_asr_result == undefined) { + vc_asr_result = document.createElement('div'); + vc_asr_result.id = 'vc_asr_result'; + vc_asr_result.innerHTML = 'ASR Result'; + document.body.appendChild(vc_asr_result); + } + + if (vc_rec_result == undefined) { + vc_rec_result = document.createElement('div'); + vc_rec_result.id = 'vc_rec_result'; + document.body.appendChild(vc_rec_result); + } + } + + vc_hint_num = 1; + for (var d = 0; d < vc_docs.length; d++) { + var doc = vc_docs[d]; + for (var i = doc.start; i <= doc.end; i++) { + var win = doc.doc.defaultView, + hint = vc_page_hints[i], + rect = hint.child.getClientRects()[0]; + + vc_scr = { + top : 0, + left : 0, + bottom : win.innerHeight, + right : win.innerWidth + }; + + hint.span.style.display = 'block'; + + if (null == rect) { + continue; + } + + var leftPos, + topPos, + position_factor_top, + position_factor_left; + + if (vc_flag_conflict) { + position_factor_top = 18; + position_factor_left = 18; + hint.span.className = 'vc_text_indicator_conflict_normal vc_tooltip_normal vc_tip_tier_second'; + } else { + position_factor_top = 15; + position_factor_left = 15; + } + + if (rect.top < position_factor_top) { + topPos = win.pageYOffset; + } else { + topPos = rect.top + win.pageYOffset - position_factor_top; + } + + if (rect.left < position_factor_left) { + leftPos = win.pageXOffset; + } else { + leftPos = rect.left + win.pageXOffset - position_factor_left; + } + + if (hint.type == 'area') { + coord = hint.elem.coords.split(','); + leftPos = parseFloat(leftPos) + parseFloat(coord[0]); + topPos = parseFloat(topPos) + parseFloat(coord[1]); + } + hint.span.style.top = topPos + 'px'; + hint.span.style.left = leftPos + 'px'; + hint.span.textContent = vc_hint_num; + + hint.span.style.display = 'block'; + + if (-1 == vc_visible_hints.indexOf(hint)) { + vc_visible_hints.push(hint); + } + + vc_hint_num++; + } + } + + // for (var bf = 0; bf < vc_bad_iframes.length; ++bf) { + // vc_result_highlight(vc_bad_iframes[bf]); + // } +} + +/** + * vc_remove_hints function removes all hints in the web page. It deletes both visible and hidden hints + */ +function vc_remove_hints() { + /* Custom pre process to remove hints */ + vc_custom_pre_remove_hints(); + + vc_remove_highlight(); + + for (var d = 0; d < vc_docs.length; d++) { + var doc = vc_docs[d].doc; + var tooltipArea = doc.querySelector('#vc_tooltip_area'); + if (null !== tooltipArea && tooltipArea.parentNode) { + tooltipArea.parentNode.removeChild(tooltipArea); + } + } + vc_visible_hints = []; + vc_page_hints = []; + vc_docs = []; + + /** if the rotation occured refresh the window information */ + vc_scr = { + top : 0, + left : 0, + bottom : window.innerHeight, + right : window.innerWidth + }; + + vc_hint_div = null; + vc_flag_hint_exist = false; + vc_flag_conflict = false; +} + +/** + * vc_hide_hints function hides the hints from the screen. Hints elements still exist + */ +function vc_hide_hints() { + /* Custom pre process to hide hints */ + vc_custom_pre_hide_hints(); + + for (var i = 0; i < vc_visible_hints.length; i++) { + var hint = vc_visible_hints[i]; + if (hint.span.classList.contains('vc_tooltip_focus') == false) { + hint.span.style.display = 'none'; + hint.span.style.top = 0; + hint.span.style.left = 0; + } + } +} + +/** + * vc_remove_popup function removes popup. + * This function is safe to call if the popup doesnt exist. + */ +function vc_remove_popup() { + var node = document.querySelector('#vc_popup'); + if (null !== node && node.parentNode) { + node.parentNode.removeChild(node); + } +} + +/** + * vc_show_popup function displays a floating div over the web page with text in it for timout milliseconds + * + * @param text text to be shown on the popup + * @param timeout time for which the popup should be shown in milliseconds. If timeout is 0 popup must be deleted manually + */ +function vc_show_popup(text, timeout) { + /* remove any existing popup */ + vc_remove_popup(); + + /* overlay creates a light grey area over the whole website */ + var overlay = document.createElement('div'); + overlay.id = 'vc_popup'; + + /* vcpopup is the main popup window, that is centered over the overlay */ + var vcpopup = document.createElement('div'); + vcpopup.id = 'vc_popup_content'; + + /* content is used to display text and center it vertically inside vcpopup */ + var content = document.createElement('div'); + content.style.display = 'table-cell'; + content.style.fontFamily = '"Open Sans", "Helvetica", sans-serif'; + content.style.verticalAlign = 'middle'; + content.innerHTML = text; + + vcpopup.appendChild(content); + overlay.appendChild(vcpopup); + document.body.appendChild(overlay); + + /* if timeout is set to 0, display popup until not deleted manually */ + if (timeout !== 0) { + setTimeout(function () { + vc_remove_popup(); + }, timeout); + } + + return; +} + +/** + * vc_remove_highlight removes highlight from conflicting links + * + * @param selectedNum the number of target tooltip + */ +function vc_remove_highlight(selectedNum) { + if (selectedNum) { + var high = document.querySelectorAll('#vc_highlight'); + for (var cn = 0; cn < high.length; cn++) { + if ((cn + 1) != selectedNum) { + high[cn].parentNode.removeChild(high[cn]); + } + } + } else { + var highlightArea = document.querySelector('#vc_highlight_area'); + if (highlightArea) { + highlightArea.parentNode.removeChild(highlightArea); + } + } +} + +/** + * vc_result_highlight creates highlight box over elem + * + * @param elem element to be highlighted + */ +function vc_result_highlight(elem) { + var doc = elem.ownerDocument, + rect; + + if (vc_is_visible(elem) == false && elem.querySelector('img')) { + rect = elem.querySelector('img').getClientRects()[0]; + } else { + rect = elem.getClientRects()[0]; + } + + if (!rect) { + return; + } + + vc_high_div = document.querySelector('#vc_highlight_area'); + + if (!vc_high_div) { + vc_high_div = doc.createElement('div'); + vc_high_div.id = 'vc_highlight_area'; + doc.body.appendChild(vc_high_div); + } + + var high_span = doc.createElement('div'); + high_span.id = 'vc_highlight'; + + /* top left position of the element */ + var leftPos = (rect.left > vc_scr.left ? rect.left : vc_scr.left); + var topPos = (rect.top > vc_scr.top ? rect.top : vc_scr.top); + + /* adjust top left position with page scroll */ + topPos += window.pageYOffset - 3; + leftPos += window.pageXOffset - 3; + + high_span.style.left = leftPos + 'px'; + high_span.style.top = topPos + 'px'; + high_span.style.width = rect.width + 'px'; + high_span.style.height = (rect.height + 6) + 'px'; + + /* if element's dimensions are 0x0 create highlight for it's children */ + if (rect.width === 0 || rect.height === 0) { + var height = topPos + rect.height; + var width = leftPos + rect.width; + for (var i = 0; i < elem.children.length; i++) { + var child = elem.children[i]; + var chRect = child.getClientRects()[0]; + if (!chRect) { + continue; + } + if (chRect.top + chRect.height > height) { + height = chRect.top + chRect.height; + } + if (chRect.left + chRect.width > width) { + width = chRect.left + chRect.width; + } + } + high_span.style.height = height - topPos + 'px'; + high_span.style.width = width - leftPos + 'px'; + } + + vc_high_div.appendChild(high_span); +} + +/** + * vc_generate_conflict_hints function creates hints for all conflicting highlighted hints + */ +function vc_generate_conflict_hints() { + vc_hint_div = document.querySelector('#vc_tooltip_area'); + + if (!vc_hint_div) { + vc_hint_div = document.createElement('div'); + vc_hint_div.id = 'vc_tooltip_area'; + document.body.insertBefore(vc_hint_div, document.body.firstChild); + } + + vc_scr = { + top : 0, + left : 0, + bottom : window.innerHeight, + right : window.innerWidth + }; + + /* Conflict links */ + var conflicts = vc_conflict_links; + + for (var i = 0; i < conflicts.length; i++) { + var elem = conflicts[i]; + var rect; + + vc_result_highlight(elem); + if (vc_is_visible(elem, vc_scr) == false && elem.querySelector('img') != null) { + rect = elem.querySelector('img').getClientRects()[0]; + } else { + rect = elem.getClientRects()[0]; + } + + if (!rect) { + return; + } + + var leftPos, + topPos, + position_factor_top = 20, //[TODO]move at proper place + position_factor_left = 28, + hint = {}, + span = document.createElement('span'); + span.id = 'vc_tooltip'; + + if (rect.top < position_factor_top) { + topPos = window.pageYOffset + 'px'; + } else { + topPos = rect.top + window.pageYOffset - position_factor_top + 'px'; + } + + if (rect.left < position_factor_left) { + leftPos = window.pageXOffset + 'px'; + } else { + leftPos = rect.left + window.pageXOffset - position_factor_left + 'px'; + } + + /* tooltip style, !please keep styles sorted */ + hint.span = span; + hint.span.style.top = topPos; + hint.span.style.left = leftPos; + vc_hint_div.appendChild(hint.span); + + hint.elem = elem; + hint.child = vc_high_div.childNodes[i]; + vc_page_hints[vc_page_hints.length] = hint; + } + + vc_docs.push({ + doc : document, + start : 0, + end : vc_page_hints.length - 1 + }); + + vc_flag_hint_exist = true; + vc_flag_conflict = true; + vc_conflict_timer = setTimeout(vc_remove_hints, 5000); + + vc_show_hints(); +} + +/** + * vc_trigger_event function makes custom DOM event + * + * @param node target element taking event + * @param eventType type of the custom event + */ +function vc_trigger_event(node, eventType) { + try { + var clickEvent = new Event(eventType); + node.dispatchEvent(clickEvent); + } catch (e) { + console.log('error ouccured', e); + } +} + +/** + * vc_do_action function creates event for selected element. + * + * @param targetElem selected element + * @param numberTag number of selected tooltip + * @param value(option) text entered into selected input element + * + * @return array including coordinates of the @targetElem and the number of targetElem. + */ +function vc_do_action(targetElem, numberTag, value) { + vc_print_log('=== Inside vc_do_action'); + vc_print_log(targetElem.elem.outerHTML); + + var elem = targetElem.elem, + type = targetElem.type, + position, + effect; + + if (!targetElem) { + return; + } + + /* Create click effect element */ + effect = document.createElement('div'); + effect.id = 'vc_click_effect'; + + if (numberTag != undefined) { + position = numberTag.getBoundingClientRect(); + effect.style.left = (position.left + (position.width / 2) - 35) + 'px' + effect.style.top = (position.top + (position.height / 2) - 35) + 'px' + + numberTag.classList.add('vc_tooltip_focus'); + numberTag.style.display = 'block'; + + //conflicts + if (vc_flag_conflict) { + vc_remove_highlight(numberTag.textContent.trim()); + } + vc_hide_hints(); + } else { + position = elem.getClientRects()[0]; + effect.style.left = (position.left - 35) + 'px' + effect.style.top = (position.top - 35) + 'px' + + //text indicators + vc_result_highlight(elem); + elem.classList.add('vc_text_focus'); + + vc_text_indicators[vc_text_indicators.length] = elem; + } + + document.body.insertBefore(effect, document.body.firstChild); + + /* Occurring events */ + try { + if (type == 'input' && value != undefined) { + setTimeout(function () { + elem.value = value; + vc_trigger_event(elem, 'keyup'); + vc_trigger_event(elem, 'input'); + try { + elem.form.submit(); + } catch (e) { + console.log(e); + } + + document.body.removeChild(effect); + vc_remove_hints(); + }, 1500); + + return [0, 0, 0] + } + + setTimeout(function () { + if (vc_asr_result != undefined) { + vc_asr_result.parentElement.removeChild(vc_asr_result); + vc_asr_result = undefined; + } + if (vc_rec_result != undefined) { + vc_rec_result.parentElement.removeChild(vc_rec_result); + vc_rec_result = undefined; + } + + if (numberTag == undefined) { + elem.classList.remove('vc_text_focus'); + } + + document.body.removeChild(effect); + vc_remove_hints(); + + elem.blur(); + elem.focus(); + + vc_print_log('=== Click Finish'); + }, 2000); + + var rect = elem.getClientRects()[0], + x = rect.left + (rect.width / 2), + y = rect.top + (rect.height / 2); + if (null == rect) { + vc_print_log('[ERROR] Target element is not valid') + return [-1, 0, 0]; + } + + if (x < 0) { + x = 0; + } + if (y < 0) { + y = 0; + } + return [1, x / window.innerWidth, y / window.innerHeight]; + } catch (e) { + console.log(e); + return [-1, 0, 0]; + } +} + +/** + * vc_click function triggers click on element connected to cmd and param. Assumption is made that tooltips are numbers! + * + * @param cmd tooltip tag number from voice-control + * @param param text parameter from voice-control + */ +function vc_click(cmd, param) { + vc_print_log('== start click cmd = ' + cmd + ', param = ' + param + ', visible tags = ' + vc_visible_hints.length); + + if (vc_flag_log == true) { + if (vc_asr_result != undefined) { + vc_asr_result.innerHTML = param; + } + + setTimeout(function () { + if (vc_asr_result != undefined) { + vc_asr_result.parentElement.removeChild(vc_asr_result); + vc_asr_result = undefined; + } + if (vc_rec_result != undefined) { + vc_rec_result.parentElement.removeChild(vc_rec_result); + vc_rec_result = undefined; + } + }, 2500); + } + + /* pre-defined rule checker */ + if (vc_check_web_control(param) == true) { + vc_remove_hints(); + + return [0, 0, 0]; + } + + // if cmd has a numerical value + if (isNaN(cmd) == false) { + vc_print_log('== numbering tag click'); + + // when cmd is floating point value without parameter + // search exactly the same text + if (Number.isInteger(cmd) == false && param == '') { + for (var i = 0; i < vc_text_indicators.length; ++i) { + if (vc_text_indicators[i].textContent.trim().indexOf(cmd) != -1) { + return vc_do_action({ + elem : vc_text_indicators[i] + }); + } + } + + var list = vc_selector([cmd.toString()]); + + for (var i = 0; i < list.length; i++) { + if (list[i].childElementCount == 0 && list[i].textContent.trim().indexOf(cmd) != -1) { + return vc_do_action({ + elem : list[i] + }); + } + } + } + + // when cmd is valid integer value + if (Number.isInteger(cmd) == true && cmd <= vc_visible_hints.length) { + var hint = vc_visible_hints[cmd - 1]; + + // insert text into input element + if (hint.type === 'input' && param != '') { + return vc_do_action(hint, hint.span, param); + } else if (param == '') { + if (!vc_flag_conflict) { + vc_conflict_links = []; + vc_conflict_links.push(hint.elem); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + if (vc_text_indicators[i].textContent.trim() == cmd) { + vc_conflict_links.push(vc_text_indicators[i]); + } + } + + if (vc_conflict_links.length > 1) { + vc_remove_hints(); + vc_generate_conflict_hints(); + return [vc_conflict_links.length, 0, 0]; + } + } + + return vc_do_action(hint, hint.span); + } + } + + // when there is no matched tooltip + vc_remove_hints(); + + return vc_search_text(cmd.toString().concat(' ', param).trim()); + } else { + vc_remove_hints(); + + return vc_search_text(param); + } + + return [-1, 0, 0]; +} + +/** + * vc_search_text function search the element that include same text with @param. + * + * @param param param from voice-control. + */ +function vc_search_text(param) { + /* phase 1. search full text in the webpage */ + /* first, compare with links in html documents */ + vc_print_log('=== start searching(text level)'); + + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 200, 100, 1)'; + } + + vc_scr = { + top : 0, + left : 0, + bottom : window.innerHeight, + right : window.innerWidth + }; + + vc_conflict_links = []; + + for (var i = 0; i < vc_text_indicators.length; ++i) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && + vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase().indexOf(param.replace(/ /g, '').toLowerCase()) !== -1) { + vc_conflict_links.push(vc_text_indicators[i]); + } + } + + if (vc_conflict_links.length == 1) { + /* if there is one result */ + return vc_do_action({ + elem : vc_conflict_links[0] + }); + } else if (vc_conflict_links.length > 1) { + vc_generate_conflict_hints(); + + return [vc_conflict_links.length, 0, 0]; + } + + /* second, compare with whole text of elements in html documents */ + var resultTokenArr = param.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').split(' '), + el = vc_selector(resultTokenArr), + preStr = '******'; + + for (var i = 0; el.length > i; i++) { + var temp = el[i]; + + if (temp.childElementCount === 0) { + var curStr = temp.textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); + if (curStr == preStr || vc_is_visible(temp) == false) { + continue; + } + + preStr = curStr; + + vc_conflict_links.push(temp); + } + } + + if (vc_conflict_links.length == 1) { + return vc_do_action({ + elem : vc_conflict_links[0] + }); + } else if (vc_conflict_links.length > 1) { + vc_generate_conflict_hints(); + + return [vc_conflict_links.length, 0, 0]; + } else { + /* + * vc_search_word depend on the voice control language. + * This function increase the accuracy of the searching result using word and letter level searching. + * If the language is changed, the definition of the function will be changed by reloading the .js file. + */ + temp = vc_search_word(param, true); + if (temp != undefined) { + return vc_do_action({ + elem : temp + }); + } else { + //vc_show_popup('There is no such kind of string.
(' + param + ')', 1500); + vc_remove_hints(); + + return [-1, 0, 0]; + } + } +} + +/** + * vc_scroll_event_firing function move the scroll. + * + * @param evt keyword to move the scroll. + */ +function vc_scroll_event_firing(evt) { + if (evt == 'DOWN') { + window.scrollBy(0, 500); + } else if (evt == 'UP') { + window.scrollBy(0, -500); + } else if (evt == 'TOP') { + window.scrollTo(0, 0); + } +} + +/** + * vc_print_html function print out log on vc_log_area and console for debug. + * If vc_flag_log is not true, then the logs will only print on console. + * + * @param text log text to print out. + */ +function vc_print_log(text) { + var d = new Date(); + var time = d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds() + ':' + d.getMilliseconds(); + console.log(time, '[', vc_print_log.caller.name, ']', text); + + if (vc_flag_log == true) { + vc_log_area.value += time + ' [' + vc_print_log.caller.name + '] ' + text + '\n'; + } +} + +/** + * vc_print_html function print out raw source of the html document for debug. + */ +function vc_print_html() { + if (vc_html_area == undefined) { + vc_html_area = document.createElement('textarea'); + vc_html_area.disabled = true; + vc_html_area.id = 'vc_html_area'; + + document.body.appendChild(vc_html_area); + + vc_html_area.value = location.href.toString() + '\n' + document.querySelector('html').innerHTML; + } else { + document.body.removeChild(vc_html_area); + vc_html_area = undefined; + } +} + +/** + * vc_search_text function is called by voice-control-webview.cpp. + * this function call some group of functions refered to @phase. + * + * @param phase key value to call a group of functions. + * @param data function data from voice-control-webview.cpp. + */ +function vc_request_action(phase, data) { + vc_print_log('phase :' + phase + ',data :' + data); + if ('SHOW_TOOLTIP' == phase) { + clearTimeout(vc_conflict_timer); + + /* create & show tooltips to recognize the voice */ + if (!vc_flag_conflict && false == vc_flag_hint_exist) { + vc_remove_hints(); + vc_generate_hints(); + } + vc_show_hints(); + } else if ('HIDE_TOOLTIP' == phase) { + /* hide tooltips */ + if (!vc_flag_conflict) { + vc_hide_hints(); + } else { + clearTimeout(vc_conflict_timer); + vc_conflict_timer = setTimeout(vc_remove_hints, 5000); + } + } else if ('RESULT' == phase) { + /* do action by the result */ + vc_all_elem = document.querySelectorAll('body *:not(script)'); + var result = vc_correct_parameter(data); + + return vc_click(result.cmd, result.param); + } else if ('REMOVE_TOOLTIP' == phase) { + clearTimeout(vc_conflict_timer); + vc_remove_hints(); + } else { + return false; + } + return true; +} + +/** + * vc_selector function is a selector function to find the elements include whole text in @strArr. + * + * @param strArr group of strings to find elements. + * + * ex) vc_selector(['abc', 'def']); + */ +function vc_selector(strArr) { + var result = []; + for (var i = 0; i < vc_all_elem.length; i++) { + var temp = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + var j; + + for (j = 0; j < strArr.length; j++) { + if (temp.includes(strArr[j].toLowerCase()) == false) { + break; + } + } + + if (strArr.length == j && vc_is_visible(vc_all_elem[i], null, true)) { + result.push(vc_all_elem[i]); + } + } + + return result; +} + +/** + * vc_get_url_path function returns url path of the view. + * + * @return part of the url(host name + path name). it is used to read page specific script. + */ +function vc_get_url_path() { + var hostName = document.location.hostname; + var pathName = document.location.pathname; + + pathName = pathName.replace(/\//gi, '.'); + + return hostName + '/' + pathName; +} + +/** + * vc_get_conflict_status function returns the conflict status. + * + * @return 1 if vc_flag_conflict is true. Otherwise 0. + */ +function vc_get_conflict_status() { + if (vc_flag_conflict) { + return 1; + } + + return 0; +} + +/** + * vc_init function initialize some elements and styles to use voice control. + */ +function vc_init() { + /* log element initialize */ + if (vc_flag_log) { + vc_log_area.disabled = true; + vc_log_area.id = 'vc_log_area'; + vc_log_area.style.visibility = 'hidden'; + + document.body.appendChild(vc_log_area); + } + + /* add tooltip style element */ + var vc_style_node = document.createElement('style'); + var vc_style_text = document.createTextNode( + '#vc_tooltip_area {\ + left : 0px;\ + position : absolute;\ + pointer-events: none;\ + top : 0px;\ + z-index : 2147483647;\ + }\ + #vc_html_area, #vc_log_area {\ + background-color : rgba(0, 0, 0, 0.5) !important;\ + color : white !important;\ + font-size : 14px;\ + height : 600px;\ + left : 50px;\ + padding : 10px 10px 10px 10px;\ + position : fixed;\ + top : 50px;\ + width : 800px;\ + z-index : 2147483647;\ + }\ + #vc_popup_content {\ + background-color : #87cff7;\ + bottom : 0px;\ + border-radius : 20px;\ + box-shadow : 0 2px 6px rgba(0, 0, 0, 0.3), 0 3px 8px rgba(0, 0, 0, 0.2);\ + color : white;\ + display : table;\ + font-size : 1.5em;\ + height : 100px;\ + left : 0px;\ + line-height : 1.5em;\ + margin : auto;\ + opacity : 1;\ + overflow : hidden;\ + position : absolute;\ + right : 0px;\ + text-align : center;\ + top : 0px;\ + width : 500px;\ + z-index : 2147483647;\ + }\ + #vc_popup {\ + background-color : rgba(0,0,0,0.2);\ + bottom : 0px;\ + left : 0px;\ + position : fixed;\ + right : 0px;\ + top : 0px;\ + z-index : 2147483647;\ + }\ + #vc_highlight_area {\ + left : 0px;\ + position : absolute;\ + pointer-events: none;\ + top : 0px;\ + z-index : 2147483646;\ + }\ + #vc_highlight {\ + border-radius: 5px;\ + font-size : 20px;\ + padding : 0 3px;\ + position : absolute;\ + pointer-events: none;\ + word-break : normal;\ + background-color: rgba(0, 234, 255, 0.2);\ + }\ + #vc_click_effect {\ + border-radius: 70px;\ + width: 70px;\ + height: 70px;\ + pointer-events: none;\ + position: fixed;\ + z-index : 2147483647;\ + background: linear-gradient(141deg, rgba(15, 185, 175, 0.6) 0%, rgba(30, 200, 220, 0.6) 51%, rgba(45, 180, 230, 0.6) 75%);\ + }\ + .vc_number_tag_normal {\ + border : 2px solid;\ + border-color : rgba(255, 255, 255, 0);\ + border-radius : 5px;\ + box-shadow : 0px 2px 2px rgba(0, 0, 0, 0.3);\ + position: absolute;\ + pointer-events: none;\ + text-align: center;\ + font-family: "Samsung0ne600";\ + color: #ffffff;\ + z-index : 2147483647;\ + word-break : normal;\ + }\ + .vc_text_indicator_conflict_normal {\ + border: 2px solid;\ + border-color: rgba(255, 255, 255, 0);\ + border-radius: 20px;\ + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);\ + position: absolute;\ + pointer-events: none;\ + text-align: center;\ + color: #ffffff;\ + font-family: "Samsung0ne600";\ + z-index: 2147483647;\ + }\ + .vc_tooltip_focus {\ + border-color: rgba(255, 255, 255, 1);\ + }\ + .vc_text_focus {\ + color: #ff0000 !important;\ + font-weight: bolder !important;\ + }\ + #vc_asr_result {\ + background : rgba(0, 0, 0, 0.8);\ + border-radius : 20px;\ + color : white;\ + font-size : 25px;\ + height : 35px;\ + padding-top : 10px;\ + padding-bottom : 10px;\ + position : absolute;\ + text-align : center;\ + top : 10px;\ + right : 10px;\ + width : 550px;\ + z-index : 2147483647;\ + }\ + #vc_rec_result {\ + border-radius : 40px;\ + height : 40px;\ + position : absolute;\ + top : 17px;\ + right : 510px;\ + width : 40px;\ + z-index : 2147483647;\ + }\ + .vc_tooltip_input {\ + background-color : rgba(60, 140, 250, 0.75);\ + }\ + .vc_tooltip_normal, .vc_tooltip_area {\ + background-color : rgba(60, 185, 165, 0.75);\ + }\ + .vc_tip_tier_first {\ + font-size: 22px;\ + line-height: 24px;\ + width: 32px;\ + height: 26px;\ + }\ + .vc_tip_tier_second {\ + font-size: 19px;\ + line-height: 22px;\ + width: 28px;\ + height: 22px;\ + }\ + .vc_tip_tier_third {\ + font-size: 14px;\ + line-height: 16px;\ + width: 21px;\ + height: 16px;\ + }\ + @keyframes vc_tooltip_show {\ + 0% {\ + opacity: 0;\ + }\ + 100% {\ + opacity: 1;\ + }\ + }\ + @keyframes vc_tooltip_click {\ + 0% {\ + box-shadow: 0 0 8px 6px rgba(60, 220, 180, 0), 0 0 0px 0px rgba(255,255,255,1), 0 0 0px 0px rgba(60, 220, 180, 0);\ + }\ + 10% {\ + box-shadow: 0 0 8px 6px rgba(60, 220, 180, 1), 0 0 3px 5px rgba(255,255,255,1), 0 0 6px 10px rgba(60, 220, 180, 1);\ + }\ + 100% {\ + box-shadow: 0 0 8px 6px rgba(60, 220, 180, 0), 0 0 0px 20px rgba(255,255,255,0.5), 0 0 0px 20px rgba(60, 220, 180, 0);\ + }\ + }\ + @keyframes vc_click_effect {\ + 0% {\ + transform: scale(0.3, 0.3);\ + opacity: 0;\ + }\ + 10% {\ + transform: scale(0.5, 0.5);\ + opacity: 0.5;\ + }\ + 100% {\ + transform: scale(1, 1);\ + opacity: 1;\ + }\ + }'); + vc_style_node.appendChild(vc_style_text); + document.head.appendChild(vc_style_node); + + var frames = window.frames; + + for (var i = 0; i < frames.length; i++) { + try { + var doc = frames[i].document; + var vc_frame_style_node = doc.createElement('style'); + var vc_frame_style_text = doc.createTextNode(vc_style_node.textContent); + + vc_frame_style_node.appendChild(vc_frame_style_text); + doc.head.appendChild(vc_frame_style_node); + } catch (e) { + continue; + } + } + + /* remove indicators on scroll */ + window.addEventListener('scroll', function () { //[TODO] need to remove the listener + vc_remove_hints(); + }, false); +} + +vc_init(); \ No newline at end of file diff --git a/js_custom/www.youtube.com.js b/js_custom/www.youtube.com.js new file mode 100755 index 0000000..d953234 --- /dev/null +++ b/js_custom/www.youtube.com.js @@ -0,0 +1,20 @@ +function vc_custom_pre_generate_hints() { + var player = document.querySelector('#movie_player'); + if (player != null) { + player.classList.remove('ytp-autohide'); + } +} + +function vc_custom_pre_show_hints() { + var player = document.querySelector('#movie_player'); + if (player != null) { + player.classList.remove('ytp-autohide'); + } +} + +function vc_custom_pre_hide_hints() { + var player = document.querySelector('#movie_player'); + if (player != null) { + player.classList.add('ytp-autohide'); + } +} \ No newline at end of file diff --git a/js_custom/www.youtube.com.tv.js b/js_custom/www.youtube.com.tv.js new file mode 100755 index 0000000..2857d6c --- /dev/null +++ b/js_custom/www.youtube.com.tv.js @@ -0,0 +1,39 @@ +function vc_custom_pre_generate_hints() { + var player = document.querySelector('#transport-controls'); + if (player != null) { + player.classList.remove('hidden'); + } + player = document.querySelector('.pivot-shelf-list'); + if (player != null) { + player.classList.remove('hidden'); + player.classList.add('animate-in'); + } +} + +function vc_custom_pre_show_hints() { + var player = document.querySelector('#transport-controls'); + if (player != null) { + player.classList.remove('hidden'); + } + player = document.querySelector('.pivot-shelf-list'); + if (player != null) { + player.classList.remove('hidden'); + player.classList.add('animate-in'); + } +} + +function vc_custom_pre_hide_hints() { + var player = document.querySelector('#transport-controls'); + if (player != null) { + player.classList.add('hidden'); + } + player = document.querySelector('.pivot-shelf-list'); + if (player != null) { + player.classList.add('hidden'); + } +} + +vc_custom_add_xpath_query('video-thumb'); +vc_custom_add_xpath_query('collapsed-guide-icons'); +vc_custom_add_xpath_query('guide-button-icon'); +vc_custom_add_xpath_query('icon-player'); \ No newline at end of file diff --git a/js_custom/www.youtube.com.tv_kids.js b/js_custom/www.youtube.com.tv_kids.js new file mode 100755 index 0000000..c01ce8e --- /dev/null +++ b/js_custom/www.youtube.com.tv_kids.js @@ -0,0 +1,39 @@ +function vc_custom_pre_generate_hints() { + var player = document.querySelector('.transport-controls'); + if (player != null) { + player.classList.remove('hidden'); + player.classList.add('focused'); + } + player = document.querySelector('#pivot-list'); + if (player != null) { + player.classList.remove('hidden'); + } +} + +function vc_custom_pre_show_hints() { + var player = document.querySelector('.transport-controls'); + if (player != null) { + player.classList.remove('hidden'); + player.classList.add('focused'); + } + player = document.querySelector('#pivot-list'); + if (player != null) { + player.classList.remove('hidden'); + } +} + +function vc_custom_pre_hide_hints() { + var player = document.querySelector('.transport-controls'); + if (player != null) { + player.classList.add('hidden'); + player.classList.remove('focused'); + } + player = document.querySelector('#pivot-list'); + if (player != null) { + player.classList.add('hidden'); + } +} + +vc_custom_add_xpath_query('anchor-icon'); +vc_custom_add_xpath_query('icon'); +vc_custom_add_xpath_query('scale-cont'); \ No newline at end of file diff --git a/packaging/vc-webview-js.manifest b/packaging/vc-webview-js.manifest new file mode 100755 index 0000000..a76fdba --- /dev/null +++ b/packaging/vc-webview-js.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/vc-webview-js.spec b/packaging/vc-webview-js.spec new file mode 100755 index 0000000..1769cb4 --- /dev/null +++ b/packaging/vc-webview-js.spec @@ -0,0 +1,45 @@ +Name: vc-webview-js +Summary: Web voice touch javascript source +Version: 0.0.1 +Release: 1 +Group: Graphics & UI Framework/Voice Framework +License: Flora-1.1 +Source0: %{name}-%{version}.tar.gz +Source1001: %{name}.manifest +BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: cmake + +%description +Javascript source package to run web voice touch function on web application runtime + +%prep +%setup -q +cp %{SOURCE1001} . + +%build +export LDFLAGS+="-Wl,--rpath=%{_libdir} -Wl,--hash-style=both -Wl,--as-needed,-lgcov" +rm -rf objdir +mkdir objdir + +cd objdir && cmake .. -DVERSION=%{version} \ + -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DCMAKE_BUILD_TYPE=Debug \ + -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE + +cd objdir && make %{?jobs:-j%jobs} + +%install +(cd objdir && +%make_install) + +%clean +rm -rf %{buildroot} + +%post + +%files +%license LICENSE +%manifest %{name}.manifest +%defattr(-,root,root,-) +%{TZ_SYS_RO_SHARE}/voice/vc-webview/res/js/* +%{TZ_SYS_RO_SHARE}/voice/vc-webview/res/js_custom/* \ No newline at end of file -- 2.7.4 From 079e69b25c23f25fa6b90c640ba89b9f79832a81 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Tue, 11 Jul 2017 15:36:08 +0900 Subject: [PATCH 3/3] Add new language specified script Change-Id: Ia6890e4bf43e6006799de24454991378228c545d Signed-off-by: Suyeon Hwang (cherry picked from commit 7401faae6d3705d9c9542e6cb07d5454b0af9aa3) --- js/vc-webview-de_DE.js | 332 ++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-en_GB.js | 381 +++++++++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-en_US.js | 62 ++++++-- js/vc-webview-es_ES.js | 353 +++++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-es_US.js | 353 +++++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-fr_FR.js | 334 +++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-it_IT.js | 353 +++++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-ja_JP.js | 223 +++++++++++++++++++++++++++++ js/vc-webview-ko_KR.js | 10 +- js/vc-webview-pt_BR.js | 365 ++++++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-ru_RU.js | 334 +++++++++++++++++++++++++++++++++++++++++++ js/vc-webview-zh_CN.js | 217 ++++++++++++++++++++++++++++ js/vc-webview-zh_HK.js | 217 ++++++++++++++++++++++++++++ js/vc-webview-zh_SG.js | 217 ++++++++++++++++++++++++++++ js/vc-webview-zh_TW.js | 217 ++++++++++++++++++++++++++++ 15 files changed, 3955 insertions(+), 13 deletions(-) create mode 100755 js/vc-webview-de_DE.js create mode 100755 js/vc-webview-en_GB.js create mode 100755 js/vc-webview-es_ES.js create mode 100755 js/vc-webview-es_US.js create mode 100755 js/vc-webview-fr_FR.js create mode 100755 js/vc-webview-it_IT.js create mode 100755 js/vc-webview-ja_JP.js create mode 100755 js/vc-webview-pt_BR.js create mode 100755 js/vc-webview-ru_RU.js create mode 100755 js/vc-webview-zh_CN.js create mode 100755 js/vc-webview-zh_HK.js create mode 100755 js/vc-webview-zh_SG.js create mode 100755 js/vc-webview-zh_TW.js diff --git a/js/vc-webview-de_DE.js b/js/vc-webview-de_DE.js new file mode 100755 index 0000000..1a45ad5 --- /dev/null +++ b/js/vc-webview-de_DE.js @@ -0,0 +1,332 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-de_DE.js + * + * This source code is a language specified script for German(de_DE). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['ein', 'zwei', 'drei', 'vier', 'fünf', 'sechs', 'sieben', 'acht', 'neun', 'zehn', + 'elf', 'zwölf', 'dreizehn', 'vierzehn', 'fünfzehn', 'sechzehn', 'siebzehn', 'achtzehn', 'neunzehn', 'zwanzig', + 'einundzwanzig', 'zweiundzwanzig', 'dreiundzwanzig', 'vierundzwanzig', 'fünfundzwanzig', 'sechsundzwanzig', 'siebenundzwanzig', 'achtundzwanzig', 'neunundzwanzig', 'dreissig', + 'einunddreissig', 'zweiunddreissig', 'dreiunddreissig', 'vierunddreissig', 'fünfunddreissig', 'sechsunddreissig', 'siebenunddreissig', 'achtunddreissig', 'neununddreissig', 'vierzig', + 'einundvierzig', 'zweiundvierzig', 'dreiundvierzig', 'vierundvierzig', 'fünfundvierzig', 'sechsundvierzig', 'siebenundvierzig', 'achtundvierzig', 'neunundvierzig', 'fünfzig', + 'einundfünfzig', 'zweiundfünfzig', 'dreiundfünfzig', 'vierundfünfzig', 'fünfundfünfzig', 'sechsundfünfzig', 'siebenundfünfzig', 'achtundfünfzig', 'neunundfünfzig', 'sechzig', + 'einundsechzig', 'zweiundsechzig', 'dreiundsechzig', 'vierundsechzig', 'fünfundsechzig', 'sechsundsechzig', 'siebenundsechzig', 'achtundsechzig', 'neunundsechzig', 'siebzig', + 'einundsiebzig', 'zweiundsiebzig', 'dreiundsiebzig', 'vierundsiebzig', 'fünfundsiebzig', 'sechsundsiebzig', 'siebenundsiebzig', 'achtundsiebzig', 'neunundsiebzig', 'achtzig', + 'einundachtzig', 'zweiundachtzig', 'dreiundachtzig', 'vierundachtzig', 'fünfundachtzig', 'sechsundachtzig', 'siebenundachtzig', 'achtundachtzig', 'neunundachtzig', 'neunzig', + 'einundneunzig', 'zweiundneunzig', 'dreiundneunzig', 'vierundneunzig', 'fünfundneunzig', 'sechsundneunzig', 'siebenundneunzig', 'achtundneunzig', 'neunundneunzig', 'hundert']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'suchen google'; + var googleSearch2 = ['suchen', 'auf google']; + var youtubeSearch = 'suchen youtube'; + var youtubeSearch2 = ['suchen', 'auf youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'erfrischen' || convert == 'neuladen') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'runterscrollen') { + vc_scroll_event_firing('DOWN'); + } else if (convert == 'hochscrollen') { + vc_scroll_event_firing('UP'); + } else if (convert == 'quellcode') { + vc_print_html(); + } else if (convert == 'nächster' || convert == 'vorwärts') { + history.forward(); + } else if (convert == 'zuvor' || convert == 'zurück' || convert == 'früher') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-en_GB.js b/js/vc-webview-en_GB.js new file mode 100755 index 0000000..89a6d17 --- /dev/null +++ b/js/vc-webview-en_GB.js @@ -0,0 +1,381 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-en_GB.js + * + * This source code is a language specified script for English(en_GB). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', + 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', + 'twenty one', 'twenty two', 'twenty three', 'twenty four', 'twenty five', 'twenty six', 'twenty seven', 'twenty eight', 'twenty nine', 'thirty', + 'thirty one', 'thirty two', 'thirty three', 'thirty four', 'thirty five', 'thirty six', 'thirty seven', 'thirty eight', 'thirty nine', 'forty', + 'forty one', 'forty two', 'forty three', 'forty four', 'forty five', 'forty six', 'forty seven', 'forty eight', 'forty nine', 'fifty', + 'fifty one', 'fifty two', 'fifty three', 'fifty four', 'fifty five', 'fifty six', 'fifty seven', 'fifty eight', 'fifty nine', 'sixty', + 'sixty one', 'sixty two', 'sixty three', 'sixty four', 'sixty five', 'sixty six', 'sixty seven', 'sixty eight', 'sixty nine', 'seventy', + 'seventy one', 'seventy two', 'seventy three', 'seventy four', 'seventy five', 'seventy six', 'seventy seven', 'seventy eight', 'seventy nine', 'eighty', + 'eighty one', 'eighty two', 'eighty three', 'eighty four', 'eighty five', 'eighty six', 'eighty seven', 'eighty eight', 'eighty nine', 'ninety', + 'ninety one', 'ninety two', 'ninety three', 'ninety four', 'ninety five', 'ninety six', 'ninety seven', 'ninety eight', 'ninety nine', 'hundred']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + if (true == convert.startsWith('to') && (' ' == text[2] || text.length == 2)) { + if (vc_visible_hints[1].type == 'input' || text.length == 2) { + result = { + cmd : 2, + param : text.substr(3).trim() + }; + return result; + } + } else if (true == convert.startsWith('for') && (' ' == text[3] || text.length == 3)) { + if (vc_visible_hints[3].type == 'input' || text.length == 3) { + result = { + cmd : 4, + param : text.substr(4).trim() + }; + return result; + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + var idx_sep; + if (isNaN(result.cmd) == true) { + if (0 < (idx_sep = result.param.includes('st ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 3, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('nd ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 3, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('th ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 3, result.param.length); + } + } + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'search google'; + var googleSearch2 = ['search', 'on google']; + var youtubeSearch = 'search youtube'; + var youtubeSearch2 = ['search', 'on youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'refresh' || convert == 'reload') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'scrolldown') { + vc_scroll_event_firing('DOWN'); + } else if (convert == 'scrollup') { + vc_scroll_event_firing('UP'); + } else if (convert == 'tothetop') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'showsourcecode') { + vc_print_html(); + } else if (convert == 'next' || convert == 'forward') { + history.forward(); + } else if (convert == 'before' || convert == 'back' || convert == 'previous') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-en_US.js b/js/vc-webview-en_US.js index fe01a8b..40906a9 100755 --- a/js/vc-webview-en_US.js +++ b/js/vc-webview-en_US.js @@ -28,7 +28,7 @@ */ function vc_search_word(param, replace) { /* phase 2. search partial word in the webpage */ - /* second, compare with links in html documents */ + /* First, compare with links in html documents */ if (vc_flag_log == true) { vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; } @@ -63,7 +63,7 @@ function vc_search_word(param, replace) { return el; } - /* first, compare with whole text of elements in html documents */ + /* Second, compare with whole text of elements in html documents */ var result = []; for (var i = 0; i < resultTokenArr.length; i++) { var obj = vc_selector([resultTokenArr[i]]); @@ -225,7 +225,16 @@ function vc_search_pronunciation(param) { * @param text text string from voice-control-webview.cpp. */ function vc_is_included_number(text) { - var numbers = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; + var numbers = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', + 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', + 'twenty one', 'twenty two', 'twenty three', 'twenty four', 'twenty five', 'twenty six', 'twenty seven', 'twenty eight', 'twenty nine', 'thirty', + 'thirty one', 'thirty two', 'thirty three', 'thirty four', 'thirty five', 'thirty six', 'thirty seven', 'thirty eight', 'thirty nine', 'forty', + 'forty one', 'forty two', 'forty three', 'forty four', 'forty five', 'forty six', 'forty seven', 'forty eight', 'forty nine', 'fifty', + 'fifty one', 'fifty two', 'fifty three', 'fifty four', 'fifty five', 'fifty six', 'fifty seven', 'fifty eight', 'fifty nine', 'sixty', + 'sixty one', 'sixty two', 'sixty three', 'sixty four', 'sixty five', 'sixty six', 'sixty seven', 'sixty eight', 'sixty nine', 'seventy', + 'seventy one', 'seventy two', 'seventy three', 'seventy four', 'seventy five', 'seventy six', 'seventy seven', 'seventy eight', 'seventy nine', 'eighty', + 'eighty one', 'eighty two', 'eighty three', 'eighty four', 'eighty five', 'eighty six', 'eighty seven', 'eighty eight', 'eighty nine', 'ninety', + 'ninety one', 'ninety two', 'ninety three', 'ninety four', 'ninety five', 'ninety six', 'ninety seven', 'ninety eight', 'ninety nine', 'hundred']; var convert = text.toLowerCase(); var result; @@ -283,6 +292,35 @@ function vc_correct_parameter(text) { result.param = result.param.substr(words[0].length + 1).trim(); } + var idx_sep; + if (isNaN(result.cmd) == true) { + if (0 < (idx_sep = result.param.includes('st ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 3, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('nd ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 3, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('th ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 3, result.param.length); + } + } + } + return result } @@ -294,17 +332,25 @@ function vc_correct_parameter(text) { function vc_check_web_control(text) { text = text.toLowerCase(); var convert = text.replace(/ /g, ''); - var googleSearch = 'google search'; - var youtubeSearch = 'youtube search'; + var googleSearch = 'search google'; + var googleSearch2 = ['search', 'on google']; + var youtubeSearch = 'search youtube'; + var youtubeSearch2 = ['search', 'on youtube']; if (text.startsWith(googleSearch) == true) { - location.href = 'https://www.google.co.kr/search?q=' + (text.substr(googleSearch.length)).trim(); + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); } else if (text.startsWith(youtubeSearch) == true) { location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); - } else if (convert == 'refresh') { + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'refresh' || convert == 'reload') { location.reload(); } else if (convert == 'google') { - location.href = 'https://www.google.co.kr/'; + location.href = 'https://www.google.com/'; } else if (convert == 'facebook') { location.href = 'https://www.facebook.com/'; } else if (convert == 'amazon') { diff --git a/js/vc-webview-es_ES.js b/js/vc-webview-es_ES.js new file mode 100755 index 0000000..30ec0c9 --- /dev/null +++ b/js/vc-webview-es_ES.js @@ -0,0 +1,353 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-es_ES.js + * + * This source code is a language specified script for Spanish(es_ES). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['uno', 'dos', 'tres', 'cuatro', 'sinco', 'seis', 'siete', 'ocho', 'nueve', 'diez', + 'on ce', 'doce', 'trece', 'catorce', 'quince', 'dieciseis', 'diecisiete', 'dieciocho', 'diecinueve', 'veinte', + 'veinti uno', 'veinti dos', 'veinti tres', 'veinti cuatro', 'veinti sinco', 'veinti seis', 'veinti siete', 'veinti ocho', 'veinti nueve', 'treinta', + 'treinta y uno', 'treinta y dos', 'treinta y tres', 'treinta y cuatro', 'treinta y sinco', 'treinta y seis', 'treinta y siete', 'treinta y ocho', 'treinta y nueve', 'cuarenta', + 'cuarenta y uno', 'cuarenta y dos', 'cuarenta y tres', 'cuarenta y cuatro', 'cuarenta y sinco', 'cuarenta y seis', 'cuarenta y siete', 'cuarenta y ocho', 'cuarenta y nueve', 'cincuenta', + 'cincuenta y uno', 'cincuenta y dos', 'cincuenta y tres', 'cincuenta y cuatro', 'cincuenta y sinco', 'cincuenta y seis', 'cincuenta y siete', 'cincuenta y ocho', 'cincuenta y nueve', 'sesenta', + 'sesenta y uno', 'sesenta y dos', 'sesenta y tres', 'sesenta y cuatro', 'sesenta y sinco', 'sesenta y seis', 'sesenta y siete', 'sesenta y ocho', 'sesenta y nueve', 'setenta', + 'setenta y uno', 'setenta y dos', 'setenta y tres', 'setenta y cuatro', 'setenta y sinco', 'setenta y seis', 'setenta y siete', 'setenta y ocho', 'setenta y nueve', 'ochenta', + 'ochenta y uno', 'ochenta y dos', 'ochenta y tres', 'ochenta y cuatro', 'ochenta y sinco', 'ochenta y seis', 'ochenta y siete', 'ochenta y ocho', 'ochenta y nueve', 'noventa', + 'noventa y uno', 'noventa y dos', 'noventa y tres', 'noventa y cuatro', 'noventa y sinco', 'noventa y seis', 'noventa y siete', 'noventa y ocho', 'noventa y nueve', 'cien']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + var idx_sep; + if (0 < (idx_sep = result.param.includes('º ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('ª ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'busca no google'; + var googleSearch2 = ['buscar', 'en google']; + var youtubeSearch = 'busca no youtube'; + var youtubeSearch2 = ['buscar', 'en youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'refrescar') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'scrolldown') { + vc_scroll_event_firing('DOWN'); + } else if (convert == 'scrollup') { + vc_scroll_event_firing('UP'); + } else if (convert == 'iralacima') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'código fuente') { + vc_print_html(); + } else if (convert == 'siguiente' || convert == 'adelante') { + history.forward(); + } else if (convert == 'antes' || convert == 'espalda' || convert == 'previo' || convert == 'previa') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-es_US.js b/js/vc-webview-es_US.js new file mode 100755 index 0000000..e8a49a5 --- /dev/null +++ b/js/vc-webview-es_US.js @@ -0,0 +1,353 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-es_US.js + * + * This source code is a language specified script for Spanish(es_US). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['uno', 'dos', 'tres', 'cuatro', 'sinco', 'seis', 'siete', 'ocho', 'nueve', 'diez', + 'on ce', 'doce', 'trece', 'catorce', 'quince', 'dieciseis', 'diecisiete', 'dieciocho', 'diecinueve', 'veinte', + 'veinti uno', 'veinti dos', 'veinti tres', 'veinti cuatro', 'veinti sinco', 'veinti seis', 'veinti siete', 'veinti ocho', 'veinti nueve', 'treinta', + 'treinta y uno', 'treinta y dos', 'treinta y tres', 'treinta y cuatro', 'treinta y sinco', 'treinta y seis', 'treinta y siete', 'treinta y ocho', 'treinta y nueve', 'cuarenta', + 'cuarenta y uno', 'cuarenta y dos', 'cuarenta y tres', 'cuarenta y cuatro', 'cuarenta y sinco', 'cuarenta y seis', 'cuarenta y siete', 'cuarenta y ocho', 'cuarenta y nueve', 'cincuenta', + 'cincuenta y uno', 'cincuenta y dos', 'cincuenta y tres', 'cincuenta y cuatro', 'cincuenta y sinco', 'cincuenta y seis', 'cincuenta y siete', 'cincuenta y ocho', 'cincuenta y nueve', 'sesenta', + 'sesenta y uno', 'sesenta y dos', 'sesenta y tres', 'sesenta y cuatro', 'sesenta y sinco', 'sesenta y seis', 'sesenta y siete', 'sesenta y ocho', 'sesenta y nueve', 'setenta', + 'setenta y uno', 'setenta y dos', 'setenta y tres', 'setenta y cuatro', 'setenta y sinco', 'setenta y seis', 'setenta y siete', 'setenta y ocho', 'setenta y nueve', 'ochenta', + 'ochenta y uno', 'ochenta y dos', 'ochenta y tres', 'ochenta y cuatro', 'ochenta y sinco', 'ochenta y seis', 'ochenta y siete', 'ochenta y ocho', 'ochenta y nueve', 'noventa', + 'noventa y uno', 'noventa y dos', 'noventa y tres', 'noventa y cuatro', 'noventa y sinco', 'noventa y seis', 'noventa y siete', 'noventa y ocho', 'noventa y nueve', 'cien']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + var idx_sep; + if (0 < (idx_sep = result.param.includes('º ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('ª ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'busca no google'; + var googleSearch2 = ['buscar', 'en google']; + var youtubeSearch = 'busca no youtube'; + var youtubeSearch2 = ['buscar', 'en youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'refrescar') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'scrolldown') { + vc_scroll_event_firing('DOWN'); + } else if (convert == 'scrollup') { + vc_scroll_event_firing('UP'); + } else if (convert == 'iralacima') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'código fuente') { + vc_print_html(); + } else if (convert == 'siguiente' || convert == 'adelante') { + history.forward(); + } else if (convert == 'antes' || convert == 'espalda' || convert == 'previo' || convert == 'previa') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-fr_FR.js b/js/vc-webview-fr_FR.js new file mode 100755 index 0000000..8f6f210 --- /dev/null +++ b/js/vc-webview-fr_FR.js @@ -0,0 +1,334 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-fr_FR.js + * + * This source code is a language specified script for French(fr_FR). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf', 'dix', + 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf', 'vingt', + 'vingt et un', 'vingt-deux', 'vingt-trois', 'vingt-quatre', 'vingt-cinq', 'vingt-six', 'vingt-sept', 'vingt-huit', 'vingt-neuf', 'trente', + 'trente et un', 'trente-deux', 'trente-trois', 'trente-quatre', 'trente-cinq', 'trente-six', 'trente-sept', 'trente-huit', 'trente-neuf', 'quarante', + 'quarante et un', 'quarante-deux', 'quarante-trois', 'quarante-quatre', 'quarante-cinq', 'quarante-six', 'quarante-sept', 'quarante-huit', 'quarante-neuf', 'cinquante', + 'cinquante et un', 'cinquante-deux', 'cinquante-trois', 'cinquante-quatre', 'cinquante-cinq', 'cinquante-six', 'cinquante-sept', 'cinquante-huit', 'cinquante-neuf', + 'soixante', 'soixante et un', 'soixante-deux', 'soixante-trois', 'soixante-quatre', 'soixante-cinq', 'soixante-six', 'soixante-sept', 'soixante-huit', 'soixante-neuf', 'soixante-dix', + 'soixante et onze', 'soixante-douze', 'soixante-treize', 'soixante-quatorze', 'soixante-quinze', 'soixante-seize', 'soixante-dix-sept', 'soixante-dix-huit', 'soixante-dix-neuf','quatre-vingts', + 'quatre-vingt-un', 'quatre-vingt-deux', 'quatre-vingt-trois', 'quatre-vingt-quatre', 'quatre-vingt-cinq', 'quatre-vingt-six', 'quatre-vingt-sept', 'quatre-vingt-huit', 'quatre-vingt-neuf', 'quatre-vingt-dix', + 'quatre-vingt-onze', 'quatre-vingt-douze', 'quatre-vingt-treize', 'quatre-vingt-quatorze', 'quatre-vingt-quinze', 'quatre-vingt-seize', 'quatre-vingt-dix-sept', 'quatre-vingt-dix-huit', 'quatre-vingt-dix-neuf', 'cent']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'rechercher google'; + var googleSearch2 = ['rechercher', 'sur google']; + var youtubeSearch = 'rechercher youtube'; + var youtubeSearch2 = ['rechercher', 'sur youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'recharger' || convert == 'rafraîchir') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'scrolldown') { + vc_scroll_event_firing('DOWN'); + } else if (convert == 'scrollup') { + vc_scroll_event_firing('UP'); + } else if (convert == 'allerausommet') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'codesource') { + vc_print_html(); + } else if (convert == 'prochain' || convert == "vers l'avant") { + history.forward(); + } else if (convert == 'avant' || convert == 'arrière' || convert == 'précédent') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-it_IT.js b/js/vc-webview-it_IT.js new file mode 100755 index 0000000..ae7bb0f --- /dev/null +++ b/js/vc-webview-it_IT.js @@ -0,0 +1,353 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-it_IT.js + * + * This source code is a language specified script for Italian(it_IT). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto', 'nove', 'dieci', + 'undici', 'dodici', 'tredici', 'quattordici', 'quindici', 'sedici', 'diciasette', 'diciotto', 'diciannove', 'venti', + 'ventiuno', 'ventidue', 'ventitre', 'ventiquattro', 'venticinque', 'ventisei', 'ventisette', 'ventiotto', 'ventinove', 'trenta', + 'trentauno', 'trentadue', 'trentatre', 'trentaquattro', 'trentacinque', 'trentasei', 'trentasette', 'trentaotto', 'trentanove', 'quaranta', + 'quarantauno', 'quarantadue', 'quarantatre', 'quarantaquattro', 'quarantacinque', 'quarantasei', 'quarantasette', 'quarantaotto', 'quarantanove', 'cinquanta', + 'cinquantauno', 'cinquantadue', 'cinquantatre', 'cinquantaquattro', 'cinquantacinque', 'cinquantasei', 'cinquantasette', 'cinquantaotto', 'cinquantanove', 'sessanta', + 'sessantauno', 'sessantadue', 'sessantatre', 'sessantaquattro', 'sessantacinque', 'sessantasei', 'sessantasette', 'sessantaotto', 'sessantanove', 'settanta', + 'settantauno', 'settantadue', 'settantatre', 'settantaquattro', 'settantacinque', 'settantasei', 'settantasette', 'settantaotto', 'settantanove', 'ottanta', + 'ottantauno', 'ottantadue', 'ottantatre', 'ottantaquattro', 'ottantacinque', 'ottantasei', 'ottantasette', 'ottantaotto', 'ottantanove', 'novanta', + 'novantauno', 'novantadue', 'novantatre', 'novantaquattro', 'novantacinque', 'novantasei', 'novantasette', 'novantaotto', 'novantanove', 'cento',]; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + var idx_sep; + if (0 < (idx_sep = result.param.includes('º ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('ª ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'ricerca google'; + var googleSearch2 = ['ricerca', 'su google']; + var youtubeSearch = 'ricerca youtube'; + var youtubeSearch2 = ['ricerca', 'su youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'ricaricare') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'scorriversoilbasso') { + vc_scroll_event_firing('DOWN'); + } else if (convert == "scorriversol'alto") { + vc_scroll_event_firing('UP'); + } else if (convert == 'vaiincima') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'codicesorgente') { + vc_print_html(); + } else if (convert == 'prossimo' || convert == 'inoltrare') { + history.forward(); + } else if (convert == 'prima' || convert == 'indietro' || convert == 'precedente') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-ja_JP.js b/js/vc-webview-ja_JP.js new file mode 100755 index 0000000..68ffedf --- /dev/null +++ b/js/vc-webview-ja_JP.js @@ -0,0 +1,223 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-jp_JP.js + * + * This source code is a language specified script for Japanese(jp_JP). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.replace(/ /gi, ''); + var threshold = resultTokenArr.length * 0.6; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the character keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', + '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', + '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', + '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', + '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', + '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', + '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', + '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', + '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', + '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九', '百']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'google 検索'; + var youtubeSearch = 'youtube 検索'; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (convert == 'リフレッシュ') { + location.reload(); + } else if (convert == '下にスクロール') { + vc_scroll_event_firing('DOWN'); + } else if (convert == '上にスクロール') { + vc_scroll_event_firing('UP'); + } else if (convert == 'トップに行き') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'ソースコード') { + vc_print_html(); + } else if (convert == '次の' || convert == '前方に') { + history.forward(); + } else if (convert == '前に' || convert == 'バック' || convert == '前') { + history.back(); + } else if (convert == '記録' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-ko_KR.js b/js/vc-webview-ko_KR.js index 25c4cdd..eca5a93 100755 --- a/js/vc-webview-ko_KR.js +++ b/js/vc-webview-ko_KR.js @@ -29,7 +29,7 @@ */ function vc_search_word(param, replace) { /* phase 2. search partial word in the webpage */ - /* second, compare with links in html documents */ + /* First, compare with links in html documents */ if (vc_flag_log == true) { vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; } @@ -65,7 +65,7 @@ function vc_search_word(param, replace) { return el; } - /* first, compare with whole text of elements in html documents */ + /* Second, compare with whole text of elements in html documents */ var result = []; for (var i = 0; i < resultTokenArr.length; i++) { var obj = vc_selector([resultTokenArr[i]]); @@ -444,7 +444,7 @@ function vc_check_web_control(text) { var youtubeSearch2 = '유튜브 '; if (text.startsWith(googleSearch) == true) { - location.href = 'https://www.google.co.kr/search?q=' + (text.substr(googleSearch.length)).trim(); + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); } else if (text.startsWith(naverSearch) == true) { location.href = 'https://search.naver.com/search.naver?where=nexearch&query=' + (text.substr(naverSearch.length)).trim(); } else if (text.startsWith(youtubeSearch) == true) { @@ -452,13 +452,13 @@ function vc_check_web_control(text) { } else if (convert == '유튜브TV') { location.href = 'https://www.youtube.com/tv'; } else if (text.startsWith(googleSearch2) == true) { - location.href = 'https://www.google.co.kr/search?q=' + (text.substr(googleSearch2.length)).trim(); + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch2.length)).trim(); } else if (text.startsWith(naverSearch2) == true) { location.href = 'https://search.naver.com/search.naver?where=nexearch&query=' + (text.substr(naverSearch2.length)).trim(); } else if (text.startsWith(youtubeSearch2) == true) { location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch2.length)).trim(); } else if (convert.startsWith('구글') == true) { - location.href = 'https://www.google.co.kr/'; + location.href = 'https://www.google.com/'; } else if (convert.startsWith('네이버') == true) { location.href = 'http://www.naver.com/'; } else if (convert.startsWith('유튜브') == true) { diff --git a/js/vc-webview-pt_BR.js b/js/vc-webview-pt_BR.js new file mode 100755 index 0000000..0ff0ae8 --- /dev/null +++ b/js/vc-webview-pt_BR.js @@ -0,0 +1,365 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-pt_BR.js + * + * This source code is a language specified script for Portuguese(pt_BR). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = [['um', 'uma'], ['dois', 'duas'], 'três', 'quartro', 'cinco', 'seis', 'sete', 'oito', 'nove', 'dez', + 'onze', 'doze', 'treze', 'catorze', 'quinze', 'dezesseis', 'dezessete', 'dezeoito', 'dezenove', 'vinte', + ['vinte e um', 'vinte e uma'], ['vinte e dois', 'vinte e duas'], 'vinte e três', 'vinte e quartro', 'vinte e cinco', 'vinte e seis', 'vinte e sete', 'vinte e oito', 'vinte e nove', 'trinda', + ['trinda e um', 'trinda e uma'], ['trinda e dois', 'trinda e duas'], 'trinda e três', 'trinda e quartro', 'trinda e cinco', 'trinda e seis', 'trinda e sete', 'trinda e oito', 'trinda e nove', 'quarenta', + ['quarenta e um', 'quarenta e uma'], ['quarenta e dois', 'quarenta e duas'], 'quarenta e três', 'quarenta e quartro', 'quarenta e cinco', 'quarenta e seis', 'quarenta e sete', 'quarenta e oito', 'quarenta e nove', 'cinquenta', + ['cinquenta e um', 'cinquenta e uma'], ['cinquenta e dois', 'cinquenta e duas'], 'cinquenta e três', 'cinquenta e quartro', 'cinquenta e cinco', 'cinquenta e seis', 'cinquenta e sete', 'cinquenta e oito', 'cinquenta e nove', 'sessenta', + ['sessenta e um', 'sessenta e uma'], ['sessenta e dois', 'sessenta e duas'], 'sessenta e três', 'sessenta e quartro', 'sessenta e cinco', 'sessenta e seis', 'sessenta e sete', 'sessenta e oito', 'sessenta e nove', 'setenta', + ['setenta e um', 'setenta e uma'], ['setenta e dois', 'setenta e duas'], 'setenta e três', 'setenta e quartro', 'setenta e cinco', 'setenta e seis', 'setenta e sete', 'setenta e oito', 'setenta e nove', 'oitenta', + ['oitenta e um', 'oitenta e uma'], ['oitenta e dois', 'oitenta e duas'], 'oitenta e três', 'oitenta e quartro', 'oitenta e cinco', 'oitenta e seis', 'oitenta e sete', 'oitenta e oito', 'oitenta e nove', 'noventa', + ['noventa e um', 'noventa e uma'], ['noventa e dois', 'noventa e duas'], 'noventa e três', 'noventa e quartro', 'noventa e cinco', 'noventa e seis', 'noventa e sete', 'noventa e oito', 'noventa e nove', 'cem']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == Array.isArray(numbers[i])) { + for (var j = 0; numbers[i].length > j; j++) { + if (true == convert.startsWith(numbers[i][j]) && (' ' == text[numbers[i][j].length] || text.length == numbers[i][j].length)) { + var partial = text.substr(numbers[i][j].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i][j].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + } else { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + var idx_sep; + if (0 < (idx_sep = result.param.includes('º ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } else if (0 < (idx_sep = result.param.includes('ª ')) && !isNaN(result.param.substr(0, idx_sep))) { + if (idx_sep == result.param.length - 1) { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = ''; + } else { + result.cmd = parseFloat(result.param.substr(0, idx_sep)); + result.param = result.param.substr(idx_sep + 2, result.param.length); + } + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'busca no google'; + var googleSearch2 = ['pesquisa', 'no google']; + var youtubeSearch = 'busca no youtube'; + var youtubeSearch2 = ['pesquisa', 'no youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'recarregar' || convert == 'refrescar') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'iratéotopo') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'códigofonte') { + vc_print_html(); + } else if (convert == 'próximo') { + history.forward(); + } else if (convert == 'antesde' || convert == 'devolta' || convert == 'anterior') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-ru_RU.js b/js/vc-webview-ru_RU.js new file mode 100755 index 0000000..d95883b --- /dev/null +++ b/js/vc-webview-ru_RU.js @@ -0,0 +1,334 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-ru_RU.js + * + * This source code is a language specified script for Russian(ru_RU). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.split(' '); + var threshold = resultTokenArr.length * 0.3; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + if (el != undefined) { + return el; + } + + return vc_search_character(param); +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + vc_print_log('=== start searching(character level)'); + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(200, 100, 0, 1)'; + } + var similarity = []; + var threshold = 0; + + param = param.toLowerCase().split(' '); + for (var i = 0; i < vc_all_elem.length; i++) { + if (vc_all_elem[i].childElementCount == 0 && vc_is_visible(vc_all_elem[i]) == true) { + var text = vc_all_elem[i].textContent.replace(/[`~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ' ').toLowerCase().split(' '); + var score = 0; + + for(var k = 0; k < param.length; k++) { + var min = 2147483647; + + if (3 > param[k].length) { + continue; + } + + for(var j = 0; j < text.length; j++) { + if (3 > text[j].length) { + continue; + } + var cost = []; + var ncost = []; + var longStr; + var shortStr; + + if (text[j].length > param[k].length) { + longStr = text[j]; + shortStr = param[k]; + } else { + longStr = param[k]; + shortStr = text[j]; + } + + for (var l = 0; l <= longStr.length; l++) { + cost[l] = l; + } + + for (var s = 1; s <= shortStr.length; s++) { + ncost[0] = s; + + for (var l = 1; l <= longStr.length; l++) { + var match = shortStr[s - 1] == longStr[l - 1] ? 0 : 1; + + var rep = cost[l - 1] + match; + var ins = cost[l] + 1; + var del = ncost[l - 1] + 1; + + ncost[l] = Math.min(rep, ins, del); + } + + var arr = cost; + cost = ncost; + ncost = arr; + } + + if (param[k].length * 0.25 >= cost[longStr.length] && min > cost[longStr.length]) { + min = cost[longStr.length]; + } + } + + if (min < 2147483647) { + score = score + min; + } else { + score = score + param[k].length; + } + } + + similarity.push(score); + } else { + similarity.push(2147483647); + } + } + + vc_print_log('=== finish searching(character level)'); + + var min = 2147483647; + for (var i = 0; i < similarity.length; i++) { + if (min > similarity[i]) { + min = similarity[i]; + } + } + + for (var i = 0; i < param.length; i++) { + if (3 <= param[i].length) { + threshold = threshold + param[i].length; + } + } + + if (threshold > min) { + return vc_all_elem[similarity.indexOf(min)]; + } + + return undefined; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', + 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать', 'двадцать', + 'двадцать один', 'двадцать два', 'двадцать три', 'двадцать четыре', 'двадцать пять', 'двадцать шесть', 'двадцать семь', 'двадцать восемь', 'двадцать девять', 'тридцать', + 'тридцать один', 'тридцать два', 'тридцать три', 'тридцать четыре', 'тридцать пять', 'тридцать шесть', 'тридцать семь', 'тридцать восемь', 'тридцать девять', 'сорок', + 'сорок один', 'сорок два', 'сорок три', 'сорок четыре', 'сорок пять', 'сорок шесть', 'сорок семь', 'сорок восемь', 'сорок девять', 'пятьдесят', + 'пятьдесят один', 'пятьдесят два', 'пятьдесят три', 'пятьдесят четыре', 'пятьдесят пять', 'пятьдесят шесть', 'пятьдесят семь', 'пятьдесят восемь', 'пятьдесят девять', 'шестьдесят', + 'шестьдесят один', 'шестьдесят два', 'шестьдесят три', 'шестьдесят четыре', 'шестьдесят пять', 'шестьдесят шесть', 'шестьдесят семь', 'шестьдесят восемь', 'шестьдесят девять', 'семьдесят', + 'семьдесят один', 'семьдесят два', 'семьдесят три', 'семьдесят четыре', 'семьдесят пять', 'семьдесят шесть', 'семьдесят семь', 'семьдесят восемь', 'семьдесят девять', 'восемьдесят', + 'восемьдесят один', 'восемьдесят два', 'восемьдесят три', 'восемьдесят четыре', 'восемьдесят пять', 'восемьдесят шесть', 'восемьдесят семь', 'восемьдесят восемь', 'восемьдесят девять', 'девяносто', + 'девяносто один', 'девяносто два', 'девяносто три', 'девяносто четыре', 'девяносто пять', 'девяносто шесть', 'девяносто семь', 'девяносто восемь', 'девяносто девять', 'сто']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + var googleSearch = 'поиск в google'; + var googleSearch2 = ['поиска', 'в google']; + var youtubeSearch = 'поиск в youtube'; + var youtubeSearch2 = ['поиска', 'в youtube']; + + if (text.startsWith(googleSearch) == true) { + location.href = 'https://www.google.com/search?q=' + (text.substr(googleSearch.length)).trim(); + } else if (text.startsWith(googleSearch2[0]) && text.endsWith(googleSearch2[1])) { + var query = text.substr(googleSearch2[0].length, text.length - googleSearch2[0].length - googleSearch2[1].length); + location.href = 'https://www.google.com/search?q=' + query.trim(); + } else if (text.startsWith(youtubeSearch) == true) { + location.href = 'https://www.youtube.com/results?search_query=' + (text.substr(youtubeSearch.length)).trim(); + } else if (text.startsWith(youtubeSearch2[0]) && text.endsWith(youtubeSearch2[1])) { + var query = text.substr(youtubeSearch2[0].length, text.length - youtubeSearch2[0].length - youtubeSearch2[1].length); + location.href = 'https://www.youtube.com/results?search_query=' + query.trim(); + } else if (convert == 'обновите') { + location.reload(); + } else if (convert == 'google') { + location.href = 'https://www.google.com/'; + } else if (convert == 'facebook') { + location.href = 'https://www.facebook.com/'; + } else if (convert == 'amazon') { + location.href = 'https://www.amazon.com/'; + } else if (convert == 'yahoo') { + location.href = 'https://www.yahoo.com/'; + } else if (convert == 'youtube') { + location.href = 'https://www.youtube.com/'; + } else if (convert == 'scrolldown') { + vc_scroll_event_firing('DOWN'); + } else if (convert == 'scrollup') { + vc_scroll_event_firing('UP'); + } else if (convert == 'перейтикначалу') { + vc_scroll_event_firing('TOP'); + } else if (convert == 'исходныйкод') { + vc_print_html(); + } else if (convert == 'следующий' || convert == 'вперед') { + history.forward(); + } else if (convert == 'предыдущие') { + history.back(); + } else if (convert == 'playlog' && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-zh_CN.js b/js/vc-webview-zh_CN.js new file mode 100755 index 0000000..881703b --- /dev/null +++ b/js/vc-webview-zh_CN.js @@ -0,0 +1,217 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-zh_CN.js + * + * This source code is a language specified script for Chinese(zh_CN). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.replace(/ /gi, ''); + var threshold = resultTokenArr.length * 0.6; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the character keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', + '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', + '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', + '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', + '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', + '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', + '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', + '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', + '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', + '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九', '百']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + + if (convert == '刷新' || convert == '重新加载') { + location.reload(); + } else if (convert == '向下滚动' || convert == '向下滾動') { + vc_scroll_event_firing('DOWN'); + } else if (convert == '向上滚动' || convert == '向上滾動') { + vc_scroll_event_firing('UP'); + } else if (convert == '去顶部' || convert == '去頂部') { + vc_scroll_event_firing('TOP'); + } else if (convert == '源代碼' || convert == '源代码') { + vc_print_html(); + } else if (convert == '下一个' || convert == '下一個' || convert == '向前' || convert == '前进' || convert == '前進') { + history.forward(); + } else if (convert == '背部' || convert == '背部' || convert == '前' || convert == '以前') { + history.back(); + } else if ((convert == '记录' || convert == '記錄') && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-zh_HK.js b/js/vc-webview-zh_HK.js new file mode 100755 index 0000000..6afbd3b --- /dev/null +++ b/js/vc-webview-zh_HK.js @@ -0,0 +1,217 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-zh_HK.js + * + * This source code is a language specified script for Chinese(zh_HK). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.replace(/ /gi, ''); + var threshold = resultTokenArr.length * 0.6; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the character keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', + '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', + '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', + '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', + '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', + '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', + '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', + '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', + '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', + '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九', '百']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + + if (convert == '刷新' || convert == '重新加载') { + location.reload(); + } else if (convert == '向下滚动' || convert == '向下滾動') { + vc_scroll_event_firing('DOWN'); + } else if (convert == '向上滚动' || convert == '向上滾動') { + vc_scroll_event_firing('UP'); + } else if (convert == '去顶部' || convert == '去頂部') { + vc_scroll_event_firing('TOP'); + } else if (convert == '源代碼' || convert == '源代码') { + vc_print_html(); + } else if (convert == '下一个' || convert == '下一個' || convert == '向前' || convert == '前进' || convert == '前進') { + history.forward(); + } else if (convert == '背部' || convert == '背部' || convert == '前' || convert == '以前') { + history.back(); + } else if ((convert == '记录' || convert == '記錄') && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-zh_SG.js b/js/vc-webview-zh_SG.js new file mode 100755 index 0000000..ee4468d --- /dev/null +++ b/js/vc-webview-zh_SG.js @@ -0,0 +1,217 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-zh_SG.js + * + * This source code is a language specified script for Chinese(zh_SG). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.replace(/ /gi, ''); + var threshold = resultTokenArr.length * 0.6; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the character keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', + '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', + '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', + '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', + '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', + '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', + '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', + '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', + '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', + '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九', '百']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + + if (convert == '刷新' || convert == '重新加载') { + location.reload(); + } else if (convert == '向下滚动' || convert == '向下滾動') { + vc_scroll_event_firing('DOWN'); + } else if (convert == '向上滚动' || convert == '向上滾動') { + vc_scroll_event_firing('UP'); + } else if (convert == '去顶部' || convert == '去頂部') { + vc_scroll_event_firing('TOP'); + } else if (convert == '源代碼' || convert == '源代码') { + vc_print_html(); + } else if (convert == '下一个' || convert == '下一個' || convert == '向前' || convert == '前进' || convert == '前進') { + history.forward(); + } else if (convert == '背部' || convert == '背部' || convert == '前' || convert == '以前') { + history.back(); + } else if ((convert == '记录' || convert == '記錄') && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file diff --git a/js/vc-webview-zh_TW.js b/js/vc-webview-zh_TW.js new file mode 100755 index 0000000..5dd23a0 --- /dev/null +++ b/js/vc-webview-zh_TW.js @@ -0,0 +1,217 @@ +/** + * Copyright 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * vc-webview-zh_TW.js + * + * This source code is a language specified script for Chinese(zh_TW). + */ + +/** + * vc_search_word function found the text with similarity calculated using words in the @param. + * + * @param param param from voice-control. + * @param replace If replace true, function correct some confused charaters and try again. + */ +function vc_search_word(param, replace) { + /* phase 2. search partial word in the webpage */ + /* First, compare with links in html documents */ + if (vc_flag_log == true) { + vc_rec_result.style.background = 'rgba(0, 100, 200, 1)'; + } + var resultTokenArr = param.replace(/ /gi, ''); + var threshold = resultTokenArr.length * 0.6; + var temp = []; + var el = undefined; + + vc_print_log('=== start vc_search_word'); + + for (var i = 0; i < vc_text_indicators.length; ++i) { + var text = vc_text_indicators[i].textContent.replace(/[ `~!‘’@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').toLowerCase(); + temp[i] = 0; + + for (var j = 0; j < resultTokenArr.length; j++) { + if (vc_is_visible(vc_text_indicators[i], vc_scr, true) && text.indexOf(resultTokenArr[j].toLowerCase()) != -1) { + temp[i]++; + } + } + } + + var max = -1; + + for (var i = 0; i < vc_text_indicators.length; i++) { + if (temp[i] >= threshold && (max == -1 || temp[i] > temp[max])) { + el = vc_text_indicators[i]; + max = i; + } + } + + if (el != undefined) { + return el; + } + + /* Second, compare with whole text of elements in html documents */ + var result = []; + for (var i = 0; i < resultTokenArr.length; i++) { + var obj = vc_selector([resultTokenArr[i]]); + for (var j = 0; j < obj.length; j++) { + temp = obj[j]; + if (temp.childElementCount === 0) { + if (temp.hasAttribute('vc_count') == false) { + temp.setAttribute('vc_count', 1); + result.push(temp); + } else { + temp.setAttribute('vc_count', parseInt(temp.getAttribute('vc_count')) + 1); + } + } + } + } + + for (var i = 0; i < result.length; i++) { + var vccnt = parseInt(result[i].getAttribute('vc_count')); + if (vccnt >= threshold && (el == undefined || vccnt > parseInt(el.getAttribute('vc_count')))) { + el = result[i]; + } + } + + for (var i = 0; i < result.length; i++) { + result[i].removeAttribute('vc_count'); + } + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using characters in the @param. + * + * @param param param from voice-control. + */ +function vc_search_character(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the character keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_search_word function found the text with similarity calculated using pronunciation keys in the @param. + * + * @param param param from voice-control. + */ +function vc_search_pronunciation(param) { + var el = undefined; + + /* TODO: Fill the logic here to find the link or text include the pronunciation keys in param. + * If you find the link or text, then allocate that into el. + * If the language does not need to pronunciation comapring, you can erase this function. + */ + + return el; +} + +/** + * vc_is_included_number function separate a number value from the @text. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_is_included_number(text) { + var numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', + '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', + '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', + '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', + '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', + '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', + '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', + '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', + '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', + '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九', '百']; + var convert = text.toLowerCase(); + var result; + + for (var i = 0; numbers.length > i; i++) { + if (true == convert.startsWith(numbers[i]) && (' ' == text[numbers[i].length] || text.length == numbers[i].length)) { + var partial = text.substr(numbers[i].length); + + if (vc_visible_hints[i].type == 'input' || text.length == numbers[i].length) { + result = { + cmd : (i + 1), + param : partial.trim() + }; + return result; + } + } + } + + result = { + cmd : NaN, + param : text.trim() + }; + + return result; +} + +/** + * vc_correct_parameter function correct the voice recognition result. + * + * @param text text string from voice-control-webview.cpp. + */ +function vc_correct_parameter(text) { + var result = vc_is_included_number(text), + words = result.param.split(' '); + + if (isNaN(result.cmd) == true && isNaN(words[0]) == false) { + result.cmd = parseFloat(words[0]); + result.param = result.param.substr(words[0].length + 1).trim(); + } + + return result +} + +/** + * vc_check_web_control function check some special keyword and run it. + * + * @param spokenWord voice recognized result string. + */ +function vc_check_web_control(text) { + text = text.toLowerCase(); + var convert = text.replace(/ /g, ''); + + if (convert == '刷新' || convert == '重新加载') { + location.reload(); + } else if (convert == '向下滚动' || convert == '向下滾動') { + vc_scroll_event_firing('DOWN'); + } else if (convert == '向上滚动' || convert == '向上滾動') { + vc_scroll_event_firing('UP'); + } else if (convert == '去顶部' || convert == '去頂部') { + vc_scroll_event_firing('TOP'); + } else if (convert == '源代碼' || convert == '源代码') { + vc_print_html(); + } else if (convert == '下一个' || convert == '下一個' || convert == '向前' || convert == '前进' || convert == '前進') { + history.forward(); + } else if (convert == '背部' || convert == '背部' || convert == '前' || convert == '以前') { + history.back(); + } else if ((convert == '记录' || convert == '記錄') && vc_flag_log) { + if (vc_log_area.style.visibility == 'visible') vc_log_area.style.visibility = 'hidden'; + else vc_log_area.style.visibility = 'visible'; + } else { + return false; + } + return true; +} \ No newline at end of file -- 2.7.4