[

вторник, 19 июля 2011 г.

Upd: Ajax отправка формы с файлом на jQuery

Вчерашний пост по поводу отправки формы с файлом через AJAX не завелся с IE. Беглый взгляд в консоль разработчика показал, что IE отправляет форму не через POST, а через GET. Не долго думая решил попробовать 2ю версию работы с jQuery Form.

Итак, форма:

<form id="ajax_form" method="post" action="/path/to/form/processing/" enctype="multipart/form-data">
<input type="text" name="some_text" />
<input type="file" name="some_file" />
<input type="submit" value="Post" />
</form>

Форма как форма. Отправка будет происходить, как с обычной формой, по нажатию на кнопку Post, которая теперь обычный submit. Для того, чтобы обернуть ее в iframe, надо в $(document).ready() инициализировать ajaxForm:

$(document).ready(function(){
    
    $('#ajax_form').ajaxForm({
        success: function(data) {
            alert(data);
        }
    });
});

Программно отправить форму можно так: $('#ajax_form').submit().

Проблема решена, но осталось 2 вопроса из-за чего не работает первый вариант в IE:

  1. неправильно работает плагин?
  2. проблемы с IE и какие? (в других браузерах все на ура)
Если глючит код плагина - невелика беда. Если же дело в IE, то может быть кто-нибудь уже с этим сталкивался и осознал в чем тут дело?

понедельник, 18 июля 2011 г.

Ajax отправка формы с файлом на jQuery

Не все так хорошо, как казалось - данный код не работает в IE! К сожалению, своего IE у меня нет - обычно "отбираю" ноут у кого-нибудь из родственников, но я таки переписал код по-другому (и не раз), и форма заработала. Новый пост тут.

Ни для кого не секрет, что через AJAX (XMLHttpRequest) нельзя отправить форму с файлом... в том смысле в каком все привыкли это делать обычным POST'ом. Весьма распространенный ход в этом случае - создать iframe, в нем форму, и отправить ее.

Безусловно это не так сложно, как кажется на первый взгляд, однако, зачем изобретать велосипед? Погуглив вчера нашел весьма удобный в обращении плагин jQuery Form.

Допустим, вы создаете динамически (в оверлее) форму следующего содержания:

<form id="ajax_form" enctype="multipart/form-data" onsubmit="return false;">
<input type="text" name="some_text" /><br />
<input type="file" name="some_file" /><br />
<button onclick="ajaxPostForm()">Post</button>
</form>

и хотите, чтобы по нажатию на Post форма отправлялась через AJAX. Используя jQuery Form это можно сделать несколькими способами, я покажу наиболее близкий к $.post():

function ajaxPostForm() {
    // получим форму
    var form = $('#ajax_form');
    // обернем ее в IFrame - поступаем как при использовании практически любого jQuery плагина
    form.ajaxForm();
    // отправим форму - большинство параметров как у $.ajax()
    form.ajaxSubmit({
        url: '/path/to/form/processing/',
        success: function(data) {
            alert(data);
        }
    });
}

И some_text и some_file ушли на сервер. Ура!

суббота, 16 июля 2011 г.

Множественный вход Google

Пару дней назад, придя на работу и открыв браузер, увидел, что gmail.com аккаунт разлогинен... Ничего страшного, бывает! Ввожу логин и пароль - вошел. Ок, теперь корпоративная почта (она тоже на gmail.com), ввожу логин/пароль и... я уже вошел, сообщил мне Google! Да не просто, а еще и предложил продолжить или отменить новый вход. Непочуяв подвоха я нажал продолжить - вошел.

Дело пошло, можно продолжать утренний моцион - прочтение почты. И тут я, что меня "обманули" - выбросили из первого аккаунта! Понимая, что так не может быть и где-то должна быть настройка, я полез ее искать в Google, куда же еще!?:) Вот она заветная ссылка на справку.

Важно! чтобы войти во второй, третий и т. д. аккаунты, воспользуйтесь ссылкой "Войти еще в один аккаунт..." в выпадающем меню аккаунта на верхней панеле, иначе вас опять выбросит, так как множественный вход должен быть включен на всех аккаунтах:)

Тоже важно! сервисы, неподдерживающие множественный вход, будут использовать тот аккаунт, которым вы вошли первым.

PS: хочется сказать, что это первая фишка от Google, которая вывела меня из себя!

пятница, 15 июля 2011 г.

SyntaxHighlighter 3 и с чем его едят

Вот все хорошо с Blogger'ом, за исключением подсветки кода:) Немного погуглив нашел такую вещь как SyntaxHighlighter, а там и статью о интеграции его в Blogger (первая в списке;)).

Вот что из этого вышло:
parents, babies = (1, 1)
while babies < 100:
    print 'This generation has %d babies' % babies
    parents, babies = (babies, parents + babies)

К сожалению, не получилось "завести" SH с автозагрузкой кистей. если будет время еще разберусь.

понедельник, 11 июля 2011 г.

Программное создание Dojo формы из JSON

Понедельник утро... самое время собрать мозги в кучу!

На этот раз расскажу об одной интересной наработке - как я программно создаю форму Dojo из JSON. Задумав сие я стал бродить по интернету и наткнулся на весьма интересный пост. Он то и послужил основой для моего класса.

Прежде всего, для затравки, покажу как выводится форма:

dojo.xhrGet({
    url: '/path/to/form/json/',
    handleAs: 'json',
    load: function(data) {
        var form = new JSONForm(data);
        dojo.byId('container').innerHTML = form.generate();
    }
});

Сгенерированный HTML код формы будет размещен в контейнере c ID container. Просто и быстро.

JSON код (основной) формы в моем случае выглядит так:
{ 

  "id" : "form_id", /* ID формы */
  "params" :  /* Параметры формы */
    { 
      "action" : "/path/to/form/post/",
      "encType" : "multipart/form-data",
      "method" : ""
    },
  "fields" : /* Массив полей */
    [ 
      { 
        "name" : "field_name", /* Название поля в формы */
        "widget" : "TextInput", /* Тип виджета */
        "params" : /* Параметры, передаются конструктору виджета Dojo */
          { 
            "id" : "field1_id", /* ID виджета Dojo (domeNode) */
            "label" : "Подпись:", /* Подпись поля */
            "name" : "widget_name" /* Название HTML элемента формы */
            /* любые другие параметры для виджета */
          }
      }
    ]
}

Тут стоит рассказать о нескольких моментах:

  1. в отличии поста на stackoverflow.org, я передаю не класс Dojo виджета в параметре widget, а, вообще говоря, ключ по которому мой класс JSONForm делает отображение на класс Dojo виджета
  2. у поля есть два свойства name: одно непосредственно в объекте field, а другое в объекте params. Дело в том, что форма на сервере (а я использую Django forms) помимо названия полей имеет еще и префикс для того, чтобы можно было скомбинировать несколько форм с одинаковыми именами полей под одним тегом формы. Так что field.name - это имя поля в форме, а field.params.name - имя поля в HTML коде.

Теперь, когда понятно в каком виде приходит форма с сервера и как она выводится, перейдем к классу JSONForm. Безусловно он написан с помощью классов Dojo.

dojo.declare('JSONForm', null, {
    
    /*
     * Отображение типов виджетов, пришедших с сервера на Dojo воджеты
     */
    _widget2dijit: {
        'Textarea': dijit.form.Textarea,
        'PasswordInput': dijit.form.ValidationTextBox,
        ...
    },

    /*
     * Конструктор
     */
    constructor: function(/* JSON Form Object */json) {
        // параметры формы
        this.id = json.id;
        this.params = json.params;
        this.params['id'] = this.id; // надо для создания виджета

        // создадим форму
        this.form = new dijit.form.Form(this.params);
        
        // поля формы
        this.fields = [];
        // поля формы с ключем по имени поля
        this.fields_dict = {};

        // создадим поля
        dojo.forEach(json.fields, function(item, index){
            this.fields[index] = this._get_dijit(item);
            this.fields_dict[item.name] = this.fields[index];
        }, this);
    },

    /*
     * Получим класс Dijit'a
     */
    _get_dijit: function(field) {
        var widget = this._widgit2dijit[field.widget];
        return widget(field.params);
    },

    /*
     * Генерация формы
     */
    generate: function() {
        // получим тег формы
        var form = this.form.domNode;

        // добавим поля
        dojo.forEach(this.fields, function(item, index){
            dojo.place(item.domNode, form);
        }, this);

        // добавим кнопку submit
        var submit = new dijit.form.Button({
            type: "submit",
            label: "Отправить"
        });
        dojo.place(submit.domNode, form);
        
        // вернем HTML нашей формы
        return form.domNode.innerHTML;
    }
});

Этого достаточно для создания и простейшего отображения полей.

Что с этим делать дальше? Это только часть кода (и весьма упрощенная), которую я использую у себя в классе, однако, дальше развитие может пойти так:

  1. Шаблоны с _Templated  для большего контроля отображения формы.
  2. AJAX валидация полей - следующее чем хочу поделиться.
  3. AJAX отправка формы.
Если на стороне клиента есть необходимость отлавливать события полей, то это легко можно сделать с помощью dojo.connect (или dijit.connect):

dojo.xhrGet({
    url: '/path/to/form/json/',
    handleAs: 'json',
    load: function(data) {
        // создадим форму
        var form = new JSONForm(data);

        // присоединимся к событию onFocus поля "field1"
        form.fields_dict["field1"].connect(form.fields_dict["field1"],
            "onFocus", function(){ alert('Фокус!'); });

        // отобразим форму
        dojo.byId('container').innerHTML = form.generate();
    }
});

Ну как? надеюсь был полезен.

пятница, 8 июля 2011 г.

Перегрузка функций закодированых ionCube и т.п. в PHP 5.3

Хотел порадовать вас Django и Dojo, но волею судьбы пришлось возиться с PHP.

Итак, проблема: имеет файл file.php закодированный, например, ionCube. Надо узнать какие функции есть в нем и перегрузить какую-либо.

1. С помощью get_defined_functions() и Reflection или Doqumentor смотрим что есть в файле.

2. Далее, переименовываем файл в base.file.php и создаем file.php со следующим содержимым:

<?php
namespace testns;
require("base.file.php");
?>

3. Все хорошо, можем перегрузить, например, функцию test_func():

<?php
namespace testns;
require("base.file.php");

function test_func()
{
}
?>

Внутри файла вызов test_func() вызовет нашу новую функцию. Старую можно вызвать так: \test_func().

Вот, собственно, и все. За одним исключением: Если в файле base.file.php есть классы, то их нужно явно импортировать в текущий namespace. Например для класса TestClass это будет выглядеть так:

<?php
namespace testns;
require("base.file.php");

use \TestClass as TestClass;

function test_func()
{
}
?>

Надеюсь это кому-то поможет!

среда, 6 июля 2011 г.

Всем привет!

Долго ли, коротко ли, но я дошел до собственного блога!

Зовут меня Александр, живу и работаю в Санкт-Петербурге. Люблю жену, ребенка, люблю спорт (хоть сейчас и не частый гость в додзе). Люблю веб и все что с этим связано, но особенно Python и Django! и хочу "поделиться" своей любовью с другими. Главное чтобы запал не пропал, но как говорится "надо себя заставить"! В моих ближайших планах несколько статей про Django и Dojo, и обработке форм.

За сим, откланяюсь.
И до скорого!