Adding javascript dynamically using ExecuteJavaScriptAsync() API in OnContextCreated event remove elements in HTML HEAD tag ( wpf cefsharp 83.4.20.0) - cefsharp

I have a web page making ActiveX calls. Currently the page is loaded in IE embedded browser. Now I am planning to start using CEF as embedded web browser. I want to achieve this without modifying the existing code.
My Sample web page code:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Test ActiveXObject</title>
</head>
<body onload="myFunction()">
<script type="text/javascript" >
function CallSampleApi()
{
var obj = new ActiveXObject("Global.Pref");
var prefs = obj.Create("Pref.myPref");
if (prefs != null ) {
return prefs.SampleAPI();
}
else {
return 'not caught';
}
}
function myFunction() {
var message = "<h1 align='center'>Browser is Chrome </h1>" +
"<table border='1' width=500>" +
"<tr bgcolor='grey'><th width=300>Function Name</th><th width=200>Result</th></tr>" +
"<tr><td>Call Sample Api</td><td align='center'>" + CallSampleApi() + "</td></tr>" +
"</table>" ;
document.write(message);
}
</script>
</body>
</html>
I am using WPF cefsharp library for embedded web browser. In my WPF code, i have written a wrapper for this ActiveXObject and adding javascript dynamically using ExecuteJavaScriptAsync() API in OnContextCreated event. This works fine. But the problem is, this code somehow removes all tag in my html file which is strange.
public void OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
{
if (_script != null && frame.IsMain)
{
if (frame.Url.Contains("dev")) // avoid dev tools call
string script = #"class ActiveXObject {
constructor(name) {
}
Create(nativeObj) {
switch (nativeObj) {
case 'Pref.myPref':
return new Preferences();
default:
return null;
}
}
}
class Preferences {
constructor() {
}
SampleAPI() {
return 'I am caught';
}
}";
frame.ExecuteJavaScriptAsync(script);
}
}
Source of the page loaded in cef embedded browser:
<html>
<head></head>
<body>
<h1 align="center">Browser is Chrome </h1>
<table border="1" width="500"><tbody><tr bgcolor="grey"><th width="300">Function Name</th><th width="200">Result</th></tr><tr><td>Call Sample Api</td><td align="center">I am caught</td></tr></tbody></table>
</body>
</html>
Not sure how HEAD elements are removed. If i remove onload event from html page and move the content within SCRIPT tag, it works fine.

Related

css not overriding external css? [duplicate]

I have a simple page that has some iframe sections (to display RSS links). How can I apply the same CSS format from the main page to the page displayed in the iframe?
Edit: This does not work cross domain unless the appropriate CORS header is set.
There are two different things here: the style of the iframe block and the style of the page embedded in the iframe. You can set the style of the iframe block the usual way:
<iframe name="iframe1" id="iframe1" src="empty.htm"
frameborder="0" border="0" cellspacing="0"
style="border-style: none;width: 100%; height: 120px;"></iframe>
The style of the page embedded in the iframe must be either set by including it in the child page:
<link type="text/css" rel="Stylesheet" href="Style/simple.css" />
Or it can be loaded from the parent page with Javascript:
var cssLink = document.createElement("link");
cssLink.href = "style.css";
cssLink.rel = "stylesheet";
cssLink.type = "text/css";
frames['iframe1'].document.head.appendChild(cssLink);
I met this issue with Google Calendar. I wanted to style it on a darker background and change font.
Luckily, the URL from the embed code had no restriction on direct access, so by using PHP function file_get_contents it is possible to get the
entire content from the page. Instead of calling the Google URL, it is possible to call a php file located on your server, ex. google.php, which will contain the original content with modifications:
$content = file_get_contents('https://www.google.com/calendar/embed?src=%23contacts%40group.v.calendar.google.com&ctz=America/Montreal');
Adding the path to your stylesheet:
$content = str_replace('</head>','<link rel="stylesheet" href="http://www.yourwebsiteurl.com/google.css" /></head>', $content);
(This will place your stylesheet last just before the head end tag.)
Specify the base url form the original url in case css and js are called relatively:
$content = str_replace('</title>','</title><base href="https://www.google.com/calendar/" />', $content);
The final google.php file should look like this:
<?php
$content = file_get_contents('https://www.google.com/calendar/embed?src=%23contacts%40group.v.calendar.google.com&ctz=America/Montreal');
$content = str_replace('</title>','</title><base href="https://www.google.com/calendar/" />', $content);
$content = str_replace('</head>','<link rel="stylesheet" href="http://www.yourwebsiteurl.com/google.css" /></head>', $content);
echo $content;
Then you change the iframe embed code to:
<iframe src="http://www.yourwebsiteurl.com/google.php" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>
Good luck!
If the content of the iframe is not completely under your control or you want to access the content from different pages with different styles you could try manipulating it using JavaScript.
var frm = frames['frame'].document;
var otherhead = frm.getElementsByTagName("head")[0];
var link = frm.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", "style.css");
otherhead.appendChild(link);
Note that depending on what browser you use this might only work on pages served from the same domain.
var $head = $("#eFormIFrame").contents().find("head");
$head.append($("<link/>", {
rel: "stylesheet",
href: url,
type: "text/css"
}));
Here is how to apply CSS code directly without using <link> to load an extra stylesheet.
var head = jQuery("#iframe").contents().find("head");
var css = '<style type="text/css">' +
'#banner{display:none}; ' +
'</style>';
jQuery(head).append(css);
This hides the banner in the iframe page. Thank you for your suggestions!
If you control the page in the iframe, as hangy said, the easiest approach is to create a shared CSS file with common styles, then just link to it from your html pages.
Otherwise it is unlikely you will be able to dynamically change the style of a page from an external page in your iframe. This is because browsers have tightened the security on cross frame dom scripting due to possible misuse for spoofing and other hacks.
This tutorial may provide you with more information on scripting iframes in general. About cross frame scripting explains the security restrictions from the IE perspective.
An iframe is universally handled like a different HTML page by most browsers. If you want to apply the same stylesheet to the content of the iframe, just reference it from the pages used in there.
The above with a little change works:
var cssLink = document.createElement("link")
cssLink.href = "pFstylesEditor.css";
cssLink.rel = "stylesheet";
cssLink.type = "text/css";
//Instead of this
//frames['frame1'].document.body.appendChild(cssLink);
//Do this
var doc=document.getElementById("edit").contentWindow.document;
//If you are doing any dynamic writing do that first
doc.open();
doc.write(myData);
doc.close();
//Then append child
doc.body.appendChild(cssLink);
Works fine with ff3 and ie8 at least
The following worked for me.
var iframe = top.frames[name].document;
var css = '' +
'<style type="text/css">' +
'body{margin:0;padding:0;background:transparent}' +
'</style>';
iframe.open();
iframe.write(css);
iframe.close();
Expanding on the above jQuery solution to cope with any delays in loading the frame contents.
$('iframe').each(function(){
function injectCSS(){
$iframe.contents().find('head').append(
$('<link/>', { rel: 'stylesheet', href: 'iframe.css', type: 'text/css' })
);
}
var $iframe = $(this);
$iframe.on('load', injectCSS);
injectCSS();
});
use can try this:
$('iframe').load( function() {
$('iframe').contents().find("head")
.append($("<style type='text/css'> .my-class{display:none;} </style>"));
});
If you want to reuse CSS and JavaScript from the main page maybe you should consider replacing <IFRAME> with a Ajax loaded content. This is more SEO friendly now when search bots are able to execute JavaScript.
This is jQuery example that includes another html page into your document. This is much more SEO friendly than iframe. In order to be sure that the bots are not indexing the included page just add it to disallow in robots.txt
<html>
<header>
<script src="/js/jquery.js" type="text/javascript"></script>
</header>
<body>
<div id='include-from-outside'></div>
<script type='text/javascript'>
$('#include-from-outside').load('http://example.com/included.html');
</script>
</body>
</html>
You could also include jQuery directly from Google: http://code.google.com/apis/ajaxlibs/documentation/ - this means optional auto-inclusion of newer versions and some significant speed increase. Also, means that you have to trust them for delivering you just the jQuery ;)
My compact version:
<script type="text/javascript">
$(window).load(function () {
var frame = $('iframe').get(0);
if (frame != null) {
var frmHead = $(frame).contents().find('head');
if (frmHead != null) {
frmHead.append($('style, link[rel=stylesheet]').clone()); // clone existing css link
//frmHead.append($("<link/>", { rel: "stylesheet", href: "/styles/style.css", type: "text/css" })); // or create css link yourself
}
}
});
</script>
However, sometimes the iframe is not ready on window loaded, so there is a need of using a timer.
Ready-to-use code (with timer):
<script type="text/javascript">
var frameListener;
$(window).load(function () {
frameListener = setInterval("frameLoaded()", 50);
});
function frameLoaded() {
var frame = $('iframe').get(0);
if (frame != null) {
var frmHead = $(frame).contents().find('head');
if (frmHead != null) {
clearInterval(frameListener); // stop the listener
frmHead.append($('style, link[rel=stylesheet]').clone()); // clone existing css link
//frmHead.append($("<link/>", { rel: "stylesheet", href: "/styles/style.css", type: "text/css" })); // or create css link yourself
}
}
}
</script>
...and jQuery link:
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
As many answers are written for the same domains, I'll write how to do this in cross domains.
First, you need to know the Post Message API. We need a messenger to communicate between two windows.
Here's a messenger I created.
/**
* Creates a messenger between two windows
* which have two different domains
*/
class CrossMessenger {
/**
*
* #param {object} otherWindow - window object of the other
* #param {string} targetDomain - domain of the other window
* #param {object} eventHandlers - all the event names and handlers
*/
constructor(otherWindow, targetDomain, eventHandlers = {}) {
this.otherWindow = otherWindow;
this.targetDomain = targetDomain;
this.eventHandlers = eventHandlers;
window.addEventListener("message", (e) => this.receive.call(this, e));
}
post(event, data) {
try {
// data obj should have event name
var json = JSON.stringify({
event,
data
});
this.otherWindow.postMessage(json, this.targetDomain);
} catch (e) {}
}
receive(e) {
var json;
try {
json = JSON.parse(e.data ? e.data : "{}");
} catch (e) {
return;
}
var eventName = json.event,
data = json.data;
if (e.origin !== this.targetDomain)
return;
if (typeof this.eventHandlers[eventName] === "function")
this.eventHandlers[eventName](data);
}
}
Using this in two windows to communicate can solve your problem.
In the main windows,
var msger = new CrossMessenger(iframe.contentWindow, "https://iframe.s.domain");
var cssContent = Array.prototype.map.call(yourCSSElement.sheet.cssRules, css_text).join('\n');
msger.post("cssContent", {
css: cssContent
})
Then, receive the event from the Iframe.
In the Iframe:
var msger = new CrossMessenger(window.parent, "https://parent.window.domain", {
cssContent: (data) => {
var cssElem = document.createElement("style");
cssElem.innerHTML = data.css;
document.head.appendChild(cssElem);
}
})
See the Complete Javascript and Iframes tutorial for more details.
Other answers here seem to use jQuery and CSS links.
This code uses vanilla JavaScript. It creates a new <style> element. It sets the text content of that element to be a string containing the new CSS. And it appends that element directly to the iframe document's head.
var iframe = document.getElementById('the-iframe');
var style = document.createElement('style');
style.textContent =
'.some-class-name {' +
' some-style-name: some-value;' +
'}'
;
iframe.contentDocument.head.appendChild(style);
When you say "doc.open()" it means you can write whatever HTML tag inside the iframe, so you should write all the basic tags for the HTML page and if you want to have a CSS link in your iframe head just write an iframe with CSS link in it. I give you an example:
doc.open();
doc.write('<!DOCTYPE html><html><head><meta charset="utf-8"/><meta http-quiv="Content-Type" content="text/html; charset=utf-8"/><title>Print Frame</title><link rel="stylesheet" type="text/css" href="/css/print.css"/></head><body><table id="' + gridId + 'Printable' + '" class="print" >' + out + '</table></body></html>');
doc.close();
You will not be able to style the contents of the iframe this way. My suggestion would be to use serverside scripting (PHP, ASP, or a Perl script) or find an online service that will convert a feed to JavaScript code. The only other way to do it would be if you can do a serverside include.
Incase if you have access to iframe page and want a different CSS to apply on it only when you load it via iframe on your page, here I found a solution for these kind of things
this works even if iframe is loading a different domain
check about postMessage()
plan is, send the css to iframe as a message like
iframenode.postMessage('h2{color:red;}','*');
* is to send this message irrespective of what domain it is in iframe
and receive the message in iframe and add the received message(CSS) to that document head.
code to add in iframe page
window.addEventListener('message',function(e){
if(e.data == 'send_user_details')
document.head.appendChild('<style>'+e.data+'</style>');
});
I think the easiest way is to add another div, in the same place as the iframe, then
make its z-index bigger than the iframe container, so you can easly just style your own div. If you need to click on it, just use pointer-events:none on your own div, so the iframe would be working in case you need to click on it ;)
I hope It will help someone ;)
I found another solution to put the style in the main html like this
<style id="iframestyle">
html {
color: white;
background: black;
}
</style>
<style>
html {
color: initial;
background: initial;
}
iframe {
border: none;
}
</style>
and then in iframe do this (see the js onload)
<iframe onload="iframe.document.head.appendChild(ifstyle)" name="log" src="/upgrading.log"></iframe>
and in js
<script>
ifstyle = document.getElementById('iframestyle')
iframe = top.frames["log"];
</script>
It may not be the best solution, and it certainly can be improved, but it is another option if you want to keep a "style" tag in parent window
Here, There are two things inside the domain
iFrame Section
Page Loaded inside the iFrame
So you want to style those two sections as follows,
1. Style for the iFrame Section
It can style using CSS with that respected id or class name. You can just style it in your parent Style sheets also.
<style>
#my_iFrame{
height: 300px;
width: 100%;
position:absolute;
top:0;
left:0;
border: 1px black solid;
}
</style>
<iframe name='iframe1' id="my_iFrame" src="#" cellspacing="0"></iframe>
2. Style the Page Loaded inside the iFrame
This Styles can be loaded from the parent page with the help of Javascript
var cssFile = document.createElement("link")
cssFile.rel = "stylesheet";
cssFile.type = "text/css";
cssFile.href = "iFramePage.css";
then set that CSS file to the respected iFrame section
//to Load in the Body Part
frames['my_iFrame'].document.body.appendChild(cssFile);
//to Load in the Head Part
frames['my_iFrame'].document.head.appendChild(cssFile);
Here, You can edit the Head Part of the Page inside the iFrame using this way also
var $iFrameHead = $("#my_iFrame").contents().find("head");
$iFrameHead.append(
$("<link/>",{
rel: "stylesheet",
href: urlPath,
type: "text/css" }
));
We can insert style tag into iframe.
<style type="text/css" id="cssID">
.className
{
background-color: red;
}
</style>
<iframe id="iFrameID"></iframe>
<script type="text/javascript">
$(function () {
$("#iFrameID").contents().find("head")[0].appendChild(cssID);
//Or $("#iFrameID").contents().find("head")[0].appendChild($('#cssID')[0]);
});
</script>
var link1 = document.createElement('link');
link1.type = 'text/css';
link1.rel = 'stylesheet';
link1.href = "../../assets/css/normalize.css";
window.frames['richTextField'].document.body.appendChild(link1);
This is how I'm doing in production. It's worth bearing in mind that if the iframe belongs to other website, it will trigger the CORS error and will not work.
var $iframe = document.querySelector(`iframe`);
var doc = $iframe.contentDocument;
var style = doc.createElement("style");
style.textContent = `*{display:none!important;}`;
doc.head.append(style);
In some cases you may also want to attach a load event to the iframe:
var $iframe = document.querySelector(`iframe`);
$iframe.addEventListener("load", function() {
var doc = $iframe.contentDocument;
var style = doc.createElement("style");
style.textContent = `*{display:none!important;}`;
doc.head.append(style);
});
There is a wonderful script that replaces a node with an iframe version of itself.
CodePen Demo
Usage Examples:
// Single node
var component = document.querySelector('.component');
var iframe = iframify(component);
// Collection of nodes
var components = document.querySelectorAll('.component');
var iframes = Array.prototype.map.call(components, function (component) {
return iframify(component, {});
});
// With options
var component = document.querySelector('.component');
var iframe = iframify(component, {
headExtra: '<style>.component { color: red; }</style>',
metaViewport: '<meta name="viewport" content="width=device-width">'
});
As an alternative, you can use CSS-in-JS technology, like below lib:
https://github.com/cssobj/cssobj
It can inject JS object as CSS to iframe, dynamically
This is just a concept, but don't implement this without security checks and filtering! Otherwise script could hack your site!
Answer: if you control target site, you can setup the receiver script like:
1) set the iframe link with style parameter, like:
http://your_site.com/target.php?color=red
(the last phrase is a{color:red} encoded by urlencode function.
2) set the receiver page target.php like this:
<head>
..........
$col = FILTER_VAR(SANITIZE_STRING, $_GET['color']);
<style>.xyz{color: <?php echo (in_array( $col, ['red','yellow','green'])? $col : "black") ;?> } </style>
..........
Well, I have followed these steps:
Div with a class to hold iframe
Add iframe to the div.
In CSS file,
divClass { width: 500px; height: 500px; }
divClass iframe { width: 100%; height: 100%; }
This works in IE 6. Should work in other browsers, do check!

How to dynamically create properties in polymer as needed

I have a use case where I have a component (like a database) that I would like to expose all the information as bindable properties. However, only a few of those properties will be need by any particular client who uses it. There could be 1000's of entries in the database. How can I figure out which ones are actually needed by the client.
For example:
Polymer('database,
{
observer : {
name : function(oldVal, newVal) { onDataChanged('name', newVal);},
addr : function(oldVal, newVal) { onDataChanged('addr', newVal);},
tel.main : function(oldVal, newVal) { onDataChanged('tel.main',
etc....
}
});
In this case I would like to dynamically create observe handlers only for the data bindings that are actually needed on the fly.
If you are willing to have your clients extend your component to specify the desired database fields then you can dynamically create observers only for the fields they specify.
Example
Component
<link rel="import" href="../../webcomponents/bower_components/polymer/polymer.html">
<polymer-element name=demo-dynamicproperties >
<template>
<h2>dynamic properties</h2>
See the console for changes
</template>
<script>
Polymer({
// Validate that it is an attribute that is allowed
// For the example we will allow anything starting with validitem
isValidAttribute: function(name) {
return (name.match('^validitem'));
},
// Get attributes
created: function() {
for (name in this.publish) {
console.log("Trying: "+name);
// Verify that it is one of the dynamic attributes
if (this.isValidAttribute(name)) {
console.log("Accepting: "+name);
this[name]="Pull from DB";
// References:
// https://www.polymer-project.org/0.5/docs/polymer/node_bind.html
// https://github.com/Polymer/NodeBind/blob/master/tests/tests.js
// https://github.com/polymer/observe-js
var observer = new PathObserver(this,name);
observer.open(makeHandler(this,name));
}
}
/************* TEST **********************************/
// Verify that dynamic updates worked by updating
this.job('update_validitem1', function() {
this.validitem1="Updated after 10 seconds";
}, 10000);
/************ End Test ******************************/
}
});
// Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
function makeHandler(element, property) {
function handler(newval,oldval) {
console.log("element" + element,"property:" + property,"from:"+oldval,"to:"+newval);
}
return handler;
}
</script>
</polymer-element>
Usage
<!DOCTYPE HTML>
<html lang="en">
<head>
<script src="../../webcomponents/bower_components/webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="../../webcomponents/bower_components/polymer/polymer.html">
<link rel="import" href="demo-dynamicproperties.html">
<title>demo-dynamicproperties test page</title>
</head>
<body>
<polymer-element name=demo-usedb extends="demo-dynamicproperties" attributes="validitem1 validitem2 invaliditem" noscript>
</polymer-element>
<h1>Demo</h1>
<template is="auto-binding">
<h2>Dynamic tag</h2>
<demo-usedb validitem1="{{item1choice2}}" item2="setthis"></demo-usedb>
<h2>Input</h2>
<input type="text" value="{{item1choice2}}">
<h3>Produces</h3>
{{item1choice2}}
</template>
</body>
</html>
It looks like the answer to the questions is that it cannot be done. There does not appear to be any hooks or events that a component can use to get notified when properties are bound (or attempted to be bound) to it. I filed a bug/enhancement request here
https://github.com/Polymer/polymer/issues/1303
to request that this feature be supported in the future.

Multiple sections in Handlebars template

I’m just getting to know Handlebars a bit better as a templating solution and have hit a problem that I don’t know how to solve.
I’ve added sections to my layout, one for the header and one for the footer for dynamically inserting scripts from my views. However, only the first section ever renders. The second one (regardless of order) is always omitted.
My layout is a simple HTML page:
<!doctype html>
<html>
<head>
<title>Test site</title>
{{{_sections.head}}}
</head>
<body>
<header>
//Logo and stuff here
</header>
{{{body}}}
<script src="//code.jquery.com/jquery-2.0.2.min.js"></script>
{{{_sections.footer}}}
</body>
</html>
And in my layout file I have:
{{#section 'head'}}
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.min.js"></script>
{{/section}}
//basic HTML here
{{#section 'footer'}}
<script>
alert("this doesn’t fire if its second!");
</script>
{{/section}}
The header section appears on the page but the footer does not. The thing is, if I put the footer at the top of the page (i.e. before the {{section ‘head’}} that then renders but the head section no longer renders.
In my app.js I’m setting up the section functionality as follows:
var handlebars = require('express3-handlebars')
.create({
defaultLayout: 'main',
helpers: {
section: function (name, options) {
if (!this._sections) {
this._sections = {};
this._sections[name] = options.fn(this);
return null;
}
}
}
});
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'handlebars');
Any ideas what I’m doing wrong here or how to add support for both sections?
Thanks
I think your sections are overwriting each other. Try changing your handlebars create to the following:
var handlebars = require('express3-handlebars')
.create({
defaultLayout: 'main',
helpers: {
section: function (name, options) {
if (!this._sections) {
this._sections = {};
}
this._sections[name] = options.fn(this);
return null;
}
}
});

What needs to be changed in this code to make the page on top of it that loads this in a iframe change load a new url?

ok so heres my code
<html>
<head>
<title></title>
<body>
<script>
<!--
/*
Cookie Redirect. Written by PerlScriptsJavaScripts.com
Copyright http://www.perlscriptsjavascripts.com
Free and commercial Perl and JavaScripts
*/
// page to go to if cookie exists
go_to = "http://www.cookieisthere.com";
// number of days cookie lives for
num_days = 365;
function ged(noDays){
var today = new Date();
var expr = new Date(today.getTime() + noDays*24*60*60*1000);
return expr.toGMTString();
}
function readCookie(cookieName){
var start = document.cookie.indexOf(cookieName);
if (start == -1){
} else {
window.location = go_to;
}
}
readCookie("seenit");
// -->
</script>
</body>
</html>
This page will load on a page through a iframe... if the cookie is their i want the parent window to go to http://www.cookieisthere.com not the original page. After reading up on it a bit some people say use _top where the link is but i dont know how to do this. All help is much appreciated :)
Try this instead
<html>
<head>
<title></title>
<body>
<script>
<!--
/*
Cookie Redirect. Written by PerlScriptsJavaScripts.com
Copyright http://www.perlscriptsjavascripts.com
Free and commercial Perl and JavaScripts
*/
// page to go to if cookie exists
go_to = "http://www.cookieisthere.com";
// number of days cookie lives for
num_days = 365;
function ged(noDays){
var today = new Date();
var expr = new Date(today.getTime() + noDays*24*60*60*1000);
return expr.toGMTString();
}
function readCookie(cookieName){
var start = document.cookie.indexOf(cookieName);
if (start == -1){
} else {
window.top.location = go_to;
}
}
readCookie("seenit");
// -->
</script>
</body>
</html>

Pop up window not appending text

I am trying to implement a 'Trace Window' pop up window when I enter a website, and then send messages to that window throughout the website in Order to diagnose some of the more awkward issues i have with the site.
The Problem is that the page changes, if The trace window already exists, all content is removed, before the new TraceText is added.
What I want is a Window that can be sent messages from any page inside the website.
I have a javascript Script debugger.js which I include as a script in every screen (shown below) I would then call the sendToTraceWindow() function to send a message to it thoughout the website. this is currently Mostly done in vbscript at present, due to the issues i am currenctly investigating.
I think it is because i am scripting in the debugger.js into every screen, which sets the traceWindow variable = null (see code below) but I do not know how to get around this!
Any help much appreciated.
Andrew
code examples:
debugger.js:
var traceWindow = null
function opentraceWindow()
{
traceWindow = window.open('traceWindow.asp','traceWindow','width=400,height=800')
}
function sendToTracewindow(sCaller, pMessage)
{
try
{
if (!traceWindow)
{
opentraceWindow()
}
if (!traceWindow.closed)
{
var currentTrace = traceWindow.document.getElementById('trace').value
var newTrace = sCaller + ":" + pMessage + "\n" + currentTrace
traceWindow.document.getElementById('trace').value = newTrace
}
}
catch(e)
{
var currentTrace = traceWindow.document.getElementById('trace').value
var newTrace = "error tracing:" + e.message + "\n" + currentTrace
traceWindow.document.getElementById('trace').value = newTrace
}
}
traceWindow.asp - just a textarea with id='trace':
<HTML>
<head>
<title>Debug Window</title>
</head>
<body>
<textarea id="trace" rows="50" cols="50"></textarea>
</body>
</HTML>
I don't think there is any way around the fact that your traceWindow variable will be reset on every page load, therefore rendering your handle to the existing window invalid. However, if you don't mind leveraging LocalStorage and some jQuery, I believe you can achieve the functionality you are looking for.
Change your trace window to this:
<html>
<head>
<title>Debug Window</title>
<script type="text/javascript" src="YOUR_PATH_TO/jQuery.js" />
<script type="text/javascript" src="YOUR_PATH_TO/jStorage.js" />
<script type="text/javascript" src="YOUR_PATH_TO/jquery.json-2.2.js" />
<script type="text/javascript">
var traceOutput;
var traceLines = [];
var localStorageKey = "traceStorage";
$(function() {
// document.ready.
// Assign the trace textarea to the global handle.
traceOutput = $("#trace");
// load any cached trace lines from local storage
if($.jStorage.get(localStorageKey, null) != null) {
// fill the lines array
traceLines = $.jStorage.get(localStorageKey);
// populate the textarea
traceOutput.val(traceLines.join("\n"));
}
});
function AddToTrace(data) {
// append the new trace data to the textarea with a line break.
traceOutput.val(traceOutput.val() + "\n" + data);
// add the data to the lines array
traceLines[tracelines.length] = data;
// save to local storage
$.jStorage.set(localStorageKey, traceLines);
}
function ClearTrace() {
// empty the textarea
traceOutput.val("");
// clear local storage
$.jStorage.deleteKey(localStorageKey);
}
</script>
</head>
<body>
<textarea id="trace" rows="50" cols="50"></textarea>
</body>
</html>
Then, in your pages where you want to trace data, you could modify your javascript like so:
var traceWindow = null;
function opentraceWindow() {
traceWindow = window.open('traceWindow.asp','traceWindow','width=400,height=800');
}
function sendToTracewindow(sCaller, pMessage) {
traceWindow.AddToTrace(sCaller + ":" + pMessage);
}
Every time a new page is loaded and the trace window is refreshed, the existing trace data is loaded from local storage and displayed in your textarea. This should achieve the functionality that you are looking for.
Please be kind on any errors - I'm winging this on a Monday morning!
Finding the jQuery library should be trivial. You can find the jStorage library here: http://www.jstorage.info/, and you can find jquery-json here: http://code.google.com/p/jquery-json/

Resources