/** * @file * JavaScript to activate "Insert" buttons on file and image fields. */ (function ($) { /** * Behavior to add "Insert" buttons. */ Drupal.behaviors.insert = {}; Drupal.behaviors.insert.attach = function(context) { if (typeof(insertTextarea) == 'undefined') { insertTextarea = $('#edit-body textarea.text-full').get(0) || false; } // Keep track of the last active textarea (if not using WYSIWYG). $('textarea:not([name$="[data][title]"]):not(.insert-processed)', context).addClass('insert-processed').focus(insertSetActive).blur(insertRemoveActive); // Add the click handler to the insert button. $('.insert-button:not(.insert-processed)', context).addClass('insert-processed').click(insert); function insertSetActive() { insertTextarea = this; this.insertHasFocus = true; } function insertRemoveActive() { if (insertTextarea == this) { var thisTextarea = this; setTimeout(function() { thisTextarea.insertHasFocus = false; }, 1000); } } function insert() { var widgetType = $(this).attr('rel'); var settings = Drupal.settings.insert.widgets[widgetType]; var wrapper = $(this).parents(settings.wrapper).filter(':first').get(0); var style = $('.insert-style', wrapper).val(); var content = $('input.insert-template[name$="[' + style + ']"]', wrapper).val(); var filename = $('input.insert-filename', wrapper).val(); var options = { widgetType: widgetType, filename: filename, style: style, fields: {} }; // Update replacements. for (var fieldName in settings.fields) { var fieldValue = $(settings.fields[fieldName], wrapper).val(); if (fieldValue) { fieldValue = fieldValue .replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } options['fields'][fieldName] = fieldValue; if (fieldValue) { var fieldRegExp = new RegExp('__' + fieldName + '(_or_filename)?__', 'g'); content = content.replace(fieldRegExp, fieldValue); } else { var fieldRegExp = new RegExp('__' + fieldName + '_or_filename__', 'g'); content = content.replace(fieldRegExp, filename); } } // File name replacement. var fieldRegExp = new RegExp('__filename__', 'g'); content = content.replace(fieldRegExp, filename); // Check for a maximum dimension and scale down the width if necessary. // This is intended for use with Image Resize Filter. var widthMatches = content.match(/width[ ]*=[ ]*"(\d*)"/i); var heightMatches = content.match(/height[ ]*=[ ]*"(\d*)"/i); if (settings.maxWidth && widthMatches && parseInt(widthMatches[1]) > settings.maxWidth) { var insertRatio = settings.maxWidth / widthMatches[1]; var width = settings.maxWidth; content = content.replace(/width[ ]*=[ ]*"?(\d*)"?/i, 'width="' + width + '"'); if (heightMatches) { var height = Math.round(heightMatches[1] * insertRatio); content = content.replace(/height[ ]*=[ ]*"?(\d*)"?/i, 'height="' + height + '"'); } } // Allow other modules to perform replacements. options['content'] = content; $.event.trigger('insertIntoActiveEditor', [options]); content = options['content']; // Cleanup unused replacements. content = content.replace(/"__([a-z0-9_]+)__"/g, '""'); // Cleanup empty attributes (other than alt). content = content.replace(/([a-z]+)[ ]*=[ ]*""/g, function(match, tagName) { return (tagName === 'alt') ? match : ''; }); // Insert the text. Drupal.insert.insertIntoActiveEditor(content); } }; // General Insert API functions. Drupal.insert = { /** * Insert content into the current (or last active) editor on the page. This * should work with most WYSIWYGs as well as plain textareas. * * @param content */ insertIntoActiveEditor: function(content) { var editorElement; // Always work in normal text areas that currently have focus. if (insertTextarea && insertTextarea.insertHasFocus) { editorElement = insertTextarea; Drupal.insert.insertAtCursor(insertTextarea, content); } // Direct tinyMCE support. else if (typeof(tinyMCE) != 'undefined' && tinyMCE.activeEditor) { editorElement = document.getElementById(tinyMCE.activeEditor.editorId); Drupal.insert.activateTabPane(editorElement); tinyMCE.activeEditor.execCommand('mceInsertContent', false, content); } // WYSIWYG support, should work in all editors if available. else if (Drupal.wysiwyg && Drupal.wysiwyg.activeId) { editorElement = document.getElementById(Drupal.wysiwyg.activeId); Drupal.insert.activateTabPane(editorElement); Drupal.wysiwyg.instances[Drupal.wysiwyg.activeId].insert(content) } // FCKeditor module support. else if (typeof(FCKeditorAPI) != 'undefined' && typeof(fckActiveId) != 'undefined') { editorElement = document.getElementById(fckActiveId); Drupal.insert.activateTabPane(editorElement); FCKeditorAPI.Instances[fckActiveId].InsertHtml(content); } // Direct FCKeditor support (only body field supported). else if (typeof(FCKeditorAPI) != 'undefined') { // Try inserting into the body. if (FCKeditorAPI.Instances[insertTextarea.id]) { editorElement = insertTextarea; Drupal.insert.activateTabPane(editorElement); FCKeditorAPI.Instances[insertTextarea.id].InsertHtml(content); } // Try inserting into the first instance we find (may occur with very // old versions of FCKeditor). else { for (var n in FCKeditorAPI.Instances) { editorElement = document.getElementById(n); Drupal.insert.activateTabPane(editorElement); FCKeditorAPI.Instances[n].InsertHtml(content); break; } } } // CKeditor module support. else if (typeof(CKEDITOR) != 'undefined' && typeof(Drupal.ckeditorActiveId) != 'undefined') { editorElement = document.getElementById(Drupal.ckeditorActiveId); Drupal.insert.activateTabPane(editorElement); CKEDITOR.instances[Drupal.ckeditorActiveId].insertHtml(content); } // Direct CKeditor support (only body field supported). else if (typeof(CKEDITOR) != 'undefined' && CKEDITOR.instances[insertTextarea.id]) { editorElement = insertTextarea; Drupal.insert.activateTabPane(editorElement); CKEDITOR.instances[insertTextarea.id].insertHtml(content); } else if (insertTextarea) { editorElement = insertTextarea; Drupal.insert.activateTabPane(editorElement); Drupal.insert.insertAtCursor(insertTextarea, content); } if (editorElement) { Drupal.insert.contentWarning(editorElement, content); } return false; }, /** * Check for vertical tabs and activate the pane containing the editor. * * @param editor * The DOM object of the editor that will be checked. */ activateTabPane: function(editor) { var $pane = $(editor).parents('.vertical-tabs-pane:first'); var $panes = $pane.parent('.vertical-tabs-panes'); var $tabs = $panes.parents('.vertical-tabs:first').find('ul.vertical-tabs-list:first li a'); if ($pane.size() && $pane.is(':hidden') && $panes.size() && $tabs.size()) { var index = $panes.children().index($pane); $tabs.eq(index).click(); } }, /** * Warn users when attempting to insert an image into an unsupported field. * * This function is only a 90% use-case, as it doesn't support when the filter * tip are hidden, themed, or when only one format is available. However it * should fail silently in these situations. */ contentWarning: function(editorElement, content) { if (!content.match(//)) { alert(Drupal.t("The selected text format will not allow it to display images. The text format will need to be changed for this image to display properly when saved.")); } }); }, /** * Insert content into a textarea at the current cursor position. * * @param editor * The DOM object of the textarea that will receive the text. * @param content * The string to be inserted. */ insertAtCursor: function(editor, content) { // Record the current scroll position. var scroll = editor.scrollTop; // IE support. if (document.selection) { editor.focus(); sel = document.selection.createRange(); sel.text = content; } // Mozilla/Firefox/Netscape 7+ support. else if (editor.selectionStart || editor.selectionStart == '0') { var startPos = editor.selectionStart; var endPos = editor.selectionEnd; editor.value = editor.value.substring(0, startPos) + content + editor.value.substring(endPos, editor.value.length); } // Fallback, just add to the end of the content. else { editor.value += content; } // Ensure the textarea does not unexpectedly scroll. editor.scrollTop = scroll; } }; })(jQuery);