Index: modules/system/system.css =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.css,v retrieving revision 1.40 diff -u -r1.40 system.css --- modules/system/system.css 16 Nov 2007 13:16:50 -0000 1.40 +++ modules/system/system.css 20 Nov 2007 02:02:46 -0000 @@ -537,3 +537,58 @@ span.password-confirm span { font-weight: normal; } + +/* +** Popup Dialog box styles +*/ + +#dialog-overlay { + position: fixed; + width: 100%; + height: 100%; +/* opacity: 0.4; */ + background: black; + z-index: 9; +} + +#dialog-overlay .loading { + background: black url(../../misc/loading.gif) no-repeat; +} + +#dialog { + border: 1px solid black; + background: white; + position: absolute; + opacity: 1.0; + z-index: 10; + color: black; + padding: 0.5em; +} + +#dialog-title { + background: #222; + color: white; + padding: 0.2em; + margin: 0.2em; +} + +#dialog-title div.title { + float:left; +} + +#dialog-title #dialog-close { + float:right; +} +#dialog-title #dialog-close a { + color: red; +} +#dialog-title div.clear { + clear:both; +} + +#dialog input { + margin: 0.1em; +} + + + Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.551 diff -u -r1.551 system.module --- modules/system/system.module 11 Nov 2007 08:48:22 -0000 1.551 +++ modules/system/system.module 20 Nov 2007 02:02:47 -0000 @@ -451,10 +451,37 @@ 'access callback' => TRUE, 'type' => MENU_CALLBACK, 'file' => 'system.admin.inc', - ); + ); + + // Used for dialog popups + $items['get-raw'] = array( + 'page callback' => 'system_get_raw_content', + 'access arguments' => TRUE, + 'type' => MENU_CALLBACK, + ); + return $items; } + +/* + * Return the content of a path as html, without the page's theming wrapper + * Used by dialogs.js for a popup with the content of a link + */ +function system_get_raw_content() { + global $base_url; + $path = $_GET['path']; + $path = substr( $path, strlen($base_url) + 1 ); + $content = menu_execute_active_handler( $path ); + $title = '
'. drupal_get_title() .'
'; + + if( $content == MENU_NOT_FOUND ) { + $content .= "Path not found: $path "; + } + print $title . '
'. $content .'
'; +} + + function system_init() { // Use the administrative theme if the user is looking at a page in the admin/* path. if (arg(0) == 'admin' || (variable_get('node_admin_theme', '0') && arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit'))) { @@ -1698,3 +1725,6 @@ $image = theme('image', $image_path, t('Powered by Drupal, an open source content management system'), t('Powered by Drupal, an open source content management system')); return l($image, 'http://drupal.org', array('html' => TRUE, 'absolute' => TRUE, 'external' => TRUE)); } + + + Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.715 diff -u -r1.715 common.inc --- includes/common.inc 16 Nov 2007 15:35:24 -0000 1.715 +++ includes/common.inc 20 Nov 2007 02:02:46 -0000 @@ -1411,6 +1411,14 @@ $options['attributes']['title'] = strip_tags($options['attributes']['title']); } + if( isset($options['popup']) ) { + drupal_add_js('misc/jquery.form.js'); + drupal_add_js('misc/dialogs.js'); + drupal_add_basepath(); + $options['attributes']['popup'] = $options['popup']; + } + + return ''. ($options['html'] ? $text : check_plain($text)) .''; } @@ -2039,6 +2047,18 @@ drupal_add_js($settings, 'setting'); } +/* + * Provide base_path for javascript. Needed for many Ajax calls + */ +function drupal_add_basepath() { + static $bathpath_added = FALSE; + if (!$bathpath_added) { + drupal_add_js( array( 'base_path' => base_path() ), 'setting' ); + $bathpath_added = TRUE; + } +} + + /** * Aggregate JS files, putting them in the files directory. * Index: modules/block/block.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v retrieving revision 1.11 diff -u -r1.11 block.admin.inc --- modules/block/block.admin.inc 14 Nov 2007 09:49:30 -0000 1.11 +++ modules/block/block.admin.inc 20 Nov 2007 02:02:46 -0000 @@ -74,7 +74,7 @@ if ($throttle) { $form[$key]['throttle'] = array('#type' => 'checkbox', '#default_value' => isset($block['throttle']) ? $block['throttle'] : FALSE); } - $form[$key]['configure'] = array('#value' => l(t('configure'), 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta'])); + $form[$key]['configure'] = array('#value' => l(t('configure'), 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta'], array( 'popup' => true ))); if ($block['module'] == 'block') { $form[$key]['delete'] = array('#value' => l(t('delete'), 'admin/build/block/delete/'. $block['delta'])); } Index: modules/block/block.js =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.js,v retrieving revision 1.1 diff -u -r1.1 block.js --- modules/block/block.js 14 Nov 2007 09:49:30 -0000 1.1 +++ modules/block/block.js 20 Nov 2007 02:02:46 -0000 @@ -17,6 +17,7 @@ // A custom message for the blocks page specifically. Drupal.theme.tableDragChangedWarning = function () { + Drupal.markPageUnsaved('edit-submit'); //add warning popup to all links return '
' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t("The changes to these blocks will not be saved until the Save blocks button is clicked.") + '
'; }; Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.40 diff -u -r1.40 drupal.js --- misc/drupal.js 5 Oct 2007 09:35:08 -0000 1.40 +++ misc/drupal.js 20 Nov 2007 02:02:46 -0000 @@ -273,3 +273,17 @@ return '' + Drupal.checkPlain(str) + ''; } }; + +/* + * Called when there is unsaved data on the page + * Warn users when the click links that they could lose their changes + * + * @param submit_id + * the id of the submit button to page the page + */ +Drupal.markPageUnsaved = function(submit_id) { + dialog = new Drupal.dialog(); + $('a[href!=#]').addClass('unsaved-warning'); + $('a[href!=#]').click( function(){ return dialog.open_unsaved(this, submit_id); } ); +}; + Index: misc/dialogs.js =================================================================== RCS file: misc/dialogs.js diff -N misc/dialogs.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ misc/dialogs.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,178 @@ +// $Id $ + + +// remove /**/ for debugging +var console = {}; +console.log = function() {}; + + + +Drupal.behaviors.dialog = function(context) { + var dialog = new Drupal.dialog(); + $('a[popup]', context).click( function(){ return dialog.open_path(this, 800); } ); +}; + +Drupal.dialog = function() { + this.default_width = 480; +}; + + +Drupal.dialog.prototype.add_overlay = function() { + var overlay = $( Drupal.theme('dialogsOverlay') ); + + overlay.css( 'opacity', '0.4' ); // for ie + $('body').prepend( overlay ); + return overlay; +}; + +Drupal.dialog.prototype.open = function( title, body, buttons, width, overlay ) { + if( !width ) { + width = this.default_width; + } + + if( !overlay ) { + overlay = this.add_overlay(); + } + + // center on the screen, add in offsets if the window has been scrolled + var overlay_width = overlay.width(); + var overlay_height = overlay.height(); + var left = ( overlay_width / 2 ) - ( width / 2 ) + f_scrollLeft(); + var top = 0; // we will reposition after adding to page + var dialog = Drupal.theme('dialogsDialog', left, top, width, title, body, buttons); + + overlay.before( dialog ); // dialog is added, but still hidden. + + // Adding button functions + for ( var id in buttons) { + var func = buttons[id].func; + $('#'+id).click( func ); + } + $('#dialog-close').click( this.close ); + + //Get dialog's height on the page, and center vertically before showing. + var dialog_height = $('#dialog').height(); + console.log( "height: " + dialog_height ); + console.log( "window: " + overlay_height ); + if( dialog_height < overlay_height ) { + top = ( overlay_height / 2 ) - ( dialog_height / 2 ) + f_scrollTop(); + } + else { // dialog is too big to fit on screen + top = 20 + f_scrollTop(); + } + $('#dialog').css('top', top); + $('#dialog').css('display', 'block'); // center and reveal + + return false; +}; + + +Drupal.dialog.prototype.open_unsaved = function( a, submit_id ) { + var body = Drupal.t("There are unsaved changes on this page. If you click away from this page, you will lose those changes."); + var popup = this; + var buttons = { + 'dialog_save': { + title: Drupal.t('Save Changes'), + func: function(){ + popup.close(); + // $('#block-admin-display-form').submit(); // doesn't work at all, don't know why + // $('#block-admin-display-form').ajaxForm( {success: function(){alert('form')}} ); // works, but only when submit is click manually + // $('#block-admin-display-form').ajaxSubmit( {success: function(){alert('submit')}} ); // doesn't work - doesn't send back hiddens or op + $('#'+submit_id).click(); // works but reloads + // window.location = a.href; // race condition, kills the saving ~50% of the time + } + }, + 'dialog_submit': { + title: Drupal.t('Discard Changes'), + func: function(){ + popup.close(); + window.location = a.href; + } + }, + 'dialog_cancel': { + title: Drupal.t('Cancel'), + func: function(){ popup.close(); } } + }; + + this.open( "Warning - Please Confirm", body, buttons ); + return false; +}; + +Drupal.dialog.prototype.open_path = function( a, width, height ) { + if( $(a).is('.unsaved-warning') ) { + return false; // don't do popup on unsaved-warning links + } + var url = a.href; + var popup = this; + // let the user know something is happening + $('body').css("cursor", "wait"); + var overlay = this.add_overlay(); + + // loaded the link's path into the dialog, instead going to new page + $.get(Drupal.settings.base_path+ "get-raw?path="+url, function(data) { + var title = $(data).eq(0).html(); + var body = $(data).slice(1).html(); + popup.open( title, body, null, 600, overlay ); + $('body').css("cursor", "auto"); + }); + return false; +} + +Drupal.dialog.prototype.close = function() { + $('#dialog').remove(); + $('#dialog-overlay').remove(); +}; + + +Drupal.theme.prototype.dialogsOverlay = function () { + return '
'; +}; + +Drupal.theme.prototype.dialogsDialog = function(left, top, width, title, body, buttons) { + var dialog = ''; // close dialog + return dialog; +}; + +/** + * + * Utility functions taken from http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html + * + */ + +function f_scrollLeft() { + return f_filterResults ( + window.pageXOffset ? window.pageXOffset : 0, + document.documentElement ? document.documentElement.scrollLeft : 0, + document.body ? document.body.scrollLeft : 0 + ); +}; +function f_scrollTop() { + return f_filterResults ( + window.pageYOffset ? window.pageYOffset : 0, + document.documentElement ? document.documentElement.scrollTop : 0, + document.body ? document.body.scrollTop : 0 + ); +}; +function f_filterResults(n_win, n_docel, n_body) { + var n_result = n_win ? n_win : 0; + if (n_docel && (!n_result || (n_result > n_docel))) + n_result = n_docel; + return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result; +};