--- /dev/null
+Wonnam Jang <wn.jang@samsung.com>
+Kwangyoun Kim <ky85.kim@samsung.com>
+Sooyeon Kim <sooyeon.kim@samsung.com>
+Suyeon Hwang <stom.hwang@samsung.com>
\ No newline at end of file
--- /dev/null
+# 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
--- /dev/null
+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.
+
--- /dev/null
+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
--- /dev/null
+/**
+ * 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
--- /dev/null
+/**
+ * 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
--- /dev/null
+/**
+ * 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.<br>(' + 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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
--- /dev/null
+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