Reputation: 4527
I want to have a "read more"-click function on a text. I'm dynamically loading a Wikipedia text for a specific keyword and have this function:
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);
}
};
As you can see in the else if
part I defined the fullText()
function set to onclick on the anchor tag. I always get the message fullText is not defined
when I click on it.
I just want to re-call the same setText()
function with the variable full
set to 1
, so the full text will be displayed instead of
Sometext... (more)
Is this possible without using ajax
? What options do I have?
PS: I also already tried calling setText()
itself instead of fullText()
but that won't be recognized as a defined function either.
Upvotes: 0
Views: 88
Reputation: 711
EDIT: The other answers above are better because they take advantage of jQuery and make more sense; my partial solution (only the edits I made) is not dependent on jQuery.
Try something like this:
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 is correct in his answer, in that function fullText
is only defined inside an instance of setText()
. Calling this function from anywhere inside function setText
would normally work the way you would expect, however you are calling fullText()
from a global onclick
handler, by writing the HTML code, and therefore has no clue as to the specific instance of setText()
that defined the relevant function fullText
.
This solution has one major problem, however, which is that if setText()
is called multiple times before the relevant documents are loaded, fullText()
would only reference the most recent document, not both. To solve this, I would actually make a global array to store different fullText
functions into, and write into the HTML which index in that array to run, and then removing the stored function from the array if it is not necessary anymore (to avoid a memory leak). There is another example below:
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;
}
Upvotes: 1
Reputation: 1563
Because function fullText()
is local to setText
the click event executes on the global scope and does not know of fullText()
Do not add your A element with inner html but do it by createElement
something like:
var hr = document.createElement("A");
hr.className="cp";
hr.onclick= function {
console.log('yes');
setText(text, lang, 1);
}
$('#text').appendChild(hr)
will create a closure and solve the problem.
Upvotes: 1
Reputation: 350212
With the onclick
attribute you can only reference functions that are in the global scope. To get around this, you can attach an event handler dynamically instead of using the onclick
attribute.
To get that done, I would suggest some changes, that lead to the following code:
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);
};
Note that you did not provide the definition of the variable length
, but I assume it is available to the function.
Upvotes: 2