Index: wp-includes/js/tinymce/plugins/wplink/editor_plugin.js =================================================================== --- wp-includes/js/tinymce/plugins/wplink/editor_plugin.js (revision 0) +++ wp-includes/js/tinymce/plugins/wplink/editor_plugin.js (revision 0) @@ -0,0 +1,56 @@ +(function() { + tinymce.create('tinymce.plugins.wpLink', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); + ed.addCommand('WP_Link', function() { + ed.windowManager.open({ + file : tinymce.baseURL + '/wp-mce-link.php', + width : 320, + height : 260, + inline : 1 + }, { + plugin_url : url // Plugin absolute URL + }); + }); + + // Register example button + ed.addButton('wplink', { + title : ed.getLang('wplink.link_desc'), + cmd : 'WP_Link' + }); + + ed.addShortcut('alt+shift+a', ed.getLang('wplink.link_desc'), 'WP_Link'); + + // Add a node change handler, selects the button in the UI when a link is selected + ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('wplink', n.nodeName == 'A'); + }); + }, + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'WordPress Link Dialog', + author : 'WordPress', + authorurl : 'http://wordpress.org', + infourl : '', + version : "1.0" + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('wplink', tinymce.plugins.wpLink); +})(); \ No newline at end of file Index: wp-includes/js/tinymce/plugins/wplink/editor_plugin.dev.js =================================================================== Index: wp-includes/js/tinymce/plugins/wplink/js/wplink.js =================================================================== --- wp-includes/js/tinymce/plugins/wplink/js/wplink.js (revision 0) +++ wp-includes/js/tinymce/plugins/wplink/js/wplink.js (revision 0) @@ -0,0 +1,189 @@ +(function($){ + var inputs = {}, panels, active, ed, + wpLink = { + init : function() { + var e, etarget, eclass; + // Init shared vars + ed = tinyMCEPopup.editor; + // Secondary options + inputs.title = $('#link-title-field'); + // Advanced Options + inputs.advancedOptions = $('#link-advanced-options'); + inputs.target = $('#link-target-select'); + inputs['class'] = $('#link-class-select'); + // Types + inputs.typeDropdown = $('#link-type'); + inputs.typeOptions = inputs.typeDropdown.find('option'); + + panels = $('.link-panel'); + active = $('.link-panel-active'); + + // Build lists + wpLink.fillClassList('link-class-select'); + wpLink.fillTargetList('link-target-select'); + + // Extract type names + inputs.typeOptions.each( function(){ + $(this).data( 'link-type', this.id.replace('link-option-id-','') ); + }); + panels.each( function(){ + $(this).data( 'link-type', this.id.replace('link-panel-id-','') ); + }); + + // Bind event handlers + inputs.typeDropdown.change( wpLink.selectPanel ); + $('#wp-update').click( wpLink.update ); + $('#wp-cancel').click( function() { tinyMCEPopup.close(); } ); + $('#link-advanced-options-toggle').click( wpLink.toggleAdvancedOptions ); + + // If link exists, select proper values. + e = ed.dom.getParent(ed.selection.getNode(), 'A'); + if ( ! e ) + return; + + // @TODO: select proper panel/fill values when a link is edited + active.find('input.url-field').val( e.href ); + inputs.title.val( ed.dom.getAttrib(e, 'title') ); + // Advanced Options + inputs.target.val( etarget = ed.dom.getAttrib(e, 'target') ); + inputs['class'].val( eclass = ed.dom.getAttrib(e, 'class') ); + if ( etarget || eclass ) // Open the adv. options if one is set. + inputs.advancedOptions.toggleClass('adv-options-active'); + }, + + update : function() { + var ed = tinyMCEPopup.editor, + attrs = { + href : active.find('input.url-field').val(), + title : inputs.title.val(), + target : inputs.target.val(), + 'class' : inputs['class'].val() + }, defaultContent, e, b; + + if ( active.hasClass('link-panel-custom') ) + defaultContent = attrs.href; + else // @TODO: Update to use the title + defaultContent = attrs.href; + + tinyMCEPopup.restoreSelection(); + e = ed.dom.getParent(ed.selection.getNode(), 'A'); + + // If the values are empty... + if ( ! attrs.href ) { + // ...and nothing is selected, we should return + if ( ed.selection.isCollapsed() ) { + tinyMCEPopup.close(); + return; + // ...and a link exists, we should unlink and return + } else if ( e ) { + tinyMCEPopup.execCommand("mceBeginUndoLevel"); + b = ed.selection.getBookmark(); + ed.dom.remove(e, 1); + ed.selection.moveToBookmark(b); + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + return; + } + } + + tinyMCEPopup.execCommand("mceBeginUndoLevel"); + + if (e == null) { + ed.getDoc().execCommand("unlink", false, null); + + // If no selection exists, create a new link from scratch. + if ( ed.selection.isCollapsed() ) { + var el = ed.dom.create('a', { href: "#mce_temp_url#" }, defaultContent); + ed.selection.setNode(el); + // If a selection exists, wrap it in a link. + } else { + tinyMCEPopup.execCommand("CreateLink", false, "#mce_temp_url#", {skip_undo : 1}); + } + + tinymce.each(ed.dom.select("a"), function(n) { + if (ed.dom.getAttrib(n, 'href') == '#mce_temp_url#') { + e = n; + ed.dom.setAttribs(e, attrs); + } + }); + } else { + ed.dom.setAttribs(e, attrs); + } + + // Don't move caret if selection was image + if (e.childNodes.length != 1 || e.firstChild.nodeName != 'IMG') { + ed.focus(); + ed.selection.select(e); + ed.selection.collapse(0); + tinyMCEPopup.storeSelection(); + } + + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + }, + + selectPanel : function( option ) { + var sel = inputs.typeOptions.filter(':selected'); + + if ( option.jquery ) { + sel.removeAttr('selected'); + sel = option.attr('selected', 'selected'); + } + + active.removeClass('link-panel-active'); + active = $('#link-panel-id-' + sel.data('link-type') ).addClass('link-panel-active'); + }, + + toggleAdvancedOptions : function() { + inputs.advancedOptions.toggleClass('adv-options-active'); + return false; + }, + + /** + * Taken from themes/advanced/js/link.js + */ + fillClassList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + if (v = tinyMCEPopup.getParam('theme_advanced_styles')) { + cl = []; + + tinymce.each(v.split(';'), function(v) { + var p = v.split('='); + + cl.push({'title' : p[0], 'class' : p[1]}); + }); + } else + cl = tinyMCEPopup.editor.dom.getClasses(); + + if (cl.length > 0) { + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + + tinymce.each(cl, function(o) { + lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + /** + * Taken from themes/advanced/js/link.js + */ + fillTargetList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v; + + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_same'), '_self'); + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_blank'), '_blank'); + + if (v = tinyMCEPopup.getParam('theme_advanced_link_targets')) { + tinymce.each(v.split(','), function(v) { + v = v.split('='); + lst.options[lst.options.length] = new Option(v[0], v[1]); + }); + } + } + } + + $(document).ready( wpLink.init ); +})(jQuery); \ No newline at end of file Index: wp-includes/js/tinymce/langs/wp-langs-en.js =================================================================== --- wp-includes/js/tinymce/langs/wp-langs-en.js (revision 15721) +++ wp-includes/js/tinymce/langs/wp-langs-en.js (working copy) @@ -429,3 +429,8 @@ caption:"Edit Image Caption", alt:"Edit Alternate Text" }); + +tinyMCE.addI18n("en.wplink",{ +link_desc:"Insert/edit link", +unlink_desc:"Unlink (Alt+Shift+S)" +}); Index: wp-includes/js/tinymce/langs/wp-langs.php =================================================================== --- wp-includes/js/tinymce/langs/wp-langs.php (revision 15721) +++ wp-includes/js/tinymce/langs/wp-langs.php (working copy) @@ -452,4 +452,9 @@ caption:"' . mce_escape( __('Edit Image Caption') ) . '", alt:"' . mce_escape( __('Edit Alternate Text') ) . '" }); + +tinyMCE.addI18n("' . $language . '.wplink",{ +link_desc:"' . mce_escape( __('Insert/edit link') ) . '", +unlink_desc:"' . mce_escape( __('Unlink') ) . ' (Alt+Shift+S)" +}); '; Index: wp-includes/js/tinymce/themes/advanced/skins/wp_theme/ui.css =================================================================== --- wp-includes/js/tinymce/themes/advanced/skins/wp_theme/ui.css (revision 15721) +++ wp-includes/js/tinymce/themes/advanced/skins/wp_theme/ui.css (working copy) @@ -274,7 +274,8 @@ .wp_themeSkin span.mce_anchor {background-position:-200px 0} .wp_themeSkin span.mce_indent {background-position:-400px 0} .wp_themeSkin span.mce_outdent {background-position:-540px 0} -.wp_themeSkin span.mce_link {background-position:-500px 0} +.wp_themeSkin span.mce_link, +.wp_themeSkin span.mce_wplink {background-position:-500px 0} .wp_themeSkin span.mce_unlink {background-position:-640px 0} .wp_themeSkin span.mce_sub {background-position:-600px 0} .wp_themeSkin span.mce_sup {background-position:-620px 0} Index: wp-includes/js/tinymce/wp-mce-link.php =================================================================== --- wp-includes/js/tinymce/wp-mce-link.php (revision 0) +++ wp-includes/js/tinymce/wp-mce-link.php (revision 0) @@ -0,0 +1,186 @@ + true ), 'objects' ); +$taxes = get_taxonomies( array( 'show_ui' => true ), 'objects' ); + +// Helper functions +function wp_link_panel_custom() { ?> +