UNPKG

oj

Version:

A unified templating language for the people. Thirsty people.

998 lines (708 loc) 28.4 kB
.plan ===== Need ------------------------------------------------------------------------------- ### Bugs * GO THROUGH ALL EXAMPLES FOR JS / CS * Make sure all ids on headers make sense * JS and CS buttons do not toggle all editors * First load of TryEditor looks horrible * website docs figure out what is missing * website docs add live examples * Remove sandbox? * DOCS need to spacing on links for code anchors Document jQuery ojAppend oj ### Website * website learn page * Top spacing to show header off #anchor-tag * create js * advanced css * media query * Binding List to model * Binding table to model * Creating a Type * Creating a ModelType * Creating a CollectionType * Download page should say stuff=) Want ------------------------------------------------------------------------------- ### Objects * Try to shrink the size of oj.js by 50% * Perf test OJ and then speed up HTML/CSS creation, and DOM manipulation * Add oj to jsfiddle.net as includable library * Add oj and plugins to one of the open source CDN (http://cdnjs.com/) * JSFiddle doesn't work in anything but chrome (this is jsfiddle.net bug) * Bug: Literal notation should not require object at start. Use argumentsUnion (improves OJML examples) * Commandline: Add --html option to build only the html (no js) * Commandline: Add --js option to build on .js file * Commandline: Add --css option to build on .css file * Validation on form elements validate:(value) -> if value blasjdf return 'failure message' TextBox '2062189935', validate:oj.validPhoneNumber((err)-> if err alert('error happened'))), validate * Bug: Fix .on handlers in attribute events (multi argument event bindings) * Bug: Allow tags to take html snippets: oj.div('<u>underlined stuff</u>') * Allow css to take raw css for plugins * Feature: Consider adding Events to objects * Feature: Compile.ojlc files as literate coffee-script * GoogleChart plugin * Area (P1) * Bar (P1) * Bubble (P1) * Candlestick (P2) * Column (P2) -- Fancy Bar Chart * Combo (P1) * Guage (P3) * Geo (P1) * Line (P2) * Pie (P1) * Timeline (P1) * TreeMap (P1) * Trendlines (P2) * Table (P2) * Scatter (P1) * Google Analytics plugin * Google AdWords plugin * Create enums * Consider event support on oj.Types * Bootstrap Plugin * Add concept of defaultThemes to Types oj.Bootstrap.Button (P1) oj.Bootstrap.BulletList (P1) oj.Bootstrap.NumberList (P1) oj.Bootstrap.List (P1) oj.Bootstrap.InlineList (P1) oj.Bootstrap.Table (P1) theme:['striped', 'hover'] oj.Bootstrap.HorizontalDivider ... * oj.Page * Figure out page navigation and virtual page navigation - Can I navigate to foo/bar, where bar transitions rather then refreshes? - Triggering off of URL - may require manual requiring of pages that can be transitioned to * Should interface with oj.load * Should interface with commandline tool to prepackage loadable pages * oj.Grid (consider how this integrates with Boostrap, if at all) - CSS Grid framework made easy * oj.Tabs * oj.Form * Support form creation and submition with validation * Consider moving Form elements into this plugin * oj.Image * Consider if * oj.SpriteImage * Support positioned sprites in background image * oj.FontImage * Support images derived from fonts. * Consider if needs Bootstrap integration * oj.NGridImage * Support n grid * consider support for sprites either in this object or SpriteImage * oj.Bootstrap.Grid * oj.Bootstrap.NavBar * oj.SearchBox (text box + filter list) * oj.FilterBox (list box + filter list to choose) * oj.FacebookLikeButton -- embed a Facebook like button * oj.GooglePlusButton -- embed a GooglePlusButton * oj.TwitterTweet -- embed a tweet * Optimization: Look up if _.filter and _.map are implemented in IE9+. Remove if so. * Optimization: Look up underscore utilities to see if they exist in IE9+. Remove if so * Optimization: Factor out the two methods needed from path to reduce file size (omit windows specific stuff) * Unit tests: for build, watch, compile by string * Unit test for View.removeAttribute and View.removeAttributes * Write unit tests to verify properties can inherit get and set separately * OJ static generator: client side unit tests Like ------------------------------------------------------------------------------- * oj.GoogleMap * oj.BingMap * oj.ScribdDocument * oj.Region liquid:true; n grid region with fixed width that grows with content liquid:false; n grid region with fixed width and height. Supports layers of images - consider horizontal region, vertical region - consider grid related regions - consider Row, Column as namings. (dynamic grid stuff?) * Linked plugin doesn't recompile with watch enabled * Bug: .json file type doesn't get sent to the client correctly in .oj and .ojc files Questions ------------------------------------------------------------------------------- Server-side Thinking =============================================================================== Usage: oj [options] <file> <dir> ... Options: -h, --help output usage information -V, --version output the version number -m, --minify Turn on minification (default: false) -w, --watch Turn on watch mode (default: off) -r, --recurse Recurse into directories (default: off) -o, --output <dir> Directory to output all files to (default: .) -v, --verbose <level> Turn on verbose level 0-3 (default: 1) -e, --exclude <modules> List of modules to exclude (jquery,oj,...) Output Options: --unify Output html/css/js into a single .html file --html Output only the html --css Output only the css --js Output only the js --js-modules Output the modules.js file Path Options: --modules-dir Directory to find modules.oj or modules.ojc --html-dir --css-dir --js-dir oj . foo --output www/ --jsdir foo/scripts --cssdir foo/styles --output-module foo/scripts/modules.js --js Output .js files only --js-modules Output modules.js that includes js (modules only) --js-pages Output js pages require oj jquery modules --script <dir> --style <dir> --module <dir> Events ------------------------------------------ thingy = Thingy({ // Will bind on('inserted', fn) events:{ // This is automatically bound when insertions happen inserting:function(){ }, 'inserted':function(){ } } thing.inserted.on(function(){ }) }) thingy.trigger('foobar:bar') thingy.on('click', function(){}) thingy.off(fn) thingy.one(function(){}) Questions on Versions ------------------------------------------ Go core or not? Pros: Illusion of smaller Form, List and Table can evolve seperately Cons: Breaks compatability Harder to get started Almost everyone will need Forms and List for complex things Work Separate Form, List, Table Add placeholder for Form, List, Table that when executed throws warning module is missing 0.2.0 Rewrite in JS 0.2.1 load event on tag functions 0.2.2 oj command - Build unified files ------------------------------------------------------------------------------ --unify oj command - Build full website ------------------------------------------------------------------------------ Build a static website with enough configuration to make it structured however you want. Reuse options that express needs / index.oj -> index.html and pages/index.js modules.oj modules/ modules.oj -> will convert to modules.js pages/ index.js login.js blog/ index.js scripts/ test.js test.oj -> will convert to test.js styles/ test.oj -> will convert to test.css Pick a directory --modules --modules-output-dir oj express - Build full website ------------------------------------------------------------------------------ app.use(oj.middleware({ modulesInDir:__dirname + "/modules", modulesOutDir:__dirname + minify: false })) Form Validation ------------------------------------------------------------------------------- CreditCardTextBox PhoneNumber credit card inList: (list) -> (v, prop) -> if not list?.indexOf? or list.indexOf(v) == -1 then "#{prop}: #{v} is not in list: #{list}" inEnum: (enumList) -> (v, prop) -> if not enumList?.indexOf? or enumList.indexOf(v) == -1 then "#{prop}: #{v} is not in enum: #{enumList}" range: (min, max) -> (v, prop) -> if v < min or max < v then "#{prop}: #{v} is not in range: [#{min}, #{max}]" min: (min) -> (v, prop) -> if v < min then "#{prop}: #{v} is too small for min: #{min}" max: (max) -> (v, prop) -> if v > max then "#{prop}: #{v} is too large for max: #{max}" lessThan: (num) -> (v, prop) -> if v >= num then "#{prop}: #{v} is too large for lessThan: #{num}" moreThan: (num) -> (v, prop) -> if v <= num then "#{prop}: #{v} is too small for moreThan: #{num}" lengthRange: (min, max) -> (v, prop) -> if not v?.length? or v.length < min or max < v.length then "#{prop}: #{v}.length is not in range: [#{min}, #{max}]" lengthMin: (min) -> (v, prop) -> if not v?.length? or v.length < min then "#{prop}: #{v}.length is too small for min: #{min}" lengthMax: (max) -> (v, prop) -> if not v?.length? or v.length > max then "#{prop}: #{v}.length is too large for max: #{max}" lengthLessThan: (num) -> (v, prop) -> if not v?.length? or v.length >= num then "#{prop}: #{v}.length is too large for lessThan: #{num}" lengthMoreThan: (num) -> (v, prop) -> if not v?.length? or v.length <= num then "#{prop}: #{v}.length is too small for moreThan: #{num}" Advanced Control thinking ------------------------------------------------------------------------------- View el Core Form values # readwrite, map from element key to value elements # map from element key to OJ instance (readonly) submit() # submit the form reset() # reset all elements clear() # clear all elements Form FormView clear() reset() validate:-> Button type: 'submit' # Can be submit, reset, or null. # It will bind submit and reset automatically CheckBox value: true/false TextBox # Edit box TextArea # Big area text box ListBox # Pull down list box FilterBox # Multi select. http://rmm5t.github.com/jquery-flexselect/ PasswordBox # Text box wit1h type:'password' set. Button # Button ResetButton # Helper button that automatically resets the form SubmitButton # Helper button that automatically calls submit CreditCardBox # (P3) PhoneNumberBox # (P3) RichTextBox SearchBox # Like filter but uses ajax Need Form.TextFilterBox # Text + List box. Typing filters Tabs Image ToolTip # Built in to all controls? Form.FileBox # File upload + drag and drop Want Watch should trigger off of changes to required files (partials, templates) This is pretty hard. Possibly watching triggers watching deeply as require is called LightBox # Pop with screen darkening Calendar Form.DateBox # w/Calendar popup Form.CreditCardBox Form.ProgressBar Form.SliderBar Google.Maps # Hard but so important Google.Plus.FollowMe Facebook.LikeMe Facebook.FollowMe Twitter.FollowMe Twitter.FollowCount GitHub.FollowCount GitHub.Repo Like CollapsiblePanel ColorPicker Rating # Star rating Docking # Drag targets for elements, so hard DragAndDrop # So hard... probably just go with jquery ImageSlider # http://dev7studios.com/nivo-slider/#/support Grid # Display grid to help designers. ZoomBox # http://www.mind-projects.it/projects/jqzoom/demos.php#demo1 TreeMenu Button Input TextArea SubmitInput Table id -> inserted in the dom $el awakens it Table id dom fragment Bootstrap thinking ------------------------------------------------------------------------------- oj.use require(oj-bootstrap), global:true oj.Bootstrap.Table theme:['striped', 'hover'] oj.Bootstrap.Button DropDownButton size: large,small, mini SplitButton Tabs add -> Bootstrap.Tab 'Name', href:'#fooaction' remove get(3).disabled = true move Pills add -> Bootstrap.Pill 'Name', href:'#fooaction' remove move disable(3) enable(3) NavList // have to think about headers HorizontalDivider TabbableNav direction: 'left', 'below', 'above', 'right' NavBar position: 'fixed-top', 'fixed-bottom', 'static-top' responsive: true inverse: true NavBrand NavLink NavVerticalDivider NavForm NavSearchBox NavButton align: 'left', 'right' NavDropDown alias NavListBox Breadcrumbs Pagination Pager Label 'default', 'success', 'warning', 'important', 'info', 'inverse' Badges 'default', 'success', 'warning', 'important', 'info', 'inverse' Hero PageHeader Thumbnail span:4, image: 'foo.bar.js' Alert ProgressBar theme:'default', 'basic', 'striped', 'animated', 'stacked', color:'warning' MediaObject MediaList Well Icon Div align:'left', 'right', 'center' emphasis: 'warning', 'muted', 'error', 'info', 'success' Abbreviation title:'full text', short text address blockquote BulletList NumberList List (unstyled) InlineList Code Model thinking ------------------------------------------------------------------------------- Table inherits: CollectionView each: (model) -> rows: [list of lists of ojml] (readwrite) row: (r) -> [list of oj or element] (readwrite) cell: (r,c) -> oj or element (readwrite) cellCount (readonly) rowCount (readonly) methods: addRow(index) removeRow(index) make creates <table> empty internals: on change doesn't matter because the row / cell will do it on add -- uses each to add a thing on remove -- closes handlers on cells, row, and deletes row Table.Row inherits: ModelView make: -> tr ... model: bind a model each: (model)-> [list of ojml] row: -> get/set row all at once cell: (c) -> oj or element cellCount (readonly) addCell: (c) -> removeCell: (c) -> Layout Thinking ------------------------------------------------------------------------------- Page scripts styles title body: -> Layout OneQuarterRight, small: -> large: -> body -> GG columns:[25,75], header: -> first: -> second: -> third: -> fourth: -> fifth: -> left: -> middle: -> right: -> footer: -> <button class:'oj-Button'> Layout columns: [1/3,1/3,1/3] engine:'gg' engine:'bootstrap' header:-> left:-> middle:-> right: -> footer:-> Grid columnRatios: [1,3] Layout left, right, header, footer Button ------------------------------------------------------------------------------- image = Image(grid:{n:1,2}) image: forState: :normal :selected :hover :depressed TextTheme RegionTheme image nine grid nw,n,ne sw,s,se Mixin ------------------------------------------------------------------------------- Mixin - Link Colors: style = require('oj-style-link-colors')(normal, hover, active, visited, focus) Mixin - Link Hover: oj.css require('oj-css-link-hover')() Mixin - Compass CS3 support http://compass-style.org/reference/compass/css3/ Special Tags .scripts type: 'foo' // optional list // list of script paths .styles type: 'foo' // optional list // list of css paths .link url: // same as href label: // text being displayed .H1 to .H6 anchor: // wraps in anchor with this name .Row // Panel designed to seperate stuff vertically // inherits from Panel .Column // Panel designed to seperate stuff horizontally .Row [] .Link Model-Each strategy div -> Table models:models, each: (model) -> [Checkbox model:model, key:'male', 3, new Date()] div -> List ordered:false, models:models, each: (model) -> a -> model.name Argument strategy div -> Table -> for model in models argument -> [(Checkbox model:model, key:'male'), 3, -> (div 'asdf')] Table models:models, each: (model, col, row) -> row -> col -> Checkbox model:model, key:'male' col -> div 'asdf' Table models:models, each: (model, col, row) -> row -> col -> Checkbox model:model, key:'male' col -> div 'asdf' List models:models, each: (model, item) -> model.name Documentation ========================================================================== OJ Download Learn Docs Plugins Express Blog OK, I'm here. What is OJ? -------------------------------------------------------------------------- OJ is a JavaScript library that helps you create websites with objects. For example the oj.Button object makes buttons and the oj.YouTubeVideo object makes -- wait for it -- YouTube videos! (YouTubeVideo) These objects create their own html and JavaScript event bindings so they _have no depedencies_. Simply include them with the package manager of your choice (npm or bower) and they will _just work_: That sounds cool. Who is this for? -------------------------------------------------------------------------- OJ is best used server-side with Express. It uses npm as a package manager even will gather and minify your modules together so they can run client-side seamlessly. If you love trying out template engines like Jade, Less, or CoffeeCup, OJ is going to impress you. (Get started with Express) For static pages there is an [oj commandline tool]() that will watch, compile, and minify everything for you in a similar way the Express support does. (Get started with commandline) For those folks wanting just client-side just `<script>` include oj.js. (Get started with client-side) What does the core oj.js library include? -------------------------------------------------------------------------- The library gives you objects to create form elements: [oj.TextBox](), [oj.Button](), [oj.ListBox](), [oj.CheckBox](), as well as other basic tags: [oj.NumberList](), [oj.BulletList]() and [oj.Table](). In addition the core library handles compiling html/css (server side) and dom creation and event binding (client side). Lastly you can create your own objects with the [oj.createType]() function, and at its lowest level lets you create html tags directly with [tag functions](). (example of a table of form elements?) What plugins exist so far? -------------------------------------------------------------------------- Check out the full list here: [ojjs.org/plugins.html](ojjs.org/plugins.html). Really, OJ plugins can do almost anything that is useful. One of my favorites is oj.markdown: (markdown) I'm afraid to ask... is OJ an MVC framework? =) -------------------------------------------------------------------------- No it isn't! OJ is just the _View_ layer, and nothing else. It doesn't make Models or Controllers. In fact, there is no reason OJ couldn't be used as the rendering layer for actual MVC frameworks, especially the ones still using mustache templating! That said, OJ does support two-way binding to Backbone Models and Collections. The reasoning behind this is a good View needs to be able to update as data changes. Backbone seemed a good choice to support right away, but there is no reason an adaptor couldn't be written to support other model systems. Take a look at these form elements bound to a Backbone model. Changing one changes them all! (Backbone binding example) The Apocalypse is Nigh! -------------------------------------------------------------------------- That isn't a question, but I understand where you are coming from=). In my quest to make websites with objects OJ had to do _a lot_ more with JavaScript then people usually do. Since this is all server-side and in many cases can even be pre-compiled I think of OJ as more of templating engine with cool objects you can add to your page. JavaScript is just the medium, but it is no different from other templating engines like Jade or Less before it. I'm sold, what do I do next? -------------------------------------------------------------------------- The best way to start depends on what you want to do: Get started with Express in JavaScript or CoffeeScript Get started with making a static site with the CLI tool in JavaScript or CoffeeScript. Get started client-side in JavaScript. Note: OJ was written in JavaScript but was designed with CoffeeScript syntax in mind. It is great in both. Contact Info -------------------------------------------------------------------------- IRC: [freenode.net#oj](http://webchat.freenode.net/?channels=oj) Email: [evan@ojjs.org](mailto:evan@ojjs.org) Twitter: @evanmoran Repo: github.com/ojjs/oj # How To Create a Static Website with the OJ CLI Tool OJ has a [commandline tool](http://ojjs.org/docs.html#commandline) that can build OJ server-side. This will get you started: ## Installing Commandline Tool (1) Install node (2) Install the `oj` commandline tool with npm: npm install -g oj (3) Install the `yeoman` tool: npm install -g yeoman (4) Install the Yeoman `generator-oj` tool: npm install -g generator-oj (5) Create your project using Yeoman: yo oj:static (6) Use to OJ CLI tool to build your static website! oj . --minify --watch Note: the OJ tool traverses through `require` includes and unifies all files together. It can inculde node modules such as `underscore`, `backbone`, etc, the same way. These will be picked up from your `package.json` file as you would expect. In addition, it can minify with `--minify` or watch with `--watch` options set. Bootstrap Implementation =============================================================================== Tag Magic ------------------------------------------------------------------------------- hidden:['xs','sm','md','lg'] // adds hidden-xs visible:['xs','sm','md','lg'] // adds visible-xs emphasis:'danger' // adds text-danger labelText: 'foo' // appends _label badge:5 // appends _badge pull: 'left' // adds pull-left align: 'left' // adds text-left tooltip: everything should support the full tooltip system. When inserted the event should be bound The general kind BSNavBar BSNavForm BSNavDropdown BSNavHeader brand:'Foo', brandHref:'#', srOnly: true BSPills base: BSNavs stacked:true BSPill active:true href:# disabled:true/false BSDropdown BSItem() BSDivider() BSItem() BSDropdown( _BSItem('Text', {href:'#'}), {divider:{}}] BSTabs base: BSNavs justified:true BSTab active:true href:# disabled:true/false BSDropdown( BSItem('Text', href:'#') bsDivider(), ) BSBreadCrumbs BSBreadCrumb active:true href:# BSTable BSProgressBar BSList BSDropDown BSNavBar Bootstrap.panel ------------------------------------------------------------------------------- // <div class="panel panel-danger"> // <div class="panel-body"> // Panel content // </div> // <div class="panel-footer">Panel footer</div> // </div> Bootstrap.panel({danger:true}, function(){ Bootstrap.panelHeader('') Bootstrap.panelBody(function(){ }) Bootstrap.panelFooter() }) Bootstrap alignment: left,right,center ------------------------------------------------------------------------------- // <h1>h1. Bootstrap heading <small>Secondary text</small></h1> // <h2>h2. Bootstrap heading <small>Secondary text</small></h2> h1('h1. Bootstrap heading ', _small('Secondary text')) h2('h2. Bootstrap heading ', _small('Secondary text')) // <p class="text-left">Left aligned</p> // <p class="text-right">Right aligned</p> // <p class="text-center">Center aligned</p> p({textLeft:true}, 'Left aligned') p({textRight:true}, 'Right aligned') p({textCenter:true}, 'Center aligned') Bootstrap colors: primary, success, info, warning, danger, muted ------------------------------------------------------------------------------- // <p class="text-primary">primary text</p> // <p class="text-success">success text</p> // <p class="text-info">info text</p> // <p class="text-warning">warning text</p> // <p class="text-danger">danger text</p> // <p class="text-muted">muted text</p> p({textPrimary:true}, 'Primary text') p({textSuccess:true}, 'Success text') p({textInfo:true}, 'Info text') p({textWarning:true}, 'Warning text') p({textDanger:true}, 'Danger text') p({textMuted:true}, 'Muted text') Bootstrap code ------------------------------------------------------------------------------- // <pre>&lt;p&gt;Sample text here...&lt;/p&gt;</pre> // Alias code to pre Bootstrap.code("&lt;p&gt;Sample text here...&lt;/p&gt;") Bootstrap grid: row/col/ with sizes and offset/pull ------------------------------------------------------------------------------- // <div class="row marketing"> Bootstrap.row(c:'marketing', function(){ // <div class="col-lg-6 col-md-3"> // <h4>Subheading</h4> // <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p> // </div> // <div class="col-lg-6 col-md-3"> // <h4>Subheading</h4> // <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p> // </div> Bootstrap.col({lg:6, xs:3}, function(){ h4('Subheading'); p('Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.'); }); Bootstrap.col({lg:6, md:4, sm:2, xs:3, xsOffset:3, mdOffset:4, mdPush:4, mdPull:5}, function(){ h4('Subheading'); p('Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.'); }); }); Bootstrap.footer ------------------------------------------------------------------------------- Bootstrap.footer(function({ p("© Company 2013") })) });