/**
*
* Default text - jQuery plugin for creating popup flyouts
*
* Author: Ilija Matoski
*
* Email: ilijamt@gmail.com
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://github.com/ilijamt/flyoutpopup
*
* Version: 0.2.0
*
* Features:
* Creates popups based on selects
* Can use as temporary note view from any element in the page
* Coloring based on the elements they were spawned from
* Future-compliant with HTML5 spec (will work with Webkit browsers and IE9)
*
* Usage:
* See README at project homepage
*
*/
;
/**
*
* @param {jQuery} $
* @param {window} window
* @param {document} document
* @param {undefined} undefined
*
* @returns undefined
*/
(function($, window, document, undefined) {
"use strict";
var _ = window._;
// Create the defaults once
var pluginName = "flyoutpopup",
defaults = {
selector: '.popupFlyoutAbleElement',
containerClass: 'popupFlyoutContainer',
containerIdPrefix: 'pfl',
template: '
',
attachElementsToTarget: true,
attachTarget: 'body',
attachToElement: null,
noTitleText: 'No title',
noTextText: 'No text',
multiplePopups: false,
draggableOptions: {
revert: true,
opacity: 0.75,
create: null,
start: null,
drag: null,
stop: function(event, ui) {
Plugin.prototype.eventDraggableStop.call(ui.helper.data(pluginName), event, ui);
}
},
colors: ["silver", "gray", "maroon", "red",
"purple", "fuchsia", "green", "lime", "olive", "yellow", "navy",
"blue", "teal", "aqua", "aliceblue", "antiquewhite", "aqua",
"aquamarine", "azure", "beige", "bisque", "black",
"blanchedalmond", "blue", "blueviolet", "brown", "burlywood",
"cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
"darkgoldenrod", "darkgray", "darkgreen", "darkgrey", "darkkhaki",
"darkmagenta", "darkolivegreen", "darkorange", "darkorchid",
"darkred", "darksalmon", "darkseagreen", "darkslateblue",
"darkslategray", "darkslategrey", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue",
"firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro",
"ghostwhite", "gold", "goldenrod", "gray", "green", "greenyellow",
"grey", "honeydew", "hotpink", "indianred", "indigo", "ivory",
"khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon",
"lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow",
"lightgray", "lightgreen", "lightgrey", "lightpink", "lightsalmon",
"lightseagreen", "lightskyblue", "lightslategray",
"lightslategrey", "lightsteelblue", "lightyellow", "lime",
"limegreen", "linen", "magenta", "maroon", "mediumaquamarine",
"mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
"mediumslateblue", "mediumspringgreen", "mediumturquoise",
"mediumvioletred", "midnightblue", "mintcream", "mistyrose",
"moccasin", "navajowhite", "navy", "oldlace", "olive", "olivedrab",
"orange", "orangered", "orchid", "palegoldenrod", "palegreen",
"paleturquoise", "palevioletred", "papayawhip", "peachpuff",
"peru", "pink", "plum", "powderblue", "purple", "red", "rosybrown",
"royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen",
"seashell", "sienna", "silver", "skyblue", "slateblue",
"slategray", "slategrey", "snow", "springgreen", "steelblue",
"tan", "teal", "thistle", "tomato", "turquoise", "violet", "wheat",
"whitesmoke", "yellow", "yellowgreen"]
};
var _fullPluginName = "plugin_" + pluginName;
/**
* Constructor
*
* @param {Object} element
* @param {Object} options
* @returns {_L8.Plugin}
*/
function Plugin(element, options) {
// options
this.options = $.extend({
}, defaults, options);
// plugin internal definitions
this.element = element;
this._defaults = defaults;
this._name = pluginName;
// plugin specific definitions
this.attachToElementName = null;
this.$attachElement = null;
this.validAttachElement = false;
this.dummyId = null;
this.flyoutElements = null;
this.pflCount = 0;
this.template = null;
if ((typeof _ === "function") && (typeof _.VERSION !== "undefined")) {
this.template = _.template(this.options.template);
} else {
this.template = tmpl(this.options.template);
}
if (typeof tmpl === "undefined" && (typeof _ === "undefined")) {
$.error("No templating engine detected, use underscore or tmpl");
}
this.elementId = $(element).prop('tagName') + "#" + $(element).
attr('id');
if (typeof $(element).attr('class') !== "undefined") {
this.elementId = this.elementId + "." + $(element).
attr('class').
split(" ").join(".");
}
this.init();
}
/**
* We have started dragging the element
*
* @param {type} event
* @param {type} ui
*
* @returns {undefined}
*/
Plugin.prototype.eventDraggableStart = function(event, ui) {
};
/**
* Draggable stop
* pflTitle
* @param {type} event
* @param {type} ui
*
* @returns {undefined}
*/
Plugin.prototype.eventDraggableStop = function(event, ui) {
var id = $(event.target).data('targetId');
var pflId = $(event.target).data('pflId');
var data = {
};
if (!this.hasFlyoutPopup(id, pflId, true) || this.options.multiplePopups) {
var title = ui.helper.data('pflTitle');
var text = ui.helper.data('pflTarget');
var evalText = ui.helper.data('pflTargetEval');
if (evalText) {
text = ui.helper[text]();
} else {
text = ui.helper.attr(text);
}
pflId = this.generatePflId();
$(event.target).data('pflId', pflId);
data = {
'id': id,
'title': title,
'text': text,
'pflId': pflId
};
this.createFlyout(data, ui.offset);
}
pflId = null;
data = null;
id = null;
};
/**
* We have created the draggable element
*
* @param {type} event
* @param {type} ui
*
* @returns {undefined}
*/
Plugin.prototype.eventDraggableCreate = function(event, ui) {
};
/**
* We are currently dragging the element
*
* @param {type} event
* @param {type} ui
* @returns {undefined}
*/
Plugin.prototype.eventDraggableDrag = function(event, ui) {
};
/**
* A PFL Id, unique to every flyout used to track how many are out there
*
* @param {String} id The id of the main container
*
* @returns {String}
*/
Plugin.prototype.generatePflId = function(id) {
this.pflCount++;
if (typeof id === "undefined" || id === null) {
return this.pflCount;
}
return id + "_" + this.pflCount;
};
/**
* Initialize function
*
* @returns {undefined}
*/
Plugin.prototype.init = function() {
this.flyoutElements = {
};
try {
this.dummyId = new Date().getTime();
this.attachToElementName = this.options.attachElementsToTarget || (this.options.attachToElement === null) ? this.options.attachTarget : this.attachToElement;
this.$attachElement = $(this.attachToElementName);
this.validAttachElement = (this.$attachElement.length > 0);
} catch (err) {
this.validAttachElement = false;
$.error('Attachment element "' + this.attachToElementName + '" is not valid.' + err);
}
this.updatePluginState();
};
/**
* Used to update the plugin state, and also rebind all the elements that need rebinding
*
* @returns {undefined}
*/
Plugin.prototype.updatePluginState = function() {
this.bindDraggable();
};
/**
* Bind's all the draggable elements.
* You should call this function to rebind the newly created elements.
*
* @returns {undefined}
*/
Plugin.prototype.bindDraggable = function() {
var $elements = $(this.options.selector + ":not(.ui-draggable)");
if ($elements.length > 0) {
var elementId = this.elementId;
var self = this;
$elements.each(function(
index, element) {
$(element).data(pluginName, self);
}).draggable(this.options.draggableOptions);
elementId = null;
self = null;
return true;
}
return false;
};
/**
* Un-Highlight all the flyouts with a color assigned to the popups
*
* @param {String} id
*
* @returns {Boolean}
*/
Plugin.prototype.unhighlightFlyouts = function(id) {
if (typeof id === "undefined" || id === null) {
return false;
}
if (typeof this.flyoutElements[id] === "undefined" || this.flyoutElements[id] === null) {
return false;
}
if (!(this.flyoutElements[id].length > 0)) {
return false;
}
$.each(this.flyoutElements[id]['items'], function(index, element) {
var originalBackgroundColor = $(element).
data('originalBackgroundColor');
$(element).
css('background-color', !(typeof originalBackgroundColor === "undefined" || originalBackgroundColor === null) ? originalBackgroundColor : '');
});
return true;
};
/**
* Get the flyout group color
*
* @param {String} id
*
* @returns {String}
*/
Plugin.prototype.getColor = function(id) {
if (typeof this.flyoutElements[id] === "undefined" || this.flyoutElements[id] === null) {
return false;
}
return this.flyoutElements[id].color;
};
/**
* Highlight all the flyouts with a color assigned to the popups
*
* @param {String} id
*
* @returns {Boolean}
*/
Plugin.prototype.highlightFlyouts = function(id) {
if (typeof id === "undefined" || id === null) {
return false;
}
if (typeof this.flyoutElements[id] === "undefined" || this.flyoutElements[id] === null) {
return false;
}
if (!(this.flyoutElements[id].length > 0)) {
return false;
}
var color = this.flyoutElements[id].color;
$.each(this.flyoutElements[id]['items'], function(index, element) {
var originalBackgroundColor = $(element).
css('background-color');
if (!(typeof originalBackgroundColor === "undefined" || originalBackgroundColor === null)) {
$(element).
data('originalBackgroundColor', originalBackgroundColor);
}
$(element).css('background-color', color);
});
return true;
};
/**
* Do we have a flyout popup on the screen for this element?
*
* @param {String} id
* @param {String} pflId
* @param {Boolean} createNoneExist
*
* @returns {Boolean}
*/
Plugin.prototype.hasFlyoutPopup = function(id, pflId, createNoneExist) {
createNoneExist = typeof createNoneExist === "undefined" || createNoneExist === null ? false : createNoneExist;
if (createNoneExist && (typeof this.flyoutElements[id] === "undefined" || this.flyoutElements[id] === null)) {
this.flyoutElements[id] = {
length: 0,
color: this.options.colors.shift(), // get the next one in line
items: {
}
};
}
if (typeof this.flyoutElements[id] === "undefined" || this.flyoutElements[id] === null) {
return false;
}
return !(typeof this.flyoutElements[id]['items'][pflId] === "undefined" || this.flyoutElements[id]['items'][pflId] === null);
};
/**
* Create a flyout of the data
*
* @param {Object} data
* @param {Object} position
*
* @returns {Boolean}
*/
Plugin.prototype.createFlyout = function(data, position) {
if (!this.validAttachElement) {
return false;
}
if (typeof data === "undefined" || data === null) {
data = {
id: null,
pflId: null
};
}
if (typeof position === "undefined" || position === null) {
position = {
top: 0,
left: 0
};
}
data['id'] = typeof data['id'] === "undefined" || data['id'] === null ? this.dummyId : data['id'];
data['pflId'] = typeof data['pflId'] === "undefined" || data['pflId'] === null ? this.generatePflId() : data['pflId'];
data = $.extend({
'containerClass': this.options.containerClass,
'containerIdPrefix': this.options.containerIdPrefix,
'title': this.options.noTitleText,
'text': this.options.noTextText
}, data);
if (this.hasFlyoutPopup(data['id'], data['pflId'], true) && !this.options.multiplePopups) {
// we already have a popup available
return true;
}
var $element = $(this.template(data));
var self = this;
$element.dialog({
dialogClass: "alert",
close: function(event, ui) {
self.closeFlyout(data['id'], data['pflId']);
}
});
$element.dialog('option', 'position', [
position.left, position.top
]);
this.flyoutElements[data['id']]['items'][data['pflId']] = $element;
this.flyoutElements[data['id']].length++;
return true;
};
/**
* Close a flyout and delete it from the data
*
* @param {type} id
* @param {type} pflId
* @returns {Boolean}
*/
Plugin.prototype.closeFlyout = function(id, pflId) {
if (typeof this.flyoutElements[id] === "undefined" || this.flyoutElements[id] === null) {
return false;
}
if (typeof this.flyoutElements[id]['items'][pflId] === "undefined" || this.flyoutElements[id]['items'][pflId] === null) {
// the element is not present
return false;
}
this.flyoutElements[id]['items'][pflId].dialog('destroy');
this.flyoutElements[id]['items'][pflId].remove();
this.flyoutElements[id]['items'][pflId] = null;
delete this.flyoutElements[id]['items'][pflId];
this.flyoutElements[id].length--;
if (Object.keys(this.flyoutElements[id]['items']).length < 1) {
this.options.colors.push(this.flyoutElements[id].color);
this.flyoutElements[id] = null;
delete this.flyoutElements[id];
}
return true;
};
/**
* Initialize function
*
* @returns {undefined}
*/
Plugin.prototype.destroy = function() {
// remove bindings for the plugin
$(this.options.selector).each(function(
index, element) {
$(element).removeData(pluginName);
});
// remove the bindings
$.each(this.flyoutElements, function(id, elements) {
$.each(elements['items'], function(index, element) {
$(element).remove(); // remove it from the DOM
});
});
this.flyoutElements = null;
this.options = null;
this.element = null;
this._defaults = null;
this._name = null;
this.attachToElementName = null;
this.$attachElement = null;
this.validAttachElement = null;
this.dummyId = null;
this.flyoutElements = null;
this.pflCount = null;
};
/**
* Wrapper for constructor
*
* @param {Array} options
* @returns {Plugin}
*/
$.fn[pluginName] = function(options) {
var args = arguments;
return this.each(function() {
var _plugin = _fullPluginName,
data = $.data(this, _plugin),
method = data ? data[options] : '';
if (!data) {
$.data(this, _plugin, (data = new Plugin(this, options)));
} else if (data instanceof Plugin && typeof method === 'function') {
method.apply(data, Array.prototype.slice.call(args, 1));
if (options === 'destroy') {
$.data(this, _plugin, null);
$.removeData(this, _plugin);
_plugin = null;
}
} else if (!method || options.charAt(0) === '_') {
$.error('Method ' + options + ' does not exist on jQuery.' + pluginName);
}
});
};
})(jQuery, window, document);