Monday, April 25, 2005
by Nik Kalyani
Monday, April 25, 2005 12:43:46 AM (Pacific Standard Time, UTC-08:00)

Dharmesh Shah asks:

I’m exploring the use of third-party controls (like Infragistics, ComponentArt, etc.) within my custom modules. My first round of experimentation with Infragistics seems to indicate a problem because of some of the Javascript and other stuff the control tries to insert. Do you have any tips or experience in using these types of controls inside a DNN module?

Nik’s response:

This is an issue that is going to plague DNN developers for some time to come. To understand why, let’s examine how components use Javascript.

Generally speaking, a third-party component will inject JS into your page in one of two ways: (1) by having a <script src=”…”> tag that links to a .js file, or (2) by injecting the script in-line using a <script> tag without the “src” attribute. The former is more efficient because it can benefit from browser caching. It is used for generic code and not for instance-specific initialization etc. The latter is necessary because it allows server-side code to create script on-the-fly. For example, in order to render the portal menu, the data for the menus is rendered on-the-fly.

Most components are written for ASP.Net applications. Your average ASP.Net application makes use of usercontrols for “shared code” to avoid repeatedly coding things such as headers, footers, feedback forms etc. Embedding a third-party component into these usercontrols is not a problem because it is rare that the same usercontrol is used multiple times on a page. In the case of DNN, usercontrols manifest themselves as “modules” and as any DNN user knows, a module may appear any number of times on a page. This is where the problem begins.

Forward-thinking component developers have envisioned this scenario and taken measures necessary to ensure the uniqueness of dynamically injected variables and objects in code. If a component developer has not done this, it’s game over when you have multiple instances of the component on the same page since the initialization code will reference only the last instance (if it even works). For example, let’s say we have an image with an ID of “MyImage” and there is a variable tracking the position of this image. The (unoptimized) code injected might look something like this:

var imgX = document.getElementById(“MyImage”).left;
var imgY = document.getElementById(“MyImage”).top;

If this code appears in a DNN module that is instantiated four times on a page, imgX and imgY will be set to the last occurrence of the code. Any further U.I. manipulation by JS will throw errors or produce generally erratic behavior.

This is the first thing to look for in a third-party component that uses client-side JS. Does it have the ability to be instantiated multiple times on the same page. The test scenario for this is easy. Download the trial version and modify one of the samples so two instances of the component are on the same page (do give them different ID’s). Does it work? If it seems to be working, double-check the page source. Look for Javascript variables and ensure that variables have a unique prefix or suffix. In most cases this will be driven by the ClientID property of the usercontrol as this is the Microsoft-recommended property to use for client-side identiciation of server-side controls.

I wish I could say that there was an easy workaround if the component does not readily allow multi-instance capability. There just isn’t. Your best bet is to contact the developer and make them aware of this problem. They may have a workaround or might make the change for you.

Another problem area is with initialization. A number of components will attach a handler to the body.onLoad() cleint-side event of a page to perform initialization. The problem occurs when the component is not well-behaved and or just plain dumb. In this case, it will either over-write an existing handler defined by some other component or even DNN itself, or just append multiple, duplicate handlers for multiple instances of a module. Again, this is something to verify through the page source.

The ID’s issued to dynamically generated U.I. objects is another problem area. Like variables and code objects, it is imperative that these U.I. objects be given unique ID’s otherwise when code tries to manipulate the object, it will fail.

The final and most perplexing problem is one of cross-compatibility. A component might do everything right, but if it sets a particular U.I. property to a certain value, and another module on the page emits script that also manipulates the same U.I. property, the result is disastrous. In this case, if changing code is not an option, the only solution is to not have the modules on the same page.

I hope this information will be helpful in figuring out which components are suitable for DNN and which ones aren’t.

by Nik Kalyani
Sunday, April 24, 2005 11:52:29 PM (Pacific Standard Time, UTC-08:00)

SnowCovered.com is the largest distributor of commercial third-party modules for DotNetNuke. If you are a DNN module developer and want to sell your product, this is the place to post it for sale. If you are a DNN end-user looking to buy a module, this is the place to buy it.

In recent months, more and more users post on the DNN forums complaining about some of the junk people pass off as modules on SnowCovered. As a result, there is a growing negative perception about the site. As a developer of commercial modules and also an end-user, I have many SnowCovered transactions and have a fairly strong opinion on the matter.

I would like to start by addressing the issue of module quality. This is simply not the responsibility of a distributor, especially when the terms are clearly spelled out for the buyer. Nor is it the responsibility of the distributor to judge what is good and what is crap. Do you go down to your local Wal-Mart and complain that they have crappy products along with good ones? Of course not, you just avoid the products that don’t meet your expectations. Why is this any different? Quite frankly, if you buy a module on SnowCovered without performing due diligence on the publisher, you’re an idiot because you failed to follow the most fundamental tenet of commerce — Caveat emptor!

Buying a module? Note the following:

1) Visit the publisher’s website prior to purchase. Is there a support page? Is there is an online forum with recent activity. Are there working product demos available? These are such basic things to look for pre-purchase, but unfortunately, people only do them post-purchase. If someone is selling a product and cannot fork over the $50 it takes to maintain a good website with working demos, you can conclude that they are opportunistic and not really in the software publishing business. Move on…

2) Do a cursory search on the net on the publisher’s name prior to purchase. Even if the publisher’s site is great, if Google is drawing a blank, chances are the publisher is not well-established. You can overlook this only if there are other means by which you can verify the publisher’s credibility.

3) DNN modules are dirt cheap. Spend the extra bucks for the source code. Then it won’t matter if the developer doesn’t publish an update for the latest version of DNN. Sure, it’s work for you if this happens and costs you a little more up front, but at least you are not stranded.

4) No one is going to give you a refund on software. This is a fact of life. Try opening a piece of software and returning it at Best Buy. Fat chance. This is no different.

The next issue I would like to address is the 25% commission. Any post where a developer is whining about this indicates that the developer is generally clueless about the market. Any distributor will charge you a commission of 18–30% for selling your software. If you don’t like this, then sell it yourself. But be prepared to have fairly low sales unless you are willing to put up some marketing dollars. All publishers benefit as a result of the aggregation on a distributor site. If you are not quite well-versed in the business of retail, you will whine about “SnowCovered taking your money.” This is plain and simple, a marketing fee. It is an industry-standard and for any sensible developer, a wise investment.

I launched a store for on my site in November 2004. I decided that Speerio has enough brand recognition and credibility that customers will not have a problem making a purchase directly on my site without a third-party. I was right. Over 85% of my sales now come from customers purchasing directly from the Speerio Online Store. However, I still want to capture business from new DNN users, so I will always continue to have a presence on SnowCovered and Xtras. It is a pain to manage upgrades etc. but in time, these systems will evolve.

One last comment on the issue of commission. The commission does not affect the buyer in any way, i.e. it is not an increased fee levied by the distributor. SnowCovered is actually using incorrect parlance. The industry standard term is “discount.” The publisher discounts their product by 25% so when SnowCovered sells at the MSRP, it gets to keep the difference. The buyer pays the MSRP in most cases unless the distributor has a promotion and gives up part of the discount by selling lower than MSRP.

Now, let’s talk about the SnowCovered Help Desk and FAQ system. Although I think Brice has done a great job of creating a market that was completely non-existent, on this topic, I must ask “What the heck are you thinking?” This is the most insane, dumb and generally speaking, lousy business decision I have seen made in some time. By extending its role from distributor to support provider, SnowCovered is setting itself up to fail in meeting customer expectations. The software for managing help requests and FAQs is a shade above really, really crappy. Every serious developer I know that sells on SnowCovered HATES it with a passion. It is a pain to use and a pain to support. I got so fed-up with it, I put a standard disclaimer on all my new SnowCovered posts…pre– and post-sales questions at SnowCovered will be ignored. Email me directly or visit the Speerio site and post on the forums. It has worked quite well, although there will be the occasional customer who will continue posting there. I wish the SnowCovered help desk and FAQ system would go away.

Now, I hope this post doesn’t give the impression that I really like SnowCovered and am OK with the fact that there is complete crap being passed off as DNN modules on there. I don’t. I hate it, especially because I put in a lot of effort into creating quality products and I hate being shelved with sub-standard products. But this is how a market economy works. Ultimately, the market decides on what is good and what isn’t. If I want the benefit of the visibility SnowCovered has, I have to publish my products on their site. Thankfully, with few exceptions, customers are smart and can tell the difference. So, for the moment, I can live with this.

 Saturday, April 23, 2005
by Nik Kalyani
Saturday, April 23, 2005 5:31:40 PM (Pacific Standard Time, UTC-08:00)

If you wish to create strong named assemblies in .Net, you need to sign them. This is done using a key that you reference through the project’s AssemblyInfo.cs or AssemblyInfo.vb file. There are three attributes related to signing:

[assembly: AssemblyDelaySign(false)] Used to allow signing of the assembly with only the public key. This allows the assembly to be used during development without having to share the private key.

[assembly: AssemblyKeyFile("")] Used to specify the path to a key file.

[assembly: AssemblyKeyName("")] Used to specify the name of a key to use from the Crypto Service Provider (CSP).

If you are going to sign all your assemblies, then the AssemblyKeyName is the best option as it does not require you to remember a path to the key file each time you create a new project. It’s much easier to remember a simple name associated with the key. Here’s how you would sign an assembly using the CSP:

1) Generate a key pair:  sn -k MyCompany.snk

2) Install into the CSP:  sn -i MyCompany.snk MYCOMPANY

3) Use in your code:  [assembly: AssemblyKeyName(“MYCOMPANY”)]

 Thursday, April 21, 2005
by Nik Kalyani
Thursday, April 21, 2005 9:33:00 AM (Pacific Standard Time, UTC-08:00)

Just got word from ComponentArt that I am going to be a member of their MVP Program. Quite excited about collaborating with other developers to create cool ComponentArt-based solutions for DotNetNuke.

 

 Wednesday, April 20, 2005
by Nik Kalyani
Wednesday, April 20, 2005 7:31:38 PM (Pacific Standard Time, UTC-08:00)

There are many different solutions for creating tabbed content in HTML pages. For a number of my apps, I needed a simple, lightweight solution that was easy to use and to integrate with my apps. I came up with a simple solution and am sharing it here. Hopefully someone will find it useful.

The solution consists of a table containing the tabs and DIV’s representing the content for each tab. The tabs table has one cell for each tab with ID of “Tab_n” where n starts with 0 and increases by 1 for each tab. Add an onClick handler for each cell that calls tabClickHandler(n). Finally, create a DIV for each tab’s content and set its ID to be “Panel_n” where n starts with 0 and increases by 1 for each tab. Add a style attribute of “display: none” for all DIVs representing the tab content except for the first, which should be set to “display:block”.

<script language="javascript">
function tabClickHandler(tab)
  {
    i = -1;
    while (true)
    {
        i++;
        objTab = eval(document.getElementById("Tab_" + i));

        if (objTab)
        {
            objTab.className = (i == tab) ? "Speerio-SelectedTab" : ((i > tab) 
                                          ?
"Speerio-RightTab" : "Speerio-LeftTab");
            document.getElementById("Panel_" + i).style.display = (i == tab ? "block" : "none");
        }
        else break;
     }
  }
</script>

<style>
    .Speerio-Tabs { width:100%; color: black; font-family: Verdana,Arial,Helvetica,Sans Serif}
    .Speerio-TabLeftSpacer {width:10%;  BORDER-BOTTOM: 1px solid black}
    .Speerio-TabRightSpacer {width:10%; BORDER-BOTTOM: 1px solid black}
    .Speerio-SelectedTab { width:20%; BORDER-RIGHT: 1px solid black; BORDER-TOP: 1px solid black; BORDER-LEFT: 1px solid black}
    .Speerio-LeftTab {cursor: hand; width:20%;  BORDER-TOP: 1px solid #cccccc; BORDER-LEFT: 1px solid #cccccc; CURSOR: hand; BORDER-BOTTOM: 1px solid black; background-color: #eeeeee}
    .Speerio-RightTab {cursor: hand; width:20%;  BORDER-RIGHT: 1px solid #cccccc; BORDER-TOP: 1px solid #cccccc; BORDER-LEFT: medium none; CURSOR: hand; BORDER-BOTTOM: 1px solid black; background-color: #eeeeee}
    .Speerio-TabLabel { font-size: 8pt; font-weight: bold; color: black; font-family: Verdana,Arial,Helvetica,Sans Serif}
</style>

<table cellspacing="0" cellpadding="2" border="0" align="center" class="Speerio-Tabs">
 <tr>
  <td class="Speerio-TabLeftSpacer">&nbsp;</td>
  <td id="Tab_0" class="Speerio-SelectedTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(0)">
   <span class="Speerio-TabLabel">ABC</span></td>
  <td id="Tab_1" class="Speerio-RightTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(1)">
   <span class="Speerio-TabLabel">DEF</span></td>
  <td id="Tab_2" class="Speerio-RightTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(2)">
   <span class="Speerio-TabLabel">GHI</span></td>
  <td id="Tab_3" class="Speerio-RightTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(3)">
   <span class="Speerio-TabLabel">JKL</span></td>

  <!-- Add as many additional cells corresponding to tabs here -->
  <td class="Speerio-TabRightSpacer" align="right">&nbsp;</td>
 </tr>
</table>
  <!-– Add a DIV for each tab’s content here -->

<div id="Panel_0" style="display:block" width="100%">Contents of the first tab</div>
<div id="Panel_1" style="display:none" width="100%">
Contents of the second tab
</div>
<div id="Panel_2" style="display:none" width="100%">
Contents of the third tab
</div>
<div id="Panel_3" style="display:none" width="100%">
Contents of the fourth tab</div>


 

 

RSS feed
Search and Links
Bling

View Nik Kalyani's profile on LinkedIn

Contact me: nik*kalyani.com (replace "*")

TechBubble
www.flickr.com
This is a Flickr badge showing public photos from techbubble. Make your own badge here.
Statistics
Total Posts: 214
This Year: 32
This Month: 0
This Week: 0
Comments: 238
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008
Nik Kalyani
Sign In
All Content © 2008, Nik Kalyani