// ==UserScript== // @author DanielOnDiordna // @name Highlight Resonator Owners // @category Highlighter // @version 1.0.0.20231019.224200 // @updateURL https://raw.githubusercontent.com/IITC-CE/Community-plugins/master/dist/DanielOnDiordna/highlight-resonator-owners.meta.js // @downloadURL https://raw.githubusercontent.com/IITC-CE/Community-plugins/master/dist/DanielOnDiordna/highlight-resonator-owners.user.js // @description [danielondiordna-1.0.0.20231019.224200] Highlight portals with resonators by owner // @id highlight-resonator-owners@DanielOnDiordna // @namespace https://softspot.nl/ingress/ // @match https://intel.ingress.com/* // @grant none // ==/UserScript== function wrapper(plugin_info) { // ensure plugin framework is there, even if iitc is not yet loaded if(typeof window.plugin !== 'function') window.plugin = function() {}; // use own namespace for plugin window.plugin.highlightresonatorowners = function() {}; var self = window.plugin.highlightresonatorowners; self.id = 'highlightresonatorowners'; self.title = 'Highlight Resonator Owners'; self.version = '1.0.0.20231019.224200'; self.author = 'DanielOnDiordna'; self.changelog = ` Changelog: version 1.0.0.20231019.224200 - version upgrade due to a change in the wrapper, added changelog - reversed the changelog order to show last changes at the top - reformatted javascript code ES6 backticks - replaced all var with let declarations - added machina faction version 0.0.5.20210724.002500 - prevent double plugin setup on hook iitcLoaded version 0.0.5.20210421.190200 - minor fix for IITC CE where runHooks iitcLoaded is executed before addHook is defined in this plugin version 0.0.5.20210328.002900 - disabled interaction on resonator text labels version 0.0.4.20210123.174900 - integrated Spectrum Colorpicker 1.8.1 plugin code, no need anymore for the separate plugin - updated plugin wrapper and userscript header formatting to match IITC-CE coding version 0.0.3.20200908.231600 - added short names option - added limit to scan portals by level and faction - added a statusbar with total and loading indicator - changed the orange highlighter function from all to any resonator by level - fixed some issues version 0.0.2.20200906.224900 - color picker for owner name/level (colorpicker add-on or drawtools plugin required) - highlight portal if missing resonator by level for a selected player - option to show/hide owner names - option to show/hide resonator levels version 0.0.1.20200906.182700 - first version `; self.namespace = 'window.plugin.' + self.id + '.'; self.pluginname = 'plugin-' + self.id; self.localstoragesettings = self.pluginname + '-settings'; self.highlightername = 'Resonator Owners'; self.portallabelslayer = {}; self.portallabelslayergroup = null; self.settings = {}; self.settings.refreshinterval = 5; // hours self.settings.resonatorowner = ''; self.settings.shownames = true; self.settings.shortnames = false; self.settings.showlevels = true; self.settings.resonatorownercolor = '#ff00f7'; self.settings.resolevel = [0,false,false,false,false,false,false,false,true]; // 0, level 1-8 self.settings.portallevel = [0,true,true,true,true,true,true,true,true]; // 0, level 1-8 self.settings.scanenl = true; self.settings.scanres = true; self.settings.scanmac = true; self.restartrunning = false; self.nextrunning = false; self.portals = {}; self.resonatorowners = {}; self.latlngindex = {}; self.updatelist = {}; self.requestlist = {}; self.requestid = ''; // need to initialise the 'spectrum' color picker self.colorpickeroptions = { flat: false, showInput: true, showButtons: true, showPalette: true, showSelectionPalette: true, allowEmpty: false, palette: [ ['#004000','#008000','#00C000'], ['#00FF00','#80FF80','#C0FFC0'], ['#000040','#000080','#0000C0'], ['#4040FF','#8080FF','#C0C0FF'], ['#6A3400','#964A00','#C05F00'], ['#E27000','#FF8309','#FFC287'], ['#a24ac3','#514ac3','#4aa8c3','#51c34a'], ['#c1c34a','#c38a4a','#c34a4a','#c34a6f'], ['#000000','#666666','#bbbbbb','#ffffff'] ]}; self.restoresettings = function() { if (typeof localStorage[self.localstoragesettings] === 'string' && localStorage[self.localstoragesettings] !== '') { try { var settings = JSON.parse(localStorage[self.localstoragesettings]); if (typeof settings === 'object' && settings instanceof Object && !(settings instanceof Array)) { for (const i in settings) { if (typeof settings[i] === typeof self.settings[i]) self.settings[i] = settings[i]; } } } catch(e) { return false; } } }; self.storesettings = function() { localStorage[self.localstoragesettings] = JSON.stringify(self.settings); }; self.highlight_portal = function(portal) { let guid = portal.options.guid; var noresonatorsforowner = (self.settings.resonatorowner != '' && self.resonatorowners[self.settings.resonatorowner] !== undefined); var noresonatorslevelforowner = false; if (noresonatorsforowner && self.portals[guid]) { var ownerlevels = {}; for (let cnt = 0; cnt < self.portals[guid].resonators.length; cnt++) { if (self.portals[guid].resonators[cnt].owner === self.settings.resonatorowner) { noresonatorsforowner = false; ownerlevels[self.portals[guid].resonators[cnt].level]++; } } //console.log(self.title,ownerlevels); for (let level = 1; level < self.settings.portallevel.length; level++) { if (self.settings.resolevel[level] && ownerlevels[level] == undefined) { noresonatorslevelforowner = true; } } } //console.log(self.title + ' highlight_portal',guid,noresonatorsforowner,noresonatorslevelforowner,portal.options.team,portal.options.level); let params = {opacity: 1.0, fillOpacity: 0.5}; if (portal.options.team === window.TEAM_NONE || !self.settings.scanenl && portal.options.team == window.TEAM_ENL || !self.settings.scanres && portal.options.team == window.TEAM_RES || !self.settings.scanmac && portal.options.team == window.TEAM_MAC || !self.settings.portallevel[portal.options.level]) { params.fillColor = window.COLORS[portal.options.team]; params.fillOpacity = 0.5; } else if (self.requestlist[guid]) { params.fillColor = window.COLORS[portal.options.team]; params.fillOpacity = 0.3; } else if (!self.portals[guid]) { params.fillColor = window.COLORS[portal.options.team]; params.fillOpacity = 0.1; } else if (noresonatorsforowner) { params.fillColor = 'red'; params.fillOpacity = 1; } else if (noresonatorslevelforowner) { params.fillColor = 'orange'; params.fillOpacity = 1; } else { params.fillColor = window.COLORS[portal.options.team]; params.fillOpacity = 0.5; } portal.setStyle(params); }; self.highlightportals = { highlight: function(data) { if (!data || !(data instanceof Object)) return; if (data.guid && window.portals[data.guid]) data.portal = window.portals[data.guid]; if (!data || !data.portal || !data.portal.options || !data.portal.options.guid) return; if (self.highlighteractive()) { self.highlight_portal(data.portal); } }, setSelected: function(active) { if (!active) { //hide window.map.removeLayer(self.portallabelslayergroup); self.stop(); } else { self.updateHighlighter(); window.map.addLayer(self.portallabelslayergroup); $(`.${self.pluginname}-portallabel`).css('pointer-events','none'); self.restart(); } } }; self.highlighteractive = function() { return (window._current_highlighter === self.highlightername); }; self.updateHighlighter = function() { if (!self.highlighteractive()) return; for (let guid in self.portals) { if (window.portals[guid]) { self.highlight_portal(window.portals[guid]); } } }; self.addLabel = function(guid,latLng) { self.removeLabel(guid); if (!self.highlighteractive()) return; if (window.getMapZoomTileParameters(window.getDataZoomForMapZoom(window.map.getZoom())).level !== 0) return; let portal = window.portals[guid]; if (window.teamStringToId(portal.options.data.team) == window.TEAM_NONE) return; // skip unclaimed if (!self.settings.scanenl && window.teamStringToId(portal.options.data.team) == window.TEAM_ENL) return; if (!self.settings.scanres && window.teamStringToId(portal.options.data.team) == window.TEAM_RES) return; if (!self.settings.scanmac && window.teamStringToId(portal.options.data.team) == window.TEAM_MAC) return; if (!self.settings.portallevel[portal.options.data.level]) return; // octant=slot: 0=E, 1=NE, 2=N, 3=NW, 4=W, 5=SW, 6=S, SE=7 // resos in the display should be ordered like this: // N NE Since the view is displayed in rows, they // NW E need to be ordered like this: N NE NW E W SE SW S // W SE i.e. 2 1 3 0 4 7 5 6 // SW S // note: as of 2014-05-23 update, this is not true for portals with empty slots! // only if all 8 resonators are deployed, we know which is in which slot var resonatortext = ['','','','','','','','']; if (self.settings.showlevels || self.settings.shownames) resonatortext = ['?','?','?','?','?','?','?','?']; var resonatorstyle = ['','','','','','','','']; if (self.portals[guid]) { if (self.portals[guid].resonators.length == 8) { // fully deployed - we can make assumptions about deployment slots $.each([2, 1, 3, 0, 4, 7, 5, 6], function(cnt, slot) { if (self.settings.resonatorowner && self.portals[guid].resonators[slot].owner === self.settings.resonatorowner) resonatorstyle[cnt] = ' color:' + self.settings.resonatorownercolor + ';'; var level = self.portals[guid].resonators[slot].level; var owner = self.portals[guid].resonators[slot].owner; if (self.settings.shortnames) owner = owner.substring(0,3); if ((cnt+1) % 2 == 0) { resonatortext[cnt] = (self.settings.showlevels?level:'') + ' ' + (self.settings.shownames?owner:''); // even, right side } else { resonatortext[cnt] = (self.settings.shownames?owner:'') + ' ' + (self.settings.showlevels?level:''); // odd, left side } }); } else { // partially deployed portal - we can no longer find out which resonator is in which slot for (let cnt = 0; cnt < 8; cnt++) { if (cnt < self.portals[guid].resonators.length) { var level = self.portals[guid].resonators[cnt].level; var owner = self.portals[guid].resonators[cnt].owner; if (self.settings.resonatorowner && owner === self.settings.resonatorowner) resonatorstyle[cnt] = ' color:' + self.settings.resonatorownercolor + ';'; if (self.settings.shortnames) owner = owner.substring(0,3); if ((cnt+1) % 2 == 0) { resonatortext[cnt] = (self.settings.showlevels?level:'') + ' ' + (self.settings.shownames?owner:''); // even, right side } else { resonatortext[cnt] = (self.settings.shownames?owner:'') + ' ' + (self.settings.showlevels?level:''); // odd, left side } } else { resonatortext[cnt] = (self.settings.showlevels || self.settings.shownames?'-':''); } } } } let labelwidth = 300; let labelheight = 40; let portaltext = `
${resonatortext[0]}
${resonatortext[1]}
${resonatortext[2]}
${resonatortext[3]}
${resonatortext[4]}
${resonatortext[5]}
${resonatortext[6]}
${resonatortext[7]}
`; self.portallabelslayer[guid] = window.L.marker(latLng, { icon: window.L.divIcon({ className: `${self.pluginname}-portallabel`, iconAnchor: [labelwidth/2 + 3,labelheight/2], iconSize: [labelwidth,labelheight], html: portaltext }), guid: guid }); self.portallabelslayer[guid].addTo(self.portallabelslayergroup); $(`.${self.pluginname}-portallabel`).css('pointer-events','none'); }; self.removeLabel = function(guid) { let existinglayer = self.portallabelslayer[guid]; if (existinglayer) { self.portallabelslayergroup.removeLayer(existinglayer); delete self.portallabelslayer[guid]; } }; self.updatePortalLabel = function(data) { let portal = window.portals[data.guid]; if (!portal) return; let latLng = portal.getLatLng(); self.addLabel(data.guid, latLng); }; self.updatePortalLabels = function() { $.each(self.portals, function(guid) { self.updatePortalLabel({guid: guid}); }); }; self.portalonvisiblelayer = function(portal) { if (portal.options.data.team === 'E' && !window.overlayStatus['Enlightened']) return false; if (portal.options.data.team === 'R' && !window.overlayStatus['Resistance']) return false; if (portal.options.data.team === 'M' && !(window.overlayStatus['__MACHINA__'] || window.overlayStatus['U̶͚̓̍N̴̖̈K̠͔̍͑̂͜N̞̥͋̀̉Ȯ̶̹͕̀W̶̢͚͑̚͝Ṉ̨̟̒̅'])) return false; let unclaimedlayername = 'Unclaimed Portals'; let found = window.setupMap.toString().match(/i === 0 \? \'([^']+)\'/); if (found) unclaimedlayername = found[1] + ' Portals'; if (portal.options.data.team === 'N' && !window.overlayStatus[unclaimedlayername]) return false; if (!window.overlayStatus['Level ' + portal.options.data.level + ' Portals']) return false; return true; }; self.storedetails = function(data) { if (!(data instanceof Object)) return; if (data.success === false) return data.guid; // retry // check if returned data is from requested portal delete(self.requestlist[data.guid]); delete(self.updatelist[data.guid]); let portal = {}; portal.team = data.details.team; portal.level = (portal.team === window.TEAM_NONE?0:data.details.level); // set level to 0 if portal is unclaimed portal.owner = data.details.owner; portal.title = data.details.title; portal.resonators = data.details.resonators; portal.checked = new Date().getTime(); // store unique resonatorowners let totalresonatorowners = Object.keys(self.resonatorowners).length; for (let cnt = 0; cnt < portal.resonators.length; cnt++) { self.resonatorowners[portal.resonators[cnt].owner] = window.teamStringToId(portal.team); } if (Object.keys(self.resonatorowners).length != totalresonatorowners) { self.updateplayerselectlist(); } self.portals[data.guid] = portal; let latlngid = data.details.latE6 + ',' + data.details.lngE6; self.latlngindex[latlngid] = data.guid; //console.log(self.title + " storedetails 4",data); // if (!portal || !(portal instanceof Object)) return; // if (portal.options && portal.options.guid && window.portals[portal.options.guid]) portal = window.portals[portal.options.guid]; // if (!portal || !portal.options || !portal.options.guid) return; self.highlight_portal(window.portals[data.guid]); //{ portal : { options : window.portals[guid].options } }); //console.log(self.title + " storedetails 5"); self.updatePortalLabel(data); //console.log(self.title + " storedetails 6"); return data.guid; }; self.stop = function() { //console.log(self.title + " STOP"); // clear list window.clearTimeout(self.timerid); self.requestlist = {}; self.requestid = ''; self.nextrunning = false; self.updatestatusbar(); }; self.restart = function() { if (!self.highlighteractive()) return; if (window.mapDataRequest.status.short !== 'done' || window.getMapZoomTileParameters(window.getDataZoomForMapZoom(window.map.getZoom())).level !== 0) { // zoom to all portals self.stop(); return; } if (self.restartrunning) return; self.restartrunning = true; //console.log(self.title + " RESTART"); // create list of portals to request: let visiblebounds = window.map.getBounds(); self.requestlist = {}; let currenttime = new Date().getTime(); for (let guid in window.portals) { let portal = window.portals[guid]; // portal must be within visible bounds // and portal must on a visible layer if (visiblebounds.contains(portal.getLatLng()) && self.portalonvisiblelayer(portal)) { // portal must be new // or changed faction // or mentioned in comms (on updatelist) // or older then refreshinterval (hours) if (self.portals[guid] === undefined || self.portals[guid]['team'] !== portal.options.data.team || self.updatelist[guid] || (currenttime - self.portals[guid]['checked']) > self.settings.refreshinterval * 60*60*1000) { if (!self.settings.scanenl && window.teamStringToId(portal.options.data.team) == window.TEAM_ENL) continue; if (!self.settings.scanres && window.teamStringToId(portal.options.data.team) == window.TEAM_RES) continue; if (!self.settings.scanmac && window.teamStringToId(portal.options.data.team) == window.TEAM_MAC) continue; if (!self.settings.portallevel[portal.options.data.level]) continue; self.requestlist[guid] = portal; //break; // REMOVE THIS LINE WHEN READY } } } self.next(); self.restartrunning = false; }; self.next = function() { if (!self.highlighteractive() || window.mapDataRequest.status.short !== 'done') { self.stop(); return; } if (self.nextrunning) return; self.nextrunning = true; //console.log(self.title + " NEXT"); // request next portal, if any if (Object.keys(self.requestlist).length === 0) { self.stop(); self.nextrunning = false; return; } // next key self.updatestatusbar(); let guid = Object.keys(self.requestlist)[0]; self.requestid = guid; let portal = window.portals[guid]; if (!portal || !portal.options) { // skip portal if not in range delete(self.requestlist[guid]); self.timerid = window.setTimeout(function() { self.nextrunning = false; self.next(); }); return; } self.timerid = window.setTimeout(function() { self.nextrunning = false; let portal = self.requestlist[self.requestid]; if (!portal) { self.next(); return; } window.portalDetail.request(self.requestid); }); }; self.publicchat = function(data) { if (!self.highlighteractive()) return; //console.log(self.title + " PUBLICCHAT"); let forceupdate = false; $.each(data.result, function(ind, json) { let plrname,latE6,lngE6,title,skipmessage = false; let portalstatuschanged = false; $.each(json[2].plext.markup, function(ind, markup) { switch(markup[0]) { case 'TEXT': // only register certain messages if (markup[1].plain.indexOf(' captured ') >= 0 || markup[1].plain.indexOf(' destroyed ') >= 0 || markup[1].plain.indexOf(' deployed ') >= 0) { portalstatuschanged = true; } else { skipmessage = true; return; } break; case 'PLAYER': plrname = markup[1].plain; break; case 'PORTAL': latE6 = markup[1].latE6; lngE6 = markup[1].lngE6; title = title ? title : markup[1].name; //address = address ? address : markup[1].address; break; } }); if (!latE6 || !lngE6 || skipmessage) return; let latlngid = latE6+','+lngE6; let time = json[1]; let guid = self.latlngindex[latlngid]; if (self.portals[guid]) { // portal is stored, check if details need to be updated let checked = self.portals[guid]['checked']; if (portalstatuschanged && time > checked) { self.updatelist[guid] = time; forceupdate = true; } } }); if (forceupdate) window.setTimeout(self.restart); }; self.onPortalSelected = function() { //console.log(self.title + " onPortalSelected"); }; self.showPortalSelected = function() { //console.log(self.title + " showPortalSelected"); }; self.portalAdded = function(data) { data.portal.on('add', function() { self.addLabel(this.options.guid,this.getLatLng()); }); data.portal.on('remove', function() { self.removeLabel(this.options.guid); }); }; self.zoomend = function() { if (!self.highlighteractive) return; if (window.getMapZoomTileParameters(window.getDataZoomForMapZoom(window.map.getZoom())).level !== 0) { // zoom to all portals map.removeLayer(self.portallabelslayergroup); } else { map.addLayer(self.portallabelslayergroup); $('.' + self.pluginname + '-portallabel').css('pointer-events','none'); } }; self.updatestatusbar = function() { $('#' + self.id + '_statusbar').replaceWith(self.statusbarhtml()); }; self.statusbarhtml = function() { let portalstotal = Object.keys(self.portals).length; let requestlisttotal = Object.keys(self.requestlist).length; return 'Portals loaded: ' + portalstotal + (requestlisttotal > 0?' Loading: ' + requestlisttotal:'') + ''; }; self.updateplayerselectlist = function() { let newlist = self.playerselectlist($('#' + self.id + '_selectplayer option:selected').val()); if (newlist !== $('#' + self.id + '_selectplayer').html()) $('#' + self.id + '_selectplayer').replaceWith(newlist); }; self.playerselectlist = function(selectedname) { //console.log(self.title + ' updateplayerselectlist ' + selectedname); let players = Object.keys(self.resonatorowners).sort(function(a,b) { return (a.toLowerCase() < b.toLowerCase()?-1:(a.toLowerCase() > b.toLowerCase()?1:0)); }); if (!selectedname) selectedname = self.settings.resonatorowner; let player_team = window.teamStringToId(window.PLAYER.team); let selectednamefound = false; let list = []; list.push(''); for (let index in players) { let plrname = players[index]; // style="color: ' + self.getPlayerColor(plrname) + '" list.push(''); if (plrname === selectedname) selectednamefound = true; } return ''; }; self.menu = function() { let lvl = 0; let reso_lvlcheckboxes = ''; let portal_lvlcheckboxes = ''; let reso_countselectors = ''; for (lvl = 1; lvl <= 8; lvl++) { portal_lvlcheckboxes += ''; reso_lvlcheckboxes += ''; reso_countselectors += ''; } let container = document.createElement('div'); container.innerHTML = ` Auto load resonator details
Limit to these portal levels:
${portal_lvlcheckboxes}
Limit to portals of these factions:


${self.statusbarhtml()}

For this selected player:
${self.playerselectlist(self.settings.resonatorowner)}
Text color
Require resonators of this level:
${reso_lvlcheckboxes}
Require this number of resonators:
${reso_countselectors}
Highlight RED: 0 resonators
Highlight ORANGE: missing required resonators

Settings:
()

version ${self.version} by ${self.author} `; let scanenlcheckbox = container.querySelector(`.${self.id}-scanenl`); scanenlcheckbox.checked = self.settings.scanenl; scanenlcheckbox.addEventListener('click',function(e) { self.settings.scanenl = this.checked; self.storesettings(); self.updateHighlighter(); self.updatePortalLabels(); self.restart(); }); let scanrescheckbox = container.querySelector(`.${self.id}-scanres`); scanrescheckbox.checked = self.settings.scanres; scanrescheckbox.addEventListener('click',function(e) { self.settings.scanres = this.checked; self.storesettings(); self.updateHighlighter(); self.updatePortalLabels(); self.restart(); }); let scanmaccheckbox = container.querySelector(`.${self.id}-scanmac`); scanmaccheckbox.checked = self.settings.scanmac; scanmaccheckbox.addEventListener('click',function(e) { self.settings.scanmac = this.checked; self.storesettings(); self.updateHighlighter(); self.updatePortalLabels(); self.restart(); }); let shownamescheckbox = container.querySelector(`.${self.id}-shownames`); shownamescheckbox.checked = self.settings.shownames; shownamescheckbox.addEventListener('click',function(e) { self.settings.shownames = this.checked; self.storesettings(); self.updatePortalLabels(); }); let shortnamescheckbox = container.querySelector(`.${self.id}-shortnames`); shortnamescheckbox.checked = self.settings.shortnames; shortnamescheckbox.addEventListener('click',function(e) { self.settings.shortnames = this.checked; self.storesettings(); self.updatePortalLabels(); }); let showlevelscheckbox = container.querySelector(`.${self.id}-showlevels`); showlevelscheckbox.checked = self.settings.showlevels; showlevelscheckbox.addEventListener('click',function(e) { self.settings.showlevels = this.checked; self.storesettings(); self.updatePortalLabels(); }); window.dialog({ html: container, id: self.pluginname + '-dialog', dialogClass: 'ui-dialog-' + self.pluginname, title: self.title }); $('#resonatorownercolor').spectrum($.extend(true, self.colorpickeroptions, { change: function(color) { self.settings.resonatorownercolor = color.toHexString(); self.storesettings(); self.updatePortalLabels(); }, color: self.settings.resonatorownercolor, })); }; self.setupColorpickerSpectrum = function() { // source: https://github.com/bgrins/spectrum // minified with https://www.minifier.org/ // Spectrum Colorpicker v1.8.1 // https://github.com/bgrins/spectrum // Author: Brian Grinstead // License: MIT (function(factory){"use strict";if(typeof define==='function'&&define.amd){define(['jquery'],factory)}else if(typeof exports=="object"&&typeof module=="object"){module.exports=factory(require('jquery'))}else{factory(jQuery)}})(function($,undefined){"use strict";var defaultOpts={beforeShow:noop,move:noop,change:noop,show:noop,hide:noop,color:!1,flat:!1,showInput:!1,allowEmpty:!1,showButtons:!0,clickoutFiresChange:!0,showInitial:!1,showPalette:!1,showPaletteOnly:!1,hideAfterPaletteSelect:!1,togglePaletteOnly:!1,showSelectionPalette:!0,localStorageKey:!1,appendTo:"body",maxSelectionSize:7,cancelText:"cancel",chooseText:"choose",togglePaletteMoreText:"more",togglePaletteLessText:"less",clearText:"Clear Color Selection",noColorSelectedText:"No Color Selected",preferredFormat:!1,className:"",containerClassName:"",replacerClassName:"",showAlpha:!1,theme:"sp-light",palette:[["#ffffff","#000000","#ff0000","#ff8000","#ffff00","#008000","#0000ff","#4b0082","#9400d3"]],selectionPalette:[],disabled:!1,offset:null},spectrums=[],IE=!!/msie/i.exec(window.navigator.userAgent),rgbaSupport=(function(){function contains(str,substr){return!!~(''+str).indexOf(substr)} var elem=document.createElement('div');var style=elem.style;style.cssText='background-color:rgba(0,0,0,.5)';return contains(style.backgroundColor,'rgba')||contains(style.backgroundColor,'hsla')})(),replaceInput=["
","
","
","
"].join(''),markup=(function(){var gradientFix="";if(IE){for(var i=1;i<=6;i++){gradientFix+="
"}} return["
","
","
","
","","
","
","
","
","
","
","
","
","
","
","
","
","
","
","
","
","
",gradientFix,"
","
","
","
","
","","
","
","
","","","
","
","
"].join("")})();function paletteTemplate(p,color,className,opts){var html=[];for(var i=0;i')}else{var cls='sp-clear-display';html.push($('
').append($('').attr('title',opts.noColorSelectedText)).html())}} return"
"+html.join('')+"
"} function hideAll(){for(var i=0;iMath.abs(dragY-oldDragY);shiftMovementDirection=furtherFromX?"x":"y"} var setSaturation=!shiftMovementDirection||shiftMovementDirection==="x";var setValue=!shiftMovementDirection||shiftMovementDirection==="y";if(setSaturation){currentSaturation=parseFloat(dragX/dragWidth)} if(setValue){currentValue=parseFloat((dragHeight-dragY)/dragHeight)} isEmpty=!1;if(!opts.showAlpha){currentAlpha=1} move()},dragStart,dragStop);if(!!initialColor){set(initialColor);updateUI();currentPreferredFormat=opts.preferredFormat||tinycolor(initialColor).format;addColorToSelectionPalette(initialColor)}else{updateUI()} if(flat){show()} function paletteElementClick(e){if(e.data&&e.data.ignore){set($(e.target).closest(".sp-thumb-el").data("color"));move()}else{set($(e.target).closest(".sp-thumb-el").data("color"));move();if(opts.hideAfterPaletteSelect){updateOriginalInput(!0);hide()}else{updateOriginalInput()}} return!1} var paletteEvent=IE?"mousedown.spectrum":"click.spectrum touchstart.spectrum";paletteContainer.on(paletteEvent,".sp-thumb-el",paletteElementClick);initialColorContainer.on(paletteEvent,".sp-thumb-el:nth-child(1)",{ignore:!0},paletteElementClick)} function updateSelectionPaletteFromStorage(){if(localStorageKey&&window.localStorage){try{var oldPalette=window.localStorage[localStorageKey].split(",#");if(oldPalette.length>1){delete window.localStorage[localStorageKey];$.each(oldPalette,function(i,c){addColorToSelectionPalette(c)})}}catch(e){} try{selectionPalette=window.localStorage[localStorageKey].split(";")}catch(e){}}} function addColorToSelectionPalette(color){if(showSelectionPalette){var rgb=tinycolor(color).toRgbString();if(!paletteLookup[rgb]&&$.inArray(rgb,selectionPalette)===-1){selectionPalette.push(rgb);while(selectionPalette.length>maxSelectionSize){selectionPalette.shift()}} if(localStorageKey&&window.localStorage){try{window.localStorage[localStorageKey]=selectionPalette.join(";")}catch(e){}}}} function getUniqueSelectionPalette(){var unique=[];if(opts.showPalette){for(var i=0;iviewWidth&&viewWidth>dpWidth)?Math.abs(offsetLeft+dpWidth-viewWidth):0);offsetTop-=Math.min(offsetTop,((offsetTop+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(dpHeight+inputHeight-extraY):extraY));return{top:offsetTop,bottom:offset.bottom,left:offsetLeft,right:offset.right,width:offset.width,height:offset.height}} function noop(){} function stopPropagation(e){e.stopPropagation()} function bind(func,obj){var slice=Array.prototype.slice;var args=slice.call(arguments,2);return function(){return func.apply(obj,args.concat(slice.call(arguments)))}} function draggable(element,onmove,onstart,onstop){onmove=onmove||function(){};onstart=onstart||function(){};onstop=onstop||function(){};var doc=document;var dragging=!1;var offset={};var maxHeight=0;var maxWidth=0;var hasTouch=('ontouchstart' in window);var duringDragEvents={};duringDragEvents.selectstart=prevent;duringDragEvents.dragstart=prevent;duringDragEvents["touchmove mousemove"]=move;duringDragEvents["touchend mouseup"]=stop;function prevent(e){if(e.stopPropagation){e.stopPropagation()} if(e.preventDefault){e.preventDefault()} e.returnValue=!1} function move(e){if(dragging){if(IE&&doc.documentMode<9&&!e.button){return stop()} var t0=e.originalEvent&&e.originalEvent.touches&&e.originalEvent.touches[0];var pageX=t0&&t0.pageX||e.pageX;var pageY=t0&&t0.pageY||e.pageY;var dragX=Math.max(0,Math.min(pageX-offset.left,maxWidth));var dragY=Math.max(0,Math.min(pageY-offset.top,maxHeight));if(hasTouch){prevent(e)} onmove.apply(element,[dragX,dragY,e])}} function start(e){var rightclick=(e.which)?(e.which==3):(e.button==2);if(!rightclick&&!dragging){if(onstart.apply(element,arguments)!==!1){dragging=!0;maxHeight=$(element).height();maxWidth=$(element).width();offset=$(element).offset();$(doc).on(duringDragEvents);$(doc.body).addClass("sp-dragging");move(e);prevent(e)}}} function stop(){if(dragging){$(doc).off(duringDragEvents);$(doc.body).removeClass("sp-dragging");setTimeout(function(){onstop.apply(element,arguments)},0)} dragging=!1} $(element).on("touchstart mousedown",start)} function throttle(func,wait,debounce){var timeout;return function(){var context=this,args=arguments;var throttler=function(){timeout=null;func.apply(context,args)};if(debounce)clearTimeout(timeout);if(debounce||!timeout)timeout=setTimeout(throttler,wait)}} function inputTypeColorSupport(){return $.fn.spectrum.inputTypeColorSupport()} var dataID="spectrum.id";$.fn.spectrum=function(opts,extra){if(typeof opts=="string"){var returnValue=this;var args=Array.prototype.slice.call(arguments,1);this.each(function(){var spect=spectrums[$(this).data(dataID)];if(spect){var method=spect[opts];if(!method){throw new Error("Spectrum: no such method: '"+opts+"'")} if(opts=="get"){returnValue=spect.get()}else if(opts=="container"){returnValue=spect.container}else if(opts=="option"){returnValue=spect.option.apply(spect,args)}else if(opts=="destroy"){spect.destroy();$(this).removeData(dataID)}else{method.apply(spect,args)}}});return returnValue} return this.spectrum("destroy").each(function(){var options=$.extend({},$(this).data(),opts);var spect=spectrum(this,options);$(this).data(dataID,spect.id)})};$.fn.spectrum.load=!0;$.fn.spectrum.loadOpts={};$.fn.spectrum.draggable=draggable;$.fn.spectrum.defaults=defaultOpts;$.fn.spectrum.inputTypeColorSupport=function inputTypeColorSupport(){if(typeof inputTypeColorSupport._cachedResult==="undefined"){var colorInput=$("")[0];inputTypeColorSupport._cachedResult=colorInput.type==="color"&&colorInput.value!==""} return inputTypeColorSupport._cachedResult};$.spectrum={};$.spectrum.localization={};$.spectrum.palettes={};$.fn.spectrum.processNativeColorInputs=function(){var colorInputs=$("input[type=color]");if(colorInputs.length&&!inputTypeColorSupport()){colorInputs.spectrum({preferredFormat:"hex6"})}};(function(){var trimLeft=/^[\s,#]+/,trimRight=/\s+$/,tinyCounter=0,math=Math,mathRound=math.round,mathMin=math.min,mathMax=math.max,mathRandom=math.random;var tinycolor=function(color,opts){color=(color)?color:'';opts=opts||{};if(color instanceof tinycolor){return color} if(!(this instanceof tinycolor)){return new tinycolor(color,opts)} var rgb=inputToRGB(color);this._originalInput=color;this._r=rgb.r;this._g=rgb.g;this._b=rgb.b;this._a=rgb.a;this._roundA=mathRound(1000*this._a)/1000;this._format=opts.format||rgb.format;this._gradientType=opts.gradientType;if(this._r<1){this._r=mathRound(this._r)} if(this._g<1){this._g=mathRound(this._g)} if(this._b<1){this._b=mathRound(this._b)} this._ok=rgb.ok;this._tc_id=tinyCounter++};tinycolor.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var rgb=this.toRgb();return(rgb.r*299+rgb.g*587+rgb.b*114)/1000},setAlpha:function(value){this._a=boundAlpha(value);this._roundA=mathRound(1000*this._a)/1000;return this},toHsv:function(){var hsv=rgbToHsv(this._r,this._g,this._b);return{h:hsv.h*360,s:hsv.s,v:hsv.v,a:this._a}},toHsvString:function(){var hsv=rgbToHsv(this._r,this._g,this._b);var h=mathRound(hsv.h*360),s=mathRound(hsv.s*100),v=mathRound(hsv.v*100);return(this._a==1)?"hsv("+h+", "+s+"%, "+v+"%)":"hsva("+h+", "+s+"%, "+v+"%, "+this._roundA+")"},toHsl:function(){var hsl=rgbToHsl(this._r,this._g,this._b);return{h:hsl.h*360,s:hsl.s,l:hsl.l,a:this._a}},toHslString:function(){var hsl=rgbToHsl(this._r,this._g,this._b);var h=mathRound(hsl.h*360),s=mathRound(hsl.s*100),l=mathRound(hsl.l*100);return(this._a==1)?"hsl("+h+", "+s+"%, "+l+"%)":"hsla("+h+", "+s+"%, "+l+"%, "+this._roundA+")"},toHex:function(allow3Char){return rgbToHex(this._r,this._g,this._b,allow3Char)},toHexString:function(allow3Char){return'#'+this.toHex(allow3Char)},toHex8:function(){return rgbaToHex(this._r,this._g,this._b,this._a)},toHex8String:function(){return'#'+this.toHex8()},toRgb:function(){return{r:mathRound(this._r),g:mathRound(this._g),b:mathRound(this._b),a:this._a}},toRgbString:function(){return(this._a==1)?"rgb("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+")":"rgba("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:mathRound(bound01(this._r,255)*100)+"%",g:mathRound(bound01(this._g,255)*100)+"%",b:mathRound(bound01(this._b,255)*100)+"%",a:this._a}},toPercentageRgbString:function(){return(this._a==1)?"rgb("+mathRound(bound01(this._r,255)*100)+"%, "+mathRound(bound01(this._g,255)*100)+"%, "+mathRound(bound01(this._b,255)*100)+"%)":"rgba("+mathRound(bound01(this._r,255)*100)+"%, "+mathRound(bound01(this._g,255)*100)+"%, "+mathRound(bound01(this._b,255)*100)+"%, "+this._roundA+")"},toName:function(){if(this._a===0){return"transparent"} if(this._a<1){return!1} return hexNames[rgbToHex(this._r,this._g,this._b,!0)]||!1},toFilter:function(secondColor){var hex8String='#'+rgbaToHex(this._r,this._g,this._b,this._a);var secondHex8String=hex8String;var gradientType=this._gradientType?"GradientType = 1, ":"";if(secondColor){var s=tinycolor(secondColor);secondHex8String=s.toHex8String()} return"progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"},toString:function(format){var formatSet=!!format;format=format||this._format;var formattedString=!1;var hasAlpha=this._a<1&&this._a>=0;var needsAlphaFormat=!formatSet&&hasAlpha&&(format==="hex"||format==="hex6"||format==="hex3"||format==="name");if(needsAlphaFormat){if(format==="name"&&this._a===0){return this.toName()} return this.toRgbString()} if(format==="rgb"){formattedString=this.toRgbString()} if(format==="prgb"){formattedString=this.toPercentageRgbString()} if(format==="hex"||format==="hex6"){formattedString=this.toHexString()} if(format==="hex3"){formattedString=this.toHexString(!0)} if(format==="hex8"){formattedString=this.toHex8String()} if(format==="name"){formattedString=this.toName()} if(format==="hsl"){formattedString=this.toHslString()} if(format==="hsv"){formattedString=this.toHsvString()} return formattedString||this.toHexString()},_applyModification:function(fn,args){var color=fn.apply(null,[this].concat([].slice.call(args)));this._r=color._r;this._g=color._g;this._b=color._b;this.setAlpha(color._a);return this},lighten:function(){return this._applyModification(lighten,arguments)},brighten:function(){return this._applyModification(brighten,arguments)},darken:function(){return this._applyModification(darken,arguments)},desaturate:function(){return this._applyModification(desaturate,arguments)},saturate:function(){return this._applyModification(saturate,arguments)},greyscale:function(){return this._applyModification(greyscale,arguments)},spin:function(){return this._applyModification(spin,arguments)},_applyCombination:function(fn,args){return fn.apply(null,[this].concat([].slice.call(args)))},analogous:function(){return this._applyCombination(analogous,arguments)},complement:function(){return this._applyCombination(complement,arguments)},monochromatic:function(){return this._applyCombination(monochromatic,arguments)},splitcomplement:function(){return this._applyCombination(splitcomplement,arguments)},triad:function(){return this._applyCombination(triad,arguments)},tetrad:function(){return this._applyCombination(tetrad,arguments)}};tinycolor.fromRatio=function(color,opts){if(typeof color=="object"){var newColor={};for(var i in color){if(color.hasOwnProperty(i)){if(i==="a"){newColor[i]=color[i]}else{newColor[i]=convertToPercentage(color[i])}}} color=newColor} return tinycolor(color,opts)};function inputToRGB(color){var rgb={r:0,g:0,b:0};var a=1;var ok=!1;var format=!1;if(typeof color=="string"){color=stringInputToObject(color)} if(typeof color=="object"){if(color.hasOwnProperty("r")&&color.hasOwnProperty("g")&&color.hasOwnProperty("b")){rgb=rgbToRgb(color.r,color.g,color.b);ok=!0;format=String(color.r).substr(-1)==="%"?"prgb":"rgb"}else if(color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("v")){color.s=convertToPercentage(color.s);color.v=convertToPercentage(color.v);rgb=hsvToRgb(color.h,color.s,color.v);ok=!0;format="hsv"}else if(color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("l")){color.s=convertToPercentage(color.s);color.l=convertToPercentage(color.l);rgb=hslToRgb(color.h,color.s,color.l);ok=!0;format="hsl"} if(color.hasOwnProperty("a")){a=color.a}} a=boundAlpha(a);return{ok:ok,format:color.format||format,r:mathMin(255,mathMax(rgb.r,0)),g:mathMin(255,mathMax(rgb.g,0)),b:mathMin(255,mathMax(rgb.b,0)),a:a}} function rgbToRgb(r,g,b){return{r:bound01(r,255)*255,g:bound01(g,255)*255,b:bound01(b,255)*255}} function rgbToHsl(r,g,b){r=bound01(r,255);g=bound01(g,255);b=bound01(b,255);var max=mathMax(r,g,b),min=mathMin(r,g,b);var h,s,l=(max+min)/2;if(max==min){h=s=0}else{var d=max-min;s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g1)t-=1;if(t<1/6)return p+(q-p)*6*t;if(t<1/2)return q;if(t<2/3)return p+(q-p)*(2/3-t)*6;return p} if(s===0){r=g=b=l}else{var q=l<0.5?l*(1+s):l+s-l*s;var p=2*l-q;r=hue2rgb(p,q,h+1/3);g=hue2rgb(p,q,h);b=hue2rgb(p,q,h-1/3)} return{r:r*255,g:g*255,b:b*255}} function rgbToHsv(r,g,b){r=bound01(r,255);g=bound01(g,255);b=bound01(b,255);var max=mathMax(r,g,b),min=mathMin(r,g,b);var h,s,v=max;var d=max-min;s=max===0?0:d/max;if(max==min){h=0}else{switch(max){case r:h=(g-b)/d+(g>1))+720)%360;--results;){hsl.h=(hsl.h+part)%360;ret.push(tinycolor(hsl))} return ret} function monochromatic(color,results){results=results||6;var hsv=tinycolor(color).toHsv();var h=hsv.h,s=hsv.s,v=hsv.v;var ret=[];var modification=1/results;while(results--){ret.push(tinycolor({h:h,s:s,v:v}));v=(v+modification)%1} return ret} tinycolor.mix=function(color1,color2,amount){amount=(amount===0)?0:(amount||50);var rgb1=tinycolor(color1).toRgb();var rgb2=tinycolor(color2).toRgb();var p=amount/100;var w=p*2-1;var a=rgb2.a-rgb1.a;var w1;if(w*a==-1){w1=w}else{w1=(w+a)/(1+w*a)} w1=(w1+1)/2;var w2=1-w1;var rgba={r:rgb2.r*w1+rgb1.r*w2,g:rgb2.g*w1+rgb1.g*w2,b:rgb2.b*w1+rgb1.b*w2,a:rgb2.a*p+rgb1.a*(1-p)};return tinycolor(rgba)};tinycolor.readability=function(color1,color2){var c1=tinycolor(color1);var c2=tinycolor(color2);var rgb1=c1.toRgb();var rgb2=c2.toRgb();var brightnessA=c1.getBrightness();var brightnessB=c2.getBrightness();var colorDiff=(Math.max(rgb1.r,rgb2.r)-Math.min(rgb1.r,rgb2.r)+Math.max(rgb1.g,rgb2.g)-Math.min(rgb1.g,rgb2.g)+Math.max(rgb1.b,rgb2.b)-Math.min(rgb1.b,rgb2.b));return{brightness:Math.abs(brightnessA-brightnessB),color:colorDiff}};tinycolor.isReadable=function(color1,color2){var readability=tinycolor.readability(color1,color2);return readability.brightness>125&&readability.color>500};tinycolor.mostReadable=function(baseColor,colorList){var bestColor=null;var bestScore=0;var bestIsReadable=!1;for(var i=0;i125&&readability.color>500;var score=3*(readability.brightness/125)+(readability.color/500);if((readable&&!bestIsReadable)||(readable&&bestIsReadable&&score>bestScore)||((!readable)&&(!bestIsReadable)&&score>bestScore)){bestIsReadable=readable;bestScore=score;bestColor=tinycolor(colorList[i])}} return bestColor};var names=tinycolor.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"};var hexNames=tinycolor.hexNames=flip(names);function flip(o){var flipped={};for(var i in o){if(o.hasOwnProperty(i)){flipped[o[i]]=i}} return flipped} function boundAlpha(a){a=parseFloat(a);if(isNaN(a)||a<0||a>1){a=1} return a} function bound01(n,max){if(isOnePointZero(n)){n="100%"} var processPercent=isPercentage(n);n=mathMin(max,mathMax(0,parseFloat(n)));if(processPercent){n=parseInt(n*max,10)/100} if((math.abs(n-max)<0.000001)){return 1} return(n%max)/parseFloat(max)} function clamp01(val){return mathMin(1,mathMax(0,val))} function parseIntFromHex(val){return parseInt(val,16)} function isOnePointZero(n){return typeof n=="string"&&n.indexOf('.')!=-1&&parseFloat(n)===1} function isPercentage(n){return typeof n==="string"&&n.indexOf('%')!=-1} function pad2(c){return c.length==1?'0'+c:''+c} function convertToPercentage(n){if(n<=1){n=(n*100)+"%"} return n} function convertDecimalToHex(d){return Math.round(parseFloat(d)*255).toString(16)} function convertHexToDecimal(h){return(parseIntFromHex(h)/255)} var matchers=(function(){var CSS_INTEGER="[-\\+]?\\d+%?";var CSS_NUMBER="[-\\+]?\\d*\\.\\d+%?";var CSS_UNIT="(?:"+CSS_NUMBER+")|(?:"+CSS_INTEGER+")";var PERMISSIVE_MATCH3="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?";var PERMISSIVE_MATCH4="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?";return{rgb:new RegExp("rgb"+PERMISSIVE_MATCH3),rgba:new RegExp("rgba"+PERMISSIVE_MATCH4),hsl:new RegExp("hsl"+PERMISSIVE_MATCH3),hsla:new RegExp("hsla"+PERMISSIVE_MATCH4),hsv:new RegExp("hsv"+PERMISSIVE_MATCH3),hsva:new RegExp("hsva"+PERMISSIVE_MATCH4),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}})();function stringInputToObject(color){color=color.replace(trimLeft,'').replace(trimRight,'').toLowerCase();var named=!1;if(names[color]){color=names[color];named=!0}else if(color=='transparent'){return{r:0,g:0,b:0,a:0,format:"name"}} var match;if((match=matchers.rgb.exec(color))){return{r:match[1],g:match[2],b:match[3]}} if((match=matchers.rgba.exec(color))){return{r:match[1],g:match[2],b:match[3],a:match[4]}} if((match=matchers.hsl.exec(color))){return{h:match[1],s:match[2],l:match[3]}} if((match=matchers.hsla.exec(color))){return{h:match[1],s:match[2],l:match[3],a:match[4]}} if((match=matchers.hsv.exec(color))){return{h:match[1],s:match[2],v:match[3]}} if((match=matchers.hsva.exec(color))){return{h:match[1],s:match[2],v:match[3],a:match[4]}} if((match=matchers.hex8.exec(color))){return{a:convertHexToDecimal(match[1]),r:parseIntFromHex(match[2]),g:parseIntFromHex(match[3]),b:parseIntFromHex(match[4]),format:named?"name":"hex8"}} if((match=matchers.hex6.exec(color))){return{r:parseIntFromHex(match[1]),g:parseIntFromHex(match[2]),b:parseIntFromHex(match[3]),format:named?"name":"hex"}} if((match=matchers.hex3.exec(color))){return{r:parseIntFromHex(match[1]+''+match[1]),g:parseIntFromHex(match[2]+''+match[2]),b:parseIntFromHex(match[3]+''+match[3]),format:named?"name":"hex"}} return!1} window.tinycolor=tinycolor})();$(function(){if($.fn.spectrum.load){$.fn.spectrum.processNativeColorInputs()}})}); $('head').append(''); }; // end setupColorpickerSpectrum self.setup = function() { if ('pluginloaded' in self) { console.log('IITC plugin already loaded: ' + self.title + ' version ' + self.version); return; } else { self.pluginloaded = true; } self.setupColorpickerSpectrum(); self.restoresettings(); self.portallabelslayergroup = new L.LayerGroup(); window.addPortalHighlighter(self.highlightername,self.highlightportals); if (self.highlighteractive()) { self.updateHighlighter(); map.addLayer(self.portallabelslayergroup); $('.' + self.pluginname + '-portallabel').css('pointer-events','none'); } window.addHook('mapDataRefreshEnd',function() { window.setTimeout(self.updateHighlighter); }); // window.addHook('portalSelected', self.onPortalSelected); // stop while map moved or when map loading starts window.map.on('movestart', self.stop); window.addHook('mapDataRefreshStart', self.stop); // restart when map loading is done window.map.on('moveend', function() { window.setTimeout(self.restart); }); // use a timeout to make sure the window status is set window.addHook('mapDataRefreshEnd',function() { window.setTimeout(self.restart); }); // use a timeout to make sure the window status is set // restart when a layer is added/removed window.map.on('overlayadd overlayremove', self.restart); // detect captures from comms window.addHook('publicChatDataAvailable',self.publicchat); window.addHook('portalDetailLoaded', function(data) { if (self.storedetails(data) === self.requestid) self.next(); }); window.addHook('portalSelected',self.onPortalSelected); window.addHook('portalDetailLoaded',self.showPortalSelected); window.addHook('portalAdded', self.portalAdded); window.map.on('zoomend',self.zoomend); $('#toolbox').append(`${self.title}`); $('head').append(` `); console.log('IITC plugin loaded: ' + self.title + ' version ' + self.version); }; var setup = function() { (window.iitcLoaded?self.setup():window.addHook('iitcLoaded',self.setup)); }; // Added to support About IITC details and changelog: plugin_info.script.version = plugin_info.script.version.replace(/\.\d{8}\.\d{6}$/,''); plugin_info.buildName = 'softspot.nl'; plugin_info.dateTimeVersion = self.version.replace(/^.*(\d{4})(\d{2})(\d{2})\.(\d{6})/,'$1-$2-$3-$4'); plugin_info.pluginId = self.id; let changelog = [{version:'This is a softspot.nl plugin by ' + self.author,changes:[]},...self.changelog.replace(/^.*?version /s,'').split(/\nversion /).map((v)=>{v=v.split(/\n/).map((l)=>{return l.replace(/^- /,'')}).filter((l)=>{return l != "";}); return {version:v.shift(),changes:v}})]; setup.info = plugin_info; //add the script info data to the function as a property if (typeof changelog !== 'undefined') setup.info.changelog = changelog; if(!window.bootPlugins) window.bootPlugins = []; window.bootPlugins.push(setup); // if IITC has already booted, immediately run the 'setup' function if(window.iitcLoaded && typeof setup === 'function') setup(); } // wrapper end // inject code into site context var script = document.createElement('script'); var info = {}; if (typeof GM_info !== 'undefined' && GM_info && GM_info.script) info.script = { version: GM_info.script.version, name: GM_info.script.name, description: GM_info.script.description }; script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');')); (document.body || document.head || document.documentElement).appendChild(script);