Kevin walked past my laptop the other day and noticed an ugly looking hot-dog-inspired-colored window, and asked - what the hell is that?
This is what it was:
Ugly? Absolutely. Useful? I think so. I thought it deserved some explanation, so here goes.
Colors
I purposely use the bright colors to distinguish the different elements, along with the exact space each element takes up, and how each element lines up. This is especially helpful for labels.
This is purely to assist with the design of the form in Clarify's User Interface Editor. These colors are not displayed at runtime in the Clarify Client.
For example, here's the same form, with the same controls, but without the colors. Notice that its hard to tell what's what, and how much space each control takes up.
With everything colored, I can easily see the full position, size, and alignment of each control. This makes designing the form much easier.
I then use a little ClearBasic code to color the elements nicely at runtime. For example:
'Color the titles and summaries
For index = 1 To 10
'Color the titles
Set label = Me.GetControlByName ("title" & cstr(index))
label.ForeColor = "hyperlink"
If index Mod 2 <> 0 And index <= numberOfResults Then
label.BackColor = "alternateRow"
Else
label.BackColor = "row"
End If
'Color the summaries
Set label = Me.GetControlByName ("summary" & cstr(index))
label.BackColor = "row"
If index Mod 2 <> 0 And index <= numberOfResults Then
label.BackColor = "alternateRow"
End If
Next index
I often do this in web development as well, adding a background-color style to div elements, allowing me to easily see the size and position of each div.
Hiding controls off-screen
A common technique is to "hide" unused controls off-screen. Expand the form, move those controls to the expanded area, and then shrink the form back to its original size. Those controls outside the visible area will not be seen by agents using the Clarify Client.
Uses of this technique include:
- Baseline controls that are not needed (Deleting these controls could cause runtime errors)
- Controls used for debugging or testing
- Additional explanations
Here's my form, expanded, so you can see the "hidden" controls:
Also notice that I've added some additional labels.
One that says "In UI Editor, expand this form to the right for more info -->" This label has its visible property set to False, so its only visible in UI Editor, and will not be seen in the Clarify Client. This clues the next developer that they can expand the form, and see the "hidden" controls, along with some more information.
I've also added a groupbox and a label that explain what's going on with the form and the colors:
Not only does it remind me what's going on when I revisit this form, but it also assists the next developer who works on this form.
Stacked Labels
You may notice the gray colored controls, which are behind the red & yellow controls. All 3 of these are labels. I've used the gray label to essentially give a left and right padding to the red and yellow labels.
You may also notice that only every other red/yellow label has a gray label behind it. This is allowing me to give a zebra effect to the results - coloring every other one.
This is how it looks at runtime in the Clarify Client:
It's just enough of a subtle color difference to separate each item, without being overbearing.
The Tab Order is important here. The gray background labels must come before the red and yellow labels, otherwise the gray label will render in front of, instead of behind, the red & yellow labels.
What are some of your UI Editor tips & tricks?
One of the best practices that ITIL brings to the party within Incident (case) Management is prioritization.
ITIL calls out 3 separate attributes: impact, urgency, and priority.
Impact: the measure of how business critical it is.
Urgency: a necessary speed of resolving an incident.
Priority: formulated from the combination of impact and urgency. Some formulate it as Priority = Urgency + Impact. Others use Priority = Urgency * Impact.
They key difference that ITIL presents with the concept of Priority versus the classic usage of Severity is that severity alone does not provide enough context for Prioritization. The urgency factor needs to be added to severity in order to provide an accurate understanding of how to prioritize activity.
Example of a priority coding system
Impact, Urgency, and Priority within Dovetail
Within Dovetail (and Clarify/Amdocs), Severity and Priority are provided, but not Impact. No worries, its easy to add this third attribute.
First, we'll add a custom field for the impact. A little SchemaScript using SchemaEditor does the trick.
<schemaScript xmlns="http://www.dovetailsoftware.com/2006/10/SchemaScript.xsd">
<addColumn name="x_impact" dataType="String" table="case">
<length>40</length>
</addColumn>
</schemaScript>
Second, we'll create a new User Defined Popup List to hold the Impact values. We'll use the Dovetail Admin UI to do this.
Third, we'll add a new drop-down list element to the case.asp page.
<% var x_impact=boCase('x_impact');%>
<%=BuildUserDropDownList("x_impact","x_impact",bReadOnly,x_impact,'')%>
Finally, we'll add the code to save the value when the case is saved in case2.asp.
fld_list.AppendItem("x_impact");
val_list.AppendItem(Request.Form('x_impact').Item);
type_list.AppendItem("String");
The case page, now with the 3 attributes:
We now have a drop-down for each attribute. But ITIL suggests that the Priority should be set based on the Impact & Urgency. Lets make that happen.
Dynamically set the priority within Dovetail Agent
First, we'll change the priority from a drop-down list to a readonly textbox. Comment out the priority select element, and then add the textbox:
<input type="text" class="clsTxt" name="priority" id="priority" value="<%=lPriority%>" readonly>
Second, we'll add some code to dynamically set the priority based on the impact and urgency. jQuery will help with this. We'll map the string values to a numeric weighting, multiply the 2 numeric weightings together to get the priority weight, and then use this to set the priority string value. We'll do this on page load, and also when either the Impact or the Urgency(Severity) drop-downs change.
function GetWeight(inputString){
if (inputString == "Medium") return 2;
if (inputString == "High") return 3;
return 1;
}
function SetPriority(){
var impact = $("#x_impact").val();
var urgency = $("#severity").val();
var weight = GetWeight(impact) * GetWeight(urgency);
if (weight > 6){
$('#priority').val("Critical");return;
}
if (weight > 4){
$('#priority').val("High");return;
}
if (weight > 2){
$('#priority').val("Medium");return;
}
if (weight > 1){
$('#priority').val("Low");return;
}
$('#priority').val("Planning");
}
$(document).ready(function(){
SetPriority();
$("#x_impact").change( function() {
SetPriority();
});
$("#severity").change( function() {
SetPriority();
});
})
Here's how the page looks now:
And changing either the Urgency or the Impact will dynamically set the Priority.
And there you have - an Incident Priority Automation Customization. (yikes, that sounds enterprisey. blurg.)
For the most part, Clarify is pretty easy to customize. Occasionally, you run into Clarify forms that just don't behave as you would expect. In particular, the "old" Clarify forms, that were all written in C, long before ClearBasic was considered - those can be problematic. ClearLogistics forms are also typically problematic - the initial ClearLogistics development team seemed to have their own way of doing things back then.
We recently assisted a customer with such an issue, and I'm sharing it here so hopefully it may help others in a similar situation.
Customizing the "Select Inventory Parts" form
The requirement at hand was to exclude inventory parts from a certain inventory location when selecting inventory parts - specifically, on Form 519 (Select Inventory Parts).
Here's the form, showing all inventory parts:
Lets say that we want to exclude those inventory parts that exist in location "12345".
Traditional approach
The traditional approach would be to get the list of records out of the grid (or the contextual object itself), loop through them, remove the ones that match, and repopulate the grid with the updated list of records.
Sub SELECT_Click() Me.DoDefault HideInventoryPartsInLocation "12345" End Sub Sub HideInventoryPartsInLocation(locationName As String) Dim partsList As List Dim origCount As Integer Dim partRecord As Record Dim index As Integer Set partsList = Cobj_part_inst.Contents origCount = partsList.Count For index = origCount-1 To 0 Step -1 Set partRecord = partsList.ItemByIndex (index) If locationName = partRecord.GetField ("location_name") Then partsList.RemoveByIndex index End If Next index cobj_part_inst.Fill partsList Cobj_TOTAL_NUM.Fill partsList.Count End Sub |
Unfortunately, this yield a Type Mismatch runtime error on this line:
Set partRecord = partsList.ItemByIndex (index)
A little debug code allows us to take a closer look at the the partsList variable:
MsgBox "partsList.ItemType: " & partsList.ItemType
The ItemType of this list is "long". We're expecting a list of records, not longs. And these longs aren't objids either. I would guess they're pointers.
No love. Lets try something else.
Another traditional approach
Another way to do this would be to do the query ourselves, excluding the parts we want to exclude, and then simply fill the grid.
Sub HideInventoryPartsInLocation(locationName As String) Dim br As New BulkRetrieve Dim partsList As List Dim gridList As List Dim origCount As Integer Dim index As Integer Dim obj As Record Dim recFilter As Record Dim str_part_number As String Dim str_mod_level As String Dim str_part_descr As String Dim str_part_serial_no As String Dim str_location_name As String Dim str_bin_name As String Dim str_container_id As String Dim ascDescString As String Dim ascDesc As Long Dim sortBy As String Set recFilter = Cobj_NEW_FILTER.Contents str_part_number = Trim(recFilter.GetField("part_number") ) str_mod_level = Trim(recFilter.GetField("mod_level")) str_part_descr = Trim(recFilter.GetField("part_descr")) str_part_serial_no = Trim(recFilter.GetField("part_serial_no")) str_location_name = Trim(recFilter.GetField("location_name")) str_bin_name = Trim(recFilter.GetField("bin_name")) str_container_id = Trim(recFilter.GetField("container_id")) br.SimpleQuery 0, "parts_view" br.AppendFilter 0, "hdr_ind", cbNotEqual, 1 br.AppendFilter 0, "hdr_ind", cbNotEqual, 3 br.AppendFilter 0, "location_name", cbNotEqual, locationName If (str_part_number <> "") Then br.AppendFilter 0, "part_number", cbLike, str_part_number & "%" End If If (str_mod_level <> "") Then br.AppendFilter 0, "mod_level", cbLike, str_mod_level & "%" End If If (str_part_descr <> "") Then br.AppendFilter 0, "part_descr", cbLike, str_part_descr & "%" End If If (str_part_serial_no <> "") Then br.AppendFilter 0, "part_serial_no", cbLike, str_part_serial_no & "%" End If If (str_location_name <> "") Then br.AppendFilter 0, "location_name", cbLike, str_location_name & "%" End If If (str_bin_name <> "") Then br.AppendFilter 0, "bin_name", cbLike, str_bin_name & "%" End If If (str_container_id <> "") Then br.AppendFilter 0, "container_id", cbLike, str_container_id & "%" End If ascDescString = ASC_DESC.Value ascDesc = cbDescending If ascDescString = "Ascending" Then ascDesc = cbAscending End If sortBy = GetStringAfterCharacter(SORT_BY_MBT.UserData, ".") sortBy = GetStringAfterCharacter(sortBy, ":") br.AppendSort 0, sortBy, ascDesc br.RetrieveRecords Set partsList = br.GetRecordList(0) cobj_part_inst.Fill partsList Cobj_TOTAL_NUM.Fill partsList.Count End Sub |
The UI doesn't like this approach at all. Notice that there are the right number of records (2) in the grid, but all of the data is empty:
and double-clicking one of these rows yields this helpful gem:
Ugh. Still no love. So now what?
Approach #1: RemoveByIndex
Perform the same query as the baseline List button. Same filtering, same sorting. Get the list of inventory parts data from the form (from the contextual object). Loop through the list of records that we retrieved from the database. If this is a record to be hidden, then remove it (by index) from the list of data retrieved from the form. Refresh the form data.
One warning here: the query must match exactly - same query, same filtering, same sort order, everything.
| Sub HideInventoryPartsInLocation(locationName As String) Dim br As New BulkRetrieve Dim partsList As List Dim gridList As List Dim origCount As Integer Dim index As Integer Dim obj As Record Dim recFilter As Record Dim str_part_number As String Dim str_mod_level As String Dim str_part_descr As String Dim str_part_serial_no As String Dim str_location_name As String Dim str_bin_name As String Dim str_container_id As String Dim ascDescString As String Dim ascDesc As Long Dim sortBy As String 'Get the user's filter criteria Set recFilter = Cobj_NEW_FILTER.Contents str_part_number = Trim(recFilter.GetField("part_number") ) str_mod_level = Trim(recFilter.GetField("mod_level")) str_part_descr = Trim(recFilter.GetField("part_descr")) str_part_serial_no = Trim(recFilter.GetField("part_serial_no")) str_location_name = Trim(recFilter.GetField("location_name")) str_bin_name = Trim(recFilter.GetField("bin_name")) str_container_id = Trim(recFilter.GetField("container_id")) 'Perform the same query as the List button's default action br.SimpleQuery 0, "parts_view" br.AppendFilter 0, "hdr_ind", cbNotEqual, 1 br.AppendFilter 0, "hdr_ind", cbNotEqual, 3 If (str_part_number <> "") Then br.AppendFilter 0, "part_number", cbLike, str_part_number & "%" End If If (str_mod_level <> "") Then br.AppendFilter 0, "mod_level", cbLike, str_mod_level & "%" End If If (str_part_descr <> "") Then br.AppendFilter 0, "part_descr", cbLike, str_part_descr & "%" End If If (str_part_serial_no <> "") Then br.AppendFilter 0, "part_serial_no", cbLike, str_part_serial_no & "%" End If If (str_location_name <> "") Then br.AppendFilter 0, "location_name", cbLike, str_location_name & "%" End If If (str_bin_name <> "") Then br.AppendFilter 0, "bin_name", cbLike, str_bin_name & "%" End If If (str_container_id <> "") Then br.AppendFilter 0, "container_id", cbLike, str_container_id & "%" End If 'Set up the ascending/descending sort order ascDescString = ASC_DESC.Value ascDesc = cbDescending If ascDescString = "Ascending" Then ascDesc = cbAscending End If 'set up the sort by sortBy = GetStringAfterCharacter(SORT_BY_MBT.UserData, ".") sortBy = GetStringAfterCharacter(sortBy, ":") 'In my testing, baseline Clarify uses location_name 'as the sort order for certain sortBy selections 'Not sure why. This may be data related. 'More exploratory testing may be warranted. If sortBy = "bin_name" Then sortBy = "location_name" If sortBy = "container_id" Then sortBy = "location_name" If sortBy = "fixed_bin_name" Then sortBy = "location_name" If sortBy = "mod_level" Then sortBy = "location_name" 'Apply the sorting criteria br.AppendSort 0, sortBy, ascDesc br.RetrieveRecords Set partsList = br.GetRecordList(0) 'Get the data from the form 'This will actually be a list of Longs, not a List of records 'More Clarify weirdness Set gridList = cobj_part_inst.Contents 'Loop through the list of records that we retrieved from the database 'If this is a record to be hidden, then remove it (by index) from the 'list of data retrieved from the form origCount = partsList.Count For index = origCount-1 To 0 Step -1 Set obj = partsList.ItemByIndex (index) If locationName = obj.GetField ("location_name") Then gridList.RemoveByIndex index End If Next index 'refresh the form data Cobj_TOTAL_NUM.Fill gridList.Count cobj_part_inst.Refresh End Sub |
Now we've excluded inventory parts in location "12345":
Success!
Approach #2: A duplicate grid
Here's another approach that should work as well.
- Setup a 2nd grid that looks like the baseline grid, along with a new LIST button.
- Add a new text box.
- Name: FILTER_BY_OBJID
- Destination COBJ: NEW_FILTER
- Destination field name: objid
- Hide this text box in the non visible part of the form.
- When the user clicks the custom LIST button, perform the same query as the baseline List button (bulkretrieve with the appropriate filters & sorting), and fill the cobj of the 2nd grid.
- On the click action for the 2nd grid:
- Get the objid of the selected row.
- Put this value in the FILTER_BY_OBJID textbox.
- Programmatically Click the baseline LIST button.
- Programmatically Click the first (and only) row in the baseline grid
- Clear the value in the FILTER_BY_OBJID textbox.
- On the double-click action for the 2nd grid:
- Programmatically Double-Click the first (and only) row in the baseline grid
We've used this approach in the past, for example on the Dispatch form (form 425).
The code for this is left as an exercise for the reader.
Summary
I hope you don't have to deal with this craziness, but if you do, hopefully you'll find this post helpful.
Sometimes you have to be a little creative, especially when dealing with forms that were written probably 15 years ago.
I've been diving into ITIL in more detail lately, understanding IT best practices, and how our products and processes match up with the guidance set forth by ITIL.
What is ITIL?
ITIL (IT Infrastructure Library) is a public framework that describes Best Practice in IT service management. It provides a framework for the governance of IT, the "service wrap", and focuses on the continual measurement and improvement of the quality of IT service delivered, from both a business and a customer perspective.
Certification
On occasion, people have mentioned ITIL certification, asking if our products are ITIL certified. So I started doing some exploring of ITIL certifications. The predominant company doing ITIL product certifications is PinkElephant. Their certification program is called PinkVerify.
From their website:
PinkVERIFY is a service Pink Elephant has provided to the IT Service Management (ITSM) community since 1999. The PinkVERIFY assessment criteria are based on several sources of industry knowledge and experience:
- High level ITIL tool requirements documented in ITIL and various publications from The Stationary Office (TSO - the official ITIL publishers)
- Practitioner input
- Software vendor input
- Pink’s own consulting experience
PinkVERIFY does not measure ITIL compliance. ITIL is not a standard, but rather a set of best practices that are adapted to address the specific needs of an organization. This being said, there are clear tool related practices that ITIL and other industry sources define as good practice; therefore, PinkVERIFY assesses a tool’s compatibility with the ITIL framework and these practices as they are defined within the criteria of this service.
Compatible = The software tool supports the PinkVERIFY criteria and ITIL terminology "out of the box" as part of its standard commercial offering.
ITIL Version 3 (V3)
In 2007, the Office of Government Commerce (OGC) released ITIL version 3 (V3), comprising a new set of five books that follow a Service Lifecycle approach. With the release of ITIL V3, Pink Elephant has developed a new PinkVERIFY certification scheme to reflect support of 14 processes within the Service Lifecycle.
The previous PinkVERIFY model was based on V2; however, all existing PinkVERIFY (V2) vendors with a current license agreement will continue to be recognized because all of the V2 processes are included in V3.
Certified compatibility
There is a set of self-assessments that product vendors can download to determine if a product will be ITIL compliant certified compatible. As we're a replacement for the Amdocs/Clarify product suite, and Amdocs is PinkVerfied, I expected us to match up as well. And we do. Except for one criteria:
Does the tool's use of terms and definitions align with ITIL terms and definitions?
ITIL terms include Incident, Problem, and Request for Change. We use similar, but not exact, terms such as Case, Solution, and Change Request.
I contacted PinkElephant to get some clarification. The answer from them was clear: the terms used must match exactly. For example, an "incident" must be an "incident". It cannot be a "case", "ticket", or "issue". This means that any system or business that uses the term "case", "issue", or "ticket" instead of "incident" would not pass the PinkVerify certification. This implies that any of these systems or businesses would not be ITIL "compatible".
I asked about Amdocs, since I know that they use "case", not "incident". The reply: This was not requirement in the previous version [ITIL V2] and this is why Amdocs is on this list. Under the new model the term Incident must be used.
So under ITIL V2, Amdocs is compliant certified compatible. But not under ITIL V3.
If we had gone through a certification process last year, we would be certified. But not now.
<rant>
I find this absurd. It shows that the focus is no longer on best practices, but on stringent following to terminology, independent of the ubiquitous language of the business. This is a great example of the issue with "certification" organizations - they tend to bear out as revenue generation vehicles, and have lost focus on raising the standards of quality for individuals, organizations, products, and the community as a whole.
Companies like Clarify (Amdocs) and Dovetail have been providing products that support (and in many cases lead the way) in best practices, and have been doing so for years. To say that they no longer meet the requirements for best practices (when in many ways we innovated in these best practices) shows the lack of connection from certification organizations to products, and to organizations that have implemented these products and deliver exemplary service on a daily basis.
This whole rant could be another post. Maybe at a later time...
</rant>
Focus on the best practices
Even though we're not ITIL "PinkVerified", our customers can (and many do) use our software to put in place and ensure the best practices that are at the heart of ITIL. More posts with specific details and examples on this will be coming soon.
I'm sure most of the ClearBasic brainiacs already know this (and I may have at one point), but the parameter to App.ShowSolution is a record of type "workaround", not a record of type "probdesc".
I probably knew this at one time, but its been a long time since I've done ClearBasic coding. I'm blogging this so that I can find it again in the future, with Google's help, of course.
If you call App.ShowSolution with a probdesc record, you get this ever-so-helpful pile of joy:
Cannot map specific relation (type 1 with relation -3).
Uh, yeah. Thanks. No, really. That was a helpful message. I'm in awe of your ability to render something so utterly useless. Freakin' programmers.
Working code example:
Sub ShowObject(objectType As String, idNumber As String)
If objectType = "solution" Then objectType = "probdesc"
Dim br As New BulkRetrieve
br.SimpleQuery 0, objectType
br.AppendFilter 0, "id_number", cbEqual, idNumber
'For solutions, we need to get the related workaround (the first one will do)
If objectType = "probdesc" Then
br.TraverseFromParent 1, "probdesc2workaround", 0
End If
br.RetrieveRecords
Dim listOfRecords As List
Set listOfRecords = br.GetRecordList(0)
If listOfRecords.Count = 0 Then
App.MsgBox "Unable to locate '" & objectType & "' with id of " & idNumber
Exit Sub
End If
Dim recObject As Record
Set recObject = listOfRecords.ItemByIndex(0)
If objectType = "case" Then
App.ShowCase recObject
Exit Sub
End If
If objectType = "probdesc" Then
Set listOfRecords = br.GetRecordList(1)
Set recObject = listOfRecords.ItemByIndex(0)
App.ShowSolution recObject
Exit Sub
End If
End Sub
Fun with Wordle, based on my tags.

A common customization within Clarify is to highlight priority cases in a wipBin or queue by setting their color. For example, make High Priority cases really stand out by coloring them red.
Clarify Classic Client
The ClearBasic Customization Guide has a couple of examples on how to do this with the Clarify Classic Client.
However, the customization was commonly applied to the Queue and wipBin forms - not the console.
As a reminder: to view the wipBin form, simply double-click a wipBin from the list in the left side of the console. Similarly, for the Queue form.
However, since about Clarify version 4, no one typically used these forms - the new console form was what was used. However, the console form can't be customized. I did a search on this to confirm my memory, and found my own post from 7 years ago. I hate when that happens.
Dovetail Agent
Highlighting rows in the console is really easy to do within Dovetail Agent.
- Add a CSS class to the case rows
- Add this class to the stylesheet, setting whatever styles/colors you want.
1. Add a CSS class to the case rows
Looking at $dovetailAgent/pages/console/console_main.asp, you'll see where the list of cases is looped over, writing out each one:
<%
while(boCaseView.EOF != true) {
%>
<tr id="...
Simply modify that, adding a new class to each row.
<%
while(boCaseView.EOF != true) {
%>
<tr class="casePriority<% =boCaseView('priority') %>" id="...
I've called mine casePriority + the priority. So if you have defined case priorities of High, Medium, and Low, then your class names will be casePriorityHigh, casePriorityMedium, and casePriorityLow.
2. Add this class to the stylesheet, setting whatever color you want.
Here, we'll simply modify $dovetailAgent/pages/stylesheets/webagent.css, and set the color of High priority cases to red. Notice that we're also setting any children anchors to the same color.
.casePriorityHigh, .casePriorityHigh a{
color:red;
}
And here's what it looks like:
How about a different style?
Lets set the background color and the font color to make it stand out even more:
.casePriorityHigh, .casePriorityHigh a{
color:#fff;
background-color:#f00;
}
You can use this same technique to color based on age, severity, condition, status, etc.
Remember to use color diligently, otherwise your application will end up looking like a 5th graders MySpace page.
Hope this helps.
Over on the 37signals blog, they're talking about some of their design decisions in tweaking their support request form.
In Clarify/Dovetail parlance, we have a Case Type and a Case Severity.
It seems 37signals have gone back and forth between the two, trying to capture both pieces of data in one element.
I do think there are 2 distinct values - the type of issue (billing, feature request, bug, etc.) and the severity/urgency of the issue (high, low, urgent, etc.), and I think their post shows the struggle when trying to combine them into one.
I do, however, appreciate that they are focused on keeping the submission form as streamlined, tight, quick, and as easy to use as possible.
I also like the fact that the Severity is focused on how the user feels, and uses natural language. For example, "Not a big deal, just need some help" is much better than "Low". Something to consider for Clarify/Dovetail implementations.
There's some interesting comments on that thread as well:
Check Dreamhost support form, they also have very funny dropdown with things like “OMG! Things are broken, people are dying” for really urgent matters etc…
I love the idea of the using emotional responses
Think about saying something like “Teach me. I’m not sure how this works… Rather than “I’m confused.” Selecting an option that says “I’m confused”, although it may be correct, just makes me feel dumb.
I also agree that Radio Buttons, generally, are a much better solution that Drop Downs. ESPECIALLY when the drop down is more verbose than, say, a State or Open/Closed/Cancelled state. Radio’s let me see all options at once without having to click. And drop-downs are HORRIBLE for people without good mousing ability. If the drop-down has a scroll bar, that’s about 1/2 dozen precise mouse-clicks for one selection. Ugh.
Good topic!
In the Dovetail SDK, there is a DeleteById method on the ClarifyGeneric object. This is useful when you know the objid of the record you want to delete. Perhaps the objid is posted to a web page, or you've pulled it out of a relation column from a different record.
DeleteById is available via the .NET interface. It is not available on an fcGeneric object via the COM interface.
How can we DeleteById in COM?
Simply use the AddForUpdate method, then do the Delete.
Example:
var objid = 268435459;
var modem = FCSession.CreateGeneric('modem');
modem.AddForUpdate(objid);
modem.Delete();
modem.UpdateAll();
John Resig (creator of jQuery) recently posted a bunch of his presentations online, focused on JavaScript and jQuery. Check 'em out.
I'm fast becoming a huge fan of jQuery, and we're now using it a lot more within Dovetail Agent.
Not only is the library itself cool - but the plethora of available plugins really make it rock.