Skip to content

Instantly share code, notes, and snippets.

@edtoken
Created October 27, 2015 17:56
Show Gist options
  • Save edtoken/e543d1371978813c2dec to your computer and use it in GitHub Desktop.
Save edtoken/e543d1371978813c2dec to your computer and use it in GitHub Desktop.
define([
'jquery',
'underscore',
'backbone',
'appdir/default/module',
'modules/galleryObject/models/module',
'modules/galleryObject/collections/gallery',
'modules/galleryObject/views/default',
'modules/galleryObject/views/empty',
'modules/galleryObject/views/popup',
//'modules/galleryObject/views/thumbnail',
'modules/galleryObject/views/full',
], function ($,
_,
Backbone,
ModuleDefaultClass,
ModuleModelClass,
GalleryCollectionClass,
GalleryDefaultViewClass,
GalleryEmptyViewClass,
GalleryPopUpViewClass,
GalleryFullViewClass) {
/**
* TODO: иногда не прогружается первая картинка при переключении в popup
*/
/**
* вспомогательные функции
*/
// разбираю объекты с картинками
var defaultSizeNames = ['thumbnail', 'thumbnail-popup', 'def', 'popup', 'full'];
// порядок разбор изображений:
// Если какого-то размера нет - его заменяет тот размер, который стоит с права до конца
// соответственно эти два размера становятся одинаковые.
//например: ['thumbnail', 'def']; = ['thumbnail', 'def', 'def', 'def'];
// последние 3 размера будут одинаковые (сами изображения)
var parseImagesObj = function(data){
var out = {};
if(!data) return out;
// переданные размеры
var sizes = _.keys(data);
/**
* временный костыль
*/
if(sizes.indexOf('catalogBigSinglePreview') >= 0){
sizes.splice(1,0, 'catalogBigSinglePreview_popup');
data['catalogBigSinglePreview_popup'] = _.clone(data['catalogBigSinglePreview']);
}
var sizeName;
_.each(defaultSizeNames, function(name, num){
if(sizes.length){
sizeName = sizes.shift();
}
out[name] = data[sizeName];
});
return out;
};
// prent controller class
// создает первую галерею на странице
var GalleryObject = ModuleDefaultClass.extend({
name:'GalleryObject',
el:$('body'),
events:{
'click .gallery-object-def-list':'eventClickDefaultImage',
'click .gallery-object-empty img':'eventClickImageEmpty',
'click .gallery-object-popup-btn-item-full':'eventClickPopupButtonFull'
},
initialize:function(options){
var self = this;
this.collection = new GalleryCollectionClass(); // коллекция со всеми моделями галерей
this.model = new ModuleModelClass(); // модель модуля
// дочерние галереи
this.children = {};
this.children.popup = new GalleryPopUpViewClass();
this.children.full = new GalleryFullViewClass();
this.$el.append(this.children.popup.$el);
this.$el.append(this.children.full.$el);
// глобальные события
$(window).bind('hashchange', function () {
self.eventChangeWidowHash();
});
// вернуть дабл клик
//.$el.dblclick(function () {
// self.parent.model.set({viewType: 'popup'});
//});
this.app.ui.keyPress(39, function (e) {
// to right
self.eventNextImage();
});
this.app.ui.keyPress(37, function (e) {
// to left
self.eventPrevImage();
});
this.app.ui.keyPress(27, function (e) {
self.eventClosePopupAndFull();
});
},
eventNextImage:function(){
for(var c in this.children){
if(!this.children[c].model || !this.children[c].nextImage) continue;
this.children[c].nextImage();
}
},
eventPrevImage:function(){
for(var c in this.children){
if(!this.children[c].model || !this.children[c].prevImage) continue;
this.children[c].prevImage();
}
},
eventClosePopupAndFull:function(){
if(this.children.popup.$el.length){
this.children.popup.eventClickCloseGallery();
}
if(this.children.full.$el.length){
this.children.full.eventClickCloseGallery();
}
},
// open popup gallery
openPopupGallery:function(galleryId, imageId){
if(this.children[galleryId]){
var model = this.children[galleryId].model;
var images = model.get('images');
if(images.popup && images.popup.length){
imageId = imageId || false;
this.children.popup.hide();
this.children.popup.remove();
this.children.full.remove();
this.children.full.hide();
this.$el.append(this.children.popup.$el);
this.children.popup.render(
this.children[galleryId].model,
imageId,
{options:{urlController:this.children[galleryId].options.urlController}}
);
this.children.popup.show();
}
}
},
openFullGallery:function(galleryId, imageId){
if(this.children[galleryId]){
var model = this.children[galleryId].model;
var images = model.get('images');
if(images.full && images.full.length){
imageId = imageId || false;
this.children.popup.hide();
this.children.popup.remove();
this.children.full.remove();
this.children.full.hide();
this.$el.append(this.children.full.$el);
this.children.full.render(
this.children[galleryId].model,
imageId,
{options:{urlController:this.children[galleryId].options.urlController}}
);
this.children.full.show();
}
}
},
// клик по обычной картинке в галерее default (переход ко второму размеру)
eventClickDefaultImage:function(e){
var $galleryNode = $(e.target).parents('.gallery-object');
if($galleryNode.length){
var galleryId = $galleryNode.attr('data-gallery-id');
if(galleryId){
// id открываемого изображения
var imageId = (e.target.nodeName == 'IMG')
? this.app.hp.images.getImageIdFromUrl(e.target.getAttribute('src'))
: this.app.hp.images.getImageIdFromUrl($(e.target).find('img').attr('src'));
if(!this.app.getAttr('mobile')){
this.openPopupGallery(galleryId, imageId);
}else{
// если мобильный открываю full
this.openFullGallery(galleryId, imageId);
}
}
}
},
eventClickImageEmpty:function(e){
var $galleryNode = $(e.target).parents('.gallery-object');
if($galleryNode.length){
var galleryId = $galleryNode.attr('data-gallery-id');
if(galleryId){
// id открываемого изображения
var imageId = (e.target.nodeName == 'IMG')
? this.app.hp.images.getImageIdFromUrl(e.target.getAttribute('src'))
: this.app.hp.images.getImageIdFromUrl($(e.target).find('img').attr('src'));
if(!this.app.getAttr('mobile')){
this.openPopupGallery(galleryId, imageId);
}else{
// если мобильный открываю full
this.openFullGallery(galleryId, imageId);
}
}
}
},
eventClickPopupButtonFull:function(){
this.children.popup.hide();
var galleryId = this.children.popup.model.id;
var activeImg = this.children.popup.model.get('activeImg');
this.openFullGallery(galleryId, activeImg);
},
// событие переключение хеша
eventChangeWidowHash:function(){
//console.log('window change hash');
},
// событие переключение фулскрин
eventChangeWindowScreen:function(){
//console.log('window change full screen')
},
// добавление новой галереи
// порядок фото обязательно: 0 - миниатюра, 1 - большой, 3 - полноэкранный
addGallery:function(images, id, options){
var opt = {};
_.extend(opt, options);
opt.galleryType = (opt.galleryType)? opt.galleryType : this.model.get('defaultGalleryType'); // тип галереи по умолчанию
// нужен уникальный ID галереи
if(!id || this.collection.get(id)) id = _.uniqueId('');
// обновленный объект настроек модуля
var moduleOptions = this.getBackendModuleOptions();
// формирую данные картинок
var modelInitData = {};
modelInitData.nodeID = 'galleryObject-' + id;
var initImages = {};
if(moduleOptions && moduleOptions['images_' + id]){
_.extend(initImages, parseImagesObj(moduleOptions['images_' + id]))
}
if(images){
_.extend(initImages, parseImagesObj(images));
}
modelInitData['images'] = initImages;
modelInitData['id'] = id;
this.collection.add(modelInitData);
var model = this.collection.get(id);
//_.extend(opt, {model:model});
opt.model = model;
// создаю галерею
switch(opt.galleryType){
case 'empty':
this.children[model.id] = new GalleryEmptyViewClass(opt);
break;
case 'def':
default:
this.children[model.id] = new GalleryDefaultViewClass(opt);
break;
}
this.delegateEvents();
}
});
return GalleryObject;
});
define([
'jquery',
'underscore',
'backbone',
'modules/galleryObject/urlController'
], function ($,
_,
Backbone,
UrlControllerClass) {
var urlControllerObj = new UrlControllerClass();
var defaultRemoveFunc = Backbone.View.prototype.remove;
// бьазовый класс галереи
return Backbone.View.extend({
urlController:urlControllerObj,
options:{
canHashChange:false,
size:'', // стандартный размер картино default/full/thumbnail
buttons:{
navigation:false,
close:false,
},
renderItems:false, // сразу отрисовать все изображения false - нет, true - все, число - количество с начала
classNames:{}, // объект с классами для элементов
imgSizes:{}, // данные размера картинок
urlController:false, // изменения в модели будут менять урл на странице, false или массив размеров, или true (все)
},
events:{},
className:'',
// все возможные таймеры
timers:{},
tagName:'div',
nodes:{}, // кеш DOM
children:{}, // child views
initialize:function(){},
/**
*
******* Создание HTMl
*
*/
/**
* Создаст объект с данными одного элемента списка галереи
* Использутеся в кеше
* @param data
* @param num
* @returns {{$node: string, node: string, num: *, wrap: string, span: string, image: string, src: string, state: string, rendered: string}}
*/
makeItemHTMLData:function(data, num){
var $node = '';
var node = '';
var wrap = '';
var span = '';
var image = '';
var src;
var state = '';
var rendered;
var id = data.id;
var className = this.options.classNames;
span += '<span data-src="' + data.src + '" title="' + data.title + '" alt="' + data.title + '" class="span-preload img-responsive preload ' + className.item + '"></span>';
image += '<img src="' + data.src + '" title="' + data.title + '" alt="' + data.title + '" class="img-responsive preload ' + className.item + '">';
src = data.src;
wrap += '<li class="' + className.item + '-wrap ' + className.item + '-' + num + ' ' + className.item + '-' + this.options.size;
wrap += (data.active !== undefined && className.active) ? ' active ' : ' ';
wrap += '" data-num="' + num + '">';
wrap += '<%= image %>';
if (data.sourceText !== undefined && data.sourceText) {
wrap += '<span class="' + className.item + '-source">Источник: ' + data.sourceText + '</span>';
}
wrap += '</li>';
if(this.options.renderItems){
state = 'process';
rendered = _.template(wrap)({image: image});
}else{
// вот тут надо сделать проверку для renderItems на count
rendered = _.template(wrap)({image: span});
}
return {
id:id,
$node:$node,
node:node,
num:num,
wrap:wrap,
span:span,
image:image,
src:src,
state:state,
rendered:rendered
}
},
/**
* добавить 1 картинку в список + закешировать
* @param imgId
* @returns {boolean}
*/
addListItemHTML:function(imgId){
if (!imgId) return false;
var items = this.model.get('images')[this.options.size];
if (!items) return false; // если нет кеша и нет картинок
var itemDataAndIndex = _.compact(_.map(items, function (item, num) {
if (item.id == imgId) {
return {
item: item,
num: num
}
}
}));
if (!itemDataAndIndex || !itemDataAndIndex.length) return false;
itemDataAndIndex = itemDataAndIndex.pop();
var itemHTMLData = this.makeItemHTMLData(itemDataAndIndex.item, itemDataAndIndex.num);
this.nodes.$list.append(itemHTMLData.rendered);
// сохраняю в индекс
this.model.addImagesIndexesItem(imgId, this.cid, itemHTMLData);
return this.model.getImagesIndexesItem(imgId, this.cid);
},
/**
* получить закешированный html для картинки по ID
* @param imgId
* @returns {*}
*/
getListItemHTML:function(imgId){
var data = this.model.getImagesIndexesItem(imgId, this.cid);
if(data && data.rendered) return data.rendered;
return false;
},
/**
* Создаст HTML для списка элементов галереи
* @returns {string}
*/
createListHTML:function(){
var self = this;
var html = '';
var contentHTML = '';
var buttonsHTML = '';
var itemsHTML = '';
var className = this.options.classNames;
var items = this.model.get('images')[this.options.size];
html += '<div class="' + className.wrap + '">';
// нужно нарисовать кноки навигации
if(this.options.buttons && this.options.buttons.navigation){
buttonsHTML += '<span class="' + className.nav + '-item ';
buttonsHTML += className.nav + '-item-prev ">';
buttonsHTML += '</span>';
buttonsHTML += '<span class="' + className.nav + '-item ';
buttonsHTML += className.nav + '-item-next ">';
buttonsHTML += '</span>';
}
// кнопки
if(this.options.buttons){
buttonsHTML += '<div class="' + className.button + '-wrap ">';
}
// кнопка открытия полного экрана
if(this.options.buttons && this.options.buttons.full){
buttonsHTML += '<span class="' + className.button + '-item ';
buttonsHTML += className.button + '-item-full ">';
buttonsHTML += '</span>';
}
// кнопка закрытия вида
if(this.options.buttons && this.options.buttons.close){
buttonsHTML += '<span class="' + className.button + '-item ';
buttonsHTML += className.button + '-item-close ">';
buttonsHTML += '</span>';
}
if(this.options.buttons){
buttonsHTML += '</div>';
}
// items
if (items){
itemsHTML += '<ul class="' + className.list + '">';
_.each(items, function (item, num) {
var itemHTMLData = self.makeItemHTMLData(item, num);
itemsHTML += itemHTMLData.rendered;
// кеширую картинку
// дальше работаю с закешированной информацией об изображении
// только, если не добавляю совсем новые
self.model.addImagesIndexesItem(item.id, self.cid, itemHTMLData);
});
itemsHTML += '</ul>';
}
html += contentHTML;
html += buttonsHTML;
html += itemsHTML;
html += '</div>';
return html;
},
renderAndLoadItemHTML:function(domCache, callback){
var self = this;
// задел на будущее, что бы была возможность "перезагружать картинки"
if(domCache.state == '' || domCache.state == 'process'){
var Img = new Image();
Img.onload = function(){
// TODO у картинки подменяется урл быстрее, чем просиходит событие ошибки зигрузки (тут)
// поэтому такой вот костылек
if(this.src.indexOf('ErrorImage') < 0){
domCache.state = true;
domCache.$node.append(domCache.image).addClass('ready').find('.span-preload').remove()
if(callback) callback(true, domCache);
}else{
// загрузилось изображение с ошибкой
var errorImage = self.app.fn.getErrorImage({350:350}, true);
domCache.state = false;
domCache.$node.addClass('error').html(domCache.image).addClass('ready error').find('img').attr('src', errorImage.src);
if(callback) callback(false, domCache);
}
};
Img.onerror = function(){
// загрузилось изображение с ошибкой
var errorImage = self.app.fn.getErrorImage({350:350}, true);
domCache.state = false;
domCache.$node.addClass('error').html(domCache.image).addClass('ready error').find('img').attr('src', errorImage.src);
if(callback) callback(false, domCache);
};
Img.src = domCache.src;
}
// отрисовка состояния ошибки
if(domCache.state === false){
var errorImage = self.app.fn.getErrorImage({350:350}, true);
domCache.$node.addClass('error');
domCache.$node.find('img').attr('src', errorImage.src).addClass('ready error');
if(callback) callback(false, domCache);
}
},
/**
*
******* Обработка событий
*
*/
/**
* тут рождается потеря памяти
* опасное место
* @returns {exports.eventChangeActiveImg}
*/
eventChangeActiveImg:function(){
/**
* в этом месте надо всегда следить что бы событие срабатывало только там, где надо
* console.log(this.options.size);
* @type {exports.eventChangeActiveImg}
*/
var self = this;
var className = this.options.classNames;
var activeImg = this.model.get('activeImg');
if (!activeImg) return this;
// закончить
function errorLoading(cache){
var errorImage = self.app.fn.getErrorImage({350:350}, true);
//
if(cache){
//cache.state = false;
// self.model.addImagesIndexesItem(cache.id, self.cid, cache);
cache.$node.find('img').attr('src', errorImage.src);
}
if(!cache){
// невозможная ошибка
alert('Ошибка работы галереи, пожалуйста обновите страницу');
}
};
// беру закешированный DOM и удаляю класс active
var allItemsCache = this.model.getImagesIndexesItem(false, this.cid);
for(var c in allItemsCache){
if(!allItemsCache[c].$node) continue;
allItemsCache[c].$node.removeClass('active');
}
var domCache = this.model.getImagesIndexesItem(activeImg, this.cid);
// кеша вовсе нет
if (!domCache) {
// добавляю html в список, записываю кеш, возвращаю кеш
domCache = this.addListItemHTML(activeImg);
}
// в кеше только html
if (domCache && !domCache.$node && !domCache.node) {
domCache.$node = this.$el.find('.' + className.item + '-' + domCache.num);
domCache.node = domCache.$node[0];
}
if(domCache && domCache.state === 'process'){
domCache.$node.addClass('active');
self.openImage(domCache);
// устанавливаю урл
if(self.options.size !== 'def') self.options.canHashChange = true;
if(self.options.canHashChange){
// устанавливаю урл
if(self.options.urlController && (self.options.urlController == true || self.options.urlController.indexOf(self.options.size) >= 0) ){
self.urlController.setUrl(self.model.toJSON(), self.options.size);
}
}else{
self.options.canHashChange = true;
}
}
// ошибка в загрузке изображения
if(!domCache || (domCache && domCache.state === false)){
// вызываю событие
//errorLoading.call(this, domCache);
//if(this.errorLoading) this.errorLoading(domCache);
domCache.$node.addClass('active');
}
if (domCache && domCache.state === '') {
// отправил на загрузку изображение
// после успешной загрузки добавляю active
domCache.$node.addClass('active');
this.renderAndLoadItemHTML(domCache, function(result, cache){
if(result){
self.openImage(cache);
if(self.options.size !== 'def') self.options.canHashChange = true;
if(self.options.canHashChange){
// устанавливаю урл
if(self.options.urlController && (self.options.urlController == true || self.options.urlController.indexOf(self.options.size) >= 0) ){
self.urlController.setUrl(self.model.toJSON(), self.options.size);
}
}else{
self.options.canHashChange = true;
}
}
if(!result){
// ошибка в загрузке изображения
//if(!domCache || (domCache && domCache.state === false)){
// вызываю событие
//errorLoading.call(this, domCache);
//if(self.errorLoading) this.errorLoading(domCache);
//}
}
});
}
if (domCache && domCache.state === true) {
domCache.$node.addClass('active');
this.openImage(domCache);
if(self.options.size !== 'def') self.options.canHashChange = true;
if(this.options.canHashChange){
// устанавливаю урл
if(self.options.urlController && (self.options.urlController == true || self.options.urlController.indexOf(self.options.size) >= 0) ){
self.urlController.setUrl(self.model.toJSON(), self.options.size);
}
}else{
this.options.canHashChange = true;
}
}
},
// надо бы вынести в отдельную вьюху
// но пусть живут тут, вынести всегда можно
nextImage:function(){
var nextImage;
var activeImg = this.model.get('activeImg');
var images = this.model.get('images')[this.options.size];
nextImage = _.find(images, function(img, num){
if(images[num-1] && images[num-1].id == activeImg){
return true;
}
});
nextImage = (nextImage)? nextImage : _.first(images);
if(nextImage && nextImage.id){
this.model.set({activeImg:nextImage.id})
}
},
prevImage:function(){
var prevImage;
var activeImg = this.model.get('activeImg');
var images = this.model.get('images')[this.options.size];
prevImage = _.find(images, function(img, num){
if(images[num+1] && images[num+1].id == activeImg){
return true;
}
});
prevImage = (prevImage)? prevImage : _.last(images);
if(prevImage && prevImage.id){
this.model.set({activeImg:prevImage.id})
}
},
// открыть изображение
// на этот момент весь DOM уже будет сформирован
// метод переназначается в наследниках
openImage:function(imgId){},
// будет вызван при ошибке загрузки изображения
errorLoading:function(cache){},
render:function(){},
/**
* капец какая важная штука remove - иначе СМЕРТЬ БРАУЗЕРУ
* обработчики будут складыватся до бесконечности и вызыватся уже не нужные
*
* потом надо вынести этот функционал глобально, полезная штука (ранее такое было только для DOM)
* для событий моделей и коллекций тоже надо
*
* переназначаю метод remove, что бы удалить лишние обработчики
* дочерние вьюхи или те, кто был создан на время - навешивают события на общую модель для галереи
* мне не нужно случайное выполнение методов,
* поэтому при удалении вьюхи надо убить все событие на которые была подписана она
* или её дети
*
* @returns {*}
*/
remove:function(){
var removeEvents = function(){
var ctx = this;
// удаляю обработчики учитывая контекст
if(ctx.model && ctx.model.off){
for(var n in ctx){
if(typeof ctx[n] == 'function'){
ctx.model.off(null, ctx[n], ctx);
}
}
}
// обойти детей, рекурсия
if(ctx.children){
for(var c in ctx.children){
removeEvents.apply(ctx.children[c])
}
}
};
removeEvents.apply(this);
// стандартный remove от Backbone который расширен мной выше
// удалит DOM и пр.
this.stopListening();
return defaultRemoveFunc.apply(this, arguments);
}
});
});
define([
'jquery',
'underscore',
'backbone',
'modules/galleryObject/views/base',
'modules/galleryObject/views/thumbnails',
'libs/stack-blur',
], function ($,
_,
Backbone,
BaseGalleryClass,
ThumbnailsViewClass,
CanvasBlur) {
// Вьюха одной галереи
var Gallery = BaseGalleryClass.extend({
options:{
size:'def',
buttons:{
navigation:true,
},
classNames:{
wrap: 'gallery-object-def-wrap',
list: 'gallery-object-def-list',
item: 'gallery-object-def-item',
nav: 'gallery-object-def-nav',
button: 'gallery-object-def-btn',
canvas: {
wrap: 'gallery-object-canvas-wrap',
item: 'gallery-object-canvas-item'
}
},
imgSizes:{
width: 800,
height: 600
}
},
className:'gallery-object-default',
tagName: 'div',
events:{
'click .gallery-object-def-nav-item-prev':'eventClickPrevImage',
'click .gallery-object-def-nav-item-next':'eventClickNextImage',
},
initialize: function (options) {
var self = this;
this.children = {};
this.nodes = {};
if(options && options.options){
_.extend(this.options, options.options);
}
this.$el.attr('id', this.model.get('nodeID'));
this.$el.attr('data-gallery-id', this.model.id);
// удалить галерею при удалении модели
this.model.bind('remove', this.remove, this);
this.model.bind('change:activeImg', this.eventChangeActiveImg, this);
this.children.thumbnails = new ThumbnailsViewClass({model:this.model});
// отрисовка обычной галереи
this.render();
// перенести это в urlController
var activeImg = this.model.get('activeImg');
if (!activeImg) {
// разбираю урл
var data = this.urlController.parseUrlToData();
if(data.activeImg){
activeImg = _.find(this.model.get('images')[this.options.size], function(item){
if(item.id == data.activeImg){
return true;
}
});
}
if(!activeImg){
activeImg = _.first(this.model.get('images')[this.options.size]);
}
if(activeImg && activeImg.id){
this.model.set({activeImg: activeImg.id});
}
}
},
eventClickPrevImage:function(){
this.prevImage();
},
eventClickNextImage:function(){
this.nextImage();
},
// создает HTML для канвас элемента
createCanvasHTML: function () {
var html = '';
var className = this.options.classNames.canvas;
html += '<div class="' + className.wrap + '">';
html += '<canvas class="' + className.item + '"></canvas>';
html += '</div>';
return html;
},
// будет вызван после изменения изображения
openImage:function(cache){
var self = this;
if(!cache || !cache.$node) return false;
var $image = cache.$node.find('img');
if(!$image.length) return false;
this.app.hp.images.checkSetImageMargins($image, cache.$node);
// render canvas after image load
this.app.fn.imageLoader($image, function (resp, img) {
if(resp){
self.renderCanvasBG(this.$image[0]);
}
},{
$image: $image
});
},
errorLoading:function(cache){
//console.log('cache', cache)
//if(self.model.get('activeImg') == cache.id){
// // переключение на следующую картинку
// if(self.nextImage) self.nextImage();
//}
},
renderCanvasBG:function(image){
if (this.timers.canvasTimer) {
clearTimeout(this.timers.canvasTimer);
}
var canvas = this.nodes.canvas;
var ctx = canvas.getContext("2d");
var renderCanvas = function(img){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgba(0,0,0,0.6)';
// если картинка не передана - все конец
if (!img) {
return;
}
// если картинка имеет нулевые размеры - не могу рисовать
// если какие-то траблы с канвасными размерами - тоже не могу рисовать
if (!img.naturalWidth || !img.naturalHeight || !canvas.height || !canvas.width) {
return;
}
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
CanvasBlur.fn.stackBlurCanvasRGBA(ctx, 0, 0, canvas.width, canvas.height, 10);
ctx.fillRect(0, 0, canvas.width, canvas.height);
return this;
};
// добавляю задержку перед отрисовкой канваса
// что бы не убить браузер если переключают быстро
if (this.app.getAttr('mobile')) {
this.timers.canvasTimer = setTimeout(function () {
renderCanvas(image);
}, 400);
} else {
this.timers.canvasTimer = setTimeout(function () {
renderCanvas(image);
}, 200);
}
},
render:function(){
var self = this;
var className = this.options.classNames;
this.children.main = this.$el.find('.gallery-object-image_main');
// устанавливаю размеры блока галереи
var width = this.$el.width();
var defSize = this.options.imgSizes;
var calcHeight = Math.ceil((width * defSize.height) / defSize.width);
this.$el.html(this.createListHTML.apply(this));
this.$el.append(this.children.thumbnails.render().el);
this.nodes = {};
this.nodes.$list = this.$el.find('.' + className.list);
this.nodes.$list.parent().append(this.createCanvasHTML());
this.nodes.$canvas = this.$el.find('.' + className.canvas.item);
this.nodes.canvas = this.nodes.$canvas[0];
this.nodes.$list.parent().css('height', calcHeight);
this.nodes.$canvas.css({
height:calcHeight,
width:width
});
this.nodes.$list.swipeleft(function(){
self.eventClickNextImage();
});
this.nodes.$list.swiperight(function(){
self.eventClickPrevImage();
});
this.nodes.canvas.width = width;
this.nodes.canvas.height = calcHeight;
return this;
}
});
return Gallery;
});
define([
'jquery',
'underscore',
'backbone',
'modules/galleryObject/views/base',
'modules/galleryObject/views/thumbnails',
'modules/galleryObject/models/gallery'
], function ($,
_,
Backbone,
BaseGalleryClass,
ThumbnailsViewClass,
GalleryModelClass) {
// вьюхя для вида popup
var GalleryPopUpView = BaseGalleryClass.extend({
options: {
buttons:{
navigation:true,
close:true,
full:true
},
size: 'popup',
classNames: {
wrap: 'gallery-object-popup-wrap',
list: 'gallery-object-popup-list',
item: 'gallery-object-popup-item',
nav: 'gallery-object-popup-nav',
button: 'gallery-object-popup-btn',
canvas: {
wrap: 'gallery-object-canvas-wrap',
item: 'gallery-object-canvas-item'
}
}
},
className: 'gallery-object-popup',
events:{
'click .gallery-object-popup-btn-item-close':'eventClickCloseGallery',
'click .gallery-object-popup-nav-item-prev':'eventClickPrevImage',
'click .gallery-object-popup-nav-item-next':'eventClickNextImage',
'click .gallery-object-popup-item-wrap':'eventClickNextImage'
},
initialize: function (options) {
if(options && options.options){
_.extend(this.options, options.options);
}
this.children = {};
this.nodes = {};
this.$el.css('display', 'none');
},
// будет вызван после изменения изображения
openImage:function(cache){
var self = this;
if(!cache || !cache.$node) return false;
var $image = cache.$node.find('img');
if(!$image.length) return false;
this.app.hp.images.riseImageGallery($image, cache.$node);
setTimeout(function(){
self.app.hp.images.checkSetImageMargins($image, cache.$node);
}, 0);
},
eventClickCloseGallery:function(){
this.hide();
this.urlController.clearUrl();
this.remove();
},
eventClickPrevImage:function(){
this.prevImage();
},
eventClickNextImage:function(){
this.nextImage();
},
// показать всплывающую галерею
show: function () {
this.$el.show();
this.app.views.index.trigger('modal:open');
},
// скрыть всплывающую галерею
hide: function () {
this.$el.hide();
this.app.views.index.trigger('modal:close');
},
// передается модель
// в модели есть вся инфа
render: function (model, openActiveImg, options) {
if (!model) return this;
// пересматриваю dom события
this.delegateEvents();
var self = this;
var data = model.toJSON();
this.models = {};
this.nodes = {};
this.model = new GalleryModelClass();
this.model.bind('remove', this.remove, this);
this.model.bind('change:activeImg', this.eventChangeActiveImg, this);
if(options && options.options){
_.extend(this.options, options.options);
}
if(openActiveImg){
// требуемый размер фоток отсутствует
if(!data.images[this.options.size]) openActiveImg = false;
if(data.images[this.options.size]){
var issetNeedImage = _.find(data.images[this.options.size], function(image){
if(image.id == openActiveImg) return true;
});
if(!issetNeedImage) openActiveImg = false;
}
}
if(!data.activeImg && !openActiveImg){
var activeImg = _.first(data.images[this.options.size]);
if(activeImg && activeImg.id){
data.activeImg = activeImg.id;
}
}
if(openActiveImg && issetNeedImage){
data.activeImg = issetNeedImage.id;
}
self.model.set(data, {silent:true}); // опасное место надое сделать без silent
// render
if(this.children.thumbnails){
this.children.thumbnails.remove();
}
var className = this.options.classNames;
this.$el.attr('data-gallery-id', this.model.id);
this.$el.html(this.createListHTML());
this.nodes.$list = this.$el.find('.' + className.list);
setTimeout(function(){
// создаю дочернюю view с миниатюрами
self.children.thumbnails = new ThumbnailsViewClass({model: self.model, options:{size:'thumbnail-popup'}});
self.$el.append(self.children.thumbnails.render().el);
self.model.trigger('change:activeImg');
}, 0);
return this;
}
});
return GalleryPopUpView;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment