Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Saturday, 21 March 2020

Windows Script Host and JScript Revisited

Background

This is a small example Windows Script File (WSF) that can be used in certain work flows.

This work flow involves dealing with files that are created in the In folder.

Due to some issue with a process upstream in this work flow, some of the files that appear in the In folder are missing their file suffix. For reasons outside the scope of this article, this cannot be rectified upstream, and, because it is known that these files all should have a .txt suffix, this script appends the required suffix where there is no suffix.

The script is supplied with an In and an Out folder path.

The Code

<job>
    <script language="JScript">
        // Technology Is Not Dull 2020
        // Get in and out folders as named arguments
        var InFolder = "";
        var OutFolder = "";
        if(WScript.Arguments.Named.Exists("in")){
            InFolder = WScript.Arguments.Named("in");
        }
        if(WScript.Arguments.Named.Exists("Out")){
            OutFolder = WScript.Arguments.Named("Out");
        }
        // If there is an in and an out parameter
        if(OutFolder!="" && InFolder!=""){
            // Create objects to get the files and copy them
            var objFSO=WScript.CreateObject("Scripting.FileSystemObject");
            var objFolder = objFSO.GetFolder(InFolder);
            var colFiles =objFolder.Files;
            // Remove any trailing '\' in supplied Out path
            OutFolder = objFSO.GetFolder(OutFolder);
            // For each file in the In folder
            for(var objEnum = new Enumerator(colFiles); !objEnum.atEnd(); objEnum.moveNext()) {
                sFileName = objEnum.item();
                sOutName = OutFolder +"\\";
                // This assumes that any file with no file suffix
                // is actually a .txt file and adds the suffix for the copied filename
                if(objFSO.GetExtensionName(sFileName) == "")
                {
                    sOutName = sOutName + objFSO.GetFileName(sFileName) + ".txt";
                }
                else
                {
                    sOutName = sOutName + objFSO.GetFileName(sFileName);
                }
                // Copy the file (overwriting any existing file)
                objFSO.CopyFile (sFileName,sOutName,true);
            }
            // Quit with value 0
            WSH.Echo("Done");
            WSH.Quit(0);
        }
        // Else there are one or more missing parameters
        //so quit with error
        else
        {
            WSH.Echo("Missing Named Parameter(s)");
            WSH.Quit(1);
        }
    </script>
</job>

Operation

The script is tested with a folder structure based on "C:\Some Folder\Documents\Javascript\test folders" with two sub folders 1 and 2.

Folder 1
Folder 2

The parameters are named using /<name>:<value>.

C:\Some Folder\Documents>cscript JScriptExample.wsf /In:"C:\Some Folder\Documents\Javascript\test folders\1" /Out:"C:\Some Folder\Documents\Javascript\test folders\2\"
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

Done

C:\Some Folder\Documents>

As you can see the files have been copied with the suffix added to the file without the suffix.

References

A brief look at JavaScript on various systems including Windows Script Host can be found here.

Sunday, 29 December 2019

YouTube Videos part 2

Having now set up an IIS/ASP server, now it is time to use it to set up your YouTube videos.
As noted in the previous post, ASP files comprise conventional HTML combined with server side Javascript code.

The JavaScript functions can be in separate included files. This allows the code to be easily reused.
The calls to the functions can then be made within the main file as required:

<% videolist="I68GG96bSYQ:Christmas lights,I68GG96bSYQ:More Chrismas,I68GG96bSYQ:Not Christmas";
Response.Write(makebuttons(videolist));
Response.Write(makeplaylist(videolist));

Server Side Functions

Create a file called makebuttons.asp.
There are three functions.
The first one assembles a button similar to that in the previous post.
The second takes a list of Youtube video IDs and their titles and assembles a button for each of the pairs.
The third function assembles the same list into YouTube playlists.
<%
function makebutton(index,buttonsource,playsource,buttonID,videotitle){
   result="";
   result=result +"<div class='videobuttoncontainer'>";
   result=result +"<img src='" +buttonsource+"' alt='Title' class='image' width='100%' onclick='setPlayList("+index.toString()+")' />";
   result=result +"<div class='videobuttonoverlay'>";
   result=result +"<img class='videobuttonicon' src='"+playsource+"' id='"+buttonID+"' onclick='setPlayList("+index.toString()+")' alt='"+videotitle+"' title='Play video: "+videotitle+"' oncontextmenu='copytoClipboard("+index.toString()+")' />";
   result=result +"</div>";
   result=result +"<span id='buttontext' class='buttontext'>"+videotitle+"</span>";
   result=result +"</div>";
   return result;
}
function makebuttons(videolist){
   result="";
   videos=videolist.split(",");
   for(ix =0;ix<videos.length;ix++){
  videoitem=videos[ix].split(":");
  result=result+makebutton(ix,"assets/button.png","assets/play.png", videoitem[0],videoitem[1]);
   }
   return result;

}
function makeplaylist(videolist){
   result="";
   videos=videolist.split(",");
   videoitem=videos[0].split(":");
   result=result+"'" +  videoitem[0]+"?playlist=";
   for(ix =1;ix<videos.length;ix++){
  videoitem2=videos[ix].split(":");
  result=result+','+videoitem2[0]
   }
   result=result+"'";
   for(ix =1;ix<videos.length;ix++){
  videoitem=videos[ix].split(":");
  result=result+",'" +  videoitem[0]+"?playlist=";
  for(iy =ix;iy<videos.length;iy++){
 videoitem2=videos[iy].split(":");
 result=result+','+videoitem2[0]
  }
  for(iy =0;iy<ix;iy++){
 videoitem2=videos[iy].split(":");
 result=result+','+videoitem2[0]
  }
  result=result+"'";
   }
   result="<script>playlists=["+result+"]</script>";
   return result;
}
%>

New Client Side functions

There are two pieces of code that will be used client side. The first is effectively the same as that used in the client side example. The second piece sets up a capability to copy the path to the video within the page to the clipboard.
<script>

function setPlayList(aPlaylist){
//alert(playlists[aPlaylist]);
youtubePlayer = document.getElementById("youtube_video");
youtubePlayer.src="https://www.youtube.com/embed/"+playlists[aPlaylist] + "&rel=0&autoplay=1";
}

function copytoClipboard(videonum){
result=window.location.href;
hashbit="";
querybit="";
newquery="";
starthash = result.indexOf("#");
startquery=result.indexOf("?");
if(starthash>0){
hashbit=result.slice(starthash);
result=result.substring(0,starthash)
 }
 else{
 hashbit="#demo";
 }
if(startquery>0){
querybit=result.slice(startquery).slice(1);
querybits=querybit.split("&");
result=result.substring(0,startquery)
foundVideo=false;
for(ix=0;ix<querybits.length;ix++){
endname=querybits[ix].indexOf("=");
if(querybits[ix].substring(0,endname)=="video"){
newquery=newquery+"video="+videonum.toString() +"&";
foundVideo=true;
}
else{
newquery=newquery+querybits[ix] +"&";
}
}
if (!foundVideo){
newquery=newquery+"video="+videonum.toString() +"&";
}
if(newquery.length>0){
newquery=newquery.slice(0,newquery.length-1);
}
result=result+"?"+newquery;

}
else{
result=result+"?video="+videonum.toString();
}
result=result+hashbit;
var copything=document.getElementById("copything")
copything.value=result;
copything.select();
copything.setSelectionRange(0, 99999);
}
</script>

The Main ASP file

The main ASP file is modified from the original:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
.videoWrapper {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.videoWrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.videoDisplay {
float: left;
width: 85%;
}
.videoList {
float: left;
width: 15%;
opacity:1;
}

.videobuttoncontainer {
position: relative;
width: 100%;
max-width: 400px;
}
.videobuttonoverlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
opacity: 0.25;
transition: .3s ease;
}

.videobuttoncontainer:hover .videobuttonoverlay:hover {
background-color: red;
opacity: 0.8;
color: white;
}
.videobuttonicon {
color: white;
font-size: 100px;
position: absolute;
top: 30%;
left: 40%;
width:25%;
height:auto;
text-align: center;
}
.buttontext{
opacity:1.0;
position:absolute;
bottom:4px;
left: 4px;
font-size: small;
color:white;
}
.buttontext:hover{
color:white;
}

</style>
<!-- #include file="makebuttons.asp" -->
<!-- #include file="makebuttons_clientside.asp"-->
</head>
<body>
<table width="100%">
<tr>
<th border="1" width="5%"></th>
<th border="1">
Test stuff
</th>
<th  width="5%">

</th>
</tr>
<tr>
<td>Ignore this</td>
<td border="1">
<div class="row">
<div class="videoList">
<% videolist="I68GG96bSYQ:Christmas lights,I68GG96bSYQ:More Chrismas,I68GG96bSYQ:Not Christmas";
Response.Write(makebuttons(videolist));
Response.Write(makeplaylist(videolist));
%>
<input type="text" value="Hello" id="copything">
</div>
 </div>
   <div class="videoDisplay">
 <div class="videoWrapper">
<iframe  id="youtube_video"
src="https://www.youtube.com/embed/I68GG96bSYQ"
frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
</div>
</div>
</div>
</td>
<td>Ignore this</td>
</tr>
</table>
</body>
</html>

When browsed to, the result is as follows:

Friday, 27 December 2019

My First ASP Page

ASP or Active Server Pages was a Microsoft web service in the early days of dynamic web pages. Though generally no longer a cutting edge technology, it is still used in a surprisingly large number of web sites.

Setup

Most Windows computers can host Internet Information Services (IIS). It is not installed by default but can be activated using the "Turn Windows features on or off" dialogue box. You can get to that either through the Control Panel application or by searching for it.


You will need to select down to the optional features to activate the ASP option.

By default ASP expects VBScript to be the default server side language, this can be changed when you start IIS.

ECMAScript is a synonym for Javascript or Jscript.
To make life easier for debugging, you can set "Send Errors To Browser" to true. This sends informative error messages rather than "This is broke". You do not want to have this set in a live environment as it makes your site extremely vulnerable to attack.

Hello World

This is a simple ASP page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
     <title>ASP Test page</title>
    </head>
    <body>
     <h1>Hello World</h1>
    </body>
</html>

So far, so HTML.

What you can do is run code at the server rather than just serve up a fixed page.

Hello World .ASP

The difference between a static HTML page and an ASP page is the Active part.
To define code that will run on the server, you need to put it between <% %>.
You can also include other files within your page. This is very useful as you can define standard parts of your web site in one location, and then reuse them on different pages.
For this you use the #include command inside HTML comments:

<!-- #include file="include-filename.asp" -->

The timeline of inclusion is that the included files are added to the file before any code is executed, so it is not possible to conditionally include file content - this does not work:

<% if(condition){%>
<!-- #include file="this-file.asp" -->
<% } %>

Remember this, otherwise you will get annoyed with it.

The first "active" ASP page will extend the previous example to print out the time.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>ASP Hello World page</title>
    </head>
    <body>
        <h1>Hello World</h1>
        <p>It is <%t=Date();
            Response.Write(t);
            %></p>
    </body>
</html>

When you first go to this page, it will display the current time. When you refresh the page, it will have the new (current) time.

The Response.Write  adds the parameter content to the page content (similar to a print or console.write command). It is possible to shorten a Response.Write(x) to <%=x%>.

Hello You

Now the previous example did make the page more dynamic, but does not really make it interactive.

For that we need two new ideas:

The Form.

A form is a block of HTML. If there is a Submit button, any selected, entered or clicked values are sent back to the web address identified by the action attribute. If no address is provided, the values are sent back to the address of the page. 

The page with the form does not need to be an ASP page, for that matter neither does the target page - however the target page does need to be one that can make use of the information being sent.

This form is simple and made up of four parts:
  • An enclosing form tag, it has an empty action attribute as it will be sending the data back to itself.
  • A text label asking you to enter your name.
  • An input of type text box for you to enter your name. It has a name attribute to identify it when it is sent. It also has a value attribute. It might seem counter-intuitive to give it a value as it is an input, but this will also put your entered name in the box after you send it (just in case you made a mistake). 
  • An input of type Submit. This has a value that will be displayed on the button. This sends the information to the address in the form's action attribute.

The Request object. 

The Request object contains all the assorted stuff that is being sent to the web page (such as the information being entered on the form).

In this case we will be asking it for the value of the myname parameter, which is supplied by the tag with the name attribute "myname". If no parameter is supplied, the value of Request("myname") is an empty string.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>ASP Form test page</title>
    </head>
    <body>
        <h1>Hello 
            <%
            personName = Request("myname");
            if(personName!=""){
                Response.Write(personName)
            }
            %>
        </h1>
        <form action="">
            Please enter your name: <input type="text" name="myname" value="<%=personName%>" />
            <input type="submit" value="Enter" name="go" />
        </form>
    </body>
</html>

When you first visit the page it will say Hello, and ask for your name.

When you enter your name and click on Enter, the display will change to say Hello <your name>, it will also add your name into the input text box.

You will also notice the URL will have changed to include the name and values of the parameters (the elements within the form):
http://localhost/form.asp?myname=Fred&go=Enter
You can actually tailor the parameters in the address bar of the browser, try changing Fred to Ned.
This can be useful, but it does rather expose the workings of your cunningly crafted web site.

This is because the default behaviour of the form tag is to use the method "GET". This does have some advantages, you can see that it is working, and you can edit the input in the address bar (great while testing). The disadvantages are that it can look messy, and that the parameters are on display and are limited by length.

The alternative is the method "POST". This packages up the parameters' names and values and sends it separately from the address.

Change the form tag's attributes to include a method = "POST" attribute:
<form action="" method="POST">
Save and refresh your page in your browser.
The problem is that you can enter the new name, but it continues to display the old one. This is because the address includes the existing (GET) parameters, and it overrides POST parameters.
Clear the existing information from the address, and it will behave as you expect.

It is important to be aware that a value sent via GET will override a value sent by POST.

There is a way round that, but that is for a second post.



Tuesday, 15 October 2019

YouTube Videos

Programmed YouTube Video viewer

Youtube takes a lot of the effort out of hosting and displaying videos. If you are happy for Google to have access to the information about who is watching your videos, then it makes sense to use them to host them.

One problem is making it easy to control how the videos are displayed and allow the viewer to select what they want to watch.

Server Side

For later.

Client Side

It is a matter of Style

Getting the video to display properly, especially if you are using a responsive style web site is a bit more complicated than Google makes out, as the default height is about 150 pixels, which is a bit embarrassing.

The solution from CSS-Tricks based on work by Thierry Koblentz sets the height as a percentage of the width. When the page resizes, the height is recalculated. Any IFRAME inside it is scaled to 100% to fill the container.

.videoWrapper {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.videoWrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
The next bit is getting the play button to hover over the images.
  .container {
  position: relative;
  width: 100%;
  max-width: 400px;
  }
  .overlay {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  height: 100%;
  width: 100%;
  opacity: 0.25;
  transition: .3s ease;
  }

  .container:hover .overlay {
  background-color: red;
  opacity: 0.8;
  }
  .icon {
  color: white;
  font-size: 100px;
  position: absolute;
  top: 30%;
  left: 40%;
  width:25%;
  height:auto;
  text-align: center;
}

The Buttons

The buttons are contained in two nested div objects.
The first (of class 'container') holds the YouTube thumbnail image.
The second (of class 'overlay') holds the play button image and has the onclick event handler described below.
<div class="container">
   <img src=http://i1.ytimg.com/vi/xxxxxxxxxxx/mqdefault.jpg 
     alt="Title" class="image" width='100%' />
   <div class="overlay">
     <img class="icon" src="play.png" onclick='setPlayList(1)'/ >
   </div>
</div>
The overlay has a normal opacity of 0.25, so the button image displays faintly. When the mouse hovers over the image, the background changes to red and the opacity increases to 0.8.

Video Selection

The video choice requires an array containing the video to play plus a rotating set of the other videos. That is a coding exercise for server side and another time.
<script>
playlists =['xxxxxx?playlist=yyyyy,zzzzz', 'yyyyy?playlist=zzzzz,xxxxx'];
 </script>

Each play button has an onclick event that calls the setPlayList function with a number which selects the element from the array described above.
<script>
function setPlayList(aPlaylist){
youtubePlayer = document.getElementById("youtube_video");
youtubePlayer.src="https://www.youtube.com/embed/"+playlists[aPlaylist] + "&rel=0&autoplay=1";
}
</script>

The autoplay parameter starts the video playing, the rel = 0 prevents videos from other channels from being displayed,

References

https://support.google.com/youtube/answer/171780?hl=en
https://css-tricks.com/NetMag/FluidWidthVideo/Article-FluidWidthVideo.php
https://alistapart.com/article/creating-intrinsic-ratios-for-video/

Monday, 23 September 2019

Javascript

JavaScript is a high-level scripting language that has become one of the core components of the World Wide Web.
Originally used client side in a user’s browser, it has migrated back to the server and is also used for general scripting purposes.

Windows

JavaScript is one of many languages supported by the Windows Scripting Host (WSH).

Hello World

The following is a JavaScript program using the Windows Scripting Host.
The file is called helloworld.js.

WSH.Echo("Hello world");
WSH.Quit();

Create the file with your favourite plain text editor (Notepad or better, but not a word processor, they tend to add lots of tat).

Save the file.

Bring up the command line interface (search for cmd).

Use the change directory command to move to where you have saved the file (if you have spaces in the folder names, enclose the path in double quotes).

To execute the file type:
cscript helloworld.js
This is what you will get (Windows 10 machine - YMMV)

C:\some\folder\tree>cscript helloworld.js
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

Hello world

C:\some\folder\tree >
An alternative is to use a WSF file (.wsf). This requires the <job> or <package> tags around the script. Because WSF files could contain any supported language (or indeed multiple languages) you need to define the language within a script tag.
<job>
    <script language="JScript">
        WSH.Echo("Hello world");
        WSH.Quit();
    </script>
</job>

C:\some\folder\tree >cscript helloworld.wsf
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

Hello world

C:\some\folder\tree >

HTML

The following is extremely simple.
The script is executed when the page is loaded but before it is displayed. It is possible to execute the JavaScript after the page has loaded or in response to some event.
<!DOCTYPE html>
<html>
    <head>
        <title>Javascript in HTML</title>
    </head>
    <body>
        <p>Testing Javascript</p>
        <script language="JScript">
            alert("Hello world!");
        </script>
    </body>
</html>
Save the file as helloworld.html.
Because this is displayed in your browser, the display will vary.

Linux

Raspberry Pi

From Raspbian Stretch onwards, most standard installs of Raspbian come with node.js installed as standard.
You can check if it is installed by running:
node -v
On the command line. If it is installed, it will return the version number.
If your installation does not have node.js, install using:
sudo apt-get install node
sudo apt-get install npm
The program is just one line:
console.log("Hello world!");
Using terminal, change the directory to where you have saved the file, you can run it by typing:
node helloworld.js
The result will be similar to:
pi@raspberrypi:~/Documents/JavaScript $ node helloworld.js
Hello world!
pi@ raspberrypi:~/Documents/JavaScript $

Useful functions

Splitting Strings

The following is a Windows specific example.
WSH.Echo("Test code");

WSH.Echo(splitString("-2MKptcmt1Q,W3XlnfNPk6I,dRYRcM-HHvY"));

 function splitString(aString){
    WSH.Echo(aString);
    result = "";
    anArray=[];
    anArray = aString.split(",");
    for(ix = 0;ix<anArray.length;ix++){
        result = result +"*" +(anArray[ix])+"*";
    }
    return result;
}


References

https://en.wikipedia.org/wiki/JavaScript
https://en.wikipedia.org/wiki/ECMAScript
https://www.w3schools.com/js/default.asp
https://www.w3schools.com/jsref/default.asp

https://en.wikipedia.org/wiki/Windows_Script_Host
https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cscript
https://docs.microsoft.com/en-us/previous-versions//98591fh7(v=vs.85)

https://www.instructables.com/id/Javascripting-Your-RaspberryPi/


Monday, 22 October 2018

Browser size - Javascript

Sometimes when you are building a web page it is useful to know what the browser size is, so you check it will display correctly if it is on a desk top, lap top, tablet or mobile.

The following Javascript will put the browser client size as the title.
<html>
<head>
    <script>
        function titleIsSize() {
            document.title = "" + document.body.clientWidth + " pixels.";           
        }
    </script>
</head>
<body  onresize="titleIsSize()"  >
</body>
</html>