Confirm() на слоях.

Собственно, задача такова: нужно с помощью слоев (дабы его потом красиво оформить) и JS сымитировать стандартный диалог confirm().При чем, нужно сделать, чтобы из кода он вызывался точно так же, как и стандартный:
function make_action(arg){    if(div_confirm('Вы действительно хотите *something*?'))    {        arg.make();        return true;    }    else    {        return false;    }}
Как это все отрисовать правильно я уже знаю, а вот как правильно оформить div_confirm() не знаю :(Пока в голову приходить только такой алгоритм:
var confirm_flag = -1;var function div_confirm(text){confirm_flag = -1;// Абстрактная инициализация диалога и его отображениеsetDivText(text);showDiv('confirm_div');while(confirm_flag == -1){    sleep(100) // Спим 100 мсек, чтобы не перегружать браузер}hideDiv('confirm_div');return confirm_flag;}
При нажатии кнопки в диалоге confirm_flag будет устанавливаться в 1 или 0 в зависимости от нажатой кнопки.Но все упирается в отсутствие нормальной реализации sleep() в JS :(Посоветуйте, как еще можно такую вещь реализовать?
14 ответов

imho, так - нереально...А как насчет вот такого:
function make_action(arg){    div_confirm('Вы действительно хотите *something*?',  function(response){         if (response) arg.make();    })}
Ну а уж сам div-confirm в нужном месте это callback вызовет.


ksnk, так, конечно, тоже можно, однако если функция, в которой используется div_confirm() достаточно сложная, то ее дробление превращается в натуральный геморрой.А уж если div_confirm() используется в нескольких местах и притом в calback'e надо использовать значения, вычисленные до вызова div_confirm(), то это вообще никуда не годится :(


это от непонимания принципов яваскрипта  делай как он сказал - всё должно шоколадно получиться.


cruelangel, сдается мне, вы так говорите от непонимания того, чего я хочу.Объясню на примере:
<html> <head>  <title>Test</title>  <script>   var confirm_callback = undefined;      function div_confirm(text, callback)   {    confirm_callback = callback;    document.getElementById('confirm_box').style.display="block";    document.getElementById('text').innerHTML = text;   }      function div_confirm_callback(responce)   {    document.getElementById('confirm_box').style.display="none";    confirm_callback(responce);   }      function bar(responce)   {    if(responce)    {     alert('Прибавили: ' + String(calc + 20));    }    else    {     alert('Ну не хотите, как хотите число осталось прежним: ' + calc);    }   }      function foo()   {    var calc = (4/2-3)*4 // Некоторая абстрактная информация, которую мы долго и нудно обрабатывали ;)    if(calc < 0)     div_confirm('Прибавить к ' + calc + ' 20?', bar)    else     alert('Вот что у нас получилось:' + calc)   }  </script>  <style>   .confirm_box   {    position:absolute;    top:30%;    left:25%;    width:50%;    display:none;    border:dashed 1px #000;    background-color:#FFEEEE;    padding:10px;    text-align: center;   }  </style> </head> <body>  <div id="confirm_box" class="confirm_box">   <span id="text">      </span>   <br><br>   <input type="button" value="OK" onclick="div_confirm_callback(true)" id="ok_btn"><input type="button" value="CANCEL" onclick="div_confirm_callback(false)" id="cl_btn">  </div>  <input type="button" value="Go!" onclick="foo()"> </body></html>
Суть выполняемых действий:1) В ответ на некоторое действие пользователя, мы получаем некоторую информацию и что-то с нею делаем, причем делаем сложную и ресурсоемкую работу, которую категорически не хочется повторять еще раз2) Смотрим на результаты: если они нас не устраивают, спрашиваем пользователя, что делать3) В зависимости от решения пользователя мы хотим что-то еще сделать с той информацией.А вот тут-то и появляется принципиальный момент: переменная, которую мы старательно обсчитывали до запроса пользователю, была уничтожена в тот момент, когда завершила свое выполнение функция foo(). И мы до нее теперь никак дотянуться не можем. Что делать? Обсчитывать ее по второму кругу? Это не подходит - занятие это ресурсоемкое, да и условия с тех пор поменялись и результат может получиться совершенно не тот, который был изначально. => Вариант с callback'ом можно припасти на крайний случай, но в общем случае это далеко не самое лучшее решение.Уже вижу ехидный вопрос: "А что мешает объявить переменную calc вне функции, сделав ее глобальной? Тогда ее будет видно и в функции bar()". Отвечаю: "Во-первых, в реальном случае этих переменных, которые могут понадобиться при дальнейшей обработке может быть намного больше и объявлять их всех глобальными неудобно. Во-вторых, использование глобальных переменных во всех известных мне языках считается дурным тоном, что тоже немаловажно. Сомневаюсь, что в JS все наоборот".Так вот объясните мне, пожалуйста, где я неправильно понял принципы JS?С уважением.


нет, ехидным будет ответ: http://www.google.com/search?ie=UTF-8&...1%8F+javascript 


cruelangel, экое, однако, утонченное ехидство! Послать читать про замыкание с примерами на каких-то совсем уж искусственных языках... ;-)вот так - вполне себе заработает... внутри function (response){...} переменная calc все еще остается доступной!
   function foo()   {    var calc = (4/2-3)*4 // Некоторая абстрактная информация, которую мы долго и нудно обрабатывали ;)    if(calc < 0)     div_confirm('Прибавить к ' + calc + ' 20?', function(response){       if(responce)      {        alert('Прибавили: ' + String(calc + 20));      }      else      {        alert('Ну не хотите, как хотите число осталось прежним: ' + calc);      }     })    else     alert('Вот что у нас получилось:' + calc)   }
переменная, которую мы старательно обсчитывали до запроса пользователю, была уничтожена в тот момент, когда завершила свое выполнение функция foo().
Неправильно! Переменные в JS уничтожаются ТОЛЬКО когда они уже совсем никому не нужны ;) 


Alex13, день добрый. Начну с простого.Вы спрашиваете где неправильно поняли принципов javascript? Отвечаю: там, где пытаетесь программировать на яваскрипте, как на поточном языке. Яваскрипт - язык событийный. Поэтому про всякие sleep лучше сразу забыть. Есть всего пару исключений, которые блокируют поток яваскрипта - alert, confirm, prompt и может еще что-нибудь, что я забыл или не знаю. В остальном - событие-привязка-срабатывание.Вариант, предложенный ksnk сам не проверял ибо некрасивый подход, но могу предложить решить эту проблему так.Чего-то эта проблема задела. Посидел. Написал, как мне кажется, достаточно красиво (в смысле кода естественно).Местами я упростил себе работу можно было изящнее, но в общем думаю ясно.
<html><body style="margin:0"><style type="text/css">#confirm_div {    position: absolute;    border-left: 2px solid #C0C0C0;    border-top: 2px solid #C0C0C0;    border-right: 2px solid #222222;    border-bottom: 2px solid #222222;    padding: 3px;    background: #DADADA;}#confirm_div, #confirm_div input {    text-align: center;    font-family: Verdana;    font-size: 9px;    margin: 3px;}#confirm_div input {    width: 50px;}</style><input type="button" onclick="test()" value="Test" /><!-- наш див --><div id="confirm_div" style="display: none;">    <div style="display:inline" id="confirm_div_message"></div>    <p style="margin:10px"></p>    <input type="button" value="OK" onclick="$dc.ok()" />    <input type="button" value="Cancel" onclick="$dc.cancel()" /></div><script type="text/javascript">var $dc; //к сожалению совсем без глобалок никудаDivConfirm = function(div_id, message_id) {    this.div = document.getElementById(div_id);    this.message = document.getElementById(message_id);        this.callback = (function() {});    this.params = new Array();    this.show = function (message, callback, params) {        this.message.innerHTML = message;        this.div.style.visibility = 'hidden';        this.div.style.display = '';        this.div.style.left = Math.round(document.body.clientWidth/2 - this.div.offsetWidth/2) + 'px';        this.div.style.top = Math.round(document.body.clientHeight/2 - this.div.offsetHeight/2) + 'px';        this.div.style.visibility = '';                this.params = params;        this.callback = function (callback, paramsArray) {                                 return function() {                                    callback(paramsArray);                                }                            }(callback, this.params)    }        this.hide = function () {        this.div.style.display = 'none';    }    this.ok = function() {        this.callback();        this.hide();    }        this.cancel = function () {        alert('No problem. Your values: ' + this.params);        this.hide();    }}function superSumRound(values) {    sum = 0;    for (var i=0; i<values.length; i++) {        sum += values[i];    }    alert('Result is: '+Math.round(sum));}//--------------function test() {    //------- мегарассчеты -------    var calc1 = 4.4;    var calc2 = 2.1;        //------- забиваем их в массив -------    var params = new Array();    params.push(calc1);    params.push(calc2);        //------- понеслася -------    $dc = new DivConfirm('confirm_div', 'confirm_div_message');    $dc.show('Process values? "'+params.toString()+'"', superSumRound, params);}</script></body></HTML>


smartov, слишком много кода ради такой простой вещи.ksnk, исправилсо 


Вариант, предложенный ksnk сам не проверял ибо некрасивый подход,
 Позвольте поинтересоваться - чем замыкание "некрасивее" Вашего вызова неанонимной функции с передачей ей сложным образом каких-то параметров?  Кроме, конечно того, что при этом используется больше букв и дополнительных сущьностей?


Написал, как мне кажется, достаточно красиво (в смысле кода естественно).
Кажется, что красиво? Чтобы не казалось, можно для начала проверить свой код с помощью JSLint.


cruelangel, спасибо за иронию, помогло 
Переменные в JS уничтожаются ТОЛЬКО когда они уже совсем никому не нужны ;) 
Оно было бы здорово, только в приведенном мною примере она-таки уничтожалась, хотя я и хотел ее потом использовать ;)smartov, спасибо за подробный ответ, навело на некоторые мысли  Если ваш код скрестить с тем, что предложил ksnk может получиться довольно удобно AKS, если уж на то пошло, то ни один из приведенных примеров проверку не проходит...


код скрестить
Строчки 58-63 кода smartov можно переписать вот так
        this.callback = function () {                                     callback(params);                                }
 Согласитесь - если произнести заклинание четче - букв тратится меньше ;)Ну и если саму комбинацию вычислительных процедур - строки 83-107 заменить на 
function test() {    //------- мегарассчеты -------    var calc1 = 4.4;    var calc2 = 2.1;        //------- понеслася -------    $dc = new DivConfirm('confirm_div', 'confirm_div_message');    $dc.show('Process values? "'+[calc1,calc2].toString()+'"', function(){      var sum = calc1+calc2;      alert('Result is: '+Math.round(sum));    });}
, то получится еще компактнее и все еще достаточно привлекательно ;-)


...если уж на то пошло
А я тут ни при чем. "Пошло" не от меня (я не писал нечто, вроде: "Ваша вариант - некрасивый подход, написал свой - получилось достаточно красиво").
...ни один из приведенных примеров проверку не проходит
Это, наверно, повод для того, чтобы задуматься и сделать выводы (для своей же пользы - чтобы извлечь кое-какую выгоду).


cruelangel
слишком много кода ради такой простой вещи.
Если присмотреться там ничего лишнего нет кроме усложнения в анонимной функции, как правильно сказал ksnk. Я вынес в объект - вот и все. А так все нужное. Еще и не хватает кой чего - не очень гут что приходится указывать message_id. Было б не облом избавился бы от этого параметра 
Позвольте поинтересоваться - чем замыкание "некрасивее"
Позволю  Тем что логика у вас inline. В моем случае в нужном месте нужно написать одну строчку. В вашем - 10, что мало того что неудобно, так и трудно читаемо. Думаю вы понимаете и без лишних рассказов почему структурирование кода это хорошо.AKS
Кажется, что красиво? Чтобы не казалось, можно для начала проверить свой код с помощью JSLint.
Проверил. Кроме необязательных в принципе точек с запятыми и спорно лучшей литеральной нотации ничего нового он мне не рассказал. Что, в общем то, и следовало ожидать. Теперь не кажется что красиво. Теперь еще и уверен.ksnk
Строчки 58-63 кода smartov можно переписать вот так
Вот тут да. Я даже не знаю зачем я там намутил. Чего-то помутнение наступило видать Добавлено: теперь я знаю почему так замутил. Еще раз пересмотрел то, что вы написали. В силу того, что программлю давно и суппортил кода достаточно у меня патологическая неприязнь к глобальным переменным. Параметры в функцию должны передаваться, а не быть глобальными. Глобальные переменные - зло.
Ну и если саму комбинацию вычислительных процедур - строки 83-107 заменить на 
Вы, наверное, хороший программист на яваскрипте, но мне кажется не совсем понимаете того, что код нужно разносить. Ваш код потом будет несуппортный, понимаете? Выискивать среди анонимных функций использующих глобальные переменные реализацию очень неудобно. Код должен быть логически разделен, а не написан как можно более коротко.