Thursday, March 15, 2012

Inheritance in Javascript using jQuery

Here is a small JS code snippet, that allows you to create class trees with almost any inheritance complexity.
NB: Uses jQuery
createClass : function (a, b) {
    var c = function() {
        $(this.__constructor.apply(this,arguments));
    },e='prototype',f;
    if ($.isFunction(a)) {
        (f = function() { })[e] = a[e];
        ((c[e] = new f()).constructor = c).parentClass = a[e];
        a = b;
    }
    $.extend(c[e],a);
    return c;
}
Basic usage:
ClassA = createClass({
    __constructor : function() {
        
    }
});
ClassB = createClass(ClassA,{
    __constructor : function() {
        ClassB.parentClass.__constructor.apply(this,arguments);

    }
});
Inheritance power demonstration:
ClassA = createClass({
    __constructor : function() {
        
    },
    hello_world : function() {
        alert('ClassA says Hello World');
    }
});

ClassB = createClass(ClassA,{
    __constructor : function() {
        ClassB.parentClass.__constructor.apply(this,arguments);
        this.hello_world();
    },
    hello_world : function() {
        ClassB.parentClass.hello_world.apply(this,arguments);
        alert('ClassB says Hello World');
    }
});
This example will give you two alerts in the following order:
  • 1. 'ClassB says Hello World'
  • 2. 'ClassA says Hello World'
Important notes:
"__constructor" is just name, that can be replace with anything you'd like, I'm usually using "init"
"parentClass" also replaceable with any other keywords you'd like.


Happy using!

Friday, March 2, 2012

jQuery.linqSelect and jQuery.datas()

We all know that jQuery has "data" method, but when dealing with more than one DOM element, I'd like to have method called "datas", which would return an array of all "data" calls for each element in jQuery selection.


After some coding, here is a solution I've finally came up with:

$.fn.linqSelect = function(n, fn) {
    var vs = [], f, t, i, v, r, a = $.isArray(n);
    $(this).each(function() {
        if (f = (t = $(this))[fn]) {
            if (a && (r = { })) for (i in n) r[v = n[i]] = f.apply(t, [v]);
            else r = n!=null ? f.apply(t, [n]) : f.apply(t);
            vs.push(r);
        }
    });
    return vs;
};

Possible usages:
$("a").linqSelect('href','attr');
Will return an array of all A's href attributes
$("input:radio[data-name][data-value]").linqSelect(['name','value'] ,'data');
Will return an array of objects {name:...,value:...} filled with corresponding data


Also one shortcut function :
$.fn.linqSelectData = function(n) {
    return this.linqSelect(n, 'data');
};
Usage:
$("input:radio[data-name][data-value]").linqSelectData(["id", "value", "sid"]);
That idea mainly shows the direction of how to implement other linq-like functions

Thursday, October 6, 2011

Flashdevelop and AIR 3



Here is full list of tricks that should be done to run AIR3.0 project on Flashdevelop's 4.0 beta version:

1. Download latest Flex SDK and AirSDK, and extract it into some new folder (in same order: Flex then Air)
2. Add SDK to FlashDevelop (4.0 beta), Tools -> Programm Settings -> AS3Context -> "Installed Flex SDKs" -> Double click on the button with three dots "..." next to the value of this row, choose there your SDK
3. Create new Air 3 project. In Project properties, compiler options, put "-swf-version=13" into "Additional Compiler Options" under "Compiler options" tab
4. In Project settings, choose 3.0 in the Platform section of Output tab
5. edit application.xml:
http://ns.adobe.com/air/application/2.7">
replace with
http://ns.adobe.com/air/application/3.0">
6. empty "bin" folder of the project.

Tuesday, October 4, 2011

Smarty upgrade to 3.1.2

Upgrading Smarty to version 3.1.2 (from 3.0.* versions) might bring you some troubles:

1. If you receive "SmartyException' with message 'property 'rendered_template' does not exist." Exception, then just rename newly copied "Smarty.class.php" to the appropriate name, appearently this exceptionis thrown if you use OLD version of smarty class with it's new system classes

2. If you receive "Trying to get property of non-object" with line 1157 or smth like that, then you appearently use Smarty class extending it. So trick is that Smarty has constructor now, so please add "parent::__construct()" as first line into your child class (that extends Smarty)

Gl & Hf

Monday, June 13, 2011

WPF WebBrowser JS Errors capture

Definition of the problem: Catch all the JS errors occurred in WebBrowser used in WPF application.

Luckily DOM's window has so called "external" object and WebBrowser componenet has a "ObjectForScripting" property which is "equal" to "window.external".

There are some restrictions with permissions, f.e. you cannot set your window or application as a ObjectForScripting. Otherwise you receive Exception "The object type is not visible to COM. You need to set ComVisibleAttribute attribute to True."
So I propose to use another class to do that.

Here is the source:
1st Part of code is run only once, in the window/app constructor f.e.

ObjectForScriptingHelper ScriptHelper = new ObjectForScriptingHelper(this);
wb_browser.ObjectForScripting = ScriptHelper;


2nd Part is run on Browser's "Navigated" event

private void wb_browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e) {
string DisableScriptError = @"function externalError(errorMsg, document, lineNumber) {
window.external.onError(errorMsg, document, lineNumber);
return true;
}
window.onerror = externalError;";
HTMLDocument doc2 = wb_browser.Document as HTMLDocument;
IHTMLScriptElement scriptErrorSuppressed = (IHTMLScriptElement)doc2.createElement("SCRIPT");
scriptErrorSuppressed.type = "text/javascript";
scriptErrorSuppressed.text = DisableScriptError;
IHTMLElementCollection nodes = doc2.getElementsByTagName("head");
foreach (IHTMLElement elem in nodes)
{

HTMLHeadElement head = (HTMLHeadElement)elem;
head.appendChild((IHTMLDOMNode)scriptErrorSuppressed);
}
}


3rd Part of script is that special class:

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[ComVisible(true)]
public class ObjectForScriptingHelper
{
TestingWindow m_Window;

public ObjectForScriptingHelper(TestingWindow w)
{
m_Window = w;
}

public void onError(Object arg1, Object arg2, Object arg3)
{
m_Window.onError(arg1, arg2, arg3);
}
}


And 4th Part of code is point where you can write your code:

public void onError(Object arg1, Object arg2, Object arg3) {
//Put your handle here
}



GL & HF


SE keywords:
How to capture script error message in a WPF WebBrowser

WPF WebBrowser screenshot

Definition of the problem: Make a screenshot of WebBrowser component inside WPF application.

I've spent half of a day googling the problem.
Found some solutions
- Using "VisualBrush" - does not work for WPF, creates black image.
- Using "FromImage" - does not work either with WPF.

Finally found this one.
Much better! But there are still "BUTS"

1. "This API was accessed with arguments from the wrong context." Did not have time to figure out, why this exception is being thrown. Something with the access permission from window to window or whatever. With other words if you get exception like that, use "Dispatcher.Invoke" part of the source-code posted below.
2. Full-Page. Some pages are longer than just one screen, so you need to make more than one screenshot to map whole page into image. There are also some DOM problems related to this task - some of the properties, like body.scrollTop just ain't being updated after you call window.scrollTo, killed some time for debugging.

Here is the source code of my final solution


browser.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(delegate(){
HTMLDocument htmlDoc = browser.Document as HTMLDocument;
HTMLBodyClass body = (HTMLBodyClass)htmlDoc.body;

var topLeftCorner = browser.PointToScreen(new System.Windows.Point(0, 0));

var topLeftGdiPoint = new System.Drawing.Point((int)topLeftCorner.X, (int)topLeftCorner.Y);
var size = new System.Drawing.Size(body.clientWidth, body.clientHeight);
var screenShot = new Bitmap(body.scrollWidth, body.scrollHeight);
var graphics = Graphics.FromImage(screenShot);
var cP = new System.Drawing.Point();
var i = 0;
var scrollTop = 0;
var cW = (int)browser.ActualWidth;
var cH = (int)browser.ActualHeight;
do
{
scrollTop = Math.Min(cH * i, body.scrollHeight - cH);
htmlDoc.parentWindow.scrollTo(0, scrollTop);
newWindow.UpdateLayout();
Thread.Sleep(1500);
cP.X = 0;
cP.Y = scrollTop;
graphics.CopyFromScreen(topLeftGdiPoint, cP, size, CopyPixelOperation.SourceCopy);
i++;
} while (scrollTop + cH < body.scrollHeight);

screenShot.Save(@"C:\temp\screens\page.png", ImageFormat.Png);
})
);


NB: This algo only scrolls vertically (downwards). But you can easily figure out the way of screening it horizontally too.

Gl & HF

Thursday, January 20, 2011

PHP improved gettype function

It's short and simple and more informative:

function get_type(&$v) {
return ($type = gettype($v))=="object" ? get_class($v) : $type;
}

Merge of PHP::gettype and PHP::get_class functions