Javascript Project Summary

 

Table of Contents

— JAVASCRIPT —

Pass by value or pass by reference?

Generic Javascript References

Declaring Strict Mode

  • Strict mode is declared by adding “use strict”; to the beginning of a JavaScript or a JavaScript function.
  • Declared at the beginning of a JavaScript file, it has global scope (all code will execute in strict mode):
Example"use strict";
x = 3.14;       // This will cause an error (x is not defined)

Why Strict Mode?

  • Strict mode makes it easier to write “secure” JavaScript.
  • Strict mode changes previously accepted “bad syntax” into real errors.
  • As an example, in normal JavaScript, mistyping a variable name creates a new global variable. In strict mode, this will throw an error, making it impossible to accidentally create a global variable.
  • In normal JavaScript, a developer will not receive any error feedback assigning values to non-writable properties.
  • In strict mode, any assignment to a non-writable property, a getter-only property, a non-existing property, a non-existing variable, or a non-existing object, will throw an error.

Splice doesn’t work when used in a Loop

  • Workaround:  just reverse the for loop, using — rather than ++.
for ( idx=lc-1; idx>=0 ; idx--)
 {
 var lType = this.logentries[idx].logType;
 if ( lType === 'Status')
 this.logentries.splice(idx,1);
 }

Reference :  

 

Sorting an Array of Objects

- JavaScript Code to Sort the Objects array by sortIDX column

mapIndex.prototype.sort = function()
{
    myMapIndex.mapIndexArray.sort(function(a, b){ return a.sortIDX - b.sortIDX });
}

Before Sort operation:
mapIndex  trackID  mapType arrayIDX  slidesLoaded  sortIndex
       0        1   track         0        false          2
       1        2   track         1        false          3
       2        3   track         2        false          4
       3        5   track         3        false          5
       4     5001   location      0        false          1
       5     5000   location      1        false          6

After Sort operation:
mapIndex  trackID  mapType arrayIDX  slidesLoaded  sortIndex
       4     5001   location      0        false          1
       0        1   track         0        false          2
       1        2   track         1        false          3
       2        3   track         2        false          4
       3        5   track         3        false          5
       5     5000   location      1        false          6

Using empty Javascript objects

  • There are 2 different ways of creating an empty object in javascrips
var objectA = {}               // This is an object literal
var objectB = new Object()     // This is the object constructor 
  • Using the || operator to set explicit null values
  • This helps ensure that values are intentionally nullified if not
  • Google is using a similar technique in their libs :     window.google = window.google || {};
  • The code below either assigns bar to foo or if bar is NOT DEFINED foo is set foo  to NULL
var foo = bar || null;    // methode 1
var foo = bar || {};      // methode 2

 Reference:

 

Anonymous function declaration

var anon = function() {
  alert('I am anonymous');
};

anon();

The most common use for anonymous functions are as arguments to other functions, or as a closure.

setTimeout(function() {
  alert('hello');
}, 1000);

// Our anonymous function is passed to setTimeout, which will execute
// the function in 1000 milliseconds.

(function() {
  alert('foo');
})();

// This is a common method of using an anonymous function as a closure,
// which many JavaScript frameworks use.

Breakdown of the above anonymous statements:

  • the surrounding braces is a wrapper for the anonymous function
  • the trailing braces initiates a call to the function and can contain arguments
(function(message) {
  alert(message);
}('foo'));
// Another way to write the previous example and get the same result

An alternative representation of the above places the initiating braces to the surrounding braces and not the function itself, which causes confusion over why the surrounding braces are needed in the first place.

(function() {
  // …
})();

Some have even resorted to giving the trailing braces technique derogatory names, in an effort to encourage people to move them back inside of the surrounding braces to where they initiate the function, instead of the surrounding braces.

Using split() and pop() to shorten long URL Names or Filenames

 
Start URL : http://localhost/wordpress/wp-content/themes/twentyfifteen-child/tracks/track5000/images/Ottp1.jpg 

After running the Javascript Code below we have shorten our original string [ usefull for traces ]:

 var splitSrc = s.src.split('/'); 
 var fName = splitSrc.pop() ;
 var dName1 = splitSrc.pop() ;
 var dName2 = splitSrc.pop() ;
 var dName3 = splitSrc.pop() ; 
 var newName = ".../" + dName3 + "/" + dName2 + "/" + dName1 + "/" + fName;

Result String: .../tracks/track5000/images/Ottp1.jpg

— Switching for PROCEDURAL to FUNCTIONAL programming —

Using  forEach  Methode

Procedural Code:: 

for (i = 0; i < tindex; i++)     
    {
        var istr2 = i.toString().lpad(3) + " " + tracks[i].trackID.lpad(3) + " " + tracks[i].sLoc.lpad(22) 
        + "     " + tracks[i].eLoc.lpad(22) + "   " + tracks[i].startLatLng;
        logMessage2(istr2);
    }    

Functional Code:: 
Parameter Details
 - sTrack  : A single Track Element
 - index   : Array Index [ == parameter i in the above procedural Code ] 
 - tracks  : Our track Array  
 
tracks.forEach(function (sTrack, index, tracks)
    {
        var istr2 = index.toString().lpad(3) + " " + sTrack.trackID.lpad(3) + " " + sTrack.sLoc.lpad(22) 
        + "     " + sTrack.eLoc.lpad(22) + "   " + sTrack.startLatLng;
        logMessage2(istr2);
    });

Sample2: Using setTimeout to delay the each processing operation
 
var displayMapTimeout = 100;
var tid = 0;
var timeout = 0;
myMapIndex.mapIndexArray.forEach(function(mapElem) {
    var tid = mapElem.trackID;
    timeout = timeout + displayMapTimeout;
    logStatus(logHeader + " --- TrackID: " + tid + " -timeout: " + timeout);
    setTimeout(myMapIndex.drawMapObjects,timeout,tid,drawTrackOnly,funcName);
});

 

Using  filter Methode

  • returns an NEW array meeting certain search conditions
var mapEntriesFound =  mapArray.filter( function (mapEntry, index, mapArray)
        { return mapEntry.trackID === ltrackID } );
var mCnt = mapEntriesFound.length;

if (mCnt !== 1) 
    {       
        mIdx = -1;     // Error conditon   
    }  
else
    {
        mIdx = mapEntriesFound[0].mapIDX;   
                             // Only on Record is found - pick up the related Index Info      
    }

— GOOGLE MAPS —

Handling DOUBLE click events on Markers in Google Maps JS API v3

Moving a Google Maps Marker

  • During the first call to drawSlideMarker() the Marker was created at positioned at this.startLatLng
  • All subsequent calls to drawSlideMarker()  moves to Slider to the track end by using setPosition(this.endLatLng)
Track.prototype.eraseSlideMarker = function( ) 
  {
  this.slideMarker = null ;    
  logMessage3("eraseSlideMarker TrackID:: slideMarker set to null "  );
  }
    
Track.prototype.drawSlideMarker = function( ) 
  {    
  if ( this.slideMarker == null )
    {    
    var pinIcon = new google.maps.MarkerImage(
                 "http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|FFFF00",
                  null, /* size is determined at runtime */
                  null, /* origin is 0,0 */
                  null, /* anchor is bottom center of the scaled image */
                  new google.maps.Size(21, 34)
                    //new google.maps.Size(42, 68)
                   //new google.maps.Size(84, 132)
            );                 
      this.slideMarker = new google.maps.Marker(
            {
            position:  this.startLatLng,
            draggable:true,
            map: googleGlobalMap,
            title: 'Slide Marker' 
            });
    this.slideMarker.setIcon(pinIcon);        
    logMessage3("drawSlideMarker TrackID:: slideMarker created:  "  + this.startLatLng );
     }
  else
     {          
     this.slideMarker.setPosition(this.endLatLng);
     logMessage3("drawSlideMarker TrackID:: slideMarker moved:  "  + this.endLatLng  );    
     }        
 }

 

Add Labels to Markers

var myIcon = 
  {
  url: 'http://maps.google.com/mapfiles/kml/paddle/blu-blank.png', // Icon URL
  labelOrigin: new google.maps.Point(25, 15),   // Position the Text Label
  scaledSize:  new google.maps.Size(50,50)      // Scale the ICON    
  };
var tMarker = new google.maps.Marker(
  {
  position:  tracks[lidx].markerLatLng,
  draggable:true,
  map: googleGlobalMap,
  title: 'Track Start - ID: ' +  tracks[lidx].trackID,
  label: 
    {
    text: (lidx+1).toString(),          // Note only the FIRST character will be displayed 
          color: 'purple'
    }
 });     
tMarker.setIcon(myIcon);

Reference:

— jQuery —

Syntax to read and change HTML elements

The jQuery syntax is tailor made for selecting HTML elements and performing some action on the element(s).
Basic syntax is: $(selector).action()
  A $ sign to define/access jQuery
  A (selector) to "query (or find)" HTML elements
  A jQuery action() to be performed on the element(s)
Examples:
    $(this).hide() - hides the current element.
    $("p").hide() - hides all <p> elements.
    $(".test").hide() - hides all elements with class="test".
    $("#test").hide() - hides the element with id="test".


Syntax to read and change CSS styles

 var wrapperP3 = $('#divp3');    // Read HTML element with id=divP3
 wrapperP3.css('zIndex','10');
 wrapperP3.css('visibility' , 'visible');
 logMessage("clearSlider() - LEAVING::  divp3[zIndex]:  " + wrapperP3.css('zIndex') +
    " - divp3[visibility]:  " + wrapperP3.css('visibility')     );

jQuery Window Resize

  • The window resize function is run when a user resizes their browser window.
  • The Windows Resize Event  is a  perfect function for responsive design
  • jQuery doesn’t have a Resize Event for DIVs
jQuery(document).ready(function() 
  {       
   /*
  Code included inside $( document ).ready() will only run once the page Document Object Model (DOM) 
  is ready for JavaScript code to execute. 
  Use ready() to make a function available after the document is loaded like our Click Button Actions 
  */
  logMessage("jQuery(document).ready(function()::  ");  
  $(window).resize(function()
      {
            logStatus('jQuery Resize Operation active:: panelMode: ' + panelMode);
            var maxtIDX = tracks.length-1;
            if ( panelMode == 'maps' && maxtIDX > 0 )
                {
                logStatus('jQuery Resize Operation active:: panelMode: ' + panelMode + " MAX Track Index: " + maxtIDX);
                resizeWindowWithGlobalBounds (maxtIDX, false);  // Resize googgle Maps 
                }
        });

Avoid flickering by using jQuery and CSS together with addClass and removeClass

If we have a Div with a background Image and overlay the DIV with a google Maps we see a flickering effect as first the background color is loaded, then the background Image and finally the google Maps gets loaded.

To avoid this effect we should disable   the background Image   before drawing the google MAP

CSS Code:
.fPanel{
    margin : 0px 5px;
  padding: 15px 10px; 
    height: 210px; 
  width: 220px !important; ;
  line-height: 10px;
  font-size:0.7em;
  color:#00FF40;
  float: left;
  }

.fPanelBackground
 {
      background-image: url("../images/fdisplay210.jpg");
 }
 
.fPanelNOBackground
 {
      background-image: none;
 } 

JQuery Code:
Before we load the Google Maps we need to disable the background Image: 
  $('#fPanel').removeClass('fPanelBackground');  
  $('#fPanel').addClass('fPanelNOBackground');  
  $("#fPanel").empty();    // clear old HTML stuff - provide an empty DIV for Google Maps              
  
  googleGlobalMap = new google.maps.Map(document.getElementById("fPanel"), 
          { mapTypeId: google.maps.MapTypeId.TERRAIN ,
            center:    centerP ,
            zoom: zoom
           });    
  
  $('#fPanel').removeClass('fPanelNOBackground');
  $('#fPanel').addClass('fPanelBackground');

 

Why first paragraph not taking this style p:first-child?

  • don’t use first-child instead use  first-of-type
  • $(“#tourModal p:first-child”) will select the first <p> element in a div section instead it will selecte the first element not depending on the elements type
var pElem = $("#tourModal p:first-of-type");
pElem.html(updateText);

Reference:

 

— PHP —

Extract GPS EXIF data from digital images by using exif_read_data

PHP Code

for ( $i = 0; $i< $slideCount; $i++ )
        { 
        if ( $slideshowArray[$i]['type'] == 'imgtype' )
          {            
          print_r("File: ".$slideshowArray[$i]['src']);
          $exif = exif_read_data($slideshowArray[$i]['src']);
          if($exif)
            {      
            $lon = getGps($exif["GPSLongitude"], $exif['GPSLongitudeRef']);
            $lat = getGps($exif["GPSLatitude"], $exif['GPSLatitudeRef']);
            $fileSize = number_format(($exif['FileSize']/1024),2).' Kb';
            print("\nLAT: ");
            var_dump($lat);    
            print("LON: " );
            var_dump($lon);
            print("FileSize: ");
            var_dump($fileSize);    
            print("\n");
            //print_r($exif);
            }
        }
      }

 function getGps($exifCoord, $hemi) 
   {
   $degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
   $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
   $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
   $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1;
   return $flip * ($degrees + $minutes / 60 + $seconds / 3600);
   }

function gps2Num($coordPart) 
   {
   $parts = explode('/', $coordPart);
   if (count($parts) <= 0)
        return 0;
   if (count($parts) == 1)
        return $parts[0];
   return floatval($parts[0]) / floatval($parts[1]);
   } 

Output:

File: http://localhost/wordpress/wp-content/themes/twentyfifteen-child/tracks/track1/images/i1.jpg
LAT: float(49.829796111111)
LON: float(11.078111388889)
FileSize: string(9) "115.10 Kb"

File: http://localhost/wordpress/wp-content/themes/twentyfifteen-child/tracks/track1/images/i2.jpg
LAT: float(49.831478611111)
LON: float(11.076601111111)
FileSize: string(9) "107.39 Kb"

File: http://localhost/wordpress/wp-content/themes/twentyfifteen-child/tracks/track1/images/i3.jpg
LAT: float(49.831956388889)
LON: float(11.077386388889)
FileSize: string(9) "103.79 Kb"

Reference

 

 — Using Gimp —

Resize Image Siue by Using Gimp Batch Image Manipulation Plugin

  • Original Picture Pixesl  2560 x 1920  results in a  2 Mbyte JPEG Image -> to large for Web
  • Resized  Picture Pixec    853 x  640    results in a 200 kByte JPEG image
1) Add Aufgaben-Satz - Größe andern -> auf Genaune Pixel Wert :  853 x  640  Pixel
2) Hinzufügen von Bildern -> Ordner hinzufügen --> Select Ordner images --> Datein aus gesamter OrdnerStruktur hinzufügen
3) Speichern in -> Neue Directory Auswählen ->  Select Ordner imagesNew 
4) Apply 

--> Old Images 
D:\xampp\htdocs\wordpress\wp-content\themes\twentyfifteen-child\tracks>dir track14004\images
 Verzeichnis von D:\xampp\htdocs\wordpress\wp-content\themes\twentyfifteen-child\tracks\track14004\images

12.06.2016  11:00    <DIR>          .
12.06.2016  11:00    <DIR>          ..
10.06.2016  12:37         7.414.784 P1030461.JPG
10.06.2016  12:41         6.989.824 P1030466.JPG
10.06.2016  12:46         6.935.040 P1030468.JPG
..

--> New Images 
D:\xampp\htdocs\wordpress\wp-content\themes\twentyfifteen-child\tracks>dir track14004\imagesNEW
 Verzeichnis von D:\xampp\htdocs\wordpress\wp-content\themes\twentyfifteen-child\tracks\track14004\imagesNEW    ..
07.10.2016  16:28           165.937 P1030461.JPG
07.10.2016  16:28           179.753 P1030466.JPG
07.10.2016  16:28           124.462 P1030468.JPG

 — CODE —

Details RESET Slider

  • ResetSlider() is the top Level Function to cleanup the Slider
  • Most work is done in clearSlider() function
    • Clears all HTML elements for #slider DIV Section
    • Invokes wrapperSlider.bbslider(‘update’) methode to readjust the slider porperties
    • Clear the background settings for #slider DIV Section [ done by Google Maps ]
    • Moves our #divP3 DIV setction on top over  #slider DIV Section by using zIndex
 resetSlider(func)
  -> clearAndStopSlider(func)
     -> stopSlider();
       -> clearSlider();

          function clearSlider()  /* Converted to CSS */
            { 
            logMessage("clearSlider():: Reset Slider !");     
            var wrapperSlider = $('#slider');    /* Get access to HTML element id="slider" */    
            wrapperSlider.empty();               /* clear inner HTML:  "" */ 
                  
            wrapperSlider.bbslider('update');    /* Force the slider to REREAD HTML data */
            var pCount2 = wrapperSlider.data('pCount');
            var pIndex2 = wrapperSlider.data('pIndex');
            logMessage("<b>clearSlider():: - After ERASING slider HTML: pCount/pIndex should be [0] -  pCount :: " 
              + pCount2  + ' - pIndex: ' + pIndex2 + "</b>");
            if (     pCount2 != 0  || pIndex2 != 0 )
              {  /* Retrieve the HTML - In certain cases Google Maps may write to our slider DIV
                    as both Google Maps and our Slider are uing the same DIV */
              logMessage("<b>ERROR clearSlider() [ pCount/PIndex != 0]:: - HTML: " + wrapperSlider.html() +  "</b>");    
              }        
                 /* Google Maps changes the background color - remove that change*/
            wrapperSlider.css('backgroundColor','');
                  
            var wrapperP3 = $('#divp3');
            wrapperP3.css('zIndex','10');
            wrapperP3.css('visibility' , 'visible');
            logMessage("clearSlider() - LEAVING:: Slider[zIndex]: " + wrapperSlider.css('zIndex')  + " - divp3[zIndex]:  " + wrapperP3.css('zIndex') +
              " - divp3[visibility]:  " + wrapperP3.css('visibility')     ); 
            }

— Potential Problems —

Google Maps adds Data to slider DIV –> panel numbering gets wrong !

  • The slider DIV is used by GOOGLE MAPS and our Slideshow Application
  • If we load the Panel Data for our Slideshow and we may get a Google MAPS update to the slider  DIV our panel number run out of order [ panel1, panel3, panel4 …. – panel2 was missing ]. This will kill the slideshow appliction !
  • After redirection the MAP panel from slider DIV to fPanel DIV the problem seems to be solved

ErrorPanelOrdering

  •  The DIV class “gm-stye .. ” was added by GOOGLE Maps

— DEBUGGING with Chrome DevTools

Display and locate a specific function using Console Prompt

  • Display and Jump to a certain Code location by using the Console window 
  • Note the console prompt is :   >

ChromDevTool1 ChromDevTool2

After RightClick on the violet function and select Show Function Definition

ChromDevTool2

 

Running a specific Javascript function from Console prompt

ChromDevTool3

  • The logStatus() function has successfully updated the console.log

ChromDevTool4

  • The logStatus() function has successfully updated out HTML page

 

Using Workspaces

  • Run your application and press F12 to start the  Chrome Dev Tools
  • Chrome Dev Tools should look like this

ChromDevTool5

  • Right click into the left window and select : Add Folder to Workspace 
  • Select our WordPress Client Theme from the local disk
  • Don’t forget to press ALLOW at the top of the FRAME 
  • After that the current status should look like :

ChromDevTool6

  • Map the resources  : RightClick on cssmenu.css [ grey ]
  • Select Map to Network Resources [ for Javascript and CSS files ]
  • Press F1 -> Workspaces to verify the correct Mappings 

ChromDevTool7

  • Here we can verify the the Disk Mappings -> Network Mappings
  • CSS changes are reflected immediate in our Browser Window [ Easy debugging ]
  • Javascript Changes need to saved first [ ctrl<s>,  F5 ]
  • Press ESC to leave that screen

 

LiveEdit recompilation in action

ChromDevTool8

  • Above Javascript function fails to display the routes as we get a reference error
  • Let us fix the error [ typo by removing ‘d’ at the end of googleMapsLoadeded ]
  • Save the changes
  • Now don’t reload the page – only rerun the specific function by pressing a button

ChromDevTool10

— DEBUGGING —

Generic Debugging References

A first Debugging Session with Firebug

Debug JSON errors

Error:  SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data
- Start Firebug Console: F12 
  -> Net -> XHR -> Response 
Fatal error: Call to undefined function parseNewGPX_Wrapper() in 
    /customers/3/7/d/hhufs.de/httpd.www/blog/wp-content/themes/twentyfifteen-child/functions.php on line 98

debug_JSON_Errors

Debugging Windows Resize  Events with Firebug

  • Enable Command Editor [ Console ->  RightClick -> Enable Command Editor ]
  • Type:  monitorEvents(window, “resize”)  and press Run
  • View the results via Console -> All – the command should be replied without any syntax Errors

DebugFirebugEventsP1

  •  After enabling MonitorEvents  resize  your window
  • Console->Errors should report the Window Resize EVENT

DebugFirebugEventsP2

Debugging a Click Event for a certain DIV ID  with Firebug

DebugFirebugEventsP4

Debugging all Events for a certain DIV ID  with Firebug

  • This includes all Events like DOM Events, Mouse Move Events

DebugFirebugEventsP5

 

— Using RouteConverters —

RouteConverter 2.16.3

  • RouteConverter 2.16.3 is a great tool to work with GPX tracks
  • It allows you to cut and re-combine Tracks
  • You can easily reverse your Track
  • You can easily restrict the number of waypoints  : Current  setting
    • Use Option 3  : Using Douglas–Peucker algorithm with distance set: 20 meters
    • Use above setting reduces the Jitters from real GPX data for if our waypoints distance is very smal  when doing uphill biking

RouteConverter

Note: 

When using Copy/Paste operation don’t create a NEW instance of the RouteConverter or you may loosing the complete Elevation Information !

Leave a Reply

Your email address will not be published. Required fields are marked *