Кроссворд из регулярных выражений: интерактивная версия

    Вдохновлённый недавним постом и комментарием к нему, решил сделать аналогичную интерактивную версию.
    Есть навигация с клавиатуры, подсветка активных строк, а также индикация соответствия строки регулярному выражению. Для удобства подсказки выделенной ячейки поворачиваются горизонтально.
    Разметка – чистый HTML+CSS3.
    Почти работает в последних версиях популярных браузеров. В IE9 глючит навигация мышкой, в FF и Opera наблюдаются проблемы с производительностью. И только Chrome – 100% OK.
    Буду благодарен за советы по оптимизации.
    Ссылка – вот. Детали реализации – под катом.
    image

    Реализация

    Пожалуй, самое интересное в реализации – это сетка кроссворда. Ячейка сверстана с помощью развития идеи «честных полигонов». Если коротко – создаются несколько контейнеров с visibility:hidden и overflow:hidden, что предоставляет отсекание лишнего содержимого. Внутри создаётся содержимое с visibility:visible. Использование этого вместе с вращением у контейнеров позволяет задать конечному элементу форму практически любого выпуклого многоугольника.
    Чтобы сделать этот многоугольник с границами в несколько пикселей, к содержимому были добавлены дополнительные внешние контейнеры с аналогичными поворотами и нужными границами. Суть показана на картинке. Здесь красным пунктиром обозначены внешние «невидимые контейнеры», чёрным – внутренние контейнеры с границами.

    Сначала идут 3 вложенных друг в друга элемента с красной рамкой, внутри них – так же вложенные видимые контейнеры с чёрной рамкой.
    Код
    HTML
    <span class="hexcell">
    	<span>
    		<span>
    			<span>
    				<span>
    					<span class="input"></span>
    				</span>
    			</span>
    		</span>
    	</span>
    </span>
    

    CSS
    .hexcell {
    	display: inline-block;
    	vertical-align: middle;
    	text-align: center;
    	width: 50px;
    	height: 70px;
    	overflow:hidden;
    	visibility:hidden;
    	-webkit-transform: rotate(120deg);
    	   -moz-transform: rotate(120deg);
    	    -ms-transform: rotate(120deg);
    	     -o-transform: rotate(120deg);
    	        transform: rotate(120deg);
    }
    .hexcell span {
    	position:relative;
    	width:100%;
    	height:100%;
    	display:inline-block;
    	overflow:hidden;
    	visibility:hidden;
    	vertical-align: middle;
    	text-align: center;
    }
    .hexcell > span {
    	-webkit-transform: rotate(-60deg);
    	   -moz-transform: rotate(-60deg);
    	    -ms-transform: rotate(-60deg);
    	     -o-transform: rotate(-60deg);
    	        transform: rotate(-60deg);
    }
    .hexcell > span > span {
    	-webkit-transform: rotate(-60deg);
    	   -moz-transform: rotate(-60deg);
    	    -ms-transform: rotate(-60deg);
    	     -o-transform: rotate(-60deg);
    	        transform: rotate(-60deg);
    }
    .hexcell > span > span > span{	/*первая рамка*/
    	border: 1px solid #000000;
    	height:68px;
    	width:48px;
    	visibility:visible;
    	-webkit-transform: rotate(120deg);
    	   -moz-transform: rotate(120deg);
    	    -ms-transform: rotate(120deg);
    	     -o-transform: rotate(120deg);
    	        transform: rotate(120deg);
    }
    .hexcell > span > span > span > span{	/*вторая рамка*/
    	border: 1px solid #000000;
    	height:68px;
    	width:48px;
    	top:-1px;
    	left:-1px;
    	visibility:visible;
    	-webkit-transform: rotate(-60deg);
    	   -moz-transform: rotate(-60deg);
    	    -ms-transform: rotate(-60deg);
    	     -o-transform: rotate(-60deg);
    	        transform: rotate(-60deg);
    }
    .hexcell > span > span > span > span > span.input{	/*содержимое с третьей рамкой*/
    	border: 1px solid #000000;
    	height:68px;
    	width:48px;
    	top:-1px;
    	left:-1px;
    	position:relative;
    	visibility:visible;
    	font-size:34px;
    	-webkit-transform: rotate(-60deg);
    	   -moz-transform: rotate(-60deg);
    	    -ms-transform: rotate(-60deg);
    	     -o-transform: rotate(-60deg);
    	        transform: rotate(-60deg);
    }
    
    Для корректного объединения ячеек в сетку делается следующее:
    • ячейки оборачиваются в контейнер, содержимое которого выравнивается по центру
    • используется псевдо-border-collapse: всем ячейкам, кроме последней, ставится меньшая ширина и последнего элемента (контейнер содержимого) убирается правая граница
    • для совмещения строчек добавляется отрицательный margin-top
    В такой комбинации несколько поставленных рядом ячеек с нужными стилями выстраиваются в нормальную сетку.
    Для расстановки заголовков средствами CSS они добавляются перед соответствующей ячейкой в контейнер с абсолютной позицией и выравниванием по правому краю. Таким образом, пропадает привязка к размеру строки и достаточно правильно расположить контейнер через CSS transform.
    Всё остальное не представляет из себя ничего сверхъестественного, потому не буду это описывать в посте. Желающие смогут всё найти в исходниках.

    Работоспособность

    Отдельные вопросы вызывает функционирование. Кроссворд гарантированно функционирует только под Webkit (разработка велась под Chrome последней версии). В Firefox и Opera тоже работает, но почему-то с заметными тормозами, особенно в Opera. Как показал профайлер в той же Opera, больше всего времени уходит на перерисовку, даже с отключёнными transitions. Под IE10 не тестировалось.
    UPD. В IE10 работает отлично, спасибо alexxxst.
    Под 9-м был баг с позиционированием заголовков (горизонтальные съезжали влево). Как я понял, это какая-то его специфика. Первый элемент в строке с position:absolute съезжает к левому краю, несмотря на отсутствие явного указания положения. Исправлено через display:inline-block у контейнера строки.
    Также вместе с поворотами криво рендерится текст. В целом, как показал опыт, рендеринг графики вместе с transform пока оставляет желать лучшего.
    UPD2. Исходники
    Метки:
    Поделиться публикацией
    Комментарии 41
    • +5
      Даже немного жаль, что уже решил его.
      Предложение: можно добавить вращение кроссворда мышкой или стрелками.
      • 0
        Идея интересна, но сложновата в реализации.
        Не думаю, что это столь необходимо. А ещё боюсь, что тогда это всё даже в Webkit начнёт тормозить.)
        • 0
          Кверху тормашками читать это всё сложно. Я когда решал, распечатал и много его крутил. Очень удобно.
      • +2
        «Честные полигоны» понравились, интересная реализация.

        p.s. странно, но в Firefox при манипуляциях на странице кушается раза в полтора больше ресурсов, чем в Хроме.
        • 0
          Да, о производительности я писал. Я подозреваю (но не уверен), что во всём виноваты transforms. Почему-то Webkit и IE с ними лучше справляется.
        • 0
          Не стоило текст поворачивать более чем на 90 градусов, читать не удобно
          • 0
            К сожалению, хорошего решения по поводу удобного восприятия текста так и не нашёл. Направление текста указывает направление слова в сетке.
            • 0
              Верхние и нижние подписи можно на 180 градусов развернуть, тогда они будут читаемыми и не потеряют направление.
              • +1
                Потеряют, там проблема в том что направления регекспов навстречу друг другу, а у текста направление одно — слева направо.
                • +1
                  Тогда они будут в обратном направлении относительно «матчимой» строки.
            • +3
              Лучше всего работает в ИЕ10… как ни странно.
              • 0
                Даже лучше, чем в Webkit? У меня, к сожалению, нет возможности самому это увидеть.
                • 0
                  Лучше всего работает в ИЕ10… как ни странно.

                  Это заговор!

                • +1
                  Стоит счетчик времени на страницу добавить, от первой введенной буквы до последней правильной
                • 0
                  где-то минут за 40. Правда, под конец облажался в одном символе, и (.)(.)(.)(.) не сходилосб. пришлось подсмотреть его :(
                  • 0
                    Сначала хотел написать, что кроссворд не имеет решений, но потом понял, в чём проблема. При клике в клетку все тексты пишутся горизонтально, и для трёх граней порядок становится неправильным. Нужно тогда и само регулярное выражение разворачивать, что вроде не сильно сложно.
                    • 0
                      Порядок остаётся прежним. Подписи я кручу только для удобства чтения.
                      А разворачивать регулярки как раз сложно (если не невозможно).
                      • 0
                        Надпись слева направо, а строка справа налево, следовательно, порядок неправильный.
                        Что касается регулярок, то, может, и бывают такие, которые нельзя развернуть, но я сходу не смог таких придумать, а имеющиеся в кроссворде разворачиваются элементарно.
                    • 0
                      Спасибо за реализацию! Решить удалось. В хроме работает почти без проблем. Только в одной регулярке (где-то снизу справа) кажется лишний пробел видим.
                      • 0
                        Да, видел, и уже исправил.
                      • 0
                        стоит сделать систему пометок(в яейку вводить несколько символов, пока не знаешь, что именно там должно быть) как в судоку. хотя, это — дело вкуса.
                        • +1
                          Отлично! Решил за час и 48 минут. Многовато, но я отвлекался.
                          Теперь знаю, какое задание на собеседованиях давать нужно =)
                          • +2
                            Если бы я увидел это задание на собеседовании, я бы встал и вышел.
                            • 0
                              Можно на дом давать, но так, чтобы простановка каждой буквы сразу отправлялась на сервер и записывалась с временем. Далее по логу легко понять, списывал претендент или нет. Даже если человек списывая сможет обмануть логирование то его за одно это взять можно будет =)
                              • 0
                                Вы не решили основную проблему: задача совершенно не подходит для собеседований. Ни на одну должность. Ни в одну компанию мира. Ни в прошлом, ни в настоящем, ни в будущем.
                                • 0
                                  Почему же? Задача дает понять, что собеседуемый умеет работать с регулярками и в общем неплохо их понимает. Там ведь и группировка, и наборы, и повторение. Не все конечно но основы есть.
                                  • 0
                                    Вы не чувствуете разницы между пониманием регулярных выражений и умением решать составленные из них кроссворды? Не говоря уж о том, что выучить 90% синтаксиса регулярных выражений можно за несколько часов с нуля, поэтому подобная проверка знаний бессмысленна; да и что не существует профессий, в которых ощутимое время занимает анализ регулярных выражений.
                                    • 0
                                      Но существуют профессии в которых 90% времени занимает написание регулярных выражений. Сам знаком с парой подобных специалистов =)
                                      • +1
                                        90%? И чем же они занимаются?.. о_О
                                        • 0
                                          Пишут скрипты для парсинга страниц
                          • 0
                            1:36:10. Это были увлекательнейшие полтора часа!
                            Всегда было интересно, как люди придумывают такие прикольные задачи — всё же настолько надо подогнать друг к дружке, чтобы и регекспы были простые и красивые, и решение было единственно, и решать было непросто. Респект авторам таких задач!
                            • 0
                              Хотел решить, ещё когда увидел в виде картинки, но терпения не хватило вертеть головой или крутить куски изображения в редакторе.
                              В таком виде отлично просто, спасибо!
                              0:59:20.
                              • 0
                                Почему-то под маком не ставится точка нигде (Chrome 26, Firefox 20, Safari 6.0.3)
                                • 0
                                  Решил вчера впервые, сейчас решил повторить, не отвлекаясь.
                                  00:38:29
                                  • 0
                                    Спасибо, удобно решать в таком формате.
                                    02:07:01, в (...?)\1* сбился при повторении букв и через некоторое время пришлось долго разматывать и вспоминать, какие кобминации не обоснованы :)
                                    • 0
                                      Жаль он не показывает, какую регулярку буква проваливает.
                                      • 0
                                        FF 24.5/Linux ячейки отрисовываются некорректно. При этом на сайте «честных полигонов» всё в порядке.
                                        • 0

                                          На планшете не отображает клавиатуру для ввода символов.

                                          • +1
                                            Хотелось бы видеть код на GitHub… Может быть выложите?

                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.