Saturday, December 22, 2007

TinyMCE, ASP.NET AJAX, and Auto-Save

I'm working on a ASP.NET web app that will allow administration of a new product feature and some of that content can be several paragraphs long. I'm using TinyMCE for those longer pieces and the ASP.NET AJAX Timer control to auto-save the form.

What I noticed is that any field connected to TinyMCE wouldn't be saved on auto-save, but would be saved just fine with a full Save button click and PostBack -- even though the same method was being used.

The details are a little hazy, but there's a layer in TinyMCE that disconnects what you see in your browser as you're typing from the actual textarea. On PostBack, the two were reconnected, but only then. After some searching I found references to TinyMCE's triggerSave() method. So, my hack to deal with this was to add the following immediately after tinyMCE.init():
setInterval("tinyMCE.triggerSave()", 30000);
This will call triggerSave() every 30 seconds. If I find a better way to handle this with the Timer control I'll update this post.

Friday, December 21, 2007

Textml vs. MarkLogic, Part 2

I had a very good conversation yesterday with John Kreisa the Director of Product Marketing for Mark Logic where we talked about the differences between Textml and MarkLogic Server -- the issues I raised in a previous post, plus a few others. One of the other topics that I forgot to mention there and is a huge plus for MarkLogic is the ability to influence relevancy ranking.

The best part of this conversation was that John initiated it. Now, I know it's a minor detail, and maybe even a little silly, but it's nice to know that they're being so proactive. None of the features we talked about may ever be added to the product, but at least I know my voice was heard.

I'm most hopeful that they add a document-focused admin console to the product. So far, it's the one thing I really miss (well, at least since I was able to build my own query parser).

UPDATE: MarkLogic recently released a new, very powerful search library. If you're reading this, you have to check out lib-search.

Thursday, December 20, 2007

ASP.NET TreeNode, Parent of the Selected Node, and RenderPreText

I bumped into something interesting today while working on a TreeView control to be used to represent a book's table of contents on a website. The control had 3 levels: the root, the chapter level, and each major section within each chapter, which we call the "a-head level."

If the user is viewing a piece of content from the a-head level, I was asked to NOT expand the chapter level TreeNode, to apply a different background color to the selected node (the a-head leaf TreeNode), and to apply the same background color to the parent chapter level TreeNode. "Should be fine," I said.

Right. In a Windows form, a TreeNode has a property called BackColor that can be set, but in a Web form, this property is not available. I'm sure there's a good reason for this, but it caught me a bit off-guard ... and much swearing ensued when I realized it.

Long story short, check out Danny Chen's great post on customizing TreeNode controls. This was the first case where I really need to mess with how the .NET framework was rendering HTML.

His post goes into much more detail on what you can do, but my needs were fairly simple. I did take advantage of the lesson to actually set a CSS class rather than just change the background color. Here's the custom TreeNode class I created to set the CSS class for the parent node of the selected node (documentation comments removed for brevity):
public class TreeNodeCustom : TreeNode
{
private string _CssClass = "";

public string CssClass
{
get { return _CssClass; }
set { _CssClass = value; }
}

public TreeNodeCustom() { }

public TreeNodeCustom(string cssClass)
{
_CssClass = cssClass;
}

protected override void RenderPreText(HtmlTextWriter writer)
{
foreach (TreeNode tn in this.ChildNodes)
{
if (tn.Selected)
{
writer.WriteFullBeginTag("div class=\"" + CssClass + "\"");
break;
}
}
base.RenderPreText(writer);
}

protected override void RenderPostText(HtmlTextWriter writer)
{
foreach (TreeNode tn in this.ChildNodes)
{
if (tn.Selected)
{
writer.WriteEndTag("div");
break;
}
}
base.RenderPostText(writer);
}
}
And here's how I call it in code when I need it:

TreeNodeCustom chapter = new TreeNodeCustom("customNode");

Visual Studio 2005 Spell Check Now Available

I've been waiting for this for awhile now. There's finally a good spell check tool for Visual Studio 2005 (and 2008) available.

Saturday, December 15, 2007

Fennel and Pepper Biscuits

I love these things.

Proof some yeast for 5-10 minutes.
  • 1 cup warm water
  • 2 tablespoons olive oil
  • 1/4 teaspoon sugar
  • 1 packet of yeast

Put together in a large bowl:

  • 5 cups of all-purpose flour
  • 1 1/4 tablespoons salt
  • 1 tablespoon fennel
  • 1 tablespoon black pepper (or to taste)
  • 1/2 cup olive oil
  • proofed yeast from above

Knead/mix together with a little warm water as needed. When done, let the dough rest for 20-30 minutes. I usually cover it with the same mixing bowl. If it's cold out, give this more time.

Preheat the oven to 425. Bring a large pot of water 3/4 of the way full to a gentle boil.

Cut off pieces of the dough and roll it out like a bread stick. Then connect the ends to form a circle. Be sure this connection is tight. Drop a group of the biscuits into the boiling water. Don't let them stick to the bottom. When they float to the top (this will take only a few seconds), remove them and place them in the oven. I normally place them directly on the racks. As you grab them out of the boiling water, aim for either the connection point or 1/3 of the way passed it because they fall apart easily.

Bake until light brown.

This recipe makes a fair number. I usually place half in a freezer bag in the freezer.

There are some interesting variations of this recipe I've seen over the years.

Tuesday, December 11, 2007

Set an ASP.NET TreeView Node to Expand and not PostBack

A classic small snippet of code that I use infrequently and takes me too long to find when I need it. Here's how to set an ASP.NET TreeView Node to expand and not PostBack when clicked.
tvNode.SelectAction = TreeNodeSelectAction.Expand;

URL Rewriting in ASP.NET with No Code

http://urlrewriter.net/ provides a great little tool for URL rewriting in ASP.NET. I used this on a site where SEO was of particular concern. The best part was that it required no code.

Instead of mydomain.com/reader/Default.aspx?id=12345&type=book I could enable links like mydomain.com/reader/Default.aspx/12345/book.

Here's how I enabled this using Web.config:
<configuration>
<!--...-->
<configSections>
<!--...-->
<!-- For URLRewriter -->
<section
name="rewriter"
requirePermission="false"
type="Intelligencia.UrlRewriter.Configuration.
RewriterConfigurationSectionHandler,
Intelligencia.UrlRewriter" />
</configSections>

<system.web>
<!--...-->
<httpModules>
<add
name="UrlRewriter"
type="Intelligencia.UrlRewriter.RewriterHttpModule,
Intelligencia.UrlRewriter"/>
</httpModules>
</system.web>

<rewriter>
<rewrite
url="~/reader/Default.aspx/(.*)/(.*)/$"
to="~/reader/Default.aspx?id=$1&type=$2" />
<rewrite
url="~/reader/Default.aspx/(.*)/(.*)$"
to="~/reader/Default.aspx?id=$1&type=$2" />
</rewriter>

</configuration>

Validation Controls for Part of a Page in ASP.NET

If there's a set of controls on the page that requires validation, but some other action that may happen that does not require validation (perhaps there's a search box that's part of a MasterPage, but that exists on a page with an email form that should have some validation), set the ValidationGroup property on the validation controls and the button that should fire them to the same value.

Thanks to a co-worker for pointing this out to me before I had to think too hard about it!

Odd and Even Numbers in XSL 1.0

Here's a way to tell if a number is odd or even in XSL 1.0, in this case as part of a snippet of code to switch CSS styles between rows in a search results set.
<xsl:attribute name="class">
<xsl:choose>
<!--returns true for odd counts-->
<xsl:when test="$number mod 2 = 1">highlight</xsl:when>
<!--returns true for even counts-->
<!--<xsl:when test="$number mod 2 = 0">nohighlight</xsl:when>-->
<xsl:otherwise>nohighlight</xsl:otherwise>
</xsl:choose>
</xsl:attribute>