/ *
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
* /
var trackingcoderegex = /^[0-9a-zA-Z]{5,40}$/ ;
function openTrackingInfoPage ( code ) {
if ( typeof code == "undefined" || code == null || code . trim ( ) == "" ) {
app . input . validate ( "#trackingcode" ) ;
app . toast . show ( {
text : "Please enter a tracking code." ,
position : "bottom" ,
closeTimeout : 2000
} ) ;
return ;
}
router . navigate ( "/track/" + code ) ;
}
function addTrackingSuggestions ( ) {
$ ( "#tracking-history-list ul" ) . html ( "" ) ;
$ ( "#tracking-history-list-empty" ) . addClass ( "display-none" ) ;
$ ( "#tracking-history-list .list" ) . removeClass ( "display-none" ) ;
var history = getTrackingHistory ( ) ;
if ( history == false || history . length == 0 ) {
$ ( "#tracking-history-list-empty" ) . removeClass ( "display-none" ) ;
$ ( "#tracking-history-list .list" ) . addClass ( "display-none" ) ;
} else {
for ( var i = history . length - 1 ; i >= 0 ; i -- ) {
$ ( "#tracking-history-list ul" ) . append ( '<li><a class="item-link item-content hapticbtn tracking-code-history-link" data-trackingcode="' + history [ i ] + '" href="/track/' + history [ i ] + '">'
+ '<div class="item-inner"><div class="item-title">'
+ history [ i ]
+ '</div></div></a></li>' ) ;
}
}
if ( inStorage ( "accountkey" ) && inStorage ( "accountnumber" ) ) {
$ ( "#tracking-account-list-empty" ) . addClass ( "display-none" ) ;
$ ( "#tracking-account-list .list" ) . removeClass ( "display-none" ) ;
apirequest ( SETTINGS . apis . gettrackingnumbers , {
accountnumber : getStorage ( "accountnumber" ) ,
accountkey : getStorage ( "accountkey" )
} , function ( success ) {
if ( success . status == "OK" ) {
$ ( "#tracking-account-list ul" ) . html ( "" ) ;
for ( var i = 0 ; i < success . trackingnumbers . length ; i ++ ) {
$ ( "#tracking-account-list ul" ) . append ( '<li><a class="item-link item-content hapticbtn" href="/track/' + success . trackingnumbers [ i ] . trackingcode + '">'
+ '<div class="item-inner">'
+ '<div class="item-title">'
+ '<div class="item-header">' + success . trackingnumbers [ i ] . nickname + '</div>'
+ success . trackingnumbers [ i ] . trackingcode
+ '<div class="item-footer">' + success . trackingnumbers [ i ] . datetimestring + '</div>'
+ '</div>'
+ '</div></a></li>' ) ;
}
if ( success . trackingnumbers . length == 0 ) {
$ ( "#tracking-account-list-empty" ) . removeClass ( "display-none" ) ;
$ ( "#tracking-account-list .list" ) . addClass ( "display-none" ) ;
}
} else {
$ ( "#tracking-account-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center"><div class="item-title" style="color: var(--f7-list-item-footer-text-color);">Error: ' + success . msg + '</div></div></li>' ) ;
}
} , function ( xhr , status , error ) {
$ ( "#tracking-account-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center"><div class="item-title" style="color: var(--f7-list-item-footer-text-color);">Server or network error. Try again later.</div></div></li>' ) ;
sendErrorReport ( "Tracking" , "Couldn't get account tracking codes" , "Server/network problem: " + xhr . status + ": " + xhr . statusText ) ;
} , "GET" ) ;
} else {
$ ( "#tracking-account-list-empty" ) . removeClass ( "display-none" ) ;
$ ( "#tracking-account-list .list" ) . addClass ( "display-none" ) ;
}
$ ( "#tracking-multi-list-empty" ) . addClass ( "display-none" ) ;
$ ( "#tracking-multi-list .list" ) . removeClass ( "display-none" ) ;
var codes = getTrackingMultiList ( ) ;
if ( codes . length > 0 ) {
$ ( "#tracking-multi-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">Loading...</div></li>' ) ;
// Only update if we're on that tab, since it's not the easiest API call for the server to do
if ( $ ( "#tracking-multi-list" ) . hasClass ( "tab-active" ) ) {
updateTrackingMultiListStatus ( ) ;
}
} else {
$ ( "#tracking-multi-list-empty" ) . removeClass ( "display-none" ) ;
$ ( "#tracking-multi-list .list" ) . addClass ( "display-none" ) ;
}
}
function updateTrackingMultiListStatus ( ) {
var codes = getTrackingMultiList ( ) ;
console . log ( codes . length ) ;
$ ( "#tracking-multi-list-empty" ) . addClass ( "display-none" ) ;
$ ( "#tracking-multi-list .list" ) . removeClass ( "display-none" ) ;
$ ( "#tracking-multi-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center"><div class="item-title">Loading...</div></div></li>' ) ;
if ( codes . length > 0 ) {
$ ( "#tracking-multi-list ul" ) . html ( "" ) ;
for ( var i = 0 ; i < codes . length ; i ++ ) {
$ ( "#tracking-multi-list ul" ) . append ( '<li><div style="cursor: pointer;" class="item-content tracking-code-multi-link noselect" data-trackingcode="' + codes [ i ] . code + '" onclick="router.navigate(\'/track/' + codes [ i ] . code + '\')">'
+ '<div class="item-inner item-cell">'
+ ( codes [ i ] . nick == "" ? "" : '<div class="item-row"><div class="item-cell"><b>' + codes [ i ] . nick + '</b></div></div>' )
+ '<div class="item-row"><div class="item-cell">' + codes [ i ] . code + '</div></div>'
+ '<div class="item-row"><div class="item-cell">'
+ '<img src="" class="trackingeventicon tracking-multi-status-icon" /> <span class="tracking-multi-status-text"></span>'
+ '</div></div></div></div></li>' ) ;
}
var codelist = [ ] ;
for ( var i = 0 ; i < codes . length ; i ++ ) {
codelist . push ( codes [ i ] . code ) ;
}
apirequest ( SETTINGS . apis . trackmultiple , {
code : codelist . join ( "," )
} , function ( resp ) {
if ( resp . status == "OK" ) {
for ( const code in resp . results ) {
$ ( ".tracking-code-multi-link[data-trackingcode=\"" + code + "\"] .tracking-multi-status-text" ) . text ( resp . results [ code ] . text ) ;
$ ( ".tracking-code-multi-link[data-trackingcode=\"" + code + "\"] .tracking-multi-status-icon" ) . attr ( "src" , "./assets/images/icons/" + resp . results [ code ] . icon + ".svg" ) ;
}
$ ( "#tracking-multi-list ul" ) . append ( '<li class="item-content"><div class="item-inner display-block text-align-center noselect" style="color: var(--f7-list-item-footer-text-color);"><i class="fas fa-info-circle"></i> <span class="taptext">Long-press</span><span class="clicktext">Right-click</span> an entry to remove it.</div></li>' ) ;
} else {
$ ( "#tracking-multi-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">Error: ' + resp . msg + '</div></li>' ) ;
sendErrorReport ( "Tracking" , "Couldn't get multi tracking" , resp . msg ) ;
}
} , function ( xhr ) {
try {
var resp = $ . parseJSON ( xhr . responseText ) ;
if ( resp && typeof resp . msg != 'undefined' ) {
$ ( "#tracking-multi-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center text-align-center">Error: ' + resp . msg + '</div></li>' ) ;
sendErrorReport ( "Tracking" , "Couldn't get multi tracking" , resp . msg ) ;
} else {
$ ( "#tracking-multi-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">There\'s a server or network problem. Check your Internet connection or try again later.</div></li>' ) ;
sendErrorReport ( "Tracking" , "Couldn't get multi tracking" , "Server/network problem: " + xhr . status + ": " + xhr . statusText ) ;
}
} catch ( ex ) {
$ ( "#tracking-multi-list ul" ) . html ( '<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">There\'s a server or network problem. Check your Internet connection or try again later.</div></li>' ) ;
sendErrorReport ( "Tracking" , "Couldn't get multi tracking" , "Server/network problem: " + xhr . status + ": " + xhr . statusText ) ;
}
} ) ;
} else {
$ ( "#tracking-multi-list-empty" ) . removeClass ( "display-none" ) ;
$ ( "#tracking-multi-list .list" ) . addClass ( "display-none" ) ;
}
}
function openTrackingBarcodeScanner ( ) {
scanBarcode ( function ( result ) {
var code = "" ;
if ( result . startsWith ( "https://helena.express/track#" ) ) {
code = result . split ( "#" ) [ 1 ] ;
} else if ( result . startsWith ( "http" ) && result . includes ( "#" ) ) {
if ( trackingcoderegex . test ( result . split ( "#" ) [ 1 ] ) ) {
code = result . split ( "#" ) [ 1 ] ;
} else {
app . dialog . alert ( "This app can't understand what's in that barcode." , "Error" ) ;
return ;
}
} else if ( trackingcoderegex . test ( result ) ) {
code = result ;
} else {
app . dialog . alert ( "This app can't understand what's in that barcode." , "Error" ) ;
return ;
}
code = code . toUpperCase ( ) ;
openTrackingInfoPage ( code ) ;
} , function ( ) {
app . dialog . alert ( "Something went wrong and we can't scan right now." , "Error" ) ;
} ) ;
}
function trackOpenAsync ( { to , resolve , reject } ) {
app . dialog . preloader ( "Loading..." ) ;
apirequest (
SETTINGS . apis . track ,
{
code : to . params . code ,
format : "json"
} ,
function ( resp ) {
app . dialog . close ( ) ;
if ( resp . status == "OK" ) {
addToTrackingHistory ( resp . code ) ;
var context = {
code : resp . code ,
info : [
{ label : "Tracking Code" , value : resp . code } ,
] ,
events : [ ] ,
map : {
enabled : ( typeof resp . info . latitude == "number" && typeof resp . info . longitude == "number" && MapControl . supported ( ) ) ,
latitude : resp . info . latitude ,
longitude : resp . info . longitude ,
accurate : resp . info . geoaccurate ,
geoiscountrylevel : ( typeof resp . info . geoiscountrylevel == "undefined" ? false : resp . info . geoiscountrylevel )
}
} ;
if ( resp . info . statustext ) {
context . info . push ( { label : "Status" , value : resp . info . statustext } ) ;
}
if ( resp . info . carrier ) {
if ( resp . info . carrier _logo ) {
context . info . push ( { label : "Carrier" , value : "<img style=\"height: 2em; padding: 0.667em; max-width: 80%; background-color: white; border-radius: 0.25em; margin-top: 0.5em;\" src=\"" + resp . info . carrier _logo + "\" />" } ) ;
} else {
context . info . push ( { label : "Carrier" , value : resp . info . carrier } ) ;
}
}
if ( resp . info . delivery _date ) {
var deliverydatelabel = "Estimated delivery on" ;
if ( resp . info . status == "DELIVERED" ) {
deliverydatelabel = "Delivered on" ;
}
context . info . push ( { label : deliverydatelabel , value : formatTimestamp ( "F j Y" , resp . info . delivery _date _unixtime ) } ) ;
}
if ( resp . info . carrier _tracking _url ) {
context . carrierurl = resp . info . carrier _tracking _url ;
}
if ( resp . info . carrier _attribution ) {
context . carrier _attribution = resp . info . carrier _attribution ;
}
for ( var i = 0 ; i < resp . events . length ; i ++ ) {
context . events . push ( {
text : resp . events [ i ] . text ,
date : resp . events [ i ] . timestring ,
icon : "./assets/images/icons/" + resp . events [ i ] . icon + ".svg"
} ) ;
}
if ( context . events . length == 0 ) {
context . events = false ;
}
sendActionReport ( "Tracking" , "Tracked package" ) ;
resolve ( {
content : compiledPages . trackresult ( context )
} ) ;
} else {
app . dialog . alert ( resp . msg , "Error" ) ;
sendErrorReport ( "Tracking" , "Couldn't get tracking" , resp . msg ) ;
reject ( ) ;
}
} ,
function ( xhr ) {
app . dialog . close ( ) ;
try {
var error = $ . parseJSON ( xhr . responseText ) ;
if ( error && typeof error . msg != 'undefined' ) {
app . dialog . alert ( error . msg , "Error" ) ;
sendErrorReport ( "Tracking" , "Couldn't get tracking" , error . msg ) ;
} else {
app . dialog . alert ( "There's a server or network problem. Check your Internet connection or try again later." , "Error" ) ;
sendErrorReport ( "Tracking" , "Couldn't get tracking" , "Server/network problem: " + xhr . status + ": " + xhr . statusText ) ;
}
} catch ( ex ) {
app . dialog . alert ( "There's a server or network problem. Check your Internet connection or try again later." , "Error" ) ;
sendErrorReport ( "Tracking" , "Couldn't get tracking" , "Server/network problem: " + xhr . status + ": " + xhr . statusText ) ;
}
reject ( ) ;
} , "GET" ) ;
}
$ ( "#app" ) . on ( "submit" , "#tracking-searchbar-form" , function ( evt ) {
evt . preventDefault ( ) ;
openTrackingInfoPage ( $ ( 'input[name=\'trackingcode\']' ) . val ( ) ) ;
return false ;
} ) ;
$ ( "#app" ) . on ( "contextmenu taphold" , ".tracking-code-history-link" , function ( evt ) {
evt . preventDefault ( ) ;
// Don't trigger contextmenu on a touch device because we'll also get a taphold
if ( evt . type == "contextmenu" && window . matchMedia ( "(pointer: coarse)" ) . matches ) {
return ;
}
var code = $ ( this ) . data ( "trackingcode" ) ;
var action = app . actions . create ( {
buttons : [
[
{
text : 'Track' ,
bold : true ,
onClick : function ( ) {
openTrackingInfoPage ( code ) ;
}
} ,
{
text : 'Add to Multi list' ,
onClick : function ( ) {
addToTrackingMultiList ( code ) ;
addTrackingSuggestions ( ) ;
}
} ,
{
text : 'Remove From History' ,
onClick : function ( ) {
removeFromTrackingHistory ( code ) ;
addTrackingSuggestions ( ) ;
}
}
] ,
[
{
text : 'Cancel' ,
color : 'red'
}
]
]
} ) ;
action . open ( ) ;
return false ;
} ) ;
$ ( "#app" ) . on ( "contextmenu taphold" , ".tracking-code-multi-link" , function ( evt ) {
evt . preventDefault ( ) ;
// Don't trigger contextmenu on a touch device because we'll also get a taphold
if ( evt . type == "contextmenu" && window . matchMedia ( "(pointer: coarse)" ) . matches ) {
return ;
}
var code = $ ( this ) . data ( "trackingcode" ) ;
var action = app . actions . create ( {
buttons : [
[
{
text : 'Open' ,
bold : true ,
onClick : function ( ) {
openTrackingInfoPage ( code ) ;
}
} ,
{
text : 'Add/Change Nickname' ,
onClick : function ( ) {
app . dialog . prompt ( "Set a nickname for " + code , "Package Name" , function ( input ) {
addNicknameToTrackingMultiList ( code , htmlEntities ( input ) ) ;
updateTrackingMultiListStatus ( ) ;
} , function ( ) {
// canceled
} , "" ) ;
}
} ,
{
text : 'Remove from list' ,
onClick : function ( ) {
removeFromTrackingMultiList ( code ) ;
addTrackingSuggestions ( ) ;
}
}
] ,
[
{
text : 'Cancel' ,
color : 'red'
}
]
]
} ) ;
action . open ( ) ;
return false ;
} ) ;
$ ( "#app" ) . on ( "contextmenu taphold" , "#brokenscannercodeadd" , function ( evt ) {
evt . preventDefault ( ) ;
// Don't trigger contextmenu on a touch device because we'll also get a taphold
if ( evt . type == "contextmenu" && window . matchMedia ( "(pointer: coarse)" ) . matches ) {
return ;
}
var code = $ ( 'input[name=\'trackingcode\']' ) . val ( ) . trim ( ) . replace ( /\s/ , "" ) ;
var action = app . actions . create ( {
buttons : [
[
{
text : 'Track' ,
bold : true ,
onClick : function ( ) {
if ( code == "" ) {
app . dialog . alert ( "You need to type a tracking code first." , "Error" ) ;
return ;
}
openTrackingInfoPage ( code ) ;
}
} ,
{
text : 'Add to Multi list' ,
onClick : function ( ) {
if ( code == "" ) {
app . dialog . alert ( "You need to type a tracking code first." , "Error" ) ;
return ;
}
if ( ! code . match ( trackingcoderegex ) ) {
app . dialog . alert ( "That doesn't seem like a valid tracking code." , "Error" ) ;
return ;
}
addToTrackingMultiList ( code ) ;
addTrackingSuggestions ( ) ;
}
}
] ,
[
{
text : 'Cancel' ,
color : 'red'
}
]
]
} ) ;
action . open ( ) ;
return false ;
} ) ;
$ ( "#app" ) . on ( "tab:show" , "#tracking-multi-list" , function ( evt ) {
updateTrackingMultiListStatus ( ) ;
} ) ;
function getTrackingHistory ( ) {
var history = getStorage ( "trackinghistory" ) ;
if ( history == "false" || history == "null" || history == null ) {
return [ ] ;
} else {
return JSON . parse ( history ) ;
}
}
function addToTrackingHistory ( code ) {
var history = getTrackingHistory ( ) ;
for ( var i = 0 ; i < history . length ; i ++ ) {
if ( history [ i ] == code ) {
history . splice ( i , 1 ) ;
}
}
// Add the code back to the list so it's at the top
history . push ( code ) ;
while ( history . length > 10 ) {
history . shift ( ) ;
}
setStorage ( "trackinghistory" , JSON . stringify ( history ) ) ;
}
function removeFromTrackingHistory ( code ) {
var history = getTrackingHistory ( ) ;
for ( var i = 0 ; i < history . length ; i ++ ) {
if ( history [ i ] == code ) {
history . splice ( i , 1 ) ;
}
}
while ( history . length > 10 ) {
history . shift ( ) ;
}
setStorage ( "trackinghistory" , JSON . stringify ( history ) ) ;
$ ( ".tracking-code-history-link[data-trackingcode=\"" + code + "\"]" ) . parent ( "li" ) . remove ( ) ;
}
function getTrackingMultiList ( ) {
var multilist = getStorage ( "multitrackingcodes" ) ;
if ( multilist == "false" || multilist == "null" || multilist == null ) {
return [ ] ;
} else {
var multilistjson = JSON . parse ( multilist ) ;
if ( multilistjson . length > 0 ) {
if ( typeof multilistjson [ 0 ] == "object" ) {
return multilistjson ;
} else {
// Old version is just string array, new version is array of objects,
// do a conversion
// TODO: Remove this code once everyone's updated to this version, since it's not efficient to do typeof every time
var newmultilist = [ ] ;
for ( var i = 0 ; i < multilistjson . length ; i ++ ) {
newmultilist . push ( {
code : multilistjson [ i ] ,
nick : ""
} ) ;
}
setStorage ( "multitrackingcodes" , JSON . stringify ( newmultilist ) ) ;
return newmultilist ;
}
} else {
return [ ] ;
}
}
}
function addToTrackingMultiList ( code , nickname ) {
if ( typeof nickname != "string" ) {
nickname = "" ;
}
var multilist = getTrackingMultiList ( ) ;
for ( var i = 0 ; i < multilist . length ; i ++ ) {
if ( multilist [ i ] . code == code ) {
// Already in list, remove so we can add with the new nick if set
multilist . splice ( i , 1 ) ;
}
}
// Add the code to the list
multilist . push ( {
code : code ,
nick : nickname
} ) ;
setStorage ( "multitrackingcodes" , JSON . stringify ( multilist ) ) ;
}
function addNicknameToTrackingMultiList ( code , nickname ) {
var multilist = getTrackingMultiList ( ) ;
for ( var i = 0 ; i < multilist . length ; i ++ ) {
if ( multilist [ i ] . code == code ) {
multilist [ i ] . nick = nickname ;
}
}
setStorage ( "multitrackingcodes" , JSON . stringify ( multilist ) ) ;
}
function removeFromTrackingMultiList ( code ) {
var multilist = getTrackingMultiList ( ) ;
for ( var i = 0 ; i < multilist . length ; i ++ ) {
if ( multilist [ i ] . code == code ) {
multilist . splice ( i , 1 ) ;
}
}
setStorage ( "multitrackingcodes" , JSON . stringify ( multilist ) ) ;
$ ( ".tracking-code-multi-link[data-trackingcode=\"" + code + "\"]" ) . parent ( "li" ) . remove ( ) ;
}