metro4
Version:
The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style
247 lines (200 loc) • 7.64 kB
JavaScript
var Popover = {
init: function( options, elem ) {
this.options = $.extend( {}, this.options, options );
this.elem = elem;
this.element = $(elem);
this.popover = null;
this.popovered = false;
this.size = {
width: 0,
height: 0
};
this._setOptionsFromDOM();
this._create();
return this;
},
options: {
popoverText: "",
popoverHide: 3000,
popoverTimeout: 10,
popoverOffset: 10,
popoverTrigger: Metro.popoverEvents.HOVER,
popoverPosition: Metro.position.TOP,
hideOnLeave: false,
closeButton: true,
clsPopover: "",
clsPopoverContent: "",
onPopoverShow: Metro.noop,
onPopoverHide: Metro.noop,
onPopoverCreate: Metro.noop
},
_setOptionsFromDOM: function(){
var element = this.element, o = this.options;
$.each(element.data(), function(key, value){
if (key in o) {
try {
o[key] = JSON.parse(value);
} catch (e) {
o[key] = value;
}
}
});
},
_create: function(){
this._createEvents();
},
_createEvents: function(){
var that = this, element = this.element, o = this.options;
var event;
switch (o.popoverTrigger) {
case Metro.popoverEvents.CLICK: event = Metro.events.click; break;
case Metro.popoverEvents.FOCUS: event = Metro.events.focus; break;
default: event = Metro.events.enter;
}
element.on(event, function(){
if (that.popover !== null || that.popovered === true) {
return ;
}
setTimeout(function(){
that.createPopover();
Utils.exec(o.onPopoverShow, [that.popover], element[0]);
if (o.popoverHide > 0) {
setTimeout(function(){
that.removePopover();
}, o.popoverHide);
}
}, o.popoverTimeout);
});
if (o.hideOnLeave === true) {
element.on(Metro.events.leave, function(){
that.removePopover();
});
}
$(window).on(Metro.events.scroll, function(){
if (that.popover !== null) that.setPosition();
});
},
setPosition: function(){
var popover = this.popover, size = this.size, o = this.options, element = this.element;
if (o.popoverPosition === Metro.position.BOTTOM) {
popover.addClass('bottom');
popover.css({
top: element.offset().top - $(window).scrollTop() + element.outerHeight() + o.popoverOffset,
left: element.offset().left + element.outerWidth()/2 - size.width/2 - $(window).scrollLeft()
});
} else if (o.popoverPosition === Metro.position.RIGHT) {
popover.addClass('right');
popover.css({
top: element.offset().top + element.outerHeight()/2 - size.height/2 - $(window).scrollTop(),
left: element.offset().left + element.outerWidth() - $(window).scrollLeft() + o.popoverOffset
});
} else if (o.popoverPosition === Metro.position.LEFT) {
popover.addClass('left');
popover.css({
top: element.offset().top + element.outerHeight()/2 - size.height/2 - $(window).scrollTop(),
left: element.offset().left - size.width - $(window).scrollLeft() - o.popoverOffset
});
} else {
popover.addClass('top');
popover.css({
top: element.offset().top - $(window).scrollTop() - size.height - o.popoverOffset,
left: element.offset().left + element.outerWidth()/2 - size.width/2 - $(window).scrollLeft()
});
}
},
createPopover: function(){
var that = this, elem = this.elem, element = this.element, o = this.options;
var popover;
var neb_pos;
var id = Utils.elementId("popover");
var closeButton;
if (this.popovered) {
return ;
}
popover = $("<div>").addClass("popover neb").addClass(o.clsPopover);
popover.attr("id", id);
$("<div>").addClass("popover-content").addClass(o.clsPopoverContent).html(o.popoverText).appendTo(popover);
if (o.popoverHide === 0 && o.closeButton === true) {
closeButton = $("<button>").addClass("button square small popover-close-button bg-white").html("×").appendTo(popover);
closeButton.on(Metro.events.click, function(){
that.removePopover();
});
}
switch (o.popoverPosition) {
case Metro.position.TOP: neb_pos = "neb-s"; break;
case Metro.position.BOTTOM: neb_pos = "neb-n"; break;
case Metro.position.RIGHT: neb_pos = "neb-w"; break;
case Metro.position.LEFT: neb_pos = "neb-e"; break;
}
popover.addClass(neb_pos);
if (o.closeButton !== true) {
popover.on(Metro.events.click, function(){
that.removePopover();
});
}
this.popover = popover;
this.size = Utils.hiddenElementSize(popover);
if (elem.tagName === 'TD' || elem.tagName === 'TH') {
var wrp = $("<div/>").css("display", "inline-block").html(element.html());
element.html(wrp);
element = wrp;
}
this.setPosition();
popover.appendTo($('body'));
this.popovered = true;
Utils.exec(o.onPopoverCreate, [popover], element[0]);
},
removePopover: function(){
var that = this;
var timeout = this.options.onPopoverHide === Metro.noop ? 0 : 300;
var popover = this.popover;
if (!this.popovered) {
return ;
}
Utils.exec(this.options.onPopoverHide, [popover], this.elem);
setTimeout(function(){
popover.hide(0, function(){
popover.remove();
that.popover = null;
that.popovered = false;
});
}, timeout);
},
show: function(){
var that = this, element = this.element, o = this.options;
if (this.popovered === true) {
return ;
}
setTimeout(function(){
that.createPopover();
Utils.exec(o.onPopoverShow, [that.popover], element[0]);
if (o.popoverHide > 0) {
setTimeout(function(){
that.removePopover();
}, o.popoverHide);
}
}, o.popoverTimeout);
},
hide: function(){
this.removePopover();
},
changeAttribute: function(attributeName){
var that = this, element = this.element, o = this.options;
var changeText = function(){
o.popoverText = element.attr("data-popover-text");
if (that.popover) {
that.popover.find(".popover-content").html(o.popoverText);
that.setPosition();
}
};
var changePosition = function(){
o.popoverPosition = element.attr("data-popover-position");
that.setPosition();
};
switch (attributeName) {
case "data-popover-text": changeText(); break;
case "data-popover-position": changePosition(); break;
}
}
};
Metro.plugin('popover', Popover);