12/31/2009

IE: change the value of a text input box on focus

IE has a strange behavior of setting the cursor to the beginning of the input box if you change the value of a text input on focus like this (using jQuery in this example):

$('#inputbox').focus(function() {$(this).val('somevalue')})

The way around this is to use event bubbling. You can use this script to allow jQuery live function to work with focus event: http://stackoverflow.com/questions/1199293/simulating-focus-and-blur-in-jquery-live-method (jQuery 1.4 and above should have this built in). So the correct code will look like:

$('#inputbox').live('focus', function() {$(this).val('somevalue')})

IE will not put the cursor in the exact position where user would expect it to be.

12/12/2009

Установка прошивки DD-WRT на маршрутизатор ASUS WL-520GC

Недавно приобрел себе маршрутизатор ASUS WL520GC для того, чтобы раздавать Wi-Fi интернет дома. Стандартная прошивка этого рутера облавает весьма скудными возможностями, например, поскольку подключен я к провайдеру через VPN, приходилось переподключать интернет каждое утро, поскольку соединение закрывалось по истесение некоторого периода неактивности. После не очень продолжительных поисков набрел на прошивку DD-WRT (http://dd-wrt.com/site/index). Прошивка (особенно в полной ее версии) предоставляет море полезного функционала, в том чиле поддержка соединения, удобный просмотр подключенных к ней клиентов, в том числе и беспроводным подключением (для беспроводных клиентов также показывается сила сигнала), позволяет мониторить трафик во всех подробностях и многое другое. К сожалению, объем флэш памяти в рутере 520GC всего 2Мб, поэтому поставить на него можно всего лишь микро версию прошивки. В этой версии, к большому моему разочарованию, отсутствуют многие полезные функции, а самое главное - PPTP клиент (передо мной стояла задача заставить рутер работать одновременно в локальной сети интернет провайдера и непосредсвтенно в интернет через VPN).

Итак, собственно установка:

1. Рутер не даст заменить прошивку, если в нем утановлена версия стандартной прошивки 2.0.1.0 или выше. Т.е. прежде, чем поставить прошивку DD-WRT, необходимо поставить в рутер более старую версию прошивки, например 2.0.0.8. Такая прошивка может быть скачана с официального сайта Asus (http://dlsvr04.asus.com/pub/ASUS/wireless/WL-520GC/FW_WL520gc_2008_EN.zip). Но для того, чтобы установить эту прошивку, нужно заставить рутер "думать", что эта версия прошивки новее, чем та которая уже установлена. Для этого нужно 2.0.0.8 в имени файла прошивки (.trx) заменить, например, на 2.0.1.2 (версия прошивки, которвя была установлена в моем рутере - 2.0.1.1). Теперь можно подгрзуить файл с прошивкой, через интерфейс обновления.

2. После всего этого можно наконец установить DD-WRT. На сайте программы есть достаточно удобный поиск (http://dd-wrt.com/site/support/router-database), который по модели рутера подскажет какую версию прошивки нужно установить. В поле поиска следует ввести 520GC. Странно, но для 520GC, среди предложенных прошивок, поиск предложил и версию мини, которая занимает больше 2 Мб. Не обрашая на версию мини внимания, выбираем версию микро (на сегодняшний день dd-wrt.v24_micro_generic.bin) и скачиваем. Этот файл заливаем в качестве новой прошивки через интерфейс обновления рутера.

3. После того, как прошивка закается на маршрутизатор и маршрутизатор перезапустится следует дать ему поработать пару минут, после чего можно приступить к настройке. Для этого в браудере вбиваем адрес маршрутизатора (по умолчанию 192.168.1.1). первым делом прошивка попросит вас создать логин и пароль для администратора. Вводим желаемый логин и пароль, и после этого переходим собственно к настройке. На закладке Setup > Basic setup в разделе WAN connection type вводим настройки подключения к провайдеру. Там в принципе все достаточно интуитивно. Остальные настройки можно смело оставить по умолчанию.

4. На закладке Wireless > Dasic settings вводим SSID - имя беспроводной сети. На закладке Wireless security вводим настройки безопасности. (проще всего на мой взгляд настроить WEP шифрование: просто вводим ключевую фразу и по ней генерируем ключи). Эти же ключи вводим в качестве ключей шифрования для WEP доступа на локальных компьютерах.

5. Все, маршрутизатор работает. Подробнее про установку прошивки можно также почитать здесь: http://www.dd-wrt.com/wiki/index.php/Installation

12/06/2009

Custom Tags in TinyMCE

One of the applications that I work with uses custom HTML-like tags to implement some of its functions. For example:

<review>Some text here</review>

The task was to create a plugin form TinyMCE that with a single click of a button would allow the user to wrap of portion of text ot HTML in such <review> tag. The task seems fairly simple and I was able to make it work pretty fast in all browsers, except IE. The problem is that TinyMCE uses DOM for processing HTML, however IE does not recognize any custom tags in DOM, thus it would simply ignore the custom tag that I put in. However, after a couple of days I've been able to solve that task as well. So let me start shwoing how the custom tag plugin is created and works.

To create new plugin in the plugins folder of the TinyMCE I create a new folder called KSReviewTag (this will be the name of the plugin). In this folder I have created a file called plugin_src.js: this will be the code for my plugin. TinyMCE comes with a bunch of plugins, so it is easy to see what the code of the plugin should be and what the interfaces are like. 

To allow the user wrapping HTML into the custom tag, a new TinyMCE command will need to be created. Since there will be only one button, the same command will be used to wrap the HTML and unwrap it, if it was already wrapped in the tag. Also, since TinyMCE and the browser do not know how to display this tag in the TinyMCE I am using SPAN with a class, so that user will be able to distinguish the text wrapped in the <review> tag. 

Adding a command looks like this:




ed.addCommand('mceKSReviewTag', function() {
var elm = ed.dom.getParent(ed.selection.getNode(), "SPAN.ksreview");
if (elm && elm.nodeName.toUpperCase() == "SPAN") {
tinyMCE.execCommand('mceRemoveNode', false, elm);
}
else {
ed.selection.setNode(ed.dom.create('span', {title: 'Review link', 'class': "ksreview"}, ed.selection.getContent()));
}
});

If the parent node of the current selection is <SPAN class="ksreview"> I remove it, otherwise I add it to the selection.

Assigning a command to a button is also really simple:



ed.addButton('KSReview', {
title : 'Review link',
cmd : 'mceKSReviewTag',
label: 'Review Link'
});


Now, when the user switches to the View Soucre mode of TinyMCE, or when the user saves the edited content I want him to see the custom tag, not the <SPAN> one. To achieve this I add a cusom handler to the PreProcess event:



ed.onPreProcess.add(function(ed, o) {
tinymce.each(ed.dom.select('span.ksreview', o.node), function(n) {
ed.dom.replace(ed.dom.create('review', null, n.innerHTML), n);
});
});


This code replaces all <SPAN class="ksreview"> tags with the custom < review> tag

Similarly, I want the custom tag to be replaced with SPAN tag when the user saves HTML content or when the editor first renders what has been previously saved in the TextArea.And this is where the Internet Explorer problem comes into play. Since IE does not understand custom tags, the TinyMCE would just drop it. However, it is not quite true to say that IE cannot work with custom tags: it can, but only in case id the custom tags have their own namespace. In other words the tag described here, if defined under the custom KS namespace would look like <ks:review>. But in order for IE to know that the KS namespace is valid it has to be mentioned at the definition of the HTML document. This is where I decided to modify the source code in the tinymce_src.js a little to make it able to support custom namespaces. In the tinymce_src.js I found where this HTML tag is defined for the editor's IFRAME and replaced it with the following:



var nsString = '';
if (s.customNS && s.customNS.length != 0) nsString = ' xmlns:' + s.customNS;
t.iframeHTML = s.doctype + '<html'+nsString+'><head xmlns="http://www.w3.org/1999/xhtml">';

So now I can add a custom namespace as a customNS configuration setting for the TinyMCE. In this case, I need to add custonNS: "ks" to the configuration settings of the editor.

So for internet explorer, bofre processing any content we need to replace <review> with <ks:review>. This is done with the following processing on the BeforeSetContent event:



ed.onBeforeSetContent.add( function(ed, o) {
if (tinymce.isIE) {
o.content = o.content.replace(new RegExp("<review>", "gi"),"<ks:review>");
o.content = o.content.replace(new RegExp("</review>", "gi"),"</ks:review>");
}
});


So the last thing left is to replace the custon tags with SPAN to display properly in the editor:



ed.onSetContent.add(function(ed, o) {
tinymce.each(ed.getDoc().getElementsByTagName("review"), function(n) {
ed.dom.replace(ed.dom.create('span', {title: 'Review link', 'class': "ksreview"}, n.innerHTML), n);
});
});


After all processing is done, all that's left to do is add some cosmetics: highlight the plugin button if the current selection is within the custom tag and display the custom tag in the DOM path properly:



ed.onNodeChange.add(function(ed, cm, n, co) {
n = ed.dom.getParent(n, 'SPAN.ksreview');

cm.setDisabled('KSReview', co);
cm.setActive('KSReview', 0);

// Activate all
if (n) {
do {
cm.setDisabled('KSReview', 0);
cm.setActive('KSReview', 1);
} while (n = n.parentNode);
}
});

if (ed.theme.onResolveName) {
ed.theme.onResolveName.add(function(th, o) {
var n = ed.dom.getParent(o.node, 'SPAN.ksreview');
if (n && n.nodeName.toUpperCase() == 'SPAN' && n.className.toUpperCase() == 'KSREVIEW') {
o.name = 'Review';
o.title = 'Review';
return false;
}
});
});