Posts Tagged ‘client’

Free Computer Based VOIP

Monday, February 23rd, 2009

I’ve used a variety of computer based VOIP over the years. My current preference in this space is Skype as it’s free for computer-to-computer calls and even allows calls to and from regular phones (at a fee).

Video and text chat are also provided, as is ‘white-boarding’ with additional plugins.

Skype is available for most platforms, even mobile phones… I’ve found that while the Windows beta versions has some additional features, the Linux release is rock-solid.

http://www.skype.com/

There are also several hardware based solutions, like Vonage, available to replace your traditional phone service… perhaps we’ll cover that later.

Skype me!

Open Source FTP Client (and Server)

Tuesday, February 17th, 2009

At one time, FTP was the only means available to move large files, times have changed but the need still exists, especially for developers like myself.

For years I’ve happily used FileZilla for my FTP needs, the client is available on most platforms. There is also a server available for Windows as most Linux variants already provide FTP.

Happy file transfers!

Clientside Session Timeout’s

Monday, July 9th, 2007

There comes a time in web application development that you need to ‘timeout’ idle users. This comes in a variety of ways, here’s a few common reasons that you may desire this activity.

  • Security – you don’t want to leave sensitive data on a users screen when they’ve gone to lunch or left for the day.
  • Server Resources – persisting/keeping an active ’session’ available on the server takes resources (the exact type varies, but this is usually database, memory or file resources)
  • Server ‘enforced’ session timeout’s and the potential errors and lost data experienced by the users in that circumstance.

My personal approach to this has evolved over time, here’s a brief synopsis:

  1. Use standard server-side session timeout, often leading to a bad user experience when they loose data on a form submit.
  2. Use META REFRESH…where timeout is in seconds, in this example it’s 60 seconds (1 minute).
    <meta http-equiv="refresh" content="60;url=http://www.giantgeek.com/" />
  3. Use javascript 'timeout' (problem is that this is not 'measureable')
    
    <script type="text/javascript">
    setTimeout("javascript:myTimeout();",minutes*60000); // code minutes
    </script>
  4. Use javascript countdown timer and custom code event.

<html>
<head>
<title>Timeout example</title>
<script type=”text/javascript”>
var build=’testing’;
var timerID = 0;
var loadTime = null;
var stopTime = null;
function xload(){
loadTime=grvMillis();
grvWindowStatus(build);
grvSetTimeout();
}
function xclose(){
grvWindowStatus(”);
}
function grvMillis(){
return new Date().getTime();
}
// Start timer
function grvTimerUpdate(){
timerID = grvTimerClear(timerID);
if(loadTime == null){
loadTime=grvMillis();// Start Time
}
// Calculate Current Time in seconds
var timeNow = grvMillis();

var think = calcMinSec( calcTimeDiff(timeNow,loadTime) );
var remain = calcMinSec( calcTimeDiff(stopTime,timeNow) );
grvWindowStatus(build + ” ” + think + ” ” + remain );
timerID = setTimeout(”grvTimerUpdate()”,1000);
}
function calcMinSec(diff){
var mm = removeDecimal(diff/60);
var ss = zeroPad(removeDecimal(diff-(mm*60)),2);
return (mm + “:” + ss);
}
function calcTimeDiff(tmpStart,tmpStop){
var diff = (tmpStart – tmpStop)/1000;
return diff;
}
function removeDecimal(val){
var rc=”";
val = val + “”;
if(val!=”"){
var pos = val.indexOf(”.”);
if(pos > -1){
rc=val.substr(0,val.indexOf(”.”));
} else {
rc=val;
}
}
return rc;
}
function zeroPad(x,sz){
x = x + “”;
while(x.length < sz){
x = “0″ + x;
}
return x;
}
function grvTimerClear(x){ // this clears a timer from the queue
if(x){
clearTimeout(x);
x = 0;
}
return x;
}
function grvSetTimeout(){
var min=45; xID=grvTimeout(”javascript:grvTimeoutUSER()”,min); // EXAMPLE: this could be conditional!
stopTime = grvCalculateTimeout(min);
grvTimerUpdate();
}
function grvCalculateTimeout(mins){
var timeNow = grvMillis();
var exp = timeNow + (mins*60*1000);
var timeExp = new Date(exp).getTime();
return timeExp;
}
function grvTimeout(x,minutes){ // this sets a timer(request) in a queue
return setTimeout(x,minutes*60000);
}
function grvTimeoutUSER(){
alert(’Session Inactivity Timeout [USER]‘);
// DO WHAT YOU NEED TO HERE!}
function grvWindowStatus(txt){
window.defaultStatus=txt;
}
</script>
</head>
<body onunload=”xclose();” onload=”xload();”>
</body>
</html>

Another benefit of this last solution is that you also have access to the user “Think Time” and can therefore measure how long the user spends on a given page.

Cheers!

Clientside sorting of HTML TABLE in JavaScript

Monday, July 2nd, 2007

To save network bandwidth and server resources, it is often beneficial to to sorting of tabular data on the client. Here’s a workable solution that I’ve implemented several times.

Additionally, the need to make the solution ‘accessible’ to screen-reader technology and be backward compatible for users without JavaScript often become challenging.

There are some small “quirks” that you should be aware of…

  • The ’sortTable’ method uses the ID of the ‘TBODY’. Working to remove this requirement through better use of the DOM.
  • Will likely rework this to use Prototype framework which should result in smaller code.
  • Future enhancement will add a class to the header indicating the sort order of the column(s).
  • Creating the ‘SPAN’ for dates to be sorted is best handled by a taglib.
  • Large TABLE’s can take a significant amount of time to sort on a client, so it’s sometimes better to use a server side solution. Developers should use their experience to make this judgment call.

Example code (XHTML logic removed as usual for brevity):

<html>
<head>
<title>Client Side TABLE sorting</title>
<style type=”text/css”>
/* SCROLL */
div.scroll {width:100%;overflow:scroll;}
html>body div.scroll {width:100%;overflow:scroll} /* fixes IE6 hack */
/*** TABULAR ***/
tr.even {background-color:#eee;}
th.first, td.first {border-width:0;}
th.memo {text-align:left;padding:0;}
td.sorted {background-color: #f0f0f0;}
th.sorted {background-color: #99f;}
tr.even td.sorted { background-color: #d0d0d0; }
table.sorted tr.error { background-color:red; }
table.sorted tr.scroll th { background-color:#99f; text-align:left;}
table.sorted tr.scroll th a.sorted { color:#fff; text-decoration:none;}
table.sorted tr.scroll th a.sorted:hover { color:#fff; text-decoration:underline;}
</style>
<script type=”text/javascript”>
//—————————————————————————–
// sortTable(id, col, rev,xcase)
//
// id – ID of the TABLE, TBODY, THEAD or TFOOT element to be sorted.
// col – Index of the column to sort, 0 = first column, 1 = second column, etc.
// rev – If true, the column is sorted in reverse (descending) order initially.
// xcase – makes sort NOT case sensitive.
//
// The following is an example of jsp code for setting up the reformatted copy of a date
// field to allow sorting by date:
//
// <fmt:formatDate var=”varSortDate” value=”${searchResult.dateOfBirth}” pattern=”${sortableDateTimePattern}” />
// <span title=”<c:out value=”${varSortDate}” />”><fmt:formatDate value=”${searchResult.dateOfBirth}” pattern=”${dateFormatPattern}” /></span> | etc.
//
// The above code creates html code that contains, for example, a line like the following:
//
// <span title=”19640101000000″>01/01/1964</span>
//
// This sort routing concatenates the title element and the text node
// content to sort on the following string:
//
// 1964010100000001/01/1964
//
// This effective ignores the date containing slashes and used the yyyyMMdd etc. value.
// Fields that are not dates should not use the span element and title attribute, unless
// it is desired to sort on something other than the text node content.
//—————————————————————————–
function sortTable(id, col, rev, xcase) {
// Get the table or table section to sort.
var tblEl = xgetHelper(id);
if(tblEl != null){
// The first time this function is called for a given table, set up an array of reverse sort flags.
if (tblEl.reverseSort == null) {
tblEl.reverseSort = new Array();
// Also, assume the column zero is initially sorted.
tblEl.lastColumn = 0; // was 1
}

// If this column has not been sorted before, set the initial sort direction.
if (tblEl.reverseSort[col] == null)
tblEl.reverseSort[col] = rev;

// If this column was the last one sorted, reverse its sort direction.
if (col == tblEl.lastColumn)
tblEl.reverseSort[col] = !tblEl.reverseSort[col];

// Remember this column as the last one sorted.
tblEl.lastColumn = col;
// Set the table display style to “none” – necessary for Netscape 6 browsers.
var oldDsply = tblEl.style.display;
tblEl.style.display = “none”;
// Sort the rows based on the content of the specified column using a selection sort.

var tmpEl;
var i, j;
var minVal, minIdx;
var testVal;
var cmp;
for (i = 0; i < tblEl.rows.length – 1; i++) {

// Assume the current row has the minimum value.
minIdx = i;
minVal = getTextValue(tblEl.rows[i].cells[col], xcase);

// Search the rows that follow the current one for a smaller value.
for (j = i + 1; j < tblEl.rows.length; j++) {
testVal = getTextValue(tblEl.rows[j].cells[col], xcase);
cmp = compareValues(minVal, testVal);
// Negate the comparison result if the reverse sort flag is set.
if (tblEl.reverseSort[col])
cmp = -cmp;
// If this row has a smaller value than the current minimum, remember its
// position and update the current minimum value.
if (cmp > 0) {
minIdx = j;
minVal = testVal;
}
}

// By now, we have the row with the smallest value. Remove it from the
// table and insert it before the current row.
if (minIdx > i) {
tmpEl = tblEl.removeChild(tblEl.rows[minIdx]);
tblEl.insertBefore(tmpEl, tblEl.rows[i]);
}
}

// Make it look pretty.
makePretty(tblEl, col);

// Restore the table’s display style.
tblEl.style.display = oldDsply;
}

return false;
}

//—————————————————————————–
// Functions to get and compare values during a sort.
//—————————————————————————–

// This code is necessary for browsers that don’t reflect the DOM constants
// (like IE).
if (document.ELEMENT_NODE == null) {
document.ELEMENT_NODE = 1;
document.TEXT_NODE = 3;
}

function getTextValue(el, xcase){
var i;
var s;
var spanTitleValue;

// Find and concatenate the values of all text nodes contained within the element.
s = “”;

for (i = 0; i < el.childNodes.length; i++) {
if (el.childNodes[i].nodeType == 1) {
if (el.childNodes[i].nodeName != null) {
if (el.childNodes[i].nodeName == “SPAN”) {
spanTitleValue = el.childNodes[i].getAttribute(”Title”);
s += spanTitleValue;
}
}
else {
}
// Use recursion to get text within sub-elements.
s += getTextValue(el.childNodes[i]);
}
else if (el.childNodes[i].nodeType == document.TEXT_NODE) {
s += el.childNodes[i].nodeValue;
}
else {
// Gets here when element is empty! <span title=”"></span>
//alert(’Error — Not element or text node’);
}
}
return normalizeString(s, xcase);
}

function compareValues(v1, v2) {

var f1, f2;
// If the values are numeric, convert them to floats.

f1 = parseFloat(v1);
f2 = parseFloat(v2);
if (!isNaN(f1) && !isNaN(f2)) {
v1 = f1;
v2 = f2;
}

// Compare the two values.
if (v1 == v2)
return 0;
if (v1 > v2)
return 1
return -1;
}

// Regular expressions for normalizing white space.
var whtSpEnds = new RegExp(”^\\s*|\\s*$”, “g”);
var whtSpMult = new RegExp(”\\s\\s+”, “g”);

function normalizeString(s, xcase) {

s = s.replace(whtSpMult, ” “); // Collapse any multiple whites space.
s = s.replace(whtSpEnds, “”); // Remove leading or trailing white space.

var rc = s;
if(xcase == true) {
rc = s.toUpperCase();
}
return rc;
}

//—————————————————————————–
// Functions to update the table appearance after a sort.
//—————————————————————————–

// Style class names.
var rowClsNm = “even”;
var colClsNm = “sorted”;

// Regular expressions for setting class names.
var rowTest = new RegExp(rowClsNm, “gi”);
var colTest = new RegExp(colClsNm, “gi”);

function makePretty(tblEl, col) {
var i, j;
var rowEl, cellEl;

// Set style classes on each row to alternate their appearance.
for (i = 0; i < tblEl.rows.length; i++) {
rowEl = tblEl.rows[i];
rowEl.className = rowEl.className.replace(rowTest, “”);
if (i % 2 != 0)
rowEl.className += ” ” + rowClsNm;
rowEl.className = normalizeString(rowEl.className);
// Set style classes on each column (other than the name column) to
// highlight the one that was sorted.
for (j = 0; j < tblEl.rows[i].cells.length; j++) { /* was j=2 */
cellEl = rowEl.cells[j];
cellEl.className = cellEl.className.replace(colTest, “”);
if (j == col)
cellEl.className += ” ” + colClsNm;
cellEl.className = normalizeString(cellEl.className);
}
}

// Find the table header and highlight the column that was sorted.
var el = tblEl.parentNode.tHead;
rowEl = el.rows[el.rows.length - 1];
// Set style classes for each column as above.
for (i = 2; i < rowEl.cells.length; i++) {
cellEl = rowEl.cells[i];
cellEl.className = cellEl.className.replace(colTest, “”);
// Highlight the header of the sorted column.
if (i == col)
cellEl.className += ” ” + colClsNm;
cellEl.className = normalizeString(cellEl.className);
}
}
function xgetHelper(id){
var obj = null;
try {
obj = document.getElementById(id);
} catch(z) {
//var dummy=alert(”Error:” + z);
}
return obj;
}
</script>
</head>
<body>
<fieldset>
<div id=”ex_div” class=”scroll”>
<table summary=”" id=”names” class=”sorted” cellspacing=”0″>
<colgroup>
<col style=”first labels” />
<col style=”form_fields” />
</colgroup>
<thead>
<tr class=”scroll”>
<th scope=”col” id=”ex_0″><a href=”javascript:void(0);” class=”sorted” onclick=”return sortTable(’ex_sort’,0,true,true);”>Alpha</a></th>
<th scope=”col” id=”ex_1″><a href=”javascript:void(0);” class=”sorted” onclick=”return sortTable(’ex_sort’,1,true,true);”>Date</a></th>
<th scope=”col” id=”ex_2″><a href=”javascript:void(0);” class=”sorted” onclick=”return sortTable(’ex_sort’,2,true,true);”>Url</a></th>
</tr>
</thead>
<tbody class=”scroll” id=”ex_sort”>
<tr class=”even”>
<td headers=”ex_0″>Alpha</td>
<td headers=”ex_1″><span title=”20070701″>July 2, 2007</span></td>
<td headers=”ex_2″><a href=”javascript:void(0);” onclick=”alert(’view.php?userid=6′);”>5</a></td>
</tr>
<tr class=”odd”>
<td headers=”ex_0″>Bravo</td>
<td headers=”ex_1″><span title=”20050903″>Sept 3, 2005</span></td>
<td headers=”ex_2″><a href=”javascript:void(0);” onclick=”alert(’view.php?userid=8′);”>4</a></td>
</tr>
<tr class=”even”>
<td headers=”ex_0″>Charlie</td>
<td headers=”ex_1″><span title=”19700709″>July 9, 1970</span></td>
<td headers=”ex_2″><a href=”javascript:void(0);” onclick=”alert(’view.php?userid=4′);”>2</a></td>
</tr>
<tr class=”odd”>
<td headers=”ex_0″>Delta</td>
<td headers=”ex_1″><span title=”20001213″>Dec. 13, 2000</span></td>
<td headers=”ex_2″><a href=”javascript:void(0);” onclick=”alert(’view.php?userid=5′);”>3</a></td>
</tr>
<tr class=”even”>
<td headers=”ex_0″>Echo</td>
<td headers=”ex_1″><span title=”20010911″>Sept 11, 2001</span></td>
<td headers=”ex_2″><a href=”javascript:void(0);” onclick=”alert(’view.php?userid=2′);”>1</a></td>
</tr>
</tbody>
</table>
</div>
</fieldset>
</body>
</html>

Cheers!

Open Source Media Player

Monday, June 18th, 2007

There’s a lot of free software out there, but just like with Instant Messaging software you have to install many of them to be flexible.

Examples:

Several years ago I stumbled upon the VideoLAN Client (aka VLC) when researching methods to stream video from my ReplayTV (Tivo predecessor/clone) to my laptop as the files were in MPEG4 format and my previous clients didn’t support it.

I urge you to check it out as it’s an all in one solution, so that you don’t need all of that other bloat-ware installed.

G’day!

P.S. – I should add that this plays most video and audio formats and is available on most platforms, not just Windows.

Free Instant Messaging (IM) Clients

Wednesday, March 28th, 2007

As indicated way back in my ‘Contact Information’ entry, I use several IM client networks. To make it easier on myself (and my poor computers), it’s usually easier to get an integrated client that connect to many services within one program.

My favorites:

For an even easier way to connect without software installations and to bypass many corporate proxy’s and/or firewalls is to use a web client.

My favorite (as I’m not aware of any others that are still online):

TTYL!

JavaScript (intro)

Thursday, May 4th, 2006

JavaScript is one of the foundations of the internet as we currently know it, but is often misunderstood. It is the “J” in AJAX (to be discussed elsewhere), and is typically used for creation of interactive browser applications with client-side (browser) functionalities such as FORM validation and manipulation of onscreen elements via the DOM (to be discussed elsewhere).

JavaScript is more appropriately called ECMAScript, as it is a ‘Standard’ from the ECMA organization. Early incarnations of this specification were called LiveScript (by Netscape). Microsoft, in typical form, created a VisualBASIC like version that they called JScript, though while mostly compatible, has some proprietary differences.

Implementation:
It’s always preferred to add this to your HEAD section (or the equivalent in HTTP Headers):

<meta http-equiv=”Content-Script-Type” content=”text/javascript” />

To include external files containing JavaScript:

<script type=”text/javascript” src=”/filename.js”></script>

To include XHTML compliant blocks of JavaScript in your page:

<script type=”text/javascript”>
<!– <![CDATA[
...
//]]> — >
</script>

DO NOT use the deprecated ‘language’ attribute:

<script language=”JavaScript”>

</script>