image

Представьте, что пользователи сайта могут сами создавать фотогалереи и публиковать их на сайте с помощью визуального редактора без знаний html. Такую задачу решал на сайте rusland.xyz

Идея сайта в том, что любой путешественник может написать историю своего похода. Такие истории содержат сочетания множества фотографий и небольшого количества текста. В стандартных wysiwyg редакторах есть опция добавить одну картинку (как на habr), но когда фотографий 50+ начинаешь искать другой выход. Что получилось в итоге? Смотрите

Примеры публикаций созданных в этом редакторе:

Далее о том, как это работает и какие инструменты использовались

Как это работает?


В редакторе нажимаем на иконку «вставить фотогалерею», загружаем фотографии на сервер и копируем все ссылки в текстовое поле:
image

Если все ок, увидим миникартинки и добавляем комментарии:
image

В визуальном редакторе фотогалерея отобразится отдельным цветовым блоком, вот так:
image

При нажатии на «Просмотр» получим полноценную фотогалерею:

image

Что использовалось?


1. Визуальный редактор ckeditor, базовая комплектация


Удобно, бесплатно, хорошее описание с примерами, все на английском. Самое главное — предоставляет разработчику возможность создания собственных плагинов, очень гибко и просто. Хватает двух первых примеров, чтобы понять, как работает и можно делать свой. Один пример даже был на хабре, про встраивание яндекс карт.

2. Фотогалерея fotorama


Красиво, просто настраивается и бесплатно. Оптимально. HTML код фотогалереи выглядит просто:
<div class="fotorama" data-nav="thumbs" data-fit="cover" data-width="100%" data-ratio="700/467" data-max-width="100%">
    <img src="img/altay/f7.jpg" data-caption="Чулышман в месте впадение в Телецкое озеро">
    <img src="img/altay/h2.jpg" data-caption="Телецкое озеро. Переправляемся в Артыбаш на катере">
    <img src="img/altay/h3.jpg" data-caption="Телецкое озеро на закате">
    <img src="img/altay/h4.jpg" data-caption="Кафе в Артыбаше, получилось забавно">
    <img src="img/altay/h5.jpg" data-caption="Поселок Артыбаш">
</div>


3. Хостинг фотографий на postimage.com


Лучший из тех, что видел. Не требует регистрации, быстрая загрузка, загрузка множества фотографий, хранятся «вечно» и бесплатно. Предоставляют API, загрузку можно встроить на свой сайт, но это за малую плату. Обойдемся пока без этого.

Детали


В ckeditor создаем свой плагин (пример1, пример2). Каждый плагин имеет три составляющих:
  1. иконка //кнопка в меню редактора
  2. plugin.js //инициализация плагина
  3. dialogs/gallery.js //описывает работу плагина

В моем случае plugin.js:
CKEDITOR.plugins.add( 'gallery', {
    icons: 'gallery',
    init: function( editor ) {
        editor.addCommand( 'gallery', new CKEDITOR.dialogCommand( 'galleryDialog' ) );
        editor.ui.addButton( 'gallery', {
            label: 'Добавить фотогалерею',
            icons: 'gallery',
            command: 'gallery'
        });

        CKEDITOR.dialog.add( 'galleryDialog', this.path + 'dialogs/gallery.js' );
    }
});

В результате в редакторе появится новая кнопка, при клике на него запускается gallery.js, который отвечает за отрисовку диалогового окна и обработку введенных данных. Основной кусок gallery.js:
CKEDITOR.dialog.add("galleryDialog", function(editor) {
	return {
		allowedContent: "img[src,alt]",
		title: "Галерея",
		minWidth: 550,
		minHeight: 150,
		contents:[{
			id: "gallery",
			label: "Details",
			elements:[
				{
					type: 'html',
					html: '<div id="step1"></div>'
				},
				{
					type: 'html',
					html: '<div id="new_data"></div>'
				}
			]
		}],
		onOk: function(){
			var dialog = this;
			getCOM();
			var output=	'<div id="fororama" class="w3-row foto_cont ckeditor">Фотогалерея сформирована:<ul>';
			for(var i=0;i<IMG.length;i++){
				output += '<li>'+IMG[i]+' - '+COM[i]+'</li>';
			}
			output += '</ul></div>'
			editor.insertHtml(output);
		},
		onShow: function() {
			init();
		}
	};
});

Блок elements декларирует, какие элементы должны быть в диалоговом окне. При открытии диалогового окна выполняется блок onShow, где инициализируются переменные, дорисовывается DOM.

При нажатии «Ок» выполняется блок onOk, который обрабатывает введенные пользователем данные и вставляет html код в редактор. В моем примере формирую массив из url картинок, который вставил пользователь в текстовое поле, затем добавляю комментарии. Далее, генерирую блок html и добавляю в редактор. В данном случае это простой список из url и комментариев.

При нажатии на «Просмотр» средствами jQuery обрабатываю специальные блоки div#fotorama… и формирую окончательный html код фотогалереи. Вот и все.

Небольшая хитрость


Пришлось пойти на это, так как мое диалоговое окно получилось сложным и прямым путем реализовать не удалось. У диалогового окна подразумевается фиксированный набор элементов, определенное количество input, select, textarea и тд. Но в моем случае контент зависел от того, сколько картинок добавил пользователь. Поэтому в elements задекларировал два пустых контейнера, куда вставлял нужные элементы средствами jQuery. При нажатии на кнопку, удалял все содержимое и рисовал другой контент.

В завершении


Ckeditor гибкий и удобный редактор, позволяющий разработчикам создавать собственные плагины любой сложности. Таким образом, простые пользователи сайта сами смогут создавать сложные объекты в публикациях без знаний html.

Кто ходил в походы, пишите истории:)

P.S. Не можете комментировать?! Почта указана на сайте. Спасибо
Поделиться с друзьями
-->

Комментарии (42)


  1. cema93
    21.07.2016 09:20
    +2

    Так ждал в конце статьи ссылку на github…


  1. mmjurov
    21.07.2016 09:24
    +1

    Добавил кнопку в CKEditor в пять строк и рассказал об этом на всю страну. Это, конечно, интереснее, чем про покемонов, но…


  1. nikitasius
    21.07.2016 10:46
    +3

    Критика:

    Грузим все фотки сразу?!
    image


    1. fivelife
      21.07.2016 11:04
      +1

      Да, это самая ценная рекомендация). Спасибо за lazyload


      1. nikitasius
        21.07.2016 11:27
        +1

        Незачто :-)

        В моем случае это

        • jquery.2.1.3.min.js
        • jquery.lazyload.1.8.4.js
        • jquery.masonry.2.1.08.min.js
        • classie.js
        • AnimOnScroll.js


        Каждый div с фоткой находится в своем .
        <style type="text/css">
                #container.fluid .item {
                    /*width: 33.3%;*/
                    height: 300px;
                    width: 300px;
                    margin: 3px 0.2% 3px 0.2%;
                }
        
                #container.fluid .item img {
                    display: block;
                    width: auto !important;
                    height: auto !important;
                    opacity: 1;
                    border: 2px solid #333;
                }
            </style>
        


        Изначально был вариант только на masonry, но большие галереи (в силу подгрузки всех превьюшек) были неудобны. В итоге был впилен lazyload.
        Из-за lazyload на портретных фотках встречается вот такая ерунда
        фотки очень близко
        image


        1. fivelife
          21.07.2016 11:34

          Богатый у вас опыт, а можно где-то посмотреть ваши работы?


          1. nikitasius
            21.07.2016 12:10
            +1

            Богатый у вас опыт, а можно где-то посмотреть ваши работы?

            Работы… На lazyload у меня закрытая галерея (семейные фото и видео). Публичная галерея с lazyload (и проект в целом) в процессе написания (музыкальный сайт 403 пока что), который засветился вот тут. Так же это опыт в плане галерей и совместимости (чтобы html5 видео играло на айпаде к примеру, конфиги для mencoder).

            В плане CSS я использую готовые решения и допиливаю их как позволяет практика и гугл. Из тех, что не стыдно показать (в технич плане и в визуальном) вот. Еще есть другой закрытый сайт, который я публиковать не стану, дабы хабр не закрыли в роскоме :-) Хостится он не у меня, но с технической точки зрения я получил оргазм, пока писал его, галерей там нету.


            1. illuzii
              21.07.2016 16:13
              +1

              напишите подробнее как сделать, чтобы html5 видео играло автоматом на ipad, iphone — некоторое время назад искал — ничего путного не нашел. Спасибо.


              1. nikitasius
                21.07.2016 22:06
                +1

                напишите подробнее как сделать, чтобы html5 видео играло автоматом на ipad, iphone

                кодируем:

                если частота звука менее чем 44.1 kHz
                for file in *.mov; do /usr/local/bin/mencoder $file -o ${file}.mp4 -vf pullup,softskip,harddup -of lavf -oac faac -af resample=44100 -srate 44100 -faacopts mpeg=4:object=2:raw:br=192 -aid 0 -ovc x264 -sws 9 -x264encopts nocabac:bframes=0:nofast_pskip:psnr:ssim:b_adapt=2:bitrate=2048:8x8dct:deblock:weight_b:threads=4:global_header:me_range=32:nodct_decimate:subq=9:frameref=9:partitions=all:aq_strength=1.0:aq_mode=1:mixed_refs:trellis=2:chroma_me:me=umh;done
                


                Если звук 44.1kHz
                for file in *.mov; do /usr/local/bin/mencoder $file -o ${file}.mp4 -vf pullup,softskip,harddup -of lavf -oac faac -faacopts mpeg=4:object=2:raw:br=192 -aid 0 -ovc x264 -sws 9 -x264encopts nocabac:bframes=0:nofast_pskip:psnr:ssim:b_adapt=2:bitrate=2048:8x8dct:deblock:weight_b:global_header:me_range=32:nodct_decimate:threads=4:subq=9:frameref=9:partitions=all:aq_strength=1.0:aq_mode=1:mixed_refs:trellis=2:chroma_me:me=umh;done
                


                А вот как перегнать slowmotion видео с айфона (240 кадров в секунду) в «нормальное» slowmotion:
                
                for file in *.mov; do /usr/local/bin/mencoder -fps 30 $file -o ${file}.mp4  -vf pullup,softskip,harddup -of lavf -nosound -ovc x264 -sws 9 -x264encopts nocabac:bframes=0:nofast_pskip:psnr:ssim:b_adapt=2:bitrate=2048:8x8dct:deblock:weight_b:global_header:me_range=32:nodct_decimate:threads=4:subq=9:frameref=9:partitions=all:aq_strength=1.0:aq_mode=1:mixed_refs:trellis=2:chroma_me:me=umh;done
                


                2 Мбит оптимальный битрейт, хотя яблоки едят и 4Мбит.

                Вместо mov можно указать другие расширения файлов. Сие работает с айфонами и айпадами, камерой панасоник (mov) и видео с андроида (mp4).

                mencoder из пакетов, ffmpeg собранный:
                ffmpeg version 2.8.2-1 Copyright (c) 2000-2015 the FFmpeg developers
                  built with gcc 5.2.1 (Debian 5.2.1-23) 20151028
                  configuration: --prefix=/usr --extra-version=1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-openal --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv
                


                1. illuzii
                  21.07.2016 22:18
                  +1

                  я понял, это не совсем то, что я хотел. Я думал, что у вас получилось решить проблему, чтобы если пользователь открыл сайт со встроенным видео — видео играло на автомате сразу на iPad, iPhone.



          1. nikitasius
            21.07.2016 12:27
            +1

            Кстати из той статья про число 60: http://jsfiddle.net/nathando/s3KPn/4/ — рабочий пример с lazyload.
            Только у меня div в <li> находятся, так структура «ощущается» :-)


            1. fivelife
              21.07.2016 12:33

              Хоть и не все картинки грузятся, но эффект ощутим:)


              1. nikitasius
                21.07.2016 12:41

                Привет древний (отсюда 404 Not Found), но логика простая.


              1. nikitasius
                21.07.2016 12:45

                Я вам в личку скинул ссылку для теста.


      1. kellas
        21.07.2016 11:47
        +1

        http://fotorama.io/customize/lazy-load/ — тут вам и делать особо ничего не надо


        1. fivelife
          21.07.2016 11:57

          Действительно) Спасибо Александр, замечено в самый раз.


  1. alexey-m-ukolov
    21.07.2016 11:15
    +1

    У нас на аналогичном проекте эта задача решена вот так:

    Скрин, 2 Мб


    1. alexey-m-ukolov
      21.07.2016 11:22
      +1

      Не ради пиара, а для удобства, оформлю ссылку правильно. Ожидал, что парсер комментариев автоматически это сделает.
      http://tripteam.org/reports/20-pohod-na-manpupuner-i-per-dyatlova-severnyi-ural


      1. fivelife
        21.07.2016 11:25
        +1

        Так лучше)


        1. alexey-m-ukolov
          21.07.2016 11:28
          +1

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


          1. fivelife
            21.07.2016 11:32

            Интересный у вас сайт, буду знать) Спасибо

            Без проблем можно отмечать главные фотографии галереи. Это и реализую после lazyload)


    1. nikitasius
      21.07.2016 11:34
      +1

      Скрин, 2 Мб

      У вас не только скрин на 2 Мб.
      Ваша галерея при старте съела 33.5 метра траффика, подгрузив полные фотки.
      Кстати, зачем сырбор с /abc/efg/photo1.jpg? Чем вам добавление sha1 хеша не угодило?
      Папка = галерея, удобнее в файлах рыться (если приспичит)
      /orig/IMG_0860.JPG_20160617195039.c195f3a9f40850b186c1d6407b4046bb0c23ac53.jpg
      — не такой уж и страшный путь.
      *exif
      *sha1


      1. alexey-m-ukolov
        21.07.2016 11:46
        +1

        > Ваша галерея при старте съела 33.5 метра траффика, подгрузив полные фотки.
        Да, это одна из проблем. Слайдер глючил с ленивой загрузкой, а разбираться времени нет, поэтому отключили её и реализовали вместо этого последовательную загрузку, чтобы страница при открытии хотя бы не тормозила.
        А по поводу полных фоток — превью там никаких нет, поэтому «неполных» фотографий быть в принципе не может.

        > Кстати, зачем сырбор с /abc/efg/photo1.jpg? Чем вам добавление sha1 хеша не угодило?
        Вот это чистой воды bike-shedding. Работает и работает, какой сырбор, зачем менять? Это вообще сжатые и обработанные файлы, не оригиналы.

        > не такой уж и страшный путь
        Путей бояться — в DevTools не ходить.


        1. nikitasius
          21.07.2016 12:15
          +1

          Вот это чистой воды bike-shedding. Работает и работает, какой сырбор, зачем менять? Это вообще сжатые и обработанные файлы, не оригиналы.

          Согласен, у каждого свои фломастеры. Хз, мне было проще добавить хеш и все складировать в одну папку, для защиты от подбора и скачивания каким-нить менеджером.


          1. alexey-m-ukolov
            21.07.2016 12:25
            +2

            Вообще, это стандартная техника для относительно равномерного распределения файлов по директориям, поскольку при очень большом количестве файлов в одной директории операции с ней могут занимать очень долго.

            От перебора эта система защищена не хуже — индекс директории посмотреть нельзя, а угадывать два уровня вложенности с неизвестным названием файла внутри можно очень-очень долго.

            Но вообще, я уже и сам не помню почему сделано именно так.


            1. nikitasius
              21.07.2016 12:36

              Вообще, это стандартная техника для относительно равномерного распределения файлов по директориям, поскольку при очень большом количестве файлов в одной директории операции с ней могут занимать очень долго.

              Надо очень много файлов в директории иметь, много, много больше, чем человек нафоткает на месяц.

              В любом случае, я только за критику подгрузки всего и разом, с технической стороны ничего не имею против :-)


  1. Nadoedalo
    21.07.2016 13:14
    +1

    Просто? Вы вот ЭТО называете просто?
    Где считывание метаданных? Время, координаты, ближайшее название объекта(типа «гора Эверест, высота 500 метров») для дефолтного коммента? Почему нельзя по фоткам посмотреть маршрут? Вообщем мильйон вариантов чего можно было бы ещё сделать так что бы было ВАААУ.

    Ну вообщем очередной слайдер на jquery. Тысячи их, и многие попроще.


    1. fivelife
      21.07.2016 13:19

      Примеры?


      1. Nadoedalo
        21.07.2016 14:26

        Примеры попроще? Или примеры того как можно сделать лучше?
        Кто из нас собирается сделать сервис который удобен клиенту?
        Метаданным сто лет в обед и удивительно что Вы хотя бы в планы на будущее не вписали их парсинг и отображение.
        http://www.panoramio.com/ вот например, первое что нагуглил по фотоаппараты с GPS

        Вообщем с моей колокольни статья — смотрите, я написал jquery-слайдер и хочу с него сделать сервис. Извини конечно, но не взлетит.


        1. fivelife
          21.07.2016 14:51

          Колокольня вещь хорошая. Интересные идеи фиксирую, будут еще — буду рад. Спасибо)


  1. almkhaj
    21.07.2016 14:19
    +2

    Я так понимаю — это больше реклама сайта. Сами истории мне понравились, только жалко, что их «кот наплакал»…


    1. fivelife
      21.07.2016 14:46

      Все по делу говорите ребята) Сайт запустился на этой неделе, минимальный функционал, который хотели сделать — реализовали. Вот теперь начнем публиковать истории и прикручивать удобства.

      Мы не реализовывали (писали) слайдер, а взяли готовое решение. Мы сделали интерфейс, который позволяет любому пользователю формировать свою галерею и публиковать на сайте.


  1. Toshi
    21.07.2016 15:10

    «Представьте, что пользователи сайта могут сами создавать фотогалереи и публиковать их на сайте с помощью визуального редактора без знаний html.»
    Это бы неплохо звучало, лет так 10-15 тому назад… Но это еще полбеды. Про безопасность веб-проектов почитайте обязательно, а я пока письмо Вам на почту с описанием проблемы скину.


    1. Toshi
      21.07.2016 15:30

      Да и про еще XSS почитайте.


    1. fivelife
      21.07.2016 15:46

      Буду признателен, спасибо


      1. Toshi
        21.07.2016 15:47

        Уже отправил, на ящик который указан в контактах на сайте.


  1. kirov2kml
    21.07.2016 15:20

    Не работает с файлами в имени которых есть "-"


    1. fivelife
      21.07.2016 15:46

      С чего это?) Все работает
      image


      1. fivelife
        21.07.2016 16:48

        Да, сорри. Есть такой момент. Использую знак "-" в качестве разделителя url и комментария. Думаю будет лучше если взять "!-" разделитель


  1. snnwolf
    21.07.2016 15:34

    Хорошая идея, хоть и требует доработки. Вставлю свои пять копеек.


    var output= '<div id="fororama" class="w3-row foto_cont ckeditor">Фотогалерея сформирована:<ul>';

    А если я заходу вставить не одну галерею? Понимаю, что jquery схавает и не подавиться, но w3c, если мне не изменяет память, рекомендует использовать уникальные id для элементов.


    1. fivelife
      21.07.2016 15:49
      -1

      Да, все правильно. Поэтому использую такое сочетание:

      var rand = Math.floor(1000000*Math.random());
            var output='<div id="fororama'+rand+'" class="w3-row foto_cont ckeditor">Фотогалерея сформирована:<ul>';
      

      Этот момент опустил, чтоб не усложнять. Спасибо, что заметили)