';
Index: modules/help/help.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/help/help.admin.inc,v
retrieving revision 1.5
diff -u -r1.5 help.admin.inc
--- modules/help/help.admin.inc 25 Nov 2007 11:11:17 -0000 1.5
+++ modules/help/help.admin.inc 19 Mar 2008 18:33:35 -0000
@@ -23,7 +23,7 @@
$output = '';
if (module_hook($name, 'help')) {
$module = drupal_parse_info_file(drupal_get_path('module', $name) .'/'. $name .'.info');
- drupal_set_title($module['name']);
+ drupal_set_title(t('Help: '). $module['name']);
$temp = module_invoke($name, 'help', "admin/help#$name", drupal_help_arg());
if (empty($temp)) {
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.50
diff -u -r1.50 content_types.inc
--- modules/node/content_types.inc 27 Jan 2008 18:03:05 -0000 1.50
+++ modules/node/content_types.inc 19 Mar 2008 18:33:36 -0000
@@ -10,6 +10,7 @@
* Displays the content type admin overview page.
*/
function node_overview_types() {
+ drupal_add_popups();
$types = node_get_types();
$names = node_get_types('names');
$header = array(t('Name'), t('Type'), t('Description'), array('data' => t('Operations'), 'colspan' => '2'));
@@ -29,7 +30,7 @@
// Set the delete column.
if ($type->custom) {
- $row[] = array('data' => l(t('delete'), 'admin/content/node-type/'. $type_url_str .'/delete'));
+ $row[] = array('data' => l(t('delete'), 'admin/content/node-type/'. $type_url_str .'/delete', array('attributes'=>array('class'=>'popup-form'))));
}
else {
$row[] = array('data' => '');
Index: modules/menu/menu.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v
retrieving revision 1.29
diff -u -r1.29 menu.admin.inc
--- modules/menu/menu.admin.inc 23 Feb 2008 08:13:09 -0000 1.29
+++ modules/menu/menu.admin.inc 19 Mar 2008 18:33:36 -0000
@@ -61,6 +61,7 @@
*/
function _menu_overview_tree_form($tree) {
static $form = array('#tree' => TRUE);
+ drupal_add_popups();
foreach ($tree as $data) {
$title = '';
$item = $data['link'];
@@ -97,11 +98,11 @@
$operations['edit'] = l(t('edit'), 'admin/build/menu/item/'. $item['mlid'] .'/edit');
// Only items created by the menu module can be deleted.
if ($item['module'] == 'menu' || $item['updated'] == 1) {
- $operations['delete'] = l(t('delete'), 'admin/build/menu/item/'. $item['mlid'] .'/delete');
+ $operations['delete'] = l(t('delete'), 'admin/build/menu/item/'. $item['mlid'] .'/delete', array('attributes'=>array('class'=>'popup-form')));
}
// Set the reset column.
elseif ($item['module'] == 'system' && $item['customized']) {
- $operations['reset'] = l(t('reset'), 'admin/build/menu/item/'. $item['mlid'] .'/reset');
+ $operations['reset'] = l(t('reset'), 'admin/build/menu/item/'. $item['mlid'] .'/reset', array('attributes'=>array('class'=>'popup-form')));
}
$form[$mlid]['operations'] = array();
Index: modules/popuppage/popuppage.js
===================================================================
RCS file: modules/popuppage/popuppage.js
diff -N modules/popuppage/popuppage.js
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/popuppage/popuppage.js 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,247 @@
+// $Id:$
+
+/**
+ * This module uses the Popup API to build dialogs that show the content from a Drupal page.
+ *
+ * It is assumed that the pages being returned from the Drupal server will be JSON
+ * and have the following format:
+ *
+ * response.title = The page title.
+ * response.messages = Error, warning and status messages, as HTML.
+ * response.path = The page URL.
+ * response.content = The content of the page, as HTML.
+ */
+
+/**
+ * Attach the popup bevior to the all the requested links on the page.
+ *
+ * @param context: The jQuery object to apply the behaviors to.
+ */
+Drupal.behaviors.popuppage = function(context) {
+ var popups = new Drupal.popups();
+
+ // Add the popup-link-in-dialog behavior to links defined in Drupal.settings.popups.links array.
+ // TODO: how to handle popups-in-popups?
+ for (var link in Drupal.settings.popups.links) {
+ var options = Drupal.settings.popups.links[link];
+ popups.attach(context, link, options); // Needs to be seperate function for closure.
+ }
+ popups.attach(context, 'a.popup', {});
+};
+
+/**
+ * Attach the popup behavior to a particular link.
+ *
+ * @param link - link that was clicked.
+ * @param options - options associated with the link.
+ */
+Drupal.popups.prototype.attach = function(context, link, options) {
+ var popups = this;
+ $(link, context).not('.popups-processed').each( function() {
+ $(this).click( function(e){
+ var a = this;
+ // If the option is distructive, check if the page is already modified, and offer to save.
+ var page_is_dirty = $('span.tabledrag-changed').size() > 0;
+ var will_modify_original = !options.noReload && !options.singleRow;
+ if( page_is_dirty && will_modify_original ) {
+ // The user will lose modifications, so popup dialog offering to save current state.
+/*
+ var body = Drupal.t("There are unsaved changes on this page, which you will lose if you continue.");
+ var buttons = {
+ 'popups_save': {title: Drupal.t('Save Changes'), func: function(){popups.save_page(a, options)}},
+ 'popups_submit': {title: Drupal.t('Continue'), func: function(){Drupal.popups.close(); popups.open_path(a, options)}},
+ 'popups_cancel': {title: Drupal.t('Cancel'), func: Drupal.popups.close}
+ };
+ return popups.open( Drupal.t('Warning: Please Confirm'), body, buttons );
+*/
+ $.getJSON(Drupal.settings.basePath + 'popuppage/save_dialog', function(json) {
+ // Attach behaviors to the buttons in the save-if-modified dialog.
+ var buttons = {
+ 'popups_save': {title: json.buttons.save, func: function(){popups.save_page(a, options)}},
+ 'popups_submit': {title: json.buttons.submit, func: function(){Drupal.popups.close(); popups.open_path(a, options)}},
+ 'popups_cancel': {title: json.buttons.cancel, func: Drupal.popups.close}
+ };
+ popups.open(json.title, json.content, buttons);
+ });
+ return false;
+// // Attach the save/continue/cancel behaviors
+// $('#popups_save').click(function(){popups.save_page(a, options)}),
+// $('#popups_submit').click(function(){Drupal.popups.close(); popups.open_path(a, options)}),
+// $('#popups_cancel').click(Drupal.popups.close);
+/*
+ var buttons = {
+ 'popups_save': {title: Drupal.settings.popups.save.buttons.save, func: function(){popups.save_page(a, options)}},
+ 'popups_submit': {title: Drupal.settings.popups.save.buttons.submit, func: function(){Drupal.popups.close(); popups.open_path(a, options)}},
+ 'popups_cancel': {title: Drupal.settings.popups.save.buttons.cancel, func: Drupal.popups.close}
+ };
+ return popups.open( Drupal.settings.popups.save.title, Drupal.settings.popups.save.message, buttons );
+*/
+ }
+ else {
+ return popups.open_path(a, options);
+ }
+ });
+ $(this).addClass('popups-processed');
+ });
+};
+
+/**
+ * Use Ajax to open the link in a popup window.
+ *
+ * @param a - link that was clicked.
+ * @param options - options associated with the link.
+ */
+Drupal.popups.prototype.open_path = function( a, options ) {
+ var popup = this;
+ // let the user know something is happening
+ $('body').css("cursor", "wait");
+ var $overlay = Drupal.popups.add_overlay();
+ Drupal.popups.add_loading();
+
+ // Set custom headers for all following requests.
+ $.ajaxSetup({
+ dataType: 'json',
+ beforeSend: function(xhr) {
+// xhr.setRequestHeader('Accept', 'application/json'); // this might be a good idea?
+ xhr.setRequestHeader("X-Drupal-Render-Mode", 'json/popup');
+ }
+ });
+
+ $.getJSON(a.href, function(json) {
+ popup.open_content(json.title, json.messages + json.content, options, a);
+ $('body').css("cursor", "auto"); // Return the cursor to normal state.
+ });
+
+ return false;
+};
+
+
+Drupal.popups.prototype.open_content = function(title, content, options, a) {
+ this.open(title, content);
+ // Add behaviors to content in popup.
+ // TODO: d-n-d: need to click to let go of selection.
+ Drupal.attachBehaviors($('#popups-body'));
+ // Adding collapse moves focus.
+ this.refocus();
+
+ // If the popup contains a form, capture submits.
+ var $form = $('form', '#popups-body');
+ $form.ajaxForm({
+ dataType: 'json',
+ beforeSubmit: Drupal.popups.beforeSubmit,
+ success: function(response, status) { Drupal.popups.formSuccess(response, options, a) },
+ });
+}
+
+/**
+ * Do before the form in the popup is submitted.
+ *
+ */
+Drupal.popups.beforeSubmit = function(form_data, $form, options) {
+ Drupal.popups.remove_popup(); // Remove just the dialog, but not the overlay.
+ Drupal.popups.add_loading();
+};
+
+/**
+ * The form in the popup was successfully submitted
+ * Update the originating page.
+ * Show any messages in a popup (TODO - make this a configurable option).
+ *
+ * @param data - JSON object from server with status of form submission.
+ * @param options - hash of per link options.
+ * @param a - the link that was clicked.
+ */
+Drupal.popups.formSuccess = function (response, options, a) {
+ if (response.status != 'redirect') { // something went wrong
+ Drupal.popups.message( "Error: " + response.messages + response.content);
+ }
+ else { // Got a good response back from the server.
+ $.getJSON(response.path, function(data) {
+ // Are we at an end point, or just moving from one popup to another?
+ if (!location.href.match(data.path)) { // Not done yet, so show results in new popup.
+ Drupal.popups.remove_loading();
+ var popups = new Drupal.popups();
+ popups.open_content(data.title, data.messages + data.content, options, a);
+ }
+ else { // Done, so show messages in dialog and embed the results in the original page.
+ if (data.messages) {
+ Drupal.popups.message(data.messages);
+ // Also insert the message into the page above the content.
+ // Might not be the standard spot, but it is the easiest to find.
+ var $next = $(Drupal.settings.popups.defaultTargetSelector);
+ $next.parent().find('div.messages').remove(); // Remove the current messages.
+ $next.before(data.messages);
+ }
+
+ // Just update a single row out of a table (still expiremental).
+ // Loop through, with special case for first element.
+ if (options.singleRow) {
+ var href = $(a).attr('href');
+ var selector = 'table a[href=' + href + ']';
+ var $new_row = $data.find(selector).parents('tr'); // new tr
+ var $target_row = $(selector).parents('tr'); // target tr.
+ for (var i in options.singleRow) {
+ var col = options.singleRow[i];
+ $new_row.find(col).contents().not('div.indentation').wrapAll('');
+ $target_row.find(col).contents()
+ .not('a.tabledrag-handle').not('span.warning').not('div.indentation')
+ .wrapAll('');
+ $('#killme').replaceWith( $new_row.find('#newvalue').html() );
+ }
+ }
+ // Update the entire content area (defined by 'target selector').
+ else if (!options.noReload) {
+ var target = options.targetSelector;
+ if (!target) {
+ target = Drupal.settings.popups.defaultTargetSelector;
+ }
+
+ // Update the original page.
+ var $c = $(target).html(data.content); // Inject the new content into the page.
+ Drupal.attachBehaviors($c);
+ }
+
+ // Update the title of the page.
+ if (options.updateTitle) {
+ $(Drupal.settings.popups.defaultTitleSelector).html(data.title);
+ document.title = data.title; // Also update the browser page title (TODO: include site name?).
+ }
+
+ // Done with changes to the original page, remove effects.
+ Drupal.popups.remove_loading();
+ if (!data.messages) {
+ // If there is not a messages popup remove the overlay.
+ Drupal.popups.remove_overlay();
+ }
+ } // End of updating original page.
+ }); // End of good response.
+ }
+};
+
+/**
+ * Submit the page and reload the results, before popping up the real dialog.
+ *
+ * @param a - link that was clicked.
+ * @param options - options associated with the link.
+ */
+Drupal.popups.prototype.save_page = function(a, options) {
+ var popups = this;
+ // TODO - what if clicking on link with option['targetSelector']?
+ var target = Drupal.settings.popups.defaultTargetSelector;
+ var $form = $('form', target);
+ var ajaxOptions = {
+ dataType: 'json',
+ beforeSubmit: Drupal.popups.beforeSubmit,
+ success: function(response, status) { // Sync up the current page contents with the submit.
+ var $data = $(response);
+ var content = $data.find('content').text();
+ var $c = $(target).html(content); // Inject the new content into the page.
+ Drupal.attachBehaviors($c);
+ Drupal.popups.close();
+ // The form has been saved, the page reloaded, now safe to show the link in a popup.
+ popups.open_path(a, options);
+ }
+ };
+ $form.ajaxSubmit( ajaxOptions ); // Submit the form.
+};
+
Index: modules/system/popup-template.tpl.php
===================================================================
RCS file: modules/system/popup-template.tpl.php
diff -N modules/system/popup-template.tpl.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/system/popup-template.tpl.php 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,13 @@
+
+
+
+
+
%title
+
+
+
%body
+
%buttons
+
+
Index: misc/popupapi.js
===================================================================
RCS file: misc/popupapi.js
diff -N misc/popupapi.js
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ misc/popupapi.js 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,462 @@
+// $Id:$
+
+/**
+ * Popup Modal Dialog API
+ *
+ * Provide an API for building and displaying JavaScript, in-page, popup modal dialogs.
+ * Modality is provided by a fixed, semi-opaque div, positioned in front of the page contents.
+ *
+ */
+
+/**
+ * Attach the popup bevior to the all the requested links on the page.
+ *
+ * @param context
+ * The jQuery object to apply the behaviors to.
+ */
+Drupal.behaviors.popups = function(context) {
+ $body = $('body');
+ if(!$body.hasClass('popups-processed')) {
+ $(document).bind('keydown', Drupal.popups.keyHandle);
+ $body.addClass('popups-processed');
+ }
+ Drupal.popups.attach(context, 'a.popup', {});
+ Drupal.popups.attach(context, 'a.popup-form', {updatePage: true});
+ Drupal.popups.attach(context, 'a.popup-nonmodal', {nonModal: true});
+};
+
+/**
+ * Create the popups object/namespace.
+ */
+Drupal.popups = function() {};
+
+/**
+ * Attach the popup behavior to a particular link.
+ *
+ * @param selector
+ * jQuery selector for links to attach popup behavior to.
+ * @param options
+ * Hash of options associated with these links.
+ */
+Drupal.popups.attach = function(context, selector, options) {
+ $(selector, context).not('.popups-processed').each( function() {
+ $(this).click( function(e){
+ var a = this;
+ // If the option is distructive, check if the page is already modified, and offer to save.
+ var pageIsDirty = $('span.tabledrag-changed').size() > 0;
+ var willModifyOriginal = options.updatePage;
+ if( pageIsDirty && willModifyOriginal ) {
+ // The user will lose modifications, so popup dialog offering to save current state.
+ $.getJSON(Drupal.settings.basePath + 'popuppage/save_dialog', function(json) {
+ // Attach behaviors to the buttons in the save-if-modified dialog.
+ var buttons = {
+ 'popups_save': {title: json.buttons.save, func: function(){Drupal.popups.savePage(a, options)}},
+ 'popups_submit': {title: json.buttons.submit, func: function(){Drupal.popups.removePopup(); Drupal.popups.openPath(a, options)}},
+ 'popups_cancel': {title: json.buttons.cancel, func: Drupal.popups.close}
+ };
+ Drupal.popups.open(json.title, json.content, buttons);
+ });
+ return false;
+ }
+ else {
+ return Drupal.popups.openPath(a, options);
+ }
+ });
+ $(this).addClass('popups-processed');
+ });
+};
+
+
+/**
+ * Generic dialog builder.
+ */
+Drupal.popups.open = function(title, body, buttons) {
+
+ Drupal.popups.addOverlay(); // TODO - nonModal option.
+ var $popup = $(Drupal.theme('popupsDialog', title, body, buttons));
+ // Start with dialog off the side. Making it invisible causes flash in FF2.
+ $popup.css('left', -9999);
+// $overlay.before( $popup ); // Add the popup to the DOM.
+ $('body').append( $popup ); // Add the popup to the DOM.
+
+ // Adding button functions
+ if (buttons) {
+ for (var id in buttons) {
+ if (buttons[id]) { // to make jslint happy.
+ var func = buttons[id].func;
+ $('#'+id).click( func );
+ }
+ }
+ }
+ $('#popups-close').click( Drupal.popups.close );
+
+ // center on the screen, adding in offsets if the window has been scrolled
+ var popupWidth = $popup.width();
+ var windowWidth = $(window).width();
+ var left = (windowWidth / 2) - (popupWidth / 2) + Drupal.popups.scrollLeft();
+
+// var top;
+ // Get popups's height on the page.
+ // Causes flash in FF2 if popup is not visible!
+ var popupHeight = $popup.height();
+ var windowHeight = $(window).height();
+ if (popupHeight > (0.9 * windowHeight) ) { // Must fit in 90% of window.
+ popupHeight = 0.9 * windowHeight;
+ $popup.height(popupHeight);
+ }
+ var top = (windowHeight / 2) - (popupHeight / 2) + Drupal.popups.scrollTop();
+
+ $popup.css('top', top).css('left', left); // Position the popup to be visible.
+
+ this.refocus(); // TODO: capture the focus when it leaves the dialog.
+ Drupal.popups.removeLoading(); // Remove the loading img.
+
+ return false;
+};
+
+/**
+ * Simple popup that functions like the browser's alert box.
+ */
+Drupal.popups.message = function(message, body) {
+ body = body || '';
+ var buttons = {
+ 'popups_ok': { title: Drupal.t('OK'), func: Drupal.popups.close }
+ };
+ Drupal.popups.open( message, body, buttons );
+};
+
+/**
+ * Handle any special keys when popup is active.
+ */
+Drupal.popups.keyHandle = function(e) {
+ if (!e) {
+ e = window.event;
+ }
+ switch (e.keyCode) {
+ case 27: // esc
+ Drupal.popups.close();
+ return false;
+ case 191: // '?' key, show help.
+ if (e.shiftKey && e.ctrlKey) {
+// console.log("Show Help");
+ var $help = $('a.popup.more-help');
+ if ($help.size()) {
+ $help.click();
+ }
+ else {
+ Drupal.popups.message(Drupal.t("Sorry, there is no additional help for this page"));
+ }
+ }
+ default: // all other keys
+// console.log( e.keyCode );
+// return true;
+ }
+};
+
+/*****************************************************************************
+ * Appearence Functions (overlay, loading graphic, remove popup) *********
+ *****************************************************************************/
+
+Drupal.popups.removePopup = function() {
+ $('#popups').fadeOut('fast', function() {
+ $('#popups').remove();
+ });
+};
+
+Drupal.popups.addOverlay = function() {
+ var $overlay = $('#popups-overlay');
+ if (!$overlay.size()) { // Overlay does not already exist, so create it.
+ $overlay = $(Drupal.theme('popupsOverlay'));
+ $overlay.css('opacity', '0.4'); // for ie6(?)
+ $body = $('body');
+ // Doing absolute positioning, so make overlay's size equal the entire body.
+ $overlay.width($body.width()).height($body.height());
+ $overlay.click(Drupal.popups.close);
+ $body.prepend($overlay);
+ }
+// return $overlay;
+};
+
+//Drupal.popups.getOverlay = function() {
+// return $('#popups-overlay');
+//};
+
+Drupal.popups.removeOverlay = function() {
+ $('#popups-overlay').fadeOut('fast', function() {
+ $('#popups-overlay').remove();
+ });
+};
+
+Drupal.popups.addLoading = function() {
+ var $loading = $('#popups-loading');
+ if (!$loading.size()) { // Overlay does not already exist, so create it.
+ var waitImageSize = 100;
+ var left = ($(window).width() / 2) - (waitImageSize / 2) + Drupal.popups.scrollLeft();;
+ var top = ($(window).height() / 2) - (waitImageSize / 2) + Drupal.popups.scrollTop();;
+ $loading = $( Drupal.theme('popupsLoading', left, top) );
+ $('body').prepend($loading);
+ }
+};
+
+Drupal.popups.removeLoading = function() {
+ $('#popups-loading').remove();
+};
+
+/**
+ * Remove everything.
+ */
+Drupal.popups.close = function() {
+ Drupal.popups.removePopup();
+ Drupal.popups.removeLoading();
+ Drupal.popups.removeOverlay();
+};
+
+/**
+ * Set the focus on the popup to the first visible form element, or the first button, or the close link.
+ */
+Drupal.popups.refocus = function() {
+ $focus = $('#popups input:visible:eq(0)')
+ if (!focus) {
+ $focus = $('#popups-close'); // Doesn't seem to work.
+ }
+ $focus.focus()
+};
+
+/****************************************************************************
+ * Theme Functions ********************************************************
+ ****************************************************************************/
+
+Drupal.theme.prototype.popupsLoading = function(left, top) {
+ var loading = '