User:Artoria2e5/Gadget-PRCoords.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
// <nowiki>
/**
* Gadget for PRCoords (People's Rectified Coordinates)
* @file Gadget for inserting valid WGS-84 coords from GCJ-02/BD-09 input
* @author User:Artoria2e5
* @see [[User:Artoria2e5/PRCoords.js]]
* @see [[:en:User:V111P/js/addToolbarButtons]]
* @license CC0
*
* Install it, edit something, select the coords (see Chinese howto #3), and
* click the button.
*
*
* 如何安装:
* 1. 将这行加入[[User:<您的用户名>/common.js]]:
* importScript('User:Artoria2e5/Gadget-PRCoords.js') // [[User:Artoria2e5/Gadget-PRCoords.js]]
*
* 如何使用:
* 1. 使用GeoHack的卫星图或OpenStreetMap地图确认条目的坐标,若正确则无需处理。
* 也可以检查地点是否碰巧在已知有偏移的地图上显示正确。若显示“正确”说明地点的
* 位置信息也存在偏移,需要修正。
* 2. 进入源码编辑。编辑工具栏上会出现两个长得一样的按钮(懒得上传不一样的了),
* 鼠标放上去会显示是 gcj02 还是 bd09。
* 后者基本只用于百度地图,前者见于其他的地图服务商。
* 3. 找到您想要转换的坐标,如:
* {{coord|121.3213|31.9320}}
* {{coord|121|19|17|N|31|55|55|E}}
* 本工具也支持较短的度数、度分格式。
* 4. 选中中间的坐标部分,如“121.3213|31.9320”、“121|19|17|N|31|55|55|E”.
* 复制坐标,以备第 7a 步重试。
* 5. 按照提示的算法类型文字,点选两个按钮中的一个。
* 6. 坐标会被直接换掉,Ctrl-Z不可撤销(因此建议选中时复制一下)。
* 目前版本会判断度分秒格式,并输出一样的格式。
* 格式转换其实可以拿出来做个功能。
* 7. 预览条目,使用GeoHack的Bing或Google卫星图确认得到的坐标。
* a. 若不正确,粘贴恢复之前复制的坐标,尝试另一个转换模式。
* 8. 清理小数点和摘要框。維基百科一般留 4 位經緯度小數,「秒」值則留到整數。
*
* <pre>
* 如何传教:
* 1. 使用 WikiBlame (wikipedia.ramselehof.de/wikiblame.php?lang=zh) 在刚才修好
* 的页面最近的 4096 次编辑中寻找加入了 "{{Coord" 的。
* 2. 点进编辑。记下版本号。
* 3. 跑到做出编辑的人的讨论页。
* 4. 甩模板:
{{subst:User:Artoria2e5/coord-notice
|diff=11223344 <!-- 改成版本号 -->
|type=GCJ-02 <!-- 改成混淆方法:GCJ-02/BD-09 -->
|add=(被 Google 整了您这是?)}} <!-- 可选 -->
* 5. 发布编辑。
* </pre>
* TODO:
* We will eventually get some Bing satellite gadget GUI done some day.
* Use [[User:Vanished_user_1929210/js/lib/EditorAPIs.js]] for VE, maybe.
*/
var coordInfo = {
'N': [+1, 'lat'],
'S': [-1, 'lat'],
'E': [+1, 'lon'],
'W': [-1, 'lon'],
}
var coordBack = {
'+lat': 'N',
'-lat': 'S',
'+lon': 'E',
'-lon': 'W',
}
/**
* Attempts to parse all of these forms, minus extra params and '{{coord|':
* {{coord|latitude|longitude|coordinate parameters|template parameters}}
* {{coord|dd|N/S|dd|E/W|coordinate parameters|template parameters}}
* {{coord|dd|mm|N/S|dd|mm|E/W|coordinate parameters|template parameters}}
* {{coord|dd|mm|ss|N/S|dd|mm|ss|E/W|coordinate parameters|template parameters}}
*/
function parseCoord(seg) {
var opts = seg.split('|')
if (opts[opts.length - 1] == '')
opts.length -= 1
if (opts[0] == '')
opts.shift()
switch (opts.length) {
case 2:
return {
lat: +opts[0],
lon: +opts[1],
format: 'dec',
}
case 4:
return {
lat: dmsToDec(opts[0], 0, 0, opts[1], 'lat'),
lon: dmsToDec(opts[2], 0, 0, opts[3], 'lon'),
format: 'd',
}
case 6:
return {
lat: dmsToDec(opts[0], opts[1], 0, opts[2], 'lat'),
lon: dmsToDec(opts[3], opts[4], 0, opts[5], 'lon'),
format: 'dm',
}
case 8:
return {
lat: dmsToDec(opts[0], opts[1], opts[2], opts[3], 'lat'),
lon: dmsToDec(opts[4], opts[5], opts[6], opts[7], 'lon'),
format: 'dms',
}
default:
throw new RangeError("opts contains" + opts.length + "elements?")
}
}
function dmsToDec(d, m, s, hemisphere = 'N', type = '') {
if (type !== '') {
if (coordInfo[hemisphere][1] !== type) {
throw new RangeError('' + hemisphere + ' ' + type)
}
}
return coordInfo[hemisphere][0] * ((+d) + (+m)/60 + (+s)/3600)
}
function decToDmsParams(dec, type) {
var sign = (+dec) >= 0 ? 1 : -1
var hemi = coordBack[(sign == -1 ? '-' : '+') + type]
dec *= sign
var d = Math.floor(dec)
var m = Math.floor((dec-d)*60)
var s = Math.round((dec-d-m/60)*3600*1e3)/1e3
return [d, m, s, hemi].join('|')
}
function reformat(seg, func = 'gcj_wgs') {
var coords = parseCoord(seg)
var newCoords = PRCoords[func](coords)
switch (coords.format) {
case "dms":
case "dm":
return [decToDmsParams(newCoords.lat, 'lat'),
decToDmsParams(newCoords.lon, 'lon')].join('|')
default:
// unexpected -- log it
console.log(coords.format)
case "dec":
case "d":
return [newCoords.lat, newCoords.lon].map(function(i) {
return Math.round(i*1e6)/1e6
}).join('|')
}
}
if (['edit', 'submit'].indexOf(mw.config.get('wgAction')) !== -1) {
;mw.loader.using([
'jquery.textSelection',
'jquery.ui',
'ext.wikiEditor',
]).then(function(){ // MW loader callback
$(function(){
"use strict"
mw.loader.load('https://zh.wikipedia.org/zhwiki/w/index.php?title=User:Artoria2e5/PRCoords.js&action=raw&ctype=text/javascript')
// The following trivial translation-associated routines are dedicated to the
// public domain under CC0 1.0.
// non-recursive fetching
var translation_fetch = {
'zh-cn': ['zh-cn', 'zh-sg', 'zh-tw', 'zh-hk', 'zh-mo'],
'zh-hans': ['zh-cn', 'zh-sg', 'zh-tw', 'zh-hk', 'zh-mo'],
'zh-sg': ['zh-sg', 'zh-cn', 'zh-tw', 'zh-hk', 'zh-mo'],
'zh-tw': ['zh-tw', 'zh-hk', 'zh-mo', 'zh-cn', 'zh-sg'],
'zh-hant': ['zh-tw', 'zh-hk', 'zh-mo', 'zh-cn', 'zh-sg'],
'zh-hk': ['zh-hk', 'zh-mo', 'zh-tw', 'zh-cn', 'zh-sg'],
'zh-mo': ['zh-mo', 'zh-hk', 'zh-tw', 'zh-cn', 'zh-sg'],
}
// @config UI Locale (defaults to autodetection for current page)
var UILocale = mw.config.get("wgUserVariant") || mw.config.get("wgUserLanguage") || 'en'
UILocale = UILocale.toLowerCase()
// The text messages are probably not PD.
var messages = {
'zh-cn': {
'%1 conv': '%1转换',
'Rectifying Chinese coordinates with [[User:Artoria2e5/Gadget-PRCoords.js]]: ':
'使用[[User:Artoria2e5/Gadget-PRCoords.js]]修正中国坐标:',
' ([not] satellite/osm verified)' :'(已/未经卫星图/OSM确认)'
},
'zh-tw': {
'%1 conv': '%1變換'
}
}
// Yes, absolutely no plural handling!
function grabT(s) {
for (var i of (translation_fetch[UILocale] || [])) {
if (typeof messages[i] !== 'object')
continue
if (typeof messages[i][s] !== 'undefined')
return messages[i][s]
}
return s
}
// Now we should start playing with
// https://en.wikipedia.org/wiki/User:V111P/js/addToolbarButtons.js
var textArea = $('#wpTextbox1')
var summary = document.getElementById('wpSummary')
var editedOnce = false
var methods = {
'gcj': 'GCJ-02',
'bd' : 'BD-09',
}
function wrapCallback(method) {
return function(s) {
try {
var sel = textArea.textSelection('getSelection')
sel = sel.replace(/\r/g, '') // IE before 9 doesn't remove the \r's
textArea.textSelection('encapsulateSelection', {
pre: reformat(sel, method),
replace: true
})
if (!editedOnce)
summary.value += grabT('Rectifying Chinese coordinates with [[User:Artoria2e5/Gadget-PRCoords.js]]: ')
summary.value += '[[' + methods[method.split('_', 1)[0]] +']]' + grabT(' ([not] satellite/osm verified)')
editedOnce = true
} catch (e) {
alert(e)
}
}
}
function makeButton(method) {
var refmt = function (method) {
var splits = method.split('_')
return splits.length >= 2 ? splits.slice(0, 2).join('→') : method;
}
return {
id: 'prcoords_' + method,
tooltip: grabT('%1 conv').replace('%1', refmt(method)),
section: 'main',
group: 'format',
callback: wrapCallback(method),
iconUrl: 'https:/upwiki/wikipedia/commons/a/ac/Globe%2C_distorted_China.svg',
}
}
window.toolbarButtonsToAdd = [makeButton('gcj_wgs_bored'), makeButton('bd_wgs_bored')]
if (mw.libs.addToolbarButtons) {
mw.libs.addToolbarButtons(window.toolbarButtonsToAdd)
window.toolbarButtonsToAdd = []
} else {
mw.loader.load('//en.wikipedia.org/zhwiki/w/index.php?title=User:Artoria2e5/js/addToolbarButtons.js&action=raw&ctype=text/javascript')
}
function bing_sat_iframe(lat, lon, width = 500, height = 400) {
let lats = '' + lat
let lons = '' + lon
let ret = document.createElement('iframe')
// sty=h -> labelled (useless)
ret.setAttribute('width', width)
ret.setAttribute('height', height)
ret.setAttribute('frameborder', 0)
ret.src = 'https://www.bing.com/maps/embed/viewer.aspx?' +
`v=${zoom}&cp=${lat}~${lon}&lvl=${zoom}&w=${width}&h=${height}&sty=a&typ=d` // '&pp=&ps=&dir=0&mkt=en-us&src=SHELL&form=BMEMJS'
return ret
}
})})}
// </nowiki>