Проблема Script.aculo.us Autocompleter в IE

Интересно, что люди в этих ответах затронули как Object.keys(), так и for...of, но никогда не комбинировали их:

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

Вы не можете просто for...of Object, потому что это не итератор и for...index или .forEach() в Object.keys() являются уродливыми / неэффективными. Я рад, что большинство людей воздерживаются от for...in (с проверкой или без проверки .hasOwnProperty()), так как это тоже немного грязно, поэтому, кроме моего ответа выше, я здесь, чтобы сказать ...


Вы можете сделать обычные ассоциации объектов итерации! Поведение так же, как Map s с прямым использованием fancy for...of DEMO , работающего в Chrome и FF (я предполагаю только ES6)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);

//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

Пока вы включаете моя подкладка ниже:

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

Без создания реального объекта карты, который не имеет приятного синтаксического сахара.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

На самом деле, с помощью этой прокладки, если вы все еще хотели воспользоваться другими функциональными возможностями карты (без их обкатки), но все же хотели использовать аккуратную нотацию объекта, поскольку теперь объекты теперь можно итерабельны, теперь вы можете просто сделать карту из нее!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

Для тех, кто не любит подмешивать или вообще не вмешивается в prototype, не стесняйтесь делать эту функцию на окне, называя ее чем-то вроде getObjIterator(), тогда:

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

Теперь вы можете просто называть его обычной функцией, ничего больше не влияет

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

или

for (let pair of getObjIterator(ordinaryObject))

Нет причин, по которым это не было бы

Добро пожаловать в будущее.

6
задан Rob W 27 December 2011 в 22:35
поделиться

5 ответов

У меня действительно есть та же самая проблема. Проблема только происходит в IE (также в 8,0 бетах)

И Firefox и Chrome, который я попробовал, не имейте никаких проблем вообще.

По словам других это происходит из-за объявления DOCTYPE в файле HTML. Проверьте здесь: http://prototype.lighthouseapp.com/projects/8887/tickets/32-ajax-autocomplete-in-ie-with-doctype

Ошибка также получила билет в рубиновых платах разработчика: http://dev.rubyonrails.org/ticket/11051

Обе ссылки имеют решения решить проблему.

Надо надеяться, ошибка будет исправлена в следующей версии prototype/scriptaculous :)

5
ответ дан 8 December 2019 в 17:31
поделиться

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

new Ajax.Autocompleter(textInputId, suggestionsHolderId, suggestionsUrl, params);

//Hack
Event.observe(window, 'load', function()
{
    try
    {
        Position.clone($(textInputId), $(suggestionsHolderId),
            { setHeight: false, offsetTop: $(textInputId).offsetHeight});
    }
    catch(e){}
});
1
ответ дан 8 December 2019 в 17:31
поделиться

Находится Ваша проблема только в IE, или во всех браузерах? Игнорирование первого символа является на самом деле значением по умолчанию для Autocompleter. В controls.js существует класс под названием Autocompleter. Локальный, который имеет поле, названное partialChars который значения по умолчанию к 2. В документах для того поля говорится:

//-partialChars - Сколько символов для ввода перед инициированием
//частичное соответствие (в отличие от minChars, который определяет
//сколько символов требуется, чтобы делать любое соответствие
//вообще). Значения по умолчанию к 2.

2
ответ дан 8 December 2019 в 17:31
поделиться

Большое спасибо за взлом. Я сам использовал это, но модифицировал его так, что он вызывается только тогда, когда используется Ajax.Autocompleter, выполнив следующие действия.

function positionAuto(element, entry) {
    setTimeout( function() {
      Element.clonePosition('choices_div', 'text_element', {
      'setWidth': false,
      'setHeight': false,
      'offsetTop': $('text_element').offsetHeight
    } );
  }, 300);
  return entry;
}

new Ajax.Autocompleter('text_element', 'choices_div', [url to web service], {
  paramName: 'fulltext',
  minChars: 2,
  callback: positionAuto, // See above
  [etc...]

Поскольку обратный вызов вызывается непосредственно перед выполнением реального запроса, размещение DIV именно в этот момент приводит к самый разумный. И убедитесь, что даже если размер окна изменяется или прокручивается, DIV расположен правильно. Что бесит, так это то, что для того, чтобы заставить его работать стабильно, мне пришлось заключить его в «setTimeout ()». Я не очень много экспериментировал с различными настройками времени, но если есть более низкий порог тайм-аута, который работает, я хотел бы знать.

Протестировано в IE 8 и 7 и работает очень хорошо. И работает с другими реальными браузерами. Надеюсь, это избавит некоторых программистов от головной боли при работе с этим.

3
ответ дан 8 December 2019 в 17:31
поделиться

Это известная ошибка с исправлением, которое работает, но еще не добавлено. Подробнее об этом можно прочитать здесь: https://prototype.lighthouseapp.com/projects/8886-prototype/tickets/618-getoffsetparent-returns-body-for-new-hidden-elements-in-ie8-final # ticket-618-9

1
ответ дан 8 December 2019 в 17:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: