atom-archive / space-pen Goto Github PK
View Code? Open in Web Editor NEWA simple and powerful client-side view framework that works in zero-gravity, no longer maintained.
License: MIT License
A simple and powerful client-side view framework that works in zero-gravity, no longer maintained.
License: MIT License
Hey again Nathan! What are you thoughts on this topic either via an unpublished feature or patch that would make this possible? Some background... I am using SpacePen as my view system in all my Spine.JS apps. I typically have a handle to some views from my controller and as well often set my model instance to the views data()
via the attach event. So no matter what, my view knows which model/params it was rendered with.
Spine.JS has a lovely feature in its ORM that basically means any model instance automatically reflects changes when any other instance is saved. So that means that if I did dig down to my SpacePen's view.data('mymodel')
that I would see said changes. So now I am wondering if I can just trigger some sort of re-build or re-render at the view layer. Looking over the SpacePen code I did not see a way I could easily do this. I tried calling .buildHtml(model)
on the view again, but to no avail. That threw this error.
TypeError: Object function ( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); } has no method 'content'
Thoughts? Should I just render a new view and tell one view to replace itself with the new?
When I follow the instructions in the readme to test I get this error. I would go in and try to fix it but I don't know grunt or browserify ...
I'm on windows 8.1 with space-pen 5.0.1.
Edit: The error seems to be due to forward slashes in a windows command.
C:\apps\space-pen>npm start
> [email protected] start C:\apps\space-pen
> grunt start
Running "coffee:lib" (coffee) task
File lib/space-pen.js created.
Running "coffeelint:src" (coffeelint) task
>> 1 file lint free.
Running "coffeelint:test" (coffeelint) task
>> 5 files lint free.
Running "coffeelint:gruntfile" (coffeelint) task
>> 1 file lint free.
Running "shell:browserify" (shell) task
'node_modules' is not recognized as an internal or external command,
operable program or batch file.
Warning: Command failed: cmd.exe /s /c "node_modules/.bin/browserify -t coffeeify spec/spec-helper.coffee -o spec/spec-helper.js"
'node_modules' is not recognized as an internal or external command,
operable program or batch file.
Use --force to continue.
@checklists.append "<div class='item'>#{description}</div>"
How apply event click on item that append on checklists?
Maybe im mistaken on the correct use of the @subview
method.
class TableView extends View
@content: (rows) ->
@div =>
@table name: 'rate', outlet: 'rate', =>
@thead =>
@th "header 1"
@th "header 2"
@th "header 3"
@tbody =>
for row, index in rows
@subview "row_#{index}", new RowView(row)
class RowView extends View
@content: (row) ->
@tr =>
@td row[0]
@td row[1]
@td row[2]
rows = [["1.1", "1.2", "1.3"], ["2.1", "2.2", "2.3"]]
$('.content').html(new TableView(rows))
generates the following HTML
<div callattachhooks="true">
<tr callattachhooks="true">
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
</tr>
<tr callattachhooks="true">
<td>2.1</td>
<td>2.2</td>
<td>2.3</td>
</tr>
<table>
<thead>
<tr>
<th>header 1</th>
<th>header 2</th>
<th>header 3</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
and I was expecting
<div callattachhooks="true">
<table>
<thead>
<tr>
<th>header 1</th>
<th>header 2</th>
<th>header 3</th>
</tr>
</thead>
<tbody>
<tr callattachhooks="true">
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
</tr>
<tr callattachhooks="true">
<td>2.1</td>
<td>2.2</td>
<td>2.3</td>
</tr>
</tbody>
</table>
</div>
This is less of an issue and more of a conversation piece. I was looking at the code that did the attach event trigger and how you have to redefine methods like append, prepend, etc. I was wondering why you did not tell people about "DOMNodeInserted" and avoid all that method redefinition?
I would expect the constructor of a View to be able to set up variables to be used in the content, as below. This is not the case, because the content function is called before the constructor, which is very surprising, and not mentioned in the docs.
Since View::initialize
is called from View::constructor
, it also has the same surprising behavior.
Test case:
class FooView extends View
initialize: ->
@fooCount = 1
@content: ->
@p "There are #{@fooCount} foos."
The document then contains There are undefined foos.
instead of the expected There are 1 foos.
.
I was playing around and tried to do @tag 'atom-text-editor', <stuff>
and it complains with a very specific error indicating that because it is a custom element inheritance needs to be used.
Any way to make that work?
I'm wanting to use space-pen on the client and wanting to use bower for my front end package management. Just wondering if you guys have thought about creating a bower package?
Is there a tutorial on getting started using this in my project anywhere to be found?
Having a look at the following method
extractOptions: (args) ->
options = {}
for arg in args
switch typeof(arg)
when 'function'
options.content = arg
when 'string', 'number'
options.text = arg.toString()
else
options.attributes = arg
options
I think it would be interesting to add the following change:
extractOptions: (args) ->
options = {}
for arg in args
switch typeof(arg)
when 'function'
options.content = arg
when 'string', 'number'
options.text = arg.toString()
# CSS selector #
when 'array'
options.selector = arg.join('.')
else
options.attributes = arg
options
This way one could write something like this:
# before makeup
@a id: "submit", class: "button shinny", href: "http:example,com", "Submit"
# after
@a ["#submit.button.shinny"], href: "http:example,com", "Submit"
# or
@a ["#submit", "button.shinny"], href: "http:example,com", "Submit"
# or even
@a ["#submit", "button", "shinny"], href: "http:example,com", "Submit"
It would be reverse compatible with the current DSL while providing a closer CSS selector approach.
Also if you don't use the array selector it shouldn't impact much current performance.
Sorry I'm coming from HAML world and feel more comfortable with that notation, but I think I'm not the only one that would benefit from this.
Tell me if you like this and I can propose a pull request.
The Github pages index still documents the old attach/detach handlers instead of the new ones. Took me a bit of time to realize it was out of date with the readme. It'd be nice if someone could rerun the page generator so that doesn't confuse anyone else in the future.
Probably related to #57.
I have an issue trying to create an atom-panel
element: @tag 'atom-panel'
.
However I don't have any issue using a custom element that is not built-in: @tag 'foobar'
.
Here is the error message:
Failed to execute 'registerElement' on 'Document': Registration failed for type
'space-pen-atom-panel'. The tag name specified in 'extends' is a custom element
name. Use inheritance instead.
The code here: https://github.com/atom/space-pen/blob/master/src/space-pen.coffee#L349 has an improper use of .attr
. .attr
changed it's operation in jQuery 1.6. From the jQuery docs ...
The .prop() method should be used to set disabled and checked instead of the .attr() method.
This type of jQuery nailed me bad recently. See atom/atom-space-pen-views#4.
This is the offending code. Do you want a PR?
$.fn.isDisabled = ->
!!@attr('disabled')
$.fn.enable = ->
@removeAttr('disabled')
$.fn.disable = ->
@attr('disabled', 'disabled')
I have a view in atom where I wish to display a canvas using raphael.js (thread here). This requires functions such as:
paper = new Raphael(document.getElementById("canvas_container"), 500, 500);
I've created a view which contains script tags for raphael and the script I'd like to execute:
@content: ->
@div class: 'block', id: 'plasmidDisplayBase', =>
@script type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js'
@div id: 'canvas_container', width: 'width: 500px; border: 1px solid #aaa'
@script type: 'text/javascript', =>
@raw fs.readFileSync("#{__dirname}/raphael-display.js").toString()
where raphael-display.js simply contains the code:
window.onload = function(){
console.log("EXECUTING");
paper = new Raphael(document.getElementById("canvas_container"), 500, 500);
var circle = paper.circle(50, 40, 10);
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");
}
When I console.log the created view, I get
<div class="block" id="plasmidDisplayBase" callattachhooks="true">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js"></script>
<div id="canvas_container" width="width: 500px; border: 1px solid #aaa"></div>
<script type="text/javascript">
window.onload = function(){
console.log("EXECUTING");
paper = new Raphael(document.getElementById("canvas_container"), 500, 500);
var circle = paper.circle(50, 40, 10);
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");
}
</script>
</div>
This appears to be what I want, but no EXECUTING message is logged to the console, and no raphael canvas is displayed. How should I interact with external javascript in this manner? Can I do this with space pen?
I tried to create a convenience for myself in a ModelView subclass of View that my models will subclass (e.g. UserView).
As a simplified example:
class ModelView extends View
constructor: (@model, @mutable) -> super @model, @mutable
@propertyView: (property, klass, label) ->
@subview property, new klass { @model, property, label, @mutable }
class UserView extends ModelView
@content: ->
@propertyView 'firstName', TextView
class TextView extends View
@content: (params) -> @input params.model.get params.property
class User: # a model, say from Parse
get: (property) -> 'Brian' # whatever
me = new User
me.set 'firstName', 'Brian'
$('body').append (new UserView me, yes)
However, this isn't working as expected and I could use a push in the right direction since I'm new to CoffeeScript and SpacePen.
The error is that in TextView, params.model is undefined.
As I expected, in the constructor of ModelView, @model is being saved as an instance var.
function ModelView(model, mutable) {
this.model = model;
this.mutable = mutable;
ModelView.__super__.constructor.call(this, this.model, this.mutable);
}
The View constructor calls @content immediately so it seems that @model is not being set after all? I think I'm a bit confused why the content is @content (static property) and not 'content' ... What am I missing? Thanks!
It would be nice to use space-pen notations in instances of an View an not just on construction.
So this example:
class TableView extends View
@content: ->
@table =>
@tbody outlet: 'body'
update_rows: (rows) ->
for row in rows
@body.append "<tr><td>#{row[0]}</td><td>#{row[1]}</td></tr>"
That also can be written this way:
class TableView extends View
@content: ->
@table =>
@tbody outlet: 'body'
update_rows: (rows) ->
for row in rows
@body.append new Row(row)
class Row extends View
@content: (row) ->
@tr =>
@td row[0]
@td row[1]
could be turned into this which I would prefer:
class TableView extends View
@content: ->
@table =>
@tbody outlet: 'body'
update_rows: (rows) ->
for row in rows
@body.append @row(row)
row: (row) ->
@partial =>
@tr =>
@td row[0]
@td row[1]
This way you don't have to instantiate a new class for using space-pen syntax
I tried to do:
@content: ->
@div outlet: 'foo'
Much to my chagrin, @foo
was not accessible. If I put an outlet on a nested div, it works fine. Is this intended?
In converting find and replace, I am getting this error:
I assume this is because I have a different version than that of some other package who got to registering this tag. Looks like there is no method to check if the element has been registered. I suppose we could try/catch. My guess is that this will happen in the wild.
When i use prependTo
, appendTo
, insertAfter
, insertBefore
method, callAttachHook execute twice.
But use append
, prepend
, after
, before
method, hooks just execute once.
It seems using @br
doesn't work. Right now I'm using @raw '<br>'
but I'm wondering if there's a better way to do this.
Thanks.
I have a very simple view:
{View} = require 'atom'
class MyView extends View
focus: -> @input.focus()
initialize: (on_url) =>
...
attached: ->
debugger; # never reached
@content: ->
@div =>
@input outlet: 'input', style: "width: 100%;", value: "https://asdf.com/"
and dump it into the DOM via:
atom.workspace.addModalPanel({item: new MyView()});
Am I missing something simple?
I watched this project with great interest. While it's fine that it wasn't continued as an Atom component, I am interested in why it has been abandoned, and what replaced it. This is more just for educational purposes and an effort to improve my conception of that might be a factor in such ui-speed-driven (I assume?) decisions.
A short blurb in the intro might fix this for me and the other ~500 people who have starred it.
The package.json says that main
is lib/space-pen.js
, but this file (generated by grunt I'm guessing) isn't included under files
. Or at least that's my guess for why require
isn't working.
For example, this would silently fail to construct the subview:
class Spacecraft extends View
@content: (params) ->
@subview 'launchController', new LaunchController(countdown: params.countdown)
@h1 "Spacecraft"
...
The requirement seems fine (slightly restrictive, but not more than similar frameworks); the only real problem is the silent and undocumented failure.
I'm really like that space-pen works and am trying to really use it in anger for client side web development. I know that this mightn't be its current primary use, but I think it has a lot of potential. The main thing that I keep scratching my head on is the dependency on jqeury
, jquery extensions
, underscore
and underscore extensions
.
I understand why these exist and that they make life extremely covenant but I'm wondering if the core of space-pen actually needs this. The question that I'm wondering is what functions does the actual core engine itself need to work vs how much is nice for devs to work with when using space-pen. If the core didn't depend on these, the overall amount of bytes one needs to use space-pen is reduced dramatically.
To start with, from what I can tell, very few of the methods in jQuery extensions
are actually used, and the only function in underscore plus
used is humanizeEventName
and likewise with underscore
the only one used is extend
. From this quick look, it would appear that underscore
and underscore-plus
could be removed as a core dependency saving around 20kb and another 4-5kb saved by removing jQuery extensions
.
Removing jQuery
on the surface seems like its a bit more difficult, given that it inherits from view. But putting aside for a moment, the only functions in jQuery
itself that seem to be in use is data
and on
, the former seems like it could be removed fairly easily and I'm wondering if the later could be an enhancement. As for the view being an actual jQuery
object, could this also be treaded as an optional enhancement if jQuery
exists. In my case, I could jQuery
or one of the jQuery-compatible APIs if I want/need.
So, knowing space-pen more than I, do you think that this would be possible, could the current extra code that isn't need by core but needed by atom
be abstracted out and included just it in another way?
A handler passed to $.fn.preempt
gets wrapped by jQuery in some fancy object that includes a guid
. It would be most excellent if $.fn.preempt
could return that wrapped handler so that it could later be passed to off()
to remove said handler.
From this discussion, it sounds like the goal is to use Emitter as a mixin for SpacePen's View so that on()
returns a Subscription
that has an off()
method that can be used to remove the listener.
I worry that this is going to be a bit of a pain because space-pen-extensions.coffee already mixes in a similar class:
Subscriber.includeInto(spacePen.View)
Currently, the implementation of command()
is super(commandName, selector, options, handler)
, which I believe delegates to this method:
$.fn.command = (eventName, selector, options, handler) ->
if not options?
handler = selector
selector = null
else if not handler?
handler = options
options = null
if selector? and typeof(selector) is 'object'
options = selector
selector = null
@document(eventName, _.humanizeEventName(eventName, options?['doc']))
@on(eventName, selector, options?['data'], handler)
So perhaps, at least as a stopgap, this method could return an object with an off()
method that removes the listener (and releases appropriate references), and at some point in the future, the return value could be a true Subscription
, which would have the same contract? As it stands today, SpacePen appears to have minimal dependencies (underscore-plus
being the only one), so it would be nice to be able to get this feature today without having to wait for all of this jQuery/Emitter/Subscription stuff to be figured out.
I'm in the process of looking at creating the bower package for space-pen and looking at the dependencies I noticed something weird.
Space-pen tries to take a dependency on jquery-extensions
if it "requirable" but if its not, just falls back to window.jquery
- here.
So I have couple of questions:
jquery
, why try for jquery-extensions
jquery-extensions
wasn't available (assuming its needed), it tried to require jquery
. Then, at that point, if require shows up empty, go to window.jquery
Does this make sense?
Hi there
if you use a subview in root level of a view it does not work. Like this:
$('.other-class').append $$ ->
@div id: 'foobar', =>
@button class: 'btn selected', 'data-display-class': 'show-bar', 'bar'
@button class: 'btn', 'data-display-class': 'show-data', 'data'
@subview '__', [subview...]
I digged into it and found what could be the problem. Within Builder.prototype.subview
there is following part which will not work with the example above:
return this.postProcessingSteps.push(function(view) {
view[outletName] = subview;
subview.parentView = view;
return view.find("div#" + subviewId).replaceWith(subview);
});
The returned view
contains all the root elements (here: div#foobar
, div#subview-\d+
).
Now .find(...)
tries to find div#subview-\d+
but as it is one of the root elements it can't find it.
A workaround for me was simply to add a div around the subview. But you have to know that first. : )
Any docs regarding how to compile and serve the coffee view files as JS?
Thanks!
What license is this distributed under? Can you add a LICENSE or MIT-LICENSE file?
I have a view defined as this:
@content: ->
@div =>
@h1 "Take a Register"
@table class: 'table hovered', =>
@thead =>
@tr =>
@th "Class"
for session in Session.all()
@th session.name
@tbody =>
for klass in Class.all()
@tr =>
@td klass.name
for session in Session.all()
@subview 'sessioncell', new SessionCellView(klass, session)
the first for session...
works fine adding X number of table headings the second is supposed to add a subview which (for the moment) looks like this:
@content: (klass, session) ->
@td =>
@span klass.name + session.name
but when this gets rendered the page html is actually:
<div callattachhooks="true">
<h1>Take a Register</h1>
<td callattachhooks="true"><span>CL1Morning</span></td>
<td callattachhooks="true"><span>CL1Afternoon</span></td>
<td callattachhooks="true"><span>CL2Morning</span></td>
<td callattachhooks="true"><span>CL2Afternoon</span></td>
<td callattachhooks="true"><span>CL3Morning</span></td>
<td callattachhooks="true"><span>CL3Afternoon</span></td>
<td callattachhooks="true"><span>CL4Morning</span></td>
<td callattachhooks="true"><span>CL4Afternoon</span></td>
<td callattachhooks="true"><span>CL5Morning</span></td>
<td callattachhooks="true"><span>CL5Afternoon</span></td>
<td callattachhooks="true"><span>CL6Morning</span></td>
<td callattachhooks="true"><span>CL6Afternoon</span></td>
<td callattachhooks="true"><span>RECMorning</span></td>
<td callattachhooks="true"><span>RECAfternoon</span></td>
<table class="table hovered">
<thead>
<tr>
<th>Class</th>
<th>Morning</th>
<th>Afternoon</th>
</tr>
</thead>
<tbody>
<tr>
<td>CL1</td>
</tr>
<tr>
<td>CL2</td>
</tr>
<tr>
<td>CL3</td>
</tr>
<tr>
<td>CL4</td>
</tr>
<tr>
<td>CL5</td>
</tr>
<tr>
<td>CL6</td>
</tr>
<tr>
<td>REC</td>
</tr>
</tbody>
</table>
</div>
Anyone got any ideas as to the problem?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.