К вопросу о jQuery старших версий в Drupal 6

Главные вкладки

Аватар пользователя Cyber Cyber 16 февраля 2012 в 21:01

Исправления Drupal 6 для совместимости с jQuery 1.7.2 и более старших версий.

Работают все функции в том числе ajax, ahah, загрузка файлов, autocomplite, batch и tabledrag.

update: j 1.7.2 & j.forms 3.09

в 6.26 пофиксили tabledrag. Правка мелкая, но все же ( сабж в атаче + немного почиканый drupal.js );
новый jquery.forms.js ( v 3.09 )

cdn: http://malsup.github.com/jquery.form.js

или

git: https://github.com/malsup/form

В common.includes нужно заменить функции для преобразования в формат json:

/**
 * Converts a PHP variable into its Javascript equivalent.
 *
 * We use HTML-safe strings, i.e. with <, > and & escaped.
 */

function drupal_to_js($var) {
  switch (gettype($var)) {
    case 'boolean':
      return $var ? 'true' : 'false'; // Lowercase necessary!
    case 'integer':
    case 'double':
      return $var;
    case 'resource':
    case 'string':
   
// Always use Unicode escape sequences (\u0022) over JSON escape
// sequences (\") to prevent browsers interpreting these as
// special characters.

// Pattern :
// array(
//  [UTF8 (hex)] => [C/C++/Java Source code]
// );
// [updated] 10.06.2012

      $replace_pairs = array(
        // ", \ and U+0000 - U+001F must be escaped according to RFC 4627.
        "\x5c" => '\u005c',
        "\x22" => '\u0022',
        "\x00" => '\u0000',
        "\x01" => '\u0001',
        "\x02" => '\u0002',
        "\x03" => '\u0003',
        "\x04" => '\u0004',
        "\x05" => '\u0005',
        "\x06" => '\u0006',
        "\x07" => '\u0007',
        "\x08" => '\u0008',
        "\x09" => '\u0009', //TAB
        "\x0a" => '\u000a', //LF : Line Feed
        "\x0b" => '\u000b',
        "\x0c" => '\u000c',
        "\x0d" => '\u000d',
        "\x0e" => '\u000e',
        "\x0f" => '\u000f',
        "\x10" => '\u0010',
        "\x11" => '\u0011',
        "\x12" => '\u0012',
        "\x13" => '\u0013',
        "\x14" => '\u0014',
        "\x15" => '\u0015',
        "\x16" => '\u0016',
        "\x17" => '\u0017',
        "\x18" => '\u0018',
        "\x19" => '\u0019',
        "\x1a" => '\u001a',
        "\x1b" => '\u001b',
        "\x1c" => '\u001c',
        "\x1d" => '\u001d',
        "\x1e" => '\u001e',
        "\x1f" => '\u001f',
       
        // Prevent browsers from interpreting these as as special.
       
        "\x27" => '\u0027',
        "\x3c" => '\u003c',
        "\x3e" => '\u003e',

        "\x26" => '\u0026',
        "\x24" => '\u0024',
        "\x40" => '\u0040',

        "\x21" => '\u0021',
        "\x3a" => '\u003a',
        "\x3b" => '\u003b',
        "\x3f" => '\u003f',

        "\x5e" => '\u005e',

        "\x28" => '\u0028',
        "\x29" => '\u0029',

        "\x7c" => '\u007c',
        "\x60" => '\u0060',
        "\x7e" => '\u007e',

        // Prevent browsers from interpreting the solidus as special and
        // non-compliant JSON parsers from interpreting // as a comment.
       
        "\x2f" => '\u002f', // slash

        // While these are allowed unescaped according to ECMA-262, section
        // 15.12.2, they cause problems in some JSON parser.
        "\xe2\x80\xa8" => '\u2028', // U+2028, Line Separator.
        "\xe2\x80\xa9" => '\u2029', // U+2029, Paragraph Separator.
      );

      //return '"'. strtr($var, $replace_pairs) .'"';

      return '"' . unicode_replacer ( $var, $replace_pairs ) . '"';
     
    case 'array':
      // Arrays in JSON can't be associative. If the array is empty or if it
      // has sequential whole number keys starting with 0, it's not associative
      // so we can go ahead and convert it as an array.
      if (empty ($var) || array_keys($var) === range(0, sizeof($var) - 1)) {
        $output = array();
        foreach ($var as $v) {
          $output[] = drupal_to_js($v);
        }
        return '[ '. implode(', ', $output) .' ]';
      }
      // Otherwise, fall through to convert the array as an object.
    case 'object':
      $output = array();
      foreach ($var as $k => $v) {
        $output[] = drupal_to_js(strval($k)) .': '. drupal_to_js($v);
      }
      return '{ '. implode(', ', $output) .' }';
    default:
      return 'null';
  }
}

/*
 Alternate for strtr( ) looks like more speedy
*/

function unicode_replacer ( $text, $replace ) {
    $keys = array_keys($replace);
    $length = array_combine($keys, array_map('strlen', $keys));
    arsort($length);
   
    $array[] = $text;
    $count = 1;
    reset($length);
    while ($key = key($length)) {
        if (strpos($text, $key) !== false) {
            for ($i = 0; $i < $count; $i += 2) {
                if (($pos = strpos($array[$i], $key)) === false) continue;
                array_splice($array, $i, 1, array(substr($array[$i], 0, $pos), $replace[$key], substr($array[$i], $pos + strlen($key))));
                $count += 2;
            }
        }
        next($length);
    }
    return implode( $array );
}

/**
 * Return data in JSON format.
 *
 * This function should be used for JavaScript callback functions returning
 * data in JSON format. It sets the header for JavaScript output.
 *
 * param $var
 *   (optional) If set, the variable will be converted to JSON and output.
 */

function drupal_json($var = NULL) {
  // We are returning JavaScript, so tell the browser.
 
    drupal_set_header('Content-Type: application/json; charset=utf-8');
 
  if (isset($var)) {
    echo drupal_to_js($var);
  }
}

В атаче исправленные JS файлы из папки misc.

Что может произойти: некоторые написанные старым языком модули могут перестать работать. По своему опыту могу сказать, что все исправляется достаточно просто и все модули в основном написаны совместимо.

p.s.: если активно перебираете DOM, то вместо указателя на селектор $('selector') в скриптах можно использовать $.shell.find('selector'), который работает в области видимости только document без учета window, что несколько быстрее.( зачем так? затем что всякие дополнительные скрипты типа гуглпоиска, метрики, других решений, которые бомбят в документ фрейемы и прочие посторонние объекты могут реально раздувать поле выборки )

ВложениеРазмер
Иконка пакета drupal_javascripts_08_05_2012.zip31.5 КБ

Комментарии

Аватар пользователя sibero sibero 17 февраля 2012 в 0:20

"Cyber" wrote:
Если нужны JS с фиксами — могу выложить

Нужны, выкладывайте, хорошее дело.

А можете подробнее написать по поводу фикса? Как я понял это патч json для работы jqery 1.6 -1.7. На сколько корректно работает, не наблюдаются ли проблемы с ajax во views?

Аватар пользователя Cyber Cyber 17 февраля 2012 в 12:25

На вьюхе не проверял, но c новыми form.js работает на ура. Батч, загрузка файлов и т.д. Могут быть проблемы со старыми модулями, но там все просто фиксится.

Я хотел сделать сборку, но один, наверное, не смогу оказать ей должной поддержки, поэтому готов отдать все фиксы нуждающимся.

"sibero777" wrote:
А можете подробнее написать по поводу фикса?

могу. это в jquery изменилось представление кодировки json некоторых спецсимволов и, в виду, особенностей парсинга json, то, что было в Drupal стало непригодным.

Аватар пользователя zeliboba4 zeliboba4 19 апреля 2012 в 22:27

А у меня во views перестали раскрываться настройки. Плюс imce перестал загружать картинки. Никто не подскажет что поправить?

Аватар пользователя ii ii 18 мая 2012 в 20:13

Спасибо за ваш труд!

У меня после замены js поля imagefield ведут себя неправильно.
После начала загрузки файла в любой из них все поля imagefield становятся disabled.
После окончания загрузки атрибут disabled у полей не снимается.

Аватар пользователя Cyber Cyber 18 мая 2012 в 21:50

July 7, 2006 at 5:41am

Хм ... В модуле JS нет. Попробуйте поискать проблему в JS:

ImageField 6.x depends on the CCK and FileField modules

Возможно, где-то код устарел морально. Посмотреть в ближайшее время не могу, к сожалению.

Аватар пользователя Cyber Cyber 20 мая 2012 в 20:42

"ii" wrote:
У меня после замены js поля imagefield ведут себя неправильно.
После начала загрузки файла в любой из них все поля imagefield становятся disabled.
После окончания загрузки атрибут disabled у полей не снимается.

Времени не хватает. Сегодня понадобилась jquery.form отдельно. Выяснилась инетерсная деталь( дело толи в моих кривых руках и невнимательности, толи в библиотеке ).

Такая же реализация в друпал почему-то работает весьма адекватно:

<!DOCTYPE html>

<!--

        Shift (c) 2012 for ...

-->

<html>

<head>

<meta charset="utf-8">

<link rel="stylesheet" href="core.css">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<script src="http://malsup.github.com/jquery.form.js"></script>

<title>____</title>

</head>

<body>

<div id="shell">

        <!-- mail send form -->

        <form id="send" action="sender.php" enctype="multipart/form-data" method="post">

                <fieldset>

                        <legend>Отправка сообщения c вложением:

                                <!-- messages -->

                                <span id="messages">

                                </span>

                                <!-- #messages -->

                        </legend>

                       

                        <label for="recepient">Получатель:

                                <input name="email" id="recepient" type="text" placeholder="введите email получателя">

                        </label>

                               

                        <!-- #recepient -->    

                        <label for="subject">Тема:

                                <input name="subject" id="subject" type="text" placeholder="введите тему письма">

                        </label>

                               

                        <!-- #subject -->

                       

                        <br />

                        <label for="include" title="выбранный файл должен быть изображением">Вложение:

                                <input name="image" id="include" type="file">

                        </label>

                               

                        <!-- #include -->

                        <br />

                        <br style="clear: both" />                     

                        <label for="message">Текст сообщения:

                                <textarea name="message" id="message"></textarea>

                        </label>

               

                        <!-- #message -->

                        <br />

                        <br style="clear: both" />

                        <!-- #SEND# -->

                                <input type="submit" value="Отправить Почту">

                        <!-- #SEND# -->

                        <p style="clear: both" id="res">

                        </p>

                </fieldset>

        </form>

        <!-- mail send form -->

</div>

<script>

 

$(function() {

        // request options

                var options = {

                beforeSubmit:  check_form,  

                success:       success_form,  

                dataType:          'json'

        };

        // targets

                var form = $( '#send' , '#shell' );

                var msg  = $( '#messages' , form );

        // sending form

        form.submit( function( e ) {

                $(this).ajaxSubmit(options);

                e.preventDefault();

        });

        // helpers

        function check_form() {

       

        }

        function success_form( responseText, statusText ) {

                $( 'input', form ).removeClass('error');

                var status = ( responseText[0].txt );

                var field  = ( responseText[0].field_id ) ? responseText[0].field_id : false;

                if( field ) {

               

                        $( field ).addClass('error');

                        $( msg ).addClass('error');

                        //$( '#send ' + tgt ).clearFields();

                       

                } else {

                        $( msg ).removeClass('error').addClass('success');

                        $( 'input[type=submit]', form ).remove();

                }

                msg.text( status );

               

        }

});

</script>

<?php

//header( 'Content-Type: application/json; charset=utf-8' );
$status = array();

//email check
$email = ( !empty( $_POST['email'] ) && preg_match('/[^@]+\@[^\.]+\.[a-z]{2,4}/i'$_POST['email']) ) ? text_check$_POST['email'] ) : false;  

if( !

$email ) {

    

$status[] = array(
        
'txt' => 'проверьте поле email',
        
'field_id' => '#recepient',
    );

}

// subject check
if( !empty( $_POST['subject'] ) ) {

    

$subject text_check$_POST['subject'] );

} else {

    

$subject  false;
    
$status[] = array(
        
'txt' => 'проверьте поле "тема"',
        
'field_id' => '#subject',
    );

}

//message check
if( !empty( $_POST['message'] ) ) {

    

$message text_check$_POST['message'] );

} else {

    

$message false
    
$status[] = array(
        
'txt' => 'проверьте поле текста сообщения',
        
'field_id' => '#message',
    );

}

/* 

    (*)разобраться почему с помощью AJAX 
    в $_POST не приходит содержимое файла; 

image check 
if( !empty( $_POST['image'] && ) ) {

 //$_POST['image'] :: До сабмита переменная есть => после нету ):

} else {

    $image = false;
    $status = array_merge( 
        $status,  
        array(
        'txt' => 'выбранный файл не является изображением',
        'field_id' => '#message',
        )
    );
}
*/

/**
 * Prepare male to send
 */

if( $email && $subject && $message ) {

    

send_mail$email$subject$message$status );

} else {

    

// RETURN STATUS IN JSON FOR AJAX
    
$output json_encode$status );
    print 
$output;
}
       
    
// :: DEBUG ::        
    //print '<pre>';  
    //print_r( $status );
    //print_r( $_POST );
    //print '</pre>';  

/**
 *     helper functions for trim text
 */

function text_check$text ) {
    return 
strip_tagshtmlspecialcharsstripslashes$text ) ) );
}

/**
 * helper function for send mail
 */

function send_mail$recepient$subject$message$status )  { 
    
    if( 
mail$recepient $subject $message ) ) {

        

$status[] = array(
            
'txt' => 'письмо для ' $recepient " отправлено",
        );

    } 
    else {

        

$status[] = array(
            
'txt' => "ошибка: письмо не отправлено",
        );

    }

    

// RETURN STATUS IN JSON FOR AJAX
    
$output json_encode$status );
    print 
$output;

}
    

?>

Возможно затык где-то в этом, но не уверен. Я так понимаю там множественные поля с файлами ???

В пределах одной формы или в разных?

Отдельно файл, если нет тругих инпут отправляется -- вместе нет.

p.s.: кому надо - ковыряйте сами. у меня вроде работает. времени тупо не хватает

Аватар пользователя ii ii 21 мая 2012 в 22:03

мало, что из написанного понял ))

"Cyber" wrote:
Выяснилась инетерсная деталь( дело толи в моих кривых руках и невнимательности, толи в библиотеке ).

какая такая "интересная деталь" была выявлена?
да, дизаблятся разные поля одной формы.

Аватар пользователя Cyber Cyber 30 мая 2012 в 17:00

"kost" wrote:
Эти файлы затрутся при обновлении Drupal?

да. к счастью последние обновления не слишком масштабные. можно чэнджлог посмотреть и обновить только нужное.

Аватар пользователя Cyber Cyber 10 июня 2012 в 20:53

переделал hex'ы( http://www.fileformat.info/info/unicode/char/search.htm?q=%D1%91&preview... );

Буду признателен, если кто даст толковую ссылку на RFC, где описано, что именно должно маскироваться и в каком порядке( чет не могу найти; все кодировать смысла нет: сильно раздувает выхлоп ).

p.s.: надо будет по другому сделать; чем больше символов перекодируется, тем больше памяти жрёт.

можно юзать

Аватар пользователя Cyber Cyber 21 июня 2012 в 11:16

По поводу нативного и ненативного преобразования hex в unicode mask:

  1. <?phpstrtr($var, $replace_pairs);?>
  2. <?phpunicode_replacer ( $var, $replace_pairs );?>

Первая работает на порядок быстрее второй, но только на чистом сервере localhost. Разница достаточно ощутимая( где-то 500-800 ms на пробной замене );

На настроенном продакшн сервере вторая функция показывает лучшие результаты( чуть медленнее первой, скорость работы всегда стабильная -- нет разброса ). Если на Drupal включен кэш, то вторая функция выглядит гораздо эффективнее первой.

Видимо дело в opcode кэшере или чем-то еще( как вариант нативный вариант не может быть закешен и каждый раз отрабатывает с нуля, что дает свои корреляции на время обработки строк в зависимости от самочувствия сервера ... как-то так ). Таким образом я остановился на выборе самописной.

Аватар пользователя Green Chest Green Chest 13 января 2013 в 1:19

Советую никому не пользоваться рекомендациями в этой теме, какие они есть на данный момент. Я поймал ошибку, которую искал примерно 4 часа, я даже не мог понять в чём дело, что не так, никаких идей не было, а потом вспомнил, что воспользовался этими рекомендациям.

Вот здесь подробней - http://www.drupal.ru/node/94978

Аватар пользователя Punk_UnDeaD Punk_UnDeaD 13 января 2013 в 14:47

"Green Chest" wrote:
Советую никому не пользоваться рекомендациями в этой теме, какие они есть на данный момент. Я поймал ошибку, которую искал примерно 4 часа, я даже не мог понять в чём дело, что не так, никаких идей не было, а потом вспомнил, что воспользовался этими рекомендациям.

просто за совместимостью библиотек надо следить, а не бездумно обновлять всё подряд

Аватар пользователя svaroha svaroha 5 ноября 2013 в 14:17

Спасибо за проделанную работу.
Добавь в свой массив несколько элементов (с https://api.drupal.org/api/drupal/includes!json-encode.inc/function/drup...)
« // Prevent browsers from interpreting these as as special.
"'" => '\u0027',
'<' => '\u003C',
'>' => '\u003E',
'&' => '\u0026',

// Prevent browsers from interpreting the solidus as special and
// non-compliant JSON parsers from interpreting // as a comment.
'/' => '\u002F',
»
У меня без этих строк не получалось распарсить json-массив.