Issue #1974580 by nod_, Wim Leers: Introduce domReady to remove jQuery dependency from drupal.js and clean it up.

8.0.x
Alex Pott 2013-05-13 13:49:00 +01:00
parent 1f39cc4b01
commit 235142af27
6 changed files with 89 additions and 124 deletions

View File

@ -12,6 +12,7 @@
"predef" : [
"Drupal",
"drupalSettings",
"domready",
"jQuery",
"_",
"matchMedia",

View File

@ -79,6 +79,50 @@ Drupal.behaviors.AJAX = {
}
};
/**
* Extends Error to provide handling for Errors in AJAX
*/
Drupal.AjaxError = function(xmlhttp, uri) {
var statusCode, statusText, pathText, responseText, readyStateText, message;
if (xmlhttp.status) {
statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status});
}
else {
statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally.");
}
statusCode += "\n" + Drupal.t("Debugging information follows.");
pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri} );
statusText = '';
// In some cases, when statusCode === 0, xmlhttp.statusText may not be defined.
// Unfortunately, testing for it with typeof, etc, doesn't seem to catch that
// and the test causes an exception. So we need to catch the exception here.
try {
statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)});
}
catch (e) {}
responseText = '';
// Again, we don't have a way to know for sure whether accessing
// xmlhttp.responseText is going to throw an exception. So we'll catch it.
try {
responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) } );
} catch (e) {}
// Make the responseText more readable by stripping HTML tags and newlines.
responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi,"");
responseText = responseText.replace(/[\n]+\s+/g,"\n");
// We don't need readyState except for status == 0.
readyStateText = xmlhttp.status === 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
this.message = statusCode + pathText + statusText + responseText + readyStateText;
this.name = 'AjaxError';
};
Drupal.AjaxError.prototype = new Error();
Drupal.AjaxError.prototype.constructor = Drupal.AjaxError;
/**
* Ajax object.
*
@ -435,8 +479,6 @@ Drupal.ajax.prototype.success = function (response, status) {
}
$(this.element).removeClass('progress-disabled').prop('disabled', false);
Drupal.freezeHeight();
for (var i in response) {
if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) {
this.commands[response[i].command](this, response[i], status);
@ -452,8 +494,6 @@ Drupal.ajax.prototype.success = function (response, status) {
Drupal.attachBehaviors(this.form, settings);
}
Drupal.unfreezeHeight();
// Remove any response-specific settings so they don't get used on the next
// call by mistake.
this.settings = null;

4
core/misc/domready/ready.min.js vendored Normal file
View File

@ -0,0 +1,4 @@
/*!
* domready (c) Dustin Diaz 2012 - License MIT
*/
!function(a,ctx,b){typeof module!="undefined"?module.exports=b():typeof define=="function"&&typeof define.amd=="object"?define(b):ctx[a]=b()}("domready",this,function(a){function m(a){l=1;while(a=b.shift())a()}var b=[],c,d=!1,e=document,f=e.documentElement,g=f.doScroll,h="DOMContentLoaded",i="addEventListener",j="onreadystatechange",k="readyState",l=/^loade|c/.test(e[k]);return e[i]&&e[i](h,c=function(){e.removeEventListener(h,c,d),m()},d),g&&e.attachEvent(j,c=function(){/^c/.test(e[k])&&(e.detachEvent(j,c),m())}),a=g?function(c){self!=top?l?c():b.push(c):function(){try{f.doScroll("left")}catch(b){return setTimeout(function(){a(c)},50)}c()}()}:function(a){l?a():b.push(a)}})

View File

@ -1,11 +1,16 @@
var Drupal = Drupal || { 'behaviors': {}, 'locale': {} };
var Drupal = { behaviors: {}, locale: {} };
// Class indicating that JS is enabled; used for styling purpose.
document.documentElement.className += ' js';
// Allow other JavaScript libraries to use $.
jQuery.noConflict();
if (window.jQuery) {
jQuery.noConflict();
}
// JavaScript should be made compatible with libraries other than jQuery by
// wrapping it in an anonymous closure.
(function ($, Drupal, drupalSettings) {
(function (domready, Drupal, drupalSettings) {
"use strict";
@ -94,6 +99,9 @@ Drupal.attachBehaviors = function (context, settings) {
}
};
// Attach all behaviors.
domready(function () { Drupal.attachBehaviors(document, drupalSettings); });
/**
* Detach registered behaviors from a page element.
*
@ -313,6 +321,15 @@ Drupal.formatPlural = function (count, singular, plural, args, options) {
}
};
/**
* Encodes a Drupal path for use in a URL.
*
* For aesthetic reasons slashes are not escaped.
*/
Drupal.encodePath = function (item) {
return window.encodeURIComponent(item).replace(/%2F/g, '/');
};
/**
* Generate the themed representation of a Drupal object.
*
@ -341,125 +358,18 @@ Drupal.theme = function (func) {
};
/**
* Freeze the current body height (as minimum height). Used to prevent
* unnecessary upwards scrolling when doing DOM manipulations.
*/
Drupal.freezeHeight = function () {
Drupal.unfreezeHeight();
$('<div id="freeze-height"></div>').css({
position: 'absolute',
top: '0px',
left: '0px',
width: '1px',
height: $('body').css('height')
}).appendTo('body');
};
/**
* Unfreeze the body height.
*/
Drupal.unfreezeHeight = function () {
$('#freeze-height').remove();
};
/**
* Encodes a Drupal path for use in a URL.
* Formats text for emphasized display in a placeholder inside a sentence.
*
* For aesthetic reasons slashes are not escaped.
* @param str
* The text to format (plain-text).
* @return
* The formatted text (html).
*/
Drupal.encodePath = function (item) {
return window.encodeURIComponent(item).replace(/%2F/g, '/');
};
/**
* Get the text selection in a textarea.
*/
Drupal.getSelection = function (element) {
var range1, range2, start, end;
if (typeof element.selectionStart !== 'number' && document.selection) {
// The current selection.
range1 = document.selection.createRange();
range2 = range1.duplicate();
// Select all text.
range2.moveToElementText(element);
// Now move 'dummy' end point to end point of original range.
range2.setEndPoint('EndToEnd', range1);
// Now we can calculate start and end points.
start = range2.text.length - range1.text.length;
end = start + range1.text.length;
return { 'start': start, 'end': end };
}
return { 'start': element.selectionStart, 'end': element.selectionEnd };
};
/**
* Extends Error to provide handling for Errors in AJAX
*/
Drupal.AjaxError = function(xmlhttp, uri) {
var statusCode, statusText, pathText, responseText, readyStateText, message;
if (xmlhttp.status) {
statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status});
}
else {
statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally.");
}
statusCode += "\n" + Drupal.t("Debugging information follows.");
pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri} );
statusText = '';
// In some cases, when statusCode === 0, xmlhttp.statusText may not be defined.
// Unfortunately, testing for it with typeof, etc, doesn't seem to catch that
// and the test causes an exception. So we need to catch the exception here.
try {
statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)});
}
catch (e) {}
responseText = '';
// Again, we don't have a way to know for sure whether accessing
// xmlhttp.responseText is going to throw an exception. So we'll catch it.
try {
responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) } );
} catch (e) {}
// Make the responseText more readable by stripping HTML tags and newlines.
responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi,"");
responseText = responseText.replace(/[\n]+\s+/g,"\n");
// We don't need readyState except for status == 0.
readyStateText = xmlhttp.status === 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
this.message = statusCode + pathText + statusText + responseText + readyStateText;
this.name = 'AjaxError';
Drupal.theme.placeholder = function (str) {
return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>';
};
Drupal.AjaxError.prototype = new Error();
Drupal.AjaxError.prototype.constructor = Drupal.AjaxError;
// Class indicating that JS is enabled; used for styling purpose.
$('html').addClass('js');
//Attach all behaviors.
$(function () {
Drupal.attachBehaviors(document, drupalSettings);
});
/**
* The default themes.
*/
$.extend(Drupal.theme, {
/**
* Formats text for emphasized display in a placeholder inside a sentence.
*
* @param str
* The text to format (plain-text).
* @return
* The formatted text (html).
*/
placeholder: function (str) {
return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>';
}
});
})(jQuery, Drupal, window.drupalSettings);
})(domready, Drupal, window.drupalSettings);

View File

@ -219,7 +219,7 @@ class JavaScriptTest extends WebTestBase {
* Tests adding inline scripts.
*/
function testAddInline() {
drupal_add_library('system', 'drupal');
drupal_add_library('system', 'jquery');
$inline = 'jQuery(function () { });';
$javascript = drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer'));
$this->assertTrue(array_key_exists('core/misc/jquery.js', $javascript), 'jQuery is added when inline scripts are added.');

View File

@ -1222,7 +1222,7 @@ function system_library_info() {
'core/misc/drupal.js' => array('group' => JS_LIBRARY, 'weight' => -18),
),
'dependencies' => array(
array('system', 'jquery'),
array('system', 'domready'),
),
);
@ -1461,6 +1461,16 @@ function system_library_info() {
),
);
// domReady.
$libraries['domready'] = array(
'title' => 'domReady',
'website' => 'https://github.com/ded/domready',
'version' => 'master',
'js' => array(
'core/misc/domready/ready.min.js' => array('group' => JS_LIBRARY, 'weight' => -21),
),
);
// jQuery.
$libraries['jquery'] = array(
'title' => 'jQuery',