Monday, September 28, 2015

[JScript] jQuery without IE

For those who looked, this is mod of plasticgrammer's post. Most of the comments are Google Translates attempts at the original programmer's Japanese.

The single biggest difference from the previous posting is that Internet Explorer is not called into to manage jQuery. Instead the htmlfile object is used.

jQuery expects a few global symbols (it is after all a browser library), so the beginning of the code declares them: document, window etc. Then the jQuery file is dragged across the internet and eval'd in the context of the script.

You'll notice that the jQuery version is quite ancient. This is another problem with this approach. I imagine that it's just a case of declaring some more public symbols. If anyone tries this, please let me know how recent you can go before things break. And if you succeed in using more recent jQuery libraries, please do let me know what modifications were required.
// To prepare, such as window or document to the global name space
(function (url) {
  if ("undefined" === typeof document)
    document = new ActiveXObject("htmlfile");
  document.write("<" + "html" + ">" + "<" + "/html>"); // this important
  if ("undefined" === typeof window)
    window = document.parentWindow;
  if ("undefined" === typeof alert)
    alert = function (s) {
      return window.alert(s);
    };
  if ("undefined" === typeof confirm)
    confirm = function (s) {
      return window.confirm(s)
    };
  if ("undefined" === typeof location)
    location = window.location;
  if ("undefined" === typeof navigator)
    navigator = window.navigator;
  if ("undefined" === typeof window.ActiveXObject)
    window.ActiveXObject = ActiveXObject;

  var XMLHttpRequest = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
  var o = XMLHttpRequest.open("GET", url, false);
  var s = XMLHttpRequest.send();
  eval(XMLHttpRequest.ResponseText);
  return true;
})("http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.js");
Now a bit of demo code. Notice how we tell JScript what $ means. Possibly that could go in the earlier block of code as yet another global.
var $ = window.$;

// Operation example of a simple jQuery object
WScript.Echo($("<" + "div" + ">").attr("a", "fo").get(0).outerHTML);

// Course alert even I can use.
alert($("<" + "div" + ">").attr("a", "fo").get(0).outerHTML);
(Blogspot didn't like seeing div etc as markup, thus the odd syntax).

© Copyright Bruce M. Axtens, 2015

[JScript] Using jQuery in IE

IE is the browser we all love to hate. It's also scriptable and so inevitably ends up being considered for various tasks.

The following fragment demonstrates the first of two mechanisms I've found for instantiating jQuery in an IE session under script control.
var oIE;
  try {
    oIE = new ActiveXObject("InternetExplorer.Application");
  } catch (errIE) {
    WScript.Quit();
  }
  oIE.Visible = false;

  oIE.Navigate("http://www.example.com");
  while (oIE.Busy) {
    WScript.Sleep(100);
  }

  WScript.Sleep(1000); // could be less

  var DOM = oIE.Document;
  var scr = DOM.createElement('script');
  scr.src = "https://code.jquery.com/jquery-2.1.4.min.js";
  DOM.head.appendChild(scr);

  var $ = DOM.parentWindow.jQuery;
The above code is sliced out of a current project. We navigate to the target, create a script tag, point it at jquery's CDN, and append it to the document's head. Then we define a $ to point to oIE.Document.parentWindow.jQuery.

The same technique can be applied to any page, really. I have a bookmark in my browser that has a name of InjectjQuery and an address of
javascript:var script = document.createElement('script');script.src = "https://code.jquery.com/jquery-2.1.4.min.js"; document.head.appendChild(script);

The second method for instantiating jQuery in IE can be found at plasticgrammer. I had difficulty with it, but got it working. It has some good things which I'll discuss in the next posting.

© Copyright Bruce M. Axtens, 2015

Sunday, September 27, 2015

[VB6] Installation in Windows 10

I'm running Windows 10 Home, 64bit. We have legacy code that needs to be modified and recompiled. Folk who find such discussions unpalatable should read no further.

I found help for this process in two places:Forty Pound Head's
Install VB6 on Windows 8 and CodeProject's How to install Visual Studio 6 on Windows 7 professional 64bit

(There's another blurb at
SoftwareOK that I'm hanging on to just in case I meet any unforseen gotchas.)

In my case, the creation of the zero length file, MSJAVA.DLL, had to be done in C:\Windows\System32 rather than C:\Windows. I had put it in the latter and ended up with, for a while, the looping install scenario described by fortypoundhead.

The recommendation
Ensure Data access components is deselected. If it's not deselected, setup will hang!

— fortypoundhead

was interesting because the Enterprise installer asserted that the data access tools are required. However, I went with the recommendation as the thought of a hanging setup didn't appeal.

I turned off SourceSafe, FoxPro and InterDev as well. I opted to have environment vars stored in VCVARS32.BAT rather than have them registered: I feared mayhem might occur given the pre-existing Visual Studio Community 2013 and Community 2015 installs.

The install was very speedy.

The installer insisted on a reboot at the end. But before I said yes to that, I set the relevant Compatibility Settings for VB6.EXE as per fortypoundhead, started VB6.EXE, wrote a quick button on a form app, compiled it to EXE and then ran it from outside VB6. No problems at all!

Now I will have to run the various updaters and install some helper apps. But so far it looks like we could get another 17 years out of VB6.


© Copyright Bruce M. Axtens, 2015

Saturday, September 26, 2015

[mLite] Arbitrary Precision Integers and Logarithms

Yeah yeah, there's something 'bout you baby I like

-- Status Quo, 1981.

It's a bit worrisome when I quote musicians from last century, but I do like mLite. Granted, I don't dream about it, but it's fun to figure out how to do things in a functional way.

In this case I was wanting to solve the RosettaCode challenge
Arbitrary-precision integers (included) which has one calculate 5^4^3^2, find out how many digits there are and then display the top 20 digits and bottom 20 digits. Bignums weren't a challenge, as they are supported natively in mLite. No, the biggest challenge was figuring out how many digits. 5^4^3^2 is an extremely large number, with 183231 digits and all of my first attempts did not complete even after running for a day.

mLite's creator,
Nils M. Holm, suggested I use logarithms. However, logarithms aren't built in to mLite yet, so I had to cook up my own logarithm library. So how do you calculate logarithms by hand? I dug around a bit and found an article on Quora entitled How can we calculate the logarithms by hand without using any calculator?. Harald Overbeek's description formed the basis for the mLite code below.
fun ntol (0, x) = if len x < 1 then [0] else x
       | (n, x) = ntol (n div 10, (n mod 10) :: x)
       | n      = ntol (n, [])
;
ntol converts a number to a list.
fun powers_of_10 9 = 1000000000
               | 8 = 100000000
               | 7 = 10000000
               | 6 = 1000000
               | 5 = 100000
               | 4 = 10000
               | 3 = 1000
               | 2 = 100
               | 1 = 10
               | 0 = 1
;
powers_of_10 is a precomputation of all the powers I knew I'd encounter during the calculation. This alone sped up the code a lot.
fun size (c, 0) = c
       | (c, n > 9999999999) = size (c + 10, trunc (n / 10000000000))
       | (c, n)              = size (c +  1, trunc (n / 10))
       | n                   = size (     0, trunc (n / 10))
;
size works out the number of digits by keeping track of how many calculations it takes to divide the number by 10 until the remainder is zero.
fun makeVisible L = map (fn x = if int x then chr (x + 48) else x) L
makeVisible turns an array of digits into a string, with handling for non-numeric elements
fun log10 (n, 0, x) = ston  implode  makeVisible ` rev x
        | (n, decimals, x) =
            let val n' = n^10;
              val size_n' = size n'
            in 
              log10 (n' / powers_of_10 size_n', decimals - 1, size_n' :: x)
   end
        | (n, decimals) =
            let
              val size_n = size n
            in
              log10 (n / 10^size_n, decimals, #"." :: rev (ntol size_n) @ [])
            end
;
Then log10 ties it all together. The second parameter specifies the number of digits precision. Below I've specified 6.

Being somewhat mathematically challenged, I still had to figure out how to use the library I had made to calculate the digits. Thankfully, there's a
mathematics community on StackExchange. They helped me out a lot. Now I could work out the number of digits in the number by rounding up the result of log10(5) * 4^9 (seeing as 3^2 is 9).

Thus I ended up with
val fourThreeTwo = 4^3^2;
val fiveFourThreeTwo = 5^fourThreeTwo;

val digitCount = trunc (log10(5,6) * fourThreeTwo + 0.5);
print "Count  = "; println digitCount;

val end20 = fiveFourThreeTwo mod (10^20);
print "End 20 = "; println end20;

val top20 = fiveFourThreeTwo div (10^(digitCount - 20)); 
print "Top 20 = "; println top20;
Which, after 1 hour and 9 minutes on an AMD A6 cpu, gave
>mlite -f 5p4p3p2.m
 Count = 183231
 End 20 = 92256259918212890625
 Top 20 = 62060698786608744707 
A nice change from my day job which centres around JavaScript, Peloton, HTML, PHP and the odd bit of T-SQL. Enjoy!

© Copyright Bruce M. Axtens, 2015

Monday, September 21, 2015

[Sound] Using SOX to convert WAV to MP3

I was sent a rather large WAV file today: a delightful composition by Ivodne Galatea called 'Ingenious Pursuits'. She's also sent me the score so I can learn to play it myself.

At 91MB I thought I might have a go at converting the WAV to MP3. Enter
Sound eXchange which very comfortably converted the WAV using the following extremely simple command:
sox "Ingeniuous Pursuits automated.wav" Ingeniuous.mp3
SoX can do way more than this with sound files. The above barely scratches the surface of the amazing power of this tool.

Having said that, the Windows installer did not include a copy of the LAME (Lame Aint an MP3 Encoder) DLL (libmp3lame.dll). I had to go hunting for that and even when I found it I had to rename it, as every ZIP I downloaded called the dll lame_enc.dll (I found downloads at
spaghetticode.org and buanzo.org). After that everything worked fine.

SoX is great. Highly recommended. I don't know the author and no one paid me to write this.


© Copyright Bruce M. Axtens, 2015

Friday, September 18, 2015

[CMD] PUSHD to path in clipboard

I use WinClip to get things in and out of the clipboard when doing stuff on the command line. (I grew up on CP/M, MP/M II and VAX VMS, so command line is usually where it's at for me.)

Occasionally, I have a path in the clipboard that I want to use as the target for a CD (or, more often, a PUSHD). I just cooked up the following .CMD script using WinClip. It uses the /F qualifier on the FOR command to iterate through the stdout of winclip -p and PUSHD to what it finds.

So what happens, you may ask, if the clipboard contains more than one line? If the paths are fully qualified then you end up in the folder defined by the last line. Otherwise, you end up in the folder defined by the first line and you see a pile of error messages about not being able to find the subsequent folders.
@echo off
 :: PUSHCLIP.CMD
 for /f "delims==" %%f in ('winclip -p') do pushd %%f
Enjoy! If you want to amplify the script to better handle unforeseen inputs, go right ahead. Share the result here if you feel so inclined.

© Copyright Bruce M. Axtens, 2015

Thursday, September 17, 2015

[JavaScript] SQLServer Date to jsDateTime

I forgot to include in the last posting the reverse function that takes a SQLServer Epoch value and converts it to a JavaScript datetime number.
function SQLServerDateTojsDateTime(a) {
  return Math.ceil((a * 86400 - 2208988800) * 1000);
 }
An example of its use (from a jscli session):
> d = new Date()
 Thu Sep 17 12:03:58 UTC+0800 2015
 > d.valueOf()
 1442462638627
 > n = jsDateTimeToSQLServerDateTime(d)
 42262.169428553236
 > m = SQLServerDateTojsDateTime(n)
 1442462638627
 > new Date(m)
 Thu Sep 17 12:03:58 UTC+0800 2015
Enjoy!

© Copyright Bruce M. Axtens, 2015

Wednesday, September 16, 2015

[JavaScript] Converting JavaScript DateTime to SQLServer DateTime

I've had the need occasionally to convert JavaScript datetime to SQLServer datetime numeric Epoch value. The following two routines do the job. In both cases I'm assuming that UTC is being used as taking timezones into consideration is a bit more work.

First jsDateTimeToSQLServerDate which takes a JavaScript Date object and forms a SQLServer Epoch integer.

   function jsDateTimeToSQLServerDate(d) {

      var SQLServerEpoch = 2208988800;
      var dMilli = d.valueOf();
      var dSec = dMilli / 1000;
      var nEpoch = SQLServerEpoch + dSec;
      var nEpochDays = nEpoch / 86400;
      var nEpochDate = Math.ceil(nEpochDays);
      return nEpochDate;
    }
The second also takes a JavaScript Date object but this time includes the time returning an Epoch floating point number.
   function jsDateTimeToSQLServerDateTime(d) {
      var SQLServerEpoch = 2208988800;
      var dMilli = d.valueOf();
      var dSec = dMilli / 1000;
      var nEpoch = SQLServerEpoch + dSec;
      var nEpochDays = nEpoch / 86400;
      var nEpochDate = Math.ceil(nEpochDays);
      return nEpochDays;
    }
The Closure compiler abbreviates those routines signficantly, as below. You may want to use this code in preference as the above was done to demonstrate the relationships in the conversion process.
   function jsDateTimeToSQLServerDate(a) {
      return Math.ceil((2208988800 + a.valueOf() / 1E3) / 86400);
    }
    function jsDateTimeToSQLServerDateTime(a) {
      a = (2208988800 + a.valueOf() / 1E3) / 86400;
      Math.ceil(a);
      return a;
    }
    ;
An example invocation:
   var now = new Date();
    // now currently
    // Wed Sep 16 22:52:09 UTC+0800 2015
    jsDateTimeToSQLServerDate(now);
    // gives
    // 42262
    jsDateTimeToSQLServerDateTime(now);
    // gives
    // 42261.61955061343
I hope this helps. I may be back here myself next time I need this routine.

© Copyright Bruce M. Axtens, 2015

[PHP] Spread camel case

My work has me doing Wordpress plugins from time to time. The following snippets comes from one of those projects. It's text a camel-case string and inserts spaces in front of capitals and numbers, turning the item into some more human-readable.
function spreadCamel($txt) 
 {
  $temp = substr($txt,0,1);
  for ($i = 1; $i < strlen($txt); $i++) {
   $c = substr($txt, $i, 1);
   if (ctype_upper($c) || ctype_digit($c)) {
    $temp = $temp . " ";
   }
   $temp = $temp . $c;
  }
  return $temp;
 } 
An example invocation:
echo spreadCamel("MyDogHasFleasAbout1Million");
the result of that being
My Dog Has Fleas About 1 Million
I hope that helps someone. There may be a better/faster/more efficient way of doing it. If there is, please post in the comments.

© Copyright Bruce M. Axtens, 2015