Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Получение значения указателя объекта


Автор: Gwire 8.7.2008, 19:24

У меня есть станицы на которой много элементов тегов <select>, <input>, <textarea> и др.
Причем их количество на каждой из станиц разное, разные параметры. Одни видемые другие нет.

В процессе выполнения скрипта мне нужно деактивировать все элементы. Пример деактивации всех объектов для <input>:
Код

Elements = document.getElementsByTagName('*')
for(i = 0; i < Elements.length; i++)
    Elements[i].disabled = true;

Аналогично для <select> и <textarea>.

Позже мне нужно востановить значения активности. Допустим так:
Код

// Сохраняю
var Mem = new Array();
for(i = 0; i < Elements.length; i++)
{   Mem.push( Elements[i].disabled );
    Elements[i].disabled = true;
}

// Востанавливаю
for(i = Elements.length-1; i >= 0; i--)
    Elements[i].disabled = Mem.pop();

И вроде все нортально, но у меня есть необходимось в этот массив сохранить не только "Elements[i].disabled",
а еще и "document.body.scroll", "document.body.bgColor", "document.body.onclick" и др.

Я питаюсь найти альтернативу запоминания порядка "push-ирования". Через простое сохранение значения указателя:
Код

TElMem = record
  Handle: Pointer;
  Value: String;
end;

Код

struct
{   int Handle;
    char* Value;
} TElMem;


Подскажите
1) как структуры определяются в javascript и
2) как получить указатель на объект?


Автор: bars80080 9.7.2008, 09:17
деактивация? а с какой целью? мож проще залить всё сверху сплошным слоем, через который не пробиться?

Автор: Gwire 9.7.2008, 10:26
smile Я в принципе занал, что не у кого не найдется ответа на мой впрос.

 smile  bars80080, если бы вопрос звучал "Стоит ли мне деактивиновать обекты?", то ваше сообщение было бы к стати.
Поповоду "проще залить всё сверху сплошным слоем" я использую такую конструкцию:
Код

<style>
    #coverlet
    {   display: none;
        position: absolute;
        top: 0px;
        left: 0px;
        width: 100%;
        height: 100%;
        background-color: #000000;
        filter: alpha(opacity=80);
    }
</style>
<script>
    var coverlet = document.createElement('div');
    coverlet.id = 'coverlet';
    coverlet.name = 'coverlet';
</script>

но есть одно "НО" с помощью [TAB] можно перейти на закритые объекты. По тому-то и нужна деактивация.

smile И вообще я питаюсь узнать
1) как получить указатель на объект и
2) как определяются структуры в javascript?

Автор: bars80080 9.7.2008, 11:24
нет, ну почему, может быть удастся пройти по DOM и деактивировать всё подряд:
Код

function deactive(obj) {
    for(i = 0; i < obj.childNodes.length; i++) {
        var el = obj.childNodes[i];
        deactive(el);
        el.disabled = false;
    }
    return;                               
}
</script>
</head>
<body onload="deactive(document.getElementsByTagName('body')[0]);">
 что-то в таком духе

Автор: Gwire 9.7.2008, 12:13
smile bars80080 вообще прикольно рекурсивно деактивировать "все подряд".
А как на счет: структур в javascript и получения указателя на объект?

Автор: dsCode 9.7.2008, 12:17
Цитата(Gwire @  8.7.2008,  19:24 Найти цитируемый пост)
1) как структуры определяются в javascript и


в JS эту роль играют объекты (хэши):

Код

var TElMem = {
  Handle: 'bla-bla',
  Value: 'bla-bla-2'
};



Цитата(Gwire @  8.7.2008,  19:24 Найти цитируемый пост)
2) как получить указатель на объект?


в JS нет указателей; присваивая переменной объект, можно на него сослаться:

Код

var a = {b: 1};
alert(a.b);
var c = a;
c.b = 2; // поменяли в c
alert(a.b); // отразилось на a



Автор: Gwire 10.7.2008, 10:12
 smile dsCode за структуры спасибо. smile А вот с указателями конечно жаль.

Такой пример:
Мне нужно сохранить значения document.body.scroll, "document.getElementsByTagName('input')[0..n].disable", document.body.onload, document.title,  и еще много другой информации в массив.

Понятно, что это все примитивы а не объекты. Если сохранять объекты, например document.body, то я не буду знать, какие данные мне нужно востанавливать onload или scroll, или то и другое.

Хотелось бы чтобы можно было осуществить такой алгоритм:
Код

var Mem = new Array();
// Сохранение переменных
Mem.push( { Handle: <указатель_1>, Value: <значение_1>} );
Mem.push( { Handle: <указатель_2>, Value: <значение_2>} );
Mem.push( { Handle: <указатель_3>, Value: <значение_3>} );

// Востановление переменных
for (i = 0; i < Mem.length; i++)
{   ElMem = Mem.pop();
    ЧислоВУказатель(ElMem.Handle) = ElMem.Value;
}


Автор: dsCode 10.7.2008, 12:37
Цитата(Gwire @  10.7.2008,  10:12 Найти цитируемый пост)
Если сохранять объекты, например document.body, то я не буду знать, какие данные мне нужно востанавливать onload или scroll


можно сохранять объект и массив свойств этого объекта для восстановления; кстати, свойство onload, например, - так же является объектом, а не примитивом (т.е. при восстановлении можно сослаться на него прямо).

P.S.: вообще, затея несколько странная

Автор: Sannis 10.7.2008, 12:40
А не проще ли ловить табуляцию по событию и прекращать его, вроде ж можно так?

Автор: ksnk 12.7.2008, 10:44
Толком не догнал, что-же нужно топикстартеру smile
Насколько удалось  понять - нужно сохранить "предыдущее состояние" "окна" и уметь восстанавливать его обратно.
Понятно, что абстрактная задача имеет абстрактную область применения, так что добавим конкретики.
"Окно" - состояние дерева объектов. Под "состоянием" будем иметь ввиду набор свойств (зафиксированный набор) какой-то веточки этого дерева.

Итого - решение становиться несколько более очевидным. Нужно каждое действие по изменению состояния записывать в какой-то лог, а затем, по этому логу восстанавливать обратно. Чтобы "пометить" изменяемый объект - мы будем присваивать ему новый уникальный идентификатор, если, у него его не было.

Код

function getId(el){
  var _id=el.getAttribute('id');
  if(!_id) {
     el.setAttribute('id','~id_'+(getId.nextId++));
     return el.getAttribute('id');
  }
  return _id;
}
getId.nextId=1;


Теперь сочиним функции изменения свойства и записи в лог. Зафиксируем набор свойств - пусть это будет backgroundColor и display. 
Код

var LOG=[];

function ch_bGround(el,newval){
    LOG.push({act:'backgroundColor',val:el.style.backgroundColor, id:getId(el)});
    el.style.backgroundColor=newval;
}

function ch_display(el,newval){
    LOG.push({act:'display',val:el.style.display, id:getId(el)});
    el.style.display=newval;
}


Ну и восстанавливать обратно по логу состояние объектов 
Код

function rollback(){
  var x=LOG.length;
  while(x--){
     document.getElementById(LOG[x].id).style[LOG[x].act]=LOG[x].val;
  }
}


Помогло?



Автор: Gwire 16.7.2008, 10:56
Над таким решением я уже думал. Правда не так "прямо" (у меня черт ногу сломит).
Но этот вариант не подходит из-за не универсальности.

Функция должна принимать совершенно произвольные значения, заранее не известные.

Автор: ksnk 16.7.2008, 15:29
Если функция принимает совершенно неизвестные значения, то и сделать она сможет только неизвестно что ;-) Задача должна ставится конкретно, тогда и решение надется само...

Автор: Gwire 22.7.2008, 12:18
Возможно код объяснит лучше, что именно я питаюсь добиться.
Код

// Какие-то глобальные переменные (для примера)
var v1, v2, v3, v4, v5, v6, v7, v8, v9: Variant;

type
  TElement = record
    Value: Variant;  // использую Variant т.к. в JS безтиповые переменные
    Address: Integer;
  end;

var MemArr: array of TElement;

// Сохранение значения переменой (если будет кто использовать "var" в вызове обязательно)
procedure MemSave(var Val: Variant);
var El: TElement;
    L: Integer;
begin
    El.Value:= Val;
    El.Address:= Integer( @Val );

    L:= Length(MemArr);
    SetLength( MemArr, L+1 );
    MemArr[L]:= El;
end;

// Востановление всех значений
procedure MemRestore();
var P: Pointer;
    i: Integer;
begin
    for i:= 0 to Length(MemArr)-1 do
    begin
        P:= Pointer(MemArr[i].Address);
        Variant(P^):= MemArr[i].Value;
    end;
    SetLength(MemArr, 0); // Сбрасиваю массив
end;

procedure Test();
begin   // #10 == '\r'   #13 == '\n'
    v1:= '- 111 -'#10#13;    v2:= '- 222 -'#10#13;    v3:= '- 333 -'#10#13;
    v4:= '- 444 -'#10#13;    v5:= '- 555 -'#10#13;    v6:= '- 666 -'#10#13;
    v7:= '- 777 -'#10#13;    v8:= '- 888 -'#10#13;    v9:= '- 999 -'#10#13;
    ShowMessage(v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8);

    // Сохраняю некоторые значения (совершенно произвольно!)
    MemSave(v5);
    MemSave(v8);
    MemSave(v2);
    MemSave(v4);

    //* Произвожу некие операций заданные алгоритмом разрабатываемого ПО.
        v4:= 4;
        v5:= 9;
        v2:= v4 + v5;
        v8:= 'v2 = '+ String(v2); // Конкретизирую v2 (задачи не касается)
        ShowMessage( v8 );
    //*

    // Востанавливаю все значения
    MemRestore;
    ShowMessage(v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8);
end;


Автор: ksnk 22.7.2008, 14:30
Gwire, Нет. Паскаль не подходит. Нужно попытаться словами объяснить что-же надо сделать. Это очень сильная магия! После формулировки правильными словами многие задачи решаются сами. smile
Еще интересует почему предложенная мной схема отличается принципиально от приведенной в Паскальном тексте?

Автор: Gwire 23.7.2008, 15:28
Незнание ответа влечет за собой формулировку вариантов решения.
Вариантов, не всегда, как стает известно в последствии, подходящих для решения паставленной задачи.

Алгоритм решения этой задачи не должен ссылаться не накие либо елеленты кроме переменной значение которой нужно сохранить.
Функции должно быть совершенно все равно какому объекту пренадлежит переменная. Приведений мной выше пример на Delphi перевести на javascript несоставляет труда, кроме конструкций "@Val" (получение адреса)  и "P^" (обращение к значению).

P.S. dsCode Хочу заметить..,
Код

Test_1_Func = function(){};
Test_2_Func = Test_1_Func;
if (Test_1_Func == Test_2_Func) alert(true); else alert(false);    // true

Test_2_Func = function(){};
if (Test_1_Func == Test_2_Func) alert(true); else alert(false);    // false

if (function(){} == function(){}) alert(true); else alert(false);  // false

что перемення функции не содержит указатель на фукцию (строки 5 и 6), как это происходит с объектами и значения присваиваются так же как и у примитивов.

Автор: krundetz 23.7.2008, 16:36
Насколько я понял проблема в том что у вас есть некий массив который содержит разномастные элементы и вам необходимо пробежаться по нему и продесаблить все элемены формы. Если я прав то посмотрите в сторону проверки типа DOM элемента. Ведь DOM элементы это обекты и у них уже есть определеные свойтва которые можно использовать и которые указывают на тип элемента. Вроде это свойство называется nodeType, но это не точно уточните в справочнике.

Автор: dsCode 23.7.2008, 16:41
Цитата(Gwire @  23.7.2008,  15:28 Найти цитируемый пост)
dsCode Хочу заметить.. (строки 5 ..


В строке 5 Вы Test_2_Func присваиваете новое значение.

Цитата(Gwire @  23.7.2008,  15:28 Найти цитируемый пост)
как это происходит с объектами


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

Код

<body onload="alert(1);">


Код

var a = window;

a.onload = function() {
  alert(2);
  return true;
};

window.onload(); // 2

Автор: ksnk 23.7.2008, 16:51
Специфика JS не позволяет хранить чистые указатели, но, как всегда, есть "обходной путь"
Код

var LOG=[];

function ch_Any(el,prop,newval){
    LOG.push({el:el,prop:prop,val:el[prop]});
    el[prop]=newval;
}

function rollback(){
  var x=LOG.length,roll;
  while(LOG.length){
    roll= LOG.pop();
    roll.el[roll.prop]=roll.val;
  }
  roll=null;
}


ch_Any(document.body.style,'backgroundColor','#cccccc');
setTimeout(function(){
rollback();
},5000);



получилось покороче. чем на Паскале smile


Автор: Gwire 24.7.2008, 12:58
Цитата(ksnk @  23.7.2008,  16:51 Найти цитируемый пост)
получилось покороче. чем на Паскале

Не намного  smile
Код

var Log: array of record V: Variant; A: Pointer; end;

procedure ch_Any(P: Pointer);
var L: Integer;
begin
    L:= Length(Log);
    SetLength( Log, L+1 );
    Log[L].V:= Variant(P^);
    Log[L].A:= P;
end;

procedure rollback();
var i: Integer;
begin
    for i:= 0 to Length(Log)-1 do
        Variant(Log[i].A^):= Log[i].V;
    SetLength(Log, 0);
end;


ksnk: А вообще решение интересное. Спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)