extlink.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. (function ($) {
  2. Drupal.extlink = Drupal.extlink || {};
  3. Drupal.extlink.attach = function (context, settings) {
  4. if (!settings.hasOwnProperty('extlink')) {
  5. return;
  6. }
  7. // Strip the host name down, removing ports, subdomains, or www.
  8. var pattern = /^(([^\/:]+?\.)*)([^\.:]{4,})((\.[a-z]{1,4})*)(:[0-9]{1,5})?$/;
  9. var host = window.location.host.replace(pattern, '$3$4');
  10. var subdomain = window.location.host.replace(pattern, '$1');
  11. // Determine what subdomains are considered internal.
  12. var subdomains;
  13. if (settings.extlink.extSubdomains) {
  14. subdomains = "([^/]*\\.)?";
  15. }
  16. else if (subdomain == 'www.' || subdomain == '') {
  17. subdomains = "(www\\.)?";
  18. }
  19. else {
  20. subdomains = subdomain.replace(".", "\\.");
  21. }
  22. // Build regular expressions that define an internal link.
  23. var internal_link = new RegExp("^https?://" + subdomains + host, "i");
  24. // Extra internal link matching.
  25. var extInclude = false;
  26. if (settings.extlink.extInclude) {
  27. extInclude = new RegExp(settings.extlink.extInclude.replace(/\\/, '\\'), "i");
  28. }
  29. // Extra external link matching.
  30. var extExclude = false;
  31. if (settings.extlink.extExclude) {
  32. extExclude = new RegExp(settings.extlink.extExclude.replace(/\\/, '\\'), "i");
  33. }
  34. // Extra external link CSS selector exclusion.
  35. var extCssExclude = false;
  36. if (settings.extlink.extCssExclude) {
  37. extCssExclude = settings.extlink.extCssExclude;
  38. }
  39. // Extra external link CSS selector explicit.
  40. var extCssExplicit = false;
  41. if (settings.extlink.extCssExplicit) {
  42. extCssExplicit = settings.extlink.extCssExplicit;
  43. }
  44. // Find all links which are NOT internal and begin with http as opposed
  45. // to ftp://, javascript:, etc. other kinds of links.
  46. // When operating on the 'this' variable, the host has been appended to
  47. // all links by the browser, even local ones.
  48. // In jQuery 1.1 and higher, we'd use a filter method here, but it is not
  49. // available in jQuery 1.0 (Drupal 5 default).
  50. var external_links = new Array();
  51. var mailto_links = new Array();
  52. $("a:not(." + settings.extlink.extClass + ", ." + settings.extlink.mailtoClass + "), area:not(." + settings.extlink.extClass + ", ." + settings.extlink.mailtoClass + ")", context).each(function(el) {
  53. try {
  54. var url = this.href.toLowerCase();
  55. if (url.indexOf('http') == 0
  56. && ((!url.match(internal_link) && !(extExclude && url.match(extExclude))) || (extInclude && url.match(extInclude)))
  57. && !(extCssExclude && $(this).parents(extCssExclude).length > 0)
  58. && !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
  59. external_links.push(this);
  60. }
  61. // Do not include area tags with begin with mailto: (this prohibits
  62. // icons from being added to image-maps).
  63. else if (this.tagName != 'AREA'
  64. && url.indexOf('mailto:') == 0
  65. && !(extCssExclude && $(this).parents(extCssExclude).length > 0)
  66. && !(extCssExplicit && $(this).parents(extCssExplicit).length < 1)) {
  67. mailto_links.push(this);
  68. }
  69. }
  70. // IE7 throws errors often when dealing with irregular links, such as:
  71. // <a href="node/10"></a> Empty tags.
  72. // <a href="http://user:pass@example.com">example</a> User:pass syntax.
  73. catch (error) {
  74. return false;
  75. }
  76. });
  77. if (settings.extlink.extClass) {
  78. Drupal.extlink.applyClassAndSpan(external_links, settings.extlink.extClass);
  79. }
  80. if (settings.extlink.mailtoClass) {
  81. Drupal.extlink.applyClassAndSpan(mailto_links, settings.extlink.mailtoClass);
  82. }
  83. if (settings.extlink.extTarget) {
  84. // Apply the target attribute to all links.
  85. $(external_links).attr('target', settings.extlink.extTarget);
  86. }
  87. Drupal.extlink = Drupal.extlink || {};
  88. // Set up default click function for the external links popup. This should be
  89. // overridden by modules wanting to alter the popup.
  90. Drupal.extlink.popupClickHandler = Drupal.extlink.popupClickHandler || function() {
  91. if (settings.extlink.extAlert) {
  92. return confirm(settings.extlink.extAlertText);
  93. }
  94. }
  95. $(external_links).click(function(e) {
  96. return Drupal.extlink.popupClickHandler(e);
  97. });
  98. };
  99. /**
  100. * Apply a class and a trailing <span> to all links not containing images.
  101. *
  102. * @param links
  103. * An array of DOM elements representing the links.
  104. * @param class_name
  105. * The class to apply to the links.
  106. */
  107. Drupal.extlink.applyClassAndSpan = function (links, class_name) {
  108. var $links_to_process;
  109. if (Drupal.settings.extlink.extImgClass){
  110. $links_to_process = $(links);
  111. }
  112. else {
  113. var links_with_images = $(links).find('img').parents('a');
  114. $links_to_process = $(links).not(links_with_images);
  115. }
  116. $links_to_process.addClass(class_name);
  117. var i;
  118. var length = $links_to_process.length;
  119. for (i = 0; i < length; i++) {
  120. var $link = $($links_to_process[i]);
  121. if ($link.css('display') == 'inline' || $link.css('display') == 'inline-block') {
  122. if (class_name == Drupal.settings.extlink.mailtoClass) {
  123. $link.append('<span class="' + class_name + '"><span class="element-invisible"> ' + Drupal.settings.extlink.mailtoLabel + '</span></span>');
  124. }
  125. else {
  126. $link.append('<span class="' + class_name + '"><span class="element-invisible"> ' + Drupal.settings.extlink.extLabel + '</span></span>');
  127. }
  128. }
  129. }
  130. };
  131. Drupal.behaviors.extlink = Drupal.behaviors.extlink || {};
  132. Drupal.behaviors.extlink.attach = function (context, settings) {
  133. // Backwards compatibility, for the benefit of modules overriding extlink
  134. // functionality by defining an "extlinkAttach" global function.
  135. if (typeof extlinkAttach === 'function') {
  136. extlinkAttach(context);
  137. }
  138. else {
  139. Drupal.extlink.attach(context, settings);
  140. }
  141. };
  142. })(jQuery);