PDA

View Full Version : Accessing a span within a div. Making it clickable.



jhodson
24 Jul 2009, 4:14 AM
Hi,

I am attempting to achieve the following:

A Panel, which contains text, allowing the user to click on any individual sentence to make it editable in a separate textArea. Essentially: user clicks sentence, sentence appears in textarea.

My approach:

A div, into which I append spans for each sentence. When the user clicks one of these spans it fires a function that copies the span's contents into the textarea, and saves the span's id for when the user has finished editing the sentence.

The problem:

I'm new to ExtJS.

I have created a window with a Panel inside it, and I have a JS function that builds a string of spans from an array of sentences. I would like to append the spans to a div 'sourceDiv', and for these to be displayed as text within the panel. But how?

Once the panel contains the spans, I would like to have a function like:

$("div#sourceDiv span").click(load_text);in order to then have load_text do the following:

var load_text = function() {
highlight_source($(this).attr("id"), $(this).text());
$("div#editor textarea").val($(this).text());
var source = $("div#sourceDiv span:nth-child("+$(this).attr("id")+")");
$("span#sourcetext").text(source.text())
}Except that the textArea is not within a div, it is within the window
rendered into document.body.

Can someone please give me some pointers as to the correct way of achieving
this with ExtJS?

Thank you very much in advance!

James

Condor
24 Jul 2009, 4:40 AM
Did you do know that Ext has a build-in inline editor?

Example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ext="http://www.extjs.com" xml:lang="en" lang="en">
<head>
<link rel="stylesheet" type="text/css" href="resources/css/ext-all.css" />
<script type="text/javascript" src="adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-all.js"></script>
<script type="text/javascript">
Ext.onReady(function(){
var ed = new Ext.Editor(new Ext.form.TextArea({
enterIsSpecial: true,
allowBlank: false
}),{
autoSize: 'both',
completeOnEnter: true,
cancelOnEsc: true,
updateEl: true
});
Ext.select('.editable').unselectable();
Ext.getBody().on('dblclick', function(e, target) {
ed.startEdit(target);
}, null, {delegate: '.editable'});
});
</script>
</head>
<body>
<div class="editable">Paragraph 1</div>
<div class="editable">Paragraph 2</div>
</body>
</html>

jhodson
24 Jul 2009, 4:54 AM
Thank you very much for the response!

I didn't know about that feature - it seems very useful.

Unfortunately, for my project I was really hoping to keep the source text and the editing of the sentence separate. It is a translator's tool that allows for clicking both in the source and target text in order to make the corresponding sentence editable only in the target language.

I have tried several layouts, and the separate editing window approach is much cleaner overall. Could you offer any help with that instead?

Thanks once again,

James

Condor
24 Jul 2009, 5:10 AM
Your code gave me no clue about what you trying to do (and it's also in jQuery).

Are you trying to do something like:

Ext.get('sourceDiv').on('click', load_text, null, {delegate: 'span'});
var load_text = function(e, target) {
highlight_source(target.id, target.innerHTML);
Ext.getCmp('id-of-textarea').setValue(target.innerHTML);
Ext.getDom('sourcetext').innerHTML = target.innerHTML;
}

jhodson
24 Jul 2009, 5:20 AM
Sorry for the confusion...

That appears to be exactly what I am after. I have a working version in JQuery, which I was trying to port to ExtJS - sorry for not making that clearer and commenting it properly.

Just one more question - I have placed all of the spans into a div as follows:


for(var i=0; i < sentences.length; i++) {
var s = document.createElement('span');
s.id = i;
s.innerText = sentences[i];
Ext.get('sourceDiv').appendChild(s);
};

But the panel that I have is within a Window, so how would I get the contents of sourceDiv to appear within the Panel?

Sorry once again for the poor posting etiquette!

Thanks for your help!
James

Condor
24 Jul 2009, 5:24 AM
Will there be only one window+panel or can there be multiple?

If there is only one, you simple give the TextArea an id (as my example already demonstrated).

jhodson
24 Jul 2009, 5:38 AM
One window rendered into document.body.

One panel that I want to display all of the source language sentences (the spans I have created).

One panel containing a text area into which I want to load a single sentence once it has been clicked on within the panel above.

These panels are items within the window and currently have no div tags associated with them. 'sourceDiv' contains all of the spans in order to make it possible for them to be clickable (is that right?). At the moment the missing link is between sourceDiv and the first panel - displaying the source sentences in a way that they can be clicked upon...

So, the text area isn't the problem at the moment.

Thanks again,
James

Condor
24 Jul 2009, 5:51 AM
So you only want to know how to create a div (sourceDiv) inside a panel?

(if not, then I think you need to explain the problem better)

jhodson
24 Jul 2009, 6:12 AM
Ok.

Stupid question. I was using applyTo instead of contentEl in order to get the contents of the Div to show up in the panel - now it appears to be showing the source text... and it's clickable.

Thanks for all of your help!

James

jhodson
24 Jul 2009, 7:12 AM
Actually, just one more related question that I can't seem to resolve in relation to this:

I have two div tags each containing spans with the same numerical id's. How can I reference them using Ext.get()?

Ideally I want to be able to get the id of a span from one div, and use it to get the text from the corresponding span in the other div. Something like this pseudocode:


//target is in 'sourceDiv'
var load_text = function(e, target) {
var i = target.id;
//Get the corresponding span
var theSpanIWant = Ext.get('targetDiv'.i);
//Use the text from the corresponding span to fill the textarea
Ext.getCmp('editBox').setValue(theSpanIWant.innerHTML);
}

Thanks again in advance,
James

Condor
24 Jul 2009, 8:48 AM
ids need to be unique, so you can't assign the same id to the source and the target span.

You'll have to give them different ids (e.g. 'source42' and 'target42').

And then you can simply get them using, e.g. Ext.get('source' + n).

jhodson
24 Jul 2009, 9:23 AM
Hmmm,

When the ids were the same it worked - as in it picked out the wrong text to display in the text area, but at least it displayed something when clicked. Now that I've changed it to the code below it's stopped responding to clicks:

Working code:


Ext.get('sourceDiv').on('click', load_text, null, {delegate: 'span'});
Ext.get('targetDiv').on('click', load_text, null, {delegate: 'span'});

//load_text function
var load_text = function(e, target) {
Ext.getCmp('editBox').setValue(target.innerHTML);
}

//Load the source text here for now - until Ajax is implemented
for(var i=0; i < sentences.length; i++) {
var s = document.createElement('span');
s.id = i;
s.innerText = sentences[i];
Ext.get('sourceDiv').appendChild(s);
};
//Same for target text:
for(var i=0; i < target.length; i++) {
var s = document.createElement('span');
s.id = i;
s.innerText = target[i];
Ext.get('targetDiv').appendChild(s);
};

Non-working code:


var load_text = function(e, target) {
var i = target.id;
var path = "target".concat(i); //"target"+i & 'target'+i also don't work
var currSpan = Ext.get(path);
Ext.getCmp('editBox').setValue(currSpan.innerHTML);
}

//Load the text here for now - until Ajax is implemented
for(var i=0; i < sentences.length; i++) {
var s = document.createElement('span');
s.id = i;
s.innerText = sentences[i];
Ext.get('sourceDiv').appendChild(s);
};
for(var i=0; i < target.length; i++) {
var s = document.createElement('span');
var path = "target".concat(i);
s.id = path;
s.innerText = target[i];
Ext.get('targetDiv').appendChild(s);
};

Ext.get('sourceDiv').on('click', load_text, null, {delegate: 'span'});
Ext.get('targetDiv').on('click', load_text, null, {delegate: 'span'});

I know I'm probably doing something silly, but I can't figure out what...

Thanks!
James

Condor
24 Jul 2009, 12:00 PM
How about:

var sentencesTpl = new XTemplate('<tpl for="."><span id="s-{xindex}">{.}</span></tpl>').compile();
sourceTpl.overwrite('sentencesDiv', sentences);
Ext.get('sentencesDiv').on('click', load_text, null, {delegate: 'span'});

var targetTpl = new XTemplate('<tpl for="."><span id="t-{xindex}">{.}</span></tpl>').compile();
targetTpl.overwrite('targetDiv', target);
Ext.get('targetDiv').on('click', load_text, null, {delegate: 'span'});

var load_text = function(e, t) {
var index = t.id.substr(2);
var sentence = Ext.getDom('s-' + index).innerHTML;
var target = Ext.getDom('t-' + index).innerHTML;
Ext.get('sentenceDiv').innerHTML = sentence;
Ext.getCmp('editBox').setValue(target);
}

jhodson
24 Jul 2009, 1:07 PM
Thanks for the reply, and for the updated code,

I tried the code, and changed a few things when the page wouldn't load - such as the template name inconsistency and missing (?) "Ext." before XTemplate. The code I used is as follows:


var sentencesTpl = new Ext.XTemplate('<tpl for="."><span id="s-{xindex}">{.}</span></tpl>').compile();
sentencesTpl.overwrite('sourceDiv', sentences);
Ext.get('sourceDiv').on('click', load_text, null, {delegate: 'span'});

var targetTpl = new Ext.XTemplate('<tpl for="."><span id="t-{xindex}">{.}</span></tpl>').compile();
targetTpl.overwrite('targetDiv', target);
Ext.get('targetDiv').on('click', load_text, null, {delegate: 'span'});

var load_text = function(e, t) {
var index = t.id.substr(2);
var sentence = Ext.getDom('s-' + index).innerHTML;
var target = Ext.getDom('t-' + index).innerHTML;
//Ext.get('sourceDiv').innerHTML = sentence;
Ext.getCmp('editBox').setValue(target);
};

This loads the page, but will always display the first sentence of target[] no matter which span is clicked. Also appears to increase loading time dramatically compared to the partial solution I had previously.

I also tried moving bits in and out of onReady()...

Any suggestions?

James

jhodson
30 Jul 2009, 12:56 AM
Just wanted to update with a fix in case anybody needed this functionality in future:

Replace "{x-index}" in the XTemplate code, with {#}. This will give you a 1-based index as specified in the XTemplate documentation. All other code works as in the previous post.

Thanks to Condor for helping me to figure this out.

James