WazeWrap Beta

A base library for WME script writers

当前为 2017-01-16 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/24870/169731/WazeWrap%20Beta.js

  1. // ==UserScript==
  2. // @name WazeWrap Beta
  3. // @namespace https://gf.qytechs.cn/users/30701-justins83-waze
  4. // @version 0.1.11
  5. // @description A base library for WME script writers
  6. // @author JustinS83/MapOMatic
  7. // @include https://beta.waze.com/*editor/*
  8. // @include https://www.waze.com/*editor/*
  9. // @exclude https://www.waze.com/*user/editor/*
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. /* global W */
  14. /* global WazeWrapBeta */
  15. var WazeWrapBeta = {};
  16.  
  17. (function() {
  18.  
  19. function bootstrap(tries) {
  20. tries = tries || 1;
  21. if (window.W &&
  22. window.W.map &&
  23. window.W.model &&
  24. window.W.loginManager &&
  25. $) {
  26. init();
  27. } else if (tries < 1000) {
  28. setTimeout(function () { bootstrap(tries++); }, 200);
  29. } else {
  30. console.log('WazeWrap failed to load');
  31. }
  32. }
  33.  
  34. bootstrap();
  35.  
  36. function init(){
  37. console.log("WazeWrapBeta initializing...");
  38. var oldLib = window.WazeWrap;
  39. var root = this;
  40.  
  41. WazeWrapBeta .Version = GM_info.script.version;
  42. WazeWrapBeta .isBetaEditor = /beta/.test(location.href);
  43.  
  44. SetUpRequire();
  45.  
  46. WazeWrapBeta .test = "test";
  47. WazeWrapBeta .Geometry = new Geometry;
  48. WazeWrapBeta .Model = new Model;
  49. WazeWrapBeta .Interface = new Interface;
  50. WazeWrapBeta .User = new User;
  51. WazeWrapBeta .Util = new Util;
  52. WazeWrapBeta.Require = new Require;
  53. root.WazeWrapBeta = WazeWrapBeta ;
  54.  
  55. console.log('WazeWrapBeta Loaded');
  56. };
  57.  
  58.  
  59. function SetUpRequire(){
  60. //if(this.isBetaEditor || typeof window.require !== "undefined")
  61. // return;
  62.  
  63. console.log("Setting d2's require fix...");
  64.  
  65. // setup one global var and put all in
  66. var WMEAPI = {};
  67.  
  68. // detect URL of WME source code
  69. WMEAPI.scripts = document.getElementsByTagName('script');
  70.  
  71. WMEAPI.url=null;
  72. for (i=0;i<WMEAPI.scripts.length;i++){
  73. if (WMEAPI.scripts[i].src.indexOf('/assets-editor/js/app')!=-1)
  74. {
  75. WMEAPI.url=WMEAPI.scripts[i].src;
  76. break;
  77. }
  78. }
  79. if (WMEAPI.url==null)
  80. throw new Error("WME Hack: can't detect WME main JS");
  81.  
  82.  
  83. // setup a fake require and require.define
  84. WMEAPI.require=function (e) {
  85. if (WMEAPI.require.define.modules.hasOwnProperty(e))
  86. return WMEAPI.require.define.modules[e];
  87. else
  88. console.error('Require failed on ' + e, WMEAPI.require.define.modules);
  89. return null;
  90. };
  91.  
  92. WMEAPI.require.define=function (m) {
  93. if (WMEAPI.require.define.hasOwnProperty('modules')==false)
  94. WMEAPI.require.define.modules={};
  95. for (var p in m){
  96. WMEAPI.require.define.modules[p]=m[p];
  97. }
  98. };
  99.  
  100. // save the original webpackJsonp function
  101. WMEAPI.tmp = window.webpackJsonp;
  102.  
  103. // taken from WME code: this function is a wrapper that setup the API and may call recursively other functions
  104.  
  105. WMEAPI.t = function (n) {
  106. if (WMEAPI.s[n]) return WMEAPI.s[n].exports;
  107. var r = WMEAPI.s[n] = {
  108. exports: {},
  109. id: n,
  110. loaded: !1
  111. };
  112. return WMEAPI.e[n].call(r.exports, r, r.exports, WMEAPI.t), r.loaded = !0, r.exports;
  113. };
  114.  
  115. // e is a copy of all WME funcs because function t need to access to this list
  116. WMEAPI.e=[];
  117. console.log("1");
  118. // the patch
  119. window.webpackJsonp = function(a, i) {
  120. // our API but we will use it only to build the require stuffs
  121. var api={};
  122. // taken from WME code. a is [1], so...
  123. for (var o, d, u = 0, l = []; u < a.length; u++) d = a[u], WMEAPI.r[d] && l.push.apply(l, WMEAPI.r[d]), WMEAPI.r[d] = 0;
  124. console.log("2");
  125. var unknownCount=0;
  126. var classname, funcStr;
  127. console.log("0.1.10");
  128. // copy i in e and keep a link from classname to index in e
  129. for (o in i){
  130. WMEAPI.e[o] = i[o];
  131. funcStr = i[o].toString();
  132. classname = funcStr.match(/CLASS_NAME:\"([^\"]*)\"/);
  133. if (classname){
  134. // keep the link.
  135. api[classname[1].replace(/\./g,'/').replace(/^W\//, 'Waze/')]={index: o, func: WMEAPI.e[o]};
  136. }
  137. else{
  138. api['Waze/Unknown/' + unknownCount]={index: o, func: WMEAPI.e[o]};
  139. unknownCount++;
  140. }
  141. }
  142. console.log("3");
  143. // taken from WME code: it calls the original webpackJsonp and do something else, but I don't really know what.
  144. // removed the call to the original webpackJsonp: still works...
  145. //for (tmp && tmp(a, i); l.length;) l.shift().call(null, t);
  146. for (; l.length;) l.shift().call(null, WMEAPI.t);
  147. WMEAPI.s[0] = 0;
  148. // run the first func of WME. This first func will call recusrsively all funcs needed to setup the API.
  149. // After this call, s will contain all instanciables classes.
  150. //var ret = WMEAPI.t(0);
  151. // now, build the requires thanks to the link we've built in var api.
  152. var module={};
  153. var apiFuncName;
  154. unknownCount=0;
  155. console.log("4");
  156. for (o in i){
  157. funcStr = i[o].toString();
  158. classname = funcStr.match(/CLASS_NAME:\"([^\"]*)\"/);
  159. if (classname){
  160. module={};
  161. apiFuncName = classname[1].replace(/\./g,'/').replace(/^W\//, 'Waze/');
  162. module[apiFuncName]=WMEAPI.t(api[apiFuncName].index);
  163. WMEAPI.require.define(module);
  164. }
  165. else{
  166. var matches = funcStr.match(/SEGMENT:"segment",/);
  167. if (matches){
  168. module={};
  169. apiFuncName='Waze/Model/ObjectType';
  170. module[apiFuncName]=WMEAPI.t(api['Waze/Unknown/' + unknownCount].index);
  171. WMEAPI.require.define(module);
  172. }
  173. unknownCount++;
  174. }
  175. }
  176. console.log("5");
  177.  
  178. // restore the original func
  179. window.webpackJsonp=WMEAPI.tmp;
  180. console.log("6");
  181. // set the require public if needed
  182. // if so: others scripts must wait for the window.require to be available before using it.
  183. WazeWrapBeta.require = WMEAPI.require;
  184. console.log(WMEAPI.require);
  185. console.log(WazeWrapBeta.require);
  186. // all available functions are in WMEAPI.require.define.modules
  187. // console.debug this variable to read it:
  188. // console.debug('Modules: ', WMEAPI.require.define.modules);
  189. // run your script here:
  190. // setTimeout(yourscript);
  191. // again taken from WME code. Not sure about what it does.
  192. //if (i[0]) return ret;
  193. };
  194.  
  195. // some kind of global vars and init
  196. WMEAPI.s = {};
  197. WMEAPI.r = {
  198. 0: 0
  199. };
  200.  
  201. // hacking finished
  202.  
  203. // load again WME through our patched func
  204. WMEAPI.WMEHACK_Injected_script = document.createElement("script");
  205. WMEAPI.WMEHACK_Injected_script.setAttribute("type", "application/javascript");
  206. WMEAPI.WMEHACK_Injected_script.src = WMEAPI.url;
  207. document.body.appendChild(WMEAPI.WMEHACK_Injected_script);
  208. console.log("d2 fix complete");
  209. }
  210.  
  211. function Geometry(){
  212. //var geometry = WazeWrap.Geometry;
  213.  
  214. //Converts to "normal" GPS coordinates
  215. this.ConvertTo4326 = function (long, lat){
  216. var projI=new OpenLayers.Projection("EPSG:900913");
  217. var projE=new OpenLayers.Projection("EPSG:4326");
  218. return (new OpenLayers.LonLat(long, lat)).transform(projI,projE);
  219. };
  220. this.ConvertTo900913 = function (long, lat){
  221. var projI=new OpenLayers.Projection("EPSG:900913");
  222. var projE=new OpenLayers.Projection("EPSG:4326");
  223. return (new OpenLayers.LonLat(long, lat)).transform(projE,projI);
  224. };
  225.  
  226. //Converts the Longitudinal offset to an offset in 4326 gps coordinates
  227. this.CalculateLongOffsetGPS = function(longMetersOffset, long, lat)
  228. {
  229. var R= 6378137; //Earth's radius
  230. var dLon = longMetersOffset / (R * Math.cos(Math.PI * lat / 180)); //offset in radians
  231. var lon0 = dLon * (180 / Math.PI); //offset degrees
  232.  
  233. return lon0;
  234. };
  235.  
  236. //Converts the Latitudinal offset to an offset in 4326 gps coordinates
  237. this.CalculateLatOffsetGPS = function(latMetersOffset, lat)
  238. {
  239. var R= 6378137; //Earth's radius
  240. var dLat = latMetersOffset/R;
  241. var lat0 = dLat * (180 /Math.PI); //offset degrees
  242.  
  243. return lat0;
  244. };
  245. /**
  246. * Checks if the given geometry is on screen
  247. * @function WazeWrap.Model.isGeometryInMapExtent
  248. * @param {OpenLayers.Geometry} Geometry to check if any part of is in the current viewport
  249. */
  250. this.isLonLatInMapExtent = function (lonLat) {
  251. 'use strict';
  252. return lonLat && W.map.getExtent().containsLonLat(lonLat);
  253. };
  254. /**
  255. * Checks if the given geometry is on screen
  256. * @function WazeWrap.Model.isGeometryInMapExtent
  257. * @param {OpenLayers.Geometry} Geometry to check if any part of is in the current viewport
  258. */
  259. this.isGeometryInMapExtent = function (geometry) {
  260. 'use strict';
  261. return geometry && geometry.getBounds &&
  262. W.map.getExtent().intersectsBounds(geometry.getBounds());
  263. };
  264. /**
  265. * Calculates the distance between two given points
  266. * @function WazeWrap.Model.calculateDistance
  267. * @param {OpenLayers.Geometry.Point} An array of OL.Geometry.Point with which to measure the total distance. A minimum of 2 points is needed.
  268. */
  269. this.calculateDistance = function(pointArray) {
  270. if(pointArray.length < 2)
  271. return 0;
  272.  
  273. var line = new OpenLayers.Geometry.LineString(pointArray);
  274. length = line.getGeodesicLength(W.map.getProjectionObject());
  275. return length; //multiply by 3.28084 to convert to feet
  276. };
  277.  
  278. this.findClosestSegment = function(mygeometry){
  279. var onscreenSegments = WazeWrapBeta.Model.getOnscreenSegments();
  280. var minDistance = Infinity;
  281. var closestSegment;
  282. for (s in onscreenSegments) {
  283. if (!onscreenSegments.hasOwnProperty(s))
  284. continue;
  285.  
  286. segmentType = onscreenSegments[s].attributes.roadType;
  287. if (segmentType === 10 || segmentType === 3 || segmentType === 16 || segmentType === 18 || segmentType === 19) //10 ped boardwalk, 16 stairway, 18 railroad, 19 runway, 3 freeway
  288. continue;
  289.  
  290. distanceToSegment = mygeometry.distanceTo(onscreenSegments[s].geometry, {details: true});
  291.  
  292. if (distanceToSegment.distance < minDistance) {
  293. minDistance = distanceToSegment.distance;
  294. closestSegment = onscreenSegments[s];//.seg = s;
  295. //closestSegment.point = new OL.Geometry.Point(distanceToSegment.x1, distanceToSegment.y1);
  296. }
  297. }
  298. return closestSegment;
  299. };
  300. };
  301.  
  302. function Model(){
  303.  
  304. this.getPrimaryStreetID = function(segmentID){
  305. return W.model.segments.get(segmentID).attributes.primaryStreetID;
  306. };
  307.  
  308. this.getStreetName = function(primaryStreetID){
  309. return W.model.streets.get(PrimaryStreetID).name;
  310. };
  311.  
  312. this.getCityID = function(primaryStreetID){
  313. return W.model.streets.get(primaryStreetID).cityID;
  314. };
  315.  
  316. this.getCityName = function(primaryStreetID){
  317. return W.model.cities.get(this.getCityID(primaryStreetID)).attributes.Name;
  318. };
  319.  
  320. this.getStateName = function(primaryStreetID){
  321. return W.model.states.get(getStateID(primaryStreetID)).Name;
  322. };
  323.  
  324. this.getStateID = function(primaryStreetID){
  325. return W.model.cities.get(primaryStreetID).attributes.stateID;
  326. };
  327.  
  328. this.getCountryID = function(primaryStreetID){
  329. return W.model.cities.get(this.getCityID(primaryStreetID)).attributes.CountryID;
  330. };
  331.  
  332. this.getCountryName = function(primaryStreetID){
  333. return W.model.countries.get(getCountryID(primaryStreetID)).name;
  334. };
  335.  
  336. this.getCityNameFromSegmentObj = function(segObj){
  337. return this.getCityName(segObj.attributes.primaryStreetID);
  338. };
  339.  
  340. this.getStateNameFromSegmentObj = function(segObj){
  341. return this.getStateName(segObj.attributes.primaryStreetID);
  342. };
  343.  
  344. //returns an array of segmentIDs for all segments that are part of the same roundabout as the passed segment
  345. this.getAllRoundaboutSegmentsFromObj = function(segObj){
  346. if(segObj.model.attributes.junctionID === null)
  347. return null;
  348.  
  349. return W.model.junctions.objects[segObj.model.attributes.junctionID].segIDs;
  350. };
  351.  
  352. this.getAllRoundaboutJunctionNodesFromObj = function(segObj){
  353. var RASegs = this.getAllRoundaboutSegmentsFromObj(segObj);
  354. var RAJunctionNodes = [];
  355. for(i=0; i< RASegs.length; i++){
  356. RAJunctionNodes.push(W.model.nodes.objects[W.model.segments.get(RASegs[i]).attributes.toNodeID]);
  357.  
  358. }
  359. return RAJunctionNodes;
  360. };
  361.  
  362. this.isRoundaboutSegmentID = function(segmentID){
  363. if(W.model.segments.get(segmentID).attributes.junctionID === null)
  364. return false;
  365. else
  366. return true;
  367. };
  368.  
  369. this.isRoundaboutSegmentObj = function(segObj){
  370. if(segObj.model.attributes.junctionID === null)
  371. return false;
  372. else
  373. return true;
  374. };
  375.  
  376.  
  377. this.getOnscreenSegments = function(){
  378. var segments = W.model.segments.objects;
  379. var mapExtent = W.map.getExtent();
  380. var onScreenSegments = [];
  381. var seg;
  382.  
  383. for (s in segments) {
  384. if (!segments.hasOwnProperty(s))
  385. continue;
  386.  
  387. seg = W.model.segments.get(s);
  388. if (mapExtent.intersectsBounds(seg.geometry.getBounds()))
  389. onScreenSegments.push(seg);
  390. }
  391. return onScreenSegments;
  392. };
  393.  
  394. /**
  395. * Defers execution of a callback function until the WME map and data
  396. * model are ready. Call this function before calling a function that
  397. * causes a map and model reload, such as W.map.moveTo(). After the
  398. * move is completed the callback function will be executed.
  399. * @function WazeWrap.Model.onModelReady
  400. * @param {Function} callback The callback function to be executed.
  401. * @param {Boolean} now Whether or not to call the callback now if the
  402. * model is currently ready.
  403. * @param {Object} context The context in which to call the callback.
  404. */
  405. this.onModelReady = function (callback, now, context) {
  406. var deferModelReady = function () {
  407. return $.Deferred(function (dfd) {
  408. var resolve = function () {
  409. dfd.resolve();
  410. W.model.events.unregister('mergeend', null, resolve);
  411. };
  412. W.model.events.register('mergeend', null, resolve);
  413. }).promise();
  414. };
  415. var deferMapReady = function () {
  416. return $.Deferred(function (dfd) {
  417. var resolve = function () {
  418. dfd.resolve();
  419. W.vent.off('operationDone', resolve);
  420. };
  421. W.vent.on('operationDone', resolve);
  422. }).promise();
  423. };
  424.  
  425. if (typeof callback === 'function') {
  426. context = context || callback;
  427. if (now && WazeWrapBeta.Util.mapReady() && WazeWrapBeta.Util.modelReady()) {
  428. callback.call(context);
  429. } else {
  430. $.when(deferMapReady() && deferModelReady()).
  431. then(function () {
  432. callback.call(context);
  433. });
  434. }
  435. }
  436. };
  437. };
  438. function User(){
  439. this.Rank = function(){
  440. return W.loginManager.user.normalizedLevel;
  441. };
  442.  
  443. this.Username = function(){
  444. return W.loginManager.user.userName;
  445. };
  446.  
  447. this.isCM = function(){
  448. if(W.loginManager.user.editableCountryIDs.length > 0)
  449. return true;
  450. else
  451. return false;
  452. };
  453. this.isAM = function(){
  454. return W.loginManager.user.isAreaManager;
  455. };
  456. };
  457.  
  458.  
  459. function Require(){
  460. this.DragElement = function(){
  461. var myDragElement = OL.Class({
  462. started: !1,
  463. stopDown: !0,
  464. dragging: !1,
  465. touch: !1,
  466. last: null ,
  467. start: null ,
  468. lastMoveEvt: null ,
  469. oldOnselectstart: null ,
  470. interval: 0,
  471. timeoutId: null ,
  472. forced: !1,
  473. active: !1,
  474. initialize: function(e) {
  475. this.map = e,
  476. this.uniqueID = myDragElement.baseID--
  477. },
  478. callback: function(e, t) {
  479. if (this[e])
  480. return this[e].apply(this, t)
  481. },
  482. dragstart: function(e) {
  483. e.xy = new OL.Pixel(e.clientX - this.map.viewPortDiv.offsets[0],e.clientY - this.map.viewPortDiv.offsets[1]);
  484. var t = !0;
  485. return this.dragging = !1,
  486. (OL.Event.isLeftClick(e) || OL.Event.isSingleTouch(e)) && (this.started = !0,
  487. this.start = e.xy,
  488. this.last = e.xy,
  489. OL.Element.addClass(this.map.viewPortDiv, "olDragDown"),
  490. this.down(e),
  491. this.callback("down", [e.xy]),
  492. OL.Event.stop(e),
  493. this.oldOnselectstart || (this.oldOnselectstart = document.onselectstart ? document.onselectstart : OL.Function.True),
  494. document.onselectstart = OL.Function.False,
  495. t = !this.stopDown),
  496. t
  497. },
  498. forceStart: function() {
  499. var e = arguments.length > 0 && void 0 !== arguments[0] && arguments[0];
  500. return this.started = !0,
  501. this.endOnMouseUp = e,
  502. this.forced = !0,
  503. this.last = {
  504. x: 0,
  505. y: 0
  506. },
  507. this.callback("force")
  508. },
  509. forceEnd: function() {
  510. if (this.forced)
  511. return this.endDrag()
  512. },
  513. dragmove: function(e) {
  514. return this.map.viewPortDiv.offsets && (e.xy = new OL.Pixel(e.clientX - this.map.viewPortDiv.offsets[0],e.clientY - this.map.viewPortDiv.offsets[1])),
  515. this.lastMoveEvt = e,
  516. !this.started || this.timeoutId || e.xy.x === this.last.x && e.xy.y === this.last.y || (this.interval > 0 && (this.timeoutId = window.setTimeout(OL.Function.bind(this.removeTimeout, this), this.interval)),
  517. this.dragging = !0,
  518. this.move(e),
  519. this.oldOnselectstart || (this.oldOnselectstart = document.onselectstart,
  520. document.onselectstart = OL.Function.False),
  521. this.last = e.xy),
  522. !0
  523. },
  524. dragend: function(e) {
  525. if (e.xy = new OL.Pixel(e.clientX - this.map.viewPortDiv.offsets[0],e.clientY - this.map.viewPortDiv.offsets[1]),
  526. this.started) {
  527. var t = this.start !== this.last;
  528. this.endDrag(),
  529. this.up(e),
  530. this.callback("up", [e.xy]),
  531. t && this.callback("done", [e.xy])
  532. }
  533. return !0
  534. },
  535. endDrag: function() {
  536. this.started = !1,
  537. this.dragging = !1,
  538. this.forced = !1,
  539. OL.Element.removeClass(this.map.viewPortDiv, "olDragDown"),
  540. document.onselectstart = this.oldOnselectstart
  541. },
  542. down: function(e) {},
  543. move: function(e) {},
  544. up: function(e) {},
  545. out: function(e) {},
  546. mousedown: function(e) {
  547. return this.dragstart(e)
  548. },
  549. touchstart: function(e) {
  550. return this.touch || (this.touch = !0,
  551. this.map.events.un({
  552. mousedown: this.mousedown,
  553. mouseup: this.mouseup,
  554. mousemove: this.mousemove,
  555. click: this.click,
  556. scope: this
  557. })),
  558. this.dragstart(e)
  559. },
  560. mousemove: function(e) {
  561. return this.dragmove(e)
  562. },
  563. touchmove: function(e) {
  564. return this.dragmove(e)
  565. },
  566. removeTimeout: function() {
  567. if (this.timeoutId = null ,
  568. this.dragging)
  569. return this.mousemove(this.lastMoveEvt)
  570. },
  571. mouseup: function(e) {
  572. if (!this.forced || this.endOnMouseUp)
  573. return this.started ? this.dragend(e) : void 0
  574. },
  575. touchend: function(e) {
  576. if (e.xy = this.last,
  577. !this.forced)
  578. return this.dragend(e)
  579. },
  580. click: function(e) {
  581. return this.start === this.last
  582. },
  583. activate: function(e) {
  584. this.$el = e,
  585. this.active = !0;
  586. var t = $(this.map.viewPortDiv);
  587. return this.$el.on("mousedown.drag-" + this.uniqueID, $.proxy(this.mousedown, this)),
  588. this.$el.on("touchstart.drag-" + this.uniqueID, $.proxy(this.touchstart, this)),
  589. $(document).on("mouseup.drag-" + this.uniqueID, $.proxy(this.mouseup, this)),
  590. t.on("mousemove.drag-" + this.uniqueID, $.proxy(this.mousemove, this)),
  591. t.on("touchmove.drag-" + this.uniqueID, $.proxy(this.touchmove, this)),
  592. t.on("touchend.drag-" + this.uniqueID, $.proxy(this.touchend, this))
  593. },
  594. deactivate: function() {
  595. return this.active = !1,
  596. this.$el.off(".drag-" + this.uniqueID),
  597. $(this.map.viewPortDiv).off(".drag-" + this.uniqueID),
  598. $(document).off(".drag-" + this.uniqueID),
  599. this.touch = !1,
  600. this.started = !1,
  601. this.forced = !1,
  602. this.dragging = !1,
  603. this.start = null ,
  604. this.last = null ,
  605. OL.Element.removeClass(this.map.viewPortDiv, "olDragDown")
  606. },
  607. adjustXY: function(e) {
  608. var t = OL.Util.pagePosition(this.map.viewPortDiv);
  609. return e.xy.x -= t[0],
  610. e.xy.y -= t[1]
  611. },
  612. CLASS_NAME: "W.Handler.DragElement"
  613. });
  614. myDragElement.baseID = 0;
  615. return myDragElement;
  616. };
  617. this.DivIcon = OpenLayers.Class({
  618. className: null ,
  619. $div: null ,
  620. events: null ,
  621. initialize: function(e, t) {
  622. this.className = e,
  623. this.moveWithTransform = !!t,
  624. this.$div = $("<div />").addClass(e),
  625. this.div = this.$div.get(0),
  626. this.imageDiv = this.$div.get(0);
  627. },
  628. destroy: function() {
  629. this.erase(),
  630. this.$div = null;
  631. },
  632. clone: function() {
  633. return new i(this.className);
  634. },
  635. draw: function(e) {
  636. return this.moveWithTransform ? (this.$div.css({
  637. transform: "translate(" + e.x + "px, " + e.y + "px)"
  638. }),
  639. this.$div.css({
  640. position: "absolute"
  641. })) : this.$div.css({
  642. position: "absolute",
  643. left: e.x,
  644. top: e.y
  645. }),
  646. this.$div.get(0);
  647. },
  648. moveTo: function(e) {
  649. null !== e && (this.px = e),
  650. null === this.px ? this.display(!1) : this.moveWithTransform ? this.$div.css({
  651. transform: "translate(" + this.px.x + "px, " + this.px.y + "px)"
  652. }) : this.$div.css({
  653. left: this.px.x,
  654. top: this.px.y
  655. });
  656. },
  657. erase: function() {
  658. this.$div.remove();
  659. },
  660. display: function(e) {
  661. this.$div.toggle(e);
  662. },
  663. isDrawn: function() {
  664. return !!this.$div.parent().length;
  665. },
  666. bringToFront: function() {
  667. if (this.isDrawn()) {
  668. var e = this.$div.parent();
  669. this.$div.detach().appendTo(e);
  670. }
  671. },
  672. forceReflow: function() {
  673. return this.$div.get(0).offsetWidth;
  674. },
  675. CLASS_NAME: "Waze.DivIcon"
  676. });
  677. };
  678. function Util(){
  679. /**
  680. * Function to defer function execution until an element is present on
  681. * the page.
  682. * @function WazeWrap.Util.waitForElement
  683. * @param {String} selector The CSS selector string or a jQuery object
  684. * to find before executing the callback.
  685. * @param {Function} callback The function to call when the page
  686. * element is detected.
  687. * @param {Object} [context] The context in which to call the callback.
  688. */
  689. this.waitForElement = function (selector, callback, context) {
  690. var jqObj;
  691.  
  692. if (!selector || typeof callback !== 'function') {
  693. return;
  694. }
  695.  
  696. jqObj = typeof selector === 'string' ?
  697. $(selector) : selector instanceof $ ? selector : null;
  698.  
  699. if (!jqObj.size()) {
  700. window.requestAnimationFrame(function () {
  701. WazeWrapBeta.Util.waitForElement(selector, callback, context);
  702. });
  703. } else {
  704. callback.call(context || callback);
  705. }
  706. };
  707.  
  708. /**
  709. * Function to track the ready state of the map.
  710. * @function WazeWrap.Util.mapReady
  711. * @return {Boolean} Whether or not a map operation is pending or
  712. * undefined if the function has not yet seen a map ready event fired.
  713. */
  714. this.mapReady = function () {
  715. var mapReady = true;
  716. W.vent.on('operationPending', function () {
  717. mapReady = false;
  718. });
  719. W.vent.on('operationDone', function () {
  720. mapReady = true;
  721. });
  722. return function () {
  723. return mapReady;
  724. };
  725. } ();
  726.  
  727. /**
  728. * Function to track the ready state of the model.
  729. * @function WazeWrap.Util.modelReady
  730. * @return {Boolean} Whether or not the model has loaded objects or
  731. * undefined if the function has not yet seen a model ready event fired.
  732. */
  733. this.modelReady = function () {
  734. var modelReady = true;
  735. W.model.events.register('mergestart', null, function () {
  736. modelReady = false;
  737. });
  738. W.model.events.register('mergeend', null, function () {
  739. modelReady = true;
  740. });
  741. return function () {
  742. return modelReady;
  743. };
  744. } ();
  745. };
  746.  
  747. function Interface() {
  748. /**
  749. * Generates id for message bars.
  750. * @private
  751. */
  752. var getNextID = function () {
  753. var id = 1;
  754. return function () {
  755. return id++;
  756. };
  757. } ();
  758. this.Shortcut = OL.Class(this, /** @lends WazeWrap.Interface.Shortcut.prototype */ {
  759. name: null,
  760. group: null,
  761. title: null,
  762. shortcut: {},
  763. callback: null,
  764. scope: null,
  765. groupExists: false,
  766. actionExists: false,
  767. eventExists: false,
  768. defaults: {
  769. group: 'default'
  770. },
  771. /**
  772. * Creates a new {WazeWrap.Interface.Shortcut}.
  773. * @class
  774. * @name WazeWrap.Interface.Shortcut
  775. * @param name {String} The name of the shortcut.
  776. * @param group {String} The name of the shortcut group.
  777. * @param title {String} The title to display for this group in the Keyboard shortcuts list
  778. * @param shortcut {String} The shortcut key(s). The shortcut
  779. * should be of the form 'i' where i is the keyboard shortuct or
  780. * include modifier keys such as 'CSA+i', where C = the control
  781. * key, S = the shift key, A = the alt key, and i = the desired
  782. * keyboard shortcut. The modifier keys are optional.
  783. * @param callback {Function} The function to be called by the
  784. * shortcut.
  785. * @param scope {Object} The object to be used as this by the
  786. * callback.
  787. * @return {WazeWrap.Interface.Shortcut} The new shortcut object.
  788. * @example //Creates new shortcut and adds it to the map.
  789. * shortcut = new WazeWrap.Interface.Shortcut('myName', 'myGroup', 'C+p', callbackFunc, null).add();
  790. */
  791. initialize: function (name, group, title, shortcut, callback, scope) {
  792. if ('string' === typeof name && name.length > 0 &&
  793. 'string' === typeof shortcut && shortcut.length > 0 &&
  794. 'function' === typeof callback) {
  795. this.name = name;
  796. this.group = group || this.defaults.group;
  797. this.title = title;
  798. this.callback = callback;
  799. this.shortcut[shortcut] = name;
  800. if ('object' !== typeof scope) {
  801. this.scope = null;
  802. } else {
  803. this.scope = scope;
  804. }
  805. return this;
  806. }
  807. },
  808. /**
  809. * Determines if the shortcut's group already exists.
  810. * @private
  811. */
  812. doesGroupExist: function () {
  813. this.groupExists = 'undefined' !== typeof W.accelerators.Groups[this.group] &&
  814. undefined !== typeof W.accelerators.Groups[this.group].members &&
  815. W.accelerators.Groups[this.group].length > 0;
  816. return this.groupExists;
  817. },
  818. /**
  819. * Determines if the shortcut's action already exists.
  820. * @private
  821. */
  822. doesActionExist: function () {
  823. this.actionExists = 'undefined' !== typeof W.accelerators.Actions[this.name];
  824. return this.actionExists;
  825. },
  826. /**
  827. * Determines if the shortcut's event already exists.
  828. * @private
  829. */
  830. doesEventExist: function () {
  831. this.eventExists = 'undefined' !== typeof W.accelerators.events.listeners[this.name] &&
  832. W.accelerators.events.listeners[this.name].length > 0 &&
  833. this.callback === W.accelerators.events.listeners[this.name][0].func &&
  834. this.scope === W.accelerators.events.listeners[this.name][0].obj;
  835. return this.eventExists;
  836. },
  837. /**
  838. * Creates the shortcut's group.
  839. * @private
  840. */
  841. createGroup: function () {
  842. W.accelerators.Groups[this.group] = [];
  843. W.accelerators.Groups[this.group].members = [];
  844. if(this.title && !I18n.translations.en.keyboard_shortcuts.groups[this.group]){
  845. console.log("Here!");
  846. console.log(I18n.translations.en.keyboard_shortcuts.groups[this.group]);
  847. I18n.translations.en.keyboard_shortcuts.groups[this.group] = {};
  848. I18n.translations.en.keyboard_shortcuts.groups[this.group].description = this.title;
  849. I18n.translations.en.keyboard_shortcuts.groups[this.group].members = [];
  850.  
  851. }
  852. },
  853. /**
  854. * Registers the shortcut's action.
  855. * @private
  856. */
  857. addAction: function () {
  858. console.log("Name " + this.name);
  859. if(this.title)
  860. I18n.translations.en.keyboard_shortcuts.groups[this.group].members[this.name] = this.name;
  861. W.accelerators.addAction(this.name, { group: this.group });
  862. },
  863. /**
  864. * Registers the shortcut's event.
  865. * @private
  866. */
  867. addEvent: function () {
  868. W.accelerators.events.register(this.name, this.scope, this.callback);
  869. },
  870. /**
  871. * Registers the shortcut's keyboard shortcut.
  872. * @private
  873. */
  874. registerShortcut: function () {
  875. W.accelerators._registerShortcuts(this.shortcut);
  876. },
  877. /**
  878. * Adds the keyboard shortcut to the map.
  879. * @return {WazeWrap.Interface.Shortcut} The keyboard shortcut.
  880. */
  881. add: function () {
  882. /* If the group is not already defined, initialize the group. */
  883. if (!this.doesGroupExist()) {
  884. this.createGroup();
  885. }
  886.  
  887. /* Clear existing actions with same name */
  888. if (this.doesActionExist()) {
  889. W.accelerators.Actions[this.name] = null;
  890. }
  891. this.addAction();
  892.  
  893. /* Register event only if it's not already registered */
  894. if (!this.doesEventExist()) {
  895. this.addEvent();
  896. }
  897.  
  898. /* Finally, register the shortcut. */
  899. this.registerShortcut();
  900. return this;
  901. },
  902. /**
  903. * Removes the keyboard shortcut from the map.
  904. * @return {WazeWrap.Interface.Shortcut} The keyboard shortcut.
  905. */
  906. remove: function () {
  907. if (this.doesEventExist()) {
  908. W.accelerators.events.unregister(this.name, this.scope, this.callback);
  909. }
  910. if (this.doesActionExist()) {
  911. delete W.accelerators.Actions[this.name];
  912. }
  913. //remove shortcut?
  914. return this;
  915. },
  916. /**
  917. * Changes the keyboard shortcut and applies changes to the map.
  918. * @return {WazeWrap.Interface.Shortcut} The keyboard shortcut.
  919. */
  920. change: function (shortcut) {
  921. if (shortcut) {
  922. this.shortcut = {};
  923. this.shortcut[shortcut] = this.name;
  924. this.registerShortcut();
  925. }
  926. return this;
  927. }
  928. }),
  929.  
  930. this.Tab = OL.Class(this, {
  931. /** @lends WazeWrap.Interface.Tab */
  932. TAB_SELECTOR: '#user-tabs ul.nav-tabs',
  933. CONTENT_SELECTOR: '#user-info div.tab-content',
  934. callback: null,
  935. $content: null,
  936. context: null,
  937. $tab: null,
  938. /**
  939. * Creates a new WazeWrap.Interface.Tab. The tab is appended to the WME
  940. * editor sidebar and contains the passed HTML content.
  941. * @class
  942. * @name WazeWrap.Interface.Tab
  943. * @param {String} name The name of the tab. Should not contain any
  944. * special characters.
  945. * @param {String} content The HTML content of the tab.
  946. * @param {Function} [callback] A function to call upon successfully
  947. * appending the tab.
  948. * @param {Object} [context] The context in which to call the callback
  949. * function.
  950. * @return {WazeWrap.Interface.Tab} The new tab object.
  951. * @example //Creates new tab and adds it to the page.
  952. * new WazeWrap.Interface.Tab('thebestscriptever', '<div>Hello World!</div>');
  953. */
  954. initialize: function (name, content, callback, context) {
  955. var idName, i = 0;
  956. if (name && 'string' === typeof name &&
  957. content && 'string' === typeof content) {
  958. if (callback && 'function' === typeof callback) {
  959. this.callback = callback;
  960. this.context = context || callback;
  961. }
  962. /* Sanitize name for html id attribute */
  963. idName = name.toLowerCase().replace(/[^a-z-_]/g, '');
  964. /* Make sure id will be unique on page */
  965. while (
  966. $('#sidepanel-' + (i ? idName + i : idName)).length > 0) {
  967. i++;
  968. }
  969. if (i) {
  970. idName = idName + i;
  971. }
  972. /* Create tab and content */
  973. this.$tab = $('<li/>')
  974. .append($('<a/>')
  975. .attr({
  976. 'href': '#sidepanel-' + idName,
  977. 'data-toggle': 'tab',
  978. })
  979. .text(name));
  980. this.$content = $('<div/>')
  981. .addClass('tab-pane')
  982. .attr('id', 'sidepanel-' + idName)
  983. .html(content);
  984.  
  985. this.appendTab();
  986. }
  987. },
  988.  
  989. append: function (content) {
  990. this.$content.append(content);
  991. },
  992.  
  993. appendTab: function () {
  994. WazeWrapBeta.Util.waitForElement(
  995. this.TAB_SELECTOR + ',' + this.CONTENT_SELECTOR,
  996. function () {
  997. $(this.TAB_SELECTOR).append(this.$tab);
  998. $(this.CONTENT_SELECTOR).first().append(this.$content);
  999. if (this.callback) {
  1000. this.callback.call(this.context);
  1001. }
  1002. }, this);
  1003. },
  1004.  
  1005. clearContent: function () {
  1006. this.$content.empty();
  1007. },
  1008.  
  1009. destroy: function () {
  1010. this.$tab.remove();
  1011. this.$content.remove();
  1012. }
  1013. });
  1014. };
  1015.  
  1016. }.call(this));

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址