WebDevice suite
This commit is contained in:
		
							parent
							
								
									212e0151fa
								
							
						
					
					
						commit
						33b57d7e67
					
				| 
						 | 
					@ -5,7 +5,7 @@ process.on('message',data => {
 | 
				
			||||||
    switch(data.type)
 | 
					    switch(data.type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        case "CLIENT_CREATED":{
 | 
					        case "CLIENT_CREATED":{
 | 
				
			||||||
            slog("CLIENT_CREATED");
 | 
					            //slog("CLIENT_CREATED");
 | 
				
			||||||
            let client = new Client();
 | 
					            let client = new Client();
 | 
				
			||||||
            client.isProxy = true;
 | 
					            client.isProxy = true;
 | 
				
			||||||
            client.proxyProcess = data.pid;
 | 
					            client.proxyProcess = data.pid;
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ process.on('message',data => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            data.value = transformDeserialization(data.value, data.typing);
 | 
					            data.value = transformDeserialization(data.value, data.typing);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            slog("CLIENT_UPDATE_PROP");
 | 
					            //slog("CLIENT_UPDATE_PROP");
 | 
				
			||||||
            let client = Client.clients.get(data.uuid);
 | 
					            let client = Client.clients.get(data.uuid);
 | 
				
			||||||
            client[data.name] = data.value;
 | 
					            client[data.name] = data.value;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ process.on('message',data => {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case "CLIENT_DESTROY":{
 | 
					        case "CLIENT_DESTROY":{
 | 
				
			||||||
            slog("CLIENT_DESTROY");
 | 
					            //slog("CLIENT_DESTROY");
 | 
				
			||||||
            if(Client.clients.has(data.uuid))
 | 
					            if(Client.clients.has(data.uuid))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Client.clients.delete(data.uuid);
 | 
					                Client.clients.delete(data.uuid);
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ process.on('message',data => {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case "ROOM_CREATED":{
 | 
					        case "ROOM_CREATED":{
 | 
				
			||||||
            slog("ROOM_CREATED");
 | 
					            //slog("ROOM_CREATED");
 | 
				
			||||||
            let room = Room.fromJSON(data.value);
 | 
					            let room = Room.fromJSON(data.value);
 | 
				
			||||||
            Room.rooms.set(room.id, room);
 | 
					            Room.rooms.set(room.id, room);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -64,13 +64,13 @@ process.on('message',data => {
 | 
				
			||||||
            data.value = transformDeserialization(data.value, data.typing);
 | 
					            data.value = transformDeserialization(data.value, data.typing);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            slog("ROOM_UPDATE_PROP");
 | 
					            //slog("ROOM_UPDATE_PROP");
 | 
				
			||||||
            let room = Room.rooms.get(data.uuid);
 | 
					            let room = Room.rooms.get(data.uuid);
 | 
				
			||||||
            room[data.name] = data.value;
 | 
					            room[data.name] = data.value;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case "ROOM_JOIN_CLIENT":{
 | 
					        case "ROOM_JOIN_CLIENT":{
 | 
				
			||||||
            slog("ROOM_JOIN_CLIENT");
 | 
					            //slog("ROOM_JOIN_CLIENT");
 | 
				
			||||||
            let room = Room.rooms.get(data.uuid);
 | 
					            let room = Room.rooms.get(data.uuid);
 | 
				
			||||||
            let client = Client.clients.get(data.client);
 | 
					            let client = Client.clients.get(data.client);
 | 
				
			||||||
            if(room && client)
 | 
					            if(room && client)
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ process.on('message',data => {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case "ROOM_EJECT_CLIENT":{
 | 
					        case "ROOM_EJECT_CLIENT":{
 | 
				
			||||||
            slog("ROOM_EJECT_CLIENT");
 | 
					            //slog("ROOM_EJECT_CLIENT");
 | 
				
			||||||
            let room = Room.rooms.get(data.uuid);
 | 
					            let room = Room.rooms.get(data.uuid);
 | 
				
			||||||
            let client = Client.clients.get(data.client);
 | 
					            let client = Client.clients.get(data.client);
 | 
				
			||||||
            if(room && client)
 | 
					            if(room && client)
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ process.on('message',data => {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case "ROOM_DESTROY":{
 | 
					        case "ROOM_DESTROY":{
 | 
				
			||||||
            slog("ROOM_DESTROY");
 | 
					            //slog("ROOM_DESTROY");
 | 
				
			||||||
            Room.rooms.delete(data.value);
 | 
					            Room.rooms.delete(data.value);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
import WebRTC from "./WebRTC";
 | 
					import WebRTC from "./WebRTC";
 | 
				
			||||||
import Peer from "./Peer";
 | 
					import Peer from "./Peer";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Deneyseldir kullanılması önerilmez
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export default class P2PFileSender
 | 
					export default class P2PFileSender
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public rtc : RTCPeerConnection;
 | 
					    public rtc : RTCPeerConnection;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ export default class WebRTC
 | 
				
			||||||
        rtcpMuxPolicy:"require",
 | 
					        rtcpMuxPolicy:"require",
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public isPolite() : boolean
 | 
					    private isPolite() : boolean
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let myId = this.peer?.mwse.peer('me').socketId as string;
 | 
					        let myId = this.peer?.mwse.peer('me').socketId as string;
 | 
				
			||||||
        let peerId = this.peer?.socketId as string;
 | 
					        let peerId = this.peer?.socketId as string;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					import "./studio/window.js";
 | 
				
			||||||
 | 
					import { InputDevicesWindow } from "./studio/InputDevices.js";
 | 
				
			||||||
 | 
					import { Rooms } from "./studio/Rooms.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let mwse = new MWSE({
 | 
				
			||||||
 | 
					    endpoint: "ws://localhost:7707"
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mwse.scope(beginEngine);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function beginEngine()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    let me = await mwse.virtualPressure.allocAPIPAddress();
 | 
				
			||||||
 | 
					    $(".network-id").text(me);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.openInputDevicesWindow = () => {
 | 
				
			||||||
 | 
					    InputDevicesWindow.toggle();
 | 
				
			||||||
 | 
					    InputDevicesWindow.bringToFront();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.openRoomsWindow = () => {
 | 
				
			||||||
 | 
					    Rooms.toggle();
 | 
				
			||||||
 | 
					    Rooms.bringToFront();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,86 @@
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8">
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
				
			||||||
 | 
					    <title>MWSE UI 24.3 Studio</title>
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css">
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" />
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <div class="container" style="max-width: 1200px;padding-top: 125px">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <h2 class="text-center">
 | 
				
			||||||
 | 
					            MWSE UI 24.3
 | 
				
			||||||
 | 
					        </h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <h1 class="text-center mb-5 mt-3 text-bold fw-bold">
 | 
				
			||||||
 | 
					            <span>Ağ Adresiniz</span>
 | 
				
			||||||
 | 
					            <span class="text-danger network-id">
 | 
				
			||||||
 | 
					                #.#.#.#
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					        </h1>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div style="position:fixed;left:0;right:0;bottom:0;background-color: rgba(0,0,0,.1);display: flex;flex-direction: row;gap: 5px">
 | 
				
			||||||
 | 
					        <span class="bg-white d-inline-block m-1">
 | 
				
			||||||
 | 
					            <button class="btn btn-outline-primary" onclick="openInputDevicesWindow()">
 | 
				
			||||||
 | 
					                Giriş Aygıtları
 | 
				
			||||||
 | 
					            </button>
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					        <!--span class="bg-white d-inline-block m-1">
 | 
				
			||||||
 | 
					            <button class="btn btn-outline-primary" onclick="openOutputDevicesWindow()">
 | 
				
			||||||
 | 
					                Çıkış Aygıtları
 | 
				
			||||||
 | 
					            </button>
 | 
				
			||||||
 | 
					        </span-->
 | 
				
			||||||
 | 
					        <span class="bg-white d-inline-block m-1">
 | 
				
			||||||
 | 
					            <button class="btn btn-outline-primary" onclick="openRoomsWindow()">
 | 
				
			||||||
 | 
					                Odalar
 | 
				
			||||||
 | 
					            </button>
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					        <span class="bg-white d-inline-block m-1">
 | 
				
			||||||
 | 
					            <button class="btn btn-outline-primary" onclick="openPeersWindow()">
 | 
				
			||||||
 | 
					                Cihazlar
 | 
				
			||||||
 | 
					            </button>
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <script src="https://ws.saqut.com/script"></script>
 | 
				
			||||||
 | 
					    <script src="./core.js" type="module"></script>
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					        html,body{
 | 
				
			||||||
 | 
					            margin: 0;
 | 
				
			||||||
 | 
					            height: 100%;
 | 
				
			||||||
 | 
					            background-image: url(./studio/background.jpg);
 | 
				
			||||||
 | 
					            background-position: center center;
 | 
				
			||||||
 | 
					            background-repeat: no-repeat;
 | 
				
			||||||
 | 
					            background-size: cover;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        *{
 | 
				
			||||||
 | 
					            box-sizing: border-box;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        * {
 | 
				
			||||||
 | 
					            scrollbar-width: thin;
 | 
				
			||||||
 | 
					            scrollbar-color: #7a7a7a #1e1e1e;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *::-webkit-scrollbar {
 | 
				
			||||||
 | 
					            width: 8px;
 | 
				
			||||||
 | 
					            height: 8px;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *::-webkit-scrollbar-track {
 | 
				
			||||||
 | 
					        background: #1e1e1e;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *::-webkit-scrollbar-thumb {
 | 
				
			||||||
 | 
					            background-color: #7a7a7a;
 | 
				
			||||||
 | 
					            border-radius: 8px;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *::-webkit-scrollbar-thumb:hover {
 | 
				
			||||||
 | 
					            background-color: #aaaaaa;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,398 @@
 | 
				
			||||||
 | 
					import DWindow from "./window.js";
 | 
				
			||||||
 | 
					import { AddCell, FilterCell, memory, RemoveCell } from "./sdb.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const InputDevicesWindow = new class InputDevicesWindow extends DWindow{
 | 
				
			||||||
 | 
					    constructor(){
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.initContent();
 | 
				
			||||||
 | 
					        this.headtext.text("Giriş Aygıtları");
 | 
				
			||||||
 | 
					        this.hide();
 | 
				
			||||||
 | 
					        this.panel.css("min-width","640px");
 | 
				
			||||||
 | 
					        this.panel.css("min-height","250px");
 | 
				
			||||||
 | 
					        this.panel.css("width","max-content");
 | 
				
			||||||
 | 
					        this.initEvent();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @type {JQuery<HTMLElement>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    table = null;
 | 
				
			||||||
 | 
					    initContent(){
 | 
				
			||||||
 | 
					        this.table = $(`
 | 
				
			||||||
 | 
					            <table class="table table-sm table-bordered table-striped text-nowrap">
 | 
				
			||||||
 | 
					                <thead>
 | 
				
			||||||
 | 
					                    <tr>
 | 
				
			||||||
 | 
					                        <th>Cihaz Türü</th>
 | 
				
			||||||
 | 
					                        <th>Sağlanan Kanallar</th>
 | 
				
			||||||
 | 
					                        <th>Akış ID</th>
 | 
				
			||||||
 | 
					                        <th></th>
 | 
				
			||||||
 | 
					                    </tr>
 | 
				
			||||||
 | 
					                </thead>
 | 
				
			||||||
 | 
					                <tbody>
 | 
				
			||||||
 | 
					                </tbody>
 | 
				
			||||||
 | 
					                <tfoot>
 | 
				
			||||||
 | 
					                    <tr>
 | 
				
			||||||
 | 
					                        <td colspan="4">
 | 
				
			||||||
 | 
					                            <button class="btn btn-success w-100 newdevice">
 | 
				
			||||||
 | 
					                                Yeni Giriş Cihazı Ekle
 | 
				
			||||||
 | 
					                            </button>
 | 
				
			||||||
 | 
					                        </td>
 | 
				
			||||||
 | 
					                    </tr>
 | 
				
			||||||
 | 
					                </tfoot>
 | 
				
			||||||
 | 
					            </table>    
 | 
				
			||||||
 | 
					        `);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.updateDevices();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.content.append(this.table);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    initEvent(){
 | 
				
			||||||
 | 
					        this.content.find(".newdevice").on('click', this.generateDevice.bind(this));
 | 
				
			||||||
 | 
					        this.addEventListener("close",()=>{
 | 
				
			||||||
 | 
					            this.hide();
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    updateDevices(){
 | 
				
			||||||
 | 
					        let tbody = this.table.find("tbody");
 | 
				
			||||||
 | 
					        tbody.text('');
 | 
				
			||||||
 | 
					        for (const cell of FilterCell("rawstream", () => true))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let tr = $(`
 | 
				
			||||||
 | 
					                <tr class="text-nowrap">
 | 
				
			||||||
 | 
					                    <td>${cell.source}</td>
 | 
				
			||||||
 | 
					                    <td>${cell.kind}</td>
 | 
				
			||||||
 | 
					                    <td>${cell.payload.id}</td>
 | 
				
			||||||
 | 
					                    <td>
 | 
				
			||||||
 | 
					                        <button class="btn btn-outline-primary action-view">Görüntüle</button>
 | 
				
			||||||
 | 
					                        <button class="btn btn-outline-danger action-close">Kapat</button>
 | 
				
			||||||
 | 
					                    </td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					            `);
 | 
				
			||||||
 | 
					            tr.attr("data-declare", cell.payload.id);
 | 
				
			||||||
 | 
					            cell.addEventListener("stop",() => tr.remove());
 | 
				
			||||||
 | 
					            tbody.append(tr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        tbody.find(".action-view").on('click', e => this.viewSource($(e.target)));
 | 
				
			||||||
 | 
					        tbody.find(".action-close").on('click', e => this.closeSource($(e.target)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    closeSource(btn){
 | 
				
			||||||
 | 
					        let streamid = btn.closest("tr").attr("data-declare");
 | 
				
			||||||
 | 
					        for (const brain of FilterCell("rawstream",e => e.payload.id == streamid)) {
 | 
				
			||||||
 | 
					            brain.stop();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    viewSource(btn){
 | 
				
			||||||
 | 
					        let streamid = btn.closest("tr").attr("data-declare");
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * @type {MediaStream}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        let p = null;
 | 
				
			||||||
 | 
					        for (const rawstream of FilterCell("rawstream",e => e.payload.id == streamid)) {
 | 
				
			||||||
 | 
					            p = rawstream.payload;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        let modal = new ViewSourceDialog(p.getTracks()[0]);
 | 
				
			||||||
 | 
					        modal.enableDialog(this);
 | 
				
			||||||
 | 
					        modal.bringToFront();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    generateDevice(){
 | 
				
			||||||
 | 
					        let modal = new AddDeviceDialog();
 | 
				
			||||||
 | 
					        modal.enableDialog(this);
 | 
				
			||||||
 | 
					        modal.bringToFront();
 | 
				
			||||||
 | 
					        modal.addEventListener("stream:added",()=>{
 | 
				
			||||||
 | 
					            this.updateDevices();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StreamRecord extends EventTarget {
 | 
				
			||||||
 | 
					    lockedby = 0;
 | 
				
			||||||
 | 
					    stop(){
 | 
				
			||||||
 | 
					        this.payload.getTracks().forEach(e => e.stop());
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("stop"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    isLocked(){
 | 
				
			||||||
 | 
					        return this.lockedby != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    lock(){
 | 
				
			||||||
 | 
					        this.lockedby++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    unlock(){
 | 
				
			||||||
 | 
					        this.lockedby--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddDeviceDialog extends DWindow {
 | 
				
			||||||
 | 
					    constructor(){
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.initContent();
 | 
				
			||||||
 | 
					        this.headtext.text("Aygıt Ekleme Sihirbazı");
 | 
				
			||||||
 | 
					        this.addEventListener('close',()=>{
 | 
				
			||||||
 | 
					            this.disableDialog();
 | 
				
			||||||
 | 
					            this.exit();
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    initContent(){
 | 
				
			||||||
 | 
					        let table = $(`
 | 
				
			||||||
 | 
					            <div style="display:flex;flex-direction:column;gap:5px">
 | 
				
			||||||
 | 
					                <button class="btn btn-success w-100 action-sdcam">
 | 
				
			||||||
 | 
					                    SD Kamara Ekle
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <button class="btn btn-success w-100 action-hdcam">
 | 
				
			||||||
 | 
					                    HD Kamara Ekle
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <button class="btn btn-success w-100 action-mic">
 | 
				
			||||||
 | 
					                    Mikrofon Ekle
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <button class="btn btn-success w-100 action-displaycam">
 | 
				
			||||||
 | 
					                    Ekran Görüntüsü Ekle
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					            </div> 
 | 
				
			||||||
 | 
					        `);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        table.find(".action-sdcam").on("click",this.sdcam.bind(this));
 | 
				
			||||||
 | 
					        table.find(".action-hdcam").on("click",this.hdcam.bind(this));
 | 
				
			||||||
 | 
					        table.find(".action-mic").on("click",this.mic.bind(this));
 | 
				
			||||||
 | 
					        table.find(".action-displaycam").on("click",this.displaycam.bind(this));
 | 
				
			||||||
 | 
					        this.content.append(table);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async sdcam(){
 | 
				
			||||||
 | 
					        let stream = await navigator.mediaDevices.getUserMedia({
 | 
				
			||||||
 | 
					            video: {
 | 
				
			||||||
 | 
					                advanced: [
 | 
				
			||||||
 | 
					                    { width: { exact: 640 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 320 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 240 } }
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                facingMode: "user"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        AddCell("rawstream", new class extends StreamRecord {
 | 
				
			||||||
 | 
					            source = "Kamera";
 | 
				
			||||||
 | 
					            kind = "Görüntü";
 | 
				
			||||||
 | 
					            payload = stream;
 | 
				
			||||||
 | 
					            constructor(){
 | 
				
			||||||
 | 
					                super();
 | 
				
			||||||
 | 
					                this.onEnded(() => {
 | 
				
			||||||
 | 
					                    this.dispatchEvent(new Event("stop"));
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                this.addEventListener("stop",() => {
 | 
				
			||||||
 | 
					                    RemoveCell("rawstream",cell => {
 | 
				
			||||||
 | 
					                        return cell.payload.id == stream.id
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            onEnded(event){
 | 
				
			||||||
 | 
					                /** @type {MediaStreamTrack} */
 | 
				
			||||||
 | 
					                let track;
 | 
				
			||||||
 | 
					                stream.getVideoTracks().forEach(e => track = e);
 | 
				
			||||||
 | 
					                if(track)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    track.addEventListener("ended",event);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("stream:added"));
 | 
				
			||||||
 | 
					        this.disableDialog();
 | 
				
			||||||
 | 
					        this.exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    async hdcam(){
 | 
				
			||||||
 | 
					        let stream = await navigator.mediaDevices.getUserMedia({
 | 
				
			||||||
 | 
					            video: {
 | 
				
			||||||
 | 
					                advanced: [
 | 
				
			||||||
 | 
					                    { width: { exact: 1920 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 1600 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 1366 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 1280 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 1024 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 900 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 800 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 640 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 320 } },
 | 
				
			||||||
 | 
					                    { width: { exact: 240 } }
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                facingMode: "user"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        AddCell("rawstream", new class extends StreamRecord {
 | 
				
			||||||
 | 
					            source = "Kamera";
 | 
				
			||||||
 | 
					            kind = "Görüntü";
 | 
				
			||||||
 | 
					            payload = stream;
 | 
				
			||||||
 | 
					            constructor(){
 | 
				
			||||||
 | 
					                super();
 | 
				
			||||||
 | 
					                this.onEnded(() => {
 | 
				
			||||||
 | 
					                    this.dispatchEvent(new Event("stop"));
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                this.addEventListener("stop",() => {
 | 
				
			||||||
 | 
					                    RemoveCell("rawstream",cell => {
 | 
				
			||||||
 | 
					                        return cell.payload.id == stream.id
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            onEnded(event){
 | 
				
			||||||
 | 
					                /** @type {MediaStreamTrack} */
 | 
				
			||||||
 | 
					                let track;
 | 
				
			||||||
 | 
					                stream.getVideoTracks().forEach(e => track = e);
 | 
				
			||||||
 | 
					                if(track)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    track.addEventListener("ended",event);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("stream:added"));
 | 
				
			||||||
 | 
					        this.disableDialog();
 | 
				
			||||||
 | 
					        this.exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    async mic(){
 | 
				
			||||||
 | 
					        let stream = await navigator.mediaDevices.getUserMedia({
 | 
				
			||||||
 | 
					            audio: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        AddCell("rawstream", new class extends StreamRecord {
 | 
				
			||||||
 | 
					            source = "Kamera";
 | 
				
			||||||
 | 
					            kind = "Ses";
 | 
				
			||||||
 | 
					            payload = stream;
 | 
				
			||||||
 | 
					            constructor(){
 | 
				
			||||||
 | 
					                super();
 | 
				
			||||||
 | 
					                this.onEnded(() => {
 | 
				
			||||||
 | 
					                    this.dispatchEvent(new Event("stop"));
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                this.addEventListener("stop",() => {
 | 
				
			||||||
 | 
					                    RemoveCell("rawstream",cell => {
 | 
				
			||||||
 | 
					                        return cell.payload.id == stream.id
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            onEnded(event){
 | 
				
			||||||
 | 
					                /** @type {MediaStreamTrack} */
 | 
				
			||||||
 | 
					                let track;
 | 
				
			||||||
 | 
					                stream.getAudioTracks().forEach(e => track = e);
 | 
				
			||||||
 | 
					                if(track)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    track.addEventListener("ended",event);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("stream:added"));
 | 
				
			||||||
 | 
					        this.disableDialog();
 | 
				
			||||||
 | 
					        this.exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    async displaycam(){
 | 
				
			||||||
 | 
					        let stream = await navigator.mediaDevices.getDisplayMedia({
 | 
				
			||||||
 | 
					            video: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        AddCell("rawstream", new class extends StreamRecord{
 | 
				
			||||||
 | 
					            source = "Ekran";
 | 
				
			||||||
 | 
					            kind = "Görüntü";
 | 
				
			||||||
 | 
					            payload = stream;
 | 
				
			||||||
 | 
					            constructor(){
 | 
				
			||||||
 | 
					                super();
 | 
				
			||||||
 | 
					                this.onEnded(() => {
 | 
				
			||||||
 | 
					                    this.dispatchEvent(new Event("stop"));
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                this.addEventListener("stop",() => {
 | 
				
			||||||
 | 
					                    RemoveCell("rawstream",cell => {
 | 
				
			||||||
 | 
					                        return cell.payload.id == stream.id
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            onEnded(event){
 | 
				
			||||||
 | 
					                /** @type {MediaStreamTrack} */
 | 
				
			||||||
 | 
					                let track;
 | 
				
			||||||
 | 
					                stream.getTracks().forEach(e => track = e);
 | 
				
			||||||
 | 
					                if(track)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    track.addEventListener("ended",event);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("stream:added"));
 | 
				
			||||||
 | 
					        this.disableDialog();
 | 
				
			||||||
 | 
					        this.exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class ViewSourceDialog extends DWindow {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  @type {MediaStreamTrack}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    track = null;
 | 
				
			||||||
 | 
					    extra = {};
 | 
				
			||||||
 | 
					    constructor(track){
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.headtext.text("Giriş Kaynağı Görüntüleme");
 | 
				
			||||||
 | 
					        this.addEventListener('close',()=>{
 | 
				
			||||||
 | 
					            this.disableDialog();
 | 
				
			||||||
 | 
					            this.exit();
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        this.track = track;
 | 
				
			||||||
 | 
					        this.initContent();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    initContent(){
 | 
				
			||||||
 | 
					        if(this.track.kind == "video")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.initVideoContent();
 | 
				
			||||||
 | 
					        }else{
 | 
				
			||||||
 | 
					            this.initAudioContent();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.table = $(`<table class="table">
 | 
				
			||||||
 | 
					            <tbody>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                    <td>Track ID</td>
 | 
				
			||||||
 | 
					                    <td>${this.track.id}</td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                    <td>Data Type</td>
 | 
				
			||||||
 | 
					                    <td>${this.track.kind}</td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                    <td>Status</td>
 | 
				
			||||||
 | 
					                    <td>${this.track.enabled ? "Active" : "Passive"}</td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                    <td>Track Label</td>
 | 
				
			||||||
 | 
					                    <td>${this.track.label}</td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					            </tbody>
 | 
				
			||||||
 | 
					        </table>`);
 | 
				
			||||||
 | 
					        this.content.append(this.table);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    initVideoContent(){
 | 
				
			||||||
 | 
					        let player = $(`<video
 | 
				
			||||||
 | 
					            style="height: 450px"
 | 
				
			||||||
 | 
					            controls
 | 
				
			||||||
 | 
					        />`);
 | 
				
			||||||
 | 
					        let stream = new MediaStream();
 | 
				
			||||||
 | 
					        stream.addTrack(this.track);
 | 
				
			||||||
 | 
					        player.on('canplay', e => e.target.play());
 | 
				
			||||||
 | 
					        player.get(0).srcObject = stream;
 | 
				
			||||||
 | 
					        this.content.append(player);
 | 
				
			||||||
 | 
					        player.on('play', e => {
 | 
				
			||||||
 | 
					            this.table.find("tbody").append(`
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                    <td>Video Width</td>
 | 
				
			||||||
 | 
					                    <td>${e.target.videoWidth}px</td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					            `);
 | 
				
			||||||
 | 
					            this.table.find("tbody").append(`
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                    <td>Video Height</td>
 | 
				
			||||||
 | 
					                    <td>${e.target.videoHeight}px</td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					            `);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    initAudioContent(){
 | 
				
			||||||
 | 
					        let player = $(`<audio
 | 
				
			||||||
 | 
					            style="width: 500px"
 | 
				
			||||||
 | 
					            controls
 | 
				
			||||||
 | 
					        />`);
 | 
				
			||||||
 | 
					        let stream = new MediaStream();
 | 
				
			||||||
 | 
					        stream.addTrack(this.track);
 | 
				
			||||||
 | 
					        player.get(0).srcObject = stream;
 | 
				
			||||||
 | 
					        player.on('canplay', e => e.target.play());
 | 
				
			||||||
 | 
					        this.content.append(player);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,65 @@
 | 
				
			||||||
 | 
					import DWindow from "./window.js";
 | 
				
			||||||
 | 
					import { AddCell, FilterCell, memory, RemoveCell } from "./sdb.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Rooms = new class Rooms extends DWindow{
 | 
				
			||||||
 | 
					    constructor(){
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.emptyConnect();
 | 
				
			||||||
 | 
					        this.headtext.text("MWSE Ağları");
 | 
				
			||||||
 | 
					        this.hide();
 | 
				
			||||||
 | 
					        this.panel.css("min-width","640px");
 | 
				
			||||||
 | 
					        this.addEventListener("close",()=>{
 | 
				
			||||||
 | 
					            this.hide();
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    emptyConnect(){
 | 
				
			||||||
 | 
					        this.content.append($(`
 | 
				
			||||||
 | 
					            <h4 class="text-white text-center">MWSE Ağları</h4>
 | 
				
			||||||
 | 
					        `),$(`
 | 
				
			||||||
 | 
					            <h6 class="text-white text-center">Herhangi bir ağa bağlı değilsiniz</h6>
 | 
				
			||||||
 | 
					        `));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        this.content.append($(`
 | 
				
			||||||
 | 
					            <h3 class="text-white text-center" style="margin-top: 50px">
 | 
				
			||||||
 | 
					                Ağ Oluştur
 | 
				
			||||||
 | 
					            </h3>
 | 
				
			||||||
 | 
					        `));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let createinput = $(`
 | 
				
			||||||
 | 
					            <input type="text" class="form-control" placeholder="Oluşturulacak Oda Adı" style="line-height:2;font-size: 2em">
 | 
				
			||||||
 | 
					        `);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let createbutton = $(`
 | 
				
			||||||
 | 
					            <button class="btn btn-lg btn-success d-block m-auto mt-3">Oluştur</button>
 | 
				
			||||||
 | 
					        `);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.content.append(createinput,createbutton);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.content.append($(`
 | 
				
			||||||
 | 
					            <h3 class="text-white text-center" style="margin-top: 50px">
 | 
				
			||||||
 | 
					                Ağa Katıl
 | 
				
			||||||
 | 
					            </h3>
 | 
				
			||||||
 | 
					        `));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let joininput = $(`
 | 
				
			||||||
 | 
					            <input type="text" class="form-control" placeholder="Katılacak Oda Adı" style="line-height:2;font-size: 2em">
 | 
				
			||||||
 | 
					        `);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let joinbutton = $(`
 | 
				
			||||||
 | 
					            <button class="btn btn-lg btn-success d-block m-auto mt-3">Katıl</button>
 | 
				
			||||||
 | 
					        `);
 | 
				
			||||||
 | 
					        this.content.append(joininput,joinbutton);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.content.append($(`
 | 
				
			||||||
 | 
					            <span class="text-white" style="margin-top: 50px;max-width:100%;font-size: 0.9em;line-height: 1;display: block;text-shadow: 0px 0px 4px black;">
 | 
				
			||||||
 | 
					                Aynı ağdaki kullanıcılar birbirini görecek ve akışlarını paylaşabilecektir.
 | 
				
			||||||
 | 
					                Verilerinizi, bilgilerinizi ve akışlarınızı paylaşmakta tamamen özgürsünüz.
 | 
				
			||||||
 | 
					                Sistem tamamen deneysel teknoloji araştırma ve geliştirme üzerine kuruludur.
 | 
				
			||||||
 | 
					                Sistem kullanılarak yapılan tüm iyi ve kötü amaçlı eylemlerden kullanıcı sorumludur.
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					        `));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 660 KiB  | 
| 
						 | 
					@ -0,0 +1,162 @@
 | 
				
			||||||
 | 
					const style = document.createElement("style");
 | 
				
			||||||
 | 
					document.head.appendChild(style);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class CSSOM {
 | 
				
			||||||
 | 
					    /** @type {Map<string, CSSOM>} */
 | 
				
			||||||
 | 
					    static rules = new Map();
 | 
				
			||||||
 | 
					    /** @type {Map<string, CSSRuleList>} */
 | 
				
			||||||
 | 
					    static cRules = new Map();
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @returns {CSSOM}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static get(name){
 | 
				
			||||||
 | 
					        return CSSOM.rules.get(name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /** @returns {CSSRule} */
 | 
				
			||||||
 | 
					    static findRule(selector){
 | 
				
			||||||
 | 
					        for (let ruleIndex = 0; ruleIndex < style.sheet.cssRules.length; ruleIndex++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let rule = style.sheet.cssRules.item(ruleIndex);
 | 
				
			||||||
 | 
					            if(rule.selectorText == selector)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return rule;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /** @returns {CSSRule} */
 | 
				
			||||||
 | 
					    static removeRule(selector){
 | 
				
			||||||
 | 
					        for (let ruleIndex = 0; ruleIndex < style.sheet.cssRules.length; ruleIndex++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let rule = style.sheet.cssRules.item(ruleIndex);
 | 
				
			||||||
 | 
					            if(rule.selectorText == selector)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                style.sheet.deleteRule(ruleIndex);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    static css(selector, values){
 | 
				
			||||||
 | 
					        let rule;
 | 
				
			||||||
 | 
					        if(!(rule = CSSOM.findRule(selector)))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let no = style.sheet.insertRule(`${selector}{}`);
 | 
				
			||||||
 | 
					            rule = style.sheet.cssRules[no];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(let [stylename, stylevalue] of Object.entries(values))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let name = stylename;
 | 
				
			||||||
 | 
					            let value = typeof stylevalue == "string" ? stylevalue.split('!')[0] : stylevalue;
 | 
				
			||||||
 | 
					            let priority = typeof stylevalue == "string" ? (stylevalue.split('!')[1] == "important" ? "important" : void 0) : void 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            name = name.replace(/([A-Z])/g,(_,$1) => '-' + $1.toLowerCase());
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            rule.style.setProperty(name, value, priority);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    static generate(idd = null, css = null){
 | 
				
			||||||
 | 
					        let id = idd || CSSOM.generateCode();
 | 
				
			||||||
 | 
					        let t = new CSSOM(id);
 | 
				
			||||||
 | 
					        CSSOM.rules.set(t.id,t);
 | 
				
			||||||
 | 
					        css && t.css(css);
 | 
				
			||||||
 | 
					        return t;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    static generateCode(){
 | 
				
			||||||
 | 
					        let mine;
 | 
				
			||||||
 | 
					        do{
 | 
				
			||||||
 | 
					            mine = Math.random().toString(36).slice(2,6);
 | 
				
			||||||
 | 
					        }while(CSSOM.rules.has(mine));
 | 
				
			||||||
 | 
					        return "i" + mine;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    id = "";
 | 
				
			||||||
 | 
					    /** @type {{[key:string]: CSSRuleList}} */
 | 
				
			||||||
 | 
					    rule_t = {};
 | 
				
			||||||
 | 
					    constructor(id){
 | 
				
			||||||
 | 
					        this.id = id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    toString(){
 | 
				
			||||||
 | 
					        return this.id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    css(name, value, prefix = 'owner'){
 | 
				
			||||||
 | 
					        let rule;
 | 
				
			||||||
 | 
					        if(!this.rule_t[prefix])
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let rulename = `.${this.id}` + (prefix == "owner" ? "" : prefix);
 | 
				
			||||||
 | 
					            let no = style.sheet.insertRule(`${rulename}{}`);
 | 
				
			||||||
 | 
					            this.rule_t[prefix] = style.sheet.cssRules[no];
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        rule = this.rule_t[prefix];
 | 
				
			||||||
 | 
					        if(value === undefined && typeof name == "string")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return rule.style.getPropertyValue(name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(value === null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            rule.style.removeProperty(name, value);
 | 
				
			||||||
 | 
					        }else{
 | 
				
			||||||
 | 
					            if(typeof name == "object")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                for(let [stylename, stylevalue] of Object.entries(name))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    let name = stylename;
 | 
				
			||||||
 | 
					                    let value = typeof stylevalue == "string" ? stylevalue.split('!')[0] : stylevalue;
 | 
				
			||||||
 | 
					                    let priority = typeof stylevalue == "string" ? (stylevalue.split('!')[1] == "important" ? "!important" : void 0) : stylevalue;
 | 
				
			||||||
 | 
					                    if(name.indexOf('-') == -1)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        rule.style[name] = value + (priority || "");
 | 
				
			||||||
 | 
					                    }else{
 | 
				
			||||||
 | 
					                        rule.style.setProperty(name, value, priority);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }else{
 | 
				
			||||||
 | 
					                rule.style.setProperty(name, value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$.fn.cssom = function(obj, prefix){
 | 
				
			||||||
 | 
					    if(prefix === void 0 || (typeof obj == "object" && typeof prefix == "string"))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let cssom;
 | 
				
			||||||
 | 
					        if(this.attr("data-cssom"))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let name = this.attr("data-cssom");
 | 
				
			||||||
 | 
					            cssom = CSSOM.get(name)
 | 
				
			||||||
 | 
					        }else{
 | 
				
			||||||
 | 
					            cssom = CSSOM.generate();
 | 
				
			||||||
 | 
					            this.addClass(cssom.id);
 | 
				
			||||||
 | 
					            this.attr("data-cssom", cssom.id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        cssom.css(obj,void 0,prefix);
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if(obj.indexOf(":") == -1){
 | 
				
			||||||
 | 
					            this.addClass(obj);
 | 
				
			||||||
 | 
					            CSSOM.css("." + obj, prefix);
 | 
				
			||||||
 | 
					        }else{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let [_class,_psudio] = obj.split(":");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.addClass(_class);
 | 
				
			||||||
 | 
					            CSSOM.css("." + _class + ":" + _psudio, prefix);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.debugCssom = function(){
 | 
				
			||||||
 | 
					    for (let ruleIndex = 0; ruleIndex < style.sheet.cssRules.length; ruleIndex++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let rule = style.sheet.cssRules.item(ruleIndex);
 | 
				
			||||||
 | 
					        console.log(rule.cssText)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					window.cssom = CSSOM;
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ typedef {Object} BirthData
 | 
				
			||||||
 | 
					 * @ property {Date} birthDate
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @typedef {Object} BrainCell
 | 
				
			||||||
 | 
					 * @property {string} type
 | 
				
			||||||
 | 
					 * @property {Object} data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @type {BrainCell[]}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export let memory = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function AddCell(name, data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    memory.push({
 | 
				
			||||||
 | 
					        type: name,
 | 
				
			||||||
 | 
					        data
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {string} type 
 | 
				
			||||||
 | 
					 * @param {(BrainCell) => boolean} filterQuery 
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function RemoveCell(type, filterQuery)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    memory = memory.filter(e => !(
 | 
				
			||||||
 | 
					        e.type == type && filterQuery(e.data)
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {string} type 
 | 
				
			||||||
 | 
					 * @param {(BrainCell) => boolean} filterQuery 
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function FilterCell(type, filterQuery)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return memory.filter(e => 
 | 
				
			||||||
 | 
					        e.type == type && filterQuery(e.data)
 | 
				
			||||||
 | 
					    ).map(e => e.data);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.memoryDump = () => memory;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,293 @@
 | 
				
			||||||
 | 
					export default class DWindow extends EventTarget {
 | 
				
			||||||
 | 
					    static allWindows = [];     // açık pencereler
 | 
				
			||||||
 | 
					    static zCounter = 1;        // global sayaç
 | 
				
			||||||
 | 
					    static normalizeThreshold = 9999; // yeniden sıfırlama eşiği
 | 
				
			||||||
 | 
					    /** @type {JQuery<HTMLElement>} */ panel = null;
 | 
				
			||||||
 | 
					    /** @type {JQuery<HTMLElement>} */ title = null;
 | 
				
			||||||
 | 
					    /** @type {JQuery<HTMLElement>} */ content = null;
 | 
				
			||||||
 | 
					    /** @type {JQuery<HTMLElement>} */ headtext = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.initpanel();
 | 
				
			||||||
 | 
					        this.enableFocus();
 | 
				
			||||||
 | 
					        DWindow.allWindows.push(this);
 | 
				
			||||||
 | 
					        this.bringToFront();
 | 
				
			||||||
 | 
					        requestAnimationFrame(()=>{
 | 
				
			||||||
 | 
					            this.enableDragging();
 | 
				
			||||||
 | 
					            this.enableResize();
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    activeDragging = true;
 | 
				
			||||||
 | 
					    activeResizing = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    initpanel() {
 | 
				
			||||||
 | 
					        this.panel = $(`<div></div>`).css({
 | 
				
			||||||
 | 
					            width: 450,
 | 
				
			||||||
 | 
					            //height: 500,
 | 
				
			||||||
 | 
					            position: "fixed",
 | 
				
			||||||
 | 
					            left: (Math.random() * 300 | 0) + 100,
 | 
				
			||||||
 | 
					            top: (Math.random() * 100 | 0) + 100,
 | 
				
			||||||
 | 
					            boxShadow: "black 0px 0px 20px -10px",
 | 
				
			||||||
 | 
					            borderRadius: "10px",
 | 
				
			||||||
 | 
					            backgroundColor: "#3333335b",
 | 
				
			||||||
 | 
					            backdropFilter: "blur(3px)",
 | 
				
			||||||
 | 
					            border: "solid 1px #a2a2a2",
 | 
				
			||||||
 | 
					            display: "flex",
 | 
				
			||||||
 | 
					            flexDirection: "column",
 | 
				
			||||||
 | 
					            outlineOffset: "-5px",
 | 
				
			||||||
 | 
					            //overflow: "hidden",
 | 
				
			||||||
 | 
					            userSelect: "none",
 | 
				
			||||||
 | 
					            minWidth: "max-content",
 | 
				
			||||||
 | 
					            minHeight: "max-content"
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        $("body").append(this.panel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.title = $(`<div></div>`).css({
 | 
				
			||||||
 | 
					            display: "flex",
 | 
				
			||||||
 | 
					            flex: "0 0 auto",
 | 
				
			||||||
 | 
					            flexDirection: "row",
 | 
				
			||||||
 | 
					            lineHeight: "2em",
 | 
				
			||||||
 | 
					            backgroundColor: "#333333",
 | 
				
			||||||
 | 
					            color: "white",
 | 
				
			||||||
 | 
					            paddingLeft: "10px",
 | 
				
			||||||
 | 
					            cursor: "move",
 | 
				
			||||||
 | 
					            borderTopLeftRadius: "10px",
 | 
				
			||||||
 | 
					            borderTopRightRadius: "10px",
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.content = $(`<div></div>`).css({
 | 
				
			||||||
 | 
					            flex: "1 1 auto",
 | 
				
			||||||
 | 
					            overflow: "auto",
 | 
				
			||||||
 | 
					            borderBottomRightRadius: "10px",
 | 
				
			||||||
 | 
					            borderBottomLeftRadius: "10px",
 | 
				
			||||||
 | 
					            padding: "20px"
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.panel.append(this.title, this.content);
 | 
				
			||||||
 | 
					        this.initTitle();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    initTitle() {
 | 
				
			||||||
 | 
					        this.headtext = $("<div>Başlıksız pencere</div>");
 | 
				
			||||||
 | 
					        const divider = $("<div style='flex:1 1 auto'></div>");
 | 
				
			||||||
 | 
					        this.exitbtn = $("<div><span class='btn btn-sm material-symbols-outlined text-white'>close</span></div>");
 | 
				
			||||||
 | 
					        this.exitbtn.on('click',()=>{
 | 
				
			||||||
 | 
					            this.dispatchEvent(new Event("close"));
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        this.title.append(
 | 
				
			||||||
 | 
					            this.headtext,
 | 
				
			||||||
 | 
					            divider,
 | 
				
			||||||
 | 
					            this.exitbtn
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enableDragging() {
 | 
				
			||||||
 | 
					        let isDragging = false;
 | 
				
			||||||
 | 
					        let startX, startY, startLeft, startTop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.title.on("mousedown", (e) => {
 | 
				
			||||||
 | 
					            if(this.activeDragging == false){
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            let isInput = $(e.target).closest("button, input, select, textarea,.btn");
 | 
				
			||||||
 | 
					            if (isInput.length) return;
 | 
				
			||||||
 | 
					            e.preventDefault();
 | 
				
			||||||
 | 
					            isDragging = true;
 | 
				
			||||||
 | 
					            startX = e.pageX;
 | 
				
			||||||
 | 
					            startY = e.pageY;
 | 
				
			||||||
 | 
					            startLeft = parseFloat(this.panel.css("left"));
 | 
				
			||||||
 | 
					            startTop = parseFloat(this.panel.css("top"));
 | 
				
			||||||
 | 
					            $("body").css("user-select", "none");
 | 
				
			||||||
 | 
					            this.dispatchEvent(new Event("dragging"));
 | 
				
			||||||
 | 
					            this.panel.css("box-shadow","black 0px 0px 40px -20px");
 | 
				
			||||||
 | 
					                this.panel.css("backdrop-filter","blur(10px)");
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $(document).on("mousemove", (e) => {
 | 
				
			||||||
 | 
					            if (!isDragging) return;
 | 
				
			||||||
 | 
					            const dx = e.pageX - startX;
 | 
				
			||||||
 | 
					            const dy = e.pageY - startY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.panel.css({
 | 
				
			||||||
 | 
					                left: startLeft + dx,
 | 
				
			||||||
 | 
					                top: startTop + dy,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $(document).on("mouseup", () => {
 | 
				
			||||||
 | 
					            if (isDragging) {
 | 
				
			||||||
 | 
					                isDragging = false;
 | 
				
			||||||
 | 
					                this.panel.css("box-shadow","black 0px 0px 20px -10px");
 | 
				
			||||||
 | 
					                this.panel.css("backdrop-filter","blur(3px)");
 | 
				
			||||||
 | 
					                $("body").css("user-select", "auto");
 | 
				
			||||||
 | 
					                this.dispatchEvent(new Event("draggingend"));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    enableResize() {
 | 
				
			||||||
 | 
					        const offset = 5; // panelin dışından 5px alan
 | 
				
			||||||
 | 
					        let resizing = false;
 | 
				
			||||||
 | 
					        let resizeDir = "";
 | 
				
			||||||
 | 
					        let startX, startY, startW, startH, startL, startT;
 | 
				
			||||||
 | 
					        const minW = 200, minH = 150;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // overlay divleri oluştur
 | 
				
			||||||
 | 
					        const handles = {};
 | 
				
			||||||
 | 
					        const names = ["n","s","e","w","ne","nw","se","sw"];
 | 
				
			||||||
 | 
					        names.forEach(n => {
 | 
				
			||||||
 | 
					            handles[n] = $('<div></div>').css({
 | 
				
			||||||
 | 
					                position: "absolute",
 | 
				
			||||||
 | 
					                zIndex: 1000,
 | 
				
			||||||
 | 
					                background: "transparent",
 | 
				
			||||||
 | 
					                cursor: n + "-resize",
 | 
				
			||||||
 | 
					                transition: "all 0.5s all",
 | 
				
			||||||
 | 
					                outlineOffset: "3px"
 | 
				
			||||||
 | 
					            }).appendTo(this.panel);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // boyut ve pozisyonlarını ayarla
 | 
				
			||||||
 | 
					        const updateHandles = () => {
 | 
				
			||||||
 | 
					            const w = this.panel.outerWidth();
 | 
				
			||||||
 | 
					            const h = this.panel.outerHeight();
 | 
				
			||||||
 | 
					            // kenarlar
 | 
				
			||||||
 | 
					            handles.n.css({ top: -offset, left: 0, width: w, height: offset*2 });
 | 
				
			||||||
 | 
					            handles.s.css({ bottom: -offset, left: 0, width: w, height: offset*2 });
 | 
				
			||||||
 | 
					            handles.w.css({ top: 0, left: -offset, width: offset*2, height: h });
 | 
				
			||||||
 | 
					            handles.e.css({ top: 0, right: -offset, width: offset*2, height: h });
 | 
				
			||||||
 | 
					            // köşeler
 | 
				
			||||||
 | 
					            handles.nw.css({ top: -offset, left: -offset, width: offset*2, height: offset*2 });
 | 
				
			||||||
 | 
					            handles.ne.css({ top: -offset, right: -offset, width: offset*2, height: offset*2 });
 | 
				
			||||||
 | 
					            handles.sw.css({ bottom: -offset, left: -offset, width: offset*2, height: offset*2 });
 | 
				
			||||||
 | 
					            handles.se.css({ bottom: -offset, right: -offset, width: offset*2, height: offset*2 });
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        updateHandles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $(window).on("resize", updateHandles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let activeDir = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // resize eventleri
 | 
				
			||||||
 | 
					        names.forEach(dir => {
 | 
				
			||||||
 | 
					            handles[dir].on("mousedown", (e) => {
 | 
				
			||||||
 | 
					                if(this.activeResizing == false){
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                activeDir = e.target;
 | 
				
			||||||
 | 
					                e.preventDefault();
 | 
				
			||||||
 | 
					                e.stopPropagation();
 | 
				
			||||||
 | 
					                resizing = true;
 | 
				
			||||||
 | 
					                resizeDir = dir;
 | 
				
			||||||
 | 
					                startX = e.pageX;
 | 
				
			||||||
 | 
					                startY = e.pageY;
 | 
				
			||||||
 | 
					                startW = this.panel.outerWidth();
 | 
				
			||||||
 | 
					                startH = this.panel.outerHeight();
 | 
				
			||||||
 | 
					                startL = parseFloat(this.panel.css("left"));
 | 
				
			||||||
 | 
					                startT = parseFloat(this.panel.css("top"));
 | 
				
			||||||
 | 
					                this.dispatchEvent(new Event("resizing"));
 | 
				
			||||||
 | 
					                $("body").css("user-select","none");
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $(document).on("mousemove", (e) => {
 | 
				
			||||||
 | 
					            if (!resizing) return;
 | 
				
			||||||
 | 
					            const dx = e.pageX - startX;
 | 
				
			||||||
 | 
					            const dy = e.pageY - startY;
 | 
				
			||||||
 | 
					            let newW = startW;
 | 
				
			||||||
 | 
					            let newH = startH;
 | 
				
			||||||
 | 
					            let newL = startL;
 | 
				
			||||||
 | 
					            let newT = startT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (resizeDir.includes("e")) newW = Math.max(minW, startW + dx);
 | 
				
			||||||
 | 
					            if (resizeDir.includes("w")) { newW = Math.max(minW, startW - dx); newL = startL + (startW - newW); }
 | 
				
			||||||
 | 
					            if (resizeDir.includes("s")) newH = Math.max(minH, startH + dy);
 | 
				
			||||||
 | 
					            if (resizeDir.includes("n")) { newH = Math.max(minH, startH - dy); newT = startT + (startH - newH); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.panel.css({ width: newW, height: newH, left: newL, top: newT });
 | 
				
			||||||
 | 
					            updateHandles();
 | 
				
			||||||
 | 
					            $(activeDir).css("outline", "solid 2px #00ff00");
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $(document).on("mouseup", () => {
 | 
				
			||||||
 | 
					            if (resizing) {
 | 
				
			||||||
 | 
					                resizing = false;
 | 
				
			||||||
 | 
					                $("body").css("user-select","auto");
 | 
				
			||||||
 | 
					                $(activeDir).css("outline", "solid 0px #00ff00");
 | 
				
			||||||
 | 
					                this.dispatchEvent(new Event("resizingend"));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    enableFocus() {
 | 
				
			||||||
 | 
					        this.panel.on("mousedown", () => {
 | 
				
			||||||
 | 
					            this.bringToFront();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bringToFront() {
 | 
				
			||||||
 | 
					        if (DWindow.zCounter > DWindow.normalizeThreshold) {
 | 
				
			||||||
 | 
					            DWindow.normalizeZ();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        DWindow.zCounter++;
 | 
				
			||||||
 | 
					        this.panel.css("z-index", DWindow.zCounter);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    showing = true;
 | 
				
			||||||
 | 
					    show(){
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("show"));
 | 
				
			||||||
 | 
					        this.panel.show();
 | 
				
			||||||
 | 
					        this.showing = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    hide(){
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("hide"));
 | 
				
			||||||
 | 
					        this.panel.hide();
 | 
				
			||||||
 | 
					        this.showing = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    toggle(){
 | 
				
			||||||
 | 
					        this.showing ? this.hide() : this.show();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    exit(){
 | 
				
			||||||
 | 
					        this.dispatchEvent(new Event("exit"));
 | 
				
			||||||
 | 
					        this.panel.remove();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					        /** @type {DWindow} */
 | 
				
			||||||
 | 
					    parent = null;
 | 
				
			||||||
 | 
					    /** @param {DWindow} parent */
 | 
				
			||||||
 | 
					    enableDialog(parent){
 | 
				
			||||||
 | 
					        this.parent = parent;
 | 
				
			||||||
 | 
					        this.parent.activeDragging = false;
 | 
				
			||||||
 | 
					        this.parent.activeResizing = false;
 | 
				
			||||||
 | 
					        this.parent.panel.css('pointer-events',"none");
 | 
				
			||||||
 | 
					        this.parent.panel.css('filter',"grayscale(1)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let [{
 | 
				
			||||||
 | 
					            left: parentL,
 | 
				
			||||||
 | 
					            top: parentT,
 | 
				
			||||||
 | 
					            width: parentW,
 | 
				
			||||||
 | 
					            height: parentH
 | 
				
			||||||
 | 
					        }] = this.parent.panel[0].getClientRects();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let [{
 | 
				
			||||||
 | 
					            width: childW,
 | 
				
			||||||
 | 
					            height: childH
 | 
				
			||||||
 | 
					        }] = this.panel[0].getClientRects();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let newLeft = parentL + (parentW - childW) / 2;
 | 
				
			||||||
 | 
					        let newTop  = parentT + (parentH - childH) / 2;
 | 
				
			||||||
 | 
					        debugger;
 | 
				
			||||||
 | 
					        newLeft = Math.max(newLeft, 20);
 | 
				
			||||||
 | 
					        newTop = Math.max(newTop, 20);
 | 
				
			||||||
 | 
					        newLeft = Math.min(newLeft, screen.availWidth - 100);
 | 
				
			||||||
 | 
					        newTop = Math.min(newTop, screen.availHeight - 100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Object.assign(this.panel[0].style, {
 | 
				
			||||||
 | 
					            left: `${Math.round(newLeft)}px`,
 | 
				
			||||||
 | 
					            top:  `${Math.round(newTop)}px`
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /** @param {DWindow} parent */
 | 
				
			||||||
 | 
					    disableDialog(){
 | 
				
			||||||
 | 
					        this.parent.activeDragging = true;
 | 
				
			||||||
 | 
					        this.parent.activeResizing = true;
 | 
				
			||||||
 | 
					        this.parent.panel.css('pointer-events',"all");
 | 
				
			||||||
 | 
					        this.parent.panel.css('filter',"initial");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -12,9 +12,9 @@ async function beginEngine()
 | 
				
			||||||
        accessType: "private",
 | 
					        accessType: "private",
 | 
				
			||||||
        description: "Private free joined room",
 | 
					        description: "Private free joined room",
 | 
				
			||||||
        ifexistsJoin: false,
 | 
					        ifexistsJoin: false,
 | 
				
			||||||
        notifyActionEjected: true,
 | 
					        notifyActionEjected: false,
 | 
				
			||||||
        notifyActionInvite: false,
 | 
					        notifyActionInvite: false,
 | 
				
			||||||
        notifyActionJoined: true
 | 
					        notifyActionJoined: false
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    try{
 | 
					    try{
 | 
				
			||||||
        await room.createRoom();
 | 
					        await room.createRoom();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,166 @@
 | 
				
			||||||
 | 
					<!doctype html>
 | 
				
			||||||
 | 
					<html lang="tr">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					<meta charset="utf-8" />
 | 
				
			||||||
 | 
					<meta name="viewport" content="width=device-width,initial-scale=1" />
 | 
				
			||||||
 | 
					<title>jQuery ile Resizable Kutu</title>
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
					  body { font-family: Arial, Helvetica, sans-serif; height:100vh; margin:0; display:flex; align-items:center; justify-content:center; background:#f2f2f2; }
 | 
				
			||||||
 | 
					  .stage { width:90vw; height:80vh; border:1px solid #ccc; position:relative; background:#fff; }
 | 
				
			||||||
 | 
					  .box {
 | 
				
			||||||
 | 
					    position:absolute;
 | 
				
			||||||
 | 
					    left:50px; top:50px;
 | 
				
			||||||
 | 
					    width:300px; height:200px;
 | 
				
			||||||
 | 
					    background:#e8f0ff;
 | 
				
			||||||
 | 
					    border:1px solid #5b8cff;
 | 
				
			||||||
 | 
					    box-sizing:border-box;
 | 
				
			||||||
 | 
					    user-select:none;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  /* küçücük tutamaklar (handles) */
 | 
				
			||||||
 | 
					  .handle {
 | 
				
			||||||
 | 
					    position:absolute;
 | 
				
			||||||
 | 
					    width:12px; height:12px;
 | 
				
			||||||
 | 
					    background:#5b8cff;
 | 
				
			||||||
 | 
					    border-radius:2px;
 | 
				
			||||||
 | 
					    margin:-6px 0 0 -6px; /* merkezler */
 | 
				
			||||||
 | 
					    cursor:default;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .handle.n { top:0; left:50%; cursor:n-resize; }
 | 
				
			||||||
 | 
					  .handle.s { bottom:0; left:50%; cursor:s-resize; }
 | 
				
			||||||
 | 
					  .handle.e { right:0; top:50%; cursor:e-resize; }
 | 
				
			||||||
 | 
					  .handle.w { left:0; top:50%; cursor:w-resize; }
 | 
				
			||||||
 | 
					  .handle.ne { right:0; top:0; cursor:ne-resize; }
 | 
				
			||||||
 | 
					  .handle.nw { left:0; top:0; cursor:nw-resize; }
 | 
				
			||||||
 | 
					  .handle.se { right:0; bottom:0; cursor:se-resize; }
 | 
				
			||||||
 | 
					  .handle.sw { left:0; bottom:0; cursor:sw-resize; }
 | 
				
			||||||
 | 
					  /* bilgi satırı (isteğe bağlı) */
 | 
				
			||||||
 | 
					  .info { position:absolute; left:6px; bottom:6px; font-size:12px; color:#333; background:rgba(255,255,255,0.8); padding:4px 6px; border-radius:4px; }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="stage">
 | 
				
			||||||
 | 
					  <div class="box" id="resizable">
 | 
				
			||||||
 | 
					    <div class="handle n" data-dir="n"></div>
 | 
				
			||||||
 | 
					    <div class="handle s" data-dir="s"></div>
 | 
				
			||||||
 | 
					    <div class="handle e" data-dir="e"></div>
 | 
				
			||||||
 | 
					    <div class="handle w" data-dir="w"></div>
 | 
				
			||||||
 | 
					    <div class="handle ne" data-dir="ne"></div>
 | 
				
			||||||
 | 
					    <div class="handle nw" data-dir="nw"></div>
 | 
				
			||||||
 | 
					    <div class="handle se" data-dir="se"></div>
 | 
				
			||||||
 | 
					    <div class="handle sw" data-dir="sw"></div>
 | 
				
			||||||
 | 
					    <div class="info" id="info"></div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					$(function(){
 | 
				
			||||||
 | 
					  var $doc = $(document);
 | 
				
			||||||
 | 
					  var $box = $('#resizable');
 | 
				
			||||||
 | 
					  var dragging = false;
 | 
				
			||||||
 | 
					  var dir = null;
 | 
				
			||||||
 | 
					  var start = {}; // {mouseX, mouseY, left, top, width, height}
 | 
				
			||||||
 | 
					  var minW = 60, minH = 40;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function updateInfo(){
 | 
				
			||||||
 | 
					    var w = Math.round($box.width()), h = Math.round($box.height());
 | 
				
			||||||
 | 
					    $('#info').text(w + ' x ' + h);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  updateInfo();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $box.on('mousedown', '.handle', function(e){
 | 
				
			||||||
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					    dragging = true;
 | 
				
			||||||
 | 
					    dir = $(this).data('dir');
 | 
				
			||||||
 | 
					    var offset = $box.position();
 | 
				
			||||||
 | 
					    start = {
 | 
				
			||||||
 | 
					      mouseX: e.pageX,
 | 
				
			||||||
 | 
					      mouseY: e.pageY,
 | 
				
			||||||
 | 
					      left: offset.left,
 | 
				
			||||||
 | 
					      top: offset.top,
 | 
				
			||||||
 | 
					      width: $box.outerWidth(),
 | 
				
			||||||
 | 
					      height: $box.outerHeight()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    // disable text selection while dragging
 | 
				
			||||||
 | 
					    $('body').css('user-select','none');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $doc.on('mousemove', function(e){
 | 
				
			||||||
 | 
					    if(!dragging) return;
 | 
				
			||||||
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					    var dx = e.pageX - start.mouseX;
 | 
				
			||||||
 | 
					    var dy = e.pageY - start.mouseY;
 | 
				
			||||||
 | 
					    var newLeft = start.left;
 | 
				
			||||||
 | 
					    var newTop = start.top;
 | 
				
			||||||
 | 
					    var newW = start.width;
 | 
				
			||||||
 | 
					    var newH = start.height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // handle horizontal changes
 | 
				
			||||||
 | 
					    if(dir.indexOf('e') !== -1){
 | 
				
			||||||
 | 
					      newW = Math.max(minW, start.width + dx);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(dir.indexOf('w') !== -1){
 | 
				
			||||||
 | 
					      newW = Math.max(minW, start.width - dx);
 | 
				
			||||||
 | 
					      newLeft = start.left + (start.width - newW);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // handle vertical changes
 | 
				
			||||||
 | 
					    if(dir.indexOf('s') !== -1){
 | 
				
			||||||
 | 
					      newH = Math.max(minH, start.height + dy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(dir.indexOf('n') !== -1){
 | 
				
			||||||
 | 
					      newH = Math.max(minH, start.height - dy);
 | 
				
			||||||
 | 
					      newTop = start.top + (start.height - newH);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // apply
 | 
				
			||||||
 | 
					    $box.css({ left: newLeft + 'px', top: newTop + 'px', width: newW + 'px', height: newH + 'px' });
 | 
				
			||||||
 | 
					    updateInfo();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $doc.on('mouseup mouseleave', function(){
 | 
				
			||||||
 | 
					    if(dragging){
 | 
				
			||||||
 | 
					      dragging = false;
 | 
				
			||||||
 | 
					      dir = null;
 | 
				
			||||||
 | 
					      $('body').css('user-select','auto');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // optional: allow dragging the whole box when clicking inside (but not on handles)
 | 
				
			||||||
 | 
					  var draggingBox = false, dragBoxStart = {};
 | 
				
			||||||
 | 
					  $box.on('mousedown', function(e){
 | 
				
			||||||
 | 
					    if($(e.target).hasClass('handle')) return;
 | 
				
			||||||
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					    draggingBox = true;
 | 
				
			||||||
 | 
					    dragBoxStart = { mouseX: e.pageX, mouseY: e.pageY, left: $box.position().left, top: $box.position().top };
 | 
				
			||||||
 | 
					    $('body').css('user-select','none');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  $doc.on('mousemove', function(e){
 | 
				
			||||||
 | 
					    if(!draggingBox) return;
 | 
				
			||||||
 | 
					    var nx = dragBoxStart.left + (e.pageX - dragBoxStart.mouseX);
 | 
				
			||||||
 | 
					    var ny = dragBoxStart.top + (e.pageY - dragBoxStart.mouseY);
 | 
				
			||||||
 | 
					    $box.css({ left: nx + 'px', top: ny + 'px' });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  $doc.on('mouseup', function(){
 | 
				
			||||||
 | 
					    if(draggingBox){
 | 
				
			||||||
 | 
					      draggingBox = false;
 | 
				
			||||||
 | 
					      $('body').css('user-select','auto');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // keyboard nudges (isteğe bağlı)
 | 
				
			||||||
 | 
					  $doc.on('keydown', function(e){
 | 
				
			||||||
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					    if(!e.altKey) return; // alt ile etkinleştir
 | 
				
			||||||
 | 
					    var pos = $box.position();
 | 
				
			||||||
 | 
					    if(e.key === 'ArrowLeft') $box.css('left', pos.left - 1);
 | 
				
			||||||
 | 
					    if(e.key === 'ArrowRight') $box.css('left', pos.left + 1);
 | 
				
			||||||
 | 
					    if(e.key === 'ArrowUp') $box.css('top', pos.top - 1);
 | 
				
			||||||
 | 
					    if(e.key === 'ArrowDown') $box.css('top', pos.top + 1);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
		Reference in New Issue