JSFiddle - React, Tailwind, and code Playground

by rdvornov

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/basis.js/1.2.1/basis.min.js"></script>
<script type="text/basis-template" id="gallery">
    <div class="gallery">
        <h1>Gallery</h1>
    </div>
</script>

<script type="text/basis-template" id="image">
    <div class="image image_{selected}" event-click="showImage">
        <img src="{url}" width="200px"/>
        <div class="image_caption">
            {caption}
        </div>
    </div>
</script>

<script type="text/basis-template" id="popup">
    <div class="image-popup image-popup_{hasImage}" event-click="close">
        <div class="image-popup__wrapper">
            <img src="{url}" width="100%"/>
            <div class="image-popup__caption">
                {caption}
            </div>
        </div>
    </div>
</script>

CSS

.image
{
    display: inline-block;
    margin-right: 20px;
    padding: 5px;
    text-align: center;
}
.image:hover
{
    background: #F0F0F0;
}
.image_selected
{
    background: gold !important;
}

.image-popup
{
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    opacity: 0;
    visibility: hidden;
    transition: opacity .22s;
    background: rgba(0, 0, 0, .5);
}
.image-popup_hasImage
{
    visibility: visible;
    opacity: 1;
}
.image-popup__wrapper
{
    position: relative;
    overflow: hidden;
    max-height: 100%;
}
.image-popup__caption
{
    position: absolute;
    bottom: 20px;
    right: 0;
    padding: 5px 15px;
    background: white;
    background: rgba(255, 255, 255, .75);    
}

JavaScript

basis.require('basis.ui');
basis.require('basis.entity');

//
// Создаем тип данных (можно и без этого, но так проще)
//
var Photo = basis.entity.createType('Photo', {
    url: basis.entity.StringId, // url будет ключом
    caption: String
});

//
// View для отображения большой фотки
//
var imagePopup = new basis.ui.Node({
    container: document.body,
    template: 'id:popup',
    binding: {
        url: 'data:',
        caption: 'data:',
        hasImage: {
            events: 'delegateChanged',
            getter: function(node){
                return !!node.delegate;
            }
        }
    },
    action: {
        close: function(){
            this.setDelegate();
        }
    }
});

//
// Список всех фоток
//
var view = new basis.ui.Node({
    dataSource: Photo.all,
    
    container: document.body,
    template: 'id:gallery',
    
    childClass: {
        template: 'id:image',
        binding: {
            url: 'data:',
            caption: 'data:'
        },
        action: {
            showImage: function(){
                imagePopup.setDelegate(this);
            }
        }
    }
});

//
// заполняем фотки
//

Photo.all.sync([
    { url: 'http://1.bp.blogspot.com/-fdjrfG6GB3g/UAe8l40JvHI/AAAAAAAAHEM/UVoPRlmQEkY/s1600/Hdhut.blogspot.com+(22).jpg', caption: 'a mountain' },
    { url: 'http://1.bp.blogspot.com/-IcT2KStgrZg/UHqtP8R6VqI/AAAAAAAABis/Pr3rHc-AnR0/s1600/ice-snowy-rocks-mountains-hd-background-wallpapers-widescreen-high-resolutions-025.jpg', caption: 'something' },
    { url: 'http://3.bp.blogspot.com/-6aNyoQc1ukw/Tiyvh2RbbxI/AAAAAAAAADk/RtDEw0lFuaA/s640/Mountain.jpg', caption: 'else' } 
]);