Merge branch 'menu-command-api' of github.com:jonnytest1/workadventure into metadataScriptingApi
This commit is contained in:
commit
ce0a72c6ce
@ -5,6 +5,8 @@ import type { ChatEvent } from './ChatEvent';
|
|||||||
import type { ClosePopupEvent } from './ClosePopupEvent';
|
import type { ClosePopupEvent } from './ClosePopupEvent';
|
||||||
import type { EnterLeaveEvent } from './EnterLeaveEvent';
|
import type { EnterLeaveEvent } from './EnterLeaveEvent';
|
||||||
import type { GoToPageEvent } from './GoToPageEvent';
|
import type { GoToPageEvent } from './GoToPageEvent';
|
||||||
|
import type { MenuItemClickedEvent } from './MenuItemClickedEvent';
|
||||||
|
import type { MenuItemRegisterEvent } from './MenuItemRegisterEvent';
|
||||||
import type { HasPlayerMovedEvent } from './HasPlayerMovedEvent';
|
import type { HasPlayerMovedEvent } from './HasPlayerMovedEvent';
|
||||||
import type { OpenCoWebSiteEvent } from './OpenCoWebSiteEvent';
|
import type { OpenCoWebSiteEvent } from './OpenCoWebSiteEvent';
|
||||||
import type { OpenPopupEvent } from './OpenPopupEvent';
|
import type { OpenPopupEvent } from './OpenPopupEvent';
|
||||||
@ -21,6 +23,7 @@ export interface TypedMessageEvent<T> extends MessageEvent {
|
|||||||
export type IframeEventMap = {
|
export type IframeEventMap = {
|
||||||
getState: GameStateEvent,
|
getState: GameStateEvent,
|
||||||
// updateTile: UpdateTileEvent
|
// updateTile: UpdateTileEvent
|
||||||
|
registerMenuCommand: MenuItemRegisterEvent
|
||||||
chat: ChatEvent,
|
chat: ChatEvent,
|
||||||
openPopup: OpenPopupEvent
|
openPopup: OpenPopupEvent
|
||||||
closePopup: ClosePopupEvent
|
closePopup: ClosePopupEvent
|
||||||
@ -56,6 +59,7 @@ export interface IframeResponseEventMap {
|
|||||||
gameState: GameStateEvent
|
gameState: GameStateEvent
|
||||||
hasPlayerMoved: HasPlayerMovedEvent
|
hasPlayerMoved: HasPlayerMovedEvent
|
||||||
dataLayer: DataLayerEvent
|
dataLayer: DataLayerEvent
|
||||||
|
menuItemClicked: MenuItemClickedEvent
|
||||||
}
|
}
|
||||||
export interface IframeResponseEvent<T extends keyof IframeResponseEventMap> {
|
export interface IframeResponseEvent<T extends keyof IframeResponseEventMap> {
|
||||||
type: T;
|
type: T;
|
||||||
|
10
front/src/Api/Events/MenuItemClickedEvent.ts
Normal file
10
front/src/Api/Events/MenuItemClickedEvent.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isMenuItemClickedEvent =
|
||||||
|
new tg.IsInterface().withProperties({
|
||||||
|
menuItem: tg.isString
|
||||||
|
}).get();
|
||||||
|
/**
|
||||||
|
* A message sent from the game to the iFrame when a menu item is clicked.
|
||||||
|
*/
|
||||||
|
export type MenuItemClickedEvent = tg.GuardedType<typeof isMenuItemClickedEvent>;
|
10
front/src/Api/Events/MenuItemRegisterEvent.ts
Normal file
10
front/src/Api/Events/MenuItemRegisterEvent.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isMenuItemRegisterEvent =
|
||||||
|
new tg.IsInterface().withProperties({
|
||||||
|
menutItem: tg.isString
|
||||||
|
}).get();
|
||||||
|
/**
|
||||||
|
* A message sent from the iFrame to the game to add a new menu item.
|
||||||
|
*/
|
||||||
|
export type MenuItemRegisterEvent = tg.GuardedType<typeof isMenuItemRegisterEvent>;
|
@ -17,7 +17,8 @@ import type { GameStateEvent } from './Events/GameStateEvent';
|
|||||||
import type { HasPlayerMovedEvent } from './Events/HasPlayerMovedEvent';
|
import type { HasPlayerMovedEvent } from './Events/HasPlayerMovedEvent';
|
||||||
import { Math } from 'phaser';
|
import { Math } from 'phaser';
|
||||||
import type { DataLayerEvent } from "./Events/DataLayerEvent";
|
import type { DataLayerEvent } from "./Events/DataLayerEvent";
|
||||||
|
import { isMenuItemRegisterEvent } from './Events/MenuItemRegisterEvent';
|
||||||
|
import type { MenuItemClickedEvent } from './Events/MenuItemClickedEvent';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,6 +75,8 @@ class IframeListener {
|
|||||||
private readonly _dataLayerChangeStream: Subject<void> = new Subject();
|
private readonly _dataLayerChangeStream: Subject<void> = new Subject();
|
||||||
public readonly dataLayerChangeStream = this._dataLayerChangeStream.asObservable();
|
public readonly dataLayerChangeStream = this._dataLayerChangeStream.asObservable();
|
||||||
|
|
||||||
|
private readonly _registerMenuCommandStream: Subject<string> = new Subject();
|
||||||
|
public readonly registerMenuCommandStream = this._registerMenuCommandStream.asObservable();
|
||||||
private readonly iframes = new Set<HTMLIFrameElement>();
|
private readonly iframes = new Set<HTMLIFrameElement>();
|
||||||
private readonly scripts = new Map<string, HTMLIFrameElement>();
|
private readonly scripts = new Map<string, HTMLIFrameElement>();
|
||||||
private sendPlayerMove: boolean = false;
|
private sendPlayerMove: boolean = false;
|
||||||
@ -140,6 +143,8 @@ class IframeListener {
|
|||||||
this.sendPlayerMove = true
|
this.sendPlayerMove = true
|
||||||
} else if (payload.type == "getDataLayer") {
|
} else if (payload.type == "getDataLayer") {
|
||||||
this._dataLayerChangeStream.next();
|
this._dataLayerChangeStream.next();
|
||||||
|
} else if (payload.type == "registerMenuCommand" && isMenuItemRegisterEvent(payload.data)) {
|
||||||
|
this._registerMenuCommandStream.next(payload.data.menutItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
@ -237,6 +242,15 @@ class IframeListener {
|
|||||||
this.scripts.delete(scriptUrl);
|
this.scripts.delete(scriptUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendMenuClickedEvent(menuItem: string) {
|
||||||
|
this.postMessage({
|
||||||
|
'type': 'menuItemClicked',
|
||||||
|
'data': {
|
||||||
|
menuItem: menuItem,
|
||||||
|
} as MenuItemClickedEvent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
sendUserInputChat(message: string) {
|
sendUserInputChat(message: string) {
|
||||||
this.postMessage({
|
this.postMessage({
|
||||||
'type': 'userInputChat',
|
'type': 'userInputChat',
|
||||||
|
@ -137,8 +137,8 @@ export class GameMap {
|
|||||||
public findPhaserLayer(layerName: string): TilemapLayer | undefined {
|
public findPhaserLayer(layerName: string): TilemapLayer | undefined {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let found = false;
|
let found = false;
|
||||||
while (!found && i<this.flatLayers.length) {
|
while (!found && i<this.phaserLayers.length) {
|
||||||
if (this.flatLayers[i].name === layerName) {
|
if (this.phaserLayers[i].layer.name === layerName) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -90,9 +90,11 @@ import { TextUtils } from "../Components/TextUtils";
|
|||||||
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
||||||
import { PinchManager } from "../UserInput/PinchManager";
|
import { PinchManager } from "../UserInput/PinchManager";
|
||||||
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
||||||
|
import { MenuScene, MenuSceneName } from '../Menu/MenuScene';
|
||||||
import {waScaleManager } from "../Services/WaScaleManager";
|
import {waScaleManager } from "../Services/WaScaleManager";
|
||||||
import type { HasPlayerMovedEvent } from '../../Api/Events/HasPlayerMovedEvent';
|
import type { HasPlayerMovedEvent } from '../../Api/Events/HasPlayerMovedEvent';
|
||||||
|
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null,
|
initPosition: PointInterface | null,
|
||||||
reconnecting: boolean
|
reconnecting: boolean
|
||||||
@ -884,10 +886,12 @@ ${escapedMessage}
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this.iframeSubscriptionList.push(iframeListener.showLayerStream.subscribe((layerEvent)=>{
|
this.iframeSubscriptionList.push(iframeListener.showLayerStream.subscribe((layerEvent)=>{
|
||||||
|
console.log('show');
|
||||||
this.setLayerVisibility(layerEvent.name, true);
|
this.setLayerVisibility(layerEvent.name, true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.iframeSubscriptionList.push(iframeListener.hideLayerStream.subscribe((layerEvent)=>{
|
this.iframeSubscriptionList.push(iframeListener.hideLayerStream.subscribe((layerEvent)=>{
|
||||||
|
console.log('hide');
|
||||||
this.setLayerVisibility(layerEvent.name, false);
|
this.setLayerVisibility(layerEvent.name, false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -917,16 +921,12 @@ ${escapedMessage}
|
|||||||
}
|
}
|
||||||
|
|
||||||
private setLayerVisibility(layerName: string, visible: boolean): void {
|
private setLayerVisibility(layerName: string, visible: boolean): void {
|
||||||
const phaserlayer = this.gameMap.findPhaserLayer(layerName);
|
const phaserLayer = this.gameMap.findPhaserLayer(layerName);
|
||||||
if (phaserlayer === undefined) {
|
if (phaserLayer === undefined) {
|
||||||
console.warn('Could not find layer "' + layerName + '" when calling WA.hideLayer / WA.showLayer');
|
console.warn('Could not find layer "' + layerName + '" when calling WA.hideLayer / WA.showLayer');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(phaserlayer.type != "tilelayer"){
|
phaserLayer.setVisible(visible);
|
||||||
console.warn('The layer "' + layerName + '" is not a tilelayer. It can not be show/hide');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
phaserlayer.setVisible(visible);
|
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -941,6 +941,8 @@ ${escapedMessage}
|
|||||||
const {roomId, hash} = Room.getIdFromIdentifier(exitKey, this.MapUrlFile, this.instance);
|
const {roomId, hash} = Room.getIdFromIdentifier(exitKey, this.MapUrlFile, this.instance);
|
||||||
if (!roomId) throw new Error('Could not find the room from its exit key: '+exitKey);
|
if (!roomId) throw new Error('Could not find the room from its exit key: '+exitKey);
|
||||||
urlManager.pushStartLayerNameToUrl(hash);
|
urlManager.pushStartLayerNameToUrl(hash);
|
||||||
|
const menuScene: MenuScene = this.scene.get(MenuSceneName) as MenuScene
|
||||||
|
menuScene.reset()
|
||||||
if (roomId !== this.scene.key) {
|
if (roomId !== this.scene.key) {
|
||||||
if (this.scene.get(roomId) === null) {
|
if (this.scene.get(roomId) === null) {
|
||||||
console.error("next room not loaded", exitKey);
|
console.error("next room not loaded", exitKey);
|
||||||
|
@ -10,6 +10,9 @@ import {GameConnexionTypes} from "../../Url/UrlManager";
|
|||||||
import {WarningContainer, warningContainerHtml, warningContainerKey} from "../Components/WarningContainer";
|
import {WarningContainer, warningContainerHtml, warningContainerKey} from "../Components/WarningContainer";
|
||||||
import {worldFullWarningStream} from "../../Connexion/WorldFullWarningStream";
|
import {worldFullWarningStream} from "../../Connexion/WorldFullWarningStream";
|
||||||
import {menuIconVisible} from "../../Stores/MenuStore";
|
import {menuIconVisible} from "../../Stores/MenuStore";
|
||||||
|
import { HtmlUtils } from '../../WebRtc/HtmlUtils';
|
||||||
|
import { iframeListener } from '../../Api/IframeListener';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
export const MenuSceneName = 'MenuScene';
|
export const MenuSceneName = 'MenuScene';
|
||||||
const gameMenuKey = 'gameMenu';
|
const gameMenuKey = 'gameMenu';
|
||||||
@ -36,12 +39,17 @@ export class MenuScene extends Phaser.Scene {
|
|||||||
private menuButton!: Phaser.GameObjects.DOMElement;
|
private menuButton!: Phaser.GameObjects.DOMElement;
|
||||||
private warningContainer: WarningContainer | null = null;
|
private warningContainer: WarningContainer | null = null;
|
||||||
private warningContainerTimeout: NodeJS.Timeout | null = null;
|
private warningContainerTimeout: NodeJS.Timeout | null = null;
|
||||||
|
private subscriptions = new Subscription()
|
||||||
constructor() {
|
constructor() {
|
||||||
super({key: MenuSceneName});
|
super({key: MenuSceneName});
|
||||||
|
|
||||||
this.gameQualityValue = localUserStore.getGameQualityValue();
|
this.gameQualityValue = localUserStore.getGameQualityValue();
|
||||||
this.videoQualityValue = localUserStore.getVideoQualityValue();
|
this.videoQualityValue = localUserStore.getVideoQualityValue();
|
||||||
|
|
||||||
|
this.subscriptions.add(iframeListener.registerMenuCommandStream.subscribe(menuCommand => {
|
||||||
|
this.addMenuOption(menuCommand);
|
||||||
|
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
preload () {
|
preload () {
|
||||||
@ -53,6 +61,13 @@ export class MenuScene extends Phaser.Scene {
|
|||||||
this.load.html(warningContainerKey, warningContainerHtml);
|
this.load.html(warningContainerKey, warningContainerHtml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
const addedMenuItems=[...this.menuElement.node.querySelectorAll(".fromApi")];
|
||||||
|
for(let index=addedMenuItems.length-1;index>=0;index--){
|
||||||
|
addedMenuItems[index].remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
menuIconVisible.set(true);
|
menuIconVisible.set(true);
|
||||||
this.menuElement = this.add.dom(closedSideMenuX, 30).createFromCache(gameMenuKey);
|
this.menuElement = this.add.dom(closedSideMenuX, 30).createFromCache(gameMenuKey);
|
||||||
@ -268,13 +283,30 @@ export class MenuScene extends Phaser.Scene {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addMenuOption(menuText: string) {
|
||||||
|
const wrappingSection = document.createElement("section")
|
||||||
|
const excapedHtml = HtmlUtils.escapeHtml(menuText);
|
||||||
|
wrappingSection.innerHTML = `<button class="fromApi" id="${excapedHtml}">${excapedHtml}</button>`
|
||||||
|
const menuItemContainer = this.menuElement.node.querySelector("#gameMenu main");
|
||||||
|
if (menuItemContainer) {
|
||||||
|
menuItemContainer.querySelector(`#${excapedHtml}.fromApi`)?.remove()
|
||||||
|
menuItemContainer.insertBefore(wrappingSection, menuItemContainer.querySelector("#socialLinks"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private onMenuClick(event: MouseEvent) {
|
private onMenuClick(event: MouseEvent) {
|
||||||
if((event?.target as HTMLInputElement).classList.contains('not-button')){
|
const htmlMenuItem = (event?.target as HTMLInputElement);
|
||||||
|
if (htmlMenuItem.classList.contains('not-button')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
switch ((event?.target as HTMLInputElement).id) {
|
if (htmlMenuItem.classList.contains("fromApi")) {
|
||||||
|
iframeListener.sendMenuClickedEvent(htmlMenuItem.id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (htmlMenuItem.id) {
|
||||||
case 'changeNameButton':
|
case 'changeNameButton':
|
||||||
this.closeSideMenu();
|
this.closeSideMenu();
|
||||||
gameManager.leaveGame(this, LoginSceneName, new LoginScene());
|
gameManager.leaveGame(this, LoginSceneName, new LoginScene());
|
||||||
|
@ -15,6 +15,8 @@ import { GameStateEvent, isGameStateEvent } from './Api/Events/GameStateEvent';
|
|||||||
import { HasPlayerMovedEvent, HasPlayerMovedEventCallback, isHasPlayerMovedEvent } from './Api/Events/HasPlayerMovedEvent';
|
import { HasPlayerMovedEvent, HasPlayerMovedEventCallback, isHasPlayerMovedEvent } from './Api/Events/HasPlayerMovedEvent';
|
||||||
import { DataLayerEvent, isDataLayerEvent } from "./Api/Events/DataLayerEvent";
|
import { DataLayerEvent, isDataLayerEvent } from "./Api/Events/DataLayerEvent";
|
||||||
import type { ITiledMap } from "./Phaser/Map/ITiledMap";
|
import type { ITiledMap } from "./Phaser/Map/ITiledMap";
|
||||||
|
import type { MenuItemRegisterEvent } from "./Api/Events/MenuItemRegisterEvent";
|
||||||
|
import { isMenuItemClickedEvent } from "./Api/Events/MenuItemClickedEvent";
|
||||||
|
|
||||||
interface WorkAdventureApi {
|
interface WorkAdventureApi {
|
||||||
sendChatMessage(message: string, author: string): void;
|
sendChatMessage(message: string, author: string): void;
|
||||||
@ -37,6 +39,7 @@ interface WorkAdventureApi {
|
|||||||
restorePlayerControls(): void;
|
restorePlayerControls(): void;
|
||||||
displayBubble(): void;
|
displayBubble(): void;
|
||||||
removeBubble(): void;
|
removeBubble(): void;
|
||||||
|
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void): void
|
||||||
getMapUrl(): Promise<string>;
|
getMapUrl(): Promise<string>;
|
||||||
getUuid(): Promise<string | undefined>;
|
getUuid(): Promise<string | undefined>;
|
||||||
getRoomId(): Promise<string>;
|
getRoomId(): Promise<string>;
|
||||||
@ -62,7 +65,7 @@ const enterStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subj
|
|||||||
const leaveStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
|
const leaveStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
|
||||||
const popups: Map<number, Popup> = new Map<number, Popup>();
|
const popups: Map<number, Popup> = new Map<number, Popup>();
|
||||||
const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<number, Map<number, ButtonClickedCallback>>();
|
const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<number, Map<number, ButtonClickedCallback>>();
|
||||||
|
const menuCallbacks: Map<string, (command: string) => void> = new Map()
|
||||||
let popupId = 0;
|
let popupId = 0;
|
||||||
interface ButtonDescriptor {
|
interface ButtonDescriptor {
|
||||||
/**
|
/**
|
||||||
@ -308,6 +311,16 @@ window.WA = {
|
|||||||
popups.set(popupId, popup)
|
popups.set(popupId, popup)
|
||||||
return popup;
|
return popup;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void) {
|
||||||
|
menuCallbacks.set(commandDescriptor, callback);
|
||||||
|
window.parent.postMessage({
|
||||||
|
'type': 'registerMenuCommand',
|
||||||
|
'data': {
|
||||||
|
menutItem: commandDescriptor
|
||||||
|
} as MenuItemRegisterEvent
|
||||||
|
}, '*');
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Listen to messages sent by the local user, in the chat.
|
* Listen to messages sent by the local user, in the chat.
|
||||||
*/
|
*/
|
||||||
@ -371,8 +384,12 @@ window.addEventListener('message', message => {
|
|||||||
dataLayerResolver.forEach(resolver => {
|
dataLayerResolver.forEach(resolver => {
|
||||||
resolver(payloadData);
|
resolver(payloadData);
|
||||||
})
|
})
|
||||||
|
} else if (payload.type == "menuItemClicked" && isMenuItemClickedEvent(payload.data)) {
|
||||||
|
const callback = menuCallbacks.get(payload.data.menuItem);
|
||||||
|
if (callback) {
|
||||||
|
callback(payload.data.menuItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
@ -7,16 +7,22 @@
|
|||||||
<button id="sendchat">Send chat message</button>
|
<button id="sendchat">Send chat message</button>
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('sendchat').onclick = () => {
|
document.getElementById('sendchat').onclick = () => {
|
||||||
WA.sendChatMessage('Hello world!', 'Mr Robot');
|
WA.sendChatMessage('Hello world!', 'Mr ROBOT');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div id="chatSent"></div>
|
<div id="chatSent"></div>
|
||||||
<script>
|
<script>
|
||||||
|
let chatbotEnabled=false
|
||||||
|
WA.registerMenuCommand('help', () => {
|
||||||
|
chatbotEnabled=true;
|
||||||
|
WA.sendChatMessage("Bonjour Monsieur/Madame, Comment puis-je vous aider ?", 'Mr Robot');
|
||||||
WA.onChatMessage((message => {
|
WA.onChatMessage((message => {
|
||||||
const chatDiv = document.createElement('p');
|
const chatDiv = document.createElement('p');
|
||||||
chatDiv.innerText = message;
|
chatDiv.innerText = 'Vous avez tapé : ' + message;
|
||||||
document.getElementById('chatSent').append(chatDiv);
|
document.getElementById('chatSent').append(chatDiv);
|
||||||
|
WA.sendChatMessage('Votre message : "' + message + '" a bien ete recu. Merci de bien vouloir patienter pendant son traitement.', 'Mr ROBOT');
|
||||||
}));
|
}));
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<div>
|
<div>
|
||||||
<label for="show/hideLayer">Metadata Layer : </label><input type="checkbox" id="show/hideLayer" name="visible" value="show" checked>
|
<label for="show/hideLayer">Metadata Layer : </label><input type="checkbox" id="show/hideLayer" name="visible" value="show" checked>
|
||||||
@ -30,8 +36,6 @@
|
|||||||
WA.hideLayer('Metadata');
|
WA.hideLayer('Metadata');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
WA.setProperty('start', 'openWebsite', 'https://www.wikipedia.org/');
|
WA.setProperty('start', 'openWebsite', 'https://www.wikipedia.org/');
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
Loading…
Reference in New Issue
Block a user