add file explorer

pull/1/head
serapath 8 years ago
parent a51ff50181
commit 40f8abe827
  1. 24
      assets/css/browser-solidity.css
  2. 9
      index.html
  3. 157
      src/app.js
  4. 21
      src/app/editor.js
  5. 318
      src/app/file-explorer.js
  6. 173
      src/app/file-panel.js
  7. 40
      test-browser/tests/fileExplorer.js

@ -1,3 +1,6 @@
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
body { body {
padding: 0; padding: 0;
font-size: 12px; font-size: 12px;
@ -39,11 +42,11 @@ body {
left: 0; left: 0;
} }
.files-wrapper { #tabs-bar {
position: absolute; position: absolute;
overflow: hidden; overflow: hidden;
top: 0; top: 0;
left: 5em; left: 200px;
right: 3em; right: 3em;
} }
@ -75,8 +78,6 @@ body {
color: #999; color: #999;
} }
.newFile,
.uploadFile,
.toggleRHP { .toggleRHP {
display: block; display: block;
float: left; float: left;
@ -124,18 +125,6 @@ body {
display: inline-block; display: inline-block;
} }
#input {
border-top: 3px solid #F4F6FF;
padding-top: 0.5em;
font-size: 15px;
position: absolute;
top: 2.5em;
left: 0;
right: 0;
bottom: 0;
min-width: 20vw;
}
#righthand-panel { #righthand-panel {
position: absolute; position: absolute;
top: 0; top: 0;
@ -161,6 +150,7 @@ body {
float: right; float: right;
height: 90%; height: 90%;
background-color: white; background-color: white;
padding-right: 1%;
} }
#header #menu { #header #menu {
@ -475,7 +465,7 @@ body {
bottom: 0; bottom: 0;
cursor: col-resize; cursor: col-resize;
z-index: 999; z-index: 999;
border-right: 3px solid #F4F6FF; border-right: 2px solid #C6CFF7;
} }
#editor .ace-tm .ace_gutter, #editor .ace-tm .ace_gutter,

@ -41,15 +41,16 @@
<body> <body>
<div id="editor"> <div id="editor">
<span class="newFile" title="New File"><i class="fa fa-plus-circle" aria-hidden="true"></i></span> <div id="tabs-bar">
<span class="uploadFile" title="Open local file"><label class="fa fa-folder-open"><input type="file" class="inputFile" multiple /></label></span>
<div class="files-wrapper">
<div class="scroller scroller-left"><i class="fa fa-chevron-left "></i></div> <div class="scroller scroller-left"><i class="fa fa-chevron-left "></i></div>
<div class="scroller scroller-right"><i class="fa fa-chevron-right "></i></div> <div class="scroller scroller-right"><i class="fa fa-chevron-right "></i></div>
<ul id="files" class="nav nav-tabs"></ul> <ul id="files" class="nav nav-tabs"></ul>
</div> </div>
<span class="toggleRHP" title="Toggle right hand panel"><i class="fa fa-angle-double-right"></i></span> <span class="toggleRHP" title="Toggle right hand panel"><i class="fa fa-angle-double-right"></i></span>
<div id="input"></div> <div id="editor-container">
<div id="filepanel"></div>
<div id="input"></div>
</div>
<div id="dragbar"></div> <div id="dragbar"></div>
</div> </div>

@ -1,10 +1,11 @@
/* global alert, confirm, prompt, FileReader, Option, Worker, chrome */ /* global alert, confirm, prompt, Option, Worker, chrome */
'use strict' 'use strict'
var async = require('async') var async = require('async')
var $ = require('jquery') var $ = require('jquery')
var base64 = require('js-base64').Base64 var base64 = require('js-base64').Base64
var swarmgw = require('swarmgw') var swarmgw = require('swarmgw')
var csjs = require('csjs-inject')
var QueryParams = require('./app/query-params') var QueryParams = require('./app/query-params')
var queryParams = new QueryParams() var queryParams = new QueryParams()
@ -24,6 +25,7 @@ var FormalVerification = require('./app/formalVerification')
var EventManager = require('./lib/eventManager') var EventManager = require('./lib/eventManager')
var StaticAnalysis = require('./app/staticanalysis/staticAnalysisView') var StaticAnalysis = require('./app/staticanalysis/staticAnalysisView')
var OffsetToLineColumnConverter = require('./lib/offsetToLineColumnConverter') var OffsetToLineColumnConverter = require('./lib/offsetToLineColumnConverter')
var FilePanel = require('./app/file-panel')
var examples = require('./app/example-contracts') var examples = require('./app/example-contracts')
@ -84,12 +86,6 @@ var run = function () {
loadFiles(filesToLoad) loadFiles(filesToLoad)
} }
// -------- check file upload capabilities -------
if (!(window.File || window.FileReader || window.FileList || window.Blob)) {
$('.uploadFile').remove()
}
// ------------------ gist load ---------------- // ------------------ gist load ----------------
var loadingFromGist = gistHandler.handleLoad(queryParams.get(), function (gistId) { var loadingFromGist = gistHandler.handleLoad(queryParams.get(), function (gistId) {
@ -159,26 +155,83 @@ var run = function () {
chromeCloudSync() chromeCloudSync()
// ----------------- editor ---------------------- // ----------------- editor ----------------------
var editor = new Editor(document.getElementById('input')) var editor = new Editor(document.getElementById('input'))
// ----------------- tabbed menu ------------------- // ---------------- FilePanel --------------------
$('#options li').click(function (ev) { /****************************************************************************
var $el = $(this) @TODO's
selectTab($el) 1. I would put a virtual file called Summary as the root entry of the treeview, which displays the list of the files with the size in bytes of each
})
2. drag'n'drop to enable to rename files&folders in the file explorer into different sub folders
var selectTab = function (el) {
var match = /[a-z]+View/.exec(el.get(0).className) 3. I would put a virtual file called `Summary` as the root entry of the treeview, which displays the list of the files with the size in bytes of each.
if (!match) return
var cls = match[0] 4. add maybe more tape tests
if (!el.hasClass('active')) {
el.parent().find('li').removeClass('active') 5. gist imports + copy to the browser => phase of writing
$('#optionViews').attr('class', '').addClass(cls)
el.addClass('active') 6. add filemanagement from righthand panel to filepanel compoennt (editing/imports/exports, public gist, load from github, create new project, ... setup load and modify files)
*/
// var sources = {
// 'test/client/credit.sol': '',
// 'src/voting.sol': '',
// 'src/leasing.sol': '',
// 'src/gmbh/contract.sol': false,
// 'src/gmbh/test.sol': false,
// 'src/gmbh/company.sol': false,
// 'src/gmbh/node_modules/ballot.sol': false,
// 'src/ug/finance.sol': false,
// 'app/solidity/mode.sol': true,
// 'app/ethereum/constitution.sol': true
// }
// Object.keys(sources).forEach(function (key) { files.set(key, sources[key]) })
/****************************************************************************/
var css = csjs`
.filepanel {
display : flex;
width : 200px;
}
`
var filepanel = document.querySelector('#filepanel')
filepanel.className = css.filepanel
var FilePanelAPI = {
createName: createNonClashingName,
switchToFile: switchToFile
}
var el = new FilePanel(FilePanelAPI, files)
filepanel.appendChild(el)
var api = el.api
api.register('ui', function changeLayout (data) {
var value
if (data.type === 'minimize') {
value = -parseInt(window['filepanel'].style.width)
value = (isNaN(value) ? -window['filepanel'].getBoundingClientRect().width : value)
window['filepanel'].style.position = 'absolute'
window['filepanel'].style.left = (value - 5) + 'px'
window['filepanel'].style.width = -value + 'px'
window['tabs-bar'].style.left = '45px'
} else if (data.type === 'maximize') {
value = -parseInt(window['filepanel'].style.left) + 'px'
window['filepanel'].style.position = 'static'
window['filepanel'].style.width = value
window['filepanel'].style.left = ''
window['tabs-bar'].style.left = value
} else {
window['filepanel'].style.width = data.width + 'px'
window['tabs-bar'].style.left = data.width + 'px'
} }
self.event.trigger('tabChanged', [cls]) })
} api.register('focus', function (path) {
[...window.files.querySelectorAll('.file .name')].forEach(function (span) {
if (span.innerText === path) switchToFile(path) // @TODO: scroll into view
})
})
files.event.register('fileRenamed', function (oldName, newName) {
[...window.files.querySelectorAll('.file .name')].forEach(function (span) {
if (span.innerText === oldName) span.innerText = newName
})
})
// ------------------ gist publish -------------- // ------------------ gist publish --------------
@ -221,39 +274,26 @@ var run = function () {
}).appendTo('body') }).appendTo('body')
}) })
// ----------------- file selector------------- // ---------------- tabbed menu ------------------
$('#options li').click(function (ev) {
var $filesEl = $('#files') var $el = $(this)
var FILE_SCROLL_DELTA = 300 selectTab($el)
$('.newFile').on('click', function () {
var newName = createNonClashingName('Untitled')
if (!files.set(newName, '')) {
alert('Failed to create file ' + newName)
} else {
switchToFile(newName)
}
}) })
// ----------------- file upload ------------- var selectTab = function (el) {
var match = /[a-z]+View/.exec(el.get(0).className)
$('.inputFile').on('change', function () { if (!match) return
var fileList = $('input.inputFile')[0].files var cls = match[0]
for (var i = 0; i < fileList.length; i++) { if (!el.hasClass('active')) {
var name = fileList[i].name el.parent().find('li').removeClass('active')
if (!files.exists(name) || confirm('The file ' + name + ' already exists! Would you like to overwrite it?')) { $('#optionViews').attr('class', '').addClass(cls)
var fileReader = new FileReader() el.addClass('active')
fileReader.onload = function (ev) {
if (!files.set(name, ev.target.result)) {
alert('Failed to create file ' + name)
} else {
switchToFile(name)
}
}
fileReader.readAsText(fileList[i])
}
} }
}) self.event.trigger('tabChanged', [cls])
}
var $filesEl = $('#files')
var FILE_SCROLL_DELTA = 300
// Switch tab // Switch tab
$filesEl.on('click', '.file:not(.active)', function (ev) { $filesEl.on('click', '.file:not(.active)', function (ev) {
@ -325,6 +365,8 @@ var run = function () {
currentFile = file currentFile = file
files.event.trigger('fileFocus', [file])
if (files.isReadOnly(file)) { if (files.isReadOnly(file)) {
editor.openReadOnly(file, files.get(file)) editor.openReadOnly(file, files.get(file))
} else { } else {
@ -368,7 +410,6 @@ var run = function () {
}) })
} }
var $filesWrapper = $('.files-wrapper')
var $scrollerRight = $('.scroller-right') var $scrollerRight = $('.scroller-right')
var $scrollerLeft = $('.scroller-left') var $scrollerLeft = $('.scroller-left')
@ -381,12 +422,8 @@ var run = function () {
return itemsWidth return itemsWidth
} }
// function widthOfHidden () {
// return ($filesWrapper.outerWidth() - widthOfList() - getLeftPosi())
// }
function widthOfVisible () { function widthOfVisible () {
return $filesWrapper.outerWidth() return document.querySelector('#editor-container').offsetWidth
} }
function getLeftPosi () { function getLeftPosi () {

@ -2,13 +2,34 @@
var EventManager = require('../lib/eventManager') var EventManager = require('../lib/eventManager')
var csjs = require('csjs-inject')
var ace = require('brace') var ace = require('brace')
var Range = ace.acequire('ace/range').Range var Range = ace.acequire('ace/range').Range
require('../mode-solidity.js') require('../mode-solidity.js')
var css = csjs`
.editor-container {
display : flex;
position : absolute;
top : 2.5em;
left : 0;
right : 0;
bottom : 0;
min-width : 20vw;
}
.ace-editor {
top : 4px;
border-top : 3px solid transparent;
font-size : 15px;
width : 100%;
}
`
document.querySelector('#editor-container').className = css['editor-container']
function Editor (editorElement) { function Editor (editorElement) {
var editor = ace.edit(editorElement) var editor = ace.edit(editorElement)
editorElement.editor = editor // required to access the editor during tests editorElement.editor = editor // required to access the editor during tests
editorElement.className += ' ' + css['ace-editor']
var event = new EventManager() var event = new EventManager()
this.event = event this.event = event
var sessions = {} var sessions = {}

@ -0,0 +1,318 @@
/* global FileReader, confirm, alert */
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var Treeview = require('ethereum-remix').ui.TreeView
var EventManager = require('../lib/eventManager')
var css = csjs`
.fileexplorer {
box-sizing : border-box;
}
.folder,
.file {
font-size : 14px;
}
.hasFocus {
background-color : #F4F6FF;
}
.rename {
background-color : white;
}
.remove {
align-self : center;
padding-left : 10px;
}
.activeMode {
display : flex;
justify-content : space-between;
margin-right : 10px;
padding-right : 19px;
}
ul {
padding : 0;
}
`
module.exports = fileExplorer
function fileExplorer (appAPI, files) {
var fileEvents = files.event
var tv = new Treeview({
extractData: function (value, tree, key) {
var newValue = {}
// var isReadOnly = false
var isFile = false
Object.keys(value).filter(function keep (x) {
if (x === '/content') isFile = true
// if (x === '/readOnly') isReadOnly = true
if (x[0] !== '/') return true
}).forEach(function (x) { newValue[x] = value[x] })
return {
path: (tree || {}).path ? tree.path + '/' + key : key,
children: isFile ? undefined
: value instanceof Array ? value.map((item, index) => ({
key: index, value: item
})) : value instanceof Object ? Object.keys(value).map(subkey => ({
key: subkey, value: value[subkey]
})) : undefined
}
},
formatSelf: function (key, data) {
return yo`<label class=${data.children ? css.folder : css.file}
data-path="${data.path}"
onload=${function (el) { adaptEnvironment(el, focus, hover) }}
onunload=${function (el) { unadaptEnvironment(el, focus, hover) }}
onclick=${editModeOn}
onkeydown=${editModeOff}
onblur=${editModeOff}
>${key}</label>`
}
})
var deleteButton = yo`
<span class=${css.remove} onclick=${deletePath}>
<i class="fa fa-trash" aria-hidden="true"></i>
</span>
`
fileEvents.register('fileFocus', fileFocus)
fileEvents.register('fileRemoved', fileRemoved)
fileEvents.register('fileRenamed', fileRenamed)
fileEvents.register('fileAdded', fileAdded)
fileEvents.register('fileChanged', fileChanged)
var filepath = null
var focusElement = null
var textUnderEdit = null
var element = tv.render(files.listAsTree())
element.className = css.fileexplorer
var api = new EventManager()
api.addFile = function addFile (file) {
var name = file.name
if (!files.exists(name) || confirm('The file ' + name + ' already exists! Would you like to overwrite it?')) {
var fileReader = new FileReader()
fileReader.onload = function (event) {
var success = files.set(name, event.target.result)
if (!success) alert('Failed to create file ' + name)
else api.trigger('focus', [name])
}
fileReader.readAsText(file)
}
}
function focus (event) {
event.cancelBubble = true
var li = this
if (focusElement === li) return
if (focusElement) focusElement.classList.toggle(css.hasFocus)
focusElement = li
focusElement.classList.toggle(css.hasFocus)
var label = getLabelFrom(li)
var filepath = label.dataset.path
var isFile = label.className.indexOf('file') === 0
if (isFile) api.trigger('focus', [filepath])
}
function hover (event) {
if (event.type === 'mouseout') {
var exitedTo = event.toElement || event.relatedTarget
if (this.contains(exitedTo)) return
this.style.backgroundColor = ''
this.style.paddingRight = '19px'
return this.removeChild(deleteButton)
}
this.style.backgroundColor = '#F4F6FF'
this.style.paddingRight = '0px'
this.appendChild(deleteButton)
}
function getElement (path) {
var label = element.querySelector(`label[data-path="${path}"]`)
if (label) return getLiFrom(label)
}
function deletePath (event) {
event.cancelBubble = true
var span = this
var li = span.parentElement.parentElement
var label = getLabelFrom(li)
var path = label.dataset.path
var isFolder = !!~label.className.indexOf('folder')
if (confirm(`
Do you really want to delete "${path}" ?
${isFolder ? '(and all contained files and folders)' : ''}
`)) {
li.parentElement.removeChild(li)
removeSubtree(files, path)
}
}
function editModeOn (event) {
var label = this
var li = getLiFrom(label)
var classes = li.className
if (~classes.indexOf('hasFocus') && !label.getAttribute('contenteditable')) {
textUnderEdit = label.innerText
label.setAttribute('contenteditable', true)
label.classList.add(css.rename)
label.focus()
}
}
function editModeOff (event) {
var label = this
if (event.type === 'blur' || event.which === 27 || event.which === 13) {
var save = textUnderEdit !== label.innerText
if (event.which === 13) event.preventDefault()
if (save && event.which !== 13) save = confirm('Do you want to rename?')
if (save) renameSubtree(label)
else label.innerText = textUnderEdit
label.removeAttribute('contenteditable')
label.classList.remove(css.rename)
}
}
function renameSubtree (label, dontcheck) {
var oldPath = label.dataset.path
var newPath = oldPath
newPath = newPath.split('/')
newPath[newPath.length - 1] = label.innerText
newPath = newPath.join('/')
if (!dontcheck) {
var allPaths = Object.keys(files.list())
for (var i = 0, len = allPaths.length, path, err; i < len; i++) {
path = allPaths[i]
if (files.IsReadOnly(path)) {
err = 'path contains readonly elements'
break
} else if (path.indexOf(newPath) === 0) {
err = 'new path is conflicting with another existing path'
break
}
}
}
if (err) {
alert(`couldn't rename - ${err}`)
label.innerText = textUnderEdit
} else {
textUnderEdit = label.innerText
updateAllLabels([getElement(oldPath)], oldPath, newPath)
}
}
function updateAllLabels (lis, oldPath, newPath) {
lis.forEach(function (li) {
var label = getLabelFrom(li)
var path = label.dataset.path
var newName = path.replace(oldPath, newPath)
label.dataset.path = newName
var isFile = label.className.indexOf('file') === 0
if (isFile) files.rename(path, newName)
var ul = li.lastChild
if (ul.tagName === 'UL') {
updateAllLabels([...ul.children], oldPath, newPath)
}
})
}
function fileChanged (filepath) { }
function fileFocus (path) {
if (filepath === path) return
filepath = path
var el = getElement(filepath)
expandPathTo(el)
setTimeout(function focusNode () { el.click() }, 0)
}
function fileRemoved (filepath) {
var li = getElement(filepath)
if (li) li.parentElement.removeChild(li)
}
function fileRenamed (oldName, newName) {
var li = getElement(oldName)
if (li) {
oldName = oldName.split('/')
newName = newName.split('/')
var index = oldName.reduce(function (idx, key, i) {
return oldName[i] !== newName[i] ? i : idx
}, undefined)
var newKey = newName[index]
var oldPath = oldName.slice(0, index + 1).join('/')
li = getElement(oldPath)
var label = getLabelFrom(li)
label.innerText = newKey
renameSubtree(label, true)
}
}
function fileAdded (filepath) {
var el = tv.render(files.listAsTree())
el.className = css.fileexplorer
element.parentElement.replaceChild(el, element)
element = el
fileFocus(filepath)
appAPI.switchToFile(filepath)
}
element.api = api
return element
}
/******************************************************************************
HELPER FUNCTIONS
******************************************************************************/
function adaptEnvironment (label, focus, hover) {
var li = getLiFrom(label)
li.style.position = 'relative'
var span = li.firstChild
// add focus
li.addEventListener('click', focus)
// add hover
span.classList.add(css.activeMode)
span.addEventListener('mouseover', hover)
span.addEventListener('mouseout', hover)
}
function unadaptEnvironment (label, focus, hover) {
var li = getLiFrom(label)
var span = li.firstChild
li.style.position = undefined
// remove focus
li.removeEventListener('click', focus)
// remove hover
span.classList.remove(css.activeMode)
span.removeEventListener('mouseover', hover)
span.removeEventListener('mouseout', hover)
}
function getLiFrom (label) {
return label.parentElement.parentElement.parentElement
}
function getLabelFrom (li) {
return li.children[0].children[1].children[0]
}
function removeSubtree (files, path) {
var allPaths = Object.keys(files.list()) // @TODO: change `files`
var removePaths = allPaths.filter(function (p) { return ~p.indexOf(path) })
removePaths.forEach(function (path) {
[...window.files.querySelectorAll('.file .name')].forEach(function (span) {
if (span.innerText === path) {
var li = span.parentElement
li.parentElement.removeChild(li) // delete tab
}
})
files.remove(path)
})
}
function expandPathTo (li) {
while ((li = li.parentElement.parentElement) && li.tagName === 'LI') {
var caret = li.firstChild.firstChild
if (caret.classList.contains('fa-caret-right')) caret.click() // expand
}
}

@ -0,0 +1,173 @@
/* global alert */
var csjs = require('csjs-inject')
var yo = require('yo-yo')
var EventManager = require('../lib/eventManager')
var FileExplorer = require('./file-explorer')
module.exports = filepanel
var css = csjs`
.container {
display : flex;
flex-direction : row;
width : 100%;
box-sizing : border-box;
}
.fileexplorer {
display : flex;
flex-direction : column;
position : relative;
top : -33px;
width : 100%;
}
.menu {
display : flex;
flex-direction : row;
}
.newFile {
padding : 10px;
}
.uploadFile {
padding : 10px;
}
.toggleLHP {
display : flex;
justify-content : flex-end;
padding : 10px;
width : 100%;
font-weight : bold;
cursor : pointer;
color : black;
}
.isVisible {
position : absolute;
left : 35px;
}
.isHidden {
position : absolute;
height : 99%
left : -101%;
}
.treeview {
height : 100%;
background-color : white;
}
.dragbar {
position : relative;
top : 6px;
cursor : col-resize;
z-index : 999;
border-right : 2px solid #C6CFF7;
}
.ghostbar {
width : 3px;
background-color : #C6CFF7;
opacity : 0.5;
position : absolute;
cursor : col-resize;
z-index : 9999;
top : 0;
bottom : 0;
}
`
var limit = 60
var canUpload = window.File || window.FileReader || window.FileList || window.Blob
var ghostbar = yo`<div class=${css.ghostbar}></div>`
function filepanel (appAPI, files) {
var fileExplorer = new FileExplorer(appAPI, files)
var dragbar = yo`<div onmousedown=${mousedown} class=${css.dragbar}></div>`
function template () {
return yo`
<div class=${css.container}>
<div class=${css.fileexplorer}>
<div class=${css.menu}>
<span onclick=${createNewFile} class="newFile ${css.newFile}" title="New File">
<i class="fa fa-plus-circle"></i>
</span>
${canUpload ? yo`
<span class=${css.uploadFile} title="Open local file">
<label class="fa fa-folder-open">
<input type="file" onchange=${uploadFile} multiple />
</label>
</span>
` : ''}
<span class=${css.toggleLHP} onclick=${toggle} title="Toggle left hand panel">
<i class="fa fa-angle-double-left"></i>
</span>
</div>
<div class=${css.treeview}>${fileExplorer}</div>
</div>
${dragbar}
</div>
`
}
var api = new EventManager()
var element = template()
element.api = api
fileExplorer.api.register('focus', function (path) {
api.trigger('focus', [path])
})
return element
function toggle (event) {
var isHidden = element.classList.toggle(css.isHidden)
this.classList.toggle(css.isVisible)
this.children[0].classList.toggle('fa-angle-double-right')
this.children[0].classList.toggle('fa-angle-double-left')
api.trigger('ui', [{ type: isHidden ? 'minimize' : 'maximize' }])
}
function uploadFile (event) {
;[...this.files].forEach(fileExplorer.api.addFile)
}
function mousedown (event) {
event.preventDefault()
if (event.which === 1) {
moveGhostbar(event)
document.body.appendChild(ghostbar)
document.addEventListener('mousemove', moveGhostbar)
document.addEventListener('mouseup', removeGhostbar)
document.addEventListener('keydown', cancelGhostbar)
}
}
function cancelGhostbar (event) {
if (event.keyCode === 27) {
document.body.removeChild(ghostbar)
document.removeEventListener('mousemove', moveGhostbar)
document.removeEventListener('mouseup', removeGhostbar)
document.removeEventListener('keydown', cancelGhostbar)
}
}
function moveGhostbar (event) {
var rhp = window['righthand-panel'].offsetLeft
var newpos = (event.pageX < limit) ? limit : event.pageX
newpos = (newpos < (rhp - limit)) ? newpos : (rhp - limit)
ghostbar.style.left = newpos + 'px'
}
function removeGhostbar (event) {
document.body.removeChild(ghostbar)
document.removeEventListener('mousemove', moveGhostbar)
document.removeEventListener('mouseup', removeGhostbar)
document.removeEventListener('keydown', cancelGhostbar)
var width = (event.pageX < limit) ? limit : event.pageX
element.style.width = width + 'px'
api.trigger('ui', [{ type: 'resize', width: width }])
}
function createNewFile () {
var newName = appAPI.createName('Untitled')
if (!files.set(newName, '')) {
alert('Failed to create file ' + newName)
} else {
appAPI.switchToFile(newName)
}
}
}

@ -0,0 +1,40 @@
'use strict'
var examples = require('../../src/app/example-contracts')
var init = require('../helpers/init')
var sauce = require('./sauce')
var sources = {
'sources': {
'ballot.sol': examples.ballot.content,
'test/client/credit.sol': '',
'src/voting.sol': '',
'src/leasing.sol': '',
'src/gmbh/contract.sol': false,
'src/gmbh/test.sol': false,
'src/gmbh/company.sol': false,
'src/gmbh/node_modules/ballot.sol': false,
'src/ug/finance.sol': false,
'app/solidity/mode.sol': true,
'app/ethereum/constitution.sol': true
}
}
module.exports = {
before: function (browser, done) {
init(browser, done)
},
'@sources': function () {
return sources
},
'FileExplorer': function (browser) {
runTests(browser)
},
tearDown: sauce
}
function runTests (browser, testData) {
browser
.waitForElementPresent('#filepanel ul li', 10000, true, function () {})
.end()
}
Loading…
Cancel
Save