MacBook, defective by design banner

title:
Put the knife down and take a green herb, dude.


descrip:

One feller's views on the state of everyday computer science & its application (and now, OTHER STUFF) who isn't rich enough to shell out for www.myfreakinfirst-andlast-name.com

Using 89% of the same design the blog had in 2001.

FOR ENTERTAINMENT PURPOSES ONLY!!!
Back-up your data and, when you bike, always wear white.

As an Amazon Associate, I earn from qualifying purchases. Affiliate links in green.

x

MarkUpDown is the best Markdown editor for professionals on Windows 10.

It includes two-pane live preview, in-app uploads to imgur for image hosting, and MultiMarkdown table support.

Features you won't find anywhere else include...

You've wasted more than $15 of your time looking for a great Markdown editor.

Stop looking. MarkUpDown is the app you're looking for.

Learn more or head over to the 'Store now!

Monday, November 30, 2015

Kendo UI Templates use a simple templating syntax we call "hash templates."

Hey, Telerik~ A quick word to the wise: It's probably worth including a link to where you actually explain that syntax everywhere you have a template property in your examples.

The info at their API docs for column templates is okay, but not great. The info at their templating explanation is pretty crucial for you to understand live examples of customizing grid display.

The four grid column template/rendering formats

Let's quickly list the different ways to produce column names and values.

  1. Column name and value spit directly into the column.
    • columns: [ "id", "field1", "field2" ]
  2. Change the title to whatever you want.
    • columns: [ "id", { title: "Whatever I want", field: "field1" } ]
  3. Use a Telerik template.
    • { title: "File Preview", template: '<img src="#:field3#" alt="Thumbnail for asset id \\##:id#"" />' },
    • This is a little messier than the others. Note the "hash template" format.
    • You put whatever column value you want after the #:, sort of like a Razor template.
    • Then close with another #.
    • To escape a "real" #, you can use \\#, an escaped escape char (\), then the #.
    • Again, their full docs on templating are here.
  4. Use a javascript function.
    • template: function(dataItem) { return "<strong>" + kendo.htmlEncode(dataItem.name) + "</strong>"; }
    • Note here that dataItem is just whatever's on the row.
    • There are no built-in properties I can find other than dirty and uid.
    • dirty is a boolean if the value's been changed, I assume.
    • uid is a GUID.
      • Honestly, I'm not sure where uid comes from, other that that's it's obviously Telerik.
      • That is, uid is not in my JSON payload.
    • NOTE: Functions don't work for title.
      • Blows up at a replace call.
      • From the telerik minimized code:
        • f.title&&(e+=i.attr("title")+'="'+f.title.replace(/'/g,"'")+'" '),

Quick critique ;^)

Though I don't mind overloading parameters, at some point, it seems like you should've sunk your time into one or the other -- either allow functions or develop some crazy templating system. Personally, I prefer number four over three, as it doesn't require any Telerik-specific knowledge.

Telerik has an interesting way of creating sort of simplest case examples, but would benefit from a sort of kitchen sink style demo that slowly builds on itself of the grid. "Here's a grid with a straight column, a column with a formatter, and a column with template." You know, like this:

Composite example with each column renderer type

$(document).ready(function() {
    $("#gridTest").kendoGrid({

        //==========================================
        // Methods to produce columns.
        //==========================================
        columns: [
        // 1. Raw column name and value.
            "id",
        // 2. Change title, raw value.
            { title: "Whatever I want", field: "field1" },
        // 3. Use a Telerik template for value.
            {
                title: "File Preview", 
                template: '<img src="#:field2#" alt="Thumbnail for \\##:id#"" />' 
            },
        // 4. Use a javascript function for value.       
            {
                title: "Test function",
                template: function(dataItem)    {
                    return "<strong>" 
                        + kendo.htmlEncode(dataItem.field3) 
                        + "</strong>";
                }
            }
        ],
        //==========================================
        // End of column fun.
        //==========================================

        filterable: true,
        sortable: true,
        pageable: true,
        height: 550,

        dataSource: {
            // http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.read
            transport: {
                read: {
                    url: "./GetInfo",
                    dataType: "json",
                    contentType: "application/json",
                    type:"POST"
                },
                parameterMap: function (data, type) {
                    // Removed this for now, but it's needed; see below.
                }
            },
            schema: {
                model: { id: "id" }
            },
            pageSize: 20,
            serverPaging: true,
            serverFiltering: true,
            serverSorting: true
        },

        lastProp: null
    });
});

See, Telerik? Was that so hard? (They have so many examples this is probably in there somewhere, but it sure isn't where I'd expect it: At the top of columns.template explanation.


Just for fun, let's also return to the parameterMap function. The way Telerik grids send parameters for information requests is sort of strange. If you're pushing something up to a .NET MVC controller, you might not want stuff that looks like sort[0][field] before it's turned into a request. That's kind of hard to deserialize.

Instead, the answer is that you deserialize it yourself, on the client, in JavaScript, then reserialize into something easy to hand to your controller. I'm going to reorganize everything into a params object that I throw into a JSON string and return from parameterMap. My new string is what'll get passed back up.

parameterMap: function (data, type) {
    // By default, the grid sends a somewhat peculiar set of parameters with requests
    // that do server-side sorting. For example the sort { field: "age", dir: "desc" }
    // is sent (by default) as:
    //      sort[0][field]: age
    //      sort[0][dir]: desc
    // The parameterMap function allows us to send it up in a different format.
    // http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#methods-sort
    var params = {
        skip: data.skip,
        take: data.take,
        page: data.page
    };

    if (data.sort)  {
        params.sort = {
            field: data.sort[0].field,
            dir: data.sort[0].dir
        };
    }
    // console.log wrapper >>> utils.logit("Param type: " + type);
    return JSON.stringify();
}

Kinda ugly default, but a reasonable way to customize things.

Labels: , ,


posted by ruffin at 11/30/2015 01:01:00 PM
Tuesday, November 24, 2015

You can find 'em here:
https://msdn.microsoft.com/en-us/library/ms190324.aspx

Or read 'em from that page here:

type char(2)
 
Object type:
AF = Aggregate function (CLR)
C = CHECK constraint
D = DEFAULT (constraint or stand-alone)
F = FOREIGN KEY constraint
FN = SQL scalar function
FS = Assembly (CLR) scalar-function
FT = Assembly (CLR) table-valued function
IF = SQL inline table-valued function
IT = Internal table
P = SQL Stored Procedure
PC = Assembly (CLR) stored-procedure
PG = Plan guide
PK = PRIMARY KEY constraint
R = Rule (old-style, stand-alone)
RF = Replication-filter-procedure
S = System base table
SN = Synonym
SO = Sequence object
 

Applies to: SQL Server 2012 through SQL Server 2016.
SQ = Service queue
TA = Assembly (CLR) DML trigger
TF = SQL table-valued-function
TR = SQL DML trigger
TT = Table type
U = Table (user-defined)
UQ = UNIQUE constraint
V = View
X = Extended stored procedure


So to check if a table exists (from here):

IF OBJECT_ID('TableName', 'U') IS NOT NULL
DROP TABLE TableName;

Voila. QED. Or something like that.



And just to complete what I was fiddling with today, here's how to create the two different types of ids, autoincrementing INT (or other INT type) and GUIDs:

TableId [uniqueidentifier] CONSTRAINT DF_SerialID DEFAULT newsequentialid(), -- GUID, natch
... or...
TableId INT IDENTITY(1,1), -- INTige

Labels: , , ,


posted by ruffin at 11/24/2015 09:03:00 AM
Monday, November 23, 2015

Why should you use DateTimeUTC and not DateTime in your SaaS systems? 4guysFromRolla actually has a pretty good answer from 2007:

The primary advantage of storing date/time values in UTC is that it makes the data transportable. To see what I mean, imagine that following scenario: you have an eCommerce website that is being hosted in a web server located in the Pacific time zone (UTC -8) and this application stores the date and time orders were placed in server time. Say a user, Bob, makes an order on August 1, 2007 at 9:00 AM UTC -8. After many months of phenomenal growth, you decide to switch to a larger web hosting company, one on the east coast where the time zone is UTC -5. Since the date/time is stored in server time, Bob's previous order still shows that it was made on August 1 2007 at 9:00 AM. But since we are now in UTC -5, it is as if Bob's order was made three hours earlier than it really was (since when it was 9:00 AM on August 1, 2007 in the west coast it was really 12:00 noon on the east coast).

One way around this, you might contend, is to execute a SQL query that adds three hours to the order date for all records in the table. Something like:

UPDATE Orders SET

OrderDate = DATEADD(hh, 3, OrderDate)

And such an approach would suffice... for this situation. But imagine that you moved to a web hosting company situated in the US state of Arizona, where daylight savings is not observed. E[s]p. Now you would have to write a more complex UPDATE statement that adjusted the hours based on whether the order date fell within daylight savings. Ick.

...

Things like daylight savings further complicate working with dates and times, but UTC does not observe any time zone, simplifying things a tiny bit. [emph mine -mfn]

To make a long story short, you have two choices:

  • Use DataTimeUTC and use built-in converters to get "local" time, usually on the client
  • Pick another "native" time zone for your system, and prepare to maintain your own converters

Seems an easy enough choice to me.

Labels: , , ,


posted by ruffin at 11/23/2015 02:43:00 PM
Saturday, November 21, 2015

I'd like to pretend that online gambling sites aren't a big deal, but I'm having a more difficult time believing that now. The way FanDuel and DraftKings took over every advertising spot on ESPN and NFL games really woke me up a little. There has to be insane amounts of cash going in. What did they recently brag they were paying out each week? Seventy-five million? Wonder what percent they don't pay out?

But gambling is gambling. Or playing games of *cough* skill (Are carnival games games of skill? Aren't they? The basketball hoop is just smaller right? If you're winning thrice the time if you're Mark Price, then it's skill, even if that's just 2%, right?) for money is playing for money. Either way, it's not something I'm interested in or really care much about. If you're not risk adverse enough to skip these games, well, you get what's coming, I guess. I mean, you can get in worse trouble selling stocks short, right? Isn't that just as much skill and luck? If you can do one, why not the other?

But then you see a story like this one from CBS News, and I, at least, started doing more thinking. PayPal handles those payments, and gets a taste. Yahoo apparently is invested in similar services. And then, the real kicker is the disclosure at the bottom of the page:

Editor's Note: CBS has an investment in FanDuel of less than 1 percent of that company's value.

Add to that Robert Kraft, and NFL Team Owner, and Fox Sports, an NFL broadcaster, both own parts of these companies, and you've got a real conflict.

Ouch. Big Business is still Big Business, no matter how little you want to pretend it affects you. Look at the people who not only have dogs in this fight, but who do get juice from its winnings:
  • The owners of the teams who are being bet (or whose players performances determine who wins a game, whichever way you look at it)
  • The teams' broadcasters (Fox) 
    • I'd add ESPN to this. So many ads, even native reads on Mike & Mike, who wouldn't stop saying that these things were games of skill, and how much they enjoyed playing. If I have to hear one more stupid comparison to state lotteries or poker games... I'd like to hear how often the hosts played & what they won/lost.
  • The news outlets that both broadcast and report on them (Yahoo and CBS)
  • The banks that provide payment to them (PayPal)
Two of these -- banks and journalists -- I don't want getting anywhere near these "games of chancy skill". And don't discount Fox Sports and ESPN as journalists. They provide entertainment first, sure, but you don't have to be Bill Simmons to wonder when their advertisers become their true customers, to the detriment of their producing hard-hitting pieces for their viewers, and anyone counting on their role as press to perform the last check and balance on corruption in sports.

Not that gambling could corrupt sports, could it?

If we keep mixing dollars between banks, journalism, and sports, sports betting could make Glass-Stegall's repeal look like a walk in the park.

Labels: ,


posted by ruffin at 11/21/2015 10:53:00 PM
Friday, November 20, 2015

I'll try not to get too verklempt, but I finally hit my informal goal for StackOverflow: I received the [second] JSLint badge [SO's awarded].


It used to be difficult to program without googling answers to what were sometimes pretty straightforward questions -- it was more efficient -- and smarter -- to "borrow" and improve on something that'd already been through the crucible than coding "from scratch". Now, it's even more difficult to code without leaning heavily on StackOverflow.

It should also be hard to receive that much value without giving something back. Admittedly, I'm nowhere near as "giving" as one of my old coworkers, who is creeping up on 80,000 StackOverflow points as I blog. But you shouldn't feel good about benefiting from StackOverflow without finding some means of giving back.

For me, giving back was sitting on the JSLint tag. We started using JSLint at a company I worked with a while back, and I think I was one of our better JavaScript guys (ie, Whitaker, above, was pretty busy, so I guess I was second), so I got stuck with implementing JSLint as a company-wide blocking check-in test for TFS. I first got a Visual Studio JSLint extension working and configured like we wanted it, then I copied what it was doing and wrote a TFS rule using Noesis, the same engine that plugin used, to test files folks were checking in, slowly forcing us to JSLint our legacy code (though with exceptions for third-party libraries) as we edited files.

Looking back, I should've used Node, which would have been much easier, but Noesis didn't require any serious installation.

Anyhow, when you're the contact person for something like this, of course you also end up being the person who actually does much of the linting, as almost every time someone edited a file over a hundred or so lines, I'd get an email about how difficult and unfair the new policy [though I believe JSLinting code is a great idea, it was our dev manager's idea, so the unfair complaints were unf. misdirected!] was. With a few folks, after a few good tries to convince them otherwise, though I feel badly about it, I occasionally relented and gave fish rather than taught folks how to fish 'em up themselves. It was ultimately better for everyone to spend the time linting than arguing about whether they should learn to lint. And admittedly, some of those files were a mess, coded by employees who had left years ago, and having everyone in your company editing JavaScript regardless of their expertise in the language can be a bad policy. Some folks (I'm looking at you, most of the iOS team!) probably had no business being in the JavaScript files to begin with. (Note: I never so much as opened an Objective-C file while working at said company. ;^D)

Regardless, like Jim Morris pitching, the unofficial work meant I became pretty good at understanding JSLint. More importantly, JSLint was (and is!) a manageable tag on StackOverflow. I'd learned it was easy to get reputation at SO just by sitting on topics and being the first to answer, but that wasn't always the best way to learn, and seemed to be more gamification than "scholarship". It's the difference between sitting on jQuery and wishing you could sit on child jQuery selectors or DOM concatenation. But JSLint had that specificity built-in. It was a small pond, but active enough that you could actually contribute.



Overly long story a little shorter, here we are. I'm the second person in StackOverflow history!!!1!1!!2 to bag the JSLint badge. And boy, I did it the hard way (which is not a complement to me). The first guy to get it, James Allardice (who also has the JSHint badge) currently has 202 points answering 32 questions. I've got 101 for answering 57. I'd like to think James plowed up the ground pretty well with the obvious answers (I've gotten 24 of my points for being the first to document `ignore`, for instance), but still.

There are at least 20 people with more JSLint points than me, but since only one has 20 or more answers in there, I still get to be second badged JSLinter on SO. (TJ Crowder will be there soon, I think, but other than Quentin at 13, nobody else has 10 answers.) I also like that with the exception of the last two guys on the list, who essentially have the same rep as me, everyone else has 3k or more than me, many with tens of thousands more. It's good company.

Looks like my first JSLint answer was on 5 Feb 2013 (with my first question on 1 May 2012), when nobody had earned this tag yet. Just a little over two years since Allardice bagged the tag, and just over 33 months since I started, I get the second.

Nobody remembers the second schmoe on the moon, but that doesn't mean it wasn't enjoyable taking the trip.

Guess I'll keep watching JSLint, but (and I'd already kinda started relaxing) I'll be a little less likely to want to be FIRST! and more likely to just chime in when I have something good to add. Which is how StackOverflow should work.

Labels: , , , ,


posted by ruffin at 11/20/2015 01:44:00 PM
Friday, November 13, 2015


Sorry, this one cracked me up. Apparently, somewhere, some way, I've told iTunes not to go online to get CD track names, perhaps. When I tell it, "No, really, go get some track names," instead of a useful, but already insanely stodgy, "Allow iTunes a single-use exception to transmit information about the tracks from your CD to the Internet," I get ye old "No Error" error.



Again, Apple's not impressing with its test case creativity. QA fail.

So, of course, I attached my external DVD drive to my iMac and imported there, no problems. What a mess iTunes has become.

Labels: , , , ,


posted by ruffin at 11/13/2015 09:35:00 PM
Wednesday, November 04, 2015

From here:

SOLUTION: in Windows 7 [and 8, as it turns out -mfn], press and hold Shift and right click on the grouped icon that you want to open all of it's grouped windows in a cascade arrangement, then click on Cascade . All the windows of this particular program will open in cascade exactly as in XP.

Wow. Yes please. I used to use the right-click shortcut to cascade all the windows, but didn't realize you could do it one application at a time, I don't think. I often leave open too many browser windows, and it's nice to bring them all to the front where they're easily eyeballed before shutting them out.

Labels: ,


posted by ruffin at 11/04/2015 10:46:00 AM
Tuesday, November 03, 2015

document.body.insertBefore(
    document.createElement("test1"), document.body.childNodes[0]
);

That could've been easier. I think. Bottom line is that you're taking the parent node, and inserting a new node (first parameter) before the existing (second param). Here, of course, I'm doing it to the body. Sub document.body with the node o' your choice.

EDIT: So here's a slightly nicer way of inserting html, since the above won't actually parse HTML in the string...

function insertAsFirstChild(strHtml, nodeWithChildren)    {
    // If strHtml isn't wrapped in tags, we probably want to put into
    // a span so that we can accept html. CreateTextElement would push
    // out the text as is, showing markup in the page.
    var newSpan, strTag, strEndTag;

    newSpan = document.createElement("span");
    if (!nodeWithChildren)  {
        nodeWithChildren = document.body;
    }

    if (
        0 === strHtml.indexOf("<")
        && strHtml.length - 1 === strHtml.lastIndexOf(">")
        && strHtml.indexOf("</" > -1)
    ) {
        strTag = strHtml.substring(1, strHtml.indexOf(">"));
        strEndTag = strHtml.slice(strHtml.lastIndexOf("</")+2, -1);

        if (strTag && strTag === strEndTag)   {
            newSpan = document.createElement(strTag);
            strHtml = strHtml.substring(strHtml.indexOf(">")+1, strHtml.lastIndexOf("</"));
        }
    }

    newSpan.innerHTML = strHtml;
    nodeWithChildren.insertBefore(newSpan, nodeWithChildren.childNodes[0]);
}

Labels: ,


posted by ruffin at 11/03/2015 10:46:00 AM
Monday, November 02, 2015

Man, TFS is just plain ole inferior to git. First, you can't merge two branches that aren't in direct relation to each other, so no leapfrogging your parent to get to your grandparent, or your great-uncle, or whatever it is that you've got. That's bad enough.


But today, my office's internet connection died, and I can't even annotate offline. Nor can I see the diff between what I've got now and what I checked in ten minutes ago. Not to mention I lose the ability to create checkins while I'm offline. If I want to create a safe rollback spot in TFS and I'm offline, I'm toast. Man, that's just sad.

(EDIT: Inserted an image of it happening again... I can't even get history on my files. ARGH. And you don't even have to lose your network completely, just your connectivity (dumb word) to your TFS server.)

git has a complete copy of your repo on each node that's using it, at least up to the last pull and for branches you're tracking locally. That lets you have everything you could've found on a server right there, locally, ready to go, as if nobody had made any checkins since you last, well, checked in on things.

Which worst case is worse? No access to any history whatsoever if you don't have a network connection, or complete history up until the last time you checked in? (Duh.)

So what's your single point of failure in TFS? (All together now: Your TFS server.) What's your single point of failure in git? HAHAHA!!! That's right, trick question. As soon as you push your repo somewhere, there isn't one.

sigh Sheesh, Microsoft, can we toss TFS already? Just get into the GitHub game, integrate your git service with Visual Studio preferentially if you have to, and keep on selling. Because boy, you sure look dumb supporting your glorified Visual SourceSafe in 2015 when there are absolutely better free options out there.

Labels: ,


posted by ruffin at 11/02/2015 02:43:00 PM

<< Older | Newer >>


Support freedom
All posts can be accessed here:


Just the last year o' posts:

URLs I want to remember:
* Atari 2600 programming on your Mac
* joel on software (tip pt)
* Professional links: resume, github, paltry StackOverflow * Regular Expression Introduction (copy)
* The hex editor whose name I forget
* JSONLint to pretty-ify JSON
* Using CommonDialog in VB 6 * Free zip utils
* git repo mapped drive setup * Regex Tester
* Read the bits about the zone * Find column in sql server db by name
* Giant ASCII Textifier in Stick Figures (in Ivrit) * Quick intro to Javascript
* Don't [over-]sweat "micro-optimization" * Parsing str's in VB6
* .ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); (src) * Break on a Lenovo T430: Fn+Alt+B
email if ya gotta, RSS if ya wanna RSS, (?_?), ยข, & ? if you're keypadless


Powered by Blogger etree.org Curmudgeon Gamer badge
The postings on this site are [usually] my own and do not necessarily reflect the views of any employer, past or present, or other entity.