Init version 49/114749/10 accepted/tizen/4.0/unified/20170816.011931 accepted/tizen/4.0/unified/20170829.015827 accepted/tizen/unified/20170429.023936 submit/tizen/20170428.060545 submit/tizen_4.0/20170811.094300 submit/tizen_4.0/20170828.100004 tizen_4.0.IoT.p1_release tizen_4.0.m1_release tizen_4.0.m2_release
authorWonnam Jang <wn.jang@samsung.com>
Wed, 15 Feb 2017 02:26:12 +0000 (11:26 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Thu, 27 Apr 2017 06:31:45 +0000 (15:31 +0900)
Change-Id: Ia882e01e6283761b018a5b104653d2f44bc4f746
Signed-off-by: Wonnam Jang <wn.jang@samsung.com>
12 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0755]
LICENSE [new file with mode: 0644]
NOTICE [new file with mode: 0644]
js/vc-webview-en_US.js [new file with mode: 0755]
js/vc-webview-ko_KR.js [new file with mode: 0755]
js/vc-webview.js [new file with mode: 0755]
js_custom/www.youtube.com.js [new file with mode: 0755]
js_custom/www.youtube.com.tv.js [new file with mode: 0755]
js_custom/www.youtube.com.tv_kids.js [new file with mode: 0755]
packaging/vc-webview-js.manifest [new file with mode: 0755]
packaging/vc-webview-js.spec [new file with mode: 0755]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..b5fa653
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+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
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..6887347
--- /dev/null
@@ -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 (file)
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 (file)
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 (executable)
index 0000000..fe01a8b
--- /dev/null
@@ -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 (executable)
index 0000000..25c4cdd
--- /dev/null
@@ -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 (executable)
index 0000000..8c785df
--- /dev/null
@@ -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.<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
diff --git a/js_custom/www.youtube.com.js b/js_custom/www.youtube.com.js
new file mode 100755 (executable)
index 0000000..d953234
--- /dev/null
@@ -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 (executable)
index 0000000..2857d6c
--- /dev/null
@@ -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 (executable)
index 0000000..c01ce8e
--- /dev/null
@@ -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 (executable)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/packaging/vc-webview-js.spec b/packaging/vc-webview-js.spec
new file mode 100755 (executable)
index 0000000..1769cb4
--- /dev/null
@@ -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