2016-11-06 117 views
0

我想在文本上有一個「多讀」功能。我動態加載特定關鍵字維基百科文本和具有這樣的功能:加載內容異步時,JavaScript無法識別我的功能?

function setText(text, lang, full) { 
    setTimeout(function() { $('#loading').fadeOut('fast'); }, 300); 
    var mylang = '<?= $_SESSION['lang']; ?>'; 
    if (mylang != 'en' && lang == 'en') 
     var AppendText = '<span class="db f09 grey mt10"><?= __('TEXT_ONLY_ENGLISH'); ?></span>'; 

    console.log(lang); 

    if (full) { 
     $('#text').html('<?= __('EMPTY'); ?>'); 
     setTimeout(function() { $('#text').fadeIn('fast'); }, 500); 
    } else if (text) { 
     // Full Text 
     function fullText() { 
      console.log('yes'); 
      setText(text, lang, 1); 
     } 

     text = text.length > length ? text.substring(0, length - 3) + 
     '... <a class="cp" onclick="fullText()"><?= __('MORE') ?></a>' : text; 
     $('#text').html(text).append(AppendText); 
     setTimeout(function() { $('#text').fadeIn('fast'); }, 500); 
    } 
}; 

正如你可以在else if部分看到我定義的fullText()功能設置的onclick錨標記。當我點擊它時,我總是收到消息fullText is not defined。 我只是想重新調用相同setText()函數變量full設置爲1,使全文將顯示

Sometext的,而不是...(更多)

這是可能不使用ajax?我有什麼選擇? PS:我也已經嘗試過撥打setText()本身,而不是fullText(),但那也不會被識別爲定義的功能。

+1

與您的問題沒有關係,但僅供參考,您不需要那些'setTimeout'調用。你可以使用'.delay()'來代替。 '$('#text')。delay(500).fadeIn('fast');' – 2016-11-06 16:07:26

+1

好的,很高興知道,謝謝。 @squint – AlexioVay

+3

'fullText'函數的作用域被定義爲函數的地方,所以'onclick'屬性將無法看到它,因爲它將在全局範圍內查找它。 – 2016-11-06 16:09:27

回答

2

使用onclick屬性,您只能引用全局範圍內的函數。爲了解決這個問題,你可以動態附加一個事件處理程序,而不是使用onclick屬性。

要弄完,我會建議一些變化,這會導致下面的代碼:

function setText(text, lang, full) { 
    setTimeout(function() { $('#loading').fadeOut('fast'); }, 300); 
    var mylang = '<?= $_SESSION['lang']; ?>'; 
    // change 1: define an element with jQuery 
    var $appendText = $('<span>'); 
    if (mylang != 'en' && lang == 'en') 
     $appendText.addClass('db f09 grey mt10').text('<?= __('TEXT_ONLY_ENGLISH')?>'); 

    console.log(lang); 

    if (full) { 
     // change 2: use text(), not html() 
     $('#text').text('<?= __('EMPTY'); ?>'); 
    } else if (text) { 
     // Full Text 
     // Change 3: define link as jQuery element: 
     var $link = $('<a>'); 
     if (text.length > length) { 
      text = text.substring(0, length - 3); 
      $link.addClass('cp').text('<?= __('MORE') ?>'); 
      // Change 4: attach click handler here: 
      $link.click(function fullText() { 
       console.log('yes'); 
       setText(text, lang, 1); 
      }); 
     } 
     // Change 5: append these jQuery elements, which can be empty: 
     $('#text').text(text).append($link).append($appendText); 
    } 
    // Change 6: move this out of the if-block, as it is the same for both cases: 
    setTimeout(function() { $('#text').fadeIn('fast'); }, 500); 
}; 

請注意,您沒有提供變量length的定義,但我相信它是提供給功能。

+0

你是一個天才,謝謝。 – AlexioVay

1

因爲function fullText()是本地setText click事件執行對全球範圍內,並且不被知道的fullText() 不要用內部HTML添加一個元素,但這樣做createElement

類似:

var hr = document.createElement("A"); 
hr.className="cp"; 
hr.onclick= function { 
      console.log('yes'); 
      setText(text, lang, 1); 
     } 
$('#text').appendChild(hr) 

將創建一個閉包並解決問題。

+0

如果我把它放在'setText()'之外,它也不會被識別。 – AlexioVay

+0

@Vaia OK也給瞭解決方案 –

1

編輯:上面的其他答案更好,因爲他們利用jQuery和更有意義;我的部分解決方案(僅限編輯)不依賴於jQuery。

嘗試這樣:

var fullText; 
function setText(text, lang, full) { 
    setTimeout(function() { $('#loading').fadeOut('fast'); }, 300); 
    var mylang = '<?= $_SESSION['lang']; ?>'; 
    if (mylang != 'en' && lang == 'en') 
     var AppendText = '<span class="db f09 grey mt10"><?= __('TEXT_ONLY_ENGLISH'); ?></span>'; 

    console.log(lang); 

    if (full) { 
     $('#text').html('<?= __('EMPTY'); ?>'); 
     setTimeout(function() { $('#text').fadeIn('fast'); }, 500); 
    } else if (text) { 
     // Full Text 
     fullText = function() { 
      console.log('yes'); 
      setText(text, lang, 1); 
     } 

     text = text.length > length ? text.substring(0, length - 3) + 
     '... <a class="cp" onclick="fullText()"><?= __('MORE') ?></a>' : text; 
     $('#text').html(text).append(AppendText); 
     setTimeout(function() { $('#text').fadeIn('fast'); }, 500); 
    } 
}; 

O_Z是正確的在他的答案,在function fullText只的setText()實例中定義。在function setText之內的任何地方調用此函數通常會按照您期望的方式工作,但是您要通過編寫HTML代碼從全局onclick調用fullText()處理程序,因此不知道setText()的特定實例的定義相關function fullText

該解決方案有一個主要問題,那就是如果setText()在加載相關文檔之前被多次調用,fullText()只會引用最近的文檔,而不是兩者。爲了解決這個問題,我實際上會創建一個全局數組來存儲不同的fullText函數,然後寫入該數組中要運行的索引,然後如果不再需要從數組中刪除存儲的函數(以避免內存泄漏)。還有另一個例子:

var fullTextFunctions = []; 
function setText(text, lang, full) { 
    setTimeout(function() { $('#loading').fadeOut('fast'); }, 300); 
    var mylang = '<?= $_SESSION['lang']; ?>'; 
    if (mylang != 'en' && lang == 'en') 
     var AppendText = '<span class="db f09 grey mt10"><?= __('TEXT_ONLY_ENGLISH'); ?></span>'; 

    console.log(lang); 

    if (full) { 
     $('#text').html('<?= __('EMPTY'); ?>'); 
     setTimeout(function() { $('#text').fadeIn('fast'); }, 500); 
    } else if (text) { 
     // Full Text 
     fullTextFunctions.push(function fullText() { 
      console.log('yes'); 
      setText(text, lang, 1); 
     }) 

     text = text.length > length ? text.substring(0, length - 3) + 
     '... <a class="cp" onclick="fullTextFunctions[' + (fullTextFunctions.length - 1) + ']()"><?= __('MORE') ?></a>' : text; 
     $('#text').html(text).append(AppendText); 
     setTimeout(function() { $('#text').fadeIn('fast'); }, 500); 
    } 
}; 

function releaseFullTextFunction(index) { 
    fullTextFunctions[index] = null; 
} 
+0

謝謝你這個詳細的答案,我真的很感激它,並且學到了很多!很高興知道JS如何在後臺工作。所以據我瞭解,你的意思是如果'文字'會改變,我應該更喜歡用數組創建這個解決方案? – AlexioVay

+0

更多的是,如果在調用fullText之前多次調用函數'setText',變量/函數'fullText'只引用最近一次'setText'被調用。所以如果你想讓'setText'的不同實例引用'fullText'的不同實例,你必須將實例存儲在一個具有唯一標識符的全局數組/對象中,假設你堅持從HTML'onclick'調用'fullText' '處理程序。 – Sabumnim