                                              ﻿/*
 * Ajaxify.js
 * Ajaxify your site out of the box, instantly.
 * http://4nf.org/
 *
 * Copyright 2014 Arvind Gupta; MIT Licensed
 */
 
 //Intuitively better understandable shorthand for String.indexOf() - String.iO()
String.prototype.iO = function(s) { return this.toString().indexOf(s) + 1; };
 

//Module global variables
var l=0, pass=0, api=window.history && window.history.pushState && window.history.replaceState;
 
//Regexes for escaping fetched HTML of a whole page - best of Balupton's "Ajaxify"
//Makes it possible to pre-fetch an entire page
var docType = /<\!DOCTYPE[^>]*>/i;
var tagso = /<(html|head|body|title|meta|script|link)([\s\>])/gi;
var tagsc = /<\/(html|head|body|title|meta|script|link)\>/gi;
 
//Helper strings
var div12 =  '<div data-ajax-class="ajy-$1"$2';
var linki = '<link rel="stylesheet" type="text/css" href="*" />', scri='<script type="text/javascript" src="*" />';
var linkr = 'link[href*="!"]', scrr = 'script[src*="!"]';
 
/*global jQuery*/ //Tell JSHint, not to moan about "jQuery" being undefined
 
// The stateful Log plugin - initialised in Ajaxify at the bottom of the file
// Usage: $.log(<string>); anywhere in Ajaxify where you would like to peek into
(function ($) {
    var Log = function (options) {
        var con = window.console;
        var settings = $.extend({
            verbosity: 0
        }, options);
        var verbosity = settings.verbosity;
        this.a = function (m) {
            if(l < verbosity && con) con.log(m);
        };
    };
    $.log = function (m, options) {
        if (!$.log.o) $.log.o = new Log(options);
        return $.log.o.a(m);
    };
})(jQuery);
 
// The stateful Cache plugin
// Usage:
// 1) $.cache() - returns currently cached page
// 2) $.cache(<URL>) - returns page with specified URL
// 3) $.cache(<jQuery object>) - saves the page in cache
(function ($) {
    var Cache = function () {
        var d = false;
        this.a = function (o) {
            if (!o) {
                return d;
            }
            if (typeof o === "string") {
                if(o === "f") {
                    $.pages("f");
                    d = undefined;
                } else d = $.pages($.memory(o));
                 
                return d;
            }
            if (typeof o === "object") {
                d = o;
                return d;
            }
        };
    };
    $.cache = function (o) {
        if (!$.cache.o) $.cache.o = new Cache();
        return $.cache.o.a(o);
    };
})(jQuery);
 
// The stateful Memory plugin
// Usage: $.memory(<URL>) - returns the same URL if not turned off internally
(function ($) {
    var Memory = function (options) {
        var d = false;
        var settings = $.extend({
            memoryoff: false
        }, options);
        var memoryoff = settings.memoryoff;
        this.a = function (h) {
            d = memoryoff;
            if (!h || d === true) return false;
            if (d === false) return h;
            if (d.iO(", ")) {
                d = d.split(", ");
                if (d.iO(h)) return false;
                else return h;
            }
            return h == d ? false : h;
        };
    };
    $.memory = function (h, options) {
        if (!$.memory.o) $.memory.o = new Memory(options);
        return $.memory.o.a(h);
    };
})(jQuery);
 
// The stateful Pages plugin
// Usage:
// 1) $.pages(<URL>) - returns page with specified URL from internal array
// 2) $.pages(<jQuery object>) - saves the passed page in internal array
// 3) $.pages(false) - returns false
(function ($) {
    var Pages = function () {
        var d = [];
        this.a = function (h) {
            if (typeof h === "string") {
                if(h === "f") d = [];
                else for (var i = 0; i < d.length; i++)
                    if (d[i][0] == h) return d[i][1];
            }
            if (typeof h === "object") {
                d.push(h);
            }
            if (typeof h === "boolean") {
                return false;
            }
        };
    };
    $.pages = function (h) {
        if (!$.pages.o) $.pages.o = new Pages();
        return $.pages.o.a(h);
    };
})(jQuery);
 
// The GetPage plugin
// First parameter is a switch:
// empty - returns cache
// <URL> - loads HTML via Ajax
// "+" - pre-fetches page
// "-" - loads page into DOM and handle scripts
// otherwise - returns selection of current page to client
(function ($) {
    var GetPage = function () {
        this.a = function (o, p, p2) {
            
            if (!o) {
                return $.cache();
            }
            if (o.iO("/")) {
                return _lPage(o, p, p2);
            }
            if (o === "+") {
                return _lPage(p, p2, false, true);
            }
            if (o === "-") {
                return _lSel(p, p2);
            }
            if($.cache()) return $.cache().find("[data-ajax-class='ajy-" + o + "']");


        };
 
        function _lSel(p, $t) { //load page into DOM and handle scripts
            pass++;
            _lDivs($t);
            $.scripts(p);
            $.scripts("s");
            $.scripts("a");
            return $.scripts("c");
        }
 
        function _lPage(h, p, post, pre) { //fire Ajax load, check for hash first
            if (h.iO("#")) h = h.split("#")[0];
            if (post || !$.cache(h)) return _lAjax(h, p, post, pre);
            if(p) p();
        }
 
        function _ld($t, $h) {

            $h.find("[data-ajax-class='ajy-script']").each(function(){
                
                 if(!($(this).attr("src"))) $(this).replaceWith('<script type="text/javascript">' + $(this).text() + '</script>');
                 else $(this).replaceWith(scri.replace('*', $(this).attr("src")));
            });

            $t.html($h.html());
        }
 
        function _lDivs($t) { //load target divs into DOM
            if ($.cache()) $t.each(function () {
                _ld($(this), $.cache().find("#" + $(this).attr("id")));
            });
        }
 
        function _lAjax(hin, p, post, pre) { //execute Ajax load
            var xhr = $.ajax({
                url: hin,
                type: post ? "POST" : "GET",
                data: post ? post.data : null,
                success: function (h) {


                    if (!h || !_isHtml(xhr)) {
                        if (!pre) location.href = hin;
                        return;
                    }

                    $.cache($(_parseHTML(h)));
                    $.pages([hin, $.cache()]);
                    if(p) p();

                },
                error: function(e){
                    if(e.status == '404') { 
                        window.location = nectarLove.rooturl + '/404';
                    }
                    
                }
            });
        }
 
        function _isHtml(x) { //restrict interesting MIME types - only HTML / XML
            var d;
            return (d = x.getResponseHeader("Content-Type")), d && (d.iO("text/html") || d.iO("text/xml"));
        }
 
        function _parseHTML(h) { //process fetched HTML
            return $.trim(_replD(h));

        }
 
        function _replD(h) { //pre-process HTML so it can be loaded by jQuery
            return String(h).replace(docType, "").replace(tagso, div12).replace(tagsc, "</div>");
        }
    };
    $.getPage = function (o, p, p2) {
        if (!$.getPage.o) $.getPage.o = new GetPage();
        return $.getPage.o.a(o, p, p2);
    };
})(jQuery);
 
// The main plugin - Ajaxify
// Is passed the global options
// Checks for necessary pre-conditions - otherwise gracefully degrades
// Initialises sub-plugins
// Calls Pronto
(function ($) {
    var Ajaxify = function (options) {
        var settings = $.extend({
            pluginon: true,
            fn: $.getPage
        }, options);
        var pluginon = settings.pluginon;
        //404 check
        if(window.location.href.indexOf("/404") > -1) pluginon = false;

        this.a = function ($this) {
            $(function () {
                if (_init(settings)) {
                    $this.pronto(settings);
                    $.getPage(location.href, $.scripts);
                }
            });
        };
 
        function _init(s) {
            if (!api || !pluginon) return false;
            $.scripts("i", s);
            $.cache(0, s);
            $.memory(0, s);
            return true;
        }
    };
    $.fn.ajaxify = function (options) {
        var $this = $(this);
        if (!$.fn.ajaxify.o) $.fn.ajaxify.o = new Ajaxify(options);
        return $.fn.ajaxify.o.a($this);
    };
})(jQuery);
 
// The stateful Scripts plugin
// First parameter is switch:
// "i" - initailise options
// "a" - handle inline scripts
// "c" - fetch canonical URL
// otherwise - delta loading
(function ($) {
    var Scripts = function (options) {
        var $s = $();
        var settings = $.extend({
            canonical: true,
            inline: true,
            inlinehints: false,
            style: true
            }, options);
        var canonical = settings.canonical,
            inline = settings.inline,
            inlinehints = settings.inlinehints,
            style = settings.style;
        this.a = function (o) {
            if (o === "i") {
                return true;
            }
            if (o === "s") {
                return _allstyle($s.y);
            }
            if (o === "a") {
                return _alltxts($s.t);
            }
            if (o === "c") {
                if (canonical && $s.can) return $s.can.attr("href");
                else return false;
            }
            $.detScripts($s); //fetch all scripts
            _addScripts(o, $s, settings); //delta-loading
        };
 
        function _allstyle($s) {
            if (!style) return;
            $("head").find("style").remove();
            $s.each(function () {
                var d = $(this).text();
                _addstyle(d);
            });
        }
         
        function _alltxts($s) {
            $s.each(function () {
                var d = $(this).text();
                if (!d.iO(").ajaxify(") && (inline || $(this).hasClass("ajaxy") || _inline(d))) _addtext(d);
            });
        }
 
        function _addtext(t) {
            try {
                $.globalEval(t);
            } catch (e) {
                //alert(e);
            }
        }
         
        function _addstyle(t) {
            $("head").append('<style type="text/css">' + t + '</style>');
        }
 
        function _inline(txt) {
            var d = inlinehints;
            if (d) {
                d = d.split(", ");
                for (var i = 0; i < d.length; i++)
                    if (txt.iO(d[i])) return true;
            }
        }
 
        function _addScripts(same, $s, st) {
            $s.c.addAll(same, "href", st);
            $s.s.addAll(same, "src", st);
        }
    };
    $.scripts = function (o, options) {
        if (!$.scripts.o) $.scripts.o = new Scripts(options);
        return $.scripts.o.a(o);
    };
})(jQuery);
 
// The DetScripts plugin - stands for "detach scripts"
// Works on "$s" jQuery object that is passed in and fills it
// Fetches all stylesheets in the head
// Fetches the canonical URL
// Fetches all external scripts on the page
// Fetches all inline scripts on the page
(function ($) {
    var DetScripts = function () {
        var head, lk, j;
        this.a = function ($s) {
            head = $.getPage("head");
            lk = head.find("[data-ajax-class='ajy-link']");
            j = $.getPage("script");
            $s.c = _rel(lk, "stylesheet");
            $s.y = head.find("style");
            $s.can = _rel(lk, "canonical");
            $s.s = j.filter(function () {
                return $(this).attr("src");
            });
            $s.t = j.filter(function () {
                return !($(this).attr("src"));
            });
        };
 
        function _rel(lk, v) {
            return $(lk).filter(function () {
                return $(this).attr("rel").iO(v);
            });
        }
    };
    $.detScripts = function ($s) {
        if (!$.detScripts.o) $.detScripts.o = new DetScripts();
        return $.detScripts.o.a($s);
    };
})(jQuery);
 
(function ($) {
    var AddAll = function (options) {
        var $scriptsO, $scriptsN, $sCssO = [],
            $sCssN = [],
            $sO = [],
            $sN = [];
        var settings = $.extend({
            deltas: true
        }, options);
        var deltas = settings.deltas;
        this.a = function ($this, same, PK) {
            if (PK == "href") {
                $scriptsO = $sCssO;
                $scriptsN = $sCssN;
            } else {
                $scriptsO = $sO;
                $scriptsN = $sN;
            } if (_allScripts($this, PK)) return true;
            if (pass) _classAlways($this, PK);
            if (same) return _sameScripts($scriptsN, PK);
            $scriptsN = [];
            _newArray($this, $scriptsN, $scriptsO, PK);
            if (pass) {
                _findCommon($scriptsO, $scriptsN);
                _freeOld($scriptsO, PK);
                _sameScripts($scriptsN, PK);
                $scriptsO = $scriptsN.slice();
            }
            if (PK == "href") {
                $sCssO = $scriptsO;
                $sCssN = $scriptsN;
            } else {
                $sO = $scriptsO;
                $sN = $scriptsN;
            }
        };
 
        function _allScripts($t, PK) {
            if (deltas) return false;
            $t.each(function () {
                _iScript($(this)[0], PK);
            });
            return true;
        }
 
        function _classAlways($t, PK) {
            $t.each(function () {
                if ($(this).attr("class") == "always") {
                    _iScript($(this).attr(PK), PK);
                   // $(this).remove();
                }
            });
        }
 
        function _sameScripts(s, PK) {
            
            //var exlucdedNSScript = 'nectar-slider.js';
            var exlucdedChartScript = 'vc_chart.js';
            var exlucdedProgressScript = 'ProgressCircle.js';

            for (var i = 0; i < s.length; i++)
                if (s[i][1] === 0 && !s[i][0].match(exlucdedChartScript) && !s[i][0].match(exlucdedProgressScript) ) _iScript(s[i][0], PK);
        }
 
        function _iScript($S, PK) {
            $("head").append((PK == "href" ? linki : scri).replace("*", $S));
        }
 
        function _newArray($t, sN, sO, PK) {
            var d;
            $t.each(function () {
                d = [$(this).attr(PK), 0];
                sN.push(d);
                if (!pass) sO.push(d);
            });
        }
 
        function _findCommon(s, sN) {
            for (var i = 0; i < s.length; i++) {
                s[i][1] = 2;
                if (_findScript(s[i][0], sN)) s[i][1] = 1;
            }
        }
 
        function _findScript($S, s) {
            if ($S)
                for (var i = 0; i < s.length; i++)
                    if (s[i][0] == $S) {
                        s[i][1] = 1;
                        return true;
                    }
        }
 
        function _freeOld(s, PK) {
            for (var i = 0; i < s.length; i++)
                if (s[i][1] == 2 && s[i][0]) _removeScript(s[i][0], PK);
        }
 
        function _removeScript($S, PK) {
            $((PK == "href" ? linkr : scrr).replace("!", $S)).remove();
        }
    };
    $.fn.addAll = function (same, PK, options) {
        var $this = $(this);
        if (!$.fn.addAll.o) $.fn.addAll.o = new AddAll(options);
        return $.fn.addAll.o.a($this, same, PK);
    };
})(jQuery);
 
(function ($) {
    var Pronto = function (options) {
        var $window = $(window),
            currentURL = '',
            requestTimer = null,
            post = null,
            $gthis, fm;
 
        // Default Options
        var settings = $.extend({
            selector: "a:not(.no-ajaxy)",
            requestDelay: 0,
            forms: true,
            turbo: true,
            previewoff: true,
            fn: false,
            cb: 0
        }, options);
 
        //Shorthands
        var selector = settings.selector,
            requestDelay = settings.requestDelay,
            forms = settings.forms,
            turbo = settings.turbo,
            previewoff = settings.previewoff,
            cb = settings.cb,
            fn = settings.fn;
        

        // Main plugin function
        this.a = function ($this) {
            $gthis = $this;
            _init_p();
            return $this;
        };
 
        // Private Methods
        function _init_p() {
            settings.$body = $("body");
            currentURL = window.location.href; // Capture current url & state
            _saveState(); // Set initial state
            $window.on("popstate", _onPop); //Set handler for popState
            if (turbo) $(selector).hoverIntent(_prefetch, _drain); //If "turbo" option defined then set handler to "_prefetch" on hoverIntent
            settings.$body.on("click.pronto", selector, _click); //For real clicks set handler to _click()
            //_ajaxify_forms();
        }
 
        //Dummy function for hoverIntent
        function _drain() {}
 
        //Prefetch target page on hoverIntent
        function _prefetch(e) {
            post = null; // Assume not a POST
            var link = e.currentTarget;
             
            //Validate link internal and not the same URL
            if (_diffHost(link)) return false;
            if (currentURL == link.href) return false;
             
            var req2 = function () {
                if (previewoff === true) return false;
                if (!_isInDivs(link) && (previewoff === false || !$(link).closest(previewoff).length)) _click(e, true);
            };
            fn('+', link.href, req2);
        }
 
        function _isInDivs(link) {
            var isInDivs = false;
            $gthis.each(function () {
                try {
                    if ($(link).parents("#" + $(this).attr("id")).length > 0) isInDivs = true;
                } catch (e) {
                    //alert(e);
                }
            });
            return isInDivs;
        }
 
        function _b(m, n) {
            if (m.indexOf("?") > 0) {
                m = m.substring(0, m.indexOf("?"));
            }
            return m + "?" + n;
        }
         
        function _k() {
            var o = fm.serialize();
            var n = $("input[name][type=submit]", fm);
            if (n.length === 0) return o;
            var p = n.attr("name") + "=" + n.val();
            if (o.length > 0) {
                o += "&" + p;
            } else {
                o = p;
            }
            return o;
        }
 
        function _ajaxify_forms() {
            if (!forms) return false;
            $('form').submit(function (q) {
                fm = $(q.target);
                if (!fm.is("form")) {
                    fm = fm.filter("input[type=submit]").parents("form:first");
                    if (fm.length === 0) {
                        return true;
                    }
                }
                var p = _k();
                var g = "get",
                    m = fm.attr("method");
                if (m.length > 0 && m.toLowerCase() == "post") g = "post";
                var h, a = fm.attr("action");
                if (a !== null && a.length > 0) h = a;
                else h = currentURL; if (g == "get") h = _b(h, p);
                else {
                    post = {};
                    post.data = p;
                }
                $window.trigger("pronto.submit", h);
                _request(h);
                return false;
            });
        }
 
        // Handle link clicks
        function _click(e, mode) {
            var link = e.currentTarget;

            //stop plugin pages from triggering ajax
            if( $.inArray(link.href, nectarLove.pluginPages) !== -1 ) { 
                document.location.href = link.href;
                return false;
            }

            post = null;
            if (_exoticKey(e) || _diffHost(link)) return; // Ignore everything but normal click and internal URLs
            if (_hashChange(link)) { // Only the hash part has changed
                _saveState(); // Update state on hash change
                return true;
            }

            if(typeof window.stop === 'function' && $('body').hasClass('ajax-loaded')) { window.stop(); } 

            e.preventDefault();
            e.stopPropagation();
            if (currentURL == link.href) {
                _saveState();
            } else _request(e, mode);


        }
 
        // Request new url
        function _request(e, mode) {
            var href = typeof(e) !== "string" ? e.currentTarget.href : e;
            $window.trigger("pronto.request", e); // Fire request event
             var reqr = function () { //Callback - continue with _render()
                _render(e, true, mode);
            };
            fn(href, reqr, post); //Call "fn" - handler of parent, informing whether POST or not
        }
 
        function _render(e, doPush, mode) {
        	if($(window).scrollTop() > 0) {
        		requestDelay = 850;
        	} else {
        		requestDelay = 450;
        	}

            if (requestTimer !== null) {
                clearTimeout(requestTimer);
                requestTimer = null;
            }
            requestTimer = setTimeout(function () {
                _doRender(e, doPush, mode);
            }, requestDelay);
        }
 
        // Save current state
        function _saveState() {
            history.replaceState({ // Update state
                url: currentURL
            }, "state-" + currentURL, currentURL);
        }
 
        // Handle back/forward navigation
        function _onPop(e) {
            var data = e.originalEvent.state;
             
            // Check if data exists
            if (data !== null && data.url !== currentURL) {
                $window.trigger("pronto.request", e); // Fire request event
                var req3 = function () { //Callback - continue with _render()
                    _render(e, false, false);
                };
                fn(data.url, req3); //Call "fn" - handler of parent, passing URL
            }
        }
 
        // Push new states to the stack on new url
        function _doPush(url, doPush) {
            currentURL = url;
            if (doPush) {
                history.pushState({
                    url: currentURL
                }, "state-" + currentURL, currentURL);
            } else {
                _saveState();
            }
        }
 
        // Render HTML
       function _doRender(e, doPush, mode) {
            var url, canURL; //Canonical URL
            url = typeof(e) !== "string" ? e.currentTarget.href || e.originalEvent.state.url : e;
            $window.trigger("pronto.load", e);  // Fire load event
            _gaCaptureView(url); // Trigger analytics page view
            _saveState(); // Update current state

            $('title').html(fn('title').html()); // Update title

            //update meta attrs
            $('meta[property="og:url"]').attr('content',fn('meta').filter('[property="og:url"]').attr('content'));
            $('meta[property="og:title"]').attr('content',fn('meta').filter('[property="og:title"]').attr('content'));
            $('meta[property="og:type"]').attr('content',fn('meta').filter('[property="og:type"]').attr('content'));

            if(fn('meta').filter('[property="og:description"]').length > 0 && $('meta[property="og:description"]').length == 0){
                
                $('head').append('<meta property="og:description" content="'+fn("meta").filter("[property='og:description']").attr("content")+'" />');
            } 
            else if(fn('meta').filter('[property="og:description"]').length == 0 && $('meta[property="og:description"]').length > 0) {
                $('meta[property="og:description"]').remove();
            } 

            else {
                $('meta[property="og:description"]').attr('content',fn('meta').filter('[property="og:description"]').attr('content'));
            }


            if(fn('meta').filter('[property="og:image"]').length > 0 && $('meta[property="og:image"]').length == 0){

                $('head').append('<meta property="og:image" content="'+fn("meta").filter("[property='og:image']").attr("content")+'" />');

            } else if(fn('meta').filter('[property="og:image"]').length == 0 && $('meta[property="og:image"]').length > 0) {
                $('meta[property="og:image"]').remove();
            } 

            else {
                $('meta[property="og:image"]').attr('content',fn('meta').filter('[property="og:image"]').attr('content'));
            }


            $('body').attr('class',fn('body').attr('class')); // Update class 
            $('body').addClass('ajax-loaded');
            $('body').attr('data-bg-header',fn('body').attr('data-bg-header'));   //Update body attr
            if($('#wpadminbar').length > 0) $('#wpadminbar').html(fn('body').find('#wpadminbar').html()); // Update admmin bar
            
            var $wooCartHasProducts = ($('.sf-menu').hasClass('product_added')) ? 'product_added' : null;
            var $wooCart = $('#header-outer .cart-outer').clone();

            $('#header-outer').html(fn('body').find('#header-outer').html());   //Update header nav 

            $('#header-outer .cart-outer').replaceWith($wooCart);
            $('#header-outer').removeClass('directional-nav-effect');
            if($wooCartHasProducts == 'product_added') $('#header-outer .sf-menu').addClass($wooCartHasProducts);
            //Update header attr
            if(fn('body').find('#header-outer[data-transparent-header]').length > 0) {
            	 $('#header-outer').attr('data-transparent-header',fn('body').find('#header-outer').attr('data-transparent-header'));   
                 if($(window).scrollTop() == '0') $('#header-outer').addClass('transparent');
            } else {
            	 $('#header-outer').removeAttr('data-transparent-header');  
                 $('#header-outer').removeClass('transparent');
            }

            if(fn('body').find('#header-outer[data-transparency-option]').length > 0) {
               $('#header-outer').attr('data-transparency-option',fn('body').find('#header-outer').attr('data-transparency-option'));   
            }

            //handle mediaElement
            fn('body').find('video.wp-video-shortcode, audio.wp-audio-shortcode').removeClass().addClass('wp-media-shortcode-ajax');

            // Update DOM and fetch canonical URL - important for handling re-directs
            canURL = fn('-', post, $gthis);
 
            //Set current URL to canonical if no hash or parameters in current URl
            if (canURL && canURL != url && !url.iO('#') && !url.iO('?')) url = canURL;
 
            //_ajaxify_forms();
             
            //If hash in URL animate scroll to it
           /* if (url.iO('#') && !mode) {
                $('html, body').animate({
                    scrollTop: $('#' + url.split('#')[1]).offset().top
                }, 500);
            }*/
 
            _doPush(url, doPush); // Push new states to the stack on new url
            $window.trigger("pronto.render", e); // Fire render event
            if(cb) cb();
        }
 
        // Google Analytics support
        function _gaCaptureView(url) {
            if (typeof window.ga !== 'undefined') window.ga('send', 'pageview', url);
        }
 
        function _diffHost(link) {
            return (window.location.protocol !== link.protocol || window.location.host !== link.host);
        }
 
        function _exoticKey(e) {
            return (e.which > 1 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey);
        }
 
        function _hashChange(link) {
            return (link.hash && link.href.replace(link.hash, '') === window.location.href.replace(location.hash, '') || link.href === window.location.href + '#');
        }
    };
 
    // Define Plugin
    $.fn.pronto = function (options) {
        var $this = $(this);
        if (!$.fn.pronto.o) $.fn.pronto.o = new Pronto(options);
        return $.fn.pronto.o.a($this);
    };
})(jQuery);
 
