2010-03-22 25 views
6

Estoy intentando agregar un atributo cuando uso un editor wysiwyg que usa el comando "createLink". Pensé que sería trivial recuperar el nodo que se creó después de que la búsqueda ejecute ese comando.Recuperar el nodo principal de la selección (rango) en Gecko y Webkit

Resulta que solo puedo capturar este nodo recién creado en IE. ¿Algunas ideas?

El código siguiente muestra el problema (los registros de depuración en la parte inferior muestran salida diferente en cada navegador):

var getSelectedHTML = function() { 
    if ($.browser.msie) { 
     return this.getRange().htmlText; 
    } else { 
     var elem = this.getRange().cloneContents(); 
     return $("<p/>").append($(elem)).html(); 
    } 
}; 

var getSelection = function() { 
    if ($.browser.msie) { 
     return this.editor.selection; 
    } else { 
     return this.iframe[0].contentDocument.defaultView.getSelection(); 
    } 
}; 

var getRange = function() { 
    var s = this.getSelection(); 
    return (s.getRangeAt) ? s.getRangeAt(0) : s.createRange(); 
}; 

var getSelectedNode = function() { 
    var range = this.getRange(); 
    var parent = range.commonAncestorContainer ? range.commonAncestorContainer : 
        range.parentElement ? range.parentElement(): 
        range.item(0); 
    return parent; 
}; 


// **** INSIDE SOME EVENT HANDLER **** 

if ($.browser.msie) { 
    this.ec("createLink", true); 
} else { 
    this.ec("createLink", false, prompt("Link URL:", "http://")); 
} 

var linkNode = $(this.getSelectedNode()); 
linkNode.attr("rel", "external"); 

$.log(linkNode.get(0).tagName); 
    // Gecko: "body" 
    // IE: "a" 
    // Webkit: "undefined" 

$.log(this.getSelectedHTML()); 
    // Gecko: "<a href="http://site.com">foo</a>" 
    // IE: "<A href="http://site.com" rel=external>foo</A>" 
    // Webkit: "foo" 

$.log(this.getSelection()); 
    // Gecko: "foo" 
    // IE: [object Selection] 
    // Webkit: "foo" 

Gracias por cualquier ayuda en esto, he rastreado preguntas relacionadas sobre SO sin éxito!

+0

@ Jason - ¿Hay algo malo con mi respuesta? Todavía no he recibido ningún comentario tuyo ... – gnarf

+0

Lo siento, tu ejemplo funciona, y el código es casi el mismo que el que tengo más compacto. Sin embargo, todavía no funciona para mi implementación, me pregunto si podría tener algo que ver con el iframe o el editor del navegador interfiriendo. Actualizaré cuando lo tenga completamente funcionando. ¡Gracias por la ayuda! – Jason

Respuesta

0

Es una solución hacky, pero debería funcionar a menos que alguien haga dos enlaces idénticos.

this.getSelection() parece conseguir los mismos tanto en el navegador sea necesario sin que:

var link=prompt('gimme link'); 

//add the thing 

var text=this.getSelection(); 

var whatYouNeed=$('a:contains("'+text+'")[href="'+link+'"'); 
13

Este es el código que he usado para obtener el "parentNode" del cursor de texto:

var getSelectedNode = function() { 
    var node,selection; 
    if (window.getSelection) { 
     selection = getSelection(); 
     node = selection.anchorNode; 
    } 
    if (!node && document.selection) { 
     selection = document.selection 
     var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange(); 
     node = range.commonAncestorContainer ? range.commonAncestorContainer : 
       range.parentElement ? range.parentElement() : range.item(0); 
    } 
    if (node) { 
     return (node.nodeName == "#text" ? node.parentNode : node); 
    } 
}; 

Ajusté mi método IE para aproximar el tuyo. Probado y funcionando IE8, FF3.6, Safari4, Chrome5. Configuré un jsbin preview con el que puedes probar.

+0

@jason - Vea también esta respuesta: http://stackoverflow.com/questions/2459180/how-to-edit-a-link-within-a-contenteditable-div/2459214#2459214 podría ayudar ... * se encoge de hombros * – gnarf

1

He encontrado que la selección puede ser complicada y problemática en todos los navegadores. ¡Incluya la magia de la edición de documentos del navegador y empeora!

Eché un vistazo a cómo TinyMCE implementa lo que estoy tratando de hacer, y tomé el mismo enfoque para modificar jHtmlArea.

Básicamente, se crea un enlace con un href falso. Luego, encuentra ese elemento dom al buscar enlaces con ese href particular. A continuación, puede agregar los atributos deseados y actualizar el href con la url real.

El solution above by gnarf es un excelente ejemplo de cómo obtener un nodo seleccionado, y funcionará para la mayoría de los escenarios.

A continuación se muestra el código de mi trabajo en torno a:

var url = prompt("Link URL:", "http://"); 

if (!url) { 
    return; 
} 

// Create a link, with a magic temp href 
this.ec("createLink", false, "#temp_url#"); 

// Find the link in the editor using the magic temp href 
var linkNode = $(this.editor.body).find("a[href='#temp_url#']"); 

linkNode.attr("rel", "external"); 

// Apply the actual desired url 
linkNode.attr("href", url); 
Cuestiones relacionadas