extlink.js 6.5 KB

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