You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.3 KiB
JavaScript

5 years ago
/******
*
*
* @constructor
*/
clippy.Balloon = function (targetEl) {
this._targetEl = targetEl;
this._hidden = true;
this._setup();
};
clippy.Balloon.prototype = {
WORD_SPEAK_TIME:200,
CLOSE_BALLOON_DELAY:2000,
_setup:function () {
this._balloon = $('<div class="clippy-balloon"><div class="clippy-tip"></div><div class="clippy-content"></div></div> ').hide();
this._content = this._balloon.find('.clippy-content');
$(document.body).append(this._balloon);
},
reposition:function () {
var sides = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
for (var i = 0; i < sides.length; i++) {
var s = sides[i];
this._position(s);
if (!this._isOut()) break;
}
},
_BALLOON_MARGIN:15,
/***
*
* @param side
* @private
*/
_position:function (side) {
var o = this._targetEl.offset();
var h = this._targetEl.height();
var w = this._targetEl.width();
o.top -= $(window).scrollTop();
o.left -= $(window).scrollLeft();
var bH = this._balloon.outerHeight();
var bW = this._balloon.outerWidth();
this._balloon.removeClass('clippy-top-left');
this._balloon.removeClass('clippy-top-right');
this._balloon.removeClass('clippy-bottom-right');
this._balloon.removeClass('clippy-bottom-left');
var left, top;
switch (side) {
case 'top-left':
// right side of the balloon next to the right side of the agent
left = o.left + w - bW;
top = o.top - bH - this._BALLOON_MARGIN;
break;
case 'top-right':
// left side of the balloon next to the left side of the agent
left = o.left;
top = o.top - bH - this._BALLOON_MARGIN;
break;
case 'bottom-right':
// right side of the balloon next to the right side of the agent
left = o.left;
top = o.top + h + this._BALLOON_MARGIN;
break;
case 'bottom-left':
// left side of the balloon next to the left side of the agent
left = o.left + w - bW;
top = o.top + h + this._BALLOON_MARGIN;
break;
}
this._balloon.css({top:top, left:left});
this._balloon.addClass('clippy-' + side);
},
_isOut:function () {
var o = this._balloon.offset();
var bH = this._balloon.outerHeight();
var bW = this._balloon.outerWidth();
var wW = $(window).width();
var wH = $(window).height();
var sT = $(document).scrollTop();
var sL = $(document).scrollLeft();
var top = o.top - sT;
var left = o.left - sL;
var m = 5;
if (top - m < 0 || left - m < 0) return true;
if ((top + bH + m) > wH || (left + bW + m) > wW) return true;
return false;
},
speak:function (complete, text, hold) {
this._hidden = false;
this.show();
var c = this._content;
// set height to auto
c.height('auto');
c.width('auto');
// add the text
c.text(text);
// set height
c.height(c.height());
c.width(c.width());
c.text('');
this.reposition();
this._complete = complete;
this._sayWords(text, hold, complete);
},
show:function () {
if (this._hidden) return;
this._balloon.show();
},
hide:function (fast) {
if (fast) {
this._balloon.hide();
return;
}
this._hiding = window.setTimeout($.proxy(this._finishHideBalloon, this), this.CLOSE_BALLOON_DELAY);
},
_finishHideBalloon:function () {
if (this._active) return;
this._balloon.hide();
this._hidden = true;
this._hiding = null;
},
_sayWords:function (text, hold, complete) {
this._active = true;
this._hold = hold;
var words = text.split(/[^\S-]/);
var time = this.WORD_SPEAK_TIME;
var el = this._content;
var idx = 1;
this._addWord = $.proxy(function () {
if (!this._active) return;
if (idx > words.length) {
delete this._addWord;
this._active = false;
if (!this._hold) {
complete();
this.hide();
}
} else {
el.text(words.slice(0, idx).join(' '));
idx++;
this._loop = window.setTimeout($.proxy(this._addWord, this), time);
}
}, this);
this._addWord();
},
close:function () {
if (this._active) {
this._hold = false;
} else if (this._hold) {
this._complete();
}
},
pause:function () {
window.clearTimeout(this._loop);
if (this._hiding) {
window.clearTimeout(this._hiding);
this._hiding = null;
}
},
resume:function () {
if (this._addWord) {
this._addWord();
} else if (!this._hold && !this._hidden) {
this._hiding = window.setTimeout($.proxy(this._finishHideBalloon, this), this.CLOSE_BALLOON_DELAY);
}
}
};