var MOCA_HOME_ID = 225;
    var MOCA_BASE_URL = 'https://book.artgallery.org.nz/';
    var MOCA_BASE_DIR = '/';
    var MOCA_HOME_URL = 'https://book.artgallery.org.nz/home';
    var MOCA_BASE_ENTITY = 'Event';
    var MOCA_BASE_ENTITYL = 'event';
    var MOCA_HOST_ENTITY = '';
    var MOCA_TICKET_ENTITY = 'Ticket';
    var MOCA_TICKET_ENTITYL = 'ticket';
    var MOCA_TICKET_HOLDER_ENTITY = 'Ticket-holder';
    var MOCA_TICKET_HOLDER_ENTITYL = 'ticket-holder';
    var MOCA_ROADSHOW_ENTITY = 'Series';
    var MOCA_ROADSHOW_ENTITYL = 'series';
    var MOCA_USE_MIDDLE_NAME = '';
    var MOCA_USE_TYPES = '2';
    var MOCA_USE_QUALS = '';
    var MOCA_USE_CERTS = '';
var BR_CURRENT_COUNTRY = {"timezone":"NZDT","currency":"NZD","ccode":"NZ","icode":"64","name":"New Zealand"};
    var MOCA_USE_PARTNERS = '';
    // Default table listing row bg colour
    var MOCA_TABLE_BG_DEFAULT = '#fff';
    // Used to stripe listing tables for readability
    var MOCA_TABLE_BG = '#f3f3f3';   // Back-end
    var MOCA_SITE_TABLE_BG = '#f4f4f4'; // Front-end
    var MOCA_TABLE_BG_BLUE = '#eceff5';
    // Highlight record being edited
    var MOCA_TABLE_HIGHLIGHT = '#ffc';
    // Highlight just-created field
    var MOCA_TABLE_NEW_ROW = 'pink';
// Deprecated! [multiple currencies for orgs now pos
//    var MOCA_GST_RATE = 15;
    // eg: Optional ticket holder fields
	var MOCA_FIELD_EXISTS = 1;
	var MOCA_FIELD_REQUIRED = 2;
	var MOCA_BR_ADMIN_PRICE_TYPE_DOLLARS = 'dollars';
	var MOCA_BR_ADMIN_PRICE_TYPE_PERCENTAGE = 'percentage';
	var MOCA_FUNC_UPDATE = 'update';
	var MOCA_FUNC_ADD = 'add';
	var MOCA_FUNC_DELETE = 'delete';
	var MOCA_FUNC_PROGRESS = 'progress';
    var MOCA_CURRENT_YEAR = 2025;
    var MOCA_AGE_LIMIT = 0;
    var MOCA_MAX_ATTENDEE_YEAR = 2025;
    var MOCA_ECOMMERCE_TRACKING = '';
    var MOCA_SHARED_SITE = false;
    /* Common Stylesheet colours: */
    var MOCA_BR_CSS_ORANGE   = '#d76927';
    var MOCA_BR_CSS_BROWN    = '#6B4936';
    var MOCA_BR_CSS_DISABLED = '#9a9a9a';
// ckeditor
window.WEBSPELLCHECKER_CONFIG = {
        autoSearch: true,
        lang: 'en_NZ',
        serviceId: 'UpGWdGRTXqi7SoK'
   };
    var MOCA_MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    var MOCA_MONTH_NAMES = ['January','February','March','April','May','June','July','August','September','October','November','December'];
    $.ajaxSetup({
            //cache:false,
        error:function(x,e){
            unthrob();
            if(x.status==0){
                // mocaAlert('No network found','Please try again');
            }else if(x.status==404){
                mocaAlert('Requested url not found','Whoops!');
            }else if(x.status==500){
                mocaAlert('A server error '+x.responseText+' - please contact the administrator','Whoops!');
            }else if(e=='parsererror'){
                mocaAlert('
Houston, we have a problem!
For help, please call 07 575 6903 or brendon@bookingrooster.co.nz .
If you\'re a technology whiz it\'s ideal to send a screenshot of this page when you contact us
','Whoops!');
            }else if(e=='timeout'){
                mocaAlert('Request time out','Please Try Again');
            }else {
                //mocaAlert('Unknown Ajax Error: '+x.responseText);
            }
        }
    });
    function throb(el){
        if(el){
            $('#ajaxBusy').css('top',(el.offset()).top);
        }
        $('.ajaxBusy').show();
        return true;
    }
    function unthrob(){return $('.ajaxBusy').hide(); }
// For ajax calls
var Func = {
        add:'add',
        edit:'edit',
        delete:'delete',
        status:'status',
        update:'update',
        progress:'progress',
        search:'search',
        costs: 'costs'
    };
    // Dismiss status messages when anything clicked:
    // $(document).ready(function(){$("*", document.body).bind('click',function(){$('#statusMessage').text('');});});
    // Populated by MocaForm::initJavascript()
    var Help = {};
    // Whether fckeditor should use default fe stylesheet
    var MocaFckStyles = true;
    function logout(){
        window.location.href = MOCA_BASE_URL + 'sitemgr/logout.php';
    }
    function highlightRows(table_id, no_header_row,skip){
      /* Given the ID of a table element, set every alternate
         row's background colour to MOCA_TABLE_BG colour. Unless
         no_header_row is set, the first row will be left untouched.
         Apply the class 'nonList' to any rows you want skipped
      */
        var odd = false;
        var first = true;
        $('TABLE#' + table_id + ' TR:not(.nonList)').map(
            function(){
                if(!no_header_row && first){skip--;first = false;return;}
                if(skip){odd=true;skip--;return;}
                if($(this).css('display')!='none'){
                  $('*:not(.nonList)',$(this)).map(function(){this.style.backgroundColor = odd ? MOCA_TABLE_BG : '';});
                  odd = !odd;
                }
            })
    }
    function feHighlightRows(table_id, no_header_row,skip,colour){
      /* Same for front-end
      */
        var odd = true;
        var first = true;
        var clr = colour ? colour : MOCA_SITE_TABLE_BG;
        $('TABLE#' + table_id + '>TBODY>TR:not(.nonList)').map(
            function(){
                if(!no_header_row && first){skip--;first = false;return;}
                if(skip){odd=true;skip--;return;}
                if($(this).css('display')!='none'){
                  $('TD:not(.nonList)',$(this)).map(function(){this.style.backgroundColor = odd ? clr : '';});
                  odd = !odd;
                }
            })
    }
    function highlightOptions(select_id,colour ){
      /* Given the ID of a select element, set every alternate
         option's background colour to given colour.MOCA_TABLE_BG colour.
      */
        colour = colour ? colour : MOCA_TABLE_BG;
        var odd = false;
        $('SELECT#' + select_id + ' OPTION:not(.nonList)').map(
            function(){
                if($(this).css('display')!='none'){
                    this.style.backgroundColor = odd ? colour : '';
                    odd = !odd;
                }
            })
    }
    function feHighlightOptions(select_id,colour ){
      /* Given the ID of a select element, set every alternate
         option's background colour to given colour.MOCA_TABLE_BG colour.
      */
        colour = colour ? colour : MOCA_SITE_TABLE_BG;
        var odd = false;
        $('SELECT#' + select_id + ' OPTION:not(.nonList)').map(
            function(){
                if($(this).css('display')!='none'){
                    this.style.backgroundColor = odd ? colour : '';
                    odd = !odd;
                }
            })
    }
    function FCKeditor_OnComplete(ed){
        // Called by editor onLoad, change internal
        // stylesheet to that initialised by moca.form
        if(!MocaFckStyles){return;}
        //var ht = ed.GetData();
        if($('#moca_browser').val()){
            ed.Config['ImageBrowserWindowWidth'] =  ed.Config['ScreenWidth'] * 0.4;
            ed.Config['ImageBrowserWindowHeight'] =  ed.Config['ScreenHeight'] * 0.4;
            ed.Config['LinkBrowserWindowWidth'] =  ed.Config['ScreenWidth'] * 0.5;
            ed.Config['LinkBrowserWindowHeight'] =  ed.Config['ScreenHeight'] * 0.5;
            ed.Config['LinkBrowserURL'] = ed.Config['BasePath'] + 'filemanager/browser/link/fe_browser.php' ;
        }
    }
    function deleteFromListing(frm,ids){
        // Delete records from listing page - ids is either array or
        // comma-separated string of ids. Form is DOM element
        frm.id_list.value = typeof ids == 'string' ? ids : ids.join(',');
        frm.func.value = 'delete';
        frm.submit();
    }
    // Convenience func for use in mocaConfirm & ilk
    function goto(href){window.location.href=href;}
    function showHelp(id){
        if((Help == undefined) || !Help[id]){return;}
        mocaAlert(Help[id],'Help');
    }
function initHelp(){
        $('.mfHelp').click(function() {
            if($(this).data("qtip")) $(this).qtip("destroy");
            var n = this.id.substr(7)=='mfHelp_' ? this.id.substr(7) : this.id;
            if((Help == undefined) || !Help[n]){return;}
            var pos = $(this).hasClass('topLeft') ?
                {corner:{target:'topLeft',tooltip:'topRight'}} :
                ($(this).hasClass('bottomLeft') ?
                    {corner:{target:'bottomLeft',tooltip:'topRight'}} :
                    {corner:{target:'topRight',tooltip:'leftBottom'}});
            $(this).qtip({
                content:Help[n],
                position:pos,
                show:{when:false, ready:true},
                hide:{when:'unfocus'},
                style: {
                    border:{width:5,radius:10,color:'#000000'},
                    padding:10,
                    background:'#000000',
                    color:'#ffffff',
                    textAlign: 'left',
                    tip: true,
                    name: 'cream'
                }
            });
        });
}
    // Front-end BR help
    $(document).ready(function(){
        initHelp();
        return false;});
    function mocaPrompt(str,func,title) {
        str = str.indexOf('<')>-1 ? str : '' + str + '
';
        str += '' + str + '
');
        $('#mocaDialog').dialog({ appendTo:document.body,
                'close':function(){$('#mocaDialog').remove();},
                'buttons': {
                    'Ok': function() {
                        var answer = jQuery('#mocaDialogText').val();
                        func(answer);
                        $(this).dialog("close");
                    },
                    'Cancel': function() {$(this).dialog("close");}
                    }
                });
    }
    function mocaConfirm(str,func,title){
        title = arguments[2] ? arguments[2] : 'Please Confirm';
        switch('jquidialog'){
            case 'jquidialog':
                str = str.indexOf('<')>-1 ? str : '' + str + '
';
                $('BODY').append('' + str + '
');
                $('#mocaDialog').dialog({ appendTo:document.body,
                        'close':function(){$('#mocaDialog').remove();},
                        'buttons': {
                            'Ok': function() {func(); $(this).dialog("close");},
                            'Cancel': function() {$(this).dialog("close");}
                            }
                        });
                break;
            case 'jqalert':
                return jAlert(str,title);
                break;
            default:
                return alert(str);
                break;
        }
    }
function mocaAlert(str,title,pos){
        /* Custom alert. First arg is message string. Second is title. Third is
          function to be executed on close. Only the first is mandatory */
        title = title ? title : '';
        var func = arguments[2] ? arguments[2] : null;
        switch('jquidialog'){
            case 'jquidialog':
                str = str.includes('<') ? str : '' + str + '
';
                if($('#mocaDialog').length==0){
                    $('body').append('' + str + '
');
                }
                else{
                    $('#mocaDialog').attr('title',title).html(str);
                }
                !pos ? $('#mocaDialog').dialog({title:title,buttons:{'Ok':function(){$(this).dialog('close');}}})
                                       :
                  $('#mocaDialog').dialog({title:title,
                                  position:{my:'left top',at:'left top',of: pos},
                                  buttons:{'Ok':function(){$(this).dialog('close');}}});
                return false;
                /*{
                         appendTo:'body',
                        'close':function(){if(func){func();}else{$(this).remove();}},
                        'buttons': {
                            'Ok': function() {
                                if(func){func();}
                                else {$(this).remove();}
                            }
                        }
                });
                if(jQuery().easydrag){
                    $('.ui-dialog').easydrag();
                }
                */
                break;
            case 'jqalert':
                return jAlert(str,title);
                break;
            default:
                return alert(str);
                break;
        }
    }
        var BrAudioContext = null;
function beep(vol, freq, duration){
    if(!BrAudioContext){BrAudioContext = new AudioContext();}
    vol = vol ? vol : 2000;
    freq = freq ? freq : 800;
    duration = duration ? duration : 60;
  v=BrAudioContext.createOscillator()
  u=BrAudioContext.createGain()
  v.connect(u)
  v.frequency.value=freq
  v.type="sine"
  u.connect(BrAudioContext.destination)
  u.gain.value=vol*0.01
  v.start(BrAudioContext.currentTime)
  v.stop(BrAudioContext.currentTime+duration*0.001)
}
function burp(){
    console.log('burp()');
beep(0,500,300);
}
function validateDob(dob){
    // Implementation of age limit
	if(!MOCA_AGE_LIMIT || MOCA_AGE_LIMIT==0){return true;}
	dob = dob.mocaReverseDate();
	var now = new Date();
	var born = new Date(Date.parse(dob));
    var birthday = new Date(now.getFullYear(), born.getMonth(), born.getDate());
    var age =  now >= birthday ? now.getFullYear() - born.getFullYear() : now.getFullYear() - born.getFullYear() - 1;
	return age >= MOCA_AGE_LIMIT;
}
    function is_numeric(el){
        return (typeof(el) === 'number' || typeof(el) === 'string') && el !== '' && !isNaN(el);
    }
    function to_decimal(n){
        n = new Number(n);
        return n.toFixed(2);
    }
    function bidf(id){
        // Apply prefix and pad booking id
        if(!is_numeric(id)){return id;}
        if(id < 10000){
            id = String(id);
            id = id.mocaPad(5);
        }
        return 'BRN' + id;
    }
	String.prototype.mocaEnglishify = function(){
	    var last = this[this.length-1];
        if ((this[this.length-2]=='1' && last=='1') || (this[this.length-2]=='1' && last=='2')){
	           return this+'th';
        }
	        switch (last) {
	            case '1':
	                return this + 'st';
	            case '2':
	                return this + 'nd';
	            case '3':
	                return this+'rd';
	            default:
	                return this+'th';
	        }
	};
	String.prototype.mocaStartsWithVowel = function(){
		var v=['a','e','i','o','u','A','E','I','O','U'];
		for(i=0; i"'`]/g, function (chr) { // "
            return '' + chr.charCodeAt(0) + ';';});
    };
    String.prototype.mocaCamelCase = function(){
        var s = $.trim( this.toLowerCase() );
        return s.replace( / ([a-z])/g, function(t,b) { return b.toUpperCase(); } );
    };
    String.prototype.mocaCapitalize = function(){
       return this.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase(); } );
    };
    String.prototype.mocaPad = function(num,char){
        char = char || '0';
        return this.length >= num ? this : new Array(num - this.length + 1).join(char) + this;
    };
	String.prototype.mocaUcWords = function() {
	  str = this.toLowerCase();
	  return str.replace(/(^([a-zA-Z\p{M}]))|([ -][a-zA-Z\p{M}])/g,
	  	function(s){
	  	  return s.toUpperCase();
		});
	};
    String.prototype.mocaReverseDate = function(){
        if(this.match(/(\d{4})-(\d{2})-(\d{2})/g)){
            var s = this.split('-');
            return s[2]+'-'+s[1]+'-'+s[0];
        }
        if(this.match(/(\d{2})-(\d{2})-(\d{4})/g)){
            var s = this.split('-');
            return s[2]+'-'+s[1]+'-'+s[0];
        }
        return this;
    };
    String.prototype.mocaValidDate = function(){
        if(res = this.match(/^(\d{1,2})-(\d{1,2})-(\d{2,4})$/)){
            var d;var m;var y;
            d = new Number(res[1]);
            if(d<1 || d>31){return false;}
            m = new Number(res[2]);
            if(m<1 || m>12){return false;}
            if(res[3].length==2){
                y = new Number(res[3]);
                if(y<50){y = y + 2000;}
                else{y = y + 1900;}
            }
            else{
	            if(res[3].length==3){return false;}
	            if(res[3].length==4){
	                y = new Number(res[3]);
	                if(y<1900 || y>2099){return false;}
	            }
            }
            return new Date(y,m-1,d);
        }
        else{
            return false;
        }
    };
    Array.prototype.mocaRemove = function(x) {
        var pos = -1;
        for(var i=0; imax){max=this[i];}
        }
        return max;
    };
	function objectSize(obj){
	    var size = 0, key;
	    for (key in obj) {
	        if (obj.hasOwnProperty(key)) size++;
	    }
	    return size;
	}
    Date.prototype.mocaToString=function() {
        // 03-12-2010
        var d = String(this.getDate());var m = String(this.getMonth()+1); var y = String(this.getYear()+1900);
        return d.mocaPad(2) + '-' + m.mocaPad(2) + '-' + y;
    };
    Date.prototype.mocaToLongString=function() {
        // 3 Apr 2015 11:58
        return String(this.getDate()) + ' ' + MOCA_MONTHS[this.getMonth()] + ' ' + String(this.getYear()+1900) + ' ' + this.getHours() + ':' + this.getMinutes();
    };
    $(document).ready(function(){
            (function($){
                // Legacy - old formbuilder edit field js
                      $.fn.positionCenter = function(options) {
                        var pos = {
                          sTop : function() {
                            return window.pageYOffset
                            || document.documentElement && document.documentElement.scrollTop
                            ||  document.body.scrollTop;
                          },
                          wHeight : function() {
                            return window.innerHeight
                            || document.documentElement && document.documentElement.clientHeight
                            || document.body.clientHeight;
                          }
                        };
                        return this.each(function(index) {
                          if (index == 0) {
                            var $this = $(this);
                            var elHeight = $this.outerHeight();
                            var elTop = pos.sTop() + (pos.wHeight() / 2) - (elHeight / 2);
                            $this.css({
                              position: 'absolute',
                              margin: '0',
                              top: elTop,
                              left: (($(window).width() - $this.outerWidth()) / 2) + 'px'
                            });
                          }
                        });
                      };
            })(jQuery);
    })
$.fn.centerIt = function() {
    this.css({
        'position': 'fixed',
        'left': '50%',
        'top': '50%'
    });
    this.css({
        'margin-left': -this.outerWidth() / 2 + 'px',
        'margin-top': -this.outerHeight() / 2 + 'px'
    });
    return this;
}
    var MocaCookiesEnabled = false;
    function clientCookieCheck(){
        // Call in form pages reliant on sessions
        setCookie('test_name','test_value',0);
        var ck = getCookie('test_name');
        if(!ck || (ck != 'test_value')) {
            return mocaAlert('Your browser and/or network is not configured '+
                         'to use "cookies". To use this site you must be able to send and receive cookies '+
                         'from our server. Until you can do so you will not  be able to continue.');
        }
        else {
            MocaCookiesEnabled = true;
            deleteCookie('test_name');
        }
    }
    function setCookie(name,
                   value,
                   expires // in X days
                   ){
        /*
         OPTIONAL PARAMS:
         path - where valid, usually '/'
         domain - all crossing of subdomain
         secure
        */
        var today = new Date();
        today.setTime( today.getTime() );
        var expires_date = new Date( today.getTime() + (expires ? expires*1000*60*60*24 : 0) );
        document.cookie = name+'='+escape( value ) +
            (expires ? ';expires='+expires_date.toGMTString() : '' ) + //expires.toGMTString()
            (arguments[3]? ';path='   + arguments[3] : '' ) +
            (arguments[4]? ';domain=' + arguments[4] : '' ) +
            (arguments[5]? ';secure' : '' );
    }
    function getCookie(name) {
        var start = document.cookie.indexOf( name + "=" );
        var len = start + name.length + 1;
        if (!start && name != document.cookie.substring( 0, name.length )) {return null;}
        if (start == -1) {return null;}
        var end = document.cookie.indexOf( ';', len );
        if ( end == -1 ) end = document.cookie.length;
        return unescape( document.cookie.substring( len, end ) );
    }
    function deleteCookie(name){
        if (getCookie(name)){
            document.cookie = name + '='   +
                (arguments[1] ? ';path='   + arguments[1] : '') +
                (arguments[2] ? ';domain=' + arguments[2] : '' ) +
                ';expires=Thu, 01-Jan-1970 00:00:01 GMT';
            }
    }
    // str * num : mult('0',5) = '00000'
    function mult(str, num) {
        return num ? Array(num + 1).join(str) : "";
    }
    function showTerms(){
        $.fancybox.init();
        $.fancybox({
                'hideOnOverlayClick':true,
                'overlayShow':true,
                'overlayOpacity':0.5,
         //                'transitionIn':'fade',
         //                'transitionOut':'fade',
         //                'speedOut':700,
                'type':'iframe',
                'scrolling':'auto',
                'height':650,
         'width':750,
                'titleShow':false,
                'href':'https://book.artgallery.org.nz/terms_of_use_popup'
        });
        $("#fancybox-wrap").easydrag();
    }
    function showLogin(id){
        $.fancybox.init();
        $.fancybox({'hideOnContentClick':false,
                'hideOnOverlayClick':false,
                'overlayShow':true,
                'overlayOpacity':0.9,
                'speedIn':1700,
                'transitionIn':'fade',
                'transitionOut':'fade',
                'speedOut':700,
                'type':'iframe',
                'scrolling':'no',
                'height':550,
                'titleShow':false,
                'href':'https://book.artgallery.org.nz/user_login_iframe?id='+id // user_login_iframe
        });
        $("#fancybox-wrap").easydrag();
    }
    function reflectLogin(){
        $.fancybox.close();
        self.location.reload(true);
    }
    function showSuggestUpgrade(goback,target){
        $.fancybox({'hideOnContentClick':false,
                'hideOnOverlayClick':false,
                'overlayShow':true,
                'overlayColor':'#d76927',
                'overlayOpacity':0.6,
                'speedIn':600,
                'transitionIn':'fade',
                'transitionOut':'fade',
                'speedOut':700,
                'type':'iframe',
                'height':450,
                'width':600,
                'titleShow':false,
                'onCleanup':function(){parent.location.href = 'https://book.artgallery.org.nz/' + goback;},
                'href':'https://book.artgallery.org.nz/suggest_upgrade/anc/'+target
        });
        $("#fancybox-wrap").easydrag();
    }
    function takeUpgrade(){
        parent.location.href = 'https://book.artgallery.org.nz/organisation_plans/upgr/1';
    }
    // DEV tool
        function dump(obj){
        var str='';
        for(p in obj){
            if (!obj.hasOwnProperty(p)) {
                continue;
            }
            var _str = typeof obj[p] === 'object' && obj[p] !== null ? (p + ' = %o', obj[p]) : obj[p];
            str = str + p + ' = ' + _str + "\n";
        }
        return str;
    }
    function parsePh(ph){
        ph = $.trim(ph);
        var bits = [];
        // Only bother with phone number if it's easily parseable:
        if(ph.indexOf(',') != -1){
            return ph.split(',');
        }
        else{
            var _bits = ph.split(' ');
            if(_bits.length==4){
                //std case
                return [_bits[0],_bits[1],_bits[2]+' '+_bits[3]];
            }
            if(_bits.length==3){
                //var num = _bits[1]+_bits[2];
                //if(num.length>7){
                if(_bits[2].length<6){
                    // no intl code
                    return ['',_bits[0],_bits[1]+' '+_bits[2]];
                }
            }
            if(_bits.length==2){
                var num = _bits[0]+_bits[1];
                if(num.length>7){
                    return  ['',_bits[0],_bits[1]];
                }
                else{
                    return  ['','',_bits.join(' ')];
                }
            }
            if(_bits.length==1){
                    return  ['','',_bits[0]];
            }
            return [_bits.shift(),_bits.shift(),_bits.join(' ')];
        }
        return [];
    }
function isDark(colour){
    // Mostly when deciding whether text on a background should be white or black
    // Variables for red, green, blue values
    var r, g, b, hsp;
    // Check the format of the colour, HEX or RGB?
    if (colour.match(/^rgb/)) {
        // If HEX --> store the red, green, blue values in separate variables
        colour = colour.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
        r = colour[1];
        g = colour[2];
        b = colour[3];
    }
    else {
        // If RGB --> Convert it to HEX: http://gist.github.com/983661
        colour = +("0x" + colour.slice(1).replace(
        colour.length < 5 && /./g, '$&$&'));
        r = colour >> 16;
        g = colour >> 8 & 255;
        b = colour & 255;
    }
    // HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html
    hsp = Math.sqrt(
    0.299 * (r * r) +
    0.587 * (g * g) +
    0.114 * (b * b)
    );
    // Using the HSP value, determine whether the colour is light or dark
    return hsp>127.5 ? false : true;
}
function shadeColour(colour, percent) {
    /* darken or lighten given colour, percent as float from  -1.0 to 1.0 */
    var f=parseInt(colour.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
    return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
}
function blendColours(c0, c1, p) {
    /* Same as shadeColour, but instead of darkenint (black) or lightening(white) you can elect the second colour.
       p = percent float from 0.0 to 1.0 */
    var f=parseInt(c0.slice(1),16),t=parseInt(c1.slice(1),16),R1=f>>16,G1=f>>8&0x00FF,B1=f&0x0000FF,R2=t>>16,G2=t>>8&0x00FF,B2=t&0x0000FF;
    return "#"+(0x1000000+(Math.round((R2-R1)*p)+R1)*0x10000+(Math.round((G2-G1)*p)+G1)*0x100+(Math.round((B2-B1)*p)+B1)).toString(16).slice(1);
}
$.fn.scrollToHere = function () {
    return this.each(function () {
        $('html, body').animate({
            scrollTop: $(this).offset().top
        }, 500);
    });
}