How to read a Javascript file - javascript

I have a file a /path/to/my_js_functions.js that contains a Javascript function my_js_functions(), amongst other functions.
How can I go about reading the function myJsFunction as a String in C++?
I am looking for a way to get the whole function and only that function, and then contain it in a char *jsFunction.
function myJsFunction(stringParam) {
return stringParam // The function returns a stringParam from the parameter
}
function anotherJsFunction(stringParam) {
return stringParam // Another function
}
Thank you all in advance.

Using fstream, I would read line by line and check whether each line contains the sequence myJsFunction. If a line does contain this sequence, then you begin aggregating to a string until you reach the next function (stopping after you reach the next keyword "function" or something of that sort). Note that using } as a keyword may not work as functions are likely to have multiple closing braces.
Another possible solution could include identifying the end of the function by noticing that when a newline is immediately followed by non-whitespace a new function is beginning, assuming the code in your file is formatted where anything lower in scope is tabbed over correctly.

To do this you need to read your javascript code file and parse it. It is highly to use some parser library to do that like cashew,esprima-cpp. I never used that before I never used any of this before, So I can't comment on that.
But here is some quick code for parser. You can start with this build on this to make it more robust.
main.cpp
#include <fstream>
#include <iostream>
#include <streambuf>
#include <string>
#include <vector>
std::string getFunction(const std::string &fileData, const std::string &name) {
std::string ret;
std::size_t start = 0;
while (true) {
const auto fNameStart = fileData.find(name, start);
if (fNameStart != std::string::npos) {
auto fStart = fileData.find_last_not_of(" ",fNameStart-1);
if(fStart == std::string::npos){
ret = "No Function Defination";
break;
}
else {
fStart = fStart-7;
if(fileData.substr(fStart,8) == "function"){
int openBraceCount = 0, closeBraceCount = 0;
std::size_t fEnd = fNameStart + name.size();
fEnd = fileData.find_first_of("{}", fEnd);
while (fEnd != std::string::npos) {
if (fileData.at(fEnd) == '{') {
openBraceCount++;
} else {
closeBraceCount++;
}
if (openBraceCount == closeBraceCount) {
ret = fileData.substr(fStart, fEnd - fStart+1);
break;
}
fEnd++;
fEnd = fileData.find_first_of("{}", fEnd);
}
if(!ret.empty()){
break;
}
else if(openBraceCount != closeBraceCount){
ret = "Function Parse Error";
break;
}
}
else{
start = fNameStart + name.size();
}
}
} else {
ret = "No Function Defination";
break;
}
}
return ret;
}
int main(int argc, char **argv) {
const std::string jsPath = "module.js";
const std::vector<std::string> vecFuncNames{"funcA", "funcB", "funcC",
"funcD", "funcE"};
std::ifstream fs(jsPath);
if (fs.is_open()) {
std::string fileData((std::istreambuf_iterator<char>(fs)),
std::istreambuf_iterator<char>());
for (auto &name : vecFuncNames) {
std::cout << name << "\n" << getFunction(fileData, name) << std::endl;
}
}
return 0;
}
module.js
function funcA ( ){
funcC(); console.log(" Hello");funcB();
}function funcC(){funcB();console.log("Hello");funcA();}
function funcB(a, b, c){
funcA(); setTimeout(function(){ alert("Hello"); }, 3000);funcC();
}
funcD();
function funcE(){{{{}}}

You can simply doing this
For example /path/code.js is the path your code stored
Your code.js
function myJsFunction(stringParam) {
return stringParam // The function returns a stringParam from the parameter
}
function anotherJsFunction(stringParam) {
return stringParam // Another function
}
module.exports = {
myJsFunction,
anotherJsFunction
}
And this is the file that you use to read the function you write
index.js
const code = require('/path/code.js');
console.log(code), it will be showing your whole code in your code.js file
If you want to make it string, you can use syntax like this. Add this in code below on your index.js file and it will make string version of your code.
String(code.myJsFunction)

Related

Converting a JavaScript code using callbacks and RegEx method to equivalent code in C#

I've the below JavaScript code, that returned a function callback related to the user command, the user command could be used in different ways, hence RegEx is required:
(function (undefined) {
"use strict";
var root = this;
var commandsList = [];
var debugStyle = 'font-weight: bold; color: #00f;';
// The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license.
var optionalParam = /\s*\((.*?)\)\s*/g;
var optionalRegex = /(\(\?:[^)]+\))\?/g;
var namedParam = /(\(\?)?:\w+/g;
var splatParam = /\*\w+/g;
var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#]/g;
var commandToRegExp = function(command) {
command = command.replace(escapeRegExp, '\\$&')
.replace(optionalParam, '(?:$1)?')
.replace(namedParam, function(match, optional) {
return optional ? match : '([^\\s]+)';
})
.replace(splatParam, '(.*?)')
.replace(optionalRegex, '\\s*$1?\\s*');
return new RegExp('^' + command + '$', 'i');
};
var registerCommand = function(command, cb, phrase) {
commandsList.push({ command: command, callback: cb, originalPhrase: phrase });
root.console.log('Command successfully loaded: %c'+phrase, debugStyle);
};
root.fonixListen = {
addCommands: function(commands) {
var cb;
for (var phrase in commands) {
if (commands.hasOwnProperty(phrase)) {
cb = root[commands[phrase]] || commands[phrase];
if (typeof cb === 'function') {
// convert command to regex then register the command
registerCommand(commandToRegExp(phrase), cb, phrase);
} else if (typeof cb === 'object' && cb.regexp instanceof RegExp) {
// register the command
registerCommand(new RegExp(cb.regexp.source, 'i'), cb.callback, phrase);
}
}
}
},
executeCommand: function(commandText) {
for (var j = 0, l = commandsList.length; j < l; j++) {
var result = commandsList[j].command.exec(commandText);
if (result) {
var parameters = result.slice(1);
// execute the matched command
commandsList[j].callback.apply(this, parameters);
return true;
}
}
}
};
}).call(this)
Below are some commands:
var commands = {
'hello :name *term': function(name) {
alert('hello '+name+''); // i.e. consider *term as optional input
},
'items identification': {
'regexp': /^(What is|What's|Could you please tell me|Could you please give me) the meaning of (TF|FFS|SF|SHF|FF|Tube Film|Shrink Film|Stretch Hood|Stretch Hood Film|Flat Film)$/,
'callback': itemsIdentification,
},
'ML SoH': {
'regexp': /^(What is|What's|Could you please tell me|Could you please give me) the (stock|inventory) of ML$/,
'callback': mlSOH,
},
'Report stock on hand': {
'regexp': /^(What is|What's) (our|the) (stock|inventory|SoH) of (TF|FFS|SF|SHF|FF|Tube Film|Shrink Film|Stretch Hood|Stretch Hood Film|Flat Film)$/,
'callback': SoH,
},
'Basic Mathematical Opertions': {
// ?\s? can be used instead of space, also could use /i instead of $/,
'regexp': /^(What is|What's|Calculate|How much is) ([\w.]+) (\+|and|plus|\-|less|minus|\*|\x|by|multiplied by|\/|over|divided by) ([\w.]+)$/,
'callback': math,
},
};
At running the app, the addCommands command is executed, and based on the input command from the user, the executeCommand command is executed.
The above works very fine with me, but I'm moving to C#, and very new to it, so looking for help, at least guiding of some functionalities and tools in C# that can help me write something similar to the above.
UPDATE
More details about what I try to do, actually I've a form, where the user input his command by voice using HTL5 voice API, the API convert this voice into text, then this text i submitted to my app, where my app work start by looking into this text, trying to find the required command using the ReqEx, then execute the programmed function/callback that is mapped with this input command.
I found the solution using Dictionary at using System.Collections.Generic; and using RegEx at using System.Text.RegularExpressions; along with the need of a function called FirstOrDefault availabe at using System.Linq;
I used Action instead of function Func as the callbacks in my case are do not return anything, i.e. they are a void functions, and because no input parameters provided, I used Action-delegate, and did not use Action<string[]>.
The working code is:
using System;
using System.Collections.Generic; // for Dictionary
using System.Linq; // for FirstOrDefault
using System.Text.RegularExpressions; // for RegEx
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var input = "What's the meaning of Stretch Hood";
var functions = new Dictionary<Regex, Action>
{
{new Regex("/^(What is|What's|Could you please tell me|Could you please give me) the meaning of (TF|FFS|SF|SHF|FF|Tube Film|Shrink Film|Stretch Hood|Stretch Hood Film|Flat Film)$/"),
itemsIdentification},
{new Regex("/^(What is|What's|Could you please tell me|Could you please give me) the (stock|inventory) of ML$/"),
mlSOH},
{new Regex("/^(What is|What's) (our|the) (stock|inventory|SoH) of (TF|FFS|SF|SHF|FF|Tube Film|Shrink Film|Stretch Hood|Stretch Hood Film|Flat Film)$/"),
SoH},
{new Regex("/^(What is|What's|Calculate|How much is) ([\w.]+) (\+|and|plus|\-|less|minus|\*|\x|by|multiplied by|\/|over|divided by) ([\w.]+)$/"),
math},
};
functions.FirstOrDefault(f => f.Key.IsMatch(input)).Value?.Invoke(); // This will execute the first Action found wherever the input matching the RegEx, the ?. means if not null ([Null-conditional Operators][1])
// or
Action action;
action = functions.FirstOrDefault(f => f.Key.IsMatch(input)).Value;
if (action != null)
{
action.Invoke();
}
else
{
// No function with that name
}
}
public static void itemsIdentification()
{
Console.WriteLine("Fn 1");
}
public static void mlSOH()
{
Console.WriteLine("Fn 2");
}
public static void SoH()
{
}
public static void math()
{
}
}
}

Providing stdin to an emscripten HTML program?

I have a C program that takes one argument (a char array / string) via command line and also reads from stdin. I've compiled it to JavaScript using emscripten. This was successful and I can run it just like the normal C program using node.js:
emcc -O2 translate.c
node translate.js "foo" < bar.txt
As you can see, I'm providing the string "foo" as an argument and the contents of bar.txt as stdin. Now I want this to be a self-contained HTML file.
By changing the output to HTML:
emcc -O2 translate.c -o trans.html
I provide the argument by adding arguments: ['foo'], to the definitions in var Module. This works as expected, the program receives the argument correctly.
Now, how do I provide the stdin input to this program? I don't need to do this dynamically. It would be fine to just declare a string somewhere in the HTML with the required stdin content.
A way would be to use the Emscripten Filesystem API, for example by calling FS.init in the Module preRun function, passing custom functions to be used for standard input, output and error.
var Module = {
preRun: function() {
function stdin() {
// Return ASCII code of character, or null if no input
}
function stdout(asciiCode) {
// Do something with the asciiCode
}
function stderr(asciiCode) {
// Do something with the asciiCode
}
FS.init(stdin, stdout, stderr);
}
};
The functions are quite low-level: they each deal with one character at a time as an ASCII code. If you have strings you want to pass in, you would have to iterate over the characters of the string yourself. I suspect charCodeAt would be helpful. To output strings from stdout or stderr, then I suspect fromCharCode would be helpful.
Example (not very well tested!) implementations using each are below.
var input = "This is from the standard input\n";
var i = 0;
var Module = {
preRun: function() {
function stdin() {
if (i < res.length) {
var code = input.charCodeAt(i);
++i;
return code;
} else {
return null;
}
}
var stdoutBuffer = "";
function stdout(code) {
if (code === "\n".charCodeAt(0) && stdoutBuffer !== "") {
console.log(stdoutBuffer);
stdoutBuffer = "";
} else {
stdoutBuffer += String.fromCharCode(code);
}
}
var stderrBuffer = "";
function stderr(code) {
if (code === "\n".charCodeAt(0) && stderrBuffer !== "") {
console.log(stderrBuffer);
stderrBuffer = "";
} else {
stderrBuffer += String.fromCharCode(code);
}
}
FS.init(stdin, stdout, stderr);
}
};
Rather than editing the output of Emscripten, you could monkey patch the Window object
window.prompt = function() {
return 'This will appear to come from standard input';
};
Not wonderful, but I would deem this less of a hack than editing the Emscripten-generated Javascript.
According the question "Edit" , I made my function , thx a lot.
Just hope the code below can help someone else.
comment run(); in the end of emscript
// in my emscript
// shouldRunNow refers to calling main(), not run().
var shouldRunNow = true;
if (Module['noInitialRun']) {
shouldRunNow = false;
}
//run(); // << here
// {{POST_RUN_ADDITIONS}}
result = areaInput(); // As the question mentioned
add the code below in your html file to activate run() in emscript
<script>
var message;
var point = -1;
function getArea(){
message = document.getElementById('input').value.split('\n');
}
function areaInput(){
if(point >= message.length - 1){
return null;
}
point += 1;
return message[point];
}
function execEmscript(){
window.console = {
log: function(str){
document.getElementById("output").value += "\n" + str;
}
}
getArea();
run();
}
</script>
remember io textareas in your html
<textarea id="input" cols="80" rows="30"></textarea>
<textarea id="output" cols="80" rows="30"></textarea>
and a button
<button onclick="execEmscript();">run</button>

V8: Fatal error: CHECK(V8::ArrayBufferAllocator() != NULL) failed

I get this error when I try to run some JS code (this + this) with V8 (tried master from two weaks ago, 3.23.17, 3.24.40, 3.25.5; 3.23.0 doesn't work anymore because of API changes):
#
# Fatal error in ..\..\src\runtime.cc, line 785
# CHECK(V8::ArrayBufferAllocator() != NULL) failed
#
A lot of other JS code has worked already, so I wonder what the problem is.
It's on Win8 with a x64 build. V8 has been build just as described in the official docs (using gyp + MSVC 2012). I don't think that there was a problem because it worked fine already with most other JS code.
I think that there might be an issue with V8 itself, but not sure...
I also asked on the mailing-list here.
Some C++ code, but I don't think that there is a problem with it because it worked fine with other JS code:
#include <string>
#include <assert.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <boost/noncopyable.hpp>
#include <v8.h>
// Create a new isolate (completely isolated JS VM).
struct V8Isolate : boost::noncopyable {
v8::Isolate* isolate;
V8Isolate() : isolate(v8::Isolate::New()) {}
~V8Isolate() { isolate->Dispose(); }
operator v8::Isolate*() { return isolate; }
v8::Isolate* operator->() { return isolate; }
};
struct ReturnType {
std::string err; // non-empty if there is an error
ReturnType(bool success) {
assert(success);
}
ReturnType(const std::string& _err) : err(_err) {
assert(!err.empty());
}
ReturnType(const char* _err) : err(_err) {
assert(!err.empty());
}
operator bool() const { return err.empty(); }
};
#define CHECK_RETURN(cmd) { ReturnType ret = (cmd); if(!ret) return ret; }
using namespace std;
using namespace v8;
ReturnType readFile(const std::string& filename, std::string& res) {
res = "";
FILE* f = fopen(filename.c_str(), "r");
if(!f) return "File '" + filename + "' cannot be opened";
while(!feof(f) && !ferror(f)) {
char buffer[1024 * 8];
size_t s = fread(buffer, 1, sizeof(buffer), f);
if(s > 0)
res.append(buffer, buffer + s);
}
auto err = ferror(f);
fclose(f);
if(err)
return "Error while reading file '" + filename + "'";
return true;
}
ReturnType execJsFile(const std::string& jsSourceDir, const std::string& extfilename) {
v8::TryCatch try_catch;
std::string sourceStr;
CHECK_RETURN(readFile(jsSourceDir + "/" + extfilename, sourceStr));
Local<String> origin = String::NewFromUtf8(Isolate::GetCurrent(), &extfilename[0], String::kNormalString, (int)extfilename.size());
Local<String> source = String::NewFromUtf8(Isolate::GetCurrent(), &sourceStr[0], String::kNormalString, (int)sourceStr.size());
Local<v8::Script> script = Script::Compile(source, origin);
if(script.IsEmpty()) {
assert(try_catch.HasCaught());
return "JS compile failed: " + jsObjToString(try_catch.Exception());
}
// Run the script to setup its environment
Local<Value> result = script->Run();
if(result.IsEmpty()) {
assert(try_catch.HasCaught());
return "JS script execution failed: " + jsReportExceptionToString(Isolate::GetCurrent(), &try_catch);
}
return true;
}
ReturnType loadJsGit() {
V8Isolate isolate;
v8::Isolate::Scope isolateScope(isolate);
HandleScope handleScope(isolate);
Handle<Context> context = Context::New(isolate);
Context::Scope contextScope(context);
auto globalObj = context->Global();
CHECK_RETURN(execJsFile(".", "global.js"));
CHECK_RETURN(execJsFile(".", "jsgit.js"));
return true;
}
int main(int argc, char** argv) {
ReturnType ret = loadJsGit();
if(!ret) cout << "error: " << ret.err << endl;
}
You need to initialize array buffer allocator.
Use malloc, for example:
class MallocArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
public:
virtual void* Allocate(size_t length) { return malloc(length); }
virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
virtual void Free(void* data, size_t length) { free(data); }
};
Initialize:
v8::V8::SetArrayBufferAllocator(new MallocArrayBufferAllocator);

Uglify JS - compressing unused variables

Uglify has a "compression" option that can remove unused variables...
However, if I stored some functions in an object like this....
helpers = {
doSomething: function () { ... },
doSomethingElese: function () { ... }
}
... is there a way to remove helpers.doSomething() if it's never accessed?
Guess I want to give the compressor permission to change my object.
Any ideas if it's possible? Or any other tools that can help?
Using a static analyzer like Uglify2 or Esprima to accomplish this task is somewhat nontrivial, because there are lots of situations that will call a function that are difficult to determine. To show the complexity, there's this website:
http://sevinf.github.io/blog/2012/09/29/esprima-tutorial/
Which attempts to at least identify unused functions. However the code as provided on that website will not work against your example because it is looking for FunctionDeclarations and not FunctionExpressions. It is also looking for CallExpression's as Identifiers while ignoring CallExpression's that are MemberExpression's as your example uses. There's also a problem of scope there, it doesn't take into account functions in different scopes with the same name - perfectly legal Javascript, but you lose fidelity using that code as it'll miss some unused functions thinking they were called when they were not.
To handle the scope problem, you might be able to employ ESTR (https://github.com/clausreinke/estr), to help figure out the scope of the variables and from there the unused functions. Then you'll need to use something like escodegen to remove the unused functions.
As a starting point for you I've adapted the code on that website to work for your very specific situation provided, but be forwarned, it will have scope issue.
This is written for Node.js, so you'll need to get esprima with npm to use the example as provided, and of course execute it with node.
var fs = require('fs');
var esprima = require('esprima');
if (process.argv.length < 3) {
console.log('Usage: node ' + process.argv[1] + ' <filename>');
process.exit(1);
}
notifydeadcode = function(data){
function traverse(node, func) {
func(node);
for (var key in node) {
if (node.hasOwnProperty(key)) {
var child = node[key];
if (typeof child === 'object' && child !== null) {
if (Array.isArray(child)) {
child.forEach(function(node) {
traverse(node, func);
});
} else {
traverse(child, func);
}
}
}
}
}
function analyzeCode(code) {
var ast = esprima.parse(code);
var functionsStats = {};
var addStatsEntry = function(funcName) {
if (!functionsStats[funcName]) {
functionsStats[funcName] = {calls: 0, declarations:0};
}
};
var pnode = null;
traverse(ast, function(node) {
if (node.type === 'FunctionExpression') {
if(pnode.type == 'Identifier'){
var expr = pnode.name;
addStatsEntry(expr);
functionsStats[expr].declarations++;
}
} else if (node.type === 'FunctionDeclaration') {
addStatsEntry(node.id.name);
functionsStats[node.id.name].declarations++;
} else if (node.type === 'CallExpression' && node.callee.type === 'Identifier') {
addStatsEntry(node.callee.name);
functionsStats[node.callee.name].calls++;
}else if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression'){
var lexpr = node.callee.property.name;
addStatsEntry(lexpr);
functionsStats[lexpr].calls++;
}
pnode = node;
});
processResults(functionsStats);
}
function processResults(results) {
//console.log(JSON.stringify(results));
for (var name in results) {
if (results.hasOwnProperty(name)) {
var stats = results[name];
if (stats.declarations === 0) {
console.log('Function', name, 'undeclared');
} else if (stats.declarations > 1) {
console.log('Function', name, 'decalred multiple times');
} else if (stats.calls === 0) {
console.log('Function', name, 'declared but not called');
}
}
}
}
analyzeCode(data);
}
// Read the file and print its contents.
var filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
if (err) throw err;
console.log('OK: ' + filename);
notifydeadcode(data);
});
So if you plop that in a file like deadfunc.js and then call it like so:
node deadfunc.js test.js
where test.js contains:
helpers = {
doSomething:function(){ },
doSomethingElse:function(){ }
};
helpers.doSomethingElse();
You will get the output:
OK: test.js
Function doSomething declared but not called
One last thing to note: attempting to find unused variables and functions might be a rabbit hole because you have situations like eval and Functions created from strings. You also have to think about apply and call etc, etc. Which is why, I assume, we don't have this capability in the static analyzers today.

How to pass a value from code behind to javascript function in WP7

I am attempting to implement a search feature for text displayed in a webbrowser control. I have a search function which works correctly to highlight text, although it currently accomplishes this by creating a search bar in javascript in the webbrowser. The problem with this is that depending on the size of the page, the javascript search bar is always a different size, which is very confusing. I would like to be able to pass a search value entered by the user in a textbox in my WP7 application to this javascript function, and then have it simply highlight the values. I do not know how to pass a value to a javascript function though, and I am having much difficulty making this work.
Javascript search function (in a text file)
javascript:(
function()
{
function G()
{
var pf=doc.getElementById('pf');
var qt=doc.getElementById('qt');
if(null==pf)
{
pf=doc.createElement('div');
pf.id='pf';
var s=pf.style;
s.position='absolute';
s.zIndex='99';
s.top=(scT||scBT)+'px';
s.left=(scL||scBL)+'px';
s.width='100%';
s.backgroundColor='#FFFF00';
pf.appendChild(doc.createTextNode('Search: '));
qt=doc.createElement('input');
qt.id='qt';
qt.type='text';
pf.appendChild(qt);
var sb=doc.createElement('input');
sb.type='button';
sb.value='Find';
sb.onclick=function()
{
P(qt.value)
};
pf.appendChild(sb);
doc.body.appendChild(pf);
}
else
{
pf.style.display='inline';
count=0;
}
}
function P(s)
{
document.getElementById('pf').style.display='none';
if(s==='')
return;
var n=srchNode(document.body,s.toUpperCase(),s.length);
alert("Found "+count+" occurrence"+(count==1?"":"s")+" of '"+s+"'.");
pf.parentNode.removeChild(pf);
return n;
}
function srchNode(node,te,len)
{
var pos,skip,spannode,middlebit,endbit,middleclone;
skip=0;
if(node.nodeType==3)
{
pos=node.data.toUpperCase().indexOf(te);
if(pos>=0)
{
spannode=document.createElement("SPAN");
spannode.style.backgroundColor="red";
middlebit=node.splitText(pos);
endbit=middlebit.splitText(len);
middleclone=middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode,middlebit);
++count;
skip=1;
}
}
else
{
if(node.nodeType==1&&node.childNodes&&node.tagName.toUpperCase()!="SCRIPT"&&node.tagName.toUpperCase!="STYLE")
{
for(var child=0;child<node.childNodes.length;++child)
{
child=child+srchNode(node.childNodes[child],te,len);
}
}
}
return skip;
}
var count=0,scL=0,scT=0,scBL=0,scBT=0;
var w=window,doc=document;
if(typeof doc.body!='undefined'&&typeof doc.body.scrollLeft!='undefined')
{
scBL=doc.body.scrollLeft;
scBT=doc.body.scrollTop;
}
if(typeof doc.documentElement!='undefined'&&typeof doc.documentElement.scrollLeft!='undefined')
{
scL=doc.documentElement.scrollLeft;
scT=doc.documentElement.scrollTop;
}
G();
})()
Find on Page method
public void FindOnPage()
{
var resource = Application.GetResourceStream(new Uri("Resources/FindOnPage/FindOnPage.txt", UriKind.Relative));
string text;
StreamReader sr = new StreamReader(resource.Stream);
//while((text = sr.ReadToEnd()) != null)
if ((text = sr.ReadToEnd()) != null)
{
TheWebBrowser.InvokeScript("eval", text);
}
}
Assuming that I had a searchbar named SearchBar, how would i pass the text to the user input through the javascript function, so that the text will be highlighted? I have no experience with javascript, so any assistance will be greatly appreciated on the subject!
There is no direct way of passing it.
You can string replace the parameter before calling eval, first modify your javascript like this
javascript:(
function(searchString)
{
function P(s)
{
if(s==='')
return;
var n=srchNode(document.body,s.toUpperCase(),s.length);
alert("Found "+count+" occurrence"+(count==1?"":"s")+" of '"+s+"'.");
return n;
}
function srchNode(node,te,len)
{
var pos,skip,spannode,middlebit,endbit,middleclone;
skip=0;
if(node.nodeType==3)
{
pos=node.data.toUpperCase().indexOf(te);
if(pos>=0)
{
spannode=document.createElement("SPAN");
spannode.style.backgroundColor="red";
middlebit=node.splitText(pos);
endbit=middlebit.splitText(len);
middleclone=middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode,middlebit);
++count;
skip=1;
}
}
else
{
if(node.nodeType==1&&node.childNodes&&node.tagName.toUpperCase()!="SCRIPT"&&node.tagName.toUpperCase!="STYLE")
{
for(var child=0;child<node.childNodes.length;++child)
{
child=child+srchNode(node.childNodes[child],te,len);
}
}
}
return skip;
}
var count=0,scL=0,scT=0,scBL=0,scBT=0;
var w=window,doc=document;
if(typeof doc.body!='undefined'&&typeof doc.body.scrollLeft!='undefined')
{
scBL=doc.body.scrollLeft;
scBT=doc.body.scrollTop;
}
if(typeof doc.documentElement!='undefined'&&typeof doc.documentElement.scrollLeft!='undefined')
{
scL=doc.documentElement.scrollLeft;
scT=doc.documentElement.scrollTop;
}
P(searchString);
})("#search#")
Then in your C# replace #search# with your SearchString.
public void FindOnPage()
{
var resource = Application.GetResourceStream(new Uri("Resources/FindOnPage/FindOnPage.txt", UriKind.Relative));
string text;
StreamReader sr = new StreamReader(resource.Stream);
//while((text = sr.ReadToEnd()) != null)
if ((text = sr.ReadToEnd()) != null)
{
text = text.Replace("#search#",SearchBar.Text); //Replace SearchBar.Text with the string you want to search
TheWebBrowser.InvokeScript("eval", text);
}
}

Categories

Resources