// RPNcalc.js, Version 1.0, 2004/07
// Copyright (C) 2004 by Hans Bauer, Schillerstr. 30, D-73072 Donzdorf
//                       http://www.h-bauer.de
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation.
//                                                                              // ------------ Variables --------------
var shift    = 0;                                                               // Shift value for stack
var xPos     = 0;                                                               // xPos: bei Input=0, bei StackA=1
var varName  = new Array();                                                     // Variable-names
var varValue = new Array();                                                     //      and values
var stack    = new Array(100);                                                  // 100 Stack-fields: stack[0]->input
for (var i=0; i<stack.length; i++) { stack[i]=0; }                              //                 + stack[1 to 99]
commands = new Array('sin','cos','tan','asin','acos','atan');                   // Commands (-> invalid variable names)
commands = commands.concat(new Array('pi','log','ln','ex','x2','yx','r2'));     //
commands = commands.concat(new Array('rx','cs','clear','div','up','down'));      //
commands = commands.concat(new Array('drop','deg','rad','var','popup'));        //

function initialize() {                                                         //>Initialize --------------------------
 writeStackValues();      writeStackLabels();                                   // Write stack-values / -labels
 writeInput("popup");     readCookies();                                        // Write 'popup'-> input, read variables
 document.RPNcalc.Input.select(); }                                             // Select input-field

function rpnFocused() { document.RPNcalc.Input.focus(); }                       //>RpnFocused -> input gets focus

                                                                                // ----------- Stack values ------------
function stackInsert(val) {                                                     //>StackInsert a give value (not string)
 for (var i=stack.length-1; i>1; i--) { stack[i] = stack[i-1]; }                // Shift stack values 1,2,3... by 1
 if (isNaN(val)) stack[1] = 0;                                                  // Insert 0 if value is not a number
 else            stack[1] = val;                                                // Else insert valid value
 writeStackValues(); }                                                          // Write stack-values

function stackDrop() {                                                          //>StackDrop
 for (var i=1; i<stack.length-1; i++) { stack[i] = stack[i+1]; }                // Shift stack values 2,3,4... by -1
 stack[stack.length-1] = 0;                                                     // Clear last stack value
 writeStackValues();  }                                                         // Write stack-values

function stackClear() {                                                         //>StackClear
 for (var i=0; i<stack.length-1; i++) { stack[i]=0; }                           // Clear stack[0 to stack.length-1]
 writeStackValues();    }                                                       // Write stack-values

                                                                                // ------------ Stack shift ------------
function changeShift(i) {                                                       //>ChangeShift by i lines
 shift += i;                                                                    // New shift value with
 if (shift<0) shift=0;                                                          //   shift>= 0
 if (shift>stack.length-6) shift = stack.length-6;                              //   shift < stack.length-6
 writeStackValues();       writeStackLabels();                                  // Write stack-values & -labels
 updateXyPos(); }                                                               // Write stack-values, Update XyPos

                                                                                // ------------ Stack write ------------
function writeStackValues() {                                                   //>WriteStackValues A to E (usually 1-5)
 with (document) {                                                              // With html-document:
   RPNcalc.stackA.value = stack[1+shift];                                       //   Write stack A from stack-values
   RPNcalc.stackB.value = stack[2+shift];                                       //               B
   RPNcalc.stackC.value = stack[3+shift];                                       //               C
   RPNcalc.stackD.value = stack[4+shift];                                       //               D
   RPNcalc.stackE.value = stack[5+shift]; } }                                   //               E

function writeStackLabels() {                                                   //>WriteStackLabels A to E (usually 1-5)
 with (document) {                                                              // With html-document
   getElementById("labelA").firstChild.data = eval(1+shift)+":";                //   Write Stack-label A
   getElementById("labelB").firstChild.data = eval(2+shift)+":";                //                     B
   getElementById("labelC").firstChild.data = eval(3+shift)+":";                //                     C
   getElementById("labelD").firstChild.data = eval(4+shift)+":";                //                     D
   getElementById("labelE").firstChild.data = eval(5+shift)+":"; } }            //                     E

function writeResultToStack(result) {                                           //>WriteResultToStack 1 (usually=A)
 stack[1] = result;                                                             // Save result in stack[1}
 if (shift==0) document.RPNcalc.stackA.value = stack[1]; }                      // Write stackA if not shifted

                                                                                // ----------- Input field -------------
function writeInput(str) {                                                      //>WriteInput
 var val = evaluate(str);                                                       // Evaluate the given string
 if (isNaN(val)) stack[0] = 0;                                                  // Not a Number: Clear stack[0]
 else            stack[0] = val;                                                // Else:         Value to stack[0]
 document.RPNcalc.Input.value = str;                                            //               String to input field
 updateXyPos();                                                                 // Update XyPos
 document.RPNcalc.Input.focus();  }                                             // Set focus on input-field

                                                                                // --------------- XyPos ---------------
function updateXyPos() {                                                        //>UpdateXyPos
 xPos = isNaN(evaluate(document.RPNcalc.Input.value)) ? 1 : 0;                  // Calculate xPos;
 if (xPos==0) stack[0] = evaluate(document.RPNcalc.Input.value);                // Update stack[0] with input value
 var lab = (xPos==0) ? "=x" : " ";                                              // EqualI: evaluate label
 document.getElementById("equalI").firstChild.data = lab;                       //         write label
 lab = (xPos==shift) ? "=y" : ((xPos-shift==1) ? "=x" : " ");                   // EqualA: evaluate label
 document.getElementById("equalA").firstChild.data = lab;                       //         write label
 lab = (xPos-shift==1) ? "=y" : " ";                                            // EqualB: evaluate label
 document.getElementById("equalB").firstChild.data = lab; }                     //         write label

                                                                                // ------------ Do Commands ------------
function doArithmetic() {                                                       //>DoArithmetic (<- rpnInputChanged)
 var len = document.RPNcalc.Input.value.length;                                 // Length of the input-string
 if (len==0) return;                                                            // Zero-length -> nothing
 var key = document.RPNcalc.Input.value.charAt(len-1);                          // Detect pressed key
 if (key=='^')    { rpnYUpX();                               return; }          // On '^' -> rpnYUpX
 if (key=='%')    { rpnPercent();                            return; }          //    '%' -> rpnPercent
 if (key=='!')    { rpnFactorial();                          return; }          //    '!' -> rpnFactorial()
 if (key=='/')    { rpnDivide();                             return; }          //    '/' -> rpnDivide
 if (key=='*')    { rpnMultiply();                           return; }          //    '*' -> rpnMultiply
 var index = document.RPNcalc.Input.value.indexOf("e");                         // Index of exponent 'e'
 if (index==-1) index = document.RPNcalc.Input.value.indexOf("E");              //       or exponent 'E'
 if (index>0 && index==len-2) return;                                           // Sign '+-' after 'eE' -> no arithmetic
 if (key=='-')    { rpnMinus();                              return; }          // Else '-' -> rpnMinus
 if (key=='+')    { rpnPlus();                               return; } }        //      '+' -> rpnPlus

function doCommand(cmd) {                                                       //>DoCommand (<- rpnEnter)
 if (cmd=='sin')  { rpnSin();                                return; }          // On 'sin'   -> rpnSin()
 if (cmd=='cos')  { rpnCos();                                return; }          //    'cos'   -> rpnCos()
 if (cmd=='tan')  { rpnTan();                                return; }          //    'tan'   -> rpnTan()
 if (cmd=='asin') { rpnAsin();                               return; }          //    'asin'  -> rpnAsin()
 if (cmd=='acos') { rpnAcos();                               return; }          //    'acos'  -> rpnAcos()
 if (cmd=='atan') { rpnAtan();                               return; }          //    'atan'  -> rpnAtan()
 if (cmd=='pi')   { writeInput(Math.PI+"");   rpnEnter();    return; }          //    'pi'    -> writeValue & Enter
 if (cmd=='log')  { rpnLog();                                return; }          //    'Log'   -> rpnLog
 if (cmd=='ln')   { rpnLn();                                 return; }          //    'ln'    -> rpnLn
 if (cmd=='ex')   { rpnEUpX();                               return; }          //    'ex'    -> rpnEUpX
 if (cmd=="x2")   { rpnXUp2();                               return; }          //    'x2'    -> rpnXUp2
 if (cmd=="yx")   { rpnYUpX();                               return; }          //    'yx'    -> rpnYUpX
 if (cmd=="r2")   { rpnSqrt();                               return; }          //    'r2'    -> rpnSqrt
 if (cmd=="rx")   { rpnXRoot();                              return; }          //    'rx'    -> rpnXRoot
 if (cmd=='cs')   { rpnChgSign();                            return; }          //    'cs'    -> rpnChgSign
 if (cmd=='clear'){ rpnClear();                              return; }          //    'clear' -> rpnClear
 if (cmd=='div')  { rpnReciprocal();                         return; }          //    'div'   -> rpnClear
 if (cmd=='up')   { rpnUp();                                 return; }          //    'up'    -> rpnUp
 if (cmd=='down') { rpnDown();                               return; }          //    'down'  -> rpnDown
 if (cmd=='drop') { rpnDrop();                               return; }          //    'drop'  -> rpnDrop
 if (cmd=='deg')  { document.RPNcalc.angle.selectedIndex=0;  return; }          //    'deg'   -> Anglemode -> deg
 if (cmd=='rad')  { document.RPNcalc.angle.selectedIndex=1;  return; }          //    'rad'   -> Anglemode -> rad
 if (cmd=='var')  { rpnVariables();                          return; }          //    'var'   -> rpnVariables
 if (cmd=='popup'){ popup();                                 return; } }        //    'popup' -> popup

function doVariable(cmd) {                                                      //>DoVariable
 if (cmd.length<=1) return;                                                     // More than 2 characters needed
 if (cmd.charAt(0)=='=') { saveVariable(cmd.substr(1), stack[1]); return; }     // On '=' -> Save variable
 if (cmd=='##')          { deleteVariables();                     return; }     //    '##'-> Delete variables
 if (cmd.charAt(0)=='#') { deleteVariable(cmd.substr(1));         return; }     //    '#' -> Delete variable
 var index = getVarIndex(cmd);                                                  // Resolve variable-index
 if (index==-1) return;                                                         // Variable not found -> nothing more
 stackInsert(varValue[index]); }                                                // Insert

                                                                                // ---------- ChangeListener -----------
function rpnInputChanged() {                                                    //>RpnInputChanged (onKeyUp)
 updateXyPos();                                                                 // Update XyPos
 doArithmetic(); }                                                              // Do arithmetic (on typed '^%/*-+')

                                                                                // ---------- ActionListener------------
function rpnDblClick(source) {                                                  //>RpnDblClick (dblClick on Stack-value)
 var str="";                                                                    // Initialize index
 if      (source=='stackA') str = stack[shift+1] + "";                          // String 'str' in 'StackA'
 else if (source=='stackB') str = stack[shift+2] + "";                          //                 'StackB'
 else if (source=='stackC') str = stack[shift+3] + "";                          //                 'StackC'
 else if (source=='stackD') str = stack[shift+4] + "";                          //                 'StackD'
 else if (source=='stackE') str = stack[shift+5] + "";                          //                 'StackE'
 if (document.RPNcalc.Input.value.length>0) rpnEnter();                         // Perform 'enter' (input->stack[1])
 writeInput(str);   }                                                           // Copy 'str' to input-field

function rpnUp()      { changeShift(+5);  document.RPNcalc.Input.focus();    }  //>RpnUp    (shift stack +1)
function rpnDown()    { changeShift(-5);  document.RPNcalc.Input.focus();    }  //>RpnDown  (shift stack -1)
function rpnClear()   { stackClear();              writeInput("");           }  //>RpnClear (clear stack & input)
function rpnDrop()    { writeInput(stack[1]+"");   stackDrop();              }  //>RpnDrop  (drop stack by 1)
function rpnEnter()   {                                                         //>RpnEnter
 var str = document.RPNcalc.Input.value;                                        // String of the input field
 if (str.length<1) stackInsert(stack[1]);                                       // Copy Stack[1] on empty input
 if (xPos==0)      stackInsert(evaluate(str));                                  // Insert valid input-value to stack
 writeInput("");                                                                // Clear input field
 doCommand(str);                                                                // Do commands (e.g. sin,.., log,..)
 doVariable(str); }                                                             // Do variable

function rpnKey(key)  {                                                         //>RpnKey
 if (document.RPNcalc.Input.value=="popup") writeInput("");                     // Clear 'popup' from RPN-startup
 writeInput(document.RPNcalc.Input.value + key);      }                         // Process keys 0...9 ','

function rpnPi()      {                                                         //>RpnPi
 if (document.RPNcalc.Input.value=="popup") writeInput("");                     // Clear 'popup' from RPN-startup
 if(xPos==0) rpnEnter();                                                        // Valid input-value -> rpnEnter
 stackInsert(Math.PI);                                                          // Write 'pi' to 1.st stack
 writeInput(""); }                                                              // Clear and focus input-field

                                                                                // ----- x! % / * - + ------------
function rpnFactorial() {                                                       //>RpnFactorial (x!)
 var res = 1;                                                                   // Initialize result=1
 for (var i=1; i<=eval(getX()); i++) res*=i;                                    // Loop: Multiply with next integer
 writeResult(res, 1); }                                                         // Write result

function rpnPercent() { writeResult(eval(getY()*getX()/100), 2);             }  //>RpnPercent      y*x/100
function rpnDivide()  { writeResult(eval(getY()/getX())    , 2);             }  //>RpnDivide       y/x
function rpnMultiply(){ writeResult(eval(getY()*getX())    , 2);             }  //>RpnMultiply     y*x
function rpnMinus()   { writeResult(eval(getY()-getX())    , 2);             }  //>RpnMinus        y-x
function rpnPlus()    { writeResult(eval(getY()+getX())    , 2);             }  //>RpnPlus         y+x

                                                                                // ----- Trigonometric -----------
function rpnSin()     { writeResult(eval(Math.sin(toRadians(getX())))   ,1); }  //>RpnSin          sin(x)
function rpnCos()     { writeResult(eval(Math.cos(toRadians(getX())))   ,1); }  //>RpnCos          cos(x)
function rpnTan()     { writeResult(eval(Math.tan(toRadians(getX())))   ,1); }  //>RpnTan          tan(x)
function rpnAsin()    { writeResult(eval(fromRadians(Math.asin(getX()))),1); }  //>RpnAsin         Asin(x)
function rpnAcos()    { writeResult(eval(fromRadians(Math.acos(getX()))),1); }  //>RpnAcos         Acos(x)
function rpnAtan()    { writeResult(eval(fromRadians(Math.atan(getX()))),1); }  //>RpnAtan         Atan(x)

                                                                                // ----- Pi 10^x e^x -------------
function rpnTenUpX()  { writeResult(eval(Math.pow(10,getX())), 1);           }  //>RpnTenUpX       10^x
function rpnEUpX()    { writeResult(eval(Math.exp(getX()))   , 1);           }  //>RpnEUpX         e^x

                                                                                // ----- 1/x Log Ln --------------
function rpnReciprocal(){ writeResult(eval(1/getX()), 1);                    }  //>RpnReciprocal   1/x
function rpnLog()       { writeResult(eval(Math.log(getX())/Math.LN10), 1);  }  //>RpnLog          Log
function rpnLn()        { writeResult(eval(Math.log(getX()))          , 1);  }  //>RpnLn           Ln

                                                                                // ----- x^2 y^x Sqrt Xroot ------
function rpnXUp2()    { writeResult(eval(getX()*getX())            , 1);     }  //>RpnXUp2         x^2
function rpnYUpX()    { writeResult(eval(Math.pow(getY(),getX()))  , 2);     }  //>RpnYUpX         y^x
function rpnSqrt()    { writeResult(eval(Math.pow(getX(),0.5))     , 1);     }  //>RpnSqrt         x^(1/2)
function rpnXRoot()   { writeResult(eval(Math.pow(getY(),1/getX())), 2);     }  //>RpnXRoot        y^(1/x)

                                                                                // ----- EEX  +/- ----------------
function rpnEex() {                                                             //>RpnEex          EEX
 if (xPos==1) { writeInput("1e");        return; }                              // Invalid input-value -> input='1e'
 writeInput(document.RPNcalc.Input.value + "e"); }                              // Else -> Add 'e' to input-value

function rpnChgSign() {                                                         //>RpnChgSign      +/-
 if (xPos==1)   { writeResult(eval(getX()*(-1)), 1);      return; }             // xPos on stack -> change sign, return
 var index            = document.RPNcalc.Input.value.indexOf("e");              // Index of exponent 'e'
 if (index==-1) index = document.RPNcalc.Input.value.indexOf("E");              //       or exponent 'E'
 if (index==-1) { writeInput(eval(getX()*(-1))+"");       return; }             // No exponent   -> change sign, return
 var len      = document.RPNcalc.Input.value.length;                            // Length of input-value as string
 var mantissa = document.RPNcalc.Input.value.substring(0,index);                // Mantissa before 'e' or 'E'
 var exponent = document.RPNcalc.Input.value.substring(index+1,len);            // Exponent after  'e' or 'E'
 var content  = evaluate(mantissa) + "e" + evaluate(exponent)*(-1);             // Content = mantissa 'e' -exponent
 document.RPNcalc.Input.value = content;                                        // New input-value
 document.RPNcalc.Input.focus();  }                                             // Focus on input-field

                                                                                // ------------ Utilities --------------
function getX() {                                                               //>GetX
 if (xPos>0) return stack[1];                                                   // xPos>0 -> stack[1]
 return evaluate(document.RPNcalc.Input.value); }                               // else   -> Value from input-field

function getY() {                                                               //>GetY
 if (xPos>0) return stack[2];                                                   // xPos>0 -> stack[2]
 return stack[1]; }                                                             // else   -> stack[1]

function writeResult(result, involved) {                                        //>WriteResult (result is value)
 if (document.RPNcalc.Input.value=="popup") writeInput("");                     // Clear 'popup' from RPN-startup
 var nDrop = xPos + involved - 2;                                               // Number of stack-drops
 for (var i=0; i<nDrop; i++) stackDrop();                                       // Drop necessary stack lines
 if (nDrop<0) { stackInsert(result);        }                                   // Write result: insert to stack[1]
 else         { writeResultToStack(result); }                                   //               overwrite stack[1]
 writeInput(""); }                                                              // Clear input field

function evaluate(str) {                                                        //>Evaluate field content
 white = str.match(/\s*/);                                                      // White spaces in string (for opera)
 if (white && str==white) return Number.NaN;                                    // Only whitespaces -> Not a number
 return parseFloat(str.replace(/,/,'.')); }                                     // Parsed string with ','->'.' or NaN

function toRadians(angle) {                                                     //>ToRadians
 if(document.RPNcalc.angle.selectedIndex==1) { return angle; }                  // Rad selected -> return unmodified
 return angle * Math.PI / 180.0; }                                              // Else         -> convert deg->rad

function fromRadians(angle) {                                                   //>FromRadians
 if(document.RPNcalc.angle.selectedIndex==1) { return angle; }                  // Rad selected -> return unmodified
 return angle * 180.0 / Math.PI; }                                              // Else         -> convert rad->deg

function popup() {                                                              //>Popup
 RPNpop = window.open("rpncalc.html","",                                        // Open RPNcalc in a popup
         "resizable=yes,scrollbars=no,width=445,height=262,left=50,top=50"); }   // with several window options

                                                                                // ------------- Variables -------------
function rpnVariables() {                                                       //>RpnVariables
 if (varName.length==0) { alert("No variables defined so far");   return; }     // No variables defined
 RPNvar = window.open("about:blank","",                                         // Open new window for RPNvar-listing
         "resizable=yes,scrollbars=yes,width=200,height=200,left=300,top=40");  //               with several options
 RPNvar.document.write('<head>\n');                                             // Write html-head
 RPNvar.document.write('<link rel=\"stylesheet\" href=\"rpnvar.css\"');         // Write link to RPNvar.css,
 RPNvar.document.write(' type=\"text\/css">\n<\/head><body>\n');                //   close html-head, open html-body
 RPNvar.document.write('<u>Defined variables:<\/u><br>\n');                     // Write header 'Defined variables'
// RPNvar..write('<a href=\"javascript:opener.rpnEnter()\">Enter<\/a><br>');    // Example how to press Enter on opener
 RPNvar.document.write('<table>\n');                                            // Start table
 RPNvar.document.write('<tr><td class=\"b0110\"><p>Name<\/p><\/td>\n');         // Table header 'Name'
 RPNvar.document.write('    <td class=\"b0010\"><p>Value<\/p><\/td><\/tr>\n');  //          and 'Value'
 for (var i=0; i<varName.length; i++) {                                         // Loop: Defined variables
   RPNvar.document.write('<tr><td class=\"b0100\"><p>');                        //   New table-line
   RPNvar.document.write(varName[i]+'<\/p><\/td>\n');                           //       with varName
   RPNvar.document.write('    <td class=\"b0000\"><p>');                        //   Next cell
   RPNvar.document.write(varValue[i]+'<\/p><\/td><\/tr>\n'); }                  //       with varValue
 RPNvar.document.write('<\/table>');
 RPNvar.document.write('<p><i>Static listing<br>will not be updated<\/i><\/p>');
 RPNvar.document.write('<\/body>');  }                                          // Close

function saveVariable(name, value) {                                            //>SaveVariable by name & value
 if(!checkValidName(name)) return;                                              // Check if name is a valid
 var index = getVarIndex(name);                                                 // Search vor variable == 'name'
 if (index>=0) { varValue[index] = value; }                                     // Replace value of existing variable
 else          { index = varName.length;                                        // Index of the new variable
                 varName[index]  = name                                         // Create new variable with 'name'
                 varValue[index] = value; }                                     //                      and ' value'
 setCookies(); }                                                                // Set cookies with variables

function checkValidName(name) {                                                 //>CheckValidName
 if (!isNaN(evaluate(name))) {                                                  // If name is evaluated to a number
   alert('Invalid variable name "' + name + '" (number)');                      //  -> Message 'invalid name'
   return false; }                                                              //     and return 'false'
 for (var i=0; i<commands.length; i++) {                                        // Check for reserved commands
   if (name==commands[i]) {                                                     // If name is equal to a command
     alert('Invalid variable name "' + name + '" (command)');                   //  -> Message 'invalid name'
     return false; } }                                                          //     and return 'false'
 return true; }                                                                 // No irregularities found -> valid

function getVarIndex(name) {                                                    //>GetVarIndex (index or -1)
 for (var i=0; i<varName.length; i++) {                                         // Loop variables
   if (varName[i]==name) return i; }                                            //   Variable found -> return index
 return -1; }                                                                   // Else return -1

function deleteVariable(name) {                                                 //>DeleteVariable by name
 var index = getVarIndex(name);                                                 // Get the index of the variable
 if (index==-1) return;                                                         // Variable does not exist -> nothing
 var arrName  = varName.slice(0,index);                                         // First part of name-array
 var arrValue = varValue.slice(0,index);                                        //               value-array
 varName      = arrName.concat(varName.slice(index+1));                         // Concat with trailing name-array
 varValue     = arrValue.concat(varValue.slice(index+1));                       //                      value-array
 setCookies(); }                                                                // Set cookies with variables

function deleteVariables() {                                                    //>DeleteVariables
 varName = new Array();     varValue = new Array();     setCookies(); }         // Instantiate new arrays

                                                                                // ------------- Cookies ---------------
function setCookies() {                                                         //>SetCookies
 this.setCookie("VarNames",  varName.join(','));                                // SetCookie "VarNames"
 this.setCookie("VarValues", varValue.join(',')); }                             //           "VarValues"

function readCookies() {                                                        //>ReadCookies (as string!)
 var varNames  = this.getCookie("VarNames");                                    // Get Cookie 'VarNames'
 var varValues = this.getCookie("VarValues");                                   //            'VavValues'
 if (varNames)  { varName  = split(varNames,',');  }                            // New array  'varName'
 if (varValues) { varValue = split(varValues,','); } }                          //            'varValue'

function split(str,token) {                                                     //>Split
 arr = new Array();                                                             // New Array 'arr' for split
 if (str.length==0) return arr;                                                 // Given String is empty -> return 'arr'
 var last = -1;                                                                 // Initialize last token index
 for (var i=0; i<str.length; i++) {                                             // Loop: Characters of given string
   if (str.charAt(i)!=token) continue;                                          //   No token -> continue
   arr[arr.length] = str.substring(last+1, i);                                  //   Else: Extract substring to 'arr'
   last=i; }                                                                    //         Update last token index
 arr[arr.length] = str.substring(last+1);                                       // Add last substring to 'arr'
 return arr; }                                                                  // Return 'arr'

                                                                                // --------------- Cookie --------------
function setCookie(name, value) {                                               //>SetCookie by name, value, expire-days
 if (!navigator.cookieEnabled) return;                                          // Disabled cookies -> nothing
 var exp = new Date();                                                          // Actual date
 var end = exp.getTime() + (50 * 24 * 60 * 60 * 1000);                          // Expire in 50 days
 exp.setTime(end);                                                              // Expire time of cookes
 document.cookie =  name + '=' + value + '; expires=' + exp.toGMTString(); }    // Set cookie with expiration-date

function getCookie(name) {                                                      //>GetCookie value (as string!)
 var cookies  = document.cookie;                                                // Cookies separated by ';'
 var posName  = cookies.indexOf(name + '=');                                    // Start position of 'name='
 if (posName == -1) return '';                                                  // Cookie not found -> Return ''
 var posValue = posName + name.length + 1;                                      // Start position of cookie-value
 var endValue = cookies.indexOf(';',posValue);                                  // End position of cookie value at ';'
 if (endValue !=-1) return cookies.substring(posValue, endValue);               // ';' -> Return substring as value
 return cookies.substring(posValue); }                                          // Else-> Return rest of line as value
