WazeWrap Beta

A base library for WME script writers

当前为 2016-11-17 提交的版本,查看 最新版本

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

  1. // ==UserScript==
  2. // @name WazeWrap Beta
  3. // @namespace https://gf.qytechs.cn/users/30701-justins83-waze
  4. // @version 0.1.5
  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 WazeWrap */
  15.  
  16. (function() {
  17.  
  18. function bootstrap(tries) {
  19. tries = tries || 1;
  20. if (W &&
  21. W.map &&
  22. W.model &&
  23. W.loginManager &&
  24. $) {
  25. init();
  26. } else if (tries < 1000) {
  27. setTimeout(function () { bootstrap(tries++); }, 200);
  28. } else {
  29. console.log('WazeWrap failed to load');
  30. }
  31. }
  32.  
  33. bootstrap();
  34.  
  35. function init(){
  36. //extendModel();
  37. //extendGeometry();
  38.  
  39. var oldLib = window.WazeWrap;
  40.  
  41. var root = this;
  42. var WazeWrap = {};
  43.  
  44. WazeWrap.Version = "0.1.5b";
  45.  
  46. SetUpRequire();
  47.  
  48. WazeWrap.isBetaEditor = /beta/.test(location.href);
  49. WazeWrap.test = "test";
  50. WazeWrap.Geometry = new Geometry;
  51. WazeWrap.Model = new Model;
  52. WazeWrap.Interface = new Interface;
  53. WazeWrap.User = new User;
  54. WazeWrap.Util = new Util;
  55. root.WazeWrap = WazeWrap;
  56.  
  57. console.log('WazeWrap Loaded');
  58. };
  59.  
  60.  
  61. function SetUpRequire(){
  62. if(typeof window.require !== "undefined")
  63. return;
  64.  
  65. console("Setting d2's require fix...");
  66. // setup one global var and put all in
  67. var WMEAPI = {};
  68.  
  69. // detect URL of WME source code
  70. WMEAPI.scripts = document.getElementsByTagName('script');
  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. WMEAPI.t = function (n) {
  105. if (WMEAPI.s[n]) return WMEAPI.s[n].exports;
  106. var r = WMEAPI.s[n] = {
  107. exports: {},
  108. id: n,
  109. loaded: !1
  110. };
  111. return WMEAPI.e[n].call(r.exports, r, r.exports, WMEAPI.t), r.loaded = !0, r.exports;
  112. };
  113.  
  114. // e is a copy of all WME funcs because function t need to access to this list
  115. WMEAPI.e=[];
  116.  
  117. // the patch
  118. window.webpackJsonp = function(a, i) {
  119. // our API but we will use it only to build the require stuffs
  120. var api={};
  121. // taken from WME code. a is [1], so...
  122. 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;
  123. var unknownCount=0;
  124. var classname, funcStr;
  125. // copy i in e and keep a link from classname to index in e
  126. for (o in i){
  127. WMEAPI.e[o] = i[o];
  128. funcStr = i[o].toString();
  129. classname = funcStr.match(/CLASS_NAME:\"([^\"]*)\"/);
  130. if (classname){
  131. // keep the link.
  132. api[classname[1].replace(/\./g,'/').replace(/^W\//, 'Waze/')]={index: o, func: WMEAPI.e[o]};
  133. }
  134. else{
  135. api['Waze/Unknown/' + unknownCount]={index: o, func: WMEAPI.e[o]};
  136. unknownCount++;
  137. }
  138. }
  139. // taken from WME code: it calls the original webpackJsonp and do something else, but I don't really know what.
  140. // removed the call to the original webpackJsonp: still works...
  141. //for (tmp && tmp(a, i); l.length;) l.shift().call(null, t);
  142. for (; l.length;) l.shift().call(null, WMEAPI.t);
  143. WMEAPI.s[0] = 0;
  144. // run the first func of WME. This first func will call recusrsively all funcs needed to setup the API.
  145. // After this call, s will contain all instanciables classes.
  146. //var ret = WMEAPI.t(0);
  147. // now, build the requires thanks to the link we've built in var api.
  148. var module={};
  149. var apiFuncName;
  150. unknownCount=0;
  151. for (o in i){
  152. funcStr = i[o].toString();
  153. classname = funcStr.match(/CLASS_NAME:\"([^\"]*)\"/);
  154. if (classname){
  155. module={};
  156. apiFuncName = classname[1].replace(/\./g,'/').replace(/^W\//, 'Waze/');
  157. module[apiFuncName]=WMEAPI.t(api[apiFuncName].index);
  158. WMEAPI.require.define(module);
  159. }
  160. else{
  161. var matches = funcStr.match(/SEGMENT:"segment",/);
  162. if (matches){
  163. module={};
  164. apiFuncName='Waze/Model/ObjectType';
  165. module[apiFuncName]=WMEAPI.t(api['Waze/Unknown/' + unknownCount].index);
  166. WMEAPI.require.define(module);
  167. }
  168. unknownCount++;
  169. }
  170. }
  171.  
  172. // restore the original func
  173. window.webpackJsonp=WMEAPI.tmp;
  174.  
  175. // set the require public if needed
  176. // if so: others scripts must wait for the window.require to be available before using it.
  177. window.require = WMEAPI.require;
  178. // all available functions are in WMEAPI.require.define.modules
  179. // console.debug this variable to read it:
  180. // console.debug('Modules: ', WMEAPI.require.define.modules);
  181. // run your script here:
  182. // setTimeout(yourscript);
  183. // again taken from WME code. Not sure about what it does.
  184. //if (i[0]) return ret;
  185. };
  186.  
  187. // some kind of global vars and init
  188. WMEAPI.s = {};
  189. WMEAPI.r = {
  190. 0: 0
  191. };
  192.  
  193. // hacking finished
  194.  
  195. // load again WME through our patched func
  196. WMEAPI.WMEHACK_Injected_script = document.createElement("script");
  197. WMEAPI.WMEHACK_Injected_script.setAttribute("type", "application/javascript");
  198. WMEAPI.WMEHACK_Injected_script.src = WMEAPI.url;
  199. document.body.appendChild(WMEAPI.WMEHACK_Injected_script);
  200. console.log("d2 fix complete");
  201. }
  202.  
  203. function Geometry(){
  204. //var geometry = WazeWrap.Geometry;
  205.  
  206. //Converts to "normal" GPS coordinates
  207. this.ConvertTo4326 = function (long, lat){
  208. var projI=new OpenLayers.Projection("EPSG:900913");
  209. var projE=new OpenLayers.Projection("EPSG:4326");
  210. return (new OpenLayers.LonLat(long, lat)).transform(projI,projE);
  211. };
  212. this.ConvertTo900913 = function (long, lat){
  213. var projI=new OpenLayers.Projection("EPSG:900913");
  214. var projE=new OpenLayers.Projection("EPSG:4326");
  215. return (new OpenLayers.LonLat(long, lat)).transform(projE,projI);
  216. };
  217.  
  218. //Converts the Longitudinal offset to an offset in 4326 gps coordinates
  219. this.CalculateLongOffsetGPS = function(longMetersOffset, long, lat)
  220. {
  221. var R= 6378137; //Earth's radius
  222. var dLon = longMetersOffset / (R * Math.cos(Math.PI * lat / 180)); //offset in radians
  223. var lon0 = dLon * (180 / Math.PI); //offset degrees
  224.  
  225. return lon0;
  226. };
  227.  
  228. //Converts the Latitudinal offset to an offset in 4326 gps coordinates
  229. this.CalculateLatOffsetGPS = function(latMetersOffset, lat)
  230. {
  231. var R= 6378137; //Earth's radius
  232. var dLat = latMetersOffset/R;
  233. var lat0 = dLat * (180 /Math.PI); //offset degrees
  234.  
  235. return lat0;
  236. };
  237. this.isLonLatInMapExtent = function (lonLat) {
  238. 'use strict';
  239. return lonLat && W.map.getExtent().containsLonLat(lonLat);
  240. };
  241. this.isGeometryInMapExtent = function (geometry) {
  242. 'use strict';
  243. return geometry && geometry.getBounds &&
  244. W.map.getExtent().intersectsBounds(geometry.getBounds());
  245. };
  246. };
  247.  
  248. function Model(){
  249. //var model = WazeWrap.Model;
  250.  
  251. this.getPrimaryStreetID = function(segmentID){
  252. return W.model.segments.get(segmentID).attributes.primaryStreetID;
  253. };
  254.  
  255. this.getStreetName = function(primaryStreetID){
  256. return W.model.streets.get(PrimaryStreetID).name;
  257. };
  258.  
  259. this.getCityID = function(primaryStreetID){
  260. return W.model.streets.get(primaryStreetID).cityID;
  261. };
  262.  
  263. this.getCityName = function(primaryStreetID){
  264. return W.model.cities.get(this.getCityID(primaryStreetID)).attributes.Name;
  265. };
  266.  
  267. this.getStateName = function(primaryStreetID){
  268. return W.model.states.get(getStateID(primaryStreetID)).Name;
  269. };
  270.  
  271. this.getStateID = function(primaryStreetID){
  272. return W.model.cities.get(primaryStreetID).attributes.stateID;
  273. };
  274.  
  275. this.getCountryID = function(primaryStreetID){
  276. return W.model.cities.get(this.getCityID(primaryStreetID)).attributes.CountryID;
  277. };
  278.  
  279. this.getCountryName = function(primaryStreetID){
  280. return W.model.countries.get(getCountryID(primaryStreetID)).name;
  281. };
  282.  
  283. this.getCityNameFromSegmentObj = function(segObj){
  284. return this.getCityName(segObj.attributes.primaryStreetID);
  285. };
  286.  
  287. this.getStateNameFromSegmentObj = function(segObj){
  288. return this.getStateName(segObj.attributes.primaryStreetID);
  289. };
  290.  
  291. //returns an array of segmentIDs for all segments that are part of the same roundabout as the passed segment
  292. this.getAllRoundaboutSegmentsFromObj = function(segObj){
  293. if(segObj.model.attributes.junctionID === null)
  294. return null;
  295.  
  296. return W.model.junctions.objects[segObj.model.attributes.junctionID].segIDs;
  297. };
  298.  
  299. this.getAllRoundaboutJunctionNodesFromObj = function(segObj){
  300. var RASegs = this.getAllRoundaboutSegmentsFromObj(segObj);
  301. var RAJunctionNodes = [];
  302. for(i=0; i< RASegs.length; i++){
  303. RAJunctionNodes.push(W.model.nodes.objects[W.model.segments.get(RASegs[i]).attributes.toNodeID]);
  304.  
  305. }
  306. return RAJunctionNodes;
  307. };
  308.  
  309. this.isRoundaboutSegmentID = function(segmentID){
  310. if(W.model.segments.get(segmentID).attributes.junctionID === null)
  311. return false;
  312. else
  313. return true;
  314. };
  315.  
  316. this.isRoundaboutSegmentObj = function(segObj){
  317. if(segObj.model.attributes.junctionID === null)
  318. return false;
  319. else
  320. return true;
  321. };
  322.  
  323. /**
  324. * Defers execution of a callback function until the WME map and data
  325. * model are ready. Call this function before calling a function that
  326. * causes a map and model reload, such as W.map.moveTo(). After the
  327. * move is completed the callback function will be executed.
  328. * @function WazeWrap.Model.onModelReady
  329. * @param {Function} callback The callback function to be executed.
  330. * @param {Boolean} now Whether or not to call the callback now if the
  331. * model is currently ready.
  332. * @param {Object} context The context in which to call the callback.
  333. */
  334. this.onModelReady = function (callback, now, context) {
  335. var deferModelReady = function () {
  336. return $.Deferred(function (dfd) {
  337. var resolve = function () {
  338. dfd.resolve();
  339. W.model.events.unregister('mergeend', null, resolve);
  340. };
  341. W.model.events.register('mergeend', null, resolve);
  342. }).promise();
  343. };
  344. var deferMapReady = function () {
  345. return $.Deferred(function (dfd) {
  346. var resolve = function () {
  347. dfd.resolve();
  348. W.vent.off('operationDone', resolve);
  349. };
  350. W.vent.on('operationDone', resolve);
  351. }).promise();
  352. };
  353.  
  354. if (typeof callback === 'function') {
  355. context = context || callback;
  356. if (now && WazeWrap.Util.mapReady() && WazeWrap.Util.modelReady()) {
  357. callback.call(context);
  358. } else {
  359. $.when(deferMapReady() && deferModelReady()).
  360. then(function () {
  361. callback.call(context);
  362. });
  363. }
  364. }
  365. };
  366. };
  367. function User(){
  368. this.Rank = function(){
  369. return W.loginManager.user.normalizedLevel;
  370. };
  371.  
  372. this.Username = function(){
  373. return W.loginManager.user.userName;
  374. };
  375.  
  376. this.isCM = function(){
  377. if(W.loginManager.user.editableCountryIDs.length > 0)
  378. return true;
  379. else
  380. return false;
  381. };
  382. this.isAM = function(){
  383. return W.loginManager.user.isAreaManager;
  384. };
  385. };
  386. function Util(){
  387. /**
  388. * Function to defer function execution until an element is present on
  389. * the page.
  390. * @function WazeWrap.Util.waitForElement
  391. * @param {String} selector The CSS selector string or a jQuery object
  392. * to find before executing the callback.
  393. * @param {Function} callback The function to call when the page
  394. * element is detected.
  395. * @param {Object} [context] The context in which to call the callback.
  396. */
  397. this.waitForElement = function (selector, callback, context) {
  398. var jqObj;
  399.  
  400. if (!selector || typeof callback !== 'function') {
  401. return;
  402. }
  403.  
  404. jqObj = typeof selector === 'string' ?
  405. $(selector) : selector instanceof $ ? selector : null;
  406.  
  407. if (!jqObj.size()) {
  408. window.requestAnimationFrame(function () {
  409. WazeWrap.Util.waitForElement(selector, callback, context);
  410. });
  411. } else {
  412. callback.call(context || callback);
  413. }
  414. };
  415.  
  416. /**
  417. * Function to track the ready state of the map.
  418. * @function WazeWrap.Util.mapReady
  419. * @return {Boolean} Whether or not a map operation is pending or
  420. * undefined if the function has not yet seen a map ready event fired.
  421. */
  422. this.mapReady = function () {
  423. var mapReady = true;
  424. W.vent.on('operationPending', function () {
  425. mapReady = false;
  426. });
  427. W.vent.on('operationDone', function () {
  428. mapReady = true;
  429. });
  430. return function () {
  431. return mapReady;
  432. };
  433. } ();
  434.  
  435. /**
  436. * Function to track the ready state of the model.
  437. * @function WazeWrap.Util.modelReady
  438. * @return {Boolean} Whether or not the model has loaded objects or
  439. * undefined if the function has not yet seen a model ready event fired.
  440. */
  441. this.modelReady = function () {
  442. var modelReady = true;
  443. W.model.events.register('mergestart', null, function () {
  444. modelReady = false;
  445. });
  446. W.model.events.register('mergeend', null, function () {
  447. modelReady = true;
  448. });
  449. return function () {
  450. return modelReady;
  451. };
  452. } ();
  453. };
  454.  
  455. function Interface() {
  456. /**
  457. * Generates id for message bars.
  458. * @private
  459. */
  460. var getNextID = function () {
  461. var id = 1;
  462. return function () {
  463. return id++;
  464. };
  465. } ();
  466. this.Shortcut = OL.Class(this, /** @lends WazeWrap.Interface.Shortcut.prototype */ {
  467. name: null,
  468. group: null,
  469. shortcut: {},
  470. callback: null,
  471. scope: null,
  472. groupExists: false,
  473. actionExists: false,
  474. eventExists: false,
  475. defaults: {
  476. group: 'default'
  477. },
  478. /**
  479. * Creates a new {WazeWrap.Interface.Shortcut}.
  480. * @class
  481. * @name WazeWrap.Interface.Shortcut
  482. * @param name {String} The name of the shortcut.
  483. * @param group {String} The name of the shortcut group.
  484. * @param shortcut {String} The shortcut key(s). The shortcut
  485. * should be of the form 'i' where i is the keyboard shortuct or
  486. * include modifier keys such as 'CSA+i', where C = the control
  487. * key, S = the shift key, A = the alt key, and i = the desired
  488. * keyboard shortcut. The modifier keys are optional.
  489. * @param callback {Function} The function to be called by the
  490. * shortcut.
  491. * @param scope {Object} The object to be used as this by the
  492. * callback.
  493. * @return {WazeWrap.Interface.Shortcut} The new shortcut object.
  494. * @example //Creates new shortcut and adds it to the map.
  495. * shortcut = new WazeWrap.Interface.Shortcut('myName', 'myGroup', 'C+p', callbackFunc, null).add();
  496. */
  497. initialize: function (name, group, shortcut, callback, scope) {
  498. if ('string' === typeof name && name.length > 0 &&
  499. 'string' === typeof shortcut && shortcut.length > 0 &&
  500. 'function' === typeof callback) {
  501. this.name = name;
  502. this.group = group || this.defaults.group;
  503. this.callback = callback;
  504. this.shortcut[shortcut] = name;
  505. if ('object' !== typeof scope) {
  506. this.scope = null;
  507. } else {
  508. this.scope = scope;
  509. }
  510. return this;
  511. }
  512. },
  513. /**
  514. * Determines if the shortcut's group already exists.
  515. * @private
  516. */
  517. doesGroupExist: function () {
  518. this.groupExists = 'undefined' !== typeof W.accelerators.Groups[this.group] &&
  519. undefined !== typeof W.accelerators.Groups[this.group].members &&
  520. W.accelerators.Groups[this.group].length > 0;
  521. return this.groupExists;
  522. },
  523. /**
  524. * Determines if the shortcut's action already exists.
  525. * @private
  526. */
  527. doesActionExist: function () {
  528. this.actionExists = 'undefined' !== typeof W.accelerators.Actions[this.name];
  529. return this.actionExists;
  530. },
  531. /**
  532. * Determines if the shortcut's event already exists.
  533. * @private
  534. */
  535. doesEventExist: function () {
  536. this.eventExists = 'undefined' !== typeof W.accelerators.events.listeners[this.name] &&
  537. W.accelerators.events.listeners[this.name].length > 0 &&
  538. this.callback === W.accelerators.events.listeners[this.name][0].func &&
  539. this.scope === W.accelerators.events.listeners[this.name][0].obj;
  540. return this.eventExists;
  541. },
  542. /**
  543. * Creates the shortcut's group.
  544. * @private
  545. */
  546. createGroup: function () {
  547. W.accelerators.Groups[this.group] = [];
  548. W.accelerators.Groups[this.group].members = [];
  549. },
  550. /**
  551. * Registers the shortcut's action.
  552. * @private
  553. */
  554. addAction: function () {
  555. W.accelerators.addAction(this.name, { group: this.group });
  556. },
  557. /**
  558. * Registers the shortcut's event.
  559. * @private
  560. */
  561. addEvent: function () {
  562. W.accelerators.events.register(this.name, this.scope, this.callback);
  563. },
  564. /**
  565. * Registers the shortcut's keyboard shortcut.
  566. * @private
  567. */
  568. registerShortcut: function () {
  569. W.accelerators._registerShortcuts(this.shortcut);
  570. },
  571. /**
  572. * Adds the keyboard shortcut to the map.
  573. * @return {WazeWrap.Interface.Shortcut} The keyboard shortcut.
  574. */
  575. add: function () {
  576. /* If the group is not already defined, initialize the group. */
  577. if (!this.doesGroupExist()) {
  578. this.createGroup();
  579. }
  580.  
  581. /* Clear existing actions with same name */
  582. if (this.doesActionExist()) {
  583. W.accelerators.Actions[this.name] = null;
  584. }
  585. this.addAction();
  586.  
  587. /* Register event only if it's not already registered */
  588. if (!this.doesEventExist()) {
  589. this.addEvent();
  590. }
  591.  
  592. /* Finally, register the shortcut. */
  593. this.registerShortcut();
  594. return this;
  595. },
  596. /**
  597. * Removes the keyboard shortcut from the map.
  598. * @return {WazeWrap.Interface.Shortcut} The keyboard shortcut.
  599. */
  600. remove: function () {
  601. if (this.doesEventExist()) {
  602. W.accelerators.events.unregister(this.name, this.scope, this.callback);
  603. }
  604. if (this.doesActionExist()) {
  605. delete W.accelerators.Actions[this.name];
  606. }
  607. //remove shortcut?
  608. return this;
  609. },
  610. /**
  611. * Changes the keyboard shortcut and applies changes to the map.
  612. * @return {WazeWrap.Interface.Shortcut} The keyboard shortcut.
  613. */
  614. change: function (shortcut) {
  615. if (shortcut) {
  616. this.shortcut = {};
  617. this.shortcut[shortcut] = this.name;
  618. this.registerShortcut();
  619. }
  620. return this;
  621. }
  622. }),
  623.  
  624. this.Tab = OL.Class(this, {
  625. /** @lends WazeWrap.Interface.Tab */
  626. TAB_SELECTOR: '#user-tabs ul.nav-tabs',
  627. CONTENT_SELECTOR: '#user-info div.tab-content',
  628. callback: null,
  629. $content: null,
  630. context: null,
  631. $tab: null,
  632. /**
  633. * Creates a new WazeWrap.Interface.Tab. The tab is appended to the WME
  634. * editor sidebar and contains the passed HTML content.
  635. * @class
  636. * @name WazeWrap.Interface.Tab
  637. * @param {String} name The name of the tab. Should not contain any
  638. * special characters.
  639. * @param {String} content The HTML content of the tab.
  640. * @param {Function} [callback] A function to call upon successfully
  641. * appending the tab.
  642. * @param {Object} [context] The context in which to call the callback
  643. * function.
  644. * @return {WazeWrap.Interface.Tab} The new tab object.
  645. * @example //Creates new tab and adds it to the page.
  646. * new WazeWrap.Interface.Tab('thebestscriptever', '<div>Hello World!</div>');
  647. */
  648. initialize: function (name, content, callback, context) {
  649. var idName, i = 0;
  650. if (name && 'string' === typeof name &&
  651. content && 'string' === typeof content) {
  652. if (callback && 'function' === typeof callback) {
  653. this.callback = callback;
  654. this.context = context || callback;
  655. }
  656. /* Sanitize name for html id attribute */
  657. idName = name.toLowerCase().replace(/[^a-z-_]/g, '');
  658. /* Make sure id will be unique on page */
  659. while (
  660. $('#sidepanel-' + (i ? idName + i : idName)).length > 0) {
  661. i++;
  662. }
  663. if (i) {
  664. idName = idName + i;
  665. }
  666. /* Create tab and content */
  667. this.$tab = $('<li/>')
  668. .append($('<a/>')
  669. .attr({
  670. 'href': '#sidepanel-' + idName,
  671. 'data-toggle': 'tab',
  672. })
  673. .text(name));
  674. this.$content = $('<div/>')
  675. .addClass('tab-pane')
  676. .attr('id', 'sidepanel-' + idName)
  677. .html(content);
  678.  
  679. this.appendTab();
  680. }
  681. },
  682.  
  683. append: function (content) {
  684. this.$content.append(content);
  685. },
  686.  
  687. appendTab: function () {
  688. WazeWrap.Util.waitForElement(
  689. this.TAB_SELECTOR + ',' + this.CONTENT_SELECTOR,
  690. function () {
  691. $(this.TAB_SELECTOR).append(this.$tab);
  692. $(this.CONTENT_SELECTOR).first().append(this.$content);
  693. if (this.callback) {
  694. this.callback.call(this.context);
  695. }
  696. }, this);
  697. },
  698.  
  699. clearContent: function () {
  700. this.$content.empty();
  701. },
  702.  
  703. destroy: function () {
  704. this.$tab.remove();
  705. this.$content.remove();
  706. }
  707. });
  708. };
  709.  
  710. }.call(this));

QingJ © 2025

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