/** * * 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: '
<%= text %>
', 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);