WME Copy to... Menu

Simplify the task of copying segment info with this easy-access right-click context menu. Copy segment names, cities, ids & etc directly to your clipboard or to WME Road Selector.

Ajankohdalta 15.2.2016. Katso uusin versio.

// ==UserScript==
// @name            WME Copy to... Menu
// @namespace       https://greasyfork.org/users/11629-TheLastTaterTot
// @version         0.1
// @description     Simplify the task of copying segment info with this easy-access right-click context menu. Copy segment names, cities, ids & etc directly to your clipboard or to WME Road Selector.
// @author          TheLastTaterTot
// @include         https://editor-beta.waze.com/*editor/*
// @include         https://www.waze.com/*editor/*
// @exclude         https://www.waze.com/*user/editor/*
// @grant           GM_setClipboard
// @run-at          document-end
// ==/UserScript==
/* jshint -W097 */

var copyTo = function(opt, val) {
    if (document.getElementById('cmClipboard').value) {
        GM_setClipboard(val);
    } else {
        switch (opt) {
            case 'cm_ids':
                document.getElementById('inRSSegId').value = val;
                break;

            case 'cm_primaryStreet':
                document.getElementById('inRSStreet').value = val;
                document.getElementById('selRSAlttStreet').value = 0;
                break;

            case 'cm_altStreets':
                document.getElementById('inRSStreet').value = val;
                document.getElementById('selRSAlttStreet').value = 1;

                break;

            case 'cm_altStreetsAND':
                document.getElementById('inRSStreet').value = '';
                break;

            case 'cm_altStreetsOR':
                document.getElementById('inRSStreet').value = '';
                break;

            case 'cm_primaryCity':
                document.getElementById('inRSCity').value = val;
                document.getElementById('selRSAltCity').value = 0;
                break;

            case 'cm_altCities':
                document.getElementById('inRSCity').value = val;
                document.getElementById('selRSAltCity').value = 1;
                break;

            case 'cm_state':
                document.getElementById('inRSState').value = val;
                //document.getElementById('btnRSAddState').click('true')
                break;

            case 'cm_roadType':
                document.getElementById('selRSRoadType').value = val;
                break;

            case 'cm_updatedBy':
                document.getElementById('inRSUpdtd').value = val;
                break;

            case 'cm_createdBy':
                document.getElementById('inRSCrtd').value = val;
                break;

            case 'cm_toConnections':

                break;
        }

        // swap panel from selection panel
        document.getElementById('user-info').style.display = 'block';
        document.getElementById('edit-panel').style.display = 'none';

        // switch active tab-content
        document.querySelector('.tab-content>.active').classList.remove('active');
        document.getElementById('sidepanel-roadselector').classList.add('active');

        // switch active nav-tab
        document.querySelector('#user-tabs li.active').classList.remove('active');
        document.getElementById('tabRSel').classList.add('active')

        // switch to RSel editor tab
        document.getElementById('roadselector-tabs').childNodes[1].classList.remove('active');
        document.getElementById('roadselector-tabs').childNodes[0].classList.add('active');
        document.getElementById('roadselector-tab-content').childNodes[1].classList.remove('active');
        document.getElementById('roadselector-tab-content').childNodes[0].classList.add('active');
    }
};


var getSegmentProperties = function(selectedItems) {
    /*var roadTypeOpts = document.querySelector('#segment-edit-general select[name="roadType"]'),
        numRoadTypes = roadTypeOpts.options.length, r, roadTypes = {};
    for (r=0; r < numRoadTypes; r++) {
        roadTypes[roadTypeOpts[r].value] = roadTypeOpts[r].text;
    }*/
    var roadTypes = {
            1: "Street",
            2: "Primary Street",
            3: "Freeway",
            4: "Ramp",
            5: "Walking Trail",
            6: "Major Highway",
            7: "Minor Highway",
            8: "Dirt road / 4X4 Trail",
            10: "Pedestrian Boardwalk",
            15: "Ferry",
            16: "Stairway",
            17: "Private Road",
            18: "Railroad",
            19: "Runway/Taxiway",
            20: "Parking Lot Road"
        };

    var s, s_ids = {}, s_altStObjKeys;
        s_ids = {ids: {},
                 primaryStreet: {},
                 altStreets: {},
                 altCities: {},
                 roadType: {},
                 createdBy: {},
                 updatedBy: {},
                 toConnections: {},
                 primaryCity: {},
                 state: {},
                 country: {}
        };

    for (s = selectedItems.length; s--;) {
        s_ids.ids[selectedItems[s].model.attributes.id] = null;
        s_ids.primaryStreet[selectedItems[s].model.attributes.primaryStreetID] = null;
        s_ids.roadType[selectedItems[s].model.attributes.roadType] = null;
        s_ids.createdBy[selectedItems[s].model.attributes.createdBy] = null;
        s_ids.updatedBy[selectedItems[s].model.attributes.updatedBy] = null;
        s_ids.primaryCity[Waze.model.streets.objects[selectedItems[s].model.attributes.primaryStreetID].cityID] = null;
        s_ids.state[Waze.model.cities.objects[Waze.model.streets.objects[selectedItems[s].model.attributes.primaryStreetID].cityID].stateID] = null;
        s_ids.country[Waze.model.cities.objects[Waze.model.streets.objects[selectedItems[s].model.attributes.primaryStreetID].cityID].countryID] = null;

        s_altSt = selectedItems[s].model.attributes.streetIDs;
        for (var a=0, numAlts=s_altSt.length; a<numAlts; a++) {
            s_ids.altStreets[s_altSt[a]] = null;
                s_ids.altCities[Waze.model.streets.objects[s_altSt[a]].cityID] = null;
        }

        s_toConnObjKeys = Object.keys(selectedItems[s].model.attributes.toConnections);
        for (var k=0, numKeys=s_toConnObjKeys.length; k<numKeys; k++) {
            if (s_toConnObjKeys[k] !== '') {
                s_ids.toConnections[s_toConnObjKeys[k]] = selectedItems[s].model.attributes.toConnections[s_toConnObjKeys[k]];
            }
        }
    }

    var seg_ids = {}, seg_names = {
            ids: [],
            primaryStreet: [],
            altStreets: [],
            altCities: [],
            roadType: [],
            createdBy: [],
            updatedBy: [],
            toConnections: [],
            primaryCity: [],
            state: [],
            country: []
    };

    for ( var idKey in s_ids ) {
        seg_ids[idKey] = Object.keys(s_ids[idKey]);

        for (var k=0, numKeys=seg_ids[idKey].length; k<numKeys; k++){
            if (seg_ids[idKey][k] !== '') {
                switch (idKey) {
                    case 'primaryStreet':
                        seg_names[idKey][k] = Waze.model.streets.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'primaryCity':
                        seg_names[idKey][k] = Waze.model.cities.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'altStreets':
                        seg_names[idKey][k] =  Waze.model.streets.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'altCities':
                        seg_names[idKey][k] = Waze.model.cities.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'state':
                        seg_names[idKey][k] = Waze.model.states.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'roadType':
                        seg_names[idKey][k] = roadTypes[String(seg_ids[idKey][k])];
                        break;
                    case 'createdBy':
                        seg_names[idKey][k] = Waze.model.users.objects[seg_ids[idKey][k]].userName;
                        break;
                    case 'updatedBy':
                        seg_names[idKey][k] = Waze.model.users.objects[seg_ids[idKey][k]].userName;
                        break;
                }
            }
        }
    }
    /*
    var seg_names = {
        primaryStreet: Waze.model.streets.objects[seg_ids.primaryStreet].name,
        primaryCity: Waze.model.cities.objects[seg_ids.primaryCity].name,
        altStreets: [],
        altCities: [],
        state: Waze.model.states.objects[seg_ids.state].name,
        roadType: roadTypes[String(seg_ids.roadType)],
        createdBy: Waze.model.users.objects[seg_ids.createdBy].userName,
        updatedBy: Waze.model.users.objects[seg_ids.updatedBy].userName
    }
    for (var a=0, numAlts=seg_ids.altStreets.length; a<numAlts; a++){
        seg_names.altStreets[a] = Waze.model.streets.objects[seg_ids.altStreets[a]].name;
        seg_ids.altCities[a] = Waze.model.streets.objects[seg_ids.altStreets[a]].cityID;
        seg_names.altCities[a] = Waze.model.cities.objects[seg_ids.altCities[a]].name;
    }
    //Waze.model.countries.objects[seg_ids.country].name;
    */
    return { ids: seg_ids, names: seg_names };
};

var resetCopyContextMenu = function(){
    document.getElementById('cmContainer').innerHTML = `
        <div id="cm_street" class="cm-menu-section">
        <dl id="cm_primaryStreet">
        <dt>Street</dt>
        </dl>
        <dl id="cm_altStreets">
        <dt>Alt street</dt>
        </dl>
        </div>
        <div id="cm_city" class="cm-menu-section">
        <dl id="cm_primaryCity">
        <dt>City</dt>
        </dl>
        <dl id="cm_altCities">
        <dt>Alt city</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl id="cm_state">
        <dt>State</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl id="cm_roadType">
        <dt>Road type</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl id="cm_updatedBy">
        <dt>Updated by</dt>
        </dl>
        <dl id="cm_createdBy">
        <dt>Created by</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl>
        <dd id="cm_ids">Segment IDs</dd>
        </dl>
        </div>`;
}; // style="border-bottom: 0;"

var removeCMEventListeners = function() {
    document.getElementById('copyContextMenu').style.display = 'none';

    window.removeEventListener('click', removeCMEventListeners, false);
    document.getElementById('toolbar').removeEventListener('mouseenter', removeCMEventListeners, false);
}

var populateCopyContextMenu = function(segInfo) {
    resetCopyContextMenu();
    var updateNames = Object.keys(segInfo.ids),
        numNames = updateNames.length,
        n, selOption, emptyArr;

    for (n = numNames; n--;) {
        if (document.getElementById('cm_'+updateNames[n]) && segInfo.ids[updateNames[n]] && segInfo.ids[updateNames[n]].length) {
            if (updateNames[n] !== 'ids') {
                emptyArr = 0;
                for (var a=0, aLength = segInfo.ids[updateNames[n]].length; a < aLength; a++) {
                    if (segInfo.names[updateNames[n]][a] && segInfo.names[updateNames[n]][a].length && segInfo.names[updateNames[n]][a] !== '') {
                        selOption = document.createElement('dd');
                        selOption.innerHTML = segInfo.names[updateNames[n]][a];
                        selOption.name = segInfo.ids[updateNames[n]][a];
                        document.getElementById('cm_'+updateNames[n]).appendChild(selOption);

                        switch (updateNames[n]) {
                            case 'roadType':
                                selOption.onclick = function(e){
                                    if (document.getElementById('cmPinMenu').value) e.stopPropagation();
                                    copyTo(this.parentNode.id, this.name);
                                };
                                break;
                            default:
                                selOption.onclick = function(e){
                                    if (document.getElementById('cmPinMenu').value) e.stopPropagation();
                                    copyTo(this.parentNode.id, this.innerHTML);
                                };
                        }
                    } else {
                        emptyArr++;
                    }
                }
                if (emptyArr === aLength) {
                    if (document.getElementById('cm_'+updateNames[n])) {
                        document.getElementById('cm_'+updateNames[n]).style.display = "none";
                    }
                }
            } else {
                selOption = document.getElementById('cm_ids');
                selOption.name = segInfo.ids[updateNames[n]].join(',');
                selOption.onclick = function(e){
                    if (document.getElementById('cmPinMenu').value) e.stopPropagation();
                    copyTo(this.id, this.name);
                };
            }
        } else if (document.getElementById('cm_'+updateNames[n])) {
            document.getElementById('cm_'+updateNames[n]).style.display = "none";
        }
    }

    if (!segInfo.names.primaryStreet.length && !segInfo.names.altStreets.length) {
        document.getElementById('cm_primaryStreet').parentNode.style.display = 'none';
    }

    if (!segInfo.names.primaryCity.length && !segInfo.names.altCities.length) {
        document.getElementById('cm_primaryCity').parentNode.style.display = 'none';
    }

    if (!segInfo.names.state.length) document.getElementById('cm_state').parentNode.style.display = 'none';

    if (!document.getElementById('cmPinMenu').value) {
        window.addEventListener('click', removeCMEventListeners, false);
        document.getElementById('toolbar').addEventListener('mouseenter', removeCMEventListeners, false);
    }
};


var selectionIsSegment = function() {
    var sel = Waze.selectionManager.selectedItems;
    if (sel.length) {
        return (sel[sel.length-1].model.type === 'segment') ? sel : false;
    } else { return false; }
};


var initCopyContextMenu = function(){
    var copyMenu = document.createElement('div'),
        copyMenuCSS = document.createElement('style'),
        copyMenuSettings;


    copyMenuCSS.type = 'text/css';
    copyMenuCSS.innerHTML = `
        div.cm-menu-section { border-bottom: 1px solid #416B7C; padding: 4px 0px; }
        .cm-menu-section dl { margin: 0; padding: 0; display: block; }
        .cm-menu-section dt { font-size: 10px; padding: 0px 10px; margin: 4px 0px 0px; text-transform: uppercase; line-height: 1.1; }
        .cm-menu-section dd { padding: 1px 10px; font-size: 11px; color: #234350; font-weight: 600;}
        .cm-menu-section dd:hover, .cm-menu-section dd:active, .cm-menu-section dd:focus { background-color: #BEDCE5; color: #416B7C; }
        .cm-menu-section dd:active { color: #64D8EA; }
        div#cmFooter { color: #DDEDF3; }
        .cm-footer-text { cursor: pointer; }
        .cm-footer-icns { margin: 0px 3px 0px 0px; cursor: pointer; display: inline-table; line-height: 1; }
        .cm-footer-icns:active, .cm-footer-icns:focus, .cm-footer-icns.toggle-off:active, .cm-footer-icns.toggle-off:focus { color: #64D8EA; }
        .cm-footer-icns.toggle-off, .cm-footer-text.toggle-off { color: #8CBBCC; }`;


    document.body.appendChild(copyMenuCSS);

    copyMenu.id = 'copyContextMenu';
    copyMenu.style.position = 'fixed';
    copyMenu.style.display = 'none';
    copyMenu.style.top = '0px';
    copyMenu.style.left = '0px';
    //copyMenu.style.backgroundColor = 'rgba(147, 196, 211, 0.95)';
    copyMenu.style.width = '180px';
    copyMenu.style.minHeight = '180px';
    copyMenu.style.margin = '0';
    copyMenu.style.padding = '0px';
    copyMenu.style.borderRadius = '5px';
    copyMenu.style.boxShadow = '0px 1px 12px rgba(0,0,0,0.7)';
    copyMenu.style.border = '1px solid rgb(89, 137, 150)';
    copyMenu.style.borderBottom = '1px solid #2D505F';
    copyMenu.style.color = 'white';
    copyMenu.style.zIndex = '9999';
    copyMenu.innerHTML = `<div id="cmContainer" style="color: white; background-color: rgba(147, 196, 211, 0.95); padding:0; margin: 0; position: relative; width: 100%; display: block;"></div>
        <div id="cmFooter" style="height: 20px; background-color: rgba(88, 136, 158, 0.85); padding: 0px 7px 0px; margin: 0; position: relative; width: 100%; display: block;"></div>`;

    document.getElementById('WazeMap').appendChild(copyMenu);

    document.getElementById('cmFooter').innerHTML = `
        <div style="position: relative; float: left; vertical-align: middle;">
        <i id="cmPinMenu" class="fa fa-thumb-tack cm-footer-icns fa-fw toggle-off" value=true title="Pin menu" data-toggle="tooltips"></i>
        <span id="cmPinClose" class="cm-footer-text toggle-off" style="font-weight: 600; border-left: 1px solid #D4E7ED; padding-left: 8px; text-transform: uppercase; font-size: 10px; letter-spacing: .7px;">Close</span>
        </div>
        <div style="display: inline-table; border-radius: 20px; border: 1px solid #6EA1B7; position: relative; float: right; padding: 0px 1px 0px 5px;">
        <span><i id="cmClipboard" value=false style="font-size: 12px; padding: 0px 3px; border-right: 1px solid #6EA1B7;" class="fa fa-clipboard fa-fw cm-footer-icns" title="Copy to Clipboard" data-toggle="tooltips"></i></span>
        <span><i id="cmRSel" value=false class="fa fa-road cm-footer-icns fa-fw toggle-off" title="Copy to WME Road Selector" data-toggle="tooltips"></i></span>
        </div>`;

    resetCopyContextMenu();

    if (localStorage.WME_CopyMenu) {
        copyMenuSettings = JSON.parse(localStorage.WME_CopyMenu);
    } else {
        copyMenuSettings = {
            clipboard: true,
            pin: false
        };
        localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
    }

    try {
        document.querySelector('#user-tabs a[href="#sidepanel-roadselector"]').parentNode.id = 'tabRSel';
    } catch (err) {}

    if (copyMenuSettings.clipboard || document.getElementById('tabRSel') === null) {
        document.getElementById('cmClipboard').value = true;
        document.getElementById('cmClipboard').classList.remove('toggle-off');
        document.getElementById('cmRSel').value = false;
        document.getElementById('cmRSel').classList.add('toggle-off');
    } else {
        document.getElementById('cmClipboard').value = false;
        document.getElementById('cmClipboard').classList.add('toggle-off');
        document.getElementById('cmRSel').value = true;
        document.getElementById('cmRSel').classList.remove('toggle-off');
    }

    if (copyMenuSettings.pin) {
        document.getElementById('cmPinMenu').value = true;
        document.getElementById('cmPinMenu').classList.remove('toggle-off');
        document.getElementById('cmPinClose').classList.remove('toggle-off');
    } else {
        document.getElementById('cmPinMenu').value = false;
        document.getElementById('cmPinMenu').classList.add('toggle-off');
        document.getElementById('cmPinClose').classList.add('toggle-off');
    }


    document.getElementById('WazeMap').addEventListener('contextmenu', function(e){
        var selectedItems = selectionIsSegment();
        if (selectedItems) {
            e.preventDefault();
            var segInfo = getSegmentProperties(selectedItems);
            populateCopyContextMenu(segInfo);

            var copyMenu = document.getElementById('copyContextMenu'),
                wazeMapWidth = $('#WazeMap').width(),
                wazeMapHeight = $('#WazeMap').height();

            copyMenu.style.display = 'block';
            copyMenu.style.top = e.y + 'px';
            copyMenu.style.left = e.x + 'px';
            //copyMenu.style.margin = (wazeMapHeight-e.offsetY)  + 'px 0px 0px' + (wazeMapWidth-e.offsetX) + 'px';

        } else {
            return false;
        }
    }, false);

    document.getElementById('cmClipboard').onclick = function(e){
        e.stopPropagation();
        document.getElementById('cmRSel').value = false;
        document.getElementById('cmRSel').classList.add('toggle-off');
        this.value = true;
        this.classList.remove('toggle-off');
        copyMenuSettings.clipboard = true;
        localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
    };

    document.getElementById('cmRSel').onclick = function(e){
        e.stopPropagation();
        if (document.getElementById('tabRSel') !== null) {
            document.getElementById('cmClipboard').value = false;
            document.getElementById('cmClipboard').classList.add('toggle-off');
            this.value = true;
            this.classList.remove('toggle-off');
            copyMenuSettings.clipboard = false;
            localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
        }
    };

    document.getElementById('cmPinMenu').onclick = function(e){
        e.stopPropagation();
        if (this.value) {
            this.value = false;
            this.classList.add('toggle-off');
            document.getElementById('cmPinClose').classList.add('toggle-off');
            removeCMEventListeners();
        } else {
            this.value = true;
            this.classList.remove('toggle-off');
            document.getElementById('cmPinClose').classList.remove('toggle-off');
            window.removeEventListener('click', removeCMEventListeners, false);
            document.getElementById('toolbar').removeEventListener('mouseenter', removeCMEventListeners, false);
        }
        copyMenuSettings.pin = !copyMenuSettings.pin;
        localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
    };

    document.getElementById('cmPinClose').onclick = function(e) {
        removeCMEventListeners();
    }



};


setTimeout(initCopyContextMenu,3000);
// ==UserScript==
// @name            WME Copy to... Menu (dev)
// @namespace       https://greasyfork.org/users/11629-TheLastTaterTot
// @version         0.1
// @description     Simplify the task of copying segment info with this easy-access right-click context menu. Copy segment names, cities, ids & etc directly to your clipboard or to WME Road Selector.
// @author          TheLastTaterTot
// @include         https://editor-beta.waze.com/*editor/*
// @include         https://www.waze.com/*editor/*
// @exclude         https://www.waze.com/*user/editor/*
// @grant           GM_setClipboard
// @run-at          document-end
// ==/UserScript==
/* jshint -W097 */

var copyTo = function(opt, val) {
    if (document.getElementById('cmClipboard').value) {
        GM_setClipboard(val);
    } else {
        switch (opt) {
            case 'cm_ids':
                document.getElementById('inRSSegId').value = val;
                break;

            case 'cm_primaryStreet':
                document.getElementById('inRSStreet').value = val;
                document.getElementById('selRSAlttStreet').value = 0;
                break;

            case 'cm_altStreets':
                document.getElementById('inRSStreet').value = val;
                document.getElementById('selRSAlttStreet').value = 1;

                break;

            case 'cm_altStreetsAND':
                document.getElementById('inRSStreet').value = '';
                break;

            case 'cm_altStreetsOR':
                document.getElementById('inRSStreet').value = '';
                break;

            case 'cm_primaryCity':
                document.getElementById('inRSCity').value = val;
                document.getElementById('selRSAltCity').value = 0;
                break;

            case 'cm_altCities':
                document.getElementById('inRSCity').value = val;
                document.getElementById('selRSAltCity').value = 1;
                break;

            case 'cm_state':
                document.getElementById('inRSState').value = val;
                //document.getElementById('btnRSAddState').click('true')
                break;

            case 'cm_roadType':
                document.getElementById('selRSRoadType').value = val;
                break;

            case 'cm_updatedBy':
                document.getElementById('inRSUpdtd').value = val;
                break;

            case 'cm_createdBy':
                document.getElementById('inRSCrtd').value = val;
                break;

            case 'cm_toConnections':

                break;
        }

        // swap panel from selection panel
        document.getElementById('user-info').style.display = 'block';
        document.getElementById('edit-panel').style.display = 'none';

        // switch active tab-content
        document.querySelector('.tab-content>.active').classList.remove('active');
        document.getElementById('sidepanel-roadselector').classList.add('active');

        // switch active nav-tab
        document.querySelector('#user-tabs li.active').classList.remove('active');
        document.getElementById('tabRSel').classList.add('active')

        // switch to RSel editor tab
        document.getElementById('roadselector-tabs').childNodes[1].classList.remove('active');
        document.getElementById('roadselector-tabs').childNodes[0].classList.add('active');
        document.getElementById('roadselector-tab-content').childNodes[1].classList.remove('active');
        document.getElementById('roadselector-tab-content').childNodes[0].classList.add('active');
    }
};


var getSegmentProperties = function(selectedItems) {
    /*var roadTypeOpts = document.querySelector('#segment-edit-general select[name="roadType"]'),
        numRoadTypes = roadTypeOpts.options.length, r, roadTypes = {};
    for (r=0; r < numRoadTypes; r++) {
        roadTypes[roadTypeOpts[r].value] = roadTypeOpts[r].text;
    }*/
    var roadTypes = {
            1: "Street",
            2: "Primary Street",
            3: "Freeway",
            4: "Ramp",
            5: "Walking Trail",
            6: "Major Highway",
            7: "Minor Highway",
            8: "Dirt road / 4X4 Trail",
            10: "Pedestrian Boardwalk",
            15: "Ferry",
            16: "Stairway",
            17: "Private Road",
            18: "Railroad",
            19: "Runway/Taxiway",
            20: "Parking Lot Road"
        };

    var s, s_ids = {}, s_altStObjKeys;
        s_ids = {ids: {},
                 primaryStreet: {},
                 altStreets: {},
                 altCities: {},
                 roadType: {},
                 createdBy: {},
                 updatedBy: {},
                 toConnections: {},
                 primaryCity: {},
                 state: {},
                 country: {}
        };

    for (s = selectedItems.length; s--;) {
        s_ids.ids[selectedItems[s].model.attributes.id] = null;
        s_ids.primaryStreet[selectedItems[s].model.attributes.primaryStreetID] = null;
        s_ids.roadType[selectedItems[s].model.attributes.roadType] = null;
        s_ids.createdBy[selectedItems[s].model.attributes.createdBy] = null;
        s_ids.updatedBy[selectedItems[s].model.attributes.updatedBy] = null;
        s_ids.primaryCity[Waze.model.streets.objects[selectedItems[s].model.attributes.primaryStreetID].cityID] = null;
        s_ids.state[Waze.model.cities.objects[Waze.model.streets.objects[selectedItems[s].model.attributes.primaryStreetID].cityID].stateID] = null;
        s_ids.country[Waze.model.cities.objects[Waze.model.streets.objects[selectedItems[s].model.attributes.primaryStreetID].cityID].countryID] = null;

        s_altSt = selectedItems[s].model.attributes.streetIDs;
        for (var a=0, numAlts=s_altSt.length; a<numAlts; a++) {
            s_ids.altStreets[s_altSt[a]] = null;
                s_ids.altCities[Waze.model.streets.objects[s_altSt[a]].cityID] = null;
        }

        s_toConnObjKeys = Object.keys(selectedItems[s].model.attributes.toConnections);
        for (var k=0, numKeys=s_toConnObjKeys.length; k<numKeys; k++) {
            if (s_toConnObjKeys[k] !== '') {
                s_ids.toConnections[s_toConnObjKeys[k]] = selectedItems[s].model.attributes.toConnections[s_toConnObjKeys[k]];
            }
        }
    }

    var seg_ids = {}, seg_names = {
            ids: [],
            primaryStreet: [],
            altStreets: [],
            altCities: [],
            roadType: [],
            createdBy: [],
            updatedBy: [],
            toConnections: [],
            primaryCity: [],
            state: [],
            country: []
    };

    for ( var idKey in s_ids ) {
        seg_ids[idKey] = Object.keys(s_ids[idKey]);

        for (var k=0, numKeys=seg_ids[idKey].length; k<numKeys; k++){
            if (seg_ids[idKey][k] !== '') {
                switch (idKey) {
                    case 'primaryStreet':
                        seg_names[idKey][k] = Waze.model.streets.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'primaryCity':
                        seg_names[idKey][k] = Waze.model.cities.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'altStreets':
                        seg_names[idKey][k] =  Waze.model.streets.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'altCities':
                        seg_names[idKey][k] = Waze.model.cities.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'state':
                        seg_names[idKey][k] = Waze.model.states.objects[seg_ids[idKey][k]].name;
                        break;
                    case 'roadType':
                        seg_names[idKey][k] = roadTypes[String(seg_ids[idKey][k])];
                        break;
                    case 'createdBy':
                        seg_names[idKey][k] = Waze.model.users.objects[seg_ids[idKey][k]].userName;
                        break;
                    case 'updatedBy':
                        seg_names[idKey][k] = Waze.model.users.objects[seg_ids[idKey][k]].userName;
                        break;
                }
            }
        }
    }
    /*
    var seg_names = {
        primaryStreet: Waze.model.streets.objects[seg_ids.primaryStreet].name,
        primaryCity: Waze.model.cities.objects[seg_ids.primaryCity].name,
        altStreets: [],
        altCities: [],
        state: Waze.model.states.objects[seg_ids.state].name,
        roadType: roadTypes[String(seg_ids.roadType)],
        createdBy: Waze.model.users.objects[seg_ids.createdBy].userName,
        updatedBy: Waze.model.users.objects[seg_ids.updatedBy].userName
    }
    for (var a=0, numAlts=seg_ids.altStreets.length; a<numAlts; a++){
        seg_names.altStreets[a] = Waze.model.streets.objects[seg_ids.altStreets[a]].name;
        seg_ids.altCities[a] = Waze.model.streets.objects[seg_ids.altStreets[a]].cityID;
        seg_names.altCities[a] = Waze.model.cities.objects[seg_ids.altCities[a]].name;
    }
    //Waze.model.countries.objects[seg_ids.country].name;
    */
    return { ids: seg_ids, names: seg_names };
};

var resetCopyContextMenu = function(){
    document.getElementById('cmContainer').innerHTML = `
        <div id="cm_street" class="cm-menu-section">
        <dl id="cm_primaryStreet">
        <dt>Street</dt>
        </dl>
        <dl id="cm_altStreets">
        <dt>Alt street</dt>
        </dl>
        </div>
        <div id="cm_city" class="cm-menu-section">
        <dl id="cm_primaryCity">
        <dt>City</dt>
        </dl>
        <dl id="cm_altCities">
        <dt>Alt city</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl id="cm_state">
        <dt>State</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl id="cm_roadType">
        <dt>Road type</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl id="cm_updatedBy">
        <dt>Updated by</dt>
        </dl>
        <dl id="cm_createdBy">
        <dt>Created by</dt>
        </dl>
        </div>
        <div class="cm-menu-section">
        <dl>
        <dd id="cm_ids">Segment IDs</dd>
        </dl>
        </div>`;
}; // style="border-bottom: 0;"

var removeCMEventListeners = function() {
    document.getElementById('copyContextMenu').style.display = 'none';

    window.removeEventListener('click', removeCMEventListeners, false);
    document.getElementById('toolbar').removeEventListener('mouseenter', removeCMEventListeners, false);
}

var populateCopyContextMenu = function(segInfo) {
    resetCopyContextMenu();
    var updateNames = Object.keys(segInfo.ids),
        numNames = updateNames.length,
        n, selOption, emptyArr;

    for (n = numNames; n--;) {
        if (document.getElementById('cm_'+updateNames[n]) && segInfo.ids[updateNames[n]] && segInfo.ids[updateNames[n]].length) {
            if (updateNames[n] !== 'ids') {
                emptyArr = 0;
                for (var a=0, aLength = segInfo.ids[updateNames[n]].length; a < aLength; a++) {
                    if (segInfo.names[updateNames[n]][a] && segInfo.names[updateNames[n]][a].length && segInfo.names[updateNames[n]][a] !== '') {
                        selOption = document.createElement('dd');
                        selOption.innerHTML = segInfo.names[updateNames[n]][a];
                        selOption.name = segInfo.ids[updateNames[n]][a];
                        document.getElementById('cm_'+updateNames[n]).appendChild(selOption);

                        switch (updateNames[n]) {
                            case 'roadType':
                                selOption.onclick = function(e){
                                    if (document.getElementById('cmPinMenu').value) e.stopPropagation();
                                    copyTo(this.parentNode.id, this.name);
                                };
                                break;
                            default:
                                selOption.onclick = function(e){
                                    if (document.getElementById('cmPinMenu').value) e.stopPropagation();
                                    copyTo(this.parentNode.id, this.innerHTML);
                                };
                        }
                    } else {
                        emptyArr++;
                    }
                }
                if (emptyArr === aLength) {
                    if (document.getElementById('cm_'+updateNames[n])) {
                        document.getElementById('cm_'+updateNames[n]).style.display = "none";
                    }
                }
            } else {
                selOption = document.getElementById('cm_ids');
                selOption.name = segInfo.ids[updateNames[n]].join(',');
                selOption.onclick = function(e){
                    if (document.getElementById('cmPinMenu').value) e.stopPropagation();
                    copyTo(this.id, this.name);
                };
            }
        } else if (document.getElementById('cm_'+updateNames[n])) {
            document.getElementById('cm_'+updateNames[n]).style.display = "none";
        }
    }

    if (!segInfo.names.primaryStreet.length && !segInfo.names.altStreets.length) {
        document.getElementById('cm_primaryStreet').parentNode.style.display = 'none';
    }

    if (!segInfo.names.primaryCity.length && !segInfo.names.altCities.length) {
        document.getElementById('cm_primaryCity').parentNode.style.display = 'none';
    }

    if (!segInfo.names.state.length) document.getElementById('cm_state').parentNode.style.display = 'none';

    if (!document.getElementById('cmPinMenu').value) {
        window.addEventListener('click', removeCMEventListeners, false);
        document.getElementById('toolbar').addEventListener('mouseenter', removeCMEventListeners, false);
    }
};


var selectionIsSegment = function() {
    var sel = Waze.selectionManager.selectedItems;
    if (sel.length) {
        return (sel[sel.length-1].model.type === 'segment') ? sel : false;
    } else { return false; }
};


var initCopyContextMenu = function(){
    var copyMenu = document.createElement('div'),
        copyMenuCSS = document.createElement('style'),
        copyMenuSettings;


    copyMenuCSS.type = 'text/css';
    copyMenuCSS.innerHTML = `
        div.cm-menu-section { border-bottom: 1px solid #416B7C; padding: 4px 0px; }
        .cm-menu-section dl { margin: 0; padding: 0; display: block; }
        .cm-menu-section dt { font-size: 10px; padding: 0px 10px; margin: 4px 0px 0px; text-transform: uppercase; line-height: 1.1; }
        .cm-menu-section dd { padding: 1px 10px; font-size: 11px; color: #234350; font-weight: 600;}
        .cm-menu-section dd:hover, .cm-menu-section dd:active, .cm-menu-section dd:focus { background-color: #BEDCE5; color: #416B7C; }
        .cm-menu-section dd:active { color: #64D8EA; }
        div#cmFooter { color: #DDEDF3; }
        .cm-footer-text { cursor: pointer; }
        .cm-footer-icns { margin: 0px 3px 0px 0px; cursor: pointer; display: inline-table; line-height: 1; }
        .cm-footer-icns:active, .cm-footer-icns:focus, .cm-footer-icns.toggle-off:active, .cm-footer-icns.toggle-off:focus { color: #64D8EA; }
        .cm-footer-icns.toggle-off, .cm-footer-text.toggle-off { color: #8CBBCC; }`;


    document.body.appendChild(copyMenuCSS);

    copyMenu.id = 'copyContextMenu';
    copyMenu.style.position = 'fixed';
    copyMenu.style.display = 'none';
    copyMenu.style.top = '0px';
    copyMenu.style.left = '0px';
    //copyMenu.style.backgroundColor = 'rgba(147, 196, 211, 0.95)';
    copyMenu.style.width = '180px';
    copyMenu.style.minHeight = '180px';
    copyMenu.style.margin = '0';
    copyMenu.style.padding = '0px';
    copyMenu.style.borderRadius = '5px';
    copyMenu.style.boxShadow = '0px 1px 12px rgba(0,0,0,0.7)';
    copyMenu.style.border = '1px solid rgb(89, 137, 150)';
    copyMenu.style.borderBottom = '1px solid #2D505F';
    copyMenu.style.color = 'white';
    copyMenu.style.zIndex = '9999';
    copyMenu.innerHTML = `<div id="cmContainer" style="color: white; background-color: rgba(147, 196, 211, 0.95); padding:0; margin: 0; position: relative; width: 100%; display: block;"></div>
        <div id="cmFooter" style="height: 20px; background-color: rgba(88, 136, 158, 0.85); padding: 0px 7px 0px; margin: 0; position: relative; width: 100%; display: block;"></div>`;

    document.getElementById('WazeMap').appendChild(copyMenu);

    document.getElementById('cmFooter').innerHTML = `
        <div style="position: relative; float: left; vertical-align: middle;">
        <i id="cmPinMenu" class="fa fa-thumb-tack cm-footer-icns fa-fw toggle-off" value=true title="Pin menu" data-toggle="tooltips"></i>
        <span id="cmPinClose" class="cm-footer-text toggle-off" style="font-weight: 600; border-left: 1px solid #D4E7ED; padding-left: 8px; text-transform: uppercase; font-size: 10px; letter-spacing: .7px;">Close</span>
        </div>
        <div style="display: inline-table; border-radius: 20px; border: 1px solid #6EA1B7; position: relative; float: right; padding: 0px 1px 0px 5px;">
        <span><i id="cmClipboard" value=false style="font-size: 12px; padding: 0px 3px; border-right: 1px solid #6EA1B7;" class="fa fa-clipboard fa-fw cm-footer-icns" title="Copy to Clipboard" data-toggle="tooltips"></i></span>
        <span><i id="cmRSel" value=false class="fa fa-road cm-footer-icns fa-fw toggle-off" title="Copy to WME Road Selector" data-toggle="tooltips"></i></span>
        </div>`;

    resetCopyContextMenu();

    if (localStorage.WME_CopyMenu) {
        copyMenuSettings = JSON.parse(localStorage.WME_CopyMenu);
    } else {
        copyMenuSettings = {
            clipboard: true,
            pin: false
        };
        localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
    }

    try {
        document.querySelector('#user-tabs a[href="#sidepanel-roadselector"]').parentNode.id = 'tabRSel';
    } catch (err) {}

    if (copyMenuSettings.clipboard || document.getElementById('tabRSel') === null) {
        document.getElementById('cmClipboard').value = true;
        document.getElementById('cmClipboard').classList.remove('toggle-off');
        document.getElementById('cmRSel').value = false;
        document.getElementById('cmRSel').classList.add('toggle-off');
    } else {
        document.getElementById('cmClipboard').value = false;
        document.getElementById('cmClipboard').classList.add('toggle-off');
        document.getElementById('cmRSel').value = true;
        document.getElementById('cmRSel').classList.remove('toggle-off');
    }

    if (copyMenuSettings.pin) {
        document.getElementById('cmPinMenu').value = true;
        document.getElementById('cmPinMenu').classList.remove('toggle-off');
        document.getElementById('cmPinClose').classList.remove('toggle-off');
    } else {
        document.getElementById('cmPinMenu').value = false;
        document.getElementById('cmPinMenu').classList.add('toggle-off');
        document.getElementById('cmPinClose').classList.add('toggle-off');
    }


    document.getElementById('WazeMap').addEventListener('contextmenu', function(e){
        var selectedItems = selectionIsSegment();
        if (selectedItems) {
            e.preventDefault();
            var segInfo = getSegmentProperties(selectedItems);
            populateCopyContextMenu(segInfo);

            var copyMenu = document.getElementById('copyContextMenu'),
                wazeMapWidth = $('#WazeMap').width(),
                wazeMapHeight = $('#WazeMap').height();

            copyMenu.style.display = 'block';
            copyMenu.style.top = e.y + 'px';
            copyMenu.style.left = e.x + 'px';
            //copyMenu.style.margin = (wazeMapHeight-e.offsetY)  + 'px 0px 0px' + (wazeMapWidth-e.offsetX) + 'px';

        } else {
            return false;
        }
    }, false);

    document.getElementById('cmClipboard').onclick = function(e){
        e.stopPropagation();
        document.getElementById('cmRSel').value = false;
        document.getElementById('cmRSel').classList.add('toggle-off');
        this.value = true;
        this.classList.remove('toggle-off');
        copyMenuSettings.clipboard = true;
        localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
    };

    document.getElementById('cmRSel').onclick = function(e){
        e.stopPropagation();
        if (document.getElementById('tabRSel') !== null) {
            document.getElementById('cmClipboard').value = false;
            document.getElementById('cmClipboard').classList.add('toggle-off');
            this.value = true;
            this.classList.remove('toggle-off');
            copyMenuSettings.clipboard = false;
            localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
        }
    };

    document.getElementById('cmPinMenu').onclick = function(e){
        e.stopPropagation();
        if (this.value) {
            this.value = false;
            this.classList.add('toggle-off');
            document.getElementById('cmPinClose').classList.add('toggle-off');
            removeCMEventListeners();
        } else {
            this.value = true;
            this.classList.remove('toggle-off');
            document.getElementById('cmPinClose').classList.remove('toggle-off');
            window.removeEventListener('click', removeCMEventListeners, false);
            document.getElementById('toolbar').removeEventListener('mouseenter', removeCMEventListeners, false);
        }
        copyMenuSettings.pin = !copyMenuSettings.pin;
        localStorage.WME_CopyMenu = JSON.stringify(copyMenuSettings);
    };

    document.getElementById('cmPinClose').onclick = function(e) {
        removeCMEventListeners();
    }



};


setTimeout(initCopyContextMenu,3000);