您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Harmonizes, formats, and locks a selected place
当前为
/* global I18n */ /* global OpenLayers */ /* global $ */ /* global W */ /* global unsafeWindow */ /* global Components */ // ==UserScript== // @name Place Harmonizer Beta // @namespace https://greasyforks.org/en/users/19426-bmtg // @version 1.0.14 // @description Harmonizes, formats, and locks a selected place // @author WMEPH development group // @include https://www.waze.com/editor/* // @include https://www.waze.com/*/editor/* // @include https://editor-beta.waze.com/editor/* // @include https://editor-beta.waze.com/*/editor/* // @grant GM_xmlhttpRequest // ==/UserScript== (function () { var WMEPHversion = "1.0.14"; var isDevVersion = true; var USA_PNH_DATA; var USA_PNH_NAMES = []; var CAN_PNH_DATA; var CAN_PNH_NAMES = []; var devVersStr; var devVersStrSpace; var devVersStrDash; if (isDevVersion) { devVersStr = "Beta"; devVersStrSpace = " " + devVersStr; devVersStrDash = "-" + devVersStr; } else { devVersStr = ""; devVersStrSpace = ""; devVersStrDash = ""; } function placeHarmonizer_bootstrap() { var bGreasemonkeyServiceDefined = false; try { if ("object" === typeof Components.interfaces.gmIGreasemonkeyService) { bGreasemonkeyServiceDefined = true; } } catch (err) { //Ignore. } if ( "undefined" === typeof unsafeWindow || ! bGreasemonkeyServiceDefined) { unsafeWindow = ( function () { var dummyElem = document.createElement('p'); dummyElem.setAttribute ('onclick', 'return window;'); return dummyElem.onclick (); } ) (); } /* begin running the code! */ if (("undefined" !== typeof W.loginManager)) { setTimeout(function() { // Pull USA PNH Data GM_xmlhttpRequest({ method: "GET", url: "https://docs.google.com/spreadsheets/d/1-f-JTWY5UnBx-rFTa4qhyGMYdHBZWNirUTOgn222zMY/export?format=tsv&id=1-f-JTWY5UnBx-rFTa4qhyGMYdHBZWNirUTOgn222zMY&gid=1061880663", onload: function (response) { //phlog(response.responseText); USA_PNH_DATA = response.responseText.split('\n'); } }); // Pull CAN PNH Data GM_xmlhttpRequest({ method: "GET", url: "http://docs.google.com/spreadsheets/d/1TIxQZVLUbAJ8iH6LPTkJsvqFb_DstrHpKsJbv1W1FZs/export?format=tsv&id=1TIxQZVLUbAJ8iH6LPTkJsvqFb_DstrHpKsJbv1W1FZs&gid=947416380", onload: function (response) { //phlog(response.responseText ); CAN_PNH_DATA = response.responseText.split('\n'); } }); }, 0); dataReady(); // Run the code } else { phlog("Bootstrap failed. Trying again..."); setTimeout(function () { placeHarmonizer_bootstrap(); }, 700); } function dataReady() { // If the data has returned, then start, otherwise wait a bit longer if ("undefined" !== typeof CAN_PNH_DATA && "undefined" !== typeof USA_PNH_DATA) { setTimeout(function(){ // Build the name search lists USA_PNH_NAMES = makeNameCheckList(USA_PNH_DATA); CAN_PNH_NAMES = makeNameCheckList(CAN_PNH_DATA); }, 200); setTimeout(runPH, 900); // start the main code } else { phlog("Waiting for PNH Data..."); setTimeout(function () { dataReady(); }, 200); } } } function runPH() { var WMEPHWhatsNew = ['All new version with new features', 'Live integration with PNH data', 'Over 600 chains harmonized', 'Works in the USA and Canada', 'Interactive banner buttons', 'Fixed bugs']; // New in this version var newSep = '\n - '; WMEPHWhatsNew = WMEPHWhatsNew.join(newSep); // If the editor installs a newer version, pop up an alert with the new elements // if ( localStorage.getItem('WMEPHversion') === null ) { // localStorage.setItem('WMEPHversion', WMEPHversion); // } else if ( localStorage.getItem('WMEPHversion') !== WMEPHversion ) { alert('WMEPH updated to v. ' + WMEPHversion + '\nUpdates:' + newSep + WMEPHWhatsNew); localStorage.setItem('WMEPHversion', WMEPHversion); localStorage.setItem(GLinkWarning, '0'); } // initialize the KB shortcut and settings tab setTimeout(setupKBShort, 100); // set up KB Shortcut setTimeout(add_PlaceHarmonizationSettingsTab, 150); // set up settings tab // function to prime the shortcuts function setupKBShort() { if (isDevVersion) { shortcut.add("Shift+Alt+s", function() { harmonizePlace(); }); } else { shortcut.add("Shift+Alt+a", function() { harmonizePlace(); }); } } var WMEPHurl = 'https://www.waze.com/forum/posting.php?mode=reply&f=819&t=164962'; // WMEPH Forum thread URL var USAPNHMasURL = 'https://docs.google.com/spreadsheets/d/1-f-JTWY5UnBx-rFTa4qhyGMYdHBZWNirUTOgn222zMY/edit#gid=0'; // Master USA PNH link var placesWikiURL = 'https://wiki.waze.com/wiki/Places'; var thisUser = W.loginManager.user; if (thisUser === null) { phlog("Could not determine user."); return; } var WMEPHdevList = ("bmtg|vtpearce|cardyin|jtsmith2|joyriding|fjsawicki|coolcanuck").split("|"); var WMEPHbetaList = ("jwe252|uscwaller|t0cableguy|tonestertm|driving79|nacron|machete808|bz2012|carloslaso|xanderb|ehepner1977|roadtechie|" + "havanaday|nimbus-|itzwolf|jroman7|mrbyte_ontheroad|ggrane|ardan74|red-nax|wambuli|turbomkt|trackmum|hawkeygoal|justins83|ronrover|" + "pesachz").split("|"); var devUser = (WMEPHdevList.indexOf(thisUser.userName.toLowerCase()) > -1); var betaUser = (WMEPHbetaList.indexOf(thisUser.userName.toLowerCase()) > -1); if (devUser) {betaUser = true;} // dev users are beta users var usrRank = thisUser.normalizedLevel; // get editor's level var GLinkWarning = 'GLinkWarning'; // Warning message for first time users not to use 3rd party sources. if (!localStorage.getItem(GLinkWarning)) { // store settings so the warning is only given once localStorage.setItem(GLinkWarning, '0'); } if (!localStorage.getItem("WMEPH-AlertNoHours" + devVersStr)) { // set default to ON if no previous setting localStorage.setItem("WMEPH-AlertNoHours" + devVersStr, '1'); } // lock levels are offset by one var lockLevel1 = 0; var lockLevel2 = 1; var lockLevel3 = 2; var lockLevel4 = 3; var lockLevel5 = 4; // Only lock up to the user's level if (lockLevel2 > (usrRank - 1)) {lockLevel2 = (usrRank - 1);} if (lockLevel3 > (usrRank - 1)) {lockLevel3 = (usrRank - 1);} if (lockLevel4 > (usrRank - 1)) {lockLevel4 = (usrRank - 1);} if (lockLevel5 > (usrRank - 1)) {lockLevel5 = (usrRank - 1);} var PMUserList = { // user names and IDs SER: {approvalActive: true, modID: '16941753', modName: 't0cableguy'}, WMEPH: {approvalActive: true, modID: '17027620', modName: 'bmtg'}, }; //var forumMsgInputs = { subject: 'Re: WMEPH', message: 'Message:', addbbcode20: '100', preview: 'Preview', attach_sig: 'on', notify: 'on' }; // Default forum post //var forumPMInputs = { subject: 'WMEPH message', message: 'Message:', preview: 'Preview', attach_sig: 'on' }; // Default PM post var severity; // error tracking to determine banner color (messages) var severityButt; // error tracking to determine banner color (action buttons) var bannButt; // Banner Buttons object var sidebarMessageOld; // *** Eventually delete once new method is complete var sidebarMessage; // Holds the banner messages var bannMess = { // banner message array in order of display bankType1: { active: false, severity: 3, message: 'Clarify the type of bank: the name has ATM but the primary category is Offices' }, gasBrandMM: { active: false, severity: 3, message: 'Gas name and brand do not appear to match. Verify which is correct.' }, gasUnbranded: { active: false, severity: 3, message: '"Unbranded" should not be used for the station brand. Change to the correct brand or use the blank entry at the top of the brand list.' }, areaNotPoint: { active: false, severity: 3, message: 'This category should be an area place. Either change it, or manually lock it.' }, areaStadium: { active: false, severity: 3, message: 'This category should be an area. Either change it, manually lock it, or consider using "Sports Court" category and a place point for small/local fields.' }, areaPostOfficeSER: { active: false, severity: 3, message: 'Only use the "Post Office" category for USPS post offices. If this is a USPS location, please change to an area place and run the script again. All other mail service places use the "Shopping and Services" Category.' }, areaHospital: { active: false, severity: 3, message: 'This category should usually be an area. Either change it, or use the "Office" category for non-emergency medical offices.' }, unmappedSER: { active: false, severity: 3, message: 'This category is usually not mapped in the SE region. If it\'s a valid place, please manually lock it.' }, pointCarDealerSER: { active: false, severity: 3, message: 'This category should be a point place, not an area.' }, nameMissing: { active: false, severity: 3, message: 'Name is missing.' }, hnMissing: { active: false, severity: 3, message: 'House number missing.' }, hnNonStandard: { active: false, severity: 3, message: 'House number is non-standard. Correct and rerun script, or manually lock the place.' }, streetMissing: { active: false, severity: 3, message: 'Street missing.' }, cityMissing: { active: false, severity: 3, message: 'City missing.' }, checkDescription: { active: false, severity: 2, message: 'Description field already contained info; PNH description was added in front of existing. Check for consistency or duplicate info.' }, resiTypeName: { active: false, severity: 2, message: 'The place name suggests a residential place. Please verify.' }, phoneInvalid: { active: false, severity: 2, message: 'Phone invalid.' }, mismatch247: { active: false, severity: 2, message: 'Hours of operation listed as open 24hrs but not for all 7 days.' }, subFuel: { active: false, severity: 1, message: 'Make sure this place is for the gas station itself and not the main store building. Otherwise undo and check the categories.' }, longURL: { active: false, severity: 1, message: 'Existing long URL was kept. Please verify.' }, catHotel: { active: false, severity: 1, message: 'Please check hotel details, as names can often be unique (e.g. Holiday Inn - Tampa North).' }, catPostOffice: { active: false, severity: 1, message: 'Verify the primary name according to your regional standards. If this is not a USPS post office, change the category, as "Post Office" is only used for USPS locations.' }, phoneMissing: { active: false, severity: 1, message: 'Phone missing.' }, urlMissing: { active: false, severity: 1, message: 'URL missing.' }, gasNoBrand: { active: false, severity: 1, message: 'Verify that gas station has no brand.' }, localURL: { active: false, severity: 0, message: 'Some locations for this business have localized urls, while others use the primary corporate site. Check if a local url applies to this location.' }, babiesRUs: { active: false, severity: 0, message: 'If there is a Toys R Us at this location, please make it the primary name and Babies R Us the alt name and rerun the script.' }, noHours: { active: false, severity: 0, message: 'Hours of operation missing.' }, generalStadium: { active: false, severity: 0, message: 'If this is a small/local ballfield or arena, consider using the "Sports Court" category and making it a point place.' }, placeFormatted: { active: false, severity: 0, message: 'Place formatted.' }, placeMatched: { active: false, severity: 0, message: 'Place matched from PNH data.' }, placeLocked: { active: false, severity: 0, message: 'Place locked.' } }; var catTransWaze2Lang = I18n.translations['en'].venues.categories; // pulls the category translations var item; var newName; var newAliases = []; var newAliasesTemp = []; var newCategories = []; var newURL; var newPhone; var newServices = []; if (isDevVersion && thisUser.userName !== 'bmtg') { debugger; } // CSS setups var cssCode = [".PHbutton {background: #ffffff;color: #000;padding: 0px 6px 0px 6px;text-decoration: none;}", ".PHbutton:hover {background: #e8e5e8;text-decoration: none;}"]; for (var cssix=0; cssix<cssCode.length; cssix++) { insertCss(cssCode[cssix]); } function insertCss( code ) { var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = code; document.head.appendChild( style ); } // END insertCss funtion // used for phone reformatting if (!String.plFormat) { String.plFormat = function(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function(name, number) { return typeof args[number] !== "undefined" ? args[number] : null; }); }; } // Banner production function WMEPH_DispWarn(e) { "use strict"; e = "<li>" + e; var n = $('<div id="WMEPHlog">').append(e); $("#WMEPH_logger_warn").append(n); } // END WMEPH_DispWarn function // Change place.name to title case var ignoreWords = ["an", "and", "as", "at", "by", "for", "from", "hhgregg", "in", "into", "of", "on", "or", "the", "to", "with"]; var capWords = ["3M", "AMC", "AOL", "AT&T", "ATM", "BBC", "BLT", "BMV", "BMW", "BP", "CBS", "CCS", "CGI", "CISCO", "CNN", "CVS", "DHL", "DKNY", "DMV", "DSW", "ER", "ESPN", "FCUK", "GNC", "H&M", "HP", "HSBC", "IBM", "IKEA", "IRS", "JBL", "JCPenney", "KFC", "LLC", "MBNA", "MCA", "MCI", "NBC", "PNC", "TCBY", "TNT", "UPS", "USA", "USPS", "VW", "ZZZ" ]; function toTitleCase(str) { if (!str) { return str; } var allCaps = (str === str.toUpperCase()); // Cap first letter of each word // str = str.replace(/\b([^\W_\d][^\s-\/]*) */g, function(txt) { str = str.replace(/([A-Za-z\u00C0-\u017F][^\s-\/]*) */g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0).toUpperCase() + txt.substr(1); }); // Cap O'Reilley's, L'Amour, D'Artagnan as long as 5+ letters str = str.replace(/[oOlLdD]'[A-Za-z']{3,}/g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0).toUpperCase() + txt.charAt(1) + txt.charAt(2).toUpperCase() + txt.substr(3); }); // Cap McFarley's, as long as 5+ letters long str = str.replace(/[mM][cC][A-Za-z']{3,}/g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0).toUpperCase() + txt.charAt(1).toLowerCase() + txt.charAt(2).toUpperCase() + txt.substr(3); }); // anything with an "&" sign, cap the character after & str = str.replace(/&.+/g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0) + txt.charAt(1).toUpperCase() + txt.substr(2); }); // lowercase any from the ignoreWords list str = str.replace(/[^ ]+/g, function(txt) { var txtLC = txt.toLowerCase(); return (ignoreWords.indexOf(txtLC) > -1) ? txtLC : txt; }); // uppercase any from the capWords List str = str.replace(/[^ ]+/g, function(txt) { var txtLC = txt.toUpperCase(); return (capWords.indexOf(txtLC) > -1) ? txtLC : txt; }); // Cap first letter of entire name str = str.charAt(0).toUpperCase() + str.substr(1); return str; } // Change place.name to title case function toTitleCaseStrong(str) { if (!str) { return str; } var allCaps = (str === str.toUpperCase()); // Cap first letter of each word // str = str.replace(/\b([^\W_\d][^\s-\/]*) */g, function(txt) { str = str.replace(/([A-Za-z\u00C0-\u017F][^\s-\/]*) */g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); // Cap O'Reilley's, L'Amour, D'Artagnan as long as 5+ letters str = str.replace(/[oOlLdD]'[A-Za-z']{3,}/g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0).toUpperCase() + txt.charAt(1) + txt.charAt(2).toUpperCase() + txt.substr(3).toLowerCase(); }); // Cap McFarley's, as long as 5+ letters long str = str.replace(/[mM][cC][A-Za-z']{3,}/g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0).toUpperCase() + txt.charAt(1).toLowerCase() + txt.charAt(2).toUpperCase() + txt.substr(3).toLowerCase(); }); // anything sith an "&" sign, cap the word after & str = str.replace(/&\w+/g, function(txt) { return ((txt === txt.toUpperCase()) && !allCaps) ? txt : txt.charAt(0) + txt.charAt(1).toUpperCase() + txt.substr(2); }); // lowercase any from the ignoreWords list str = str.replace(/[^ ]+/g, function(txt) { var txtLC = txt.toLowerCase(); return (ignoreWords.indexOf(txtLC) > -1) ? txtLC : txt; }); // uppercase any from the capWords List str = str.replace(/[^ ]+/g, function(txt) { var txtLC = txt.toUpperCase(); return (capWords.indexOf(txtLC) > -1) ? txtLC : txt; }); // Cap first letter of entire name str = str.charAt(0).toUpperCase() + str.substr(1); return str; } // Form banner Message function formBannMess(bannKey) { bannMess[bannKey].active = true; severity = Math.max(bannMess[bannKey].severity, severity); } // Form banner Button Message function formBannButt(bannKey) { bannButt[bannKey].active = true; severityButt = Math.max(bannButt[bannKey].severity, severityButt); } // normalize phone function normalizePhone(s, outputFormat) { if (!s) { formBannMess('phoneMissing'); return s; } var s1 = s.replace(/\D/g, ''); // remove non-number characters var m = s1.match(/^1?([2-9]\d{2})([2-9]\d{2})(\d{4})$/); // Ignore leading 1, and also don't allow area code or exchange to start with 0 or 1 (***USA/CAN specific) if (!m) { formBannMess('phoneInvalid'); return s; } else { return String.plFormat(outputFormat, m[1], m[2], m[3]); } } // Normalize url //function normalizeURL(placeName,s,addr) { function normalizeURL(s) { if (!s) { // Notify that url is missing and provide web search to find website and gather data (provided for all editors) formBannMess('urlMissing'); formBannButt('webSearch'); return s; } s = s.replace(/ \(.*/g, ''); // remove anything with parentheses after it s = s.replace(/ /g, ''); // remove any spaces var m = s.match(/^https?:\/\/(.*)$/i); // remove http(s):// if (m) { s = m[1]; } /* OLD CODE to strip www. Keep in case of reinstatement if ($("#WMEPH-StripWWW" + devVersStr).prop('checked')) { // if option is checked, remove 'www.' from the url m = s.match(/^www\.(.*)$/i); if (m) { s = m[1]; } } */ m = s.match(/^(.*)\/pages\/welcome.aspx$/i); // remove unneeded terms if (m) { s = m[1]; } m = s.match(/^(.*)\/pages\/default.aspx$/i); // remove unneeded terms if (m) { s = m[1]; } m = s.match(/^(.*)\/index.html$/i); // remove unneeded terms if (m) { s = m[1]; } m = s.match(/^(.*)\/index.htm$/i); // remove unneeded terms if (m) { s = m[1]; } m = s.match(/^(.*)\/index.php$/i); // remove unneeded terms if (m) { s = m[1]; } m = s.match(/^(.*)\/$/i); // remove final slash if (m) { s = m[1]; } return s; } // END normalizeURL function // Only run the harmonization if a venue is selected function harmonizePlace() { // Script is only for R2+ editors if (usrRank < 2) { alert("Script is currently available for editors of Rank 2 and up."); return; } // Only run if a single place is selected if (W.selectionManager.selectedItems.length === 1) { var item = W.selectionManager.selectedItems[0].model; if (item.type === "venue") { blurAll(); // focus away from current cursor position harmonizePlaceGo(); } } } // Main script function harmonizePlaceGo() { // Not sure what this does, but it's in all the other scripts that update Waze objects if (isDevVersion && !betaUser) { alert("Please sign up to beta-test this script version.\nSend a PM or Slack-DM to bmtg, or post in the WMEPH forum thread. Thanks."); return; } var UpdateObject; if (typeof(require) !== "undefined") { UpdateObject = require("Waze/Action/UpdateObject"); } else { UpdateObject = W.Action.UpdateObject; } var placePL = WMEPH_initialiseFL(); // set up external post div and pull place PL placePL = placePL.replace(/&layers=[\d]+/g, ''); // remove Permalink Layers var region; var state2L; var gFormState = ""; var newPlaceURL; var approveRegionURL; var PNHOrderNum = ""; var PNHNameTemp = ""; var PNHNameTempWeb = ""; sidebarMessageOld = []; sidebarMessage = []; // var topSBMess; // Unused, delete severity = 0; severityButt = 0; for (var bannKey in bannMess) { bannMess[bannKey].active = false; } bannButt = { // set up banner action buttons. Structure: // active: false until activated in the script // bannText: The text before the button option // id: button id // value: button text // title: tooltip text // cLog: message for console // action: The action that happens if the button is pressed addAlias: { // append optional Alias to the name active: false, bannText: "Is there a " + newAliasesTemp[0] + " at this location?", severity: 0, id: "addAlias", value: "Yes", title: 'Add ' + newAliasesTemp[0], cLog: "Added optional alt-name", action: function() { newAliases = insertAtIX(newAliases,newAliasesTemp,0); if (specCases.indexOf('altName2Desc') > -1) { if ( item.attributes.description.toUpperCase().indexOf(newAliasesTemp.toUpperCase()) === -1 ) { newDescripion = newAliasesTemp + '\n' + newDescripion; W.model.actionManager.add(new UpdateObject(item, { description: newDescripion })); } } W.model.actionManager.add(new UpdateObject(item, { aliases: newAliases })); //phlog(bannButt.addAlias.cLog); bannButt.addAlias.active = false; // reset the display flag } }, // END addAlias definition addCat2: { // append optional secondary category to the place active: false, bannText: "Is there a " + newCategories[0] + " at this location?", severity: 0, id: "addCat2", value: "Yes", title: 'Add ' + newCategories[0], cLog: "Added optional secondary category", action: function() { newCategories.push.apply(newCategories,altCategories); W.model.actionManager.add(new UpdateObject(item, { categories: newCategories })); //phlog(bannButt.addCat2.cLog); bannButt.addCat2.active = false; // reset the display flag } }, // END addCat2 definition addPharm: { // append Pharmacy to the place active: false, bannText: "Is there a Pharmacy at this location?", severity: 1, id: "addPharm", value: "Yes", title: 'Add Pharmacy category', cLog: "Added Pharmacy", action: function() { newCategories = insertAtIX(newCategories, 'PHARMACY', 1); W.model.actionManager.add(new UpdateObject(item, { categories: newCategories })); //phlog(bannButt.addPharm.cLog); bannButt.addPharm.active = false; // reset the display flag } }, // END addPharm definition appendAMPM: { // append AMPM to the name active: false, bannText: "Is there an ampm at this location?", severity: 1, id: "appendAMPM", value: "Yes", title: 'Add ampm to the place', cLog: "Added ampm", action: function() { newCategories = insertAtIX(newCategories, 'CONVENIENCE_STORE', 1); newName = 'ARCO ampm'; newURL = 'ampm.com'; W.model.actionManager.add(new UpdateObject(item, { name: newName, url: newURL, categories: newCategories })); //phlog(bannButt.appendAMPM.cLog); bannButt.appendAMPM.active = false; // reset the display flag bannButt.addConvStore.active = false; // also reset the addConvStore display flag } }, // END appendAMPM definition gasMismatch: { // if the gas brand and name don't match active: false, bannText: "Gas name and brand don't match. Move brand to name?", severity: 3, id: "gasMismatch", value: "Yes", title: 'Change the primary name to the brand and make the current name the alt-name.', cLog: "Updated station name from brand", action: function() { newAliases = insertAtIX(newAliases, newName, 0); W.model.actionManager.add(new UpdateObject(item, { name: brand, aliases: newAliases })); phlog(bannButt.gasMismatch.cLog); bannButt.gasMismatch.active = false; // reset the display flag newName = item.attributes.brand; } }, // END gasMismatch definition STC: { // Force strong title case option active: false, // Activated if Strong Title Case != Normal Title Case (e.g. HomeSpace Company) bannText: "Force Title Case: ", severity: 0, id: "toTitleCaseStrong", value: "Yes", title: "Force Title Case to InterNal CaPs", cLog: "Applied Strong Title Case", action: function() { newName = toTitleCaseStrong(item.attributes.name); // Get the Strong Title Case name if (newName !== item.attributes.name) { // if they are not equal W.model.actionManager.add(new UpdateObject(item, { // update the place name name: newName })); phlog(bannButt.STC.cLog); } for (var ixali = 0; ixali < item.attributes.aliases.length; ixali++) { newAliases[ixali] = toTitleCaseStrong(item.attributes.aliases[ixali].slice(0)); // Get the Strong Title Case name } phlog(newAliases); phlog(item.attributes.aliases); phlog(newAliases !== item.attributes.aliases); //phlog(toTitleCaseStrong(item.attributes.aliases[ixali])); if (newAliases !== item.attributes.aliases) { // if they are not equal W.model.actionManager.add(new UpdateObject(item, { // update the place name aliases: newAliases })); phlog(bannButt.STC.cLog); } bannButt.STC.active = false; // reset the display flag } }, // END Strong Title Case definition addATM: { active: false, bannText: "ATM at location? ", severity: 0, id: "addATM", value: "Yes", title: "Add the ATM category to this place", cLog: "Added ATM category", action: function() { newCategories = insertAtIX(newCategories,"ATM",1); // Insert ATM category in the second position W.model.actionManager.add(new UpdateObject(item, { // update the place name categories: newCategories })); bannButt.addATM.active = false; // reset the display flag } }, // END addATM definition standaloneATM: { active: false, bannText: "Is this a standalone ATM? ", severity: 2, id: "standaloneATM", value: "Yes", title: "Is this a standalone ATM with no bank branch?", cLog: "Changed to standalone ATM", action: function() { newCategories = ["ATM"]; // Change to ATM only if (newName.indexOf("ATM") === -1) { newName = newName + ' ATM'; } W.model.actionManager.add(new UpdateObject(item, { categories: newCategories })); bannButt.bankCorporate.active = false; // reset the bank Branch display flag bannButt.bankBranch.active = false; // reset the bank Branch display flag bannButt.standaloneATM.active = false; // reset the standalone ATM display flag } }, // END standaloneATM definition bankBranch: { active: false, bannText: "Is this a bank branch office? ", severity: 1, id: "bankBranch", value: "Yes", title: "Is this a bank branch office?", cLog: "Changed to bank branch", action: function() { newCategories = ["BANK_FINANCIAL","ATM"]; // Change to bank and atm cats newName = newName.replace(/[\- (]*ATM[\- )]*/g, ' ').replace(/^ /g,'').replace(/ $/g,''); // strip ATM from name if present W.model.actionManager.add(new UpdateObject(item, { categories: newCategories })); W.model.actionManager.add(new UpdateObject(item, { name: newName })); bannButt.bankCorporate.active = false; // reset the bank Branch display flag bannButt.bankBranch.active = false; // reset the bank Branch display flag bannButt.standaloneATM.active = false; // reset the standalone ATM display flag } }, // END bankBranch definition bankCorporate: { active: false, bannText: "Is this the bank's corporate offices?", severity: 1, id: "bankCorporate", value: "Yes", title: "Is this the bank's corporate offices?", cLog: "Changed to bank branch", action: function() { newCategories = ["OFFICES"]; // Change to offices category newName = newName.replace(/[\- (]*ATM[\- )]*/g, ' ').replace(/^ /g,'').replace(/ $/g,''); // strip ATM from name if present W.model.actionManager.add(new UpdateObject(item, { categories: newCategories })); W.model.actionManager.add(new UpdateObject(item, { name: newName })); bannButt.bankCorporate.active = false; // reset the bank Branch display flag bannButt.bankBranch.active = false; // reset the bank Branch display flag bannButt.standaloneATM.active = false; // reset the standalone ATM display flag } }, // END bankCorporate definition addConvStore: { active: false, bannText: "Add convenience store category? ", severity: 1, id: "addConvStore", value: "Yes", title: "Add the Convenience Store category to this place", cLog: "Added Convenience Store category", action: function() { newCategories = insertAtIX(newCategories,"CONVENIENCE_STORE",1); // Insert C.S. category in the second position W.model.actionManager.add(new UpdateObject(item, { // update categories: newCategories })); bannButt.addConvStore.active = false; // reset the display flag } }, // END addConvStore definition isitUSPS: { active: false, bannText: "Is this a USPS location? ", severity: 0, id: "isitUSPS", value: "Yes", title: "Is this a USPS location?", cLog: "Fixed USPS", action: function() { newServices = ["AIR_CONDITIONING", "CREDIT_CARDS", "PARKING_FOR_CUSTOMERS", "WHEELCHAIR_ACCESSIBLE"]; W.model.actionManager.add(new UpdateObject(item, { url: "usps.com" })); if (region === 'SER') { W.model.actionManager.add(new UpdateObject(item, { aliases: ["United States Postal Service"] })); } bannButt.isitUSPS.active = false; } }, // END isitUSPS definition PlaceWebsite: { active: false, bannText: "", severity: 0, id: "PlaceWebsite", value: "Open place website", title: "Direct link to place website", cLog: "Open web search", action: function() { window.open('http:\/\/' + newURL); } }, // END PlaceWebsite definition webSearch: { active: false, bannText: "", severity: 0, id: "webSearch", value: "Web Search", title: "Search the web for this place. Do not copy info from 3rd party sources!", cLog: "Open web search", action: function() { if (localStorage.getItem(GLinkWarning) === '1') { window.open(buildGLink(newName,addr)); } else { if (confirm('***Please DO NOT copy info from Google or third party sources.*** This link is to help you find the business webpage.\nClick OK to agree and continue.') ) { // if the category doesn't translate, then pop an alert that will make a forum post to the thread localStorage.setItem(GLinkWarning, '1'); window.open(buildGLink(newName,addr)); } } } }, // END webSearch definition NewPlaceSubmit: { active: false, bannText: "No PNH match. If place is a chain: ", severity: 0, id: "NewPlaceSubmit", value: "Submit new data", title: "Submit info for a new chain through the linked form", cLog: "Open submit new place form", action: function() { window.open(newPlaceURL); } }, // END NewPlaceSubmit definition ApprovalSubmit: { active: false, bannText: "PNH data exists but is not approved for your region: ", severity: 0, id: "ApprovalSubmit", value: "Request approval", title: "Request region/country approval of this place", cLog: "Open request approval form", action: function() { if (PMUserList.hasOwnProperty(region)) { if (PMUserList[region].approvalActive) { var forumPMInputs = { subject: 'PNH approval for "' + PNHNameTemp + '"', message: 'Please approve "' + PNHNameTemp + '" for the ' + region + ' region. Thanks\n \nPNH order number: ' + PNHOrderNum + '\n \nExample Permalink: ' + placePL + '\n \nPNH Link: ' + USAPNHMasURL, preview: 'Preview', attach_sig: 'on' }; forumPMInputs['address_list[u]['+PMUserList[region].modID+']'] = 'to'; // SER region, sends a PM to t0cableguy = 16941753 WMEPH_openPostDataInNewTab('https://www.waze.com/forum/ucp.php?i=pm&mode=compose', forumPMInputs); } else { window.open(approveRegionURL); } } else { window.open(approveRegionURL); } } }, // END ApprovalSubmit definition placesWiki: { active: true, bannText: "", severity: 0, id: "placesWiki", value: "Places wiki", title: "Open the places wiki page", cLog: "Opened places wiki", action: function() { window.open(placesWikiURL); } }, // END placesWiki definition PlaceErrorForumPost: { active: true, bannText: "", severity: 0, id: "PlaceErrorForumPost", value: "Report script error", title: "Report an error on the forum", cLog: "Post initiated", action: function() { var forumMsgInputs = { subject: 'Re: WMEPH Bug report', message: 'Permalink: ' + placePL + '\nPlace name: ' + item.attributes.name + '\nCountry: ' + addr.country.name + '\nDescribe the error:\n ', addbbcode20: '100', preview: 'Preview', attach_sig: 'on', notify: 'on' }; WMEPH_openPostDataInNewTab(WMEPHurl + '#preview', forumMsgInputs); } } // END PlaceErrorForumPost definition }; // END bannButt definitions //Setting switch for the Places Wiki button if ( $("#WMEPH-HidePlacesWiki" + devVersStr).prop('checked') ) { bannButt.placesWiki.active = false; } // provide Google search link to places if (devUser || betaUser || usrRank > 2) { // enable the link for all places, for R4+ and betas formBannButt('webSearch'); } // Only can select one place at a time in WME, so the loop is superfluous (eg, ix=0 will work), but perhaps we leave it in case we add some sort of looping process like URs. for (var ix = 0; ix < W.selectionManager.selectedItems.length; ix++) { item = W.selectionManager.selectedItems[ix].model; // get GPS lat/long coords from place var itemGPS = OpenLayers.Layer.SphericalMercator.inverseMercator(item.attributes.geometry.bounds.right,item.attributes.geometry.bounds.top); // phlog("Place GPS coords: "+itemGPS); var lockOK = true; // if nothing goes wrong, then place will be locked var customStoreFinder = false; // switch indicating place-specific custom store finder url var customStoreFinderLocal = false; // switch indicating place-specific custom store finder url with localization option (GPS/addr) var customStoreFinderURL = ""; // switch indicating place-specific custom store finder url var customStoreFinderLocalURL = ""; // switch indicating place-specific custom store finder url with localization option (GPS/addr) var categories = item.attributes.categories; newCategories = categories.slice(0); newName = item.attributes.name; newName = toTitleCase(newName); // var nameShort = newName.replace(/[^A-Za-z]/g, ''); // strip non-letters for PNH name searching // var nameNumShort = newName.replace(/[^A-Za-z0-9]/g, ''); // strip non-letters/non-numbers for PNH name searching newAliases = item.attributes.aliases.slice(0); var brand = item.attributes.brand; var newDescripion = item.attributes.description; newURL = item.attributes.url; var newURLSubmit = ""; if (newURL !== null) { newURLSubmit = newURL; } newPhone = item.attributes.phone; newServices = item.attributes.services.slice(0); var addServices = []; var addr = item.getAddress(); var PNHNameRegMatch; var lockLevelDefault; /* // ### Future use, leave in place WMETB_getAddress = function(e) { "use strict"; if ("segment" == e.type) var t = e.model.streets.get(e.attributes.primaryStreetID); else if ("venue" == e.type) var o = e.model.streets.get(e.attributes.streetID); var r, n, a, i, s = e; return t ? (r = e.model.cities.get(t.cityID), n = e.model.states.get(r.stateID), a = e.model.countries.get(r.countryID), i = e.attributes.streetIDs.map(function(e) { s.model.streets.get(e) }), { street: t, city: r, state: n, country: a, altStreets: i }) : o ? (r = e.model.cities.get(o.cityID), n = e.model.states.get(r.stateID), a = e.model.countries.get(r.countryID), { street: o, city: r, state: n, country: a }) : { street: "Error", city: "Error", state: "Error", country: "Error" } } */ // Some user submitted places have no data in the country, state and address fields. Need to have that to make the localization work. if (!addr.state || !addr.country) { alert("Place has no address data. Please set at least a city and rerun the script."); return; // don't run the script } // Country restrictions var countryCode; if (addr.country.name === "United States") { countryCode = "USA"; } else if (addr.country.name === "Canada") { countryCode = "CAN"; } else { alert("At present this script is not supported in this country."); return; } if (countryCode === "USA") { // Setup USA State and Regional vars switch (addr.state.name) { case "Arkansas": state2L = "AR"; region = "SCR"; gFormState = "&entry.124157720=AR"; break; case "Louisiana": state2L = "LA"; region = "SCR"; gFormState = "&entry.124157720=LA"; break; case "Mississippi": state2L = "MS"; region = "SCR"; gFormState = "&entry.124157720=MS"; break; case "Oklahoma": state2L = "OK"; region = "SCR"; gFormState = "&entry.124157720=OK"; break; case "Texas": state2L = "TX"; region = "TX"; gFormState = "&entry.1252443068=TX"; break; case "Alaska": state2L = "AK"; region = "NWR"; gFormState = "&entry.124157720=AK"; break; case "Idaho": state2L = "ID"; region = "NWR"; gFormState = "&entry.124157720=ID"; break; case "Montana": state2L = "MT"; region = "NWR"; gFormState = "&entry.124157720=MT"; break; case "Oregon": state2L = "OR"; region = "NWR"; gFormState = "&entry.124157720=OR"; break; case "Washington": state2L = "WA"; region = "NWR"; gFormState = "&entry.124157720=WA"; break; case "Wyoming": state2L = "WY"; region = "NWR"; gFormState = "&entry.124157720=WY"; break; case "Hawaii": state2L = "HI"; region = "HI"; gFormState = "&entry.124157720=OR"; break; case "Arizona": state2L = "AZ"; region = "SWR"; gFormState = "&entry.124157720=AZ"; break; case "California": state2L = "CA"; region = "SWR"; gFormState = "&entry.124157720=CA"; break; case "Colorado": state2L = "CO"; region = "SWR"; gFormState = "&entry.124157720=CO"; break; case "Nevada": state2L = "NV"; region = "SWR"; gFormState = "&entry.124157720=NV"; break; case "New Mexico": state2L = "NM"; region = "SWR"; gFormState = "&entry.124157720=NM"; break; case "Utah": state2L = "UT"; region = "SWR"; gFormState = "&entry.124157720=UT"; break; case "Iowa": state2L = "IA"; region = "PLN"; gFormState = "&entry.124157720=IA"; break; case "Kansas": state2L = "KS"; region = "PLN"; gFormState = "&entry.124157720=KS"; break; case "Minnesota": state2L = "MN"; region = "PLN"; gFormState = "&entry.124157720=MN"; break; case "Missouri": state2L = "MO"; region = "PLN"; gFormState = "&entry.124157720=MO"; break; case "Nebraska": state2L = "NE"; region = "PLN"; gFormState = "&entry.124157720=NE"; break; case "North Dakota": state2L = "ND"; region = "PLN"; gFormState = "&entry.124157720=ND"; break; case "South Dakota": state2L = "SD"; region = "PLN"; gFormState = "&entry.124157720=SD"; break; case "Illinois": state2L = "IL"; region = "GLR"; gFormState = "&entry.124157720=IL"; break; case "Indiana": state2L = "IN"; region = "GLR"; gFormState = "&entry.124157720=IN"; break; case "Michigan": state2L = "MI"; region = "GLR"; gFormState = "&entry.124157720=MI"; break; case "Ohio": state2L = "OH"; region = "GLR"; gFormState = "&entry.124157720=OH"; break; case "Wisconsin": state2L = "WI"; region = "GLR"; gFormState = "&entry.124157720=WI"; break; case "Kentucky": state2L = "KY"; region = "SAT"; gFormState = "&entry.1025078817=KY+-+Kentucky"; break; case "North Carolina": state2L = "NC"; region = "SAT"; gFormState = "&entry.1025078817=NC+-+North+Carolina"; break; case "South Carolina": state2L = "SC"; region = "SAT"; gFormState = "&entry.1025078817=SC+-+South+Carolina"; break; case "Tennessee": state2L = "TN"; region = "SAT"; gFormState = "&entry.1025078817=TN+-+Tennessee"; break; case "Alabama": state2L = "AL"; region = "SER"; gFormState = "&entry.2010899807=AL+-+Alabama"; break; case "Florida": state2L = "FL"; region = "SER"; gFormState = "&entry.2010899807=FL+-+Florida"; break; case "Georgia": state2L = "GA"; region = "SER"; gFormState = "&entry.2010899807=GA+-+Georgia"; break; case "Connecticut": state2L = "CT"; region = "NEW"; gFormState = "&entry.124157720=CT"; break; case "Maine": state2L = "ME"; region = "NEW"; gFormState = "&entry.124157720=ME"; break; case "Massachusetts": state2L = "MA"; region = "NEW"; gFormState = "&entry.124157720=MA"; break; case "New Hampshire": state2L = "NH"; region = "NEW"; gFormState = "&entry.124157720=NH"; break; case "Rhode Island": state2L = "RI"; region = "NEW"; gFormState = "&entry.124157720=RI"; break; case "Vermont": state2L = "VT"; region = "NEW"; gFormState = "&entry.124157720=VT"; break; case "Delaware": state2L = "DE"; region = "NOR"; gFormState = "&entry.124157720=DE"; break; case "New Jersey": state2L = "NJ"; region = "NOR"; gFormState = "&entry.124157720=NJ"; break; case "New York": state2L = "NY"; region = "NOR"; gFormState = "&entry.124157720=NY"; break; case "Pennsylvania": state2L = "PA"; region = "NOR"; gFormState = "&entry.124157720=PA"; break; case "District of Columbia": state2L = "DC"; region = "MAR"; gFormState = "&entry.124157720=DC"; break; case "Maryland": state2L = "MD"; region = "MAR"; gFormState = "&entry.124157720=MD"; break; case "Virginia": state2L = "VA"; region = "MAR"; gFormState = "&entry.124157720=VA"; break; case "West Virginia": state2L = "WV"; region = "MAR"; gFormState = "&entry.124157720=WV"; break; default: state2L = "Unknown"; region = "Unknown"; } phlog("Place is in region " + region); } // END USA regional/state assigning if (countryCode === "CAN") { // Setup Canadian provinces switch (addr.state.name) { case "Ontario": state2L = "ON"; region = "CAN"; break; case "British Columbia": state2L = "BC"; region = "CAN"; break; case "Alberta": state2L = "AB"; region = "CAN"; break; case "Saskatchewan": state2L = "SK"; region = "CAN"; break; case "Manitoba": state2L = "MB"; region = "CAN"; break; case "Ontario": state2L = "ON"; region = "CAN"; break; case "Quebec": state2L = "QC"; region = "CAN"; break; case "Newfoundland And Labrador": state2L = "NL"; region = "CAN"; break; case "New Brunswick": state2L = "NB"; region = "CAN"; break; case "Prince Edward Island": state2L = "PE"; region = "CAN"; break; case "Nova Scotia": state2L = "NS"; region = "CAN"; break; case "Nunavut": state2L = "NU"; region = "CAN"; break; case "Northwest Territories": state2L = "NT"; region = "CAN"; break; case "Yukon": state2L = "YT"; region = "CAN"; break; default: state2L = "Unknown"; region = "Unknown"; } phlog("Place is in province: " + state2L); } // END Canada assignments // If region or state is unknown, report the error if (state2L === "Unknown" || region === "Unknown") { if (confirm('WMEPH: Localization Error\nClick OK to report this error') ) { // if the location is not found, then pop an alert that will make a forum post to the thread var forumMsgInputs = { subject: 'Re: WMEPH Bug report', message: 'Error report: State name "' + addr.state.name + '" is not found.', addbbcode20: '100', preview: 'Preview', attach_sig: 'on', notify: 'on' }; WMEPH_openPostDataInNewTab(WMEPHurl + '#preview', forumMsgInputs); } return; } // Clear attributes from residential places if (item.attributes.residential) { newName = item.attributes.houseNumber + " " + addr.street.name; if (item.attributes.name !== newName) { // Set the residential place name to the address (to clear any personal info) phlog("Residential Name reset"); W.model.actionManager.add(new UpdateObject(item, {name: newName})); } newCategories = ["RESIDENCE_HOME"]; newDescripion = null; if (item.attributes.description !== null && item.attributes.description !== "") { // remove any description phlog("Residential description cleared"); W.model.actionManager.add(new UpdateObject(item, {description: newDescripion})); } newPhone = null; if (item.attributes.phone !== null && item.attributes.phone !== "") { // remove any phone info phlog("Residential Phone cleared"); W.model.actionManager.add(new UpdateObject(item, {phone: newPhone})); } newURL = null; if (item.attributes.url !== null && item.attributes.url !== "") { // remove any url phlog("Residential URL cleared"); W.model.actionManager.add(new UpdateObject(item, {url: newURL})); } if (item.attributes.services.length > 0) { phlog("Residential URL cleared"); W.model.actionManager.add(new UpdateObject(item, {services: [] })); } } else { // for non-residential places // Place Harmonization var PNHMatchData = harmoList(newName,state2L,region,countryCode,newCategories); // check against the PNH list PNHNameRegMatch = false; if (PNHMatchData[0] !== "NoMatch" && PNHMatchData[0] !== "ApprovalNeeded" ) { // *** Replace place data with PNH data PNHNameRegMatch = true; var PNH_DATA_headers; if (countryCode === "USA") { PNH_DATA_headers = USA_PNH_DATA[0].split("|"); } else if (countryCode === "CAN") { PNH_DATA_headers = CAN_PNH_DATA[0].split("|"); } var ph_name_ix = PNH_DATA_headers.indexOf("ph_name"); var ph_aliases_ix = PNH_DATA_headers.indexOf("ph_aliases"); var ph_category1_ix = PNH_DATA_headers.indexOf("ph_category1"); var ph_category2_ix = PNH_DATA_headers.indexOf("ph_category2"); var ph_description_ix = PNH_DATA_headers.indexOf("ph_description"); var ph_url_ix = PNH_DATA_headers.indexOf("ph_url"); var ph_order_ix = PNH_DATA_headers.indexOf("ph_order"); // var ph_notes_ix = PNH_DATA_headers.indexOf("ph_notes"); var ph_speccase_ix = PNH_DATA_headers.indexOf("ph_speccase"); var ph_sfurl_ix = PNH_DATA_headers.indexOf("ph_sfurl"); var ph_sfurllocal_ix = PNH_DATA_headers.indexOf("ph_sfurllocal"); // var ph_forcecat_ix = PNH_DATA_headers.indexOf("ph_forcecat"); var ph_displaynote_ix = PNH_DATA_headers.indexOf("ph_displaynote"); // Check special cases var specCases = PNHMatchData[ph_speccase_ix]; if (specCases !== "0" && specCases !== "") { specCases = specCases.replace(/,[^A-Za-z0-9}]+/g, ",,"); // tighten up commas if more than one specCase flag. specCases = specCases.split(",,"); // split by comma } var scFlag; var localURLcheck = ''; for (var scix = 0; scix < specCases.length; scix++) { // find any button/message flags in the special case (format: butt_xyzXyz) if ( specCases[scix].match(/^buttOn_/g) !== null ) { scFlag = specCases[scix].match(/^buttOn_(.+)/i)[1]; bannButt[scFlag].active = true; } else if ( specCases[scix].match(/^buttOff_/g) !== null ) { scFlag = specCases[scix].match(/^buttOff_(.+)/i)[1]; bannButt[scFlag].active = false; } else if ( specCases[scix].match(/^messOn_/g) !== null ) { scFlag = specCases[scix].match(/^messOn_(.+)/i)[1]; bannMess[scFlag].active = true; } else if ( specCases[scix].match(/^messOff_/g) !== null ) { scFlag = specCases[scix].match(/^messOff_(.+)/i)[1]; bannMess[scFlag].active = false; } // parseout localURL data if exists if ( specCases[scix].match(/^localURL_/g) !== null ) { localURLcheck = specCases[scix].match(/^localURL_(.+)/i)[1]; } } // Display any notes for the specific place if (PNHMatchData[ph_displaynote_ix] !== '0' && PNHMatchData[ph_displaynote_ix] !== '' ) { if ( containsAny(specCases,['pharmhours']) ) { if ( item.attributes.description.toUpperCase().indexOf('PHARMACY') === -1 || item.attributes.description.toUpperCase().indexOf('HOURS') === -1 ) { sidebarMessage.push(PNHMatchData[ph_displaynote_ix]); severity = Math.max(severity,1); } } else { sidebarMessage.push(PNHMatchData[ph_displaynote_ix]); } } // populate the variables from PNH data newName = PNHMatchData[ph_name_ix]; newAliasesTemp = PNHMatchData[ph_aliases_ix]; newDescripion = PNHMatchData[ph_description_ix]; PNHOrderNum = PNHMatchData[ph_order_ix]; // url parsing var localURLcheckRE; if ( localURLcheck !== '') { if (newURL !== null || newURL !== '') { localURLcheckRE = new RegExp(localURLcheck, "i"); if ( newURL.match(localURLcheckRE) !== null ) { newURL = normalizeURL(newURL); } else { newURL = PNHMatchData[ph_url_ix]; formBannMess('localURL'); } } else { newURL = PNHMatchData[ph_url_ix]; formBannMess('localURL'); } } else { newURL = PNHMatchData[ph_url_ix]; } var priPlaceCat = catTranslate(PNHMatchData[ph_category1_ix]); // translate primary category to WME code var altCategories = PNHMatchData[ph_category2_ix]; if (altCategories !== "0" && altCategories !== "") { altCategories = altCategories.replace(/,[^A-Za-z0-9]*/g, ","); // tighten up commas if more than one secondary category. altCategories = altCategories.split(","); // split by comma for (var catix = 0; catix<altCategories.length; catix++) { // translate altCats into WME cat codes var newAltTemp = catTranslate(altCategories[catix]); if (newAltTemp === "ERROR") { // if no translation, quit the loop phlog('Category ' + altCategories[catix] + 'cannot be translated.'); return; } else { altCategories[catix] = newAltTemp; // replace with translated element } } } if ( ["GAS_STATION"].indexOf(priPlaceCat) > -1 ) { // for primary categories in the vector, don't replace existing sub-categories if ( altCategories !== "0" && altCategories !== "" ) { // if alts exist insertAtIX(newCategories, altCategories, 1); // then insert the alts into the existing category array } } else { // completely replace categories with PNH categories newCategories = [priPlaceCat]; if (altCategories !== "0" && altCategories !== "") { newCategories.push.apply(newCategories,altCategories); } } // *** need to add a section above to allow other permissible categories to remain? (optional) if (newAliasesTemp !== "0" && newAliasesTemp !== "") { // make aliases array newAliasesTemp = newAliasesTemp.replace(/,[^A-za-z0-9]*/g, ","); // tighten up commas if more than one alias. newAliasesTemp = newAliasesTemp.split(","); // split by comma } if (specCases.indexOf('buttOn_addAlias') > -1) { bannButt.addAlias.bannText = "Is there a " + newAliasesTemp[0] + " at this location?"; bannButt.addAlias.title = 'Add ' + newAliasesTemp[0]; } if (specCases.indexOf('buttOn_addCat2') > -1) { bannButt.addAlias.bannText = "Is there a " + catTransWaze2Lang[altCategories[0]] + " at this location?"; bannButt.addAlias.title = 'Add ' + catTransWaze2Lang[altCategories[0]]; } if ( specCases.indexOf('bank') > -1 ) { // PNH banks // #### Needs work // Generic Bank treatment /* var newNameExt = ' '+newName+' '; newNameExt = newNameExt.replace(/[^A-Za-z0-9]/g, ' '); var ixBank = item.attributes.categories.indexOf("BANK_FINANCIAL"); var ixATM = item.attributes.categories.indexOf("ATM"); var ixOffices = item.attributes.categories.indexOf("OFFICES"); // if the name contains ATM in it if ( newNameExt.toUpperCase().indexOf('ATM ') > -1 ) { if ( ixOffices === 0 ) { formBannMess('bankType1'); formBannButt('standaloneATM'); formBannButt('bankBranch'); formBannButt('bankCorporate'); } else if ( ixBank === -1 && ixATM === -1 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } else if ( ixBank === 0 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } else if ( ixATM === 0 && ixBank > 0) { formBannButt('bankBranch'); } // Net result: If the place has ATM cat only and ATM in the name, then it will be green } else { // if no ATM in name: if ( ixOffices === 0 ) { formBannButt('bankBranch'); } else if ( ixBank === -1 && ixATM === -1 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } else if ( ixBank > -1 && ixATM === -1 ) { formBannButt('addATM'); } else if ( ixATM === 0 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } else if ( ixBank > 0 && ixATM > 0 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } // Net result: If the place has Bank category first, then it will be green } */ } else if ( specCases.indexOf('hotel') > 1 ) { // for certain flags, proceed with update } else { // for certain flags, proceed with update if (newName !== item.attributes.name) { phlog("Name updated"); W.model.actionManager.add(new UpdateObject(item, { name: newName })); } if (!containsAll(newAliases,newAliasesTemp) && newAliasesTemp !== "0" && newAliasesTemp !== "" && specCases.indexOf('optionName2') === -1 ) { newAliases = insertAtIX(newAliases,newAliasesTemp,0); phlog("Alt Names updated"); W.model.actionManager.add(new UpdateObject(item, { aliases: newAliases })); } if (!matchSets(item.attributes.categories,newCategories) && specCases.indexOf('optionCat2') === -1 ) { phlog("Categories updated" + " with " + newCategories); W.model.actionManager.add(new UpdateObject(item, { categories: newCategories })); } if (newDescripion !== null && newDescripion !== "0") { if ( item.attributes.description.toUpperCase().indexOf(newDescripion.toUpperCase()) === -1 ) { if ( item.attributes.description !== "" || item.attributes.description !== null ) { formBannMess('checkDescription'); } phlog("Description updated"); newDescripion = newDescripion + '\n' + item.attributes.description; W.model.actionManager.add(new UpdateObject(item, { description: newDescripion })); } } } if ( PNHMatchData[ph_speccase_ix] === 'subFuel' ) { formBannMess('subFuel'); } // *** Add storefinder URL codes } else { // if no match found if (PNHMatchData[0] === "ApprovalNeeded") { PNHNameTemp = PNHMatchData[1]; PNHNameTempWeb = PNHNameTemp.replace(/&/g, "%26"); PNHNameTempWeb = PNHNameTempWeb.replace(/\//g, "%2F"); PNHOrderNum = PNHMatchData[2]; } if (newName !== item.attributes.name) { phlog("Name updated"); W.model.actionManager.add(new UpdateObject(item, { name: newName })); } if (newName !== toTitleCaseStrong(newName)) { formBannButt('STC'); } // #### Needs work // Generic Bank treatment var ixBank = item.attributes.categories.indexOf("BANK_FINANCIAL"); var ixATM = item.attributes.categories.indexOf("ATM"); var ixOffices = item.attributes.categories.indexOf("OFFICES"); var newNameExt = ' '+newName+' '; newNameExt = newNameExt.replace(/[^A-Za-z0-9]/g, ' '); // if the name contains ATM in it if ( newNameExt.toUpperCase().indexOf('ATM ') > -1 ) { if ( ixOffices === 0 ) { formBannMess('bankType1'); formBannButt('standaloneATM'); formBannButt('bankBranch'); formBannButt('bankCorporate'); } else if ( ixBank === -1 && ixATM === -1 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } else if ( ixBank === 0 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } else if ( ixATM === 0 && ixBank > 0) { formBannButt('bankBranch'); } // Net result: If the place has ATM cat only and ATM in the name, then it will be green } else if (ixBank > -1 || ixATM > -1) { // if no ATM in name: if ( ixOffices === 0 ) { formBannButt('bankBranch'); } else if ( ixBank > -1 && ixATM === -1 ) { formBannButt('addATM'); } else if ( ixATM === 0 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } else if ( ixBank > 0 && ixATM > 0 ) { formBannButt('standaloneATM'); formBannButt('bankBranch'); } // Net result: If the place has Bank category first, then it will be green } } // END match/no-match updates // Gas station treatment applies to all if (newCategories[0] === 'GAS_STATION') { // Brand checking if ( !item.attributes.brand || item.attributes.brand === null || item.attributes.brand === "" ) { formBannMess('gasNoBrand'); } else if (item.attributes.brand === 'Unbranded' ) { formBannMess('gasUnbranded'); lockOK = false; } else if ( newName.toUpperCase().indexOf(item.attributes.brand.toUpperCase()) === -1 ) { formBannButt('gasMismatch'); lockOK = false; } // Add convenience store category to station if (newCategories.indexOf("CONVENIENCE_STORE") === -1 && !bannMess.subFuel.active) { if ( $("#WMEPH-ConvenienceStoreToGasStations" + devVersStr).prop('checked') ) { // Automatic if user has the setting checked newCategories = insertAtIX(newCategories, "CONVENIENCE_STORE", 1); // insert the C.S. category W.model.actionManager.add(new UpdateObject(item, { // update categories: newCategories })); } else { // If not checked, then it will be a banner button formBannButt('addConvStore'); } } } // Make submission links var regionFormURL = ''; var newPlaceAddon = ''; var approvalAddon = ''; var approvalMessage = 'Submitted via WMEPH. PNH order number ' + PNHOrderNum; switch (region) { case "NWR": regionFormURL = 'https://docs.google.com/forms/d/1hv5hXBlGr1pTMmo4n3frUx1DovUODbZodfDBwwTc7HE/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "SWR": regionFormURL = 'https://docs.google.com/forms/d/1Qf2N4fSkNzhVuXJwPBJMQBmW0suNuy8W9itCo1qgJL4/viewform'; newPlaceAddon = '?entry.1497446659='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.1497446659='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "HI": regionFormURL = 'https://docs.google.com/forms/d/1Qf2N4fSkNzhVuXJwPBJMQBmW0suNuy8W9itCo1qgJL4/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel3; break; case "PLN": regionFormURL = 'https://docs.google.com/forms/d/1ycXtAppoR5eEydFBwnghhu1hkHq26uabjUu8yAlIQuI/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "SCR": regionFormURL = 'https://docs.google.com/forms/d/1KZzLdlX0HLxED5Bv0wFB-rWccxUp2Mclih5QJIQFKSQ/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "TX": regionFormURL = 'https://docs.google.com/forms/d/1x7VM7ofPOKVnWOaX7d70OWXpnVKf6Mkadn4dgYxx4ic/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "GLR": regionFormURL = 'https://docs.google.com/forms/d/19btj-Qt2-_TCRlcS49fl6AeUT95Wnmu7Um53qzjj9BA/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "SAT": regionFormURL = 'https://docs.google.com/forms/d/1bxgK_20Jix2ahbmUvY1qcY0-RmzUBT6KbE5kjDEObF8/viewform'; newPlaceAddon = '?entry.2063110249='+newName+'&entry.2018912633='+newURLSubmit+'&entry.1924826395='+thisUser.userName+gFormState; approvalAddon = '?entry.2063110249='+PNHNameTempWeb+'&entry.123778794='+approvalMessage+'&entry.1924826395='+thisUser.userName+gFormState; lockLevelDefault = lockLevel3; break; case "SER": regionFormURL = 'https://docs.google.com/forms/d/1jYBcxT3jycrkttK5BxhvPXR240KUHnoFMtkZAXzPg34/viewform'; newPlaceAddon = '?entry.822075961='+newName+'&entry.1422079728='+newURLSubmit+'&entry.1891389966='+thisUser.userName+gFormState; approvalAddon = '?entry.822075961='+PNHNameTempWeb+'&entry.607048307='+approvalMessage+'&entry.1891389966='+thisUser.userName+gFormState; lockLevelDefault = lockLevel3; break; case "TER": regionFormURL = 'https://docs.google.com/forms/d/1v7JhffTfr62aPSOp8qZHA_5ARkBPldWWJwDeDzEioR0/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "NEW": regionFormURL = 'https://docs.google.com/forms/d/1UgFAMdSQuJAySHR0D86frvphp81l7qhEdJXZpyBZU6c/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "NOR": regionFormURL = 'https://docs.google.com/forms/d/1iYq2rd9HRd-RBsKqmbHDIEBGuyWBSyrIHC6QLESfm4c/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "MAR": regionFormURL = 'https://docs.google.com/forms/d/1PhL1iaugbRMc3W-yGdqESoooeOz-TJIbjdLBRScJYOk/viewform'; newPlaceAddon = '?entry.925969794='+newName+'&entry.1970139752='+newURLSubmit+'&entry.1749047694='+thisUser.userName+gFormState; approvalAddon = '?entry.925969794='+PNHNameTempWeb+'&entry.50214576='+approvalMessage+'&entry.1749047694='+thisUser.userName+gFormState; lockLevelDefault = lockLevel2; break; case "CAN": regionFormURL = 'https://docs.google.com/forms/d/13JwXsrWPNmCdfGR5OVr5jnGZw-uNGohwgjim-JYbSws/viewform'; newPlaceAddon = '?entry_839085807='+newName+'&entry_1067461077='+newURLSubmit; approvalAddon = '?entry_839085807='+PNHNameTempWeb+'&entry_1125435193='+approvalMessage; lockLevelDefault = lockLevel2; break; default: regionFormURL = ""; lockLevelDefault = lockLevel2; } switch (state2L) { case "WA": lockLevelDefault = lockLevel3; break; case "CO": lockLevelDefault = lockLevel4; break; case "AZ": lockLevelDefault = lockLevel2; break; case "NV": lockLevelDefault = lockLevel2; break; case "NM": lockLevelDefault = lockLevel2; break; case "UT": lockLevelDefault = lockLevel2; break; case "LA": lockLevelDefault = lockLevel4; break; } newPlaceURL = regionFormURL + newPlaceAddon; approveRegionURL = regionFormURL + approvalAddon; // *** filter weak/parent categories from stronger categories (remove food and drink if restaurant, etc.) // Category/Name-based Services, added to any existing services: if ( containsAny(newCategories,["BANK_FINANCIAL","ATM"]) ) { addServices = ["AIR_CONDITIONING", "PARKING_FOR_CUSTOMERS", "WHEELCHAIR_ACCESSIBLE"]; } if ( containsAny(newCategories,["GAS_STATION"]) ) { addServices = ["RESTROOMS", "AIR_CONDITIONING", "PARKING_FOR_CUSTOMERS", "WHEELCHAIR_ACCESSIBLE"]; } if ( containsAny(newCategories,["SHOPPING_CENTER","PARKING_LOT","GARAGE_AUTOMOTIVE_SHOP"]) ) { addServices = ["PARKING_FOR_CUSTOMERS", "WHEELCHAIR_ACCESSIBLE"]; } if ( containsAny(newCategories,["HOSPITAL_MEDICAL_CARE","DEPARTMENT_STORE","RESTAURANT","CAFE","CAR_DEALERSHIP","FURNITURE_HOME_STORE","SPORTING_GOODS", "CAR_DEALERSHIP","BAR","GYM_FITNESS","CONVENIENCE_STORE","SUPERMARKET_GROCERY","PET_STORE_VETERINARIAN_SERVICES","TOY_STORE","PERSONAL_CARE"]) ) { addServices = ["RESTROOMS", "CREDIT_CARDS", "AIR_CONDITIONING", "PARKING_FOR_CUSTOMERS", "WHEELCHAIR_ACCESSIBLE"]; } if ( containsAny(newCategories,["BOOKSTORE","FASHION_AND_CLOTHING","PERSONAL_CARE","BAKERY","HARDWARE_STORE","DESSERT","FAST_FOOD","PHARMACY","ELECTRONICS", "FLOWERS","MARKET","JEWELRY","MUSIC_STORE"]) ) { addServices = ["CREDIT_CARDS", "AIR_CONDITIONING", "PARKING_FOR_CUSTOMERS", "WHEELCHAIR_ACCESSIBLE"]; } // Push the services onto the existing services array newServices = insertAtIX(newServices,addServices,12); // These categories get their services replaced if ( containsAny(newCategories,["COLLEGE_UNIVERSITY","SCHOOL","RELIGIOUS_CENTER","KINDERGARDEN"]) && (newCategories.indexOf("PARKING_LOT") === -1) ) { newServices = ["RESTROOMS", "AIR_CONDITIONING", "PARKING_FOR_CUSTOMERS", "WHEELCHAIR_ACCESSIBLE"]; } // Place Area check if (item.isPoint() && containsAny(newCategories,["GAS_STATION","PARKING_LOT","AIRPORT","BRIDGE","CEMETERY","EMBASSY_CONSULATE","FIRE_DEPARTMENT", "POLICE_STATION","PRISON_CORRECTIONAL_FACILITY","SCHOOL","SHOPPING_CENTER","RACING_TRACK","THEME_PARK","GOLF_COURSE","PARK"]) ) { formBannMess('areaNotPoint'); lockOK = false; } if (item.isPoint() && newCategories.indexOf("STADIUM_ARENA") > -1) { formBannMess('areaStadium'); lockOK = false; } if (region === "SER" && item.isPoint() && newCategories.indexOf("POST_OFFICE") > -1) { formBannMess('areaPostOfficeSER'); lockOK = false; } if (item.isPoint() && newCategories.indexOf("HOSPITAL_MEDICAL_CARE") > -1) { formBannMess('areaHospital'); lockOK = false; } if (region === "SER" && containsAny(newCategories,["JUNCTION_INTERCHANGE","SEA_LAKE_POOL","RIVER_STREAM","FOREST_GROVE","CANAL","SWAMP_MARSH","ISLAND","BEACH","TRANSPORTATION"]) ) { formBannMess('unmappedSER'); lockOK = false; } if (region === "SER" && item.is2D() && (newCategories.indexOf("CAR_DEALERSHIP") > -1)) { formBannMess('pointCarDealerSER'); lockOK = false; } // Address check if (!item.attributes.name && !item.attributes.residential) { formBannMess('nameMissing'); lockOK = false; } } // END if (not residential) // House number check if (!item.attributes.houseNumber) { formBannMess('hnMissing'); lockOK = false; } else { var hnOK = false; var hnTemp = item.attributes.houseNumber.replace(/[^\d]/g, ''); // Digits only var hnTempDash = item.attributes.houseNumber.replace(/[^\d-]/g, ''); // Digits and dashes only if (hnTemp === item.attributes.houseNumber && hnTemp < 1000000) { // general check that HN is 6 digits or less, & that it is only [0-9] hnOK = true; } if (state2L === "HI") { // Allowance for XX-XXXX HN format for Hawaii if (hnTempDash.match(/^\d{1,2}-\d{1,4}$/g) !== null) { if (hnTempDash === hnTempDash.match(/^\d{1,2}-\d{1,4}$/g)[0]) { hnOK = true; } } } if (!hnOK) { formBannMess('hnNonStandard'); lockOK = false; } } if (!addr.street || addr.street.isEmpty) { formBannMess('streetMissing'); lockOK = false; } if (!addr.city || addr.city.isEmpty) { formBannMess('cityMissing'); lockOK = false; } if (!item.attributes.residential) { // Check for missing hours field if ( $("#WMEPH-AlertNoHours" + devVersStr).prop('checked') ) { // ### Needs correct hours field check below if (item.attributes.openingHours.length === 0) { // if no hours... if (!containsAny(newCategories,["PARKING_LOT","STADIUM_ARENA","CONVENTIONS_EVENT_CENTER","CEMETERY","FIRE_DEPARTMENT", "POLICE_STATION","MILITARY","FACTORY_INDUSTRIAL","ATM","TRANSPORTATION","AIRPORT","FERRY_PIER","SEAPORT_MARINA_HARBOR","SUBWAY_STATION","TRAIN_STATION", "BRIDGE","TUNNEL","TAXI_STATION","JUNCTION_INTERCHANGE","ISLAND","SEA_LAKE_POOL","RIVER_STREAM","FOREST_GROVE","FARM","CANAL","SWAMP_MARSH","DAM"]) ) { formBannMess('noHours'); } } else if (item.attributes.openingHours.length === 1) { // if one set of hours exist... if (item.attributes.openingHours[0].days.length < 7 && item.attributes.openingHours[0].fromHour==='00:00' && (item.attributes.openingHours[0].toHour==='00:00' || item.attributes.openingHours[0].toHour==='23:59' ) ) { formBannMess('mismatch247'); } } } // URL formatting newURL = normalizeURL(newURL); if (newURL !== item.attributes.url && newURL !== "" && newURL !== "0") { // if option is checked and place was harmonized, keep long URL for Harmonized place if domains match4444444 if ($("#WMEPH-PreserveLongURLs" + devVersStr).prop('checked') && PNHNameRegMatch && item.attributes.url !== null) { var tempNormURL = normalizeURL(item.attributes.url); // Normalize existing url tempNormURL = tempNormURL.replace(/\/.*/g, ''); // strip everything after the domain var mTemp = tempNormURL.match(/^www\.(.*)$/i); // strip www. if there (this is just for checking, doesn't strip www from the WME field) if (mTemp) { tempNormURL = mTemp[1]; } var tempNewURL = newURL.replace(/\/.*/g, ''); // strip newURL down to domain mTemp = tempNewURL.match(/^www\.(.*)$/i); // strip www. if there (this is just for checking, doesn't strip www from the WME field) if (mTemp) { tempNewURL = mTemp[1]; } phlog(tempNormURL.indexOf(tempNewURL)); if ( tempNormURL.indexOf(tempNewURL) > -1 ) { // domain match check newURL = normalizeURL(item.attributes.url); // Keep existing, normalized URL formBannMess('longURL'); } } phlog("URL updated"); W.model.actionManager.add(new UpdateObject(item, { url: newURL })); } // Phone formatting var outputFormat = "({0}) {1}-{2}"; if ( containsAny(["SAT","CA","CO"],[region,state2L]) && (/^\d{3}-\d{3}-\d{4}$/.test(item.attributes.phone))) { outputFormat = "{0}-{1}-{2}"; } else if (region === "SER" && !(/^\(\d{3}\) \d{3}-\d{4}$/.test(item.attributes.phone))) { outputFormat = "{0}-{1}-{2}"; } else if (region === "GLR") { outputFormat = "{0}-{1}-{2}"; } else if (countryCode === "CAN") { outputFormat = "+1-{0}-{1}-{2}"; } newPhone = normalizePhone(item.attributes.phone, outputFormat); if (newPhone !== item.attributes.phone) { phlog("Phone updated"); W.model.actionManager.add(new UpdateObject(item, {phone: newPhone})); } } // END if (not residential) // Post Office cat check if (newCategories.indexOf("POST_OFFICE") > -1) { formBannButt('isitUSPS'); } // Add services to existing, only if they are different than what's there if (!item.attributes.residential && !matchSets(item.attributes.services,newServices) && $("#WMEPH-EnableServices" + devVersStr).prop('checked')) { phlog("Services updated"); W.model.actionManager.add(new UpdateObject(item, { services: newServices })); } // Place locking if (lockOK) { var levelToLock = lockLevel3; if (region === "SER") { if (newCategories.indexOf("COLLEGE_UNIVERSITY") > -1 && newCategories.indexOf("PARKING_LOT") > -1) { levelToLock = lockLevel4; } else if ( item.isPoint() && newCategories.indexOf("COLLEGE_UNIVERSITY") > -1 && newCategories.indexOf("HOSPITAL_MEDICAL_CARE") === -1 ) { levelToLock = lockLevel4; } else if ( containsAny(newCategories,["HOSPITAL_MEDICAL_CARE","COLLEGE_UNIVERSITY","STADIUM_ARENA","SCHOOL","AIRPORT"]) ) { levelToLock = lockLevel5; } } if (region === "SAT") { var SATlevel5Categories = ["HOSPITAL_MEDICAL_CARE", "AIRPORT"]; if ( containsAny(newCategories,SATlevel5Categories) ) { levelToLock = lockLevel5; } } if (region === "MAR") { var MARlevel4Categories = [ "HOSPITAL_MEDICAL_CARE", "AIRPORT", "FIRE_DEPARTMENT", "POLICE_STATION" ]; if ( containsAny(newCategories,MARlevel4Categories) ) { levelToLock = lockLevel4; } } if (item.attributes.lockRank < levelToLock) { phlog("Venue locked!"); W.model.actionManager.add(new UpdateObject(item, { lockRank: levelToLock })); } bannMess.placeLocked.active = true; } // User alerts for potentially confusing places var hotelCat = 0; var walmartFlag = 0; if (Math.max(severity, severityButt) < 3) { var nameShortSpace = newName.replace(/[^A-Za-z ]/g, ''); if ( ["HOME","MY HOME","HOUSE","MY HOUSE","CASA","MI CASA"].indexOf( nameShortSpace.toUpperCase() ) > -1 ) { formBannMess('resiTypeName'); } if (newName === "UPS") { sidebarMessageOld.push("If this is a 'UPS Store' location, please change the name to The UPS Store and run the script again."); severity = Math.max(1, severity); } if (newName === "FedEx") { sidebarMessageOld.push("If this is a FedEx Office location, please change the name to FedEx Office and run the script again."); severity = Math.max(1, severity); } if (newName === "IBM Southeast EFCU") { sidebarMessageOld.push("Please add the suffix ' - LOCATION' to the primary name as found on IBMSEFCU's website"); severity = Math.max(2, severity); } if (walmartFlag === 1) { sidebarMessageOld.push("If this Walmart sells groceries, please add the Supermarket category to the place."); severity = Math.max(1, severity); } if (newCategories.indexOf("POST_OFFICE") > -1) { customStoreFinder = "https://tools.usps.com/go/POLocatorAction.action"; customStoreFinder = true; formBannMess('catPostOffice'); } if (item.is2D() && newCategories.indexOf("STADIUM_ARENA") > -1) { formBannMess('generalStadium'); } if (hotelCat === 1 || newCategories.indexOf("HOTEL") > -1) { formBannMess('catHotel'); } } // #### Needs work if (newURL !== null && newURL !== "") { if (customStoreFinder) { sidebarMessageOld.push("(<a href=\"" + customStoreFinder + "\" target=\"_blank\" style=\"color: #FFF\" title=\"Open " + newName + " store finder in a new tab\">Website</a>)"); // *** Storefinder work } else { bannButt.PlaceWebsite.active = true; } } // push together messages from active bannMess objects for (var bannKey in bannMess) { if (bannMess[bannKey].active) { sidebarMessage.push(bannMess[bannKey].message); } } // Make Messaging banners assembleBanner(item); } // (End Place 'loop') } // END harmonizePlaceGo function // Set up banner messages function assembleBanner(item) { var sidebarMessageEXT = sidebarMessage.slice(0); // pull out message array to add on to if necessary severityButt = 0; for (var NHix = 0; NHix < Object.keys(bannButt).length; NHix++ ) { var tempKey = Object.keys(bannButt)[NHix]; var strButt1; var strButt2 = ''; if (bannButt[tempKey].active) { strButt1 = bannButt[tempKey].bannText + '<input class="PHbutton" id="' + bannButt[tempKey].id + '" title="' + bannButt[tempKey].title + '" type="button" value="' + bannButt[tempKey].value + '">'; sidebarMessageEXT.push(strButt1 + strButt2); severityButt = Math.max(bannButt[tempKey].severity, severityButt); } } if (isDevVersion) { sidebarMessageEXT.push('WMEPH Beta'); } displayBanners(sidebarMessageEXT.join("<li>"), Math.max(severity, severityButt) ); setupButtons(item); // if (EXTOption) { // sidebarMessageEXT = sidebarMessageEXT.join("<li>"); // displayBanners(sidebarMessageEXT,severity); // setupButtons(); // } else { // displayBanners(sidebarMessageOld,severity); // setupButtons(); // } } // END assemble Banner function // Button event handlers function setupButtons(item) { var ixButt = 0; var btn = []; for (var NHix = 0; NHix < Object.keys(bannButt).length; NHix++ ) { var tempKey = Object.keys(bannButt)[NHix]; if (bannButt[tempKey].active) { btn[ixButt] = document.getElementById(bannButt[tempKey].id); btn[ixButt].onclick = (function(buttonId, item){ return function() { //bannButt[buttonId].action(item); bannButt[buttonId].action(); assembleBanner(item); }; })(tempKey, item) ixButt++; } } } // END setupButtons function // Display banners with <LI> string and severity function displayBanners(sbm,sev) { $('#WMEPH_logger_warn').empty(); if (sev === 0) { $('<div id="WMEPH_logger_warn">').css("width", "290").css("background-color", "rgb(36, 172, 36)").css("color", "white").css("font-size", "15px").css("font-weight", "bold").css("margin-left", "auto").css("margin-right", "auto").prependTo(".contents"); } if (sev === 1) { $('<div id="WMEPH_logger_warn">').css("width", "290").css("background-color", "rgb(40, 40, 230)").css("color", "white").css("font-size", "15px").css("font-weight", "bold").css("margin-left", "auto").css("margin-right", "auto").prependTo(".contents"); } if (sev === 2) { $('<div id="WMEPH_logger_warn">').css("width", "290").css("background-color", "rgb(217, 173, 42)").css("color", "white").css("font-size", "15px").css("font-weight", "bold").css("margin-left", "auto").css("margin-right", "auto").prependTo(".contents"); } if (sev === 3) { $('<div id="WMEPH_logger_warn">').css("width", "290").css("background-color", "rgb(211, 48, 48)").css("color", "white").css("font-size", "15px").css("font-weight", "bold").css("margin-left", "auto").css("margin-right", "auto").prependTo(".contents"); } WMEPH_DispWarn(sbm); } // END displayBanners funtion // Build a Google search url based on place name and address function buildGLink(searchName,addr) { var searchStreet = ""; var searchCity = ""; searchName = searchName.replace(/&/g, "%26"); searchName = searchName.replace(/[ \/]/g, "%20"); if ("string" === typeof addr.street.name) { searchStreet = addr.street.name + ",%20"; } searchStreet = searchStreet.replace(/ /g, "%20"); if ("string" === typeof addr.city.name) { searchCity = addr.city.name + ",%20"; } searchCity = searchCity.replace(/ /g, "%20"); return "http://www.google.com/search?q=" + searchName + ",%20" + searchStreet + searchCity + addr.state.name; } // END buildGLink function // WME Category translation from Natural language to object language function catTranslate(natCategories) { if (natCategories.toUpperCase().replace(/ AND /g, "").replace(/[^A-Z]/g, "").indexOf('PETSTORE') > -1) { return "PET_STORE_VETERINARIAN_SERVICES"; } for(var keyCat in catTransWaze2Lang){ if ( natCategories.toUpperCase().replace(/ AND /g, "").replace(/[^A-Z]/g, "") === catTransWaze2Lang[keyCat].toUpperCase().replace(/ AND /g, "").replace(/[^A-Z]/g, "")) { return keyCat; } } if (confirm('WMEPH: Category Error!\nClick OK to report this error') ) { // if the category doesn't translate, then pop an alert that will make a forum post to the thread forumMsgInputs = { subject: 'Re: WMEPH Bug report', message: 'Error report: category "' + natCategories + '" is not translatable.', addbbcode20: '100', preview: 'Preview', attach_sig: 'on', notify: 'on' }; WMEPH_openPostDataInNewTab(WMEPHurl + '#preview', forumMsgInputs); } return "ERROR"; } // END catTranslate function // compares two arrays to see if equal, regardless of order function matchSets(array1, array2) { if (array1.length !== array2.length) {return false;} // compare lengths for (var i = 0; i < array1.length; i++) { if (array2.indexOf(array1[i]) === -1) { return false; } } return true; } // function that checks if all elements of target are in array:source function containsAll(source,target) { if (typeof(target) === "string") { target = [target]; } // if a single string, convert to an array for (var ixx = 0; ixx < target.length; ixx++) { if ( source.indexOf(target[ixx]) === -1 ) { return false; } } return true; } // function that checks if any element of target are in source function containsAny(source,target) { if (typeof(source) === "string") { source = [source]; } // if a single string, convert to an array if (typeof(target) === "string") { target = [target]; } // if a single string, convert to an array var result = source.filter(function(tt){ return target.indexOf(tt) > -1; }); return (result.length > 0); } // Function that inserts a string or a string array into another string array at index ix and removes any duplicates function insertAtIX(array1, array2, ix) { // array1 is original string, array2 is the inserted string, at index ix var arrayNew = array1.slice(0); // slice the input array so it doesn't change if (typeof(array2) === "string") { array2 = [array2]; } // if a single string, convert to an array if (typeof(array2) === "object") { // only apply to inserted arrays var arrayTemp = arrayNew.splice(ix); // split and hold the first part arrayNew.push.apply(arrayNew, array2); // add the insert arrayNew.push.apply(arrayNew, arrayTemp); // add the tail end of original } return uniq(arrayNew); // remove any duplicates (so the function can be used to move the position of a string) } // settings tab function add_PlaceHarmonizationSettingsTab() { //Create Settings Tab var phTabHtml = '<li><a href="#sidepanel-ph' + devVersStr + '" data-toggle="tab" id="PlaceHarmonization' + devVersStr + '">WMEPH' + devVersStrSpace + '</a></li>'; $("#user-tabs ul.nav-tabs:first").append(phTabHtml); //Create Settings Tab Content var phContentHtml = '<div class="tab-pane" id="sidepanel-ph' + devVersStr + '"><div id="PlaceHarmonizer' + devVersStr + '"><p>WMEPH' + devVersStrSpace + ' v. ' + WMEPHversion + '</p><hr align="center" width="90%"><p>Settings:</p></div></div>'; $("#user-info div.tab-content:first").append(phContentHtml); //Create Settings Checkboxes and Load Data //example condition: if ( $("#WMEPH-PreserveLongURLs" + devVersStr).prop('checked') ) { } createSettingsCheckbox("WMEPH-HidePlacesWiki" + devVersStr,"Hide 'Places Wiki' button in results banner"); createSettingsCheckbox("WMEPH-AlertNoHours" + devVersStr,"Alert for missing or unlikely hours of operation"); if (devUser || betaUser || usrRank > 2) { createSettingsCheckbox("WMEPH-EnableServices" + devVersStr,"Enable automatic addition of common services"); } if (devUser || betaUser || usrRank > 2) { createSettingsCheckbox("WMEPH-ConvenienceStoreToGasStations" + devVersStr,'Automatically add "Convenience Store" category to gas stations'); } if (devUser) { // Old option for removing www. Keep in case it is needed. // createSettingsCheckbox("WMEPH-StripWWW" + devVersStr,"Strip 'www.' from all URLs"); } if (devUser || betaUser || usrRank > 2) { createSettingsCheckbox("WMEPH-PreserveLongURLs" + devVersStr,"Preserve existing long URLs for harmonized places"); } if (devUser) { // Override script regionality (devs only) var phDevContentHtml = '<hr align="center" width="90%"><p>Dev Only Settings:</p></div></div>'; $("#PlaceHarmonizer" + devVersStr).append(phDevContentHtml); createSettingsCheckbox("WMEPH-RegionOverride" + devVersStr,"Disable Region Specificity"); } var feedbackString = 'Submit script feedback & suggestions'; var placesWikiStr = 'Open the WME Places Wiki page'; var phContentHtml2 = '<div class="tab-pane" id="sidepanel-ph' + devVersStr + '"><div id="PlaceHarmonizer' + devVersStr + '"><hr align="center" width="90%"><p><a href="' + placesWikiURL + '" target="_blank" title="'+placesWikiStr+'">'+placesWikiStr+'</a><p><a href="' + WMEPHurl + '" target="_blank" title="'+feedbackString+'">'+feedbackString+'</a></p></div></div>'; $("#PlaceHarmonizer" + devVersStr).append(phContentHtml2); // $("#user-info div.tab-content:first").append(phContentHtml2); phlog('Ready...!'); } // END Settings Tab // This routine will create a checkbox in the #PlaceHarmonizer tab and will load the setting // settingID: The #id of the checkbox being created. // textDescription: The description of the checkbox that will be use function createSettingsCheckbox(settingID, textDescription) { //Create settings checkbox and append HTML to settings tab var phTempHTML = '<input type="checkbox" id="' + settingID + '">'+ textDescription +'</input><br>'; $("#PlaceHarmonizer" + devVersStr).append(phTempHTML); //phlog(settingID + ' checkbox created'); //Associate click event of new checkbox to call saveSettingToLocalStorage with proper ID $("#" + settingID).click(function() {saveSettingToLocalStorage(settingID);}); //phlog('Callback Set'); //Load Setting for Local Storage, if it doesn't exist set it to NOT checked. //If previously set to 1, then trigger "click" event. if (!localStorage.getItem(settingID)) { //phlog(settingID + ' not found.'); } else if (localStorage.getItem(settingID) === "1") { //phlog(settingID + ' = 1 so invoking click'); $("#" + settingID).trigger('click'); } //phlog('Setting Checked'); } // Save settings prefs function saveSettingToLocalStorage(settingID) { if ($("#" + settingID).prop('checked')) { // phlog(settingID + ' to 1'); localStorage.setItem(settingID, '1'); } else { // phlog(settingID + ' to 0'); localStorage.setItem(settingID, '0'); } } // Focus away from the current cursor focus, to set text box changes function blurAll() { var tmp = document.createElement("input"); document.body.appendChild(tmp); tmp.focus(); document.body.removeChild(tmp); } // Sets up a div for submitting forms function WMEPH_initialiseFL() { var wmephlinks = WMEPH_getId("WMEPH-forumlink"); var mapFooter = WMEPH_getElementsByClassName("WazeControlPermalink"); if (mapFooter.length === 0) { phlog("Error, can't find permalink container"); setTimeout(WMEPH_initialiseFL, 1000); return; } var WMEPH_divPerma = mapFooter[0]; var WMEPH_aPerma = null; for (var i = 0; i < WMEPH_divPerma.children.length; i++) { if (WMEPH_divPerma.children[i].className === 'icon-link') { WMEPH_aPerma = WMEPH_divPerma.children[i]; break; } if (WMEPH_divPerma.children[i].className === 'fa fa-link') { WMEPH_aPerma = WMEPH_divPerma.children[i]; break; } } //WMEPH_aPerma.style.display = 'none'; if (wmephlinks !== null) {return WMEPH_aPerma.href;} var WMEPH_nodeWMEPH = document.createElement('div'); WMEPH_nodeWMEPH.id = 'WMEPH-forumlink'; WMEPH_nodeWMEPH.style.display = 'inline'; WMEPH_divPerma.appendChild(WMEPH_nodeWMEPH); return WMEPH_aPerma.href; } // END WMEPH_initialiseFL function function WMEPH_getElementsByClassName(classname, node) { // Get element by class name if (!node) {node = document.getElementsByTagName("body")[0];} var a = []; var re = new RegExp('\\b' + classname + '\\b'); var els = node.getElementsByTagName("*"); for (var i = 0, j = els.length; i < j; i++) { if (re.test(els[i].className)) { a.push(els[i]); } } return a; } // END WMEPH_getElementsByClassName function function WMEPH_getId(node) { // getID function return document.getElementById(node); } // Make a populated post on a forum thread function WMEPH_openPostDataInNewTab(url, data) { var form = document.createElement('form'); form.target = '_blank'; form.action = url; form.method = 'post'; form.style.display = 'none'; for (var k in data) { if (data.hasOwnProperty(k)) { var input; if (k === 'message') { input = document.createElement('textarea'); } else if (k === 'username') { input = document.createElement('username_list'); } else { input = document.createElement('input'); } input.name = k; input.value = data[k]; input.type = 'hidden'; form.appendChild(input); } } WMEPH_getId('WMEPH-forumlink').appendChild(form); form.submit(); WMEPH_getId('WMEPH-forumlink').removeChild(form); return true; } // END WMEPH_openPostDataInNewTab function // Function that checks current place against the Harmonization Data. Returns place data or "NoMatch" function harmoList(itemName,state2L,region3L,country,itemCats) { var PNH_DATA_headers; var ixendPNH_NAMES; if (country === 'USA') { PNH_DATA_headers = USA_PNH_DATA[0].split("|"); // pull the data header names ixendPNH_NAMES = USA_PNH_NAMES.length; } else if (country === 'CAN') { PNH_DATA_headers = CAN_PNH_DATA[0].split("|"); // pull the data header names ixendPNH_NAMES = CAN_PNH_NAMES.length; } else { alert("No PNH data exists for this country."); return; } var ph_name_ix = PNH_DATA_headers.indexOf("ph_name"); var ph_category1_ix = PNH_DATA_headers.indexOf("ph_category1"); var ph_forcecat_ix = PNH_DATA_headers.indexOf("ph_forcecat"); // Force the category match var ph_region_ix = PNH_DATA_headers.indexOf("ph_region"); // Find the index for regions var ph_order_ix = PNH_DATA_headers.indexOf("ph_order"); var nameComps; // filled with search names to compare against place name var PNHPriCat; // Primary category of PNH data var PNHForceCat; // Primary category of PNH data var approvedRegions; // filled with the regions that are approved for the place, when match is found var matchPNHData = []; // array of matched data var currMatchData; var currMatchNum = 0; // index for multiple matches, currently returns on first match var PNHOrderNum; var PNHNameTemp; var PNHNameMatch = false; // tracks match status var PNHMatchProceed; // tracks match status itemName = itemName.toUpperCase(); // UpperCase the current place name (The Holly And Ivy Pub #23 --> THE HOLLY AND IVY PUB #23 ) itemName = itemName.replace(/ AND /g, ''); // Clear the word " AND " from the name (THE HOLLY AND IVY PUB #23 --> THE HOLLYIVY PUB #23 ) itemName = itemName.replace(/^THE /g, ''); // Clear the word "THE " from the start of the name ( THE HOLLYIVY PUB #23 -- > HOLLYIVY PUB #23 ) itemName = itemName.replace(/[^A-Z0-9]/g, ''); // Clear all non-letter and non-number characters ( HOLLYIVY PUB #23 -- > HOLLYIVYPUB23 ) var itemNameNoNum = itemName.replace(/[^A-Z]/g, ''); // Clear non-letter characters for alternate match ( HOLLYIVYPUB23 --> HOLLYIVYPUB ) // Search performance stats var t0; var t1; if (devUser) { t0 = performance.now(); // Speed check start } // for each place on the PNH list (skipping headers at index 0) // phlog(ixendPNH_NAMES); for (var phnum=1; phnum<ixendPNH_NAMES; phnum++) { PNHMatchProceed = false; if (country === 'USA') { nameComps = USA_PNH_NAMES[phnum].split("|"); // splits all possible search names for the current PNH entry } else if (country === 'CAN') { nameComps = CAN_PNH_NAMES[phnum].split("|"); // splits all possible search names for the current PNH entry } if ( nameComps.indexOf(itemName) > -1 || nameComps.indexOf(itemNameNoNum) > -1 ) { // Compare WME place name to PNH search name list if (country === 'USA') { matchPNHData[currMatchNum] = USA_PNH_DATA[phnum]; // Pull the data line from the PNH data table. (**Set in array for future multimatch features) } else if (country === 'CAN') { matchPNHData[currMatchNum] = CAN_PNH_DATA[phnum]; // Pull the data line from the PNH data table. (**Set in array for future multimatch features) } currMatchData = matchPNHData[currMatchNum].split("|"); // Split the PNH place data into string array PNHPriCat = catTranslate(currMatchData[ph_category1_ix]); PNHForceCat = currMatchData[ph_forcecat_ix]; if (itemCats[0] === "GAS_STATION") { // Gas stations only harmonized if the WME place category is already gas station (prevents Costco Gas becoming Costco Store) PNHForceCat = "1"; } if ( PNHForceCat === "1" && itemCats.indexOf(PNHPriCat) === 0 ) { // Name and primary category match PNHMatchProceed = true; } else if ( PNHForceCat === "2" && itemCats.indexOf(PNHPriCat) > -1 ) { // Name and any category match PNHMatchProceed = true; } else if ( PNHForceCat === "0" || PNHForceCat === "") { // Name only match PNHMatchProceed = true; } if (PNHMatchProceed) { PNHNameMatch = true; // PNH match found (once true, stays true) PNHNameTemp = currMatchData[ph_name_ix]; // temp name for approval return PNHOrderNum = currMatchData[ph_order_ix]; // temp order number for approval return approvedRegions = currMatchData[ph_region_ix].replace(/ /g, ''); // remove spaces from region field approvedRegions = approvedRegions.toUpperCase().split(","); // upper case the approved regions and split by commas if (approvedRegions.indexOf(state2L) > -1 || approvedRegions.indexOf(region3L) > -1 || // if the WME-selected item matches the region approvedRegions.indexOf(country) > -1 || // OR if the country code is in the data then it is approved for all regions therein $("#WMEPH-RegionOverride" + devVersStr).prop('checked')) { // OR if region override is selected if (devUser) { t1 = performance.now(); // log search time phlog("Found place in " + (t1 - t0) + " milliseconds."); } bannMess.placeMatched.active = true; return currMatchData; // Return the PNH data string array to the main script } currMatchNum++; // *** Multiple matches for future work } } } // END loop through PNH places // If NO (name & region) match was found: if (PNHNameMatch) { // if a name match was found but not for region, prod the user to get it approved bannButt.ApprovalSubmit.active = true; phlog("PNH data exists but not approved for this area."); if (devUser) { t1 = performance.now(); // log search time phlog("Searched all PNH entries in " + (t1 - t0) + " milliseconds."); } return ["ApprovalNeeded", PNHNameTemp, PNHOrderNum]; } else { // if no match was found, suggest adding the place to the sheet if it's a chain bannButt.NewPlaceSubmit.active = true; phlog("Place not found in the " + country + " PNH list."); if (devUser) { t1 = performance.now(); // log search time phlog("Searched all PNH entries in " + (t1 - t0) + " milliseconds."); } return ["NoMatch"]; } } // END harmoList function // KB Shortcut object var shortcut = { 'all_shortcuts': {}, //All the shortcuts are stored in this array 'add': function(shortcut_combination, callback, opt) { //Provide a set of default options var default_options = { 'type': 'keydown', 'propagate': false, 'disable_in_input': false, 'target': document, 'keycode': false }; if (!opt) {opt = default_options;} else { for (var dfo in default_options) { if (typeof opt[dfo] === 'undefined') {opt[dfo] = default_options[dfo];} } } var ele = opt.target; if (typeof opt.target === 'string') {ele = document.getElementById(opt.target);} // var ths = this; shortcut_combination = shortcut_combination.toLowerCase(); //The function to be called at keypress var func = function(e) { e = e || window.event; if (opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields var element; if (e.target) {element = e.target;} else if (e.srcElement) {element = e.srcElement;} if (element.nodeType === 3) {element = element.parentNode;} if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {return;} } //Find Which key is pressed var code; if (e.keyCode) {code = e.keyCode;} else if (e.which) {code = e.which;} var character = String.fromCharCode(code).toLowerCase(); if (code === 188) {character = ",";} //If the user presses , when the type is onkeydown if (code === 190) {character = ".";} //If the user presses , when the type is onkeydown var keys = shortcut_combination.split("+"); //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked var kp = 0; //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken var shift_nums = { "`": "~","1": "!","2": "@","3": "#","4": "$","5": "%","6": "^","7": "&", "8": "*","9": "(","0": ")","-": "_","=": "+",";": ":","'": "\"",",": "<",".": ">","/": "?","\\": "|" }; //Special Keys - and their codes var special_keys = { 'esc': 27,'escape': 27,'tab': 9,'space': 32,'return': 13,'enter': 13,'backspace': 8,'scrolllock': 145, 'scroll_lock': 145,'scroll': 145,'capslock': 20,'caps_lock': 20,'caps': 20,'numlock': 144,'num_lock': 144,'num': 144, 'pause': 19,'break': 19,'insert': 45,'home': 36,'delete': 46,'end': 35,'pageup': 33,'page_up': 33,'pu': 33,'pagedown': 34, 'page_down': 34,'pd': 34,'left': 37,'up': 38,'right': 39,'down': 40,'f1': 112,'f2': 113,'f3': 114,'f4': 115,'f5': 116, 'f6': 117,'f7': 118,'f8': 119,'f9': 120,'f10': 121,'f11': 122,'f12': 123 }; var modifiers = { shift: { wanted: false, pressed: false }, ctrl: { wanted: false, pressed: false }, alt: { wanted: false, pressed: false }, meta: { wanted: false, pressed: false } //Meta is Mac specific }; if (e.ctrlKey) {modifiers.ctrl.pressed = true;} if (e.shiftKey) {modifiers.shift.pressed = true;} if (e.altKey) {modifiers.alt.pressed = true;} if (e.metaKey) {modifiers.meta.pressed = true;} var k; for (var i = 0; k = keys[i], i < keys.length; i++) { //Modifiers if (k === 'ctrl' || k === 'control') { kp++; modifiers.ctrl.wanted = true; } else if (k === 'shift') { kp++; modifiers.shift.wanted = true; } else if (k === 'alt') { kp++; modifiers.alt.wanted = true; } else if (k === 'meta') { kp++; modifiers.meta.wanted = true; } else if (k.length > 1) { //If it is a special key if (special_keys[k] === code) {kp++;} } else if (opt['keycode']) { if (opt['keycode'] === code) {kp++;} } else { //The special keys did not match if (character === k) {kp++;} else { if (shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase character = shift_nums[character]; if (character === k) {kp++;} } } } } if (kp === keys.length && modifiers.ctrl.pressed === modifiers.ctrl.wanted && modifiers.shift.pressed === modifiers.shift.wanted && modifiers.alt.pressed === modifiers.alt.wanted && modifiers.meta.pressed === modifiers.meta.wanted) { callback(e); if (!opt['propagate']) { //Stop the event //e.cancelBubble is supported by IE - this will kill the bubbling process. e.cancelBubble = true; e.returnValue = false; //e.stopPropagation works in Firefox. if (e.stopPropagation) { e.stopPropagation(); e.preventDefault(); } return false; } } }; this.all_shortcuts[shortcut_combination] = { 'callback': func, 'target': ele, 'event': opt['type'] }; //Attach the function with the event if (ele.addEventListener) {ele.addEventListener(opt['type'], func, false);} else if (ele.attachEvent) {ele.attachEvent('on' + opt['type'], func);} else {ele['on' + opt['type']] = func;} }, //Remove the shortcut - just specify the shortcut and I will remove the binding 'remove': function(shortcut_combination) { shortcut_combination = shortcut_combination.toLowerCase(); var binding = this.all_shortcuts[shortcut_combination]; delete(this.all_shortcuts[shortcut_combination]); if (!binding) {return;} var type = binding['event']; var ele = binding['target']; var callback = binding['callback']; if (ele.detachEvent) {ele.detachEvent('on' + type, callback);} else if (ele.removeEventListener) {ele.removeEventListener(type, callback, false);} else {ele['on' + type] = false;} } }; // END Shortcut function } // END runPH Function // This function runs at script load, and builds the search name dataset to compare the WME selected place name to. function makeNameCheckList(PNH_DATA) { // Builds the list of search names to match to the WME place name var PNH_NAMES = []; var PNH_DATA_headers = PNH_DATA[0].split("|"); // split the data headers out var ph_name_ix = PNH_DATA_headers.indexOf("ph_name"); // find the indices needed for the function var ph_category1_ix = PNH_DATA_headers.indexOf("ph_category1"); var ph_searchnamebase_ix = PNH_DATA_headers.indexOf("ph_searchnamebase"); var ph_searchnamemid_ix = PNH_DATA_headers.indexOf("ph_searchnamemid"); var ph_searchnameend_ix = PNH_DATA_headers.indexOf("ph_searchnameend"); var ph_disable_ix = PNH_DATA_headers.indexOf("ph_disable"); var t0 = performance.now(); // Speed check start var newNameListLength; // static list length for (var pnhix=0; pnhix<PNH_DATA.length; pnhix++) { // loop through all PNH places var pnhEntryTemp = PNH_DATA[pnhix].split("|"); // split the current PNH data line if (pnhEntryTemp[ph_disable_ix] !== "1") { var newNameList = pnhEntryTemp[ph_name_ix].toUpperCase(); // pull out the primary PNH name & upper case it newNameList = newNameList.replace(/ AND /g, ''); // Clear the word "AND" from the name newNameList = newNameList.replace(/^THE /g, ''); // Clear the word "THE" from the start of the name newNameList = [newNameList.replace(/[^A-Z0-9]/g, '')]; // Clear non-letter and non-number characters, store in array // The following code sets up alternate search names as outlined in the PNH dataset. // Formula, with P = primary; B1, B2 = base terms; M1, M2 = mid terms; E1, E2 = end terms // Search list will build: P, B, PM, BM, PE, BE, PME, BME. // Multiple M terms are applied singly and in pairs (B1M2M1E2). Multiple B and E terms are applied singly (e.g B1B2M1 not used). // Any doubles like B1E2=P are purged at the end to reduce search times. if (pnhEntryTemp[ph_searchnamebase_ix] !== "0") { // If base terms exist, otherwise only the primary name is matched var pnhSearchNameBase = pnhEntryTemp[ph_searchnamebase_ix].replace(/[^A-Za-z0-9,]/g, ''); // clear non-letter and non-number characters (keep commas) pnhSearchNameBase = pnhSearchNameBase.toUpperCase().split(","); // upper case and split the base-name list newNameList.push.apply(newNameList,pnhSearchNameBase); // add them to the search list if (pnhEntryTemp[ph_searchnamemid_ix] !== "0") { // if middle search term add-ons exist var pnhSearchNameMid = pnhEntryTemp[ph_searchnamemid_ix].replace(/[^A-Za-z0-9,]/g, ''); // clear non-letter and non-number characters pnhSearchNameMid = pnhSearchNameMid.toUpperCase().split(","); // upper case and split if (pnhSearchNameMid.length > 1) { // if there are more than one mid terms, it adds a permutation of the first 2 pnhSearchNameMid.push.apply( pnhSearchNameMid,[ pnhSearchNameMid[0]+pnhSearchNameMid[1],pnhSearchNameMid[1]+pnhSearchNameMid[0] ] ); } newNameListLength = newNameList.length; for (var extix=1; extix<newNameListLength; extix++) { // extend the list by adding Mid terms onto the SearchNameBase names for (var altix=0; altix<pnhSearchNameMid.length; altix++) { newNameList.push(newNameList[extix]+pnhSearchNameMid[altix] ); } } } if (pnhEntryTemp[ph_searchnameend_ix] !== "0") { // if end search term add-ons exist var pnhSearchNameEnd = pnhEntryTemp[ph_searchnameend_ix].replace(/[^A-Za-z0-9,]/g, ''); // clear non-letter and non-number characters pnhSearchNameEnd = pnhSearchNameEnd.toUpperCase().split(","); // upper case and split newNameListLength = newNameList.length; for (var exetix=1; exetix<newNameListLength; exetix++) { // extend the list by adding End terms onto all the SearchNameBase & Base+Mid names for (var aletix=0; aletix<pnhSearchNameEnd.length; aletix++) { newNameList.push(newNameList[exetix]+pnhSearchNameEnd[aletix] ); } } } } // Next, add extensions to the search names based on the WME place category newNameListLength = newNameList.length; var catix; if (pnhEntryTemp[ph_category1_ix].toUpperCase().replace(/[^A-Za-z0-9]/g, '') === "HOTEL") { for ( catix=0; catix<newNameListLength; catix++) { // extend the list by adding Hotel to all items newNameList.push(newNameList[catix]+"HOTEL"); } } else if (pnhEntryTemp[ph_category1_ix].toUpperCase().replace(/[^A-Za-z0-9]/g, '') === "BANKFINANCIAL") { for ( catix=0; catix<newNameListLength; catix++) { // extend the list by adding Bank and ATM to all items newNameList.push(newNameList[catix]+"BANK"); newNameList.push(newNameList[catix]+"ATM"); } } else if (pnhEntryTemp[ph_category1_ix].toUpperCase().replace(/[^A-Za-z0-9]/g, '') === "SUPERMARKETGROCERY") { for ( catix=0; catix<newNameListLength; catix++) { // extend the list by adding Supermarket to all items newNameList.push(newNameList[catix]+"SUPERMARKET"); } } else if (pnhEntryTemp[ph_category1_ix].toUpperCase().replace(/[^A-Za-z0-9]/g, '') === "GYMFITNESS") { for ( catix=0; catix<newNameListLength; catix++) { // extend the list by adding Gym to all items newNameList.push(newNameList[catix]+"GYM"); } } else if (pnhEntryTemp[ph_category1_ix].toUpperCase().replace(/[^A-Za-z0-9]/g, '') === "GASSTATION") { for ( catix=0; catix<newNameListLength; catix++) { // extend the list by adding Gas terms to all items newNameList.push(newNameList[catix]+"GAS"); newNameList.push(newNameList[catix]+"GASOLINE"); newNameList.push(newNameList[catix]+"FUEL"); newNameList.push(newNameList[catix]+"GASSTATION"); } } else if (pnhEntryTemp[ph_category1_ix].toUpperCase().replace(/[^A-Za-z0-9]/g, '') === "CARRENTAL") { for ( catix=0; catix<newNameListLength; catix++) { // extend the list by adding Car Rental terms to all items newNameList.push(newNameList[catix]+"RENTAL"); newNameList.push(newNameList[catix]+"RENTACAR"); newNameList.push(newNameList[catix]+"CARRENTAL"); newNameList.push(newNameList[catix]+"RENTALCAR"); } } newNameList = uniq(newNameList); // remove any duplicate search names newNameList = newNameList.join("|"); // join the list with | PNH_NAMES.push(newNameList); // push the list to the master search list } else { // END if valid line PNH_NAMES.push('00'); } } var t1 = performance.now(); // log search time phlog("Built search list of " + PNH_DATA.length + " PNH places in " + (t1 - t0) + " milliseconds."); return PNH_NAMES; } // END makeNameCheckList // Removes duplicate strings from string array function uniq(a) { "use strict"; var seen = {}; return a.filter(function(item) { return seen.hasOwnProperty(item) ? false : (seen[item] = true); }); } // END uniq function function phlog(m) { console.log('WMEPH' + devVersStrDash + ': ' + m); } placeHarmonizer_bootstrap(); })(); // var DLscript = document.createElement("script"); // DLscript.textContent = runPH.toString() + ' \n' + 'runPH();'; // DLscript.setAttribute("type", "application/javascript"); // document.body.appendChild(DLscript);// JavaScript Document