Following on from this question here
I have a custom ActiveX control which raises an event "BeforePageValidated" which has a parameter "args" which is an object which contains a boolean. The purpose of this is to allow the client to override the validation and force it fail by setting the boolean value to true.
I can catch the event in IE using the following
<script for="objInterviewNOW" event="BeforePageValidated(args)">
However I can't access the property of the args object.
How should I be doing this?
Worked it out for myself.
The problem was that the event was being passed down from another dll used by the activeX control, and this is where the args class was declared.
Fixed it by creating a copy of the args class in the activeX object and using this when raising the event.
Unfortunately does mean the args class is duplicated, so maybe someone knows a better way?
args also needs to register as com object.
[ComVisible(true)]
[GuidAttribute("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]
public class args
{
}
Hope this will help.
Related
Application is using IE WebBrwoser Control. However sometimes javascript error dialogs comes up,to solve this put_silent property was used on WebBrowser element,but that disables all the dialogs.So is there a way to disable Javascript error debugging in WebBrowser control?
On your control do right click and click on Inspect Element. If you did not disable the IE menu, it should open the Developer window on right or bottom side. Select there the tab "Debug", click on the hexagon and check "Don't stop on exception" or "Stop on unhandled exceptions". I believe this is a global setting for the browser, so you maybe can do it just from IE.
Update 1
First implement IDocHostUIHandler and wrap the external handler calls. It is declared in Mshtmhst.h so you probably have to include it. Don't forget about IUnknown members, also have to be wrapped. ATL wizards can be used to implement interfaces, but anyway you will have to understand exactly that you do:
class MyDocHostUIHandler: public IDocHostUIHandler
{
public:
IDocHostUIHandler* externalHandler;
HRESULT EnableModeless( BOOL fEnable)
{
return externalHandler->EnableModeless(fEnable);
}
HRESULT FilterDataObject(IDataObject* pDO, IDataObject** ppDORet)
{
return externalHandler->FilterDataObject(pDO, ppDORet)ș
}
.... Wrap all the functions from External Handler like above
};
Create an instance of your class:
MyDocHostUIHandler* myHandler = new MyDocHostUIHandler();
Then in your code call like it is specified in MSDN.
First you get the MSHTML object
CComPtr<IHTMLDocument2> m_spDocument;
hr = m_WebBrowser->get_Document(&m_spDocument);// Get the MSHTML object
Then you get the existing default handler
ComPtr<IOleObject> spOleObject;
hr = m_spDocument.As(&spOleObject);
ComPtr<IOleClientSite> spClientSite;//<--this will be the default handler
hr = spOleObject->GetClientSite(&spClientSite);
Save the existing handler to your class, so you will be able to wrap its functions
//see myHandler is the instance of interface you implemented in first step
myHandler->externalHandler = spClientSite;
Get the custom doc:
ComPtr<ICustomDoc> spCustomDoc;
hr = m_spDocument.As(&spCustomDoc);//m_spDocument it is the pointer to your MSHTML
Now replace the handler from HSMTML:
//myHandler is the instance of class you implemented above
spCustomDoc->SetUIHandler(myHandler);
After this step, the MSHTML should not notice anything, but you will be able to add breakpoints in your MyDocHostUIHandler class and see which function is called by your MSHTML and when.
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers
How do I get a list of all the properties of GlobalEventHandlers?
Specifically, I want to test if a passed string is a property of GlobalEventHandlers, something like:
console.log(GlobalEventHandlers.includes('onClick')); // true
console.log(GlobalEventHandlers.includes('fizzBuzz')); // false
The only real way to get all of them is to build the list yourself, but you can loop over the keys in the window object and look for keys that start with on
Object.keys(window).filter(k => !k.indexOf('on'))
BUT that is not going to return just the built in ones. If someone set a custom event listener like
window.onfoobar = function () {}
than that will also show up in the result.
I wrote an npm package that does that for you.
Full usage and installation: global-event-handlers-map.
it extracts every global event handler under every object that exists under window (including window).
for example, by calling:
const getGlobalEventsHandlersMap = require('global-event-handlers-map');
const gehsMap = getGlobalEventsHandlersMap('WebSocket');
you will get the following result (gehsMap would be):
{
"WebSocket": [
"onopen",
"onerror",
"onclose",
"onmessage"
]
}
by calling getGlobalEventsHandlersMap() with no arguments, you will receive ALL global event handlers.
the README file should be very indicative and should help you understand how to get everything you need from that package.
you can either:
execute the code once in the browser, get the results, and use that map statically in your code.
integrate the library in your code and by that dynamically create the map every time your code runs in the browser.
the best way depends on your needs, and should be your call. i can help you understand which way is best for you depends on your needs.
hope that helps!
I am creating an ActiveX control for a hardware (card swiper) device. I have understanding of ActiveX development and working, but I am little stuck with my specific scenario. Device SKD (dll files) have method to activate swiper/chip reader in order to be in listening state. Assume the following:
SDK sdk = new SDK();
sdk.RegisterCallback(GlobalCallback);
sdk.ActivateSwiper();
public void GlobalCallback(op, .., ..)
{
switch(op) {
case Swiped:
readCardData();
break;
case TransactionData:
readData();
break;
//. . . .
}
Above code is just for example. SDK has a global callback method for any event triggered through device (eg, card swiped, ICC seated, etc). If the SDK is being used in WPF/WinForm app, it is super easy get it working. But in my case, I must need to handle the raised event in javascript on my web page.
So, I have exposed a method in ActiveX to turn on the device, which works perfect:
[Guid("4794D615-BE51-4a1e-B1BA-453F6E9337C4")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IComEvents))]
public class MyComObject : IComObject
{
[ComVisible(true)]
public string ActivateDevice()
{
SDK sdk = new SDK();
sdk.RegisterCallback(GlobalCallback);
string resultCode = sdk.ActivateSwiper();
return resultCode;
}
//. . <other code> . . .
}
and use it in webpage as:
<object id="myComComponent" name="myComComponent" classid="clsid:4794D615-BE51-4a1e-B1BA-453F6E9337C4"></object>
<script language="javascript" type="text/javascript">
var returnCode = myComComponent.ActivateDevice(); //or by creating ActiveXObject
</script
I have also got the idea about how to handle events using ActiveX on webpage. I learnt it from HERE. But the event is handled by calling the exposed method to raise event. And in my case, when card is swiped, the call will go to GlobalCallback() method.
Questioins:
Is there any workaround, I can implement handler in my scenario, to make it usable on javascript?
I am thinking of something like PropertyChanged event, bound to a string property, which holds the derived card data. and the handlers returns this property value. Is there any workaround possible like this? I need little help with this.
I am thinking this as:
public static string CARD_DATA;
public void GlobalCallback(op, .., ..)
{
switch(op) {
case Swiped:
CARD_DATA = readCardData();
//and CARD_DATA is bound to property-changed event, and its handler returns its value.
//other code
Is this even possible? If so, What to be exposed? and How to use it? as this property will be changed internally, when card is swiped, and case Swiped: is executed. Is there any workaround?
Other Info:
Web App is MVC 4 famework based
Device is The Augusta (IDTech). (they don't have actieX/plugin for web)
I want to set value of a zk datebox from javascript. Actually I can set the value but when I want to access its value, it is throwing a null pointer exception. More generally, some abilities of the zk components can be manupulated but others not. For example I can fire a button onclick event but I can not set an attribute of that button by javascript.
For example these two work :
zk.Widget.$('$startDateProxy').setValue(start); zk.Widget.$('$addEventBtn').fire('onClick');
But these two not:
zk.Widget.$('$startDateProxy').setAttribute("startDate",start) -> cutting the operation
alert(startDateProxy.getValue().toString()) -> null pointer
Thanks
PS: I am trying to use FULLCALENDAR (arshaw.com/fullcalendar)
Thank you for your answer. startDateProxy component is Datebox, not Calendar. Sorry for missing information. I solved the problem by using AuService. I defined a hidden button. Fired its onClick with the parameters. Sample usage:
Client Side:
zk.Widget.$('$eventBtn').fire('onClick',{start : start ,end : end});
Server Side:
public void service(AuRequest request, boolean everError) {
if (Events.ON_CLICK.equals(request.getCommand())) {
Map data = request.getData(); // can be read start,end parameters from here
//dosomething here
}
Try it instead
alert(this.$f('addEventBtn').getLabel());
The Class Calendar does not have a setAttribute method (see the docs).
Most of the examples you find on the web, of using javascript from ASP.NET pages puts the javascript in the markup file (*.aspx). This is, of course, a really bad idea(tm), for all but the simplest uses of javascript.
What we want, of course, is to wrap the javascript up into a class, and to instantiate an instance of that class and tie it to the code-behind.
Microsoft provides a framework for doing this for user controls and server controls, in its IScriptControl interface. This allows a developer to create a javascript "component" - to define a javascript class in a *.js file, to include the *.js file on the page that contains the control, to instantiate an instance of the component, to set variables in the component from values in the code-behind, and to get a reference to the component in javascript on the client side.
The thing is - IScriptControl only works for user and server controls. It cannot be used to instantiate javascript objects at the page level.
So - how do people do this? We have some patterns we've been using, that seem to work. I was wondering what everyone thought of them, and what other people were using.
We start by defining a javascript class in a *.js file. In the code-behind, we create a loadJavascript() function, that we call from Page_Load on initial load or full postback (but not on partial postbacks).
In loadJavascript(), we include the *.js file with ScriptManager.RegisterClientScriptInclude(), and then construct a bit of javascript that instantiates an instance of the class, assigns a reference to a known name, and registers the object's initialize() and dispose() methods as handlers for window.load and window.unload.
E.g.:
string url = this.ResolveUrl("./FooBar.js");
ScriptManager.RegisterClientScriptInclude(this, this.GetType(), url, url);
string script = #"
if (typeof {0}_obj == 'undefined')
{0}_obj = {{}};
{0}_obj.fooBar = new FooBar();
Sys.UI.DomEvent.addHandler(window, 'load',
function()
{{
{0}_obj.fooBar.initialize('{1}', '{2}');
}}
);
Sys.UI.DomEvent.addHandler(window, 'unload', {0}_obj.fooBar.dispose);
";
script = String.Format(script,
new object[]
{
this.ClientID,
this.foo.ClientID,
this.bar.ClientID
});
ScriptManager.RegisterStartupScript(
this, this.GetType(), this.ClientID, script, true);
We construct an object name in the global namespace, based on the ClientID of the page, if we haven't already. We add an instance of our new class as a member of our global object. We add a window.load handler that calls our object's intialize() method, passing the clientIDs of the controls on the page that the object's methods need to access. And we add a window.unload handler that calls our object's dispose() method, that does whatever cleanup that is necessary.
This seems to be working, for us. We've used this pattern on a number of pages, some of which did significant amounts of partial-postbacks, without any problems.
I was wondering, first, what people thought of the pattern.
But more, I was wondering if we'd been reinventing the wheel, and if there were other approaches to dealing with the issues we were addressing, that we weren't aware of.
Anyone have any better ideas?
But more, I was wondering if we'd been reinventing the wheel, and if there were other approaches to dealing with the issues we were addressing, that we weren't aware of.
I think this the most good approaches, I use the same way some years now with out any problem in very complex javascript code. I do not see why you question your self :)
The idea is this you follow, now maybe there are some variations, maybe I not call the unload, nether create an object to keep the foobar and call the foobar rightway, but the idea is the same. I also check if the Javascript file have been loaded...
string script = #"
if (typeof (FooBar) != "undefined") {{
var {0}fooBar = new FooBar();
Sys.UI.DomEvent.addHandler(window, 'load',
function()
{{
{0}fooBar.initialize('{1}', '{2}');
}}
);
}}