All Downloads are FREE. Search and download functionalities are using the official Maven repository.

js.ide.index.jsx Maven / Gradle / Ivy

There is a newer version: 0.0.13
Show newest version
const catalog = new Catalog();
let project = null;
let currentContent = null;

function getParam(name) {
    // return new URL(window.location.href).searchParams.get(name);
    return new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href)[1];
}


function makeTreeId(content) {
    return content.type==="Prompto" ?
        content.subType + "_" + makeValidId(content.name) :
        content.value.mimeType.replace("/", "_") + "_" + makeValidId(content.value.name);
}

function saveBlob() {
    const blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
    saveAs(blob,'test.txt');
}

function getEditorWindow() {
    const frame = document.getElementById("editor");
    return frame.contentWindow;
}

function editorReady() {
    setEditorDefaults();
    loadProject(true);
}

function setEditorDefaults() {
    const window = getEditorWindow();
    window.setDialect("E");
}

function loadProject(loadDependencies) {
    const dbId = getParam("dbId");
    loadCodeInWorker(dbId, loadDependencies);
    loadDescription(dbId);
    loadResources(dbId);
}

function loadDescription(dbId) {
    var params = [{name: "dbId", value: dbId.toString()}, {name: "register", type: "Boolean", value: false}];
    var url = '/ws/run/getModuleDescription?params=' + JSON.stringify(params);
    loadJSON(url, function (response) {
        if (response.error)
            alert(response.error);
        else
            project = response.data;
    });
}

function loadResources(dbId) {
    const params = [ {name:"dbId", value:dbId} ];
    const url = '/ws/run/getModuleResources?params=' + JSON.stringify(params);
    loadJSON(url, function(response) {
        if (response.error)
            alert(response.error);
        else {
            const resources = response.data.value;
            const delta = { added: { resources: resources}};
            catalogUpdated(delta, () => {});
            catalog.markResources(resources, "CLEAN");
        }
    });
}

function loadJSON(url, success) {
    loadText(url, function (text) {
        const json = JSON.parse(text);
        success(json);
    });
}

function loadText(url, success) {
    const xhr = new XMLHttpRequest();
    xhr.onerror = function(e) {
        self.console.log("Error " + e.target.status + " occurred while receiving the document.");
        return null;
    };
    xhr.onload = function(e) {
        if(success)
            success(xhr.responseText);
    };
    xhr.open('GET', url);
    //noinspection EqualityComparisonWithCoercionJS
    if(url[0]!="/" && url[0]!=".")
        xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
    xhr.send(null);
}

function loadCodeInWorker(dbId, loadDependencies) {
    const window = getEditorWindow();
    window.setProject(dbId, loadDependencies);
}

class GroupTree extends React.Component {

    constructor(props) {
        super(props);
        this.renderItem = this.renderItem.bind(this);
        this.toggleTreeNode = this.toggleTreeNode.bind(this);
        this.itemClicked = this.itemClicked.bind(this);
    }

    render() {
        let items = this.props.items;
        if(!this.props.showLibraries)
            items = items.filter(item => !item.core);
        return 
    • { items.map(item => { return this.renderItem(item); }, this) }
  • } renderItem(item) { const key = this.props.type + "_" + makeValidId(item.name); const className = 'list-group-item' + (item.core ? ' core' : ''); return
  • {item.name} {item.core && }
  • ; } toggleTreeNode(e) { $(e.target).parent().children('ul').toggle(300); } itemClicked(e) { e.stopPropagation(); const a = $(e.target); let content = { type: "Prompto", subType: this.props.type, name: a.text() }; content.core = a.attr("core") ? eval(a.attr("core")) : false; setEditorContent(content); } } class MethodTree extends GroupTree { constructor(props) { super(props); this.renderItem = this.renderItem.bind(this); this.renderProto = this.renderProto.bind(this); } renderItem(method) { const key = this.props.type + "_" + makeValidId(method.name); const className = 'list-group-item' + (method.core ? ' core' : ''); if(method.protos.length>1) { return
    • { method.protos.map(proto => { return this.renderProto(method, proto); }, this) }
  • ; } else { const proto = method.protos[0]; return
  • {method.name} {method.core && }
  • ; } } renderProto(method, proto) { const key = this.props.type + "_" + makeValidId(proto.proto); const className = 'list-group-item' + (method.core ? ' core' : ''); return
  • {proto.proto} { method.core && }
  • ; } itemClicked(e) { e.stopPropagation(); const a = $(e.target); const name = a.attr("name"); const proto = a.attr("proto"); const core = a.attr("core") ? eval(a.attr("core")) : false; const main = a.attr("main") ? eval(a.attr("main")) : false; const content = { type: "Prompto", subType: this.props.type, name: name, proto: proto, core: core, main: main }; setEditorContent(content); } } class TextResourceTree extends GroupTree { constructor(props) { super(props); this.renderItem = this.renderItem.bind(this); this.itemClicked = this.itemClicked.bind(this); } renderItem(item) { const key = item.value.mimeType.replace("/", "_") + "_" + makeValidId(item.value.name); return
  • {item.value.name}
  • ; } itemClicked(e) { e.stopPropagation(); const a = $(e.target); let content = { type: this.props.type, name: a.text() }; content.body = catalog.getResourceBody(content); setEditorContent(content); } } class BinaryResourceTree extends GroupTree { constructor(props) { super(props); this.renderItem = this.renderItem.bind(this); this.itemClicked = this.itemClicked.bind(this); } renderItem(item) { const key = item.value.mimeType.replace("/", "_") + "_" + makeValidId(item.value.name); return
  • {item.value.name}
  • ; } itemClicked(e) { e.stopPropagation(); const a = $(e.target); let content = { type: this.props.type, name: a.text() }; let resource = catalog.resourceFromContent(content); if(resource.value.data) content.data = resource.value.data; else if(resource.value.file) content.file = resource.value.file; setEditorContent(content); } } class ProjectTree extends React.Component { render() { const catalog = this.props.catalog; return
    ; } toggleShowLibraries(e) { showLibraries(e.target.checked); } toggleTreeNode(e) { $(e.target).parent().children('div').toggle(300); } } function showLibraries(show) { catalog.showLibraries = show; ReactDOM.render(, document.getElementById('project-tree')); } function catalogUpdated(delta, callback) { catalog.applyDelta(delta); ReactDOM.render(, document.getElementById('project-tree'), callback); } function installDialectDropdownHandler() { $('#nav-dialect').click(function (e) { if(e.target.id.indexOf('dialect-')===0) { $('li').removeClass('active'); $(e.target).parent().addClass('active'); const dialect = e.target.id.substring('dialect-'.length, 'dialect-'.length + 1); const window = getEditorWindow(); window.setDialect(dialect); } }); } function installNewDropdownHandler() { $('#nav-new').click(function (e) { if(e.target.id.indexOf('new-')===0) { const label = $(e.target).text(); const type = e.target.id.substring('new-'.length); if(type==='Prompto') setEditorContent({ type: "Prompto" }); else if(type==='Image' || type==='Audio' || type==='Video' || type==='Other') newFileResource(type, label); else newTextResource(type, label); } }); } function renderNavbar() { const projectName = getParam("name"); ReactDOM.render(Prompto Code Editor for: {projectName}, document.getElementById('project-name')); } $(document).ready(function () { renderNavbar(); installDialectDropdownHandler(); installNewDropdownHandler(); }); function selectContentInProjectTree(content) { const id = makeTreeId(content); const leaf = $("#" + id); leaf.parentsUntil("#project-tree").show(50); leaf.trigger("click"); } function isTextResourceContent() { return currentContent && currentContent.type !== "Prompto" && currentContent.type !== "Image" && currentContent.type !== "Audio" && currentContent.type !== "Video" && currentContent.type !== "Other"; } function setEditorContent(content) { if(content && content===currentContent) return; const window = getEditorWindow(); if(isTextResourceContent()) { currentContent.body = window.getResourceBody(); catalog.setResourceBody(currentContent); } currentContent = content; window.setContent(content); } class NewTextResourceDialog extends React.Component { constructor(props) { super(props); this.state = {folder: getParam("name"), name: '', extension: this.props.type.toLowerCase().replace(" ", "-")}; this.handleFolder = this.handleFolder.bind(this); this.handleName = this.handleName.bind(this); this.handleExtension = this.handleExtension.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } render() { const placeholder = this.props.label; return

    New {this.props.label}

    / .
    ; } handleFolder(event) { this.state.folder = event.target.value; } handleName(event) { this.state.name = event.target.value; } handleExtension(event) { this.state.extension = event.target.value; } handleSubmit(event) { const path = this.state.folder + "/" + this.state.name + "." + this.state.extension; this.props.submit(this.props.type, path); } } function newTextResource(type, label) { ReactDOM.render(, document.getElementById('new-resource')); const dialog = $("#new-resource"); dialog.on('shown.bs.modal', () => $("#nameInput").focus()); dialog.modal(); } function createTextResource(type, path) { const id = createTextResourceInCatalog(type, path, () => selectContentInProjectTree(id)); $('#new-resource').modal('toggle'); } function createTextResourceInCatalog(type, path, callback) { const methodName = "createResource" + type; if(!window[methodName]) alert("No such method:" + methodName); const content = window[methodName](path); content.value.module = { type: "Module", value: { dbId: getParam("dbId") } }; const delta = { added: { resources: [content]}}; catalogUpdated(delta, callback); return content; } function createResourceHtml(path) { return { type: "TextResource", value: { name: path, mimeType: "text/html", body: "\n" + "\n" + "\t\n" + "\t\n" + "\t\n" + "\t\tHello!\n" + "\t\n" + "" } }; } function createResourceJs(path) { return { type: "TextResource", value: { name: path, mimeType: "text/javascript", body: "function hello() {\n" + "\talert('Hello');\n" + "}" } }; } function createResourceJsx(path) { return { type: "TextResource", value: { name: path, mimeType: "text/babel", body: "function hello() {\n" + "\talert('Hello');\n" + "}" } }; } function createResourceCss(path) { return { type: "TextResource", value: { name: path, mimeType: "text/css", body: "body {\n" + "\tbackground-color: white;\n" + "}" } }; } function createResourceJson(path) { return { type: "TextResource", value: { name: path, mimeType: "text/json", body: '{ "field": 123 }' } }; } function createResourceXml(path) { return { type: "TextResource", value: { name: path, mimeType: "text/xml", body: '\n' + '\n' + '\tdata\n' + '\n' } }; } function createResourceYaml(path) { return { type: "TextResource", value: { name: path, mimeType: "text/yaml", body: 'invoice: 34843\n' + 'date : 2001-01-23\n' + 'bill-to: &id001\n' + '\tgiven : Chris\n' + '\tfamily : Dumars\n' + '\taddress:\n' + '\t\tlines: |\n' + '\t\t\t458 Walkman Dr.\n' + '\t\t\tSuite #292\n' + '\t\tcity : Royal Oak\n' + '\t\tstate : MI\n' + '\t\tpostal : 48046\n' } }; } function createResourceTxt(path) { return { type: "TextResource", value: { name: path, mimeType: "text/plain", body: 'Hello there!' } }; } const DroppedFileWidget = widgets.DroppedFileWidget.default; const DroppedWidgetStyle = { display: 'inline-flex', border: '1px solid lightgray', height: '300px', width: '650px', padding: '20px', alignItems: 'center', justifyContent: 'center' }; class NewFileResourceDialog extends React.Component { constructor(props) { super(props); this.state = {folder: getParam("name"), file: null}; this.handleFolder = this.handleFolder.bind(this); this.handleName = this.handleName.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.handleDrop = this.handleDrop.bind(this); } render() { return

    New {this.props.label}

    / {this.state.name && } {!this.state.name && }
    ; } handleDrop(file) { this.setState({ file: file, name: file.name }); } handleFolder(event) { this.setState({ folder: event.target.value }); } handleName(event) { this.setState({ name: event.target.value }); } handleSubmit(event) { const path = this.state.folder + "/" + this.state.name; this.props.submit(this.props.type, path, this.state.file); } } function newFileResource(type, label) { ReactDOM.render(, document.getElementById('new-resource')); const dialog = $("#new-resource"); dialog.on('shown.bs.modal', () => $("#nameInput").focus()); dialog.modal(); } function createFileResource(type, path, file) { const id = createFileResourceInCatalog(type, path, file, () => selectContentInProjectTree(id)); $('#new-resource').modal('toggle'); } function createFileResourceInCatalog(type, path, file, callback) { const content = { type: "BinaryResource", value: { name: path, mimeType: file.type, file: file } }; content.value.module = { type: "Module", value: { dbId: getParam("dbId") } }; const delta = { added: { resources: [content]}}; catalogUpdated(delta, callback); return content; } class ImageDisplayer extends React.Component { constructor(props) { super(props); this.loadPreview = this.loadPreview.bind(this); this.state = { preview: null}; this.loadPreview(this.props.file); } componentWillReceiveProps(nextProps) { if(this.props.file !== nextProps.file) { this.setState({preview: null}); this.loadPreview(nextProps.file); } } loadPreview(file) { if(file && file.type.startsWith("image/")) { const reader = new FileReader(); reader.onload = (e) => { this.setState({ preview: e.target.result }); }; reader.readAsDataURL(file); } } render() { const source = this.props.source || this.state.preview; const state = source ? "PREVIEW" : "LOADING"; return
    { state==="PREVIEW" && } { state==="LOADING" && 'Loading...' }
    } } function setContentImage(element, content) { ReactDOM.render(, element); } function destroy() { if(currentContent===null) window.alert("Nothing to destroy!"); else { const id = currentContent; currentContent = null; const window = getEditorWindow(); window.destroy(id); } } function revert() { // TODO confirm setEditorContent({ type: "Prompto" }); loadProject(false); } function commit() { // TODO confirm setEditorContent({ type: "Prompto" }); const window = getEditorWindow(); window.prepareCommit(); } function commitPrepared(declarations) { let resources = catalog.prepareCommit(); if((declarations && declarations.length) || (resources && resources.length)) { const form = new FormData(); if(resources && resources.length) resources = prepareResourceFiles(form, resources); const stuff = (declarations || []).concat(resources || []); const params = JSON.stringify([{name: "edited", type: "EditedStuff[]", value: stuff}]); form.append("params", params); const xhr = new XMLHttpRequest(); xhr.upload.addEventListener('load', function(success) { commitSuccessful(success); }); xhr.addEventListener('error', function(failure) { commitFailed(failure); }); xhr.open('POST', '/ws/run/storeEdited', true); xhr.send(form); } } function prepareResourceFiles(formData, resources) { return resources.map(res => { let stuff = res.value.stuff; if(stuff.type==="BinaryResource" && stuff.value.file) { stuff = Object.assign({}, stuff); stuff.value.data = { mimeType: stuff.value.file.type, partName: "@" + stuff.value.file.name }; formData.append(stuff.value.data.partName, stuff.value.file); delete stuff.value.file; res.value.stuff = stuff; } return res; }); } function commitFailed(failure) { alert("Commit failed!"); // TODO send to UI } function commitSuccessful(success) { alert("Commit ok!"); const window = getEditorWindow(); window.commitSuccessful(); } function setRunMode(label) { $("#run-mode").html(" " + label + " " + ""); } function getRunMode() { const text = $("#run-mode").text(); const mode = text.indexOf("compiled")>=0 ? "EXECUTE/" : "INTERPRET/"; return mode + (text.indexOf("Server")>=0 ? "REMOTE" : "LOCAL"); } function run() { const msg = getRunnableAlert(currentContent); if (msg) alert(msg); else if (currentContent.type === "Html") openWebPage(currentContent); else runPromptoCode(); } function stopServer() { fetchModuleURL((url)=>{ var fullUrl = url + "ws/control/exit"; loadText(fullUrl); }); } function resetServer() { fetchModuleURL((url)=>{ var fullUrl = url + "ws/control/clear-context"; loadText(fullUrl); }); } function openWebPage(id) { const tab = window.open(window.location.href, '_blank', ''); fetchModuleURL((url)=>{ tab.location = url + id.name; tab.focus(); }); } function fetchModuleURL(success) { const dbId = getParam("dbId"); const params = [ {name:"dbId", value:dbId.toString()}]; const url = '/ws/run/getModulePort?params=' + JSON.stringify(params); loadJSON(url, function(response) { if (response.error) ; // TODO something else { const href = self.location.protocol + "//" + self.location.hostname + ":" + response.data + "/"; success(href); } }); } function runPromptoCode() { switchUIToRunMode(); print("Running " + currentContent.name + "..."); const runMode = getRunMode(); const window = getEditorWindow(); window.runMethod(currentContent, runMode); } function done(data) { const button = document.getElementById("run-button"); button.innerHTML = "Done"; } function getRunnableAlert(id) { if (!id) return "Nothing to run!"; else if(id.subType==="test") return null; else if(id.subType==="method" && id.main) return null; else if(id.type=="Html" && project.type==="WebSite") return null; else return "Can only run tests methods, main methods or web pages!"; } function stop() { edit(); } function edit() { switchUIToEditMode(); } function switchUIToRunMode() { const doc = document.getElementById("output"); doc.innerHTML = ""; $(".edit-mode").hide(); $(".run-mode").show(); const button = document.getElementById("run-button"); button.onclick = function() { stop(); }; button.innerHTML = "Stop"; } function switchUIToEditMode() { $(".run-mode").hide(); $(".edit-mode").show(); const button = document.getElementById("run-button"); button.onclick = function() { run(); }; button.innerHTML = "Run"; } function print(msg) { const doc = document.getElementById("output"); doc.innerHTML += msg + "
    "; } // a utility method to inspect worker data in Firefox/Safari function inspect(name) { const window = getEditorWindow(); window.inspect(name); } // a utility method to inspect worker data in Firefox/Safari function inspected(data) { console.log(data); }




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy