So, I’m a programmer. It’s pretty much impossible that this blog won’t one day include information about the programming that I’m doing. Thus, I though it’d be nice to try and make sure that I can put nicely structured and pretty code-blocks in my posts. Here’s my first attempt at doing so:
[cc lang='javascript' ]
var Dashbox = Class.create({
/**************************************************************** PROPERTIES */
overlay_id: “screen_overlay_for_dialog”, // id given to the overlay elements
dialog_class: “dashbox”, // the class added to all of the dialogs
dialog_id: null, // will be set when dialog is created
removeDiv: true, // if true, the dialog div is removed from the body when it’s closed
json: null, // sent to server in this.activate()
href: “”, // url of server page to fetch in activate()
/**************************************************************** DEFAULT STYLES */
// the following styles are applied to the overlay and dialog objects in initiatlize below. we make them properties
// of the class so that they can be altered by the user of this class as necessary.
overlay_style: “background: #FFF; filter: alpha(opacity=50); left: 0; opacity: .50; position: absolute; top: 0; width: 100%; z-index: 5000″,
dialog_style: “background: #252525; border: 1px solid #FFF; color: #FFF; margin-left: -250px; padding: 10px; width: 500px; z-index: 9999″,
/**************************************************************** METHODS */
// this function is called when the class is constructed. the first parameter is required; it’s the href of the
// page we’re going to load via ajax within the dialog. the latter two parameters are optional: the first replace
// the default this.responders object and the second is for custom CSS rules for this specific dialog allowing
// different dialogs to have different styles.
initialize: function(href, custom_responders, custom_dialog_options) {
var body = $$(“body”)[0];
this.href = href;
// the first dashbox that’s added to a page will also trigger the creation of the overlay div. subsequent
// dashboxes will not recreate this div because of the if-statement.
if(!$(this.overlay_id)) body.insert(new Element(“div”, { id: this.overlay_id }).setStyle(this.overlay_style).hide());
var dialog = new Element(“div”).setStyle(this.dialog_style);
if(custom_dialog_options) dialog.setStyle(custom_dialog_options);
// all dashbox dialogs must have the following three styles (and the margin-left style that we work on below)
// so we’ll override them if they’ve been set otherwise.
dialog.setStyle(“position: absolute; left: 50%;”).addClassName(this.dialog_class);
this.dialog_id = dialog.identify(); // creates an id for this dialog and saves it in the property
body.insert(dialog.hide()); // hide and add the dialog to the bottom of the body
// last thing to do with respect to this dialog’s styles is to make sure that the left margin of the
// dialog is exactly equal to negative one half the width of the dialog. otherwise, the dialog isn’t
// centered in the middle of the screen.
dialog.setStyle(“margin-left: ” + Math.floor(dialog.getWidth() * -.5) + “px”);
// the optional custom responders parameter can contain up to five functions that will be called during
// the lifecycle of this dialog below. those functions must be named beforeLoad, beforeOpen, afterOpen,
// beforeClose, and afterClose. the final three are the most commonly used. here, we’ll copy the custom
// responders into this class. we do this within initialize so that sub-classes of Dashbox can have
// their own responders separate from their parentclass (this one) and any other Dashboxes within
// the DOM
if(custom_responders) for(responder in custom_responders) this[responder] = custom_responders[responder];
},
activate: function(event) {
if(event) event.stop();
this.setOverlayDimensions($(this.overlay_id)); // sets overlay dimensions based on page and adjusts for scrolling
if(this.beforeLoad) this.beforeLoad(); // calls the beforeLoad handler with this object as the scope
// notice that we send this.json to the server as the parameters for the Updater. this property defaults to
// null above but if it’s necessary, it can be set otherwise either by hand when creating the dashbox or
// during the beforeLoad handler called above.
new Ajax.Updater(this.dialog_id, this.href, {
parameters: this.json, evalScripts: true, onComplete: this.show_dialog.bind(this)
});
},
show_dialog: function() {
// unlike the other event handlers beforeOpen can return a boolean false value indicating that, for
// some reason, that it is not “safe” to show the dialog. we rely on the short curcuiting of the
// AND conditional should beforeOpen be null.
if(this.beforeOpen && this.beforeOpen()===false) return;
// some versions IE have problems with opacity over select boxes. thus, we’ll simply hide them all
// here if we’re using IE prior to showing the overlay and the dialog. we set their visibility style
// to hidden to avoid the dom element repositioning that would happen if we used hide() instead.
if(Prototype.Browser.IE) {
$$(“select”).invoke(“setStyle”, “visibility: hidden”); // hide them all
$$(“.dashbox select”).invoke(“setStyle”, “visibility: visible”); // show any in a dialog
}
// flash and other embedded objects will likely have a z-index that’s forced to be as high as possible
// especially in Firefox. thus, we’ll hide them here.
$w(“embed object”).each(function(tag) { $$(tag).invoke(“hide”); });
// now to actual show the dialog. we set the dialog div’s display to block and move it onto the
// screen such that it is centered using the this.calculate_dialog_top() function.
$(this.overlay_id).show();
$(this.dialog_id).setStyle(“top: ” + this.calculate_dialog_top() + “px”).show();
// now that we’ve shown the dialog, we’ll call the afterOpen handler. the default action of this
// handler (above) is to find elements with dialog attributes equal to deactivate and make them
// close the dialog.
if(this.afterOpen) this.afterOpen();
},
close_dialog: function(event) {
if(event && event.stop) event.stop();
// before we actually close the dialog, we want to call the beforeClose handler. this handler allows us to
// make sure that all the work that the visitor needed to do within the dialog has actually been done and
// if the handler returns boolean false, we’ll actually avoid closing the dialog. this gives the dialog a
// chance to verify that form values are in the correct format, for example.
if(this.beforeClose && this.beforeClose(event)===false) return;
// if we didn’t return from this function (thus not closing the dialog) we can now close it. since we hid
// select elements in IE, we’ll want to re-show them here. also, our embed and object elements need to be
// re-shown as well. then, since dialogs could potentially have dialogs added to them, we’ll close any div
// elements within this dialog which have the appropriate dialog class as defined above. finally, we’ll
// close this dialog by hiding it.
if(Prototype.Browser.IE) $$(“select”).invoke(“setStyle”, “visibility: visible”);
$w(“embed object”).each(function(tag) { $$(tag).invoke(“show”); });
$(this.dialog_id).select(“div.”+this.dialog_class).invoke(“hide”);
$(this.dialog_id).hide();
// to hide the overlay, we first need to make sure that all dialogs have been closed. to do this, we get a list of
// all divs with the appropriate class as defined in the document and then get a list of booleans for their visiblity.
// with that list, we can find any boolean true value. if we find such a value, we’re done as the not operator at the
// front of the if-conditional will stop after the first boolean true. however, if we don’t find a boolean true value
// then we’ll execute the if-block, which hides the overlay.
if(!$$(“div.”+this.dialog_class).invoke(“visible”).find(function(boolean) { return boolean===true }))
$(this.overlay_id).hide();
// and the last thing we’ll do is simply call the afterClose function to allow the user to clean
// up or process information that may have been processed by the dialog.
if(this.afterClose != null) this.afterClose();
// if you’re going to be re-opening the same dialog on the same page over and over again, it makes
// sense to alter this.removeDiv from true to false. this will let the div element be persistant
// within the page and allows you to re-call the activate() method for the same object more than
// once which avoids recreating it over and over again sucking up memory on visitor’s machines.
if(this.removeDiv) $(this.dialog_id).remove() // remove the content and the div
else $(this.dialog_id).update(“”); // remove the content without removing the div
},
calculate_dialog_top: function() {
wHeight = this.getWindowHeight();
dHeight = $(this.dialog_id).getHeight();
diff = Math.floor((wHeight – dHeight)/2); // get the halfway point between the window & dialog heights
diff += this.getWindowScroll(); // add on the number of pixels we’ve scrolled from the top
return diff < 0 ? 0 : diff; // and return zero or that difference to place this dialog
},
// the following two functions directly from control.modal.js by Ryan Johnson available online at
// http://livepipe.net/projects/control_modal/. getWindowScroll added using the information within Lightbox Gone
// Wild’s (http://particletree.com/features/lightbox-gone-wild/) getScroll() function by Chris Campbell.
getWindowWidth: function() { return self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0; },
getWindowHeight: function() { return self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0; },
getWindowScroll: function() { return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; },
setOverlayDimensions: function(overlay) {
// to make sure that our overlay is the full width of the window, we’ll extend it here. the only reason it wouldn’t
// be the width of the window is if the window has been extended due to AJAX or if there is a width specification on
// the body tag with a non-static position style.
var win_width = this.getWindowWidth();
if(overlay.getWidth() < win_width) overlay.setStyle(“width: ” + win_width + “px”); // now to set the height of the overlay we’ll either use the window’s height or the total scrolling height of the // body, which ever is greater. var body = $$(“body”)[0]; var doc = body.up(); var win_height = this.getWindowHeight(); var win_scroll = body.offsetHeight > doc.scrollHeight ? body.offsetHeight : doc.scrollHeight;
overlay.setStyle(“height: ” + (win_height > win_scroll ? win_height : win_scroll) + “px”);
}
});
document.fire(“dashbox:loaded”);
[/cc]