(function($) { /** * Allows icon definition via HTML5 data attrs for easier handling in PHP. * * Adds an alternative appearance so we can toggle back and forth between them * and register event handlers to add custom styling and behaviour. Example use * is in the CMS with the saving buttons - depending on the page's state one of * them will either say "Save draft" or "Saved", and will have different colour. */ $.widget('ssui.button', $.ui.button, { options: { alternate: { icon: null, text: null }, showingAlternate: false }, /** * Switch between the alternate appearances. */ toggleAlternate: function() { if (this._trigger('ontogglealternate')===false) return; // Only switch to alternate if it has been enabled through options. if (!this.options.alternate.icon && !this.options.alternate.text) return; this.options.showingAlternate = !this.options.showingAlternate; this.refresh(); }, /** * Adjust the appearance to fit with the current settings. */ _refreshAlternate: function() { this._trigger('beforerefreshalternate'); // Only switch to alternate if it has been enabled through options. if (!this.options.alternate.icon && !this.options.alternate.text) return; if (this.options.showingAlternate) { this.element.find('.ui-button-icon-primary').hide(); this.element.find('.ui-button-text').hide(); this.element.find('.ui-button-icon-alternate').show(); this.element.find('.ui-button-text-alternate').show(); } else { this.element.find('.ui-button-icon-primary').show(); this.element.find('.ui-button-text').show(); this.element.find('.ui-button-icon-alternate').hide(); this.element.find('.ui-button-text-alternate').hide(); } this._trigger('afterrefreshalternate'); }, /** * Construct button - pulls in options from data attributes. * Injects new elements for alternate appearance (if requested via options). */ _resetButton: function() { var iconPrimary = this.element.data('icon-primary'), iconSecondary = this.element.data('icon-secondary'); if (!iconPrimary) iconPrimary = this.element.data('icon'); // TODO Move prefix out of this method, without requriing it for every icon definition in a data attr if(iconPrimary) this.options.icons.primary = 'btn-icon-' + iconPrimary; if(iconSecondary) this.options.icons.secondary = 'btn-icon-' + iconSecondary; $.ui.button.prototype._resetButton.call(this); // Pull options from data attributes. Overriden by explicit options given on widget creation. if (!this.options.alternate.text) { this.options.alternate.text = this.element.data('text-alternate'); } if (!this.options.alternate.icon) { this.options.alternate.icon = this.element.data('icon-alternate'); } if (!this.options.showingAlternate) { this.options.showingAlternate = this.element.hasClass('ss-ui-alternate'); } // Create missing elements. if (this.options.alternate.icon) { this.buttonElement.append( "" ); } if (this.options.alternate.text) { this.buttonElement.append( "" + this.options.alternate.text + "" ); } this._refreshAlternate(); }, refresh: function() { $.ui.button.prototype.refresh.call(this); this._refreshAlternate(); }, destroy: function() { this.element.find('.ui-button-text-alternate').remove(); this.element.find('.ui-button-icon-alternate').remove(); $.ui.button.prototype.destroy.call( this ); } }); /** * Extends jQueryUI dialog with iframe abilities (and related resizing logic), * and sets some CMS-wide defaults. * * Additional settings: * - 'autoPosition': Automatically reposition window on resize based on 'position' option * - 'widthRatio': Sets width based on percentage of window (value between 0 and 1) * - 'heightRatio': Sets width based on percentage of window (value between 0 and 1) * - 'reloadOnOpen': Reloads the iframe whenever the dialog is reopened * - 'iframeUrl': Create an iframe element and load this URL when the dialog is created */ $.widget("ssui.ssdialog", $.ui.dialog, { options: { // Custom properties iframeUrl: '', reloadOnOpen: true, dialogExtraClass: '', // Defaults modal: true, bgiframe: true, autoOpen: false, autoPosition: true, minWidth: 500, maxWidth: 800, minHeight: 300, maxHeight: 700, widthRatio: 0.8, heightRatio: 0.8, resizable: false }, _create: function() { $.ui.dialog.prototype._create.call(this); var self = this; // Create iframe var iframe = $(''); iframe.bind('load', function(e) { if($(this).attr('src') == 'about:blank') return; iframe.addClass('loaded').show(); // more reliable than 'src' attr check (in IE) self._resizeIframe(); self.uiDialog.removeClass('loading'); }).hide(); if(this.options.dialogExtraClass) this.uiDialog.addClass(this.options.dialogExtraClass); this.element.append(iframe); // Let the iframe handle its scrolling if(this.options.iframeUrl) this.element.css('overflow', 'hidden'); }, open: function() { $.ui.dialog.prototype.open.call(this); var self = this, iframe = this.element.children('iframe'); // Load iframe if(this.options.iframeUrl && (!iframe.hasClass('loaded') || this.options.reloadOnOpen)) { iframe.hide(); iframe.attr('src', this.options.iframeUrl); this.uiDialog.addClass('loading'); } // Resize events $(window).bind('resize.ssdialog', function() {self._resizeIframe();}); }, close: function() { $.ui.dialog.prototype.close.call(this); this.uiDialog.unbind('resize.ssdialog'); $(window).unbind('resize.ssdialog'); }, _resizeIframe: function() { var opts = {}, newWidth, newHeight, iframe = this.element.children('iframe');; if(this.options.widthRatio) { newWidth = $(window).width() * this.options.widthRatio; if(this.options.minWidth && newWidth < this.options.minWidth) { opts.width = this.options.minWidth } else if(this.options.maxWidth && newWidth > this.options.maxWidth) { opts.width = this.options.maxWidth; } else { opts.width = newWidth; } } if(this.options.heightRatio) { newHeight = $(window).height() * this.options.heightRatio; if(this.options.minHeight && newHeight < this.options.minHeight) { opts.height = this.options.minHeight } else if(this.options.maxHeight && newHeight > this.options.maxHeight) { opts.height = this.options.maxHeight; } else { opts.height = newHeight; } } if(!jQuery.isEmptyObject(opts)) { this._setOptions(opts); // Resize iframe within dialog iframe.attr('width', opts.width - parseFloat(this.element.css('paddingLeft')) - parseFloat(this.element.css('paddingRight')) ); iframe.attr('height', opts.height - parseFloat(this.element.css('paddingTop')) - parseFloat(this.element.css('paddingBottom')) ); // Enforce new position if(this.options.autoPosition) { this._setOption("position", this.options.position); } } } }); $.widget("ssui.titlebar", { _create: function() { this.originalTitle = this.element.attr('title'); var self = this; var options = this.options; var title = options.title || this.originalTitle || ' '; var titleId = $.ui.dialog.getTitleId(this.element); this.element.parent().addClass('ui-dialog'); var uiDialogTitlebar = this.element. addClass( 'ui-dialog-titlebar ' + 'ui-widget-header ' + 'ui-corner-all ' + 'ui-helper-clearfix' ); // By default, the if(options.closeButton) { var uiDialogTitlebarClose = $('') .addClass( 'ui-dialog-titlebar-close ' + 'ui-corner-all' ) .attr('role', 'button') .hover( function() { uiDialogTitlebarClose.addClass('ui-state-hover'); }, function() { uiDialogTitlebarClose.removeClass('ui-state-hover'); } ) .focus(function() { uiDialogTitlebarClose.addClass('ui-state-focus'); }) .blur(function() { uiDialogTitlebarClose.removeClass('ui-state-focus'); }) .mousedown(function(ev) { ev.stopPropagation(); }) .appendTo(uiDialogTitlebar); var uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('')) .addClass( 'ui-icon ' + 'ui-icon-closethick' ) .text(options.closeText) .appendTo(uiDialogTitlebarClose); } var uiDialogTitle = $('') .addClass('ui-dialog-title') .attr('id', titleId) .html(title) .prependTo(uiDialogTitlebar); uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); }, destroy: function() { this.element .unbind('.dialog') .removeData('dialog') .removeClass('ui-dialog-content ui-widget-content') .hide().appendTo('body'); (this.originalTitle && this.element.attr('title', this.originalTitle)); } }); $.extend($.ssui.titlebar, { version: "0.0.1", options: { title: '', closeButton: false, closeText: 'close' }, uuid: 0, getTitleId: function($el) { return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid); } }); }(jQuery));