206 lines
6.1 KiB
JavaScript
206 lines
6.1 KiB
JavaScript
wpj.domUtils = {
|
|
crossFade: function ($old, $new, complete)
|
|
{
|
|
var width,
|
|
height = $old.outerHeight(true),
|
|
speed = 300;
|
|
|
|
if ($old[0].getBoundingClientRect().width)
|
|
width = $old[0].getBoundingClientRect().width;
|
|
else
|
|
width = $old.outerWidth(true);
|
|
|
|
|
|
if (width <= 0)
|
|
{
|
|
$old.before($new).hide();
|
|
|
|
if (complete)
|
|
complete($old, $new);
|
|
else
|
|
$old.remove();
|
|
return;
|
|
}
|
|
|
|
var $positionWrap = $old.wrap($('<div class="crossfade-wrapper">').width(width).height(height)).parent(),
|
|
$oldWrap = $old.wrap('<div class="crossfade-position old">').parent(),
|
|
$newWrap = $new.wrap('<div class="crossfade-position new">').parent();
|
|
|
|
$newWrap.css({opacity: 0});
|
|
$positionWrap.append($newWrap);
|
|
$new.trigger('crossFaded');
|
|
$oldWrap.animate({opacity: 0}, speed);
|
|
$newWrap.animate({opacity: 1}, speed, undefined, function()
|
|
{
|
|
$oldWrap.unwrap();
|
|
$old.unwrap();
|
|
$new.unwrap();
|
|
if (complete)
|
|
complete($old, $new);
|
|
else
|
|
$old.remove();
|
|
});
|
|
var new_height = $newWrap.height(),
|
|
old_height = $positionWrap.height();
|
|
if (old_height != new_height)
|
|
$positionWrap.animate({height: new_height}, speed);
|
|
},
|
|
reloadParts: function($selector, dataPromise, finishedCallback)
|
|
{
|
|
// Set all parts to loading state
|
|
$selector.addClass('reload-loading').animate({opacity: 0.66}, 300);
|
|
|
|
dataPromise.done(function($html){
|
|
var newParts = wpj.domUtils.crossFadeParts($selector, $html);
|
|
|
|
$selector.removeClass('reload-loading');
|
|
|
|
if (finishedCallback)
|
|
finishedCallback(newParts);
|
|
});
|
|
},
|
|
crossFadeParts: function($oldParts, $newHtml)
|
|
{
|
|
var $oldPart, $newPart, newParts = [], selector;
|
|
|
|
$oldParts.each(function(){
|
|
$oldPart = $(this);
|
|
|
|
selector = '[data-reload="'+$oldPart.data('reload')+'"]';
|
|
$newPart = $newHtml.find(selector).addBack(selector);
|
|
|
|
$.merge(newParts, $newPart);
|
|
|
|
if ($oldPart.closest('.crossfade-wrapper').length || !document.documentElement.contains(this))
|
|
{
|
|
// console.log('$old', 'in crossfade', $oldPart.closest('.crossfade-wrapper').length, 'removed', !document.documentElement.contains(this));
|
|
$oldPart = $('[data-reload="'+$oldPart.data('reload')+'"]');
|
|
|
|
if ($oldPart.length > 1)
|
|
$oldPart = $oldPart.filter('.crossfade-position.new > [data-reload]');
|
|
|
|
$oldPart.html($newPart.html());
|
|
return;
|
|
}
|
|
|
|
if (!$newPart.length)
|
|
{
|
|
// Create dummy empty element if element not in result
|
|
$newPart = $('<div>').attr('data-reload', $oldPart.data('reload'));
|
|
}
|
|
|
|
wpj.domUtils.crossFade($oldPart, $newPart);
|
|
});
|
|
|
|
return newParts;
|
|
},
|
|
reloadPartsFromUrl: function(url, $oldParts, data)
|
|
{
|
|
// Load new category products
|
|
var dataLoaded = $.Deferred(),
|
|
method = data ? 'post' : 'get';
|
|
|
|
wpj.domUtils.reloadParts($oldParts, dataLoaded);
|
|
|
|
$[method](url, data, function (data) {
|
|
dataLoaded.resolve(wpj.domUtils.parseHtml(data));
|
|
});
|
|
},
|
|
getHash: function()
|
|
{
|
|
return location.href.split("#")[1] || "";
|
|
},
|
|
parseHtml: function (html, selector)
|
|
{
|
|
var $content = $("<div>").append($.parseHTML(html, true));
|
|
|
|
if (selector)
|
|
return $content.find(selector);
|
|
else
|
|
return $content.children();
|
|
},
|
|
scrollTo: function ($anchor, speed)
|
|
{
|
|
var offset = $anchor.offset();
|
|
|
|
if (speed == undefined)
|
|
speed = 1000;
|
|
|
|
if (offset)
|
|
{
|
|
$('html, body').stop().animate({
|
|
scrollTop: offset.top - 100
|
|
}, speed);
|
|
}
|
|
},
|
|
activeTimers: {},
|
|
resetTimer: function (id, timeout, callback)
|
|
{
|
|
var timers = wpj.domUtils.activeTimers,
|
|
timer = timers[id];
|
|
if (timer)
|
|
clearTimeout(timer);
|
|
|
|
timers[id] = setTimeout(function ()
|
|
{
|
|
delete timers[id];
|
|
callback();
|
|
}, timeout);
|
|
},
|
|
initOpeners: function($selector)
|
|
{
|
|
if (!$selector)
|
|
$selector = $('body');
|
|
|
|
// Disable animation during init to avoid reflows
|
|
$.fx.off = true;
|
|
|
|
var event = 'change';
|
|
if (!$selector.is('input'))
|
|
event = 'click';
|
|
|
|
$selector.on(event + ' update', '[data-opener]', function(e){
|
|
var $this = $(e.currentTarget),
|
|
$target = $($this.data('opener')),
|
|
checked;
|
|
|
|
if ($this.is('input'))
|
|
checked = $this.is(':checked');
|
|
else
|
|
{
|
|
checked = $this.is('.active');
|
|
if (e.type != 'update')
|
|
checked = !checked;
|
|
}
|
|
|
|
$target[checked ? 'slideDown' : 'slideUp']()[checked ? 'addClass' : 'removeClass']('active').trigger('opened');
|
|
$this[checked ? 'addClass' : 'removeClass']('active');
|
|
|
|
return !$this.is('a');
|
|
})
|
|
// Trigger change event on init to update target visibility
|
|
.find('[data-opener]').trigger('update');
|
|
|
|
$.fx.off = false;
|
|
},
|
|
isInView: function ($elem)
|
|
{
|
|
var $window = $(window),
|
|
docViewTop = $window.scrollTop(),
|
|
docViewBottom = docViewTop + $window.height(),
|
|
elemTop = $elem.offset().top,
|
|
elemBottom = elemTop + $elem.height();
|
|
|
|
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
|
|
},
|
|
/**
|
|
* @param {HTMLElement} openerHtmlElement
|
|
*/
|
|
expandOpener: function (openerHtmlElement)
|
|
{
|
|
var $opener = $(openerHtmlElement);
|
|
$opener.addClass('active');
|
|
$opener.trigger('update');
|
|
}
|
|
};
|