Ассоциативные массивы, не работает
Доброго времени суток, уважаемые форумчане!
есть функция валидации полей вида: RikkiValidInput(this, /(^(\d+-)*\d+$)/, '', 'input-group has-success', 'input-group', '', '', ''); function RikkiValidInput(element, reg, aler, sClass, eClass, clr, idSpan, num) { if (reg.test(element.value)) { if (idSpan) { var count = num - element.value.length; $(idSpan).html(count); if (element.value.length <= num) { element.parentNode.className = sClass; } else { element.parentNode.className = eClass; } } else { element.parentNode.className = sClass; } } else if (element.value) { if (clr) { element.parentNode.className = clr; element.value = ""; if (idSpan) { $(idSpan).hide(); } } else { element.parentNode.className = eClass; } if (aler) { alert(aler); } } return false; } хочу привести к цивилизованному виду: var numberSet { reg: /(^(\d+-)*\d+$)/, aler: '', sClass: 'input-group has-success', eClass: 'input-group', clr: '', idSpan: '', num: '' } RikkiValidation(this, numberSet); function RikkiValidation(element, valSet) { if (reg.test(element.value)) { if (valSet.idSpan) { var count = valSet.num - element.value.length; $(valSet.idSpan).html(count); if (element.value.length <= valSet.num) { element.parentNode.className = valSet.sClass; } else { element.parentNode.className = valSet.eClass; } } else { element.parentNode.className = valSet.sClass; } } else if (element.value) { if (valSet.clr) { element.parentNode.className = valSet.clr; element.value = ''; if (valSet.idSpan) { $(valSet.idSpan).hide(); } } else { element.parentNode.className = valSet.eClass; } if (valSet.aler) { alert(valSet.aler); } } return false; } ну в общем, во втором исполнении не валидирует, где ошибка? и насколько безопасно применять ассоциативные массивы? |
Цитата:
|
В самой первой строке еще ошибка. После объявления переменной должен идти оператор присвоения.
|
Цитата:
<input type="tel" pattern="([0-9][ ()+-]*){10,11}$" placeholder="+7 (123) 456-78-90" data-err="Введите номер телефона в федеральном формате 10-11 цифр" value="" name="some"/> <!-- пример с реальной формы --> <input data-index="2" maxlength="100" name="comeback[2]" pattern="^[^\s@]+@[^\s@]+\.[^\s@]+$" errmsg="oшибка в адресе, образец: " placeholder="email@example.com" required="5" type="email"> Дальше все вроде понятно. Скрипт пробегает по полям, берет значение, паттерн, проверяет, если косяк - вызывает рендер ошибки, та берет из переданного инпута дата-ерр+плейсхолдер и выводит куда-то, и объявляет инвалидом этот инпут и не дает кнопке нажиматья. Это модель для текстов. Номера, диапазоны, чекбоксы, радио и списки потребуют своей модели. Но самая жирная модель будет у файлового поля. Тем не менее схема передачи условий та же самая - все необходимое лежит в инпуте. Выбор модели определяется типом поля. |
Разрешите задать свой вопрос, тоже касательно цивилизованных методов. Как сделать чтобы рулезы не размножались с каждым объектом, а существовали как общий для всех объектов метод, то есть прототипом?
О чем я выше писал, сейчас сделано вот так: var FormField=function(el){ var type= el.type, value= el.value.trim(), pat= el.getAttribute('pattern'), req= el.getAttribute('required'), err= el.getAttribute('errmsg')+"\n"+el.getAttribute('placeholder'), rules={ 'text':function(){ var len=value.length; if(req && len<req) throw 'Минимальное количество знаков: '+req; else if(len && pat && !new RegExp(pat).test(value)) throw err; }, 'select-one':function(){ if(el.selectedIndex<0 && req) throw 'Необходимо выбрать из списка'; }, 'select-multiple':function(){ var mul=el.getAttribute('multiple'), for(var count=0, i=0; i<el.length; i++) if(el[i].selected) count++; if(req && count<req) throw 'Необходимо выбрать не меньше чем '+req; else if(mul && count>mul) throw 'Можно выбрать не больше чем '+mul; } }; return { el:el, error:null, title:el.title, validate:function() { if(type in rules) rules[type](); else rules.text(); } }; }; В блоке инициализации каждому полю сопоставляется этот объект и все объекты сохраняются в объект-массив по именам полей. Как я понимаю приватный объект rules размножается, то есть копируется, а хотелось бы понять как его вынести в прототип. Спасибо. |
kostyanet, а если так:
validate: (type in rules) ? rules[type] : rules.text |
Decode, спасибо
Цитата:
kostyanet, попробую осилить, но сначала надо с элементарными вещами разобраться area элементы уже местами использую благодаря bootstrap) вот с исправлениями и все равно не валидирует: echo "<script type='text/javascript'> var numberSet = { reg: /(^(\d+-)*\d+$)/, aler: '', sClass: 'input-group has-success', eClass: 'input-group', clr: '', idSpan: '', num: '' } </script>"; $RIA_number = array( 'simpleInGr' => '1', 'pTxt' => $locale['search103'], 'pClass' => 'text-muted', 'inputName' => 'on_number', 'divClass' => 'input-group', 'spanTitle' => $locale['search104'], 'inputClass' => 'form-control text-center', 'value' => '', 'maxlength' => '20', 'placeholder' => $locale['search105'], 'js' => "onClick=\"clearInput(this, 'input-group', '');\" onKeyup=\"RikkiValidation(this, numberSet);\"", 'readonly' => '' ); echo $RikkiInput->RikkiTxt($RIA_number); function RikkiValidation(element, valSet) { if (reg.test(element.value)) { if (valSet.idSpan) { var count = valSet.num - element.value.length; $(valSet.idSpan).html(count); if (element.value.length <= valSet.num) { element.parentNode.className = valSet.sClass; } else { element.parentNode.className = valSet.eClass; } } else { element.parentNode.className = valSet.sClass; } } else if (element.value) { if (valSet.clr) { element.parentNode.className = valSet.clr; element.value = ''; if (valSet.idSpan) { $(valSet.idSpan).hide(); } } else { element.parentNode.className = valSet.eClass; } if (valSet.aler) { alert(valSet.aler); } } return false; } |
Цитата:
ЗЫ Такое впечатление что вы дописываете что-то свое в какой-то фреймворк. |
нет это мое и не самый лучший вариант прототипа как я поняла. Первую функцию вместе с Rise вывели) теперь хочу сделать по типу php с хранением данных в ассоциативных массивах. Убрала reg все равно не валидирует
это не фреймворк, это код для быстрой записи html public function RikkiTxt($RIA) { $RikkiTxt = ""; if ($RIA['inputClass'] != 'hide') $RikkiTxt .= "<p".(!empty($RIA['pClass']) ? " class='".$RIA['pClass']."'" : "").">".(!empty($RIA['pTxt']) ? "<br>".$RIA['pTxt'] : "")."</p>".PHP_EOL; if (isset($RIA['simpleInGr']) || isset($RIA['countInGr']) || isset($RIA['rightInGr']) || isset($RIA['dblInGr'])) $RikkiTxt .= "<div id='idDi".$RIA['inputName']."' class='".$RIA['divClass']."'>".PHP_EOL; if (isset($RIA['simpleInGr']) || isset($RIA['dblInGr'])) { $RikkiTxt .= "<span class='input-group-addon'>".(!empty($RIA['spanTitle']) ? $RIA['spanTitle'] : "")."</span>".PHP_EOL; } elseif (isset($RIA['countInGr'])) { $RikkiTxt .= "<span class='input-group-addon'>".(!empty($RIA['spanTitle']) ? $RIA['spanTitle'] : "")."<span id='idSp".$RIA['inputName']."' class='".$RIA['countSpanClass']."'>".($RIA['maxlength']-2)."</span></span>".PHP_EOL; } $RikkiTxt .= "<input type='text' id='id".$RIA['inputName']."' name='".$RIA['inputName']."' class='".$RIA['inputClass']."' value='".$RIA['value']."'".(!empty($RIA['maxlength']) ? " maxlength='".$RIA['maxlength']."'" : "").(!empty($RIA['placeholder']) ? " placeholder='".$RIA['placeholder']."'" : "").(!empty($RIA['js']) ? " ".$RIA['js'] : "").(!empty($RIA['readonly']) ? " readonly" : "").">".PHP_EOL; if (isset($RIA['rightInGr']) || isset($RIA['dblInGr'])) { $RikkiTxt .= "<span class='input-group-addon'>".(!empty($RIA['eSpanTitle']) ? $RIA['eSpanTitle'] : "")."</span>".PHP_EOL; } if (isset($RIA['simpleInGr']) || isset($RIA['countInGr']) || isset($RIA['rightInGr']) || isset($RIA['dblInGr'])) $RikkiTxt .= "</div>".PHP_EOL; return $RikkiTxt; } но в JS я 0++ ) |
Цитата:
Что вы называете валидацией - какой-то колхозный рендер ошибок. Он вообще тут не нужен в контексте обсуждения как сделать валидацию. Никого не колышет как эти ошибки рендерятся, как убираются, как все остальное. Цитата:
У вас рендер формы (полей) на сервере или в браузере? Ну, применительно к рубрике - поля уже есть в хтмле, или жаба их рисует по полученным откуда-то данным? Дело в том что нет никакого смысла передавать одновременно и поля и эти массивы для контроля за полями, ибо можно на сервере раскидать все по хтмлю, а в браузере собрать все обратно. Это имеет смысл, ибо часть атрибутов работает и без скриптов, например maxlength и вообще в перспективе можно будет заюзать встроенную в браузеры валидацию когда она наконец там закрепится. Ну вот, пример такого рода я привел - когда из массива в пхп мы делаем инпуты, а потом с инпутов собираем обратно в массив объектов со своими встроенными методами проверки в браузере. |
У вас рендер на сервере или в браузере?в данном случае на сервере часть атрибутов не во всех браузерах работает к сожалению, поэтому пусть будет колхозный но верный рендер, с area лично не связываюсь, беру только железно протестированный во всех браузерах bootstrap, мне бы это зло домучить и с js можно завязать, на все остальное хватает арсенала bootstrapa kostyanet, здесь не только ошибки, здесь еще счетчик количества символов и очистка в случае ввода запрещенных символов с возможностью подключения и отключения в зависимости от поля чтобы понятней http://citr.tk в поле "название" что-нибудь наберите, двойной клик очистить поле |
Ладно, тогда вместо
if (reg.test(element.value)) { надо if (valSet.reg.test(element.value)) { |
Цитата:
Не важно, все равно эта ваша функция - дикая лапша. Между тем вы сами, выше, заявили о желании что-то там цивилизовать. Видите как быстро баттхерт может заставить захотеть одичать. |
Цитата:
|
kostyanet, спасибо заработало, сейчас посмотрю ваш вариант, но плохо что сразу нельзя все в одной связке сделать и валидация и счетчик и очистка
сорри ARIA http://www.w3.org/TR/aria-in-html/ да и вообще вся эта расширенная семантика. Я не прогер мне надо просто сделать свою базу, А все эти навороты больше для какх-то онлайн игрушек подходят ИМХО конечно |
Цитата:
|
рони, да уже исправила)
Ах да забыла: какие риски использования ассоциативных массивов? |
Цитата:
Это потому что вы не прогер вам плохо, а прогерам очень плохо от таких вот кодов, как у вас, непрогреров. Я показал лишь часть файла, этот объект сам только проверется, а рендером занимается контроллер, в который кидаются throw. Никаких рисков нет, одни только бонусы. А вот какие бонусы дают фичи для инвалидов? Они что, начали активно тратить свои пенсии в интернете или статьи читать? |
"Это потому что вы не прогер вам плохо, а прогерам очень плохо от таких вот кодов, как у вас, непрогреров" :lol: ну что поделаешь... лень матушка... итак свой индусский код месяц переделывала, чтобы можно было задавать вопросы на php.ru) и тебе при этом не только отвечали но и понимали) лень и неохота, сделаю базу ... потом может как тех задание скину в какой-нибудь продвинутый центр разработки за деньги и сделаю шедевр, а так пракически невозможно описать что тебе конкретно нужно, итог один сайт глазами прогера, а не потребителя
|
В "контроллере" примерно такая система
var fields={}, /* здесь все те самые поля-объекты */ validate=function(e) { /* это самое и вешается на всякие там события у полей */ var f=fields[this.name]; if(f.error) { /* если уже был косяк то стереть */ f.el.title=f.title; f.el.classList.remove('invalid'); f.error=null; } try { f.validate(); } catch(err) { submit.disabled=f.error=true; if(e.type!='input') { /* рендерит ошибку если сработало по событию, по вызову из скрипта - нет */ f.title=f.el.title; f.el.title=err; f.el.classList.add('invalid'); } } }, То есть весь рендер заключается в обвести поле красной рамкой и поменять его title чтоб чел мог подвести мышь и почитать что надо сделать. Я проверял несколько дизайнов сообщений об ошибках и пришел к выводу что такой - самый лучший. Он кстати с нативным полностью совпадает как вы уже поняли. |
щас попробую проследовать вашей логике...думаю...
"фичи для инвалидов" сейчас походу и жилье заставят строить с фичами для инвалидов, полюбому в 214-фз заставят в обязательном порядке оборудовать все помещения под инвалидов, что сделает себестоимость еще дороже, у меня за 5лет не было ни одного клиента инвалида. Хотя если вы профессиональный прогер то лучше наловчиться их прикручивать, больше шансов взять госзаказ kostyanet validate=function(e) что такое: e ? и validate= ?? e - это по-видимому el? |
Цитата:
ЗЫ Не по теме. Если мы наладим жизнь инвалидов, стать инвалидом будет не страшно, а может быть даже привлекательно и почетно и в таком роде. Несомненно так и случится. Люди начнут с удовольствием становиться инвалидами чтобы пожить в свое удовольствие. Да, в этом суровая правда - стать инвалидом должно быть страшно. Тяготы инвалидов должны пугать. И поэтому инвалид может жить нормально только если у него есть деньги. То есть их надо зарабатывать чтобы на всякий случай. Вот и все. |
Цитата:
Я показал только один, там еще есть файловый - капец наворченный и небольшой для работы с кодами символов (ну там всякие типа иконки-картинки), которые кагбе текст, но в то же время не текст. На стороне сервера типов больше, ибо на жабе например не нужны пароли и даты - даты у меня строками, а на сервере под все - свой класс. |
Я когда писал эти классы и скрипты пытался найти готовые решения, чтоб велик не изобретать - фига-то, - пришлось изобретать. Попадался бред той или иной степени тяжести. Ну вот, у вас я вижу такой кусок кода
$RIA_number = array( 'simpleInGr' => '1', 'pTxt' => $locale['search103'], 'pClass' => 'text-muted', 'inputName' => 'on_number', 'divClass' => 'input-group', 'spanTitle' => $locale['search104'], 'inputClass' => 'form-control text-center', 'value' => '', 'maxlength' => '20', 'placeholder' => $locale['search105'], 'js' => "onClick=\"clearInput(this, 'input-group', '');\" onKeyup=\"RikkiValidation(this, numberSet);\"", 'readonly' => '' ); Который стопудово не принадлежит только типу number, а значит можно сделать базовый класс и наследоваться с него всем остальным кто разделяет эти опции. Откуда у вас это? С такого массива элементарно отрендерить input. Правда всяких опций по рендеру многовато, так не делается, ну это не важно. Если не рендерить поля, то можно передать объект как таковой, через json, например: <script><?php echo json_decode($RIA_number);?></script> Добавить туда еще паттерн и в скрипте сразу будет лежать база с которой можно взять и отрендерить форму, чтобы сервер не напрягать, поскольку он все равно json отдал. Да, как наследоваться. В рамках массивов - через слияние: $_common = array( 'pClass' => 'text-muted', 'divClass' => 'input-group', 'inputClass' => 'form-control text-center', 'value' => '', 'maxlength' => '20', 'readonly' => '' ); $RIA_number = array_merge($_common, array( 'simpleInGr' => '1', 'pTxt' => $locale['search103'], 'inputName' => 'on_number', 'spanTitle' => $locale['search104'], 'placeholder' => $locale['search105'], ) ); |
Цитата:
я поняла вашу функцию, она не привязана к верстке в отличие от моей и годится на все типы полей от input до select, моя функция просто одно значение массива вашей функции, конкретно для Input, просто у меня пока не было надобности валидировать select на js, а для валидации чекбоксов, у меня другая функция с завязкой на php для безопасности, function RikkiCbxInLnk(element, link, linktype, erlink, digit, arr) { var num = 0; var l = ''; for (var i = 0; i < element.elements.length; i++) { var v = element.elements[i].value; if (element.elements[i].type == 'checkbox') { if (element.elements[i].checked === true) { num++; if ($.trim(v) != '000') { if (num <= digit) { if ($.inArray(v, arr) != -1) { l += linktype + num + '=' + $.trim(v); window.location.href = link + l; } else { window.location.href = erlink; } } } else if (num == 1) { for (var j = 0; j < element.elements.length; j++) { if (element.elements[j].checked === true) { element.elements[j].checked = false; } } window.location.href = link + linktype + '1=000'; } } } } return false; }(здесь тоже на асмассив перейду) останусь при своей функции:) заинтересовало: а почему именно throw а не алерт? |
Цитата:
1) - для удобства клиента, не более того и чуть-чуть для экономии ресусрсов сервера, ну что бы не гонять тупизну туда-сюда. 2) - для безопасности, для правильности и еще раз для безопасности. Аксиома: абсолютно ничего нельзя проверить в браузере. Потому что браузера вообще может не быть. Вам из любой проги напихают заголовков в сервер и все. |
Цитата:
Вы просто терминологией не владеете. Это называется - уровень абстракции. В ваших дошираках он низкий - вы пишите конкретную функцию на каждое поле. А я показываю уровень повыше - когда данные нормализованы и одна и та же "функция" может проверить по ним любое поле. В кавычках потому что функций тоже много, просто над ними надстройка в виде еще одной извилины которая понимает какое поле и что с ним делать надо. Вам это вообще зачем надо? Найдите программиста, расскажите что надо сделать и он вам за неделю все сделает. Блин, да готовое приспособит из своих сусеков. Нормальное программирование всегда стремится к определению факта в одном месте и максимальному реюзу этих фактов в разных местах. Например вот самый короткий пример (чтобы не растягивать мессагу) объекта для поля пароля <?php class FormPassword extends FormField { public function __construct($data=array()) { $this->_d=array_merge( array('cap'=>'Пароль', 'pattern'=>'^[\x20-\x7e]*$', 'errmsg'=>'вводите только печатные символы', 'required'=>3),$data); $this->set_name(); } protected function before_render(){ $this->_d=array_merge($this->_d, array('title'=>'Показать пароль', 'onkeyup'=>'{this.title=this.value}', 'value'=>null)); } public function prepare(&$link){ return $link->password($this->value); } } В свою очередь FormField extends FormTag - ниже по иерархии, а все этой категории (формы) объекты входят в коллекцию объекта ActiveForm, который тоже там extends пару раз, в том числе от объекта таблицы бд, которая превращается в объект специальным скриптом и затем кастомизируется. Зачем все эти навороты? Затем что в бд уже дофига чего определено, например там есть разница между текстовым и числовым отношением, есть разница между числовыми полями, даты, списки и тп. Повторять все эти сущности вручную в скрипте не имеет смысла, можно стянуть с бд и перевести на сущности веб-интерфейса. Я процитирую только запрос, с результатов которого затем делается объект, затем кастомизируется в модели, в частности к полям добавляются нормальные названия, скажем вместо tel - Телефон, опции рендера, паттерны те самые и прочие опции. $q='select `table_name`,`column_name`,`data_type` as `dtype`, coalesce(`character_maximum_length`,`numeric_precision`) as `maxlength`, `numeric_scale` as `decimals`, `column_key`, (`is_nullable`="NO" && `column_default` is NULL) as `required`, `column_default` as `value`, `column_type` as `data` from `information_schema`.`columns` where `table_schema`="'.$this->db_name.'" and `table_name`="'.$table_name.'"'; Достаточно испугал? А я ведь тоже не программист, я - дизайнер, мое дело вообще-то - ФШ, Корел и Люстра. Представьте _ЧТО_ пишут настоящие программисты (а не лопухи с этого форума) и какой уровень абстракции они могут задать и какой уровень сервиса обеспечить и вам сразу перехочется самой что-то там изобретать. Словом от такого вот запроса через массу объектов на сервере данные попадают в браузер в виде хтмл-формы и оттуда валятся данные в те же самые объекты которые их и проверяют согласно своим свойствам, методам, логике и полученным данным. Это и называется - ООП. |
Цитата:
Короче, вот есть дохлый сайт с такой формой, зайдите проверьте svet-exclusive.ru/contacts/comeback - во избежание отправки в контору введите заведомо неправильную капчу чтобы посмотреть как сработает прерывание на сервере. Там точно такая же система, ну конечно средствами php. |
throw или exception - это нелокальный goto :)
|
Цитата:
<script>var Fields=<?php echo json_encode($fields);?>;</script> Теперь в скрипте в своем берете этот Fields, который объект и достаете из него все что было на сервере нарисовано. var a_number=Fields.a_number; console.log(a_number.name); // выведет имя поля |
json_encode без перезагрузки страницы?
посмотрела http://svet-exclusive.ru/contacts/comeback не увидела ни счетчиков ни выбросов ошибок, ни очистки полей, скучновато, хочется больше интерактива, чтобы понять что данные на сайте как минимум актуальны на сегодняшний день и я не зря тру мышь здесь) Цитата:
а для бизнеса живучесть системы на первом месте, допустим какое-нибудь быдло через знакомых мусоров решило отмыть деньги и давит на сделку, посылаешь на три буквы смело да еще и говоришь ему что оно быдло, естессно после этого будет не один DDOS подконтрольных мусорам хакеров на условном очень много, но тебе пофигу, помаются помаются поугрожают зубы поскалят и отвалят, это лучше чем писать на них в генпрокуратуру На сайте в примере понравился вывод ошибки при неверной капче, хочу такой же, вот: function RikkiTxtJS(element, valSet) { try { if (valSet.reg.test(element.value)) { if (valSet.idSpan) { var count = valSet.num - element.value.length; $(valSet.idSpan).html(count); (element.value.length <= valSet.num) ? element.parentNode.className = valSet.sClass : element.parentNode.className = valSet.eClass; } else { element.parentNode.className = valSet.sClass; } } else if (element.value) { throw 'Err1'; } } catch(er) { if (er=='Err1') { if (valSet.clr) { element.parentNode.className = valSet.clr; element.value = ''; if (valSet.idSpan) { $(valSet.idSpan).hide(); } } else { element.parentNode.className = valSet.eClass; } if (valSet.Err1) { $(valSet.eDiv).html(valSet.Err1); } } } return false; } тут еще очистку diva доработать немного и готово. Профессор спасиба вы мой светильник в тьмаJS :) |
Цитата:
Блин, вот так бывает да. Пишешь вроде как человеку, а на том конце сидит ТП начитавшаяся предисловий на форумах быдла. Короче, лечиться вам надо. Особенно показания второго абзаца могут заинтересовать отечественную психиатрию. |
kostyanet, не начиталась, а действительно пришлось через это пройти( жила в центре в фсбэшном доме а там прослушка на весь дом ну и задавили мне сделку на 90млн, да пофигу, богатые тоже завидуют, чмошная женушка-домохозяйка одного генерала на гавно изошлась там. Как оно ушло так оно и придет, а у них зато потом склады со строительными напизженными материалами сгорели, дымища на весь город была, я тут не причем, Бог наказал. Со всех сторон пытались душить и проверки насылали и подставных клиентов подсылали, даже смешно на эти крючки только начинающий осел менеджер попался бы и то жадный до легкой наживы, не на ту напали. Делать ей нечего, от безделья и развлекалась, интриги там плела, стареет... надо ж уничтожить всех кто красивее и моложе. Потом про эту элитную квартиру которую я снимала, я много чего узнала, но это сложно доказать практически невозможно, а так бы засадить их пожизненно надо, оборотни в погонах( Там живут и нормальные люди но закрывают глаза, никто не будет с ними связываться, это звери, ее сыночек с женой развелся, та прям выла несколько дней на весь дом, потом ее в психушку запихнули вродебы, вобщем исчезла кудато, вабще кошмарное место, и не съехать было договор на год был 40 000 в месяц + комуналка и регистрация по месту, вот в такой переделке я побывала) А ведь специально сняла в элитном доме чтобы не было зависти, думала тут все на роверах, че им за дело до меня, чему завидовать, я по сравнению с ними близко не стою, ан нет... Благодаря тому что средний класс не в курсе методичек элиты, вот такие оборотни и остаются безнаказанными.
я сделала с data-атрибутами как вы и говорили см. http://rikki.xp3.biz/search.php вкладка "номер" у меня даже прикольней получилось со всплывающим popover Такой remix bootstrapa и kostyanet ) |
Часовой пояс GMT +3, время: 17:05. |