2013-12-19 36 views
2

我有一個div,其contenteditable屬性設置爲true。當用戶鍵入'#''@',我想得到任何他/她鍵入直到按下空格鍵。這樣,我可以根據他/她可能輸入的單詞,從db中提出建議。
請看看下面的例子,如何收集在#或@旁邊輸入的字符/單詞div

<div id="editableDiv" contenteditable="true"> 
    I may tweet from @twitter in the near #future 
    <ul id="suggestUL"></ul> 
</div> 

只要用戶類型'@''#',我必須能夠收集無論他/她可以輸入(根據上面的例子中,後@ttwtwitwittwitttwittetwitter。而經過ffu ... future)。 'twitter'後,用戶鍵入空格鍵這樣,詞集必須停止,必須從#重新開始。

編輯
代碼來獲得在那裏我可以顯示建議列表像素

function getCaretPixelPos($node) { 
    var offsetx = 0; 
    var offsety = 0; 

    var nodeLeft = 0, 
    nodeTop = 0; 
    if ($node) { 
     nodeLeft = $node.offsetLeft; 
     nodeTop = $node.offsetTop; 
    } 

    var pos = { left: 0, top: 0 }; 

    if (document.selection) { 
     var range = document.selection.createRange(); 
     pos.left = range.offsetLeft + offsetx - nodeLeft + 'px'; 
     pos.top = range.offsetTop + offsety - nodeTop + 'px'; 
    } else if (window.getSelection) { 
     var sel = window.getSelection(); 
     var range = sel.getRangeAt(0).cloneRange(); 
     try { 
      range.setStart(range.startContainer, range.startOffset - 1); 
     } catch (e) { } 
     var rect = range.getBoundingClientRect(); 
     if (range.endOffset == 0 || range.toString() === '') { 
      // first char of line 
      if (range.startContainer == $node) { 
       // empty div 
       if (range.endOffset == 0) { 
        pos.top = '0px'; 
        pos.left = '0px'; 
       } else { 
        // firefox need this 
        var range2 = range.cloneRange(); 
        range2.setStart(range2.startContainer, 0); 
        var rect2 = range2.getBoundingClientRect(); 
        pos.left = rect2.left + offsetx - nodeLeft + 'px'; 
        pos.top = rect2.top + rect2.height + offsety - nodeTop + 'px'; 
       } 
      } else { 
       pos.top = range.startContainer.offsetTop + 'px'; 
       pos.left = range.startContainer.offsetLeft + 'px'; 
      } 
     } else { 
      pos.left = rect.left + rect.width + offsetx - nodeLeft + 'px'; 
      pos.top = rect.top + offsety - nodeTop + 'px'; 
     } 
    } 
    //console.log('pos left : ' + pos.left + ' pos top : ' + pos.top); 
    //console.log($('#suggestUL')); 
    $('#suggestUL').css('left', pos.left); 
    $('#suggestUL').css('top', pos.top); 
    //console.log('suggestUL left : ' + $('#suggestUL').css('left') + ' suggestUL top : ' + $('#suggestUL').css('top')); 
}; 

這是我如何調用上面的函數

var event = e || window.event; 
    var keyCode = event.keyCode || event.which; 
    if (keyCode == 35 || keyCode == 64) 
     getCaretPixelPos($('#editableDiv')[0]); 

PS:我不知道爲什麼我被標題罰款-2。無論如何,我編輯標題更清晰。我是學習者,如果我在選擇標題或提問時出現任何錯誤,請提出建議。
在此先感謝。

+5

你試過的也表明過。 –

+0

看正則表達式... –

+0

^是。如果你還沒有嘗試過任何東西,[輸入HTML5事件](https://developer.mozilla.org/en-US/docs/Web/Reference/Events/input?redirectlocale=en-US&redirectslug=DOM%2FMozilla_event_reference% 2Finput)和/或只是常規的[keyboardevent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)應該讓你開始 –

回答

0

我終於能夠解決所有輸入問題。
這裏是一個性格'@'代碼呼籲

功能的KeyDown

var fetchSuggestions = false; 
var suggestForString = ''; 
function fnShowSuggestionUL(e) { 
    var event = e || window.event; 
    var keyCode = event.keyCode || event.which; 
    // KeyCode = 35 -> # 
    // KeyCode = 64 -> @ 
    // KeyCode = 32 -> space 
    // KeyCode = 13 -> Enter (Carriage Return) 
    if (keyCode == 35 || keyCode == 64) { 
     fetchSuggestions = true; 
     suggestForString = ''; 
     $('#suggestUL').css('display', 'block'); 
     fnPositionSuggestUL(); 
    } 
    else if (keyCode == 32 || keyCode == 13) { 
     fetchSuggestions = false; 
     suggestForString = ''; 
     $('#suggestUL').css('display', 'none'); 
     return; 
    } 
    if (fetchSuggestions == false) 
     return; 
    var data = String.fromCharCode(keyCode); 
    suggestForString = suggestForString + data; 
    // TODO: bring suggestions from database and append them as list items to "suggestUL" 
} 

位置suggestUL'#'

function fnPositionSuggestUL() { 
    var $node = $('#editableDiv')[0] 
    var offsetx = 0; 
    var offsety = 0; 

    var nodeLeft = 0, 
    nodeTop = 0; 
    if ($node) { 
     nodeLeft = $node.offsetLeft; 
     nodeTop = $node.offsetTop; 
    } 

    var pos = { left: 0, top: 0 }; 

    if (document.selection) { 
     var range = document.selection.createRange(); 
     pos.left = range.offsetLeft + offsetx - nodeLeft + 'px'; 
     pos.top = range.offsetTop + offsety - nodeTop + 'px'; 
    } else if (window.getSelection) { 
     var sel = window.getSelection(); 
     var range = sel.getRangeAt(0).cloneRange(); 
     try { 
      range.setStart(range.startContainer, range.startOffset - 1); 
     } catch (e) { } 
     var rect = range.getBoundingClientRect(); 
     if (range.endOffset == 0 || range.toString() === '') { 
      // first char of line 
      if (range.startContainer == $node) { 
       // empty div 
       if (range.endOffset == 0) { 
        pos.top = '0'; 
        pos.left = '0'; 
       } else { 
        // firefox need this 
        var range2 = range.cloneRange(); 
        range2.setStart(range2.startContainer, 0); 
        var rect2 = range2.getBoundingClientRect(); 
        pos.left = rect2.left + offsetx - nodeLeft; 
        pos.top = rect2.top + rect2.height + offsety - nodeTop; 
       } 
      } else { 
       pos.top = range.startContainer.offsetTop; 
       pos.left = range.startContainer.offsetLeft; 
      } 
     } else { 
      pos.left = rect.left + rect.width + offsetx - nodeLeft; 
      pos.top = rect.top + offsety - nodeTop; 
     } 
    } 
    //Create suggestUL if does not exist or destroyed 
    fnCreateSuggestUL(); 

    $('#suggestUL').css('left', pos.left + 'px').css('top', (pos.top + 18)+'px'); 
}; 

我想感謝一個和所有誰回答/在這裏評論。
請儘可能優化以上代碼,以便需要的人獲得完美的代碼。

PS:適用於Chrome和Firefox。 suggestUL在IE中沒有正確定位。
Happy Coding!!

0

試試這個:

var str = ''; 
$('#editableDiv').keyup(function(e){ 
    if($(this).val() == '@' || $(this).val() == "#"){ 
    if(e.keyCode !=32){ 
     str += String.fromCharCode(e.keyCode); 
    } 
    } 
}); 
alert(str); 
+0

可能需要使用'$(this).text()'而不是'$(this)來獲得最後輸入的字符。 val()' – skos

+0

是的!謝謝你的建議。這只是我的想法。我知道有很多方法可以做。 :D – HICURIN

2

您可以使用下面的腳本,伴隨着這一點,你需要使用一些UL/LI元素組合,它會顯示每行一個建議,一旦數據從服務器獲取。您可以使用jQuery Ajax從服務器獲取數據並動態創建ul/li列表。

var fetchData = false; 
    var suggestionChar = ''; 
    $('#editableDiv').on('keypress',function(event){ 
     var keyCode = event.which || event.keyCode. 
     var hashKey; // Set keyCode for # 
     var atKey; // Set keycode for @ 
     var spaceKey //SpaceKey code 
     if(keyCode == hashKey || keyCode == atKey){ 
      fetchData = true 
      suggestionChar = ''; 
      return; //flag is set now look out for next key cod. 
     } 
     else if (keyCode == spaceKey){ 
      fetchData = false; 
      suggestionChar = ''; 
     } 
     if(fetchData){ 
      var data = String.fromCharCode(keyCode); 
      suggestionChar = suggestionChar + data; 
      // use "suggestionChar" for fetching the data from server. 
      // fetch suggestions from Server. 
      // On success call back create the dynamic list of ul/li which will show the suggestion to user. You need to bind the user click event and/or keypress event for ul/li so that user can select the suggestion using mouse and keyboard along with 'Space' key. 
     } 
    }) 
+0

我對此有想法,但這是唯一可行的方法嗎?我對正則表達式知之甚少。我想正則表達式必須解決我的問題。你說啥? –

+1

雷克斯會給你你想要的文本字符串。但對於什麼時候開始和停止。你會需要類似的方法。如果你只是使用Regx和改變事件的股利,也將工作。但用這種方法沒有regx,我覺得這樣更好,因爲你可以訪問字符哪個用戶需要建議沒有雷克斯。上述解決方案將需要很少的改進,以收集#/ @後輸入的所有字符。 –

+0

讓我試試這個概念。如果你能獲得時間,請幫我解決問題。謝謝 –

1

我製作了這個東東(僅textarea):http://jsfiddle.net/wared/sL2sZ/。我試圖符合你的要求,但使用可編輯的DIV使事情工作要花費更多的時間。我決定放棄並從StackOverflow中獲取靈感。希望你可以從我的代碼中挑選一些想法來實現你的目標。 更多關於getCaret()這裏:https://stackoverflow.com/a/263796/1636522


衫尾...

目前,您能得到插入符號的像素位置,而我的代碼爲您帶來一個辦法來解決當前插入符索引字。缺少的鏈接是一個跨瀏覽器的解決方案,從可編輯的DIV中獲得脫字號索引(這是我放棄的地方,對我來說工作太多),實際上,當前版本的getCaret()只接受textarea。

換句話說,您所要做的就是修改getCaret()的正文以使其與可編輯的DIV一起工作。一旦你有了索引,你可以在getWord()附近找到它,所以你可以檢查它是否帶有前綴「@」,然後使用getCaretPixelPos()顯示適當的建議。

$('textarea').on('click keyup', function isAt() { 
    var idx = getCaret(this), 
     text = $(this).val(), 
     word = getWord(text, idx); 
    $('p').html([ 
     '"', word, '" ', word.charAt(0) === '@' 
     ? '<span style="color:blue">is prefixed</span>' 
     : '<span style="color:red">is not prefixed</span>' 
    ].join('')); 
}).focus(); 

function getWord(s, i) { 
    var r = /\s/g; 
    if (!i || r.test(s[i - 1])) return ''; 
    while (i && !r.test(s[--i])) {} 
    r.lastIndex = i && ++i; 
    return s.slice(i, (
     r.exec(s) || { index: s.length } 
    ).index); 
} 
+0

< - 謝謝瓦雷德。讓我來研究它。我希望這必須解決我的問題。 –

+0

對不起Wared,我沒有從div中得到caret索引。我發佈了我的答案。請看看它。用你的知識優化它。我是一個正則表達式的窮人。謝謝你的幫助。 –

+0

對不起,我現在很忙。以下是一些幫助:https://www.google.fr/search?q=get+caret+position+contenteditable。 – leaf

相關問題