views:

75

answers:

3

I have a string[] containing individual words parsed out of a paragraph of text. I need to display each word in its own cell, and have each cell be assigned a dynamic width based on the word's length. I want to be able to have as many words as possible within the maximum width of each row.

In short, I'm trying to take a given paragraph of text and present it as a series of editable controls in a way which resembles how it might appear as a plain text document, with each word consuming only its required space on each "line".

I first tried using a DataList with RepeatLayout in Table mode and RepeatColumns to a set value of 10, with a Repeater within containing a Label control; this resulted in 10 words per row but each cell with a fixed width.

I've considered using a GridView with a single column which I would cram with as many words (in the form of Label controls) per row as will fit, adding new rows as necessary until the entire paragraph is built.

Could anyone please share an elegant way to do this?

A: 

Best way I can think of approaching something like this is to simply use a repeater and float everything left.

<asp:Repeater runat="server" id="rptr">
   <ItemTemplate>
      <span style="float:left; height:22px; line-height:22px;"><%# Eval("Word") %></span>
   </ItemTemplate>
</asp:Repeater>
LorenVS
+1  A: 

I'll start off by saying that, from a user interface perspective, I'm not entirely sure as to why you would need to do this, but if it must be done you'd do something along these lines:

  • Start off with your string[]
  • Create a List<List<string>>
  • Loop through your original array, adding the strings to a new List<string>
  • Once you've reached your desired total character length, add the List<string> to your List<List<string>> (which contains your lines)
  • Repeat these steps until you've gone all the way through your original array

Once this is done, you bind the list o' list to a repeater like this below (pseudo code; might be off a bit):

<asp:Repeater id="rpt1" runat="server">
<ItemTemplate>
  <div>
    <asp:Repeater id="rpt2" runat="server" DataSource='<%# Container.DataItem %>'>
    <ItemTemplate>
       <asp:TextBox id="txt1" runat="server" Text='<%# Container.DataItem %>' Width='<%# MyWidthAlgorithm(Container.DataItem) %>'
    </ItemTemplate>
    </asp:Repeater>
  </div>
</ItemTemplate>
</asp:Repeater>
John
It's related to a project I'm working on which depends on being able to break up a paragraph of text so that its words can be manipulated and made editable individually. Sort of like a web-based notepad, except each word is treated as more than just a string.
Darth Continent
+1  A: 

The magic you're looking for is the "contenteditable" attribute. Works in IE, Firefox and Chrome.

I'm not sure what the hell you're doing with this, lmao... but this ought to work:

Your Code Behind:

protected void Page_Load(object sender, EventArgs e)
{
    //creating some bogus collection of strings.
    string[] parts = { "this", "is", "a", "test", "of", "the", "goofiest", "ui", "ever" };
    //bind it to the repeater.
    rptr.DataSource = parts;
    rptr.DataBind();
    //now we'll add them to a JavaScript array we can access client side.
    StringBuilder sb = new StringBuilder();
    sb.Append("document.stringItems = new Array();");
    for (int i = 0; i < parts.Length; i++)
        sb.AppendFormat("document.stringItems[{0}] = '{1}';", i, parts[i]);
    ScriptManager.RegisterClientScriptBlock(this, GetType(), "someKey", sb.ToString(), true);
}
protected void btnTest_Click(object sender, EventArgs e)
{
    //display the result just so we can see it's working.
    lblResult.Text = hdnResult.Value;
}

Your .ASPX:

<asp:Repeater ID="rptr" runat="server">
    <ItemTemplate>
        <span contenteditable="true" style="border: solid 1px;" onkeyup="updateItem(event, <%#Container.ItemIndex%>)">
            <%#Container.DataItem%></span>
    </ItemTemplate>
</asp:Repeater>
<asp:HiddenField ID="hdnResult" runat="server" />
<asp:Button ID="btnTest" runat="server" Text="Test" OnClick="btnTest_Click" />
<script type="text/javascript" language="javascript">
    //<![CDATA[
    function updateItem(e, index) {
        //get the source element. (magic here for cross browser lameness)
        var src;
        if(window.event) {
            e = window.event;
            src = e.srcElement;
        }else{
            src = e.target;
        }
        //update our item in our array.
        document.stringItems[index] = src.innerHTML;
        //update our hidden field.
        var s = '';
        var space = false;
        for (var i = 0; i < document.stringItems.length; i++) {
            if (space)
                s += ' ';
            else
                space = true;
            s += document.stringItems[i];
        }
        var hdnResult = document.getElementById('<%=hdnResult.ClientID%>');
        hdnResult.value = s;
    }
    //]]>
</script>
<asp:Label ID="lblResult" runat="server"></asp:Label>

You'll have to add some javascript for the onkeypress too to make sure they're not adding carriage returns or spaces or whatever it is you don't want them putting in... but this is the basic idea.

I hope that helps. Good luck.

blesh
Thanks, this did the trick.
Darth Continent