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

Friday, September 24, 2010

Update multiple records with single query, or Bundle Record Update

Actually it's a lie, it's not a single query, it's 3 queries, but it's still much more sufficient if you deal with more than 3 records to be updated with different values.

So, the problem is to run lot of update queries like:
update table_name set value_column='value1' where key_column = key1;
update table_name set value_column='value2' where key_column = key2;
...
update table_name set value_column='valueN' where key_column = keyN;

If you have N more than 3, then you should test the performance of the following approach:
1. create temporary table temp_table(k int,v varchar);
2. insert int temp_tabl values
(key1,'value1'),
(key2,'value2'),
...,
(keyN,'valueN')

3. update table_name, temp_table set
table_name.value_column=temp_table.v
where table_name.key_column=temp_table.k

For ~50 records, it works ~2 times faster, so think about it.

Как-то-так

Friday, September 3, 2010

Eclipse PDT 64Bit Windows 7 problem

This was the first thing that I thought is happening - my PDT IDE is working too slow because of incompatibility with my 64bit OS. I was 100% sure... because PDT "ate" ~80-100% of one of my 4 CPUs. I hate these moments thinking that my QuatroCore SUCKS runing java app :( ... Thanks Lord I was wrong.

Just turn the Outline view OFF and CPU back to 10-20%... too many classes , methods, properties are killing Outline view in Eclipse PDT. Don't keep it constantly open.


Wednesday, September 1, 2010

SD Card size must be at least 9MB

If you receive this error when creating new Android Virtual Device (AVD) even though you've input much more than 9MiB into "SD Card size" field... Consider following advice:

Here is some additional detail on what sizes are considered valid or invalid when generating a new AVD (set to MiB): 0-8: invalid 9-2047: valid 2047-4104: invalid 4105-6143: valid 6144-8200: invalid 8201: valid

Taken from here

Installing Android SDK

What a wonderful day is when you start learning new things...

Today was one of those, cuz I've started with Android SDK. Downloaded (for Windows) it and run "SDK Setup.exe", then wanted to create new Virtual Device (AVD) and failed, cuz "Target dropdown" was disabled and New AVD Wizard complains that is should be selected.

I've started googling, got many advices, most of them too complicated to be true for my situation. From the bottom of my "IMHO" I felt that there should be easier way, and so it was.

I've noticed the error I ignored on the first run, something about "Setup was not able to fetch smth via https"...

So the first thing you should do after downloading and running Android SDK (Windows) , go to Settings and check "Force https:// ... sources to be fetched using http:// ...", then go to "Available packages" and Refresh. There should be more options available under main Repository URL... select them and Install.

Now you have some new Targets available on the "Create new Android Virtual Device (AVD)" Wizard window.

GL & HF

Monday, August 16, 2010

Sphinx extended query syntax

One advice I should give is about the syntax of query.

I your text-search involves more than one attribute, then you have two choices to build your query like:
1. Query: @attr1 "*keyword*" | @attr2 "*keyword*" | @attr3 "*keyword*"
2. Query: @(attr1|attr2|attr3) "*keyword*"

Now benchmarking:
1st Query, on 1000 iterations, took 23.2s of pure sphinx time
2nd Query, on 1000 iterations, took 16.2s of pure sphinx time.

Make you conclusions... ;)

PS: I also tried 3rd approach:
I made concatenated attribute, named it @attr1_attr2_attr3 in sphinx's configuration file, and query's format was like:
@attr1_attr2_attr3 "*keyword*"... 1000 iterations of this type of query, took 17.9 seconds... much better than 1st one, but still 2nd is better.

Wednesday, August 11, 2010

Bromine first install. Fatal error

I love those tricky moments, when you have to dance with a tambourine around your pc, to make it work using our galaxy logic etc.

So, the problem: I got following error when first started, freshly unzipped bromine project:


Notice: Trying to get property of non-object in /usr/home/.../www/cake/libs/cache/file.php on line 244

Fatal error: Call to a member function cd() on a non-object in /usr/home/.../www/cake/libs/cache/file.php on line 244

It's under FreeBSD (that should be important moment I guess).

You wanna know how this SHOULD be fixed?
Here is what I've found:

Go to www/app/config/core.php's line stating:
date_default_timezone_set('UTC');
and uncomment it.

Cake engine does not like when this line is commented out and acts unpredictably

IE8 dynamically created tables

I had to generate tables and append them to DOM dynamically (on ajax data requests responded).

IE8 acted as a bad-ass teacher to me, cuz I forgot to use tbody tag. So hopefully that helps:

BAD code:
var table = document.createElement("table");
var tr = document.createElement("tr");
table.appendChild(tr);
...
document.appendChild(table);

GOOD code:
var table = document.createElement("table");
var tbody = document.createElement("tbody");
var tr = document.createElement("tr");
tbody.appendChild(tr);
table.appendChild(tbody);
...
document.appendChild(table);

Otherwise IE ignores the content of your table and shows it with zero height and zero width.

I should mention, that IE8's Developer Tools did help me to find that out ;)

Niivisi

HTML Parsing Error: Unable to modify the parent container element before the child element is closed (KB927917)

When creating dynamically generated pages, you can meet following error in IE browser:

HTML Parsing Error: Unable to modify the parent container element before the child element is closed (KB927917)

That "KB927917" secret code also comes along with

Line: 0
Character: 0
Source: 0

So now you "know" where to dig to.

So I met one. And it was odd, cuz my JS is runing on Jquery's document.ready event, when everything should be ready:

$(document).ready(function(){
... my js ...
});

But it does not make any sense for IE? No. For FF3, Chrome, etc. does, but not for IE. So what does?

$(document).ready(function(){
setInterval("documentIsReallyReadyNowEvenInIE();",1000);
});
function documentIsReallyReadyNowEvenInIE() {
... my js ...
}

Вот-так-то

Monday, June 21, 2010

JQuery droppable "unspecified error" in IE

I was implementing some Drag'N'Drop algoritms using JQuery .draggable & .droppable plugins, when in IE got "unspecified error". Thanks to Microsoft, they finaly got released so called "Development Tools". Debugging my page using that, gave me exception inside jQuery's code. It was the line saying "d=b.getboundingclientrect()".

It got me a while to understand why that happens, and the answer is:
jQuery's event handles/listerners are not unbinded automatically from the elements you remove from the DOM... they keep firing. So every time you use something like $('...').droppable(...
you should also do $('...').droppable('destroy'), if you remove that $('...') from the DOM. I did.

Conclusion: $('...').droppable('destroy');


Friday, June 18, 2010

2010 FIFA WC

"2010 FIFA World Cup in SA... what's next? ISAF World Cup in Somali?"

VMware Workstation cannot connect to the virtual machine.

My VM was up for ~2 last weeks and it seemt to get tired, so it hung up today. Tried to restart VM, close VM, none worked.
- Closing VMWare workstation gave me error that VM is busy, so please wait for it to finish and then close ...
- Restarting VM was disabled, due to tireness I guess
- Windows's 7 resource manager said vmware.exe makes 0b/s writes and 0b/s reads to/from hard-drive

So it was obvious to me that the only solution is to find vmware.exe in processes list and kill it.

Runing it again and trying to play virtual machine gave me another riddle to solve:
"VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run the program and to access all directories it uses and rights to access all directories for temporary files."

I'll skip all the sarcasm on the usefullness of this advise and come right to the solution:
"Restart the Host computer" and it works nice.

Strange , cuz I remember the other time, that vmware.exe was restarted same gentle way, there were no problems appeared.

It's also fair to mention that before restarting the host computer I tried google... found a lot of hints how to fix that problem... Good for me I did not start trying any of them.

Conclusion: killing vm from the processes list is not always good idea

Santé!

Just another "another blog"

There won't be "In this blog i will..." in this message, cuz I will not.

I'm a 30 year male, specializing in "computer science".

The idea to open the blog came to me, when I realized that it is impossible to find some good answers for some not very common questions, which popup during my work. So "Just another blog" is intendet to be one of those useless places mis-indexed by searching engines.

Hopefully, one day, anyone beats the system and finds something usefull here, which i doubt.

Adiós