CruisersWiki:GetKml.js

From CruisersWiki

Revision as of 14:57, 30 October 2017 by Vadim (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
//
/*
    DON'T USE!
 
   GetKml.js

   Copyright (c) 2016 Vadim Shlyakhov
   Licensed MIT
*/

(function () {
    var kml_top = '' +
        '<?xml version="1.0" encoding="UTF-8"?>\n' +
        '<kml xmlns="http://earth.google.com/kml/2.2">\n' +
        '<Document>\n' +
        '  <name>{0}</name>\n' +
        '  <description>{1}</description>\n' +
        '';

    var kml_style = '' +
        '  <Style id="{0}">\n' +
        '    <IconStyle>\n' +
        '      <Icon>\n' +
        '        <href>{1}</href>\n' +
        '      </Icon>\n' +
        '    </IconStyle>\n' +
        '  </Style>\n' +
        '';

    var kml_placemark = '' +
        '  <Placemark>\n' +
        '    <name>{name}</name>\n' +
        '    <styleUrl>#{category}</styleUrl>\n' +
        '    <Point>\n' +
        '      <coordinates>{lon},{lat}</coordinates>\n' +
        '    </Point>\n' +
        '    <description><![CDATA[<div dir="ltr">{description}</div>]]></description>\n' +
        '  </Placemark>\n' +
        '';

    var kml_name_decorated = '<![CDATA[<a href="{1}" target="_blank">{0}</a>]]>';

    // var kml_description_decorated = '<div class="cw-chartlet-category">{0}</div><div class="cw-chartlet-content">{1}</div>';

    var kml_bottom = ''+
        '</Document>\n' +
        '</kml>\n' +
        '';

    var format = function (str, col) { // http://stackoverflow.com/a/5341855
        col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);

        return str.replace(/\{\{|\}\}|\{(\w+)\}/g, function (m, n) {
            if (m == "{{") { return "{"; }
            if (m == "}}") { return "}"; }
            return col[n];
        });
    };

    function kmlBuild (options, callback) {

        var kml_out = '';
        var s = '';

        var parents = [];

        function out(s) {
            // console.log(s);
            kml_out += s;
        }
        
        // https://commons.wikimedia.org/wiki/Category:Nautical_Chart_Icons
        // https://commons.wikimedia.org/wiki/Category:Wikivoyage_map_icons
        // https://commons.wikimedia.org/wiki/Category:Map_icons
        // https://commons.wikimedia.org/wiki/Category:Diagrams_of_U.S._Recreational_and_Cultural_Interest_Area_Symbol_Guide_Signs

        var style_icons = {
            // 'danger': 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Warning_sign_font_awesome-red.svg/20px-Warning_sign_font_awesome-red.svg.png',
            // 'danger': 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Dialog-warning.svg/25px-Dialog-warning.svg.png',
            // 'danger': 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Emoji_u26a0.svg/25px-Emoji_u26a0.svg.png',
            'danger': 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/24/Warning_icon.svg/25px-Warning_icon.svg.png',
            'waypoint': 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Map_marker.svg/20px-Map_marker.svg.png',
            // 'article': 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/City_locator_16.svg/20px-City_locator_16.svg.png',
            'article': 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/City_locator_30.svg/20px-City_locator_30.svg.png',
            //'berth': 'http://www.cruiserswiki.org/images/c/cf/Marina_icon.png',
            'berth': 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/MUTCD_RS-056.svg//20px-MUTCD_RS-056.svg.png',
            //'anchorage': 'http://www.cruiserswiki.org/images/3/3f/Anchor_Icon.png',
            //'anchorage': 'https://commons.wikimedia.org/wiki/Special:Redirect/file/MUTCD_RS-053.svg?width=20',
            'anchorage': 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/MUTCD_RS-053.svg/20px-MUTCD_RS-053.svg.png',
            'buoy': 'http://www.cruiserswiki.org/images/4/4d/Buoy_icon.png',
            'officials': 'http://www.cruiserswiki.org/images/7/71/Poe.jpg',
            //'waypoint': 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/City_locator_12.svg/20px-City_locator_12.svg.png',
            'facilities': 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/MUTCD_RS-022.svg/20px-MUTCD_RS-022.svg.png',
            'service': 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/MUTCD_RS-027.svg//20px-MUTCD_RS-027.svg.png',
            'chandler': 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/MUTCD_RS-141.svg/20px-MUTCD_RS-141.svg.png',
            'provisions': 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/MUTCD_RS-020.svg/20px-MUTCD_RS-020.svg.png',
            // 'catering': 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/RM-050_Food_sign.svg/20px-RM-050_Food_sign.svg.png',
            'eatingout': 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/SymbolRestaurant.svg/20px-SymbolRestaurant.svg.png',
            'accommodation': 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/MUTCD_RS-037.svg/20px-MUTCD_RS-037.svg.png',
            'beach': 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/MUTCD_RS-145.svg/20px-MUTCD_RS-145.svg.png',
            'other': 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/MUTCD_RS-080.svg/20px-MUTCD_RS-080.svg.png',
        };

        function out_styles () {
            for (var st in style_icons) {
                out(format(kml_style, st, style_icons[st]));
            }
        }

        function some (arr) {
            return typeof arr !== 'undefined' && arr.length > 0;
        }

        function first (arr) {
            return some(arr) ? arr[0] : '';
        }

        function join (arr) {
            return some(arr) ? arr.join(' ') : '';
        }

        function join_html (arr) {
            var out = [];
            if (arr) {
                for (var i=0, li=arr.length; i < li; i++) {
                    out.push(arr[i].html);
                }
            }
            return out.join(' ');
        }

        var mf_processors = {
            "h-review": function (props, poi) {
                var review_url = first(props.url);
                if (options.decorated) {
                    if (review_url) {
                        poi.name = format(kml_name_decorated, poi.name, review_url);
                    }
                    // description = format(kml_description_decorated, category, description);
                }
                poi.description = join_html(props.description);
            },
            "h-card": function (props, poi) {
                if (! poi.name) {
                    poi.name = first(props.name);
                }
                var category = first(props.category);
                poi.category = style_icons[category] ? category : 'other';
            },
            "h-geo": function (props, poi) {
                poi.lat = first(props.latitude);
                poi.lon = first(props.longitude);
                poi.name = first(props.name);
            },
        };

        function process_placemark(item_list) {
            var poi = {};
            for (var i=0, li=item_list.length; i < li; i++) {
                var item = item_list[i];
                var type = first(item.type);
                var props = item.properties;
                var processor = mf_processors[type];
                processor && processor(props, poi);
            }
            if (poi.lat != null && poi.lon != null)
                out(format(kml_placemark, poi));
        }

        var mf_subitem_map = {
            "h-review": 'item',
            "h-card": 'geo',
        };

        function process_item_list (item_list, parents) {
            for (var i=0, li=item_list && item_list.length; i < li; i++) {
                var item = item_list[i];
                var type = first(item.type);
                var props = item.properties;
                var subitem_id = mf_subitem_map[type];
                if (subitem_id) {
                    process_item_list(item.properties[subitem_id], [item].concat(parents))
                } else {
                    process_placemark([item].concat(parents));
                }
                if (item.children) 
                    process_item_list(item.children, []);
            }
        }

        var parsed = Microformats.get(options.data);

        if (parsed.items && parsed.items.length > 0) {
            // console.log('POIs loaded ' + parsed.items.length);
            out(format(kml_top, options.page, options.uri));
            out_styles();

            process_item_list(parsed.items, []);

            out(kml_bottom);
        }
        //console.log(kml_out);
        callback(kml_out);
    }

    function getKml (options, callback) {
        options = options || {};
        loadWikiScript('CruisersWiki:Microformat-shiv.min.js',
            function () {
                options.uri = wikiUri(options.page || wgPageName);
                if (options.page) {
                    $.get(options.uri, function(data, status) {
                        options.data =  {
                            'baseUrl': wgServer,
                            'html': data
                        };
                        kmlBuild(options, callback);
                    });
                } else {
                    options.page = wgPageName;
                    kmlBuild(options, callback);
                }
            });
    }

    function b64EncodeUnicode(str) { //https://developer.mozilla.org/en/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
        return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
            return String.fromCharCode('0x' + p1);
        }));
    }

    function getKmlUri (options, callback) {
        getKml(options, function (kml) {
            // var data_uri = 'data:text/xml;charset=utf-8;base64,' + b64EncodeUnicode(kml);
            var data_uri = 'data:text/xml;charset=utf-8,' + encodeURIComponent(kml);
            callback(data_uri);
        });
    }

    function downloadKml (kml_uri) {
        var kml_anchor = $('#kml-anchor')[0];
        if (! kml_anchor) {
            var $a = $('<a id="kml-anchor" style="display:none">')
                .attr('download', wgTitle + '.kml')
                .attr('href', kml_uri);
            $('body').append($a);
            kml_anchor = $('#kml-anchor')[0];
        }
        kml_anchor.click();
    }

    function addKmlLink () {
        var $a = $('<a style="cursor:pointer">Download KML</a>')
            .click(function () {
                getKmlUri({}, downloadKml);
            });

        $('#p-tb ul').append($('<li>').append($a));
    }

    if ($('.h-geo').length > 0) {
        addKmlLink();
    }

    window.getKmlUri = getKmlUri;
    window.getKml = getKml;
})();
// 
Personal tools
advertisement
Friends of Cruisers Wiki