I got a bit confused yesterday (once again

). I was comparing two different programs. The test app 'paras' and my current project called 'textreader'. I thought about it during the night and I felt sure that I must have forgotten something. This morning I discovered that that was true. I had forgotten to clear the field 'myText3' in 'paras', which I had intended to do. I fixed this but it made no difference. It is still not possible to add more than one 'link word' to a textline. However, the fact remains that it is possible to do this in 'textreader' but in 'textreader' there is never more than one textline in question. I have put a zip the latest version of 'paras' here:
https://www.mediacours.com/tb_examples/paras2.zipHere are the relevant parts of the code from 'textreader'. I could send you the whole thing but it would be a bit complicated to set up and I fear you may find it hard to follow my labyrinthine code. Please let me know if you need any explanations. I have started copying all the code but there is really far too much. I'll try and give you only the essential parts.
1) a function called makeLinkWord() uses getTheWord() to locate the word in the text. Here is the version of getTheWord() used:
- Code: Select all
<function name="getTheWord" event="" params="">
<![CDATA[
let obj;
if (this.spelling == true) // used for spelling in textarea 'myText'.
{
obj = "myText";
}
else
{
obj = "myText2"; //pictures is true. getTheWord is used by author to create colored words in a div.
}
const txt = tbfunction_pgTBObjGet(obj, "text");
let txtEnd = txt.length;
let pos = tbfunction_caretPosition(obj, -1);
let ws = /\s/.test(txt[pos]);
if (ws == true || txt[pos] == "")
{
pos -= 1;
}
pos -= 1;
let start;
let end;
ws = /\s/.test(txt[pos]);
while (ws == false && pos > -1 && txt[pos] != "")
{
pos -= 1;
ws = /\s/.test(txt[pos]);
}
pos += 1;
start = pos;
pos += 1;
ws = /\s/.test(txt[pos]);
while (ws == false && pos < txtEnd && txt[pos] != "")
{
pos += 1;
ws = /\s/.test(txt[pos]);
}
pos -= 1;
end = pos;
let str = txt[start];
pos = start;
while (pos < end + 1 && pos < txtEnd - 1)
{
pos += 1
str = str + txt[pos]
}
//this.obj.setSelectionRange(start, end + 1); //could be selected but this is not required here.
//INVERTED COMMAS: THERE MUST HAVE BEEN A COMPETITION FOR FANCY PUNCTUATION!!!
str = str.trim();
let L = str.length;
if (str[0] == "'" || str[0] == "‘")
{
str = str.substring(1, L);
L = str.length;
L -= 1;
if (str[L] = "'" || str[L] == "’") //It's a pair
{
str = str.substring(0, L);
}
}
//Every country seems to have a different style of inverted commas!
//str tbfunction_pgReplace("‘", "", str); //single quote English and others. don't think that this is used as an apostrophe but it could be.
//str = tbfunction_pgReplace("’", "", str); //single quote 146 English, Dutch and others, may be an apostrophe so only take it out at beginning and end (as above).
str = tbfunction_pgReplace('"', '', str); //double quote English and others
str = tbfunction_pgReplace('“', '', str); //double quote English and others
str = tbfunction_pgReplace('”', '', str); //double quote Swedish and others
str = tbfunction_pgReplace("«", "", str); //guillemet Italian and others
str = tbfunction_pgReplace("»", "", str); //guillemet Danish and others
str = tbfunction_pgReplace("„", "", str); //double lower quote German and others
str = tbfunction_pgReplace("‚", "", str); //single lower quote German and others
str = tbfunction_pgReplace(";", "", str); //VARIOUS OTHER PUNCTUATION MARKS
str = tbfunction_pgReplace(":", "", str);
str = tbfunction_pgReplace(",", "", str);
str = tbfunction_pgReplace(".", "", str);
str = tbfunction_pgReplace("?", "", str);
str = tbfunction_pgReplace("¿", "", str);
str = tbfunction_pgReplace("(", "", str);
str = tbfunction_pgReplace(")", "", str);
str = tbfunction_pgReplace("`", "", str); //ansi 96
str = tbfunction_pgReplace("", "", str); //ansi 127
str = str.trim();
return [start, str];
]]>
</function>
I think it's identical to the same function used in 'paras' but I'm not sure.
2) makeLinkWord() stores the position of the char immediately in front of the word selected and the word itself in global variables belonging to an object called 'upload' and then makes it possible to upload an image to an appropriately named newly created folder.
3) once the image file is in place, the image is displayed and the innerHTML of a field called 'myText2' is modified to create the 'link word'. Here is the relevant part of the code that does this:
- Code: Select all
if (!(reply == 1) && !(reply == 2))
{
sharedActions.input("11`1", "1"); //Error: web server was unavailable or unable to respond.
}
else
{
if (reply == 2)
{
newFileName = tbfunction_pgReplace(".gif", ".png", newFileName); //gif may be converted to png by picturesUp.html depending on its size.
}
let start = upload.start;
console.log("in upload start is " + start);
start = start * 1;
const myWord = upload.holdWord;
const start2 = ('0000' + start).slice(-5);
let colorNo = upload.holdClass;
colorNo = sharedActions.colorFromNo(colorNo);
tbfunction_pgTBObjSet("picFrame", "rgbFill", colorNo);
const myID = upload.holdClass + start2;
let folderName = start2;
//PROCESS TO ADD LINK SPAN:
let htm = sharedActions.obj2.innerHTML; //obj2 is field 'myText2'
const classType = "linkWord" + upload.holdClass; //this is a number that indicates the color to use.
const newWord = '<span id=' + String.fromCharCode(34) + myID + String.fromCharCode(34) + ' onclick= "top.relay(event,' + String.fromCharCode(39) + myID + ',' + newFileName + String.fromCharCode(39) + ')" class="' + classType + '"> ' + myWord + '</span>';
const fct = function() //fct 1
{
//add the chevron
tbfunction_caretPosition("myText2", start, "", "ˆ", false); //THIS IS WHERE THE CHEVRON IS PUT INTO THE innerHTML
htm = sharedActions.obj2.innerHTML;
const oldWord = "ˆ" + myWord;
//add the new span
htm = tbfunction_pgReplace(oldWord, newWord, htm);
console.log(htm);
const fct = function() //fct 2
{
//update innerHTML
sharedActions.obj2.innerHTML = htm; //colored word will appear in text of 'myText2'
sharedActions.pages[sharedActions.currentPage] = htm;
//console.log(htm);
const filePath = "../../" + sharedActions.currentFolder + "/" + folderName + "/" + newFileName;
var tmp = new Image();
tmp.addEventListener( "load", function() {
var sz = [ tmp.naturalWidth, tmp.naturalHeight ];
const address = "url(" + String.fromCharCode(34) + filePath + String.fromCharCode(34) + ")";
sharedActions.setFrame(myWord, address, sz[0], sz[1]);
//clear globals
upload.folderName = "";
upload.holdWord = "";
upload.holdClass = "";
upload.originalName = "";
upload.start = "";
sharedActions.recordAgain = true; //context 3 is used to make saveFile use pageCount + 1 instead of currentPage.
sharedActions.saveFile(sharedActions.holdTotal, 1, 3); //pictures are always added only after all recordings are done.
const fct = function() //fct 3
{
tbfunction_pgTBObjSet("closeList", "click"); //hide the picture
}
setTimeout(fct, 4000) //3
});
tmp.src = filePath;
sharedActions.hideWait();
}
setTimeout(fct, 200); //2
}
setTimeout(fct, 200); //1
}
sharedActions.stopSleep = true; return; //======================> END
I have just checked that this code is still functioning correctly and it is. You can add as many link words (and images) as you choose.
Thanks for your time and good luck
John
UPDATE Part of the problem must be the presence of
< and
> https://stackoverflow.com/questions/5068951/what-do-lt-and-gt-stand-for what generates these? I've been trying to convert them back to
< and
> but I haven't succeeded yet.
UPDATE 2 This seems to work (for button 'insert' in 'paras'):
- Code: Select all
<insert>
<function name="myClick" event="click" params="" useTB="true">
<![CDATA[
let txtArray = [];
tbfunction_pgTBObjSet("retWord", "text", "");
tbfunction_pgTBObjSet("myText3", "text", "");
let txt = sharedActions.obj2.innerHTML;
txtArray = tbfunction_pgSplitToArray(txt, "<br>");
tbfunction_pgTBObjSet("ctr", "text", txtArray.length);
const retVal = sharedActions.getTheWord();
//console.log(retVal[0] + " " + retVal[1] + " " + retVal[2]);
const myWord = retVal[1];
tbfunction_pgTBObjSet("retWord", "text", myWord);
tbfunction_pgTBObjSet("pos1", "text", retVal[2]); //paragraph No.
tbfunction_pgTBObjSet("pos2", "text", retVal[0]); //position of start of word
let textline = txtArray[retVal[2]];
textline = tbfunction_pgReplace("<", "<", textline, true);
textline = tbfunction_pgReplace(">", ">", textline, true);
tbfunction_pgTBObjSet("myText3", "text", textline);
const n = retVal[2];
let pos;
if (n > 0)
{
pos = retVal[0] - 1;
}
else
{
pos = retVal[0];
}
tbfunction_caretPosition("myText3", pos, "", "ˆ", false); //THIS IS WHERE THE CHEVRON IS PUT INTO THE innerHTML
const htm = sharedActions.obj3.innerHTML;
console.log(htm);
txtArray[n] = htm;
txt = txtArray.join("<br>");
const myNo = tbfunction_getRandomNumber(1, 6);
let myID = sharedActions.myID;
myID = ('0000' + myID).slice(-5);
myID = myNo + myID;
const newFileName = "example.jpg"
const classType = "linkWord" + myNo; //this is a number that indicates the color to use.
const newWord = '<span id=' + String.fromCharCode(34) + myID + String.fromCharCode(34) + ' onclick= "top.relay(event,' + String.fromCharCode(39) + myID + ',' + newFileName + String.fromCharCode(39) + ')" class="' + classType + '"> ' + myWord + '</span>';
const oldWord = "ˆ" + myWord;
txt = tbfunction_pgReplace(oldWord, newWord, txt);
txt = tbfunction_pgReplace("<", "<", txt, true);
txt = tbfunction_pgReplace(">", ">", txt, true);
sharedActions.obj2.innerHTML = txt;
console.log(txt);
]]>
</function>
</insert>
but surely there must be a better way of doing this? It's not 100% bug free either but it's an improvement!
