├── test
├── .empty
├── angles.html
└── angles_test.js
├── .git-ref
├── demo
├── img
│ ├── readme_start.png
│ ├── readme_context.png
│ ├── readme_loadsave.png
│ ├── glyphicons-halflings.png
│ ├── readme_notification.png
│ ├── angles_logo_red-trans.eps
│ ├── angles_logo_red-trans.png
│ └── glyphicons-halflings-white.png
├── GoogleDriveStorage.js
├── README.md
├── index.html
├── srvValidation.html
├── css
│ ├── bootstrap-responsive.min.css
│ ├── jasny-bootstrap.min.css
│ └── bootstrap-responsive.css
└── js
│ └── jasny-bootstrap.min.js
├── .gitmodules
├── version.js
├── .gitignore
├── deps
├── config.js
└── client.js
├── bower.json
├── src
├── contextHelp.coffee
├── notificationCenter.coffee
├── validator.coffee
├── fileUploader.coffee
├── validatorSRV.coffee
├── validatorSAX.coffee
└── angles-editor-view.coffee
├── package.json
├── COPYING.md
├── resources
├── rng2js.xsl
└── tei_all.odd
├── Gruntfile.js
├── README.md
└── dist
└── angles.min.js
/test/.empty:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.git-ref:
--------------------------------------------------------------------------------
1 | 5b36385234833c51e2bc01e3fe8feb85918cf68a
2 |
--------------------------------------------------------------------------------
/demo/img/readme_start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/readme_start.png
--------------------------------------------------------------------------------
/demo/img/readme_context.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/readme_context.png
--------------------------------------------------------------------------------
/demo/img/readme_loadsave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/readme_loadsave.png
--------------------------------------------------------------------------------
/demo/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/demo/img/readme_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/readme_notification.png
--------------------------------------------------------------------------------
/demo/img/angles_logo_red-trans.eps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/angles_logo_red-trans.eps
--------------------------------------------------------------------------------
/demo/img/angles_logo_red-trans.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/angles_logo_red-trans.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "vendor/isaacs/sax-js"]
2 | path = vendor/isaacs/sax-js
3 | url = https://github.com/isaacs/sax-js.git
4 |
--------------------------------------------------------------------------------
/demo/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umd-mith/angles/HEAD/demo/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/version.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var x;
3 | eval("x= " + require("fs").readFileSync(__dirname + "/package.json"))
4 | console.log(x.version)
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Junk that could exist anywhere:
2 | .DS_Store
3 | *.swp
4 | *.tmp
5 |
6 | node_modules/
7 | bower_components/
8 | app/
9 | .grunt
10 |
--------------------------------------------------------------------------------
/deps/config.js:
--------------------------------------------------------------------------------
1 | var config = {
2 | 'client_id': '{PUT YOUR ID HERE}.apps.googleusercontent.com',
3 | 'scope': ['https://www.googleapis.com/auth/drive',"https://www.googleapis.com/auth/drive.file"]
4 | };
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angles",
3 | "version": "0.1.0",
4 | "dependencies": {
5 | "jquery": "~2.0.3",
6 | "ace-builds": "1.1.1",
7 | "underscore": "~1.5.1",
8 | "backbone": "1.0.0"
9 | },
10 | "main": "dist/angles.js",
11 | "devDependencies": {
12 | "qunit": "~1.11.0"
13 | },
14 | "ignore": [
15 | "**/.*",
16 | "node_modules",
17 | "components",
18 | "bower_components",
19 | "test",
20 | "tests"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/src/contextHelp.coffee:
--------------------------------------------------------------------------------
1 | # --- ContextHelp ---
2 |
3 | class Angles.ContextHelp
4 | constructor: (options) ->
5 | dispatcher = @dispatcher = options.dispatcher
6 | @$odd = {}
7 | @$angles = options.anglesView
8 |
9 | setODD: (o) -> @$odd = o
10 |
11 | getODDfor: (e) ->
12 | elements = @$odd.members
13 | for item in elements
14 | if item.ident == e
15 | return item
16 | null
17 |
18 | getDescOf: (e) -> @getODDfor(e)?.desc
19 |
20 | getChildrenOf: (e) ->
21 | @getODDfor(e)?.children
--------------------------------------------------------------------------------
/src/notificationCenter.coffee:
--------------------------------------------------------------------------------
1 | # --- NotificationCenter ---
2 |
3 | class Angles.NotificationCenter
4 | constructor: (options) ->
5 | dispatcher = @dispatcher = options.dispatcher
6 |
7 | @$angles = options.anglesView
8 | @$notifications = new Angles.NotificationList()
9 |
10 | #console.log(@$notifications)
11 |
12 | dispatcher.on "notification:push", (e) => @push e
13 |
14 | dispatcher.on "notification:clear", (e) => @clear()
15 |
16 | push: (m) ->
17 | @$notifications.add m
18 |
19 | clear: ->
20 | m.destroy() while m = @$notifications.first()
21 | null
--------------------------------------------------------------------------------
/src/validator.coffee:
--------------------------------------------------------------------------------
1 | # --- Validator ---
2 |
3 | class Angles.Validator
4 | constructor: (options) ->
5 | dispatcher = @dispatcher = options.dispatcher
6 | @$schema = {}
7 | @$errors = []
8 | @$angles = options.anglesView
9 |
10 | displayErrors: ->
11 | for e in @errors()
12 | @dispatcher.trigger "validation:error", e
13 | @endValidation()
14 |
15 | addError: (e) ->
16 | @$errors.push e
17 |
18 | clearErrors: -> @$errors = []
19 |
20 | endValidation: ->
21 | @dispatcher.trigger "validation:end"
22 |
23 | setSchema: (s) ->
24 | @$schema = s
25 | @dispatcher.trigger "validation"
26 |
27 | errors: -> @$errors
28 |
29 | hasErrors: -> @$errors.length != 0
--------------------------------------------------------------------------------
/src/fileUploader.coffee:
--------------------------------------------------------------------------------
1 | # --- FileUploader ---
2 |
3 | class Angles.FileUploader
4 | constructor: (options) ->
5 | dispatcher = @dispatcher = options.dispatcher
6 | @$angles = options.anglesView
7 | @storedFiles = options.storedFiles
8 |
9 | _handleFileSelect: (evt) =>
10 | file = evt.target.files[0]
11 |
12 | reader = new FileReader()
13 |
14 | reader.onload = (e) =>
15 |
16 | same_name = @storedFiles.find (model) ->
17 | return model.get('name') == file.name
18 |
19 | # Overwrite if already in Local Storage
20 | if same_name?
21 | same_name.destroy()
22 |
23 | # Save new document on Local Storage
24 | newModel = @storedFiles.create
25 | name: file.name,
26 | content: e.target.result
27 | @dispatcher.trigger "document:switch", newModel
28 |
29 | reader.readAsText(file,"UTF-8")
30 |
31 | bind: (el) ->
32 | $(el).change @_handleFileSelect
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angles",
3 | "description": "XML editing mode for the Ajax.org Code Editor with support for TEI",
4 | "version": "0.1.0",
5 | "homepage": "https://github.com/umd-mith/angles",
6 | "engines": {"node": ">= 0.6.0"},
7 | "main": "dist/angles.js",
8 | "repository": {
9 | "type": "git",
10 | "url" : "https://github.com/umd-mith/angles.git"
11 | },
12 | "dependencies": {
13 | },
14 | "devDependencies": {
15 | "grunt": "0.4.1",
16 | "grunt-cli": "latest",
17 | "grunt-contrib-uglify": "~0.2.2",
18 | "grunt-contrib-clean": "latest",
19 | "grunt-contrib-qunit": "~0.2.2",
20 | "grunt-contrib-coffee": "latest",
21 | "shelljs": "latest",
22 | "rimraf": "~2.2.1",
23 | "bower": "latest"
24 | },
25 | "scripts": {
26 | "test": "grunt test"
27 | },
28 | "mappings": {
29 | "angles": "."
30 | },
31 | "licenses": [{
32 | "type": "BSD New",
33 | "url": "http://opensource.org/licenses/BSD-3-Clause"
34 | }],
35 | "directories": {
36 | "lib": "dist/angles"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/COPYING.md:
--------------------------------------------------------------------------------
1 | Except as noted in individual files, files in this project are distributed under the BSD license:
2 |
3 | Copyright (c) 2010, Ajax.org B.V. Copyright (c) 2012-2013, University of Maryland. All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 | * Neither the name of University of Maryland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10 |
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF MARYLAND BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 |
--------------------------------------------------------------------------------
/test/angles.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test Test Suite
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 | subpar test markup
36 | normal test markup
37 | awesome test markup
38 |
39 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/validatorSRV.coffee:
--------------------------------------------------------------------------------
1 | # --- ValidatorSRV - Extends Validator ---
2 |
3 | class Angles.ValidatorSRV extends Angles.Validator
4 | constructor: (options) ->
5 | super(options)
6 | @$validatorUrl = options.validator
7 |
8 | # If an ajax request to a server and a request handler are provided, set them here.
9 | # Otherwise use example handlers below.
10 | @$requestHandler = if options.requestHandler? then options.requestHandler else requestHandler
11 | @$validationHandler = if options.validationHandler? then options.validationHandler else validationHandler
12 |
13 | @dispatcher.on "validation", =>
14 | @dispatcher.trigger "validation:start"
15 | @$requestHandler @
16 |
17 | # Override this, or provide your own validation handler if your validator returns a different response
18 | requestHandler = (validator) ->
19 | doc = validator.$angles.getDocument()
20 | xmlDocument = escape(doc.getValue())
21 | $.ajax
22 | url: validator.$validatorUrl
23 | type: "POST"
24 | crossDomain: true
25 | processData: false
26 | data: "schema="+validator.$schema+"&document="+xmlDocument
27 | dataType: "json",
28 | success: (data) ->
29 | validator.$validationHandler validator, data
30 | error: (xhr, textStatus, thrownError, data) =>
31 | @dispatcher.trigger 'notification:clear'
32 | thrownError = if xhr.status == 0 then "Cannot reach server" else thrownError
33 | n =
34 | type: "Server"
35 | info: "Status: " + xhr.status
36 | message: thrownError
37 | location:
38 | row: -1
39 | column: -1
40 | @dispatcher.trigger 'notification:push', n
41 |
42 | # Override this, or provide your own validation handler if your validator returns a different response
43 | validationHandler = (validator, data) ->
44 | validator.$errors = []
45 | for datum in data
46 | validator.$errors.push
47 | text: datum.message
48 | row: datum.line-1
49 | column: datum.column
50 | type: datum.type
51 | validator.displayErrors()
--------------------------------------------------------------------------------
/resources/rng2js.xsl:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 | xml:
11 |
12 |
13 |
14 |
15 | schema({
16 | ,
17 |
18 | ,
19 |
20 |
21 | })
22 |
23 | _start: " "
24 |
25 |
26 |
27 |
28 |
29 | " ",
30 |
31 |
32 | : {
33 | model: " ",
34 | children: [ ],
35 | attributes: {, }}
36 |
37 | " ": {optional: true false , value: " "}
38 |
39 | ( ,)
40 |
41 | (| )
42 |
43 | *
44 |
45 |
46 |
47 | ( )*
48 |
49 | ( )+
50 |
51 | ( )
52 |
53 | \s?
54 |
55 | _empty_
56 |
57 | _text_
58 |
--------------------------------------------------------------------------------
/resources/tei_all.odd:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | TEI with maximal setup
9 | Sebastian Rahtz
10 |
11 |
12 |
13 | This template file is freely available and you are
14 | hereby authorised to copy, modify, and redistribute it in
15 | any way without further reference or permissions.
16 | When making such modifications, you are strongly
17 | recommended to change the present text to include an
18 | accurate statement of the licencing conditions applicable
19 | to your modified text.
20 |
21 |
22 |
23 | Written from scratch.
24 |
25 |
26 |
27 |
28 |
29 | TEI Complete
30 | This TEI customization describes a schema that includes
31 | all of the TEI (P5) modules. This is a very useful
32 | starting place for manually creating your own customizations
33 | — it is much easier to delete the modules you do not
34 | want than to add the modules you do. Furthermore this
35 | customization often proves helpful for testing TEI
36 | software.
37 | However, this particular TEI customization is not
38 | recommended for actual use for encoding documents. It
39 | produces schemas and reference documentation that will be much
40 | larger, and include many more elements, than almost anyone could
41 | conceivably ever need. Tempting though it may be simply to have
42 | absolutely everything, and just ignore elements not
43 | required, experience has shown that their presence makes the
44 | documentation harder to read and use, and makes a schema that is
45 | far more lax than desired.
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/demo/GoogleDriveStorage.js:
--------------------------------------------------------------------------------
1 |
2 | function loadFile(fileid){
3 | console.log(fileid);
4 | var request = gapi.client.request({
5 | 'path': '/drive/v2/files/'+fileid,
6 | 'method': 'GET'});
7 |
8 | request.execute(function(resp) {
9 | console.log('Title: ' + resp.title);
10 | console.log('Description: ' + resp.description);
11 | console.log('MIME type: ' + resp.mimeType);
12 | if (resp.downloadUrl) {
13 | var accessToken = gapi.auth.getToken().access_token;
14 | var xhr = new XMLHttpRequest();
15 | xhr.open('GET', resp.downloadUrl);
16 | xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
17 | xhr.onload = function() {
18 | console.log("RESPONSE: "+JSON.stringify(xhr.responseText));
19 | editor.setValue(xhr.responseText);
20 | };
21 | xhr.onerror = function() {
22 | alert("ERROR");
23 | };
24 | xhr.send();
25 | } else {
26 | alert("ERROR");
27 | }
28 | });
29 | }
30 | $("#login").click(function(){
31 |
32 |
33 | gapi.auth.authorize(config, function() {
34 | $("#login").replaceWith("Save |Load |Logout ");
35 | $("#load").click(function(){
36 |
37 | fn = prompt("Filename: ");
38 | gapi.client.load('drive', 'v2', function() {
39 | var request = gapi.client.drive.files.list({
40 | 'q': "title='"+fn+"'"
41 | });
42 | request.execute(function(resp) {
43 | loadFile(resp.items[0].id);
44 |
45 | });
46 | });
47 | fileid="0Bw7PrlWT3aWaVWQyLU5KZ1I1RVU";
48 |
49 |
50 | });
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | $("#save").click(function(){
61 | txt = editor.getValue();
62 | filename = prompt("Enter a filename: ")
63 | var metadata = {
64 | 'title': filename,
65 | 'mimeType': "text/plain"
66 | };
67 |
68 | const boundary = '-------314159265358979323846';
69 | const delimiter = "\r\n--" + boundary + "\r\n";
70 | const close_delim = "\r\n--" + boundary + "--";
71 |
72 | var multipartRequestBody =
73 | delimiter +
74 | 'Content-Type: application/json\r\n\r\n' +
75 | JSON.stringify(metadata) +
76 | delimiter +
77 | 'Content-Type: text/plain\r\n' +
78 | 'Content-Transfer-Encoding: utf8\r\n' +
79 | '\r\n' +
80 | txt +
81 | close_delim;
82 |
83 |
84 |
85 | var request = gapi.client.request({
86 | 'path': '/upload/drive/v2/files',
87 | 'method': 'POST',
88 | 'params': {'uploadType': 'multipart'},
89 | 'headers': {
90 | 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
91 | },
92 | 'body': multipartRequestBody});
93 |
94 |
95 |
96 | request.execute();
97 |
98 |
99 |
100 |
101 |
102 |
103 | });
104 |
105 | });
106 |
107 |
108 | });
109 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | 'use strict';
4 |
5 | // catch these here so they don't bite us later when we try to run tasks
6 | var shell = require('shelljs'),
7 | rimraf = require('rimraf'),
8 | bower_cmd = require('bower/lib/util/cmd');
9 |
10 | grunt.initConfig({
11 | pkg: grunt.file.readJSON('package.json'),
12 |
13 | coffee: {
14 | compile: {
15 | files: {
16 | 'dist/angles.js': ['src/*.coffee']
17 | }
18 | }
19 | },
20 |
21 | clean: [ 'dist', 'bower_components' ],
22 |
23 | uglify: {
24 | options: {
25 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
26 | },
27 | my_target: {
28 | files: {
29 | 'dist/angles.min.js': 'dist/angles.js'
30 | }
31 | }
32 | },
33 |
34 | qunit: {
35 | all: ['test/*.html']
36 | },
37 | });
38 |
39 | grunt.registerTask('default', ['coffee', 'uglify', 'install-deps']);
40 | grunt.registerTask('test', ['default', 'qunit']);
41 | grunt.registerTask('real-clean', [ 'clean', 'clean:node_modules']);
42 |
43 | grunt.registerTask('clean:node_modules', 'Remove locally installed node modules.', function() {
44 | var filepath = './node_modules';
45 | if(!grunt.file.exists(filepath)) {
46 | return false;
47 | }
48 | if(grunt.file.isPathCwd(filepath)) {
49 | grunt.verbose.error();
50 | grunt.fail.warn('Cannot delete the current working directory.');
51 | return false;
52 | }
53 | else if(!grunt.file.isPathInCwd(filepath)) {
54 | grunt.verbose.error();
55 | grunt.fail.warn('Cannot delete files outside the current working directory.');
56 | return false;
57 | }
58 | try {
59 | rimraf.sync(filepath);
60 | grunt.log.ok();
61 | }
62 | catch(e) {
63 | grunt.log.error();
64 | grunt.fail.warn('Unable to delete "' + filepath + '" file (' + e.message + ').', e);
65 | }
66 | });
67 |
68 | grunt.registerTask('install-deps', 'Install all JavaScript dependencies using bower, including optional libraries.', function() {
69 | var done = this.async();
70 | if(!shell.which("bower")) {
71 | console.log("Sorry, this script requires bower.");
72 | exit(1);
73 | }
74 | console.log("Running 'bower install'");
75 | bower_cmd('bower',['install']).then(function() {
76 | console.log("running 'bower install Backbone.localStorage'");
77 | return bower_cmd('bower', ['install', 'Backbone.localStorage']);
78 | }).then(function() {
79 | console.log("running 'bower install FileSaver'");
80 | return bower_cmd('bower', ['install', 'FileSaver']);
81 | }).then(function() {
82 | console.log("Finished installing dependencies");
83 | done();
84 | }).fail(function() {
85 | console.log("Unable to install dependencies");
86 | done();
87 | }).done();
88 | });
89 |
90 | grunt.registerTask('demo', 'Install all dependencies and provide a list of demo files', ['default', 'install-deps', 'demo:files' ]);
91 | grunt.registerTask('demo:files', "List available demonstration files.", function() {
92 | console.log("demo/index.html");
93 | console.log("demo/srvValidation.html");
94 | });
95 |
96 | grunt.event.on('qunit.spawn', function(url) {
97 | grunt.log.ok("Running test: " + url);
98 | });
99 |
100 | grunt.loadNpmTasks('grunt-contrib-uglify');
101 | grunt.loadNpmTasks('grunt-contrib-clean');
102 | grunt.loadNpmTasks('grunt-contrib-qunit');
103 | grunt.loadNpmTasks('grunt-contrib-coffee');
104 |
105 | };
--------------------------------------------------------------------------------
/deps/client.js:
--------------------------------------------------------------------------------
1 | var gapi=window.gapi=window.gapi||{};gapi._bs=new Date().getTime();(function(){var e=void 0,f=window,h="push",i="replace",j="length";var l=f,o=document,p=l.location,t=function(){},u=/\[native code\]/,w=function(a,b,d){return a[b]=a[b]||d},x=function(a){for(var b=0;bx.call(b,c)&&d[h](c)}return d},W=/[@"'<>]|%2F/,X=/^https?:\/\/[^\/]+\.google\.com(:\d+)?\/[^\?]+$/,Y=function(a){var b=o.createElement(T);b.setAttribute("src",a);b.async="true";a=o.getElementsByTagName(T)[0];a.parentNode.insertBefore(b,a)},$=function(a,b){var d=b||{};"function"==typeof b&&(d={},d[R.a]=b);var g=d,c=g&&g[R.c];if(c)for(var k=0;k0&&m[n-1])m[n]=b;else for(b();b=m[++n];)if(!b())break};if(!s[j])return m[n](t);var H="loaded_"+A.I++;z[H]=function(a){m[n](a);z[H]=null};c=r.split(";");c=(k=M[c.shift()])&&k(c);if(!c)throw"Bad hint:"+
5 | r;c=c[i]("__features__",U(s))[i](/\/$/,"")+(g[j]?"/ed=1/exm="+U(g):"")+("/cb=gapi."+H);if(!X.test(c)||W.test(c))throw"Bad URL "+c;g[h].apply(g,s);d[R.f]||l.___gapisync?(d=c,"loading"!=o.readyState?Y(d):o.write("<"+T+' src="'+encodeURI(d)+'">'+T+">")):Y(c)};var Z=function(a){if(A.hee&&0
18 | @reset = ->
19 | parser = sax.parser true,
20 | xmlns: true
21 | noscript: true
22 | position: true
23 |
24 |
25 |
26 | if callbacks.error?
27 | parser.onerror = (e) =>
28 | if e.message.split(/\n/)[0] != "Text data outside of root node."
29 | callbacks.error.call @, e
30 | parser.resume()
31 | else
32 | parser.onerror = (e) =>
33 | if e.message.split(/\n/)[0] != "Text data outside of root node."
34 | @validationError (e.message.split(/\n/))[0]
35 | parser.resume()
36 |
37 | if callbacks.characters?
38 | parser.ontext = (t) => callbacks.characters.call @, t
39 |
40 | if callbacks.startElement?
41 | parser.onopentag = (node) => callbacks.startElement.call @, node
42 |
43 | if callbacks.endElement?
44 | parser.onclosetag = (name) => callbacks.endElement.call @, name
45 |
46 | if callbacks.comment?
47 | parser.oncomment = (comment) => callbacks.comment.call @, comment
48 |
49 | if callbacks.startCdata?
50 | parser.onopencdata = => callbacks.startCdata.call @
51 |
52 | if callbacks.cdata?
53 | parser.oncdata = (cdata) => callbacks.cdata.call @, cdata
54 |
55 | if callbacks.endCdata?
56 | parser.onclosecdata = => callbacks.endCdata.call @
57 |
58 | if callbacks.endDocument?
59 | parser.onend = => callbacks.endDocument.call @
60 |
61 | if callbacks.startDocument?
62 | parser.onstart = => callbacks.startDocument.call @
63 | else
64 | parser.onstart = ->
65 |
66 | @$parser = parser
67 | @$errors = []
68 |
69 | parse: (doc) ->
70 | @reset()
71 | parser = @$parser
72 | n = doc.getLength()
73 |
74 | parser.onstart()
75 |
76 | for i in [0..n]
77 | parser.write doc.getLine(i)+"\n"
78 | parser.close()
79 |
80 | if @validated()
81 | true
82 | else
83 | false
84 |
85 | validationError: (text, type) ->
86 | parser = @$parser
87 | @$errors.push
88 | text: text
89 | row: parser.line
90 | column: parser.column
91 | type: if type? then type else "error"
92 |
93 | validated: -> @$errors.length == 0
94 |
95 |
96 | # --- ValidatorSAX - Extends Validator ---
97 | class Angles.ValidatorSAX extends Angles.Validator
98 | constructor: (options) ->
99 | super(options)
100 | @dispatcher.on "validation", =>
101 | doc = @$angles?.getDocument()
102 | if doc?
103 | @dispatcher.trigger "validation:start"
104 | @validate @$angles.getDocument()
105 |
106 | checkSchema: (parser, els) ->
107 | return unless @$schema?
108 |
109 | if els?.length == 1
110 | if not @$schema.hasOwnProperty els[0]?.name
111 | parser.validationError "Invalid root element: " + els[0].name + "."
112 | else
113 | rexp = new RegExp @$schema._start, "ig"
114 | if rexp.exec(els[0].name+",") == null
115 | parser.validationError "Invalid root element: " + els[0].name + "."
116 | return
117 |
118 | currentEl = els[0].name
119 | parentEl = els[1].name
120 |
121 | if not @$schema[parentEl]?
122 | parser.validationError "The #{currentEl} element is not allowed as a child of the #{parentEl} element."
123 | else if currentEl not in @$schema[parentEl]?.children
124 | parser.validationError "The #{currentEl} element is not allowed as a child of the #{parentEl} element."
125 | return
126 |
127 | checkChildren: (parser, els) ->
128 | return unless @$schema?
129 |
130 | return unless els.length > 0
131 |
132 | currentEl = els[0]
133 | childNames = currentEl.children.join(',')
134 | childNames += "," if childNames != ""
135 |
136 | return unless @$schema.hasOwnProperty(currentEl?.name)
137 | return unless @$schema[currentEl.name].hasOwnProperty("model")
138 |
139 | rexp = new RegExp @$schema[currentEl.name].model, "ig"
140 | if rexp.exec(childNames) == null
141 | parser.validationError currentEl.name + " is invalid: one or more required children are missing or its child elements are in the wrong order."
142 |
143 | validate: (editor) ->
144 | els = []
145 | parser = new Angles.SAXParser
146 | startDocument: => els = []
147 | endDocument: =>
148 | if els.length > 0
149 | names = (e.name for e in els)
150 | parser.validationError "Unclosed elements at end of document: #{names.join(", ")}"
151 | startElement: (node) =>
152 | if els.length > 0
153 | els[0].children.push node.local
154 | els.unshift
155 | name: node.local
156 | children: []
157 | @checkSchema parser, els
158 | characters: (t) =>
159 | if els.length > 0
160 | if t.match(/^[\s\r\n]*$/) == null
161 | els[0].children.push '_text_'
162 | endElement: (name) =>
163 | @checkChildren parser, els
164 | els.shift()
165 | parser.parse(editor)
166 | @$errors = parser.$errors
167 | @displayErrors()
--------------------------------------------------------------------------------
/demo/README.md:
--------------------------------------------------------------------------------
1 | # Angles - Demonstration and Examples
2 |
3 | The HTML pages in this directory demonstrate how to use Angles with a number of optional components.
4 |
5 | To install all of the dependencies and build the ANGLES library, you can install the required node libraries and then run the 'demo' grunt task:
6 |
7 | ``` bash
8 | $ npm install -g grunt-cli
9 | $ npm install
10 | $ grunt demo
11 | ```
12 |
13 | This will run through various installation procedures and end by printing out a list of available demonstration files.
14 |
15 | See the [top-level README](../README.md) for more information on installing grunt and associated dependencies.
16 |
17 | ## `index.html`
18 |
19 | This basic demonstration shows all features of Angles that do no need any server-side component. With this kind of set up, one could use Angles offline, or embed it into a website as a TEI editor. Angles will perform basic TEI-Lite validation, allow users to save their work in the browser, and save and load files from disk. The following sections will guide you through each component.
20 |
21 | ### The Demo Interface
22 |
23 | If the installation was completed correctly, the page will show an editable basic TEI file, a group of buttons on the left for saving and loading documents, and a validation button on top.
24 |
25 | ![Image of Angles demo interface][start]
26 |
27 | ### Contextual help
28 |
29 | When typing a new XML element (with `<`) a pop up will appear showing the TEI elements allowed in a given context (TEI-all only).
30 | This uses the JSON file `p5subset.js`, taken from [TEI's vault](http://www.tei-c.org/Vault/P5/current/xml/tei/odd/).
31 |
32 | A description of a selected element from the pop up will appear below the editor in the notification area. Click or press `Enter` on the desired element and it will be inserted at the position of the cursor.
33 |
34 | ![Example of context help interface][context]
35 |
36 | **N.B.** You can generate your own JSON for contextual help from any TEI ODD. Use [odd2json.xslt](https://github.com/TEIC/Stylesheets/blob/master/odds/odd2json.xsl) from the TEI GitHub Stylesheet repository - *make sure to set the paramenter showChildren to "true"*.
37 |
38 | ### Notifications
39 |
40 | Notifications can be used to display any type of message to the user. The demo shows how they can be used to drive the validation status indicator (green/red box in top right corner), validation errors, and element descriptions from the contextual help.
41 |
42 | ![Usage of notifications in the UI][notifications]
43 |
44 | ### Local storage operations
45 |
46 | Save and load current document to the user's browser's HTML5 Local Storage. The user can store multiple files and will be shown the latest open file when visiting the page again.
47 |
48 | ![Local Storage operations][loadsave]
49 |
50 | :warning: The demo does not include a way of removing any file stored in the Local Storage. The Local Storage can be cleared manually in a browser's settings.
51 |
52 | ### Save and Upload files
53 |
54 | The user can also save (download) or upload a file. Once a file is uploaded, it also gets stored in the HTML5 Local Storage.
55 |
56 | ### Validation
57 |
58 | This demonstration uses the [`rng.js`](https://github.com/umd-mith/angles/blob/master/demo/rng.js) JSON file as the JavaScript-friendly representation of a light-weight TEI schema for simple validation of the TEI without requiring a separate server process.
59 |
60 | The file is validated when it is loaded, at other times the user has to click on "Validate" to validate the file.
61 |
62 | ## `srvValidation.html`
63 |
64 | ## Validation
65 |
66 | When a more sophisticated validation is needed, Angles must be hooked up to a local or online validation service. This page demonstrates how to hook to an online validation service. During development we used [a simple Scalatra service](https://github.com/travisbrown/validation-demo).
67 |
68 | The validation server is able to fetch RelaxNG schemata from the web, so the interface links to several schemata on the web and allows the user to choose one. URLs to other schemata can be included in `srvValidation.html` by adding a new `` to `div#schema`.
69 |
70 | ``` html
71 | My schema
72 | ```
73 |
74 | If you want to use a different service or implement your own, you might need to override `Angles.ValidatorSRV.requestHandler` and `Angles.ValidatorSRV.validationHandler` to send the right request to your service and handle the response.
75 |
76 | `Angles.ValidatorSRV.requestHandler` handles the request to the service. We POST two parameters: `schema` (the URL to an RelaxNG document) and `document` (the content of the editor). Another service is likely to expect different paramenters and a different negotiation process.
77 |
78 | ``` coffeescript
79 | $.ajax
80 | url: validator.$validatorUrl
81 | type: "POST"
82 | crossDomain: true
83 | processData: false
84 | data: "schema="+validator.$schema+"&document="+xmlDocument
85 | dataType: "json",
86 | ```
87 |
88 | `Angles.ValidatorSRV.validationHandler` handles the service's response and passes it on to flag errors in the editor and to show error notifications. All you will have to change here is where to find each piece of information in your service's response.
89 |
90 | ``` coffeescript
91 | for datum in data
92 | validator.$errors.push
93 | text: datum.message
94 | row: datum.line-1
95 | column: datum.column
96 | type: datum.type
97 | ```
98 |
99 | [start]: img/readme_start.png "Angles demo interface"
100 | [context]: img/readme_context.png "Context help"
101 | [notifications]: img/readme_notification.png "Notifications"
102 | [loadsave]: img/readme_loadsave.png "Local Storage operations"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ANGLES
2 |
3 | The ANGLES Project is a research project aimed at developing a
4 | lightweight, online XML code editor, which can support teaching of
5 | text encoding as well as text encoding research projects, either by
6 | distributed research teams or at institutions without resources to
7 | purchase expensive software licenses. By combining the model of
8 | intensive code development (a.k.a. the "code sprint") with testing
9 | and feedback by domain experts gathered at nationally-recognized
10 | disciplinary conferences, the project proposes a bridge between
11 | humanities centers who have greater resources to program scholarly
12 | software and the scholars who form the core user community for such
13 | software through their teaching and research.
14 |
15 | ## Repository Structure
16 |
17 | This repository has the following directories:
18 |
19 | * demo: simple demonstration page incorporating the ANGLES mode plugin. This demo assumes that you have installed the needed dependencies using `bower`.
20 | * dist: the built plugin ready for distribution.
21 | * src: the source code for non-ACE components that work with the ACE editor.
22 | * test: any unit tests.
23 | * vendor: dependencies not available through `bower`
24 |
25 | **N.B.**: You will need to clone this repository recursively to capture the dependencies in `vendor/`:
26 |
27 | ``` bash
28 | $ git clone --recursive https://github.com/umd-mith/angles.git
29 | ```
30 |
31 | If you've already cloned the repository without the `--recursive` flag, or if you are using a client
32 | that does not allow you to specify the flag, you can manually check out these dependencies with the following commands:
33 |
34 | ``` bash
35 | $ git submodule init
36 | $ git submodule update
37 | ```
38 |
39 |
40 | ## Development Toolchain
41 |
42 | ANGLES is based on the [Ace Editor](http://ace.ajax.org/) and uses `grunt`
43 | to manage its build and testing process. This means that
44 | you need the following installed before you can work on the CoffeeScript
45 | source code:
46 |
47 | * node.js (see [the guide to installing Node.js via package manager](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager); you will need a recent version of node.js)
48 | * grunt (see [the `grunt` getting started guide](http://gruntjs.com/getting-started))
49 | * bower
50 |
51 | ``` bash
52 | $ npm install -g grunt-cli
53 | $ npm install -g bower
54 | ```
55 |
56 | You also need the following Node packages intalled via `npm`:
57 |
58 | * grunt-contrib-uglify
59 | * grunt-contrib-clean
60 | * grunt-contrib-qunit
61 | * grunt-contrib-coffee
62 | * rimraf
63 | * shelljs
64 |
65 | ``` bash
66 | $ npm install grunt-contrib-uglify
67 | $ npm install grunt-contrib-clean
68 | $ npm install grunt-contrib-qunit
69 | $ npm install grunt-contrib-coffee
70 | $ npm install rimraf
71 | $ npm install shelljs
72 | ```
73 |
74 | You can also install these dependencies by running
75 |
76 | ``` bash
77 | $ npm install
78 | ```
79 |
80 | in your clone of the repository.
81 |
82 | ### Building
83 |
84 | To build the plugins for ACE, run the following command:
85 |
86 | ``` bash
87 | $ grunt
88 | ```
89 |
90 | This will build everything and leave the new files in `dist/`. In addition, all required and optional JavaScript dependencies managed through `bower` will be downloaded and placed in the `bower_components/` directory.
91 |
92 | ### Testing
93 |
94 | The tests assume that you have installed the required dependencies using `bower`.
95 |
96 | #### Headless Testing
97 |
98 | You may run tests without a browser using `grunt` if you have [PhantomJS](http://phantomjs.org/) installed.
99 |
100 | ``` bash
101 | $ grunt test
102 | ```
103 |
104 | #### In-Browser Testing
105 |
106 | You may also run the tests in your browser by loading the `test/angles.html` page. Any errors will be highlighted in the web page. You may also want to view the browser's console log for additional error messages or stack traces if there are errors.
107 | ## Using ANGLES in your Project
108 |
109 | Refer to the demos for examples to set up the various components. A minimal installation of ANGLES would include the ANGLES plugin and the required dependencies listed below.
110 |
111 | ### The ANGLES plugin
112 |
113 | When built, the main plugin will be in `dist/angles.js`. You may also install the most recent distribution using `bower`. (See [bower.io](http://bower.io/#installing-bower) for information on installing and using `bower`.)
114 |
115 | ``` bash
116 | $ bower install angles-tei
117 | ```
118 |
119 | The plugin will be in `bower_components/angles/dist/angles.js`. The required dependencies (see below) will also be installed. However, optional dependencies will need to be installed separately.
120 |
121 | ### Dependencies
122 |
123 | ANGLES has a number of JavaScript libraries on which it depends. These may be installed using `bower` or using `grunt`, though `grunt` will require that `bower` be installed.
124 |
125 | To use `grunt` to manage `bower` and install all dependencies, both required and optional, run:
126 |
127 | ``` bash
128 | $ grunt install-deps
129 | ```
130 |
131 | #### Required Dependencies
132 |
133 | You may download the primary dependencies using `bower` or download your own. (See [bower.io](http://bower.io/#installing-bower) for information on installing and using `bower`.)
134 |
135 | From the top directory of the repository, you may run `bower`:
136 |
137 | ``` bash
138 | $ bower install
139 | ```
140 |
141 | or
142 |
143 | ``` bash
144 | $ bower install jQuery
145 | $ bower install ace-builds
146 | $ bower install underscore
147 | $ bower install backbone
148 | ```
149 |
150 | This will install the dependencies into `bower_components`.
151 |
152 | * [jQuery](https://jquery.com/)
153 | * [ACE editor](http://ace.c9.io/)
154 | * [underscore.js](http://underscorejs.org/)
155 | * [backbone.js](http://backbonejs.org/)
156 |
157 | #### Optional Dependencies
158 |
159 | The following dependencies are optional and are not included in the `bower` configuration:
160 |
161 | ``` bash
162 | $ bower install Backbone.localStorage
163 | $ bower install FileSaver
164 | ```
165 |
166 | * [Backbone.localStorage](https://github.com/jeromegn/Backbone.localStorage) (optional for save/load component)
167 | * [FileSaver](https://github.com/eligrey/FileSaver.js) (optional for saving file to disk)
168 |
169 | ### Demo
170 |
171 | A number of demonstrations are available in the `demo/` directory. See [the README](./demo/README.md) in that directory for more information.
172 |
173 | You can ensure everything is built and dependencies are downloaded by running
174 |
175 | ``` bash
176 | $ grunt demo
177 | ```
178 |
179 | This will also print out a list of demonstration files that you may open in your browser.
180 |
181 | ### Cleaning Files
182 |
183 | After building ANGLES or installing JavaScript libraries with `bower`, you can clean the `dist/` and `bower_components/` directories by running:
184 |
185 | ``` bash
186 | $ grunt clean
187 | ```
188 |
189 | To remove any locally installed node modules, you may run:
190 |
191 | ``` bash
192 | $ grunt real-clean
193 | ```
194 |
195 |
--------------------------------------------------------------------------------
/src/angles-editor-view.coffee:
--------------------------------------------------------------------------------
1 | #
2 | # Events managed in the ACEEditorView.dispather:
3 | #
4 | # editor:change - an editor change event
5 | # editor:reload - force the editor to reload content from the model
6 | # editor:error - an error reported by the editor or wrapper
7 | #
8 | # document:switch - a request to change the document the editor is editing
9 | # document:save - a request to save the document currently in the editor
10 | #
11 | # validation:start - notice that validation is beginning
12 | # validation:end - notice that validation has finished
13 | # validation:error - the report of a validation error
14 | #
15 | # If you replace the Angles.ACEEditorView with a different view to wrap
16 | # a different editor, you will need to implement a getDocument() function
17 | # that returns the same properties as the one here, but with data from
18 | # your editor instance. This lets the validator not depend on the ACE
19 | # API.
20 | #
21 | # To provide different storage for the collection, replace
22 | # Angles.XMLDocumentList (here, we're using local storage):
23 | #
24 | # Angles.XMLDocumentList = Backbone.Collection.extend({
25 | # mode: Angles.XMLDocument,
26 | # localStorage: new Backbone.LocalStorage("SomeCollection")
27 | # });
28 | #
29 |
30 | window.Angles = {}
31 | ((Angles,_,Backbone,ace) ->
32 | ACEEditor = null
33 |
34 | # XMLDocument
35 | class Angles.XMLDocument extends Backbone.Model
36 | defaults:
37 | "name" : "untitled"
38 | "content": ""
39 |
40 | validate: (attrs) ->
41 | # console.log(attrs);
42 | #if(attrs.name === undefined) {
43 | # return "document must have a name";
44 | #}
45 | #if(attrs.name =~ /^\s*$/) {
46 | # return "document must have a name";
47 | #}
48 |
49 | # XMLDocument List
50 | class Angles.XMLDocumentList extends Backbone.Collection
51 | model: Angles.XMLDocument
52 |
53 | # Notification
54 | class Angles.Notification extends Backbone.Model
55 | defaults:
56 | "type" : ""
57 | "info" : ""
58 | "message" : ""
59 | "resource": ""
60 | "location":
61 | "column": -1
62 | "row" : -1
63 |
64 | # Notification List
65 | class Angles.NotificationList extends Backbone.Collection
66 | model: Angles.Notification
67 |
68 | #
69 | # This file selector will list the documents in the Angles.XMLDocumentList
70 | # collection and allow selection of a document.
71 | #
72 | # Fires a document:change event when the selected file is to be loaded
73 | # into the editor. The event's data parameter is the model object from
74 | # which to get the content.
75 | #
76 | # options:
77 | #
78 | # * el: element into which this view should be rendered
79 | # * dispatcher: dispatcher object to use for events
80 | # * collection: collection of models from which a model should be selected
81 | #
82 | # template classes:
83 | # .file-list - list of files - new files are appended to the end
84 | # .new-file - element that triggers a new file dialog
85 | #
86 | #
87 | # _.templateSettings =
88 | # interpolate: /\{\{(.+?)\}\}/g
89 | # escape: /\{\{-(.+?)\}\}/g
90 |
91 | class Angles.FileSelector extends Backbone.View
92 |
93 | initialize: ->
94 | @template = _.template $('#file-list-template').html()
95 |
96 | render: ->
97 | @$el.html @template {}
98 | @collection.each @addOne, @
99 | @
100 |
101 | addOne: (model) ->
102 | view = new Angles.FileSelectorRow
103 | model: model
104 | @$("form").append view.render().$el
105 |
106 | class Angles.FileSelectorRow extends Backbone.View
107 |
108 | initialize: ->
109 | @template = _.template $('#file-item-template').html()
110 | @listenTo @model, 'change', @render
111 | @listenTo @model, 'destroy', @remove
112 |
113 | render: ->
114 | @$el.html @template @model.toJSON()
115 | @
116 |
117 | class Angles.NotificationTable extends Backbone.View
118 |
119 | initialize: ->
120 | @template = _.template $('#notification-list-template').html()
121 |
122 | render: ->
123 | @$el.html @template {}
124 | @listenTo @collection, 'add', @addOne
125 | @
126 |
127 | addOne: (model) ->
128 | view = new Angles.NotificationRow
129 | model: model
130 | @$(".notifications").append view.render().$el
131 |
132 | class Angles.NotificationRow extends Backbone.View
133 |
134 | initialize: ->
135 | @template = _.template $('#notification-template').html()
136 | @listenTo @model, 'change', @render
137 | @listenTo @model, 'destroy', @remove
138 |
139 | render: ->
140 | @$el.html @template @model.toJSON()
141 | @
142 |
143 | #
144 | # We intend ACEEditorView to be a singleton class for a particular area
145 | # on the page - not to be instantiated for each document in the collection.
146 | #
147 | # You may pass a dispatcher object into the initializer if you want to
148 | # use one from another application to allow integration.
149 | #
150 |
151 | class Angles.ACEEditorView extends Backbone.View
152 | tagName: "div"
153 | className: "ace-editor"
154 |
155 | initialize: ->
156 | annotations = []
157 | dispatcher = @options.dispatcher or _.clone Backbone.Events
158 | @dispatcher = dispatcher
159 |
160 | dispatcher.on "editor:reload", =>
161 | @clearAnnotations()
162 | @setContent()
163 |
164 | dispatcher.on "document:save", => @saveModel()
165 |
166 | dispatcher.on "validation:start", =>
167 | annotations = [];
168 | @dispatcher.trigger 'notification:clear'
169 |
170 | dispatcher.on "validation:error", (e) =>
171 | annotations.push(e)
172 | n =
173 | type: "validation"
174 | info: e.type
175 | message: e.text
176 | location:
177 | row: e.row
178 | column: e.column
179 | @dispatcher.trigger 'notification:push', n
180 |
181 | dispatcher.on "validation:end", =>
182 | select = @$editor.getSelection()
183 |
184 | @clearAnnotations()
185 | @$editor.focus()
186 | if annotations.length > 0
187 | @$editor.gotoLine annotations[0].row+1, annotations[0].column, true
188 | select.selectWordLeft()
189 | select.selectWordLeft()
190 |
191 | @$editor.session.setAnnotations(annotations)
192 |
193 | dispatcher.on "document:switch", (e) => @setModel(e)
194 |
195 | render: ->
196 | @$editor = ace.edit(@el);
197 | @$editor.getSession().on 'change', (e) => @dispatcher.trigger 'editor:change', e
198 | @$editor.getSession().setMode "ace/mode/xml"
199 |
200 | # Load ace modules #
201 |
202 | #ace.config.set("basePath", "../deps/")
203 | ace.config.loadModule 'ext/angles', =>
204 |
205 | @$editor.setOptions
206 | enableODDAutocompletion: true
207 |
208 | completer =
209 | getCompletions: (editor, session, pos, prefix, callback) =>
210 | if @$context?
211 | context = this.$context
212 |
213 | _findParent = (row, column) ->
214 | openTags = []
215 | closedTags = []
216 | allTags = []
217 | isOpeningTag = false
218 | isClosingTag = false
219 |
220 | finalTag = ''
221 | maxRow = editor.getSession().getLength()
222 |
223 | _scanRow = (row, column) ->
224 | return if row > maxRow
225 | curColumn = 0
226 | tokens = editor.getSession().getTokens(row)
227 | lastTag = null
228 | for token in tokens
229 | curColumn += token.value.length
230 |
231 | isfinal = ->
232 | switch
233 | when openTags.length == 0
234 | true
235 | when openTags.length == closedTags.length
236 | openTags.pop()
237 | closedTags.pop()
238 | false
239 | when openTags[openTags.length-1] == closedTags[closedTags.length-1]
240 | openTags.pop()
241 | closedTags.pop()
242 | false
243 | else
244 | false
245 |
246 | latestTag = token.value if token.type == "meta.tag.tag-name"
247 |
248 | if curColumn > column
249 | switch
250 | when token.type == "meta.tag" and token.value == "<"
251 | isOpeningTag = true
252 | when token.type == "meta.tag.r" and token.value == ">" and (isOpeningTag or isClosingTag)
253 | isOpeningTag = false
254 | isClosingTag = false
255 | when token.type == "meta.tag.r" and token.value == ">" and openTags.length == 0
256 | # The cursor must be on a closing tag,
257 | # return element value
258 | return latestTag
259 | when token.type == "meta.tag" and token.value == ""
260 | isClosingTag = true
261 | when token.type == "meta.tag.r" and token.value == "/>"
262 | isOpeningTag = false
263 | isClosingTag = false
264 | milestone = openTags[openTags.length-1]
265 | milestone = latestTag if !milestone?
266 | closedTags.push milestone
267 | return milestone if isfinal()
268 | when token.type == "meta.tag.tag-name" and isOpeningTag
269 | allTags.push "<#{token.value}>"
270 | openTags.push token.value
271 | return token.value if isfinal()
272 | when token.type == "meta.tag.tag-name" and isClosingTag
273 | allTags.push "#{token.value}>"
274 | closedTags.push token.value
275 | return token.value if isfinal()
276 |
277 | _scanRow(row+1, 0)
278 |
279 | _scanRow(row, column)
280 |
281 | pos = editor.getCursorPosition()
282 | ident = _findParent(pos.row, pos.column)
283 | completions = []
284 |
285 | children = context.getChildrenOf(ident);
286 |
287 | if children?
288 | for c in children
289 | completions.push
290 | caption: c.ident,
291 | snippet: "#{c.ident}>#{c.ident}>",
292 | meta: "element"
293 | else
294 | completions.push
295 | caption: "unknown parent"
296 | snippet: ""
297 | meta: "element"
298 |
299 | if completions.length > 0
300 | callback null, completions
301 | else
302 | 0 #console.log 'Context Help component not loaded'
303 | @$editor.completers = [completer]
304 |
305 | ace.config.on "desc", (e) =>
306 | @dispatcher.trigger("editor:context", e.ident)
307 |
308 | ace.config.on "desc:clear", (e) =>
309 | @dispatcher.trigger 'notification:clear'
310 |
311 | @
312 |
313 | setContent: -> @$editor.setValue @model.get('content')
314 |
315 |
316 | getContent: -> @$editor.getValue()
317 |
318 | getDocument: ->
319 | getValue: => @$editor.getValue()
320 | getLength: => @$editor.session.getDocument().getLength()
321 | getLine: (n) => @$editor.session.getDocument().getLine(n)
322 |
323 | saveModel: ->
324 | @model.set 'content', @getContent()
325 | @model.save
326 | success: => @dispatcher.trigger "editor:reload"
327 | error: => @dispatcher.trigger "editor:error", "Unable to change document"
328 |
329 | setModel: (m) ->
330 | @model = m;
331 | @dispatcher.trigger "editor:reload"
332 |
333 | clearAnnotations: -> @$editor.session.clearAnnotations()
334 |
335 | setMode: (m) -> @$editor.getSession().setMode(m)
336 |
337 | )(window.Angles,_,Backbone,ace)
338 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Angles Editor Demo
5 |
6 |
7 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
46 |
47 |
48 |
49 |
50 |
51 |
<?xml version="1.0" encoding="UTF-8"?>
52 | <TEI xmlns="http://www.tei-c.org/ns/1.0">
53 | <teiHeader>
54 | <fileDesc>
55 | <titleStmt>
56 | <title>Title</title>
57 | </titleStmt>
58 | <publicationStmt>
59 | <p>Publication Information</p>
60 | </publicationStmt>
61 | <sourceDesc>
62 | <p>Information about the source</p>
63 | </sourceDesc>
64 | </fileDesc>
65 | </teiHeader>
66 | <text>
67 | <body>
68 | <p>Some text here.</p>
69 | </body>
70 | </text>
71 | </TEI>
72 |
73 |
74 |
Local Storage
75 |
81 |
82 |
Load from Disk Change
83 |
84 |
x
85 |
86 |
87 |
88 |
89 |
90 |
110 |
111 |
115 |
116 |
117 |
121 |
122 |
123 |
127 |
132 |
136 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
349 |
351 |
352 |
353 |
354 |
355 |
356 |
--------------------------------------------------------------------------------
/demo/srvValidation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Angles Editor Demo
5 |
6 |
7 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
46 |
47 |
48 |
49 |
50 |
Validate with:
51 |
52 | TEI Lite
54 | TEI Tite
56 | TEI Bare
58 | TEI MS Desc
60 | TEI Drama
62 | TEI ODD
64 | TEI All
66 | TEI Lite + MEI CMN
68 |
69 |
70 |
71 |
72 |
73 |
74 |
<?xml version="1.0" encoding="UTF-8"?>
75 | <TEI xmlns="http://www.tei-c.org/ns/1.0">
76 | <teiHeader>
77 | <fileDesc>
78 | <titleStmt>
79 | <title>Title</title>
80 | </titleStmt>
81 | <publicationStmt>
82 | <p>Publication Information</p>
83 | </publicationStmt>
84 | <sourceDesc>
85 | <p>Information about the source</p>
86 | </sourceDesc>
87 | </fileDesc>
88 | </teiHeader>
89 | <text>
90 | <body>
91 | <p>Some text here.</p>
92 | </body>
93 | </text>
94 | </TEI>
95 |
96 |
97 |
Local Storage
98 |
104 |
105 |
Load from Disk Change
106 |
107 |
x
108 |
109 |
110 |
111 |
112 |
113 |
133 |
134 |
138 |
139 |
140 |
144 |
145 |
146 |
150 |
155 |
159 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
368 |
369 |
372 |
373 |
374 |
375 |
--------------------------------------------------------------------------------
/demo/css/bootstrap-responsive.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Responsive v2.2.1
3 | *
4 | * Copyright 2012 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
10 |
--------------------------------------------------------------------------------
/demo/js/jasny-bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Jasny-bootstrap.js by @ArnoldDaniels
3 | * Copyright 2012 Arnold Daniels
4 | * http://www.apache.org/licenses/LICENSE-2.0.txt
5 | */
6 | !function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.options.target&&(this.$target=e(this.options.target)),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.strict=this.options.strict,this.$menu=e(this.options.menu),this.shown=!1,typeof this.source=="string"&&(this.url=this.source,this.source=this.searchAjax),t.nodeName=="SELECT"&&this.replaceSelect(),this.text=this.$element.val(),this.$element.attr("data-text",this.value).attr("autocomplete","off"),typeof this.$target!="undefined"?this.$element.attr("data-value",this.$target.val()):typeof this.$element.attr("data-value")=="undefined"&&this.$element.attr("data-value",this.strict?"":this.value),this.$menu.css("min-width",this.$element.width()+12),this.listen()};t.prototype={constructor:t,replaceSelect:function(){this.$target=this.$element,this.$element=e(' '),this.source={},this.strict=!0;var t=this.$target.find("option"),n;for(var r=0;r0?e.find(".item-text").text():e.text();return t=this.updater(t,"value"),n=this.updater(n,"text"),this.$element.val(n).attr("data-value",t),this.text=n,typeof this.$target!="undefined"&&this.$target.val(t).trigger("change"),this.$element.trigger("change"),this.hide()},updater:function(e,t){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length=n.options.items&&delete r[e]}),this.render(r).show())},searchAjax:function(t,n){var r=this;this.ajaxTimeout&&clearTimeout(this.ajaxTimeout),this.ajaxTimeout=setTimeout(function(){r.ajaxTimeout&&clearTimeout(r.ajaxTimeout);if(t===""){r.hide();return}e.get(r.url,{q:t,limit:r.options.items},function(e){typeof e=="string"&&(e=JSON.parse(e)),n(e)})},this.options.ajaxdelay)},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(t){return e.isArray(t)?this.sortArray(t):this.sortObject(t)},sortArray:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},sortObject:function(e){var t={},n;for(n in e)e[n].toLowerCase().indexOf(this.query.toLowerCase())||(t[n]=e[n],delete e[n]);for(n in e)~e[n].indexOf(this.query)&&(t[n]=e[n],delete e[n]);for(n in e)t[n]=e[n];return t},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return""+t+" "})},render:function(t){var n=this,r=e([]);return e.map(t,function(i,s){if(r.length>=n.options.items)return;var o,u;e.isArray(t)&&(s=i),o=e(n.options.item),u=o.find("a").length?o.find("a"):o,u.html(n.highlighter(i)),o.attr("data-value",s),o.find("a").length===0&&o.addClass("dropdown-header"),r.push(o[0])}),r.not(".dropdown-header").first().addClass("active"),this.$menu.html(r),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.nextAll("li:not(.dropdown-header)").first();r.length||(r=e(this.$menu.find("li:not(.dropdown-header)")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prevAll("li:not(.dropdown-header)").first();n.length||(n=this.$menu.find("li:not(.dropdown-header)").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("change",e.proxy(this.change,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this)),e(window).on("unload",e.proxy(this.destroyReplacement,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},change:function(e){var t;this.$element.val()!=this.text&&(t=this.$element.val()===""||this.strict?"":this.$element.val(),this.$element.val(t),this.$element.attr("data-value",t),this.text=t,typeof this.$target!="undefined"&&this.$target.val(t))},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'',item:' ',ajaxdelay:400,minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).off("focus.typeahead.data-api").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.is("select")&&n.attr("autofocus",!0),t.preventDefault(),n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=window.orientation!==undefined,n=navigator.userAgent.toLowerCase().indexOf("android")>-1,r=function(t,r){if(n)return;this.$element=e(t),this.options=e.extend({},e.fn.inputmask.defaults,r),this.mask=String(r.mask),this.init(),this.listen(),this.checkVal()};r.prototype={init:function(){var t=this.options.definitions,n=this.mask.length;this.tests=[],this.partialPosition=this.mask.length,this.firstNonMaskPos=null,e.each(this.mask.split(""),e.proxy(function(e,r){r=="?"?(n--,this.partialPosition=e):t[r]?(this.tests.push(new RegExp(t[r])),this.firstNonMaskPos===null&&(this.firstNonMaskPos=this.tests.length-1)):this.tests.push(null)},this)),this.buffer=e.map(this.mask.split(""),e.proxy(function(e,n){if(e!="?")return t[e]?this.options.placeholder:e},this)),this.focusText=this.$element.val(),this.$element.data("rawMaskFn",e.proxy(function(){return e.map(this.buffer,function(e,t){return this.tests[t]&&e!=this.options.placeholder?e:null}).join("")},this))},listen:function(){if(this.$element.attr("readonly"))return;var t=(navigator.userAgent.match(/msie/i)?"paste":"input")+".mask";this.$element.on("unmask",e.proxy(this.unmask,this)).on("focus.mask",e.proxy(this.focusEvent,this)).on("blur.mask",e.proxy(this.blurEvent,this)).on("keydown.mask",e.proxy(this.keydownEvent,this)).on("keypress.mask",e.proxy(this.keypressEvent,this)).on(t,e.proxy(this.pasteEvent,this))},caret:function(e,t){if(this.$element.length===0)return;if(typeof e=="number")return t=typeof t=="number"?t:e,this.$element.each(function(){if(this.setSelectionRange)this.setSelectionRange(e,t);else if(this.createTextRange){var n=this.createTextRange();n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",e),n.select()}});if(this.$element[0].setSelectionRange)e=this.$element[0].selectionStart,t=this.$element[0].selectionEnd;else if(document.selection&&document.selection.createRange){var n=document.selection.createRange();e=0-n.duplicate().moveStart("character",-1e5),t=e+n.text.length}return{begin:e,end:t}},seekNext:function(e){var t=this.mask.length;while(++e<=t&&!this.tests[e]);return e},seekPrev:function(e){while(--e>=0&&!this.tests[e]);return e},shiftL:function(e,t){var n=this.mask.length;if(e<0)return;for(var r=e,i=this.seekNext(t);rn.length)break}else this.buffer[i]==n.charAt(s)&&i!=this.partialPosition&&(s++,r=i);if(!e&&r+1=this.partialPosition)this.writeBuffer(),e||this.$element.val(this.$element.val().substring(0,r+1));return this.partialPosition?i:this.firstNonMaskPos}},e.fn.inputmask=function(t){return this.each(function(){var n=e(this),i=n.data("inputmask");i||n.data("inputmask",i=new r(this,t))})},e.fn.inputmask.defaults={mask:"",placeholder:"_",definitions:{9:"[0-9]",a:"[A-Za-z]","?":"[A-Za-z0-9]","*":"."}},e.fn.inputmask.Constructor=r,e(document).on("focus.inputmask.data-api","[data-mask]",function(t){var n=e(this);if(n.data("inputmask"))return;t.preventDefault(),n.inputmask(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){n=e.extend({},e.fn.rowlink.defaults,n);var r=t.nodeName.toLowerCase()=="tr"?e(t):e(t).find("tr:has(td)");r.each(function(){var t=e(this).find(n.target).first();if(!t.length)return;var r=t.attr("href");e(this).find("td").not(".nolink").click(function(){window.location=r}),e(this).addClass("rowlink"),t.replaceWith(t.html())})};e.fn.rowlink=function(n){return this.each(function(){var r=e(this),i=r.data("rowlink");i||r.data("rowlink",i=new t(this,n))})},e.fn.rowlink.defaults={target:"a"},e.fn.rowlink.Constructor=t,e(function(){e('[data-provide="rowlink"],[data-provides="rowlink"]').each(function(){e(this).rowlink(e(this).data())})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.type=this.$element.data("uploadtype")||(this.$element.find(".thumbnail").length>0?"image":"file"),this.$input=this.$element.find(":file");if(this.$input.length===0)return;this.name=this.$input.attr("name")||n.name,this.$hidden=this.$element.find('input[type=hidden][name="'+this.name+'"]'),this.$hidden.length===0&&(this.$hidden=e(' '),this.$element.prepend(this.$hidden)),this.$preview=this.$element.find(".fileupload-preview");var r=this.$preview.css("height");this.$preview.css("display")!="inline"&&r!="0px"&&r!="none"&&this.$preview.css("line-height",r),this.original={exists:this.$element.hasClass("fileupload-exists"),preview:this.$preview.html(),hiddenVal:this.$hidden.val()},this.$remove=this.$element.find('[data-dismiss="fileupload"]'),this.$element.find('[data-trigger="fileupload"]').on("click.fileupload",e.proxy(this.trigger,this)),this.listen()};t.prototype={listen:function(){this.$input.on("change.fileupload",e.proxy(this.change,this)),e(this.$input[0].form).on("reset.fileupload",e.proxy(this.reset,this)),this.$remove&&this.$remove.on("click.fileupload",e.proxy(this.clear,this))},change:function(e,t){if(t==="clear")return;var n=e.target.files!==undefined?e.target.files[0]:e.target.value?{name:e.target.value.replace(/^.+\\/,"")}:null;if(!n){this.clear();return}this.$hidden.val(""),this.$hidden.attr("name",""),this.$input.attr("name",this.name);if(this.type==="image"&&this.$preview.length>0&&(typeof n.type!="undefined"?n.type.match("image.*"):n.name.match(/\.(gif|png|jpe?g)$/i))&&typeof FileReader!="undefined"){var r=new FileReader,i=this.$preview,s=this.$element;r.onload=function(e){i.html(' "),s.addClass("fileupload-exists").removeClass("fileupload-new")},r.readAsDataURL(n)}else this.$preview.text(n.name),this.$element.addClass("fileupload-exists").removeClass("fileupload-new")},clear:function(e){this.$hidden.val(""),this.$hidden.attr("name",this.name),this.$input.attr("name","");if(navigator.userAgent.match(/msie/i)){var t=this.$input.clone(!0);this.$input.after(t),this.$input.remove(),this.$input=t}else this.$input.val("");this.$preview.html(""),this.$element.addClass("fileupload-new").removeClass("fileupload-exists"),e&&(this.$input.trigger("change",["clear"]),e.preventDefault())},reset:function(e){this.clear(),this.$hidden.val(this.original.hiddenVal),this.$preview.html(this.original.preview),this.original.exists?this.$element.addClass("fileupload-exists").removeClass("fileupload-new"):this.$element.addClass("fileupload-new").removeClass("fileupload-exists")},trigger:function(e){this.$input.trigger("click"),e.preventDefault()}},e.fn.fileupload=function(n){return this.each(function(){var r=e(this),i=r.data("fileupload");i||r.data("fileupload",i=new t(this,n)),typeof n=="string"&&i[n]()})},e.fn.fileupload.Constructor=t,e(document).on("click.fileupload.data-api",'[data-provides="fileupload"]',function(t){var n=e(this);if(n.data("fileupload"))return;n.fileupload(n.data());var r=e(t.target).closest('[data-dismiss="fileupload"],[data-trigger="fileupload"]');r.length>0&&(r.trigger("click.fileupload"),t.preventDefault())})}(window.jQuery);
--------------------------------------------------------------------------------
/test/angles_test.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | /*
3 | ======== A Handy Little QUnit Reference ========
4 | http://api.qunitjs.com/
5 |
6 | Test methods:
7 | module(name, {[setup][ ,teardown]})
8 | test(name, callback)
9 | expect(numberOfAssertions)
10 | stop(increment)
11 | start(decrement)
12 | Test assertions:
13 | ok(value, [message])
14 | equal(actual, expected, [message])
15 | notEqual(actual, expected, [message])
16 | deepEqual(actual, expected, [message])
17 | notDeepEqual(actual, expected, [message])
18 | strictEqual(actual, expected, [message])
19 | notStrictEqual(actual, expected, [message])
20 | throws(block, [expected], [message])
21 | */
22 |
23 | test("Check namespaces", function() {
24 | expect(4);
25 | ok(typeof ace !== "undefined" && ace !== null, "Ace namespace defined");
26 | ok(typeof _ !== "undefined" && _ !== null, "Underscore namespace defined");
27 | ok(typeof Backbone !== "undefined" && Backbone !== null, "Backbone namepsace defined");
28 | ok(typeof Angles !== "undefined" && Angles !== null, "Angles namespace defined");
29 | });
30 |
31 | test("Check base validation class", function() {
32 | var validator = new Angles.Validator({
33 | dispatcher: _.clone(Backbone.Events)
34 | }), dispatcher, validationEventTriggered = 0, validationEndEventTriggered = 0, validationErrorEventTriggered = 0;
35 |
36 | expect(28);
37 |
38 | dispatcher = validator.dispatcher;
39 |
40 | dispatcher.on("validation", function() {
41 | validationEventTriggered += 1;
42 | });
43 | dispatcher.on("validation:end", function() {
44 | validationEndEventTriggered += 1;
45 | });
46 | dispatcher.on("validation:error", function() {
47 | validationErrorEventTriggered += 1;
48 | });
49 |
50 | ok(typeof validator !== "undefined" && validator !== null, "Validator object is created");
51 | ok(typeof validator.displayErrors !== "undefined" && validator.displayErrors !== null, "displayErrors method exists");
52 | ok(typeof validator.endValidation !== "undefined" && validator.endValidation !== null, "endValidation method exists");
53 | ok(typeof validator.setSchema !== "undefined" && validator.setSchema !== null, "setSchema method exists");
54 | ok(typeof validator.errors !== "undefined" && validator.errors !== null, "errors method exists");
55 |
56 | equal(validationEventTriggered, 0, "validation event counter zero before test");
57 | equal(validationErrorEventTriggered, 0, "validation:error counter zero before test");
58 | equal(validationEndEventTriggered, 0, "validation:end counter zero before test");
59 | validator.setSchema({});
60 | equal(validationEventTriggered, 1, "validation event was triggered by setting the schema");
61 | equal(validationErrorEventTriggered, 0, "validation:error not triggered by setting the schema");
62 | equal(validationEndEventTriggered, 0, "validation:end not triggered by setting the schema");
63 |
64 | validationEventTriggered = 0;
65 | validationErrorEventTriggered = 0;
66 | validationEndEventTriggered = 0;
67 | equal(validationEventTriggered, 0, "validation event counter zero before test");
68 | equal(validationErrorEventTriggered, 0, "validation:error counter zero before test");
69 | equal(validationEndEventTriggered, 0, "validation:end counter zero before test");
70 | validator.endValidation();
71 | equal(validationEventTriggered, 0, "validation event not triggered by endValidation");
72 | equal(validationErrorEventTriggered, 0, "validation:error not triggered by endValidation");
73 | equal(validationEndEventTriggered, 1, "validation:end was triggered by endValidation");
74 |
75 | validationEventTriggered = 0;
76 | validationErrorEventTriggered = 0;
77 | validationEndEventTriggered = 0;
78 |
79 | ok(!validator.hasErrors(), "validator has no errors");
80 | validator.addError({});
81 | validator.addError({});
82 | equal(validationEventTriggered, 0, "validation event not triggered by addError");
83 | equal(validationErrorEventTriggered, 0, "validation:error not triggered by addError");
84 | equal(validationEndEventTriggered, 0, "validation:end not triggered by addError");
85 | ok(validator.hasErrors(), "validator now has errors");
86 | equal(validator.errors().length, 2, "validator has two errors");
87 | validator.displayErrors();
88 | equal(validationEventTriggered, 0, "validation event not triggered by displayErrors");
89 | equal(validationErrorEventTriggered, 2, "validation:error triggered twice by displayErrors");
90 | equal(validationEndEventTriggered, 1, "validation:end triggered by displayErrors");
91 |
92 | validationEventTriggered = 0;
93 | validationErrorEventTriggered = 0;
94 | validationEndEventTriggered = 0;
95 |
96 | validator.clearErrors();
97 | ok(!validator.hasErrors(), "validator has no errors after clearErrors");
98 | equal(validator.errors().length, 0, "validator errors() returns empty array after clearErrors");
99 | });
100 |
101 | test("Check SAX/browser-based validation class", function() {
102 | var validator, dispatcher, validationEventTriggered = 0, validationEndEventTriggered = 0,
103 | validationErrorEventTriggered = 0, doc;
104 |
105 | expect(23);
106 |
107 | validator = new Angles.ValidatorSAX({
108 | dispatcher: _.clone(Backbone.Events)
109 | });
110 |
111 | ok(typeof validator !== "undefined" && validator !== null, "Validator object is created");
112 | ok(typeof validator.displayErrors !== "undefined" && validator.displayErrors !== null, "displayErrors method exists");
113 | ok(typeof validator.endValidation !== "undefined" && validator.endValidation !== null, "endValidation method exists");
114 | ok(typeof validator.setSchema !== "undefined" && validator.setSchema !== null, "setSchema method exists");
115 | ok(typeof validator.errors !== "undefined" && validator.errors !== null, "errors method exists");
116 |
117 | dispatcher = validator.dispatcher;
118 |
119 | dispatcher.on("validation", function() {
120 | validationEventTriggered = 1;
121 | });
122 | dispatcher.on("validation:end", function() {
123 | validationEndEventTriggered = 1;
124 | });
125 | dispatcher.on("validation:error", function() {
126 | validationErrorEventTriggered += 1;
127 | });
128 |
129 | ok(typeof window.testSchema !== "undefined" && window.testSchema !== null, "Schema loaded");
130 | equal(validationEventTriggered, 0, "validation event counter zero before test");
131 | equal(validationErrorEventTriggered, 0, "validation:error counter zero before test");
132 | equal(validationEndEventTriggered, 0, "validation:end counter zero before test");
133 | validator.setSchema(window.testSchema);
134 |
135 | equal(validationEventTriggered, 1, "validation event was triggered by setting the schema");
136 | equal(validationErrorEventTriggered, 0, "validation:error not triggered by setting the schema");
137 | equal(validationEndEventTriggered, 0, "validation:end not triggered by setting the schema");
138 |
139 | validationEventTriggered = 0;
140 | validationErrorEventTriggered = 0;
141 | validationEndEventTriggered = 0;
142 |
143 | doc = {
144 | getLine: function(i) {
145 | return doc.$lines[i];
146 | },
147 | getLength: function() { return doc.$lines.length; },
148 | $lines: [
149 | "",
150 | " "
151 | ]
152 | };
153 |
154 | equal(validationEventTriggered, 0, "validation event counter zero before test");
155 | equal(validationErrorEventTriggered, 0, "validation:error counter zero before test");
156 | equal(validationEndEventTriggered, 0, "validation:end counter zero before test");
157 | validator.validate(doc);
158 |
159 | equal(validationEventTriggered, 0, "validation event not triggered by validation");
160 | ok(validationErrorEventTriggered > 0, "validation:error triggered by validation");
161 | equal(validationEndEventTriggered, 1, "validation:end triggered by validation");
162 | equal(validator.errors().length, 1, "one error");
163 | equal(validator.errors()[0].row, 1, "on row one");
164 | equal(validator.errors()[0].type, "error", "an error (not a warning)");
165 |
166 | // no RDF allowed in the browser-based validation schema, so RDF removed. Otherwise, this is the document
167 | // from https://github.com/opensiddur/opensiddur/blob/master/code/tests/minimal-valid.xml
168 |
169 | doc.$lines = [
170 | '',
171 | ' ',
172 | ' ',
173 | ' ',
174 | ' Minimal valid JLPTEI ',
175 | ' ',
176 | ' ',
177 | ' ',
178 | ' To the extent possible under law, ',
179 | 'the contributors who associated ',
180 | '[Creative Commons Zero](licenses/cc0/1.0) ',
181 | 'with this work have waived all copyright and related or ',
182 | 'neighboring rights to this work. ',
183 | 'A list of contributors is available at ',
184 | '[http://jewishliturgy.org/base/text/contributors](http://jewishliturgy.org/base/text/contributors).',
185 | '
',
186 | ' ',
187 | ' $Id: minimal-valid.xml 411 2010-01-03 06:58:09Z efraim.feinstein $ ',
188 | ' ',
189 | ' ',
190 | ' Born digital.
',
191 | ' ',
192 | ' ',
193 | ' ',
194 | '',
195 | ' ',
196 | ' ',
197 | ' Shortest document ever',
198 | '
Yay!
',
199 | '
',
200 | ' ',
201 | ' ',
202 | ' '
203 | ];
204 |
205 | validationEventTriggered = 0;
206 | validationErrorEventTriggered = 0;
207 | validationEndEventTriggered = 0;
208 | validator.clearErrors();
209 |
210 | ok(!validator.hasErrors(), "Errors cleared");
211 |
212 | validator.validate(doc);
213 | ok(!validator.hasErrors(), "no errors after validating valid document");
214 | });
215 |
216 | test("Check notification infrastructure", function() {
217 | var note, noteList, note1, note2, noteCenter, dispatcher;
218 |
219 | expect(22);
220 |
221 | ok(typeof Angles.Notification !== "undefined" && Angles.Notification !== null, "Notification class is defined");
222 | ok(typeof Angles.NotificationList !== "undefined" && Angles.NotificationList !== null, "NotificationList class is defined");
223 | ok(typeof Angles.NotificationCenter !== "undefined" && Angles.NotificationCenter !== null, "NotificationCenter class is defined");
224 |
225 | note = new Angles.Notification();
226 | ok(typeof note !== "undefined" && note !== null, "Created Angles.Notification successfully");
227 | deepEqual(note.attributes, {
228 | info: "",
229 | location: {
230 | column: -1,
231 | row: -1
232 | },
233 | message: "",
234 | resource: "",
235 | type: ""
236 | }, "Proper initialized default attributes");
237 |
238 | note = new Angles.Notification({
239 | info: "info",
240 | location: {
241 | column: 10,
242 | row: 20
243 | },
244 | message: "message",
245 | resource: "resource",
246 | type: "type"
247 | });
248 | ok(typeof note !== "undefined" && note !== null, "Created Angles.Notification successfully with custom data");
249 | deepEqual(note.attributes, {
250 | info: "info",
251 | location: {
252 | column: 10,
253 | row: 20
254 | },
255 | message: "message",
256 | resource: "resource",
257 | type: "type"
258 | }, "Proper initialized given attributes");
259 |
260 | noteList = new Angles.NotificationList();
261 | ok(typeof noteList !== "undefined" && noteList !== null, "Created Angles.NotificationList");
262 |
263 | equal(noteList.length, 0, "note list is empty");
264 | noteList.add(note);
265 | equal(noteList.length, 1, "note list should have one entry");
266 | noteList.add(note);
267 | equal(noteList.length, 1, "note list should have one entry");
268 | noteList.add({
269 | info: "info2",
270 | message: "Message2",
271 | resource: "resource2",
272 | type: 'type2'
273 | });
274 | equal(noteList.length, 2, "note list should have two entries");
275 |
276 | note1 = noteList.at(0);
277 | note2 = noteList.at(1);
278 | ok(typeof note1 !== "undefined" && note1 !== null, "first item in noteList is defined");
279 | ok(typeof note2 !== "undefined" && note2 !== null, "second item in noteList is defined");
280 |
281 | equal(note1.get('info'), 'info', 'First note was inserted first');
282 | equal(note2.get('info'), 'info2', 'Second note was inserted second');
283 |
284 | noteCenter = new Angles.NotificationCenter({
285 | dispatcher: _.clone(Backbone.Events)
286 | });
287 | ok(typeof noteCenter !== "undefined" && noteCenter !== null, "notification center object was created");
288 |
289 | dispatcher = noteCenter.dispatcher;
290 | ok(typeof dispatcher !== "undefined" && dispatcher !== null, "notification center dispatcher was created");
291 |
292 | equal(noteCenter.$notifications.length, 0, "No notifications");
293 |
294 | noteCenter.push({});
295 |
296 | equal(noteCenter.$notifications.length, 1, "One notification now");
297 |
298 | dispatcher.trigger("notification:push", {});
299 |
300 | equal(noteCenter.$notifications.length, 2, "Two notifications now");
301 |
302 | dispatcher.trigger("notification:clear");
303 |
304 | equal(noteCenter.$notifications.length, 0, "No notifications after notification:clear trigger");
305 |
306 | });
307 |
308 | test("Check context help", function() {
309 | var contextHelp, dispatcher;
310 | //expect(0);
311 | ok(typeof Angles.ContextHelp !== "undefined" && Angles.ContextHelp !== null, "ContextHelp class is defined");
312 |
313 | ok(typeof window.testODD !== "undefined" && window.testODD !== null, "Test ODD file loaded");
314 | /*
315 | getDescOf: (e) -> @getODDfor(e)?.desc
316 |
317 | getChildrenOf: (e) ->
318 | @getODDfor(e)?.children
319 | */
320 |
321 | contextHelp = new Angles.ContextHelp({
322 | dispatcher: _.clone(Backbone.Events)
323 | });
324 | dispatcher = contextHelp.dispatcher;
325 | contextHelp.setODD(window.testODD);
326 |
327 | ok(contextHelp.getODDfor("p"), "There's something for 'p'");
328 | ok(!contextHelp.getODDfor("foobar"), "There's nothing for 'foobar'");
329 | });
330 |
331 | test("Check XMLDocument(List)", function() {
332 | var doc, docList;
333 |
334 | ok(typeof Angles.XMLDocument !== "undefined" && Angles.XMLDocument !== null, "XMLDocument class is defined");
335 | ok(typeof Angles.XMLDocumentList !== "undefined" && Angles.XMLDocumentList !== null, "XMLDocumentList class is defined");
336 |
337 | doc = new Angles.XMLDocument();
338 | ok(typeof doc !== "undefined" && doc !== null, "XMLDocument instance created");
339 | deepEqual(doc.attributes, {
340 | "name": "untitled",
341 | "content": ""
342 | }, "correct default attributes for a document");
343 |
344 | doc = new Angles.XMLDocument({
345 | "name": "Foo",
346 | "content": "Bar"
347 | });
348 |
349 | ok(typeof doc !== "undefined" && doc !== null, "XMLDocument instance created");
350 |
351 | deepEqual(doc.attributes, {
352 | "name": "Foo",
353 | "content": "Bar"
354 | }, "correct attributes for document");
355 |
356 | docList = new Angles.XMLDocumentList();
357 | ok(typeof docList !== "undefined" && docList !== null, "XMLDocumentList instance created");
358 | });
359 |
360 | test("Check ACE editor instantiation", function() {
361 | var editor, dispatcher, doc;
362 | //expect(5);
363 |
364 | ok(typeof Angles.ACEEditorView !== "undefined" && Angles.ACEEditorView !== null, "ACEEditorView class is defined");
365 | editor = new Angles.ACEEditorView({
366 | el: "#ace-editor"
367 | });
368 | ok(typeof editor !== "undefined" && editor !== null, "editor is created");
369 |
370 | editor.render();
371 | ok(typeof editor.$editor !== "undefined" && editor.$editor !== null, "ACE instance is defined");
372 |
373 | ok(editor.$el.hasClass("ace_editor"), "ACE edit area has the right class");
374 |
375 | dispatcher = editor.dispatcher;
376 |
377 | doc = new Angles.XMLDocument({
378 | "content": "***Foo***"
379 | });
380 | editor.setModel(doc);
381 | equal(editor.getContent(), "***Foo***", "Getting content from editor returns value set");
382 |
383 | });
384 |
385 | })();
--------------------------------------------------------------------------------
/demo/css/jasny-bootstrap.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Jasny Bootstrap Extensions j3
3 | *
4 | * Copyright 2012 Jasny BV
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Extended with pride by @ArnoldDaniels of jasny.net
9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.container-semifluid{max-width:940px;padding-right:20px;padding-left:20px;margin-right:auto;margin-left:auto;*zoom:1}.container-semifluid:before,.container-semifluid:after{display:table;line-height:0;content:""}.container-semifluid:after{clear:both}form>*:last-child{margin-bottom:0}label input[type="image"],label input[type="checkbox"],label input[type="radio"]{vertical-align:middle}select{padding-left:2px}.small-labels .control-group>label{width:70px}.small-labels .controls{margin-left:80px}.small-labels .form-actions{padding-left:80px}.form-vertical .form-horizontal .control-group>label{text-align:left}.form-horizontal .form-vertical .control-group>label{float:none;padding-top:0;text-align:left}.form-horizontal .form-vertical .controls{margin-left:0}.form-horizontal .form-vertical.form-actions,.form-horizontal .form-vertical .form-actions{padding-left:20px}.control-group .control-group{margin-bottom:0}.form-horizontal .well .control-label{width:120px}.form-horizontal .well .controls{margin-left:140px}form .well>*:last-child{margin-bottom:0}.editor{width:100%;height:100px;padding:5px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.uneditable-textarea.editor-html{padding:5px 3px 5px 5px;white-space:normal}textarea.editor-html{visibility:hidden}.uneditable-input,.uneditable-textarea{display:inline-block;padding:4px 3px 4px 5px;font-size:14px;line-height:20px;color:#555;cursor:not-allowed;background-color:#fff;border:1px solid #eee;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.uneditable-input{height:20px;overflow:hidden;white-space:pre}.uneditable-textarea{overflow-x:hidden;overflow-y:auto;white-space:pre-wrap}select[disabled],textarea[disabled],input[type="text"][disabled],input[type="password"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="search"][disabled]{color:#999}.uneditable-input.disabled,.uneditable-textarea.disabled{color:#999;cursor:not-allowed;background-color:#f5f5f5;border-color:#ddd}textarea,.uneditable-textarea{height:60px}textarea[rows="1"],.uneditable-textarea[rows="1"]{height:40px}textarea[rows="2"],.uneditable-textarea[rows="2"]{height:60px}textarea[rows="3"],.uneditable-textarea[rows="3"]{height:80px}textarea[rows="4"],.uneditable-textarea[rows="4"]{height:100px}textarea[rows="5"],.uneditable-textarea[rows="5"]{height:120px}textarea[rows="6"],.uneditable-textarea[rows="6"]{height:140px}textarea[rows="7"],.uneditable-textarea[rows="7"]{height:160px}textarea[rows="8"],.uneditable-textarea[rows="8"]{height:180px}textarea[rows="9"],.uneditable-textarea[rows="9"]{height:200px}textarea[rows="10"],.uneditable-textarea[rows="10"]{height:220px}textarea[rows="11"],.uneditable-textarea[rows="11"]{height:240px}textarea[rows="12"],.uneditable-textarea[rows="12"]{height:260px}textarea[rows="13"],.uneditable-textarea[rows="13"]{height:280px}textarea[rows="14"],.uneditable-textarea[rows="14"]{height:300px}textarea[rows="15"],.uneditable-textarea[rows="15"]{height:320px}textarea[rows="16"],.uneditable-textarea[rows="16"]{height:340px}textarea[rows="17"],.uneditable-textarea[rows="17"]{height:360px}textarea[rows="18"],.uneditable-textarea[rows="18"]{height:380px}textarea[rows="19"],.uneditable-textarea[rows="19"]{height:400px}textarea[rows="20"],.uneditable-textarea[rows="20"]{height:420px}textarea[rows="21"],.uneditable-textarea[rows="21"]{height:440px}textarea[rows="22"],.uneditable-textarea[rows="22"]{height:460px}textarea[rows="23"],.uneditable-textarea[rows="23"]{height:480px}textarea[rows="24"],.uneditable-textarea[rows="24"]{height:500px}textarea[rows="25"],.uneditable-textarea[rows="25"]{height:520px}textarea[rows="26"],.uneditable-textarea[rows="26"]{height:540px}textarea[rows="27"],.uneditable-textarea[rows="27"]{height:560px}textarea[rows="28"],.uneditable-textarea[rows="28"]{height:580px}textarea[rows="29"],.uneditable-textarea[rows="29"]{height:600px}textarea[rows="30"],.uneditable-textarea[rows="30"]{height:620px}textarea[rows="35"],.uneditable-textarea[rows="35"]{height:720px}textarea[rows="40"],.uneditable-textarea[rows="40"]{height:820px}textarea[rows="45"],.uneditable-textarea[rows="45"]{height:920px}textarea[rows="50"],.uneditable-textarea[rows="50"]{height:1020px}textarea[rows="55"],.uneditable-textarea[rows="55"]{height:1120px}textarea[rows="60"],.uneditable-textarea[rows="60"]{height:1220px}textarea[rows="65"],.uneditable-textarea[rows="65"]{height:1320px}textarea[rows="70"],.uneditable-textarea[rows="70"]{height:1420px}textarea[rows="75"],.uneditable-textarea[rows="75"]{height:1520px}textarea[rows="80"],.uneditable-textarea[rows="80"]{height:1620px}textarea[rows="85"],.uneditable-textarea[rows="85"]{height:1720px}textarea[rows="90"],.uneditable-textarea[rows="90"]{height:1820px}textarea[rows="95"],.uneditable-textarea[rows="95"]{height:1920px}textarea[rows="100"],.uneditable-textarea[rows="100"]{height:2020px}.uneditable-textarea{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.uneditable-input[class*="span"],.uneditable-textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .uneditable-textarea[class*="span"]{float:none;margin-left:0}.input-append .uneditable-input,.input-prepend .uneditable-input{vertical-align:top}.input-append .uneditable-input[class*="span"],.input-prepend .uneditable-input[class*="span"]{display:inline-block}.uneditable-form input[disabled],.uneditable-form textarea[disabled],.uneditable-form select[disabled]{cursor:auto}.uneditable-form .uneditable-input,.uneditable-form .uneditable-textarea{cursor:text}.uneditable-form .form-actions{background-color:transparent}.header-actions{padding:0 20px;line-height:36px}.table-actions{padding-bottom:20px;*zoom:1}.table-actions:before,.table-actions:after{display:table;line-height:0;content:""}.table-actions:after{clear:both}tr.rowlink td{cursor:pointer}tr.rowlink td.nolink{cursor:auto}.table tbody tr.rowlink:hover td{background-color:#cfcfcf}a.rowlink{font:inherit;color:inherit;text-decoration:inherit}.act{display:inline;padding:0;font-weight:bold;color:#555;background:inherit;border:0;-webkit-transition:text-shadow .1s linear;-moz-transition:text-shadow .1s linear;-o-transition:text-shadow .1s linear;transition:text-shadow .1s linear}.act:hover{color:#333;text-decoration:none;text-shadow:1px 1px 3px rgba(85,85,85,0.5)}.act-primary{color:#006dcc}.act-primary:hover{color:#04c;text-shadow:1px 1px 3px rgba(0,109,204,0.5)}.act-info{color:#49afcd}.act-info:hover{color:#2f96b4;text-shadow:1px 1px 3px rgba(75,175,206,0.5)}.act-success{color:#51a351}.act-success:hover{color:#468847;text-shadow:1px 1px 3px rgba(81,164,81,0.5)}.act-warning{color:#c09853}.act-warning:hover{color:#f89406;text-shadow:1px 1px 3px rgba(192,152,84,0.5)}.act-danger{color:#b94a48}.act-danger:hover{color:#bd362f;text-shadow:1px 1px 3px rgba(185,72,70,0.5)}.act.disabled,.act[disabled]{color:#aaa;cursor:not-allowed}.act.disabled:hover,.act[disabled]:hover{color:#aaa;text-shadow:none}.form-actions .act{line-height:30px}@font-face{font-family:IconicStroke;font-weight:normal;src:url(../font/iconic_stroke.eot);src:local('IconicStroke'),url(../font/iconic_stroke.eot?#iefix) format('embedded-opentype'),url(../font/iconic_stroke.woff) format('woff'),url(../font/iconic_stroke.ttf) format('truetype'),url(../font/iconic_stroke.svg#iconic) format('svg'),url(../font/iconic_stroke.otf) format('opentype')}@font-face{font-family:IconicFill;font-weight:normal;src:url(../font/iconic_fill.eot);src:local('IconicFill'),url(../font/iconic_fill.eot?#iefix) format('embedded-opentype'),url(../font/iconic_fill.woff) format('woff'),url(../font/iconic_fill.ttf) format('truetype'),url(../font/iconic_fill.svg#iconic) format('svg'),url(../font/iconic_fill.otf) format('opentype')}@media screen,print{[class*="iconic-"]{font-style:inherit;font-weight:normal;vertical-align:bottom}[class*="iconic-"]:before{display:inline-block;width:1em;font-family:IconicFill;font-size:.9em;text-align:center;vertical-align:middle;content:""}.iconic-stroke:before{font-family:IconicStroke}.iconic-hash:before{content:'\23'}.iconic-question-mark:before{content:'\3f'}.iconic-at:before{content:'\40'}.iconic-pilcrow:before{content:'\b6'}.iconic-info:before{content:'\2139'}.iconic-arrow-left:before{content:'\2190'}.iconic-arrow-up:before{content:'\2191'}.iconic-arrow-right:before{content:'\2192'}.iconic-arrow-down:before{content:'\2193'}.iconic-home:before{content:'\2302'}.iconic-sun:before{content:'\2600'}.iconic-cloud:before{content:'\2601'}.iconic-umbrella:before{content:'\2602'}.iconic-star:before{content:'\2605'}.iconic-moon:before{content:'\263e'}.iconic-heart:before{content:'\2764'}.iconic-cog:before{content:'\2699'}.iconic-bolt:before{content:'\26a1'}.iconic-key:before{content:'\26bf'}.iconic-rain:before{content:'\26c6'}.iconic-denied:before{content:'\26d4'}.iconic-mail:before{content:'\2709'}.iconic-pen:before{content:'\270e'}.iconic-x:before{content:'\2717'}.iconic-o-x:before{content:'\2718'}.iconic-check:before{content:'\2713'}.iconic-o-check:before{content:'\2714'}.iconic-left-quote:before{content:'\275d'}.iconic-right-quote:before{content:'\275e'}.iconic-plus:before{content:'\2795'}.iconic-minus:before{content:'\2796'}.iconic-curved-arrow:before{content:'\2935'}.iconic-document-alt:before{content:'\e000'}.iconic-calendar:before{content:'\e001'}.iconic-map-pin-alt:before{content:'\e002'}.iconic-comment-alt1:before{content:'\e003'}.iconic-comment-alt2:before{content:'\e004'}.iconic-pen-alt:before{content:'\e005'}.iconic-pen-alt2:before{content:'\e006'}.iconic-chat-alt:before{content:'\e007'}.iconic-o-plus:before{content:'\e008'}.iconic-o-minus:before{content:'\e009'}.iconic-bars-alt:before{content:'\e00a'}.iconic-book-alt:before{content:'\e00b'}.iconic-aperture-alt:before{content:'\e00c'}.iconic-beaker-alt:before{content:'\e010'}.iconic-left-quote-alt:before{content:'\e011'}.iconic-right-quote-alt:before{content:'\e012'}.iconic-o-arrow-left:before{content:'\e013'}.iconic-o-arrow-up:before{content:'\e014'}.iconic-o-arrow-right:before{content:'\e015'}.iconic-o-arrow-down:before{content:'\e016'}.iconic-o-arrow-left-alt:before{content:'\e017'}.iconic-o-arrow-up-alt:before{content:'\e018'}.iconic-o-arrow-right-alt:before{content:'\e019'}.iconic-o-arrow-down-alt:before{content:'\e01a'}.iconic-brush:before{content:'\e01b'}.iconic-brush-alt:before{content:'\e01c'}.iconic-eyedropper:before{content:'\e01e'}.iconic-layers:before{content:'\e01f'}.iconic-layers-alt:before{content:'\e020'}.iconic-compass:before{content:'\e021'}.iconic-award:before{content:'\e022'}.iconic-beaker:before{content:'\e023'}.iconic-steering-wheel:before{content:'\e024'}.iconic-eye:before{content:'\e025'}.iconic-aperture:before{content:'\e026'}.iconic-image:before{content:'\e027'}.iconic-chart:before{content:'\e028'}.iconic-chart-alt:before{content:'\e029'}.iconic-target:before{content:'\e02a'}.iconic-tag:before{content:'\e02b'}.iconic-rss:before{content:'\e02c'}.iconic-rss-alt:before{content:'\e02d'}.iconic-share:before{content:'\e02e'}.iconic-undo:before{content:'\e02f'}.iconic-reload:before{content:'\e030'}.iconic-reload-alt:before{content:'\e031'}.iconic-loop:before{content:'\e032'}.iconic-loop-alt:before{content:'\e033'}.iconic-back-forth:before{content:'\e034'}.iconic-back-forth-alt:before{content:'\e035'}.iconic-spin:before{content:'\e036'}.iconic-spin-alt:before{content:'\e037'}.iconic-move-horizontal:before{content:'\e038'}.iconic-move-horizontal-alt:before{content:'\e039'}.iconic-o-move-horizontal:before{content:'\e03a'}.iconic-move-vertical:before{content:'\e03b'}.iconic-move-vertical-alt:before{content:'\e03c'}.iconic-o-move-vertical:before{content:'\e03d'}.iconic-move:before{content:'\e03e'}.iconic-move-alt:before{content:'\e03f'}.iconic-o-move:before{content:'\e040'}.iconic-transfer:before{content:'\e041'}.iconic-download:before{content:'\e042'}.iconic-upload:before{content:'\e043'}.iconic-cloud-download:before{content:'\e044'}.iconic-cloud-upload:before{content:'\e045'}.iconic-fork:before{content:'\e046'}.iconic-play:before{content:'\e047'}.iconic-o-play:before{content:'\e048'}.iconic-pause:before{content:'\e049'}.iconic-stop:before{content:'\e04a'}.iconic-eject:before{content:'\e04b'}.iconic-first:before{content:'\e04c'}.iconic-last:before{content:'\e04d'}.iconic-fullscreen:before{content:'\e04e'}.iconic-fullscreen-alt:before{content:'\e04f'}.iconic-fullscreen-exit:before{content:'\e050'}.iconic-fullscreen-exit-alt:before{content:'\e051'}.iconic-equalizer:before{content:'\e052'}.iconic-article:before{content:'\e053'}.iconic-read-more:before{content:'\e054'}.iconic-list:before{content:'\e055'}.iconic-list-nested:before{content:'\e056'}.iconic-cursor:before{content:'\e057'}.iconic-dial:before{content:'\e058'}.iconic-new-window:before{content:'\e059'}.iconic-trash:before{content:'\e05a'}.iconic-battery-half:before{content:'\e05b'}.iconic-battery-empty:before{content:'\e05c'}.iconic-battery-charging:before{content:'\e05d'}.iconic-chat:before{content:'\e05e'}.iconic-mic:before{content:'\e05f'}.iconic-movie:before{content:'\e060'}.iconic-headphones:before{content:'\e061'}.iconic-user:before{content:'\e062'}.iconic-lightbulb:before{content:'\e063'}.iconic-cd:before{content:'\e064'}.iconic-folder:before{content:'\e065'}.iconic-document:before{content:'\e066'}.iconic-pin:before{content:'\e067'}.iconic-map-pin:before{content:'\e068'}.iconic-book:before{content:'\e069'}.iconic-book-alt2:before{content:'\e06a'}.iconic-box:before{content:'\e06b'}.iconic-calendar-alt:before{content:'\e06c'}.iconic-comment:before{content:'\e06d'}.iconic-iphone:before{content:'\e06e'}.iconic-bars:before{content:'\e06f'}.iconic-camera:before{content:'\e070'}.iconic-volume-mute:before{content:'\e071'}.iconic-volume:before{content:'\e072'}.iconic-battery-full:before{content:'\e073'}.iconic-magnifying-glass:before{content:'\e074'}.iconic-lock:before{content:'\e075'}.iconic-unlock:before{content:'\e076'}.iconic-link:before{content:'\e077'}.iconic-wrench:before{content:'\e078'}.iconic-clock:before{content:'\e079'}.iconic-sun-stroke:before{font-family:IconicStroke;content:'\2600'}.iconic-moon-stroke:before{font-family:IconicStroke;content:'\263e'}.iconic-star-stroke:before{font-family:IconicStroke;content:'\2605'}.iconic-heart-stroke:before{font-family:IconicStroke;content:'\2764'}.iconic-key-stroke:before{font-family:IconicStroke;content:'\26bf'}.iconic-document-alt-stroke:before{font-family:IconicStroke;content:'\e000'}.iconic-comment-alt1-stroke:before{font-family:IconicStroke;content:'\e003'}.iconic-comment-alt2-stroke:before{font-family:IconicStroke;content:'\e004'}.iconic-pen-alt-stroke:before{font-family:IconicStroke;content:'\e005'}.iconic-chat-alt-stroke:before{font-family:IconicStroke;content:'\e007'}.iconic-award-stroke:before{font-family:IconicStroke;content:'\e022'}.iconic-tag-stroke:before{font-family:IconicStroke;content:'\e02b'}.iconic-trash-stroke:before{font-family:IconicStroke;content:'\e05a'}.iconic-folder-stroke:before{font-family:IconicStroke;content:'\e065'}.iconic-document-stroke:before{font-family:IconicStroke;content:'\e066'}.iconic-map-pin-stroke:before{font-family:IconicStroke;content:'\e068'}.iconic-calendar-alt-stroke:before{font-family:IconicStroke;content:'\e06c'}.iconic-comment-stroke:before{font-family:IconicStroke;content:'\e06d'}.iconic-lock-stroke:before{font-family:IconicStroke;content:'\e075'}.iconic-unlock-stroke:before{font-family:IconicStroke;content:'\e076'}}.page-alert{position:absolute;top:0;left:50%;z-index:1020;width:0}.page-alert .alert{width:550px;margin-left:-300px;border-top-width:0;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.navbar-fixed-top+.page-alert{top:40px}body>.page-alert{position:fixed}.btn-file{position:relative;overflow:hidden;vertical-align:middle}.btn-file>input{position:absolute;top:0;right:0;margin:0;font-size:23px;cursor:pointer;opacity:0;filter:alpha(opacity=0);transform:translate(-300px,0) scale(4);direction:ltr}.fileupload{margin-bottom:9px}.fileupload .uneditable-input{display:inline-block;margin-bottom:0;vertical-align:middle;cursor:text}.fileupload .thumbnail{display:inline-block;margin-bottom:5px;overflow:hidden;text-align:center;vertical-align:middle}.fileupload .thumbnail>img{display:inline-block;max-height:100%;vertical-align:middle}.fileupload .btn{vertical-align:middle}.fileupload-exists .fileupload-new,.fileupload-new .fileupload-exists{display:none}.fileupload-inline .fileupload-controls{display:inline}.fileupload-new .input-append .btn-file{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.thumbnail-borderless .thumbnail{padding:0;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.fileupload-new.thumbnail-borderless .thumbnail{border:1px solid #ddd}.control-group.warning .fileupload .uneditable-input{color:#a47e3c;border-color:#a47e3c}.control-group.warning .fileupload .fileupload-preview{color:#a47e3c}.control-group.warning .fileupload .thumbnail{border-color:#a47e3c}.control-group.error .fileupload .uneditable-input{color:#b94a48;border-color:#b94a48}.control-group.error .fileupload .fileupload-preview{color:#b94a48}.control-group.error .fileupload .thumbnail{border-color:#b94a48}.control-group.success .fileupload .uneditable-input{color:#468847;border-color:#468847}.control-group.success .fileupload .fileupload-preview{color:#468847}.control-group.success .fileupload .thumbnail{border-color:#468847}.nav-tabs>li>a,.nav-pills>li>a{outline:0}.nav-tabs>li.disabled>a{color:#ccc;cursor:not-allowed}.tabbable{border-color:#ddd;border-style:solid;border-width:0;*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tabbable>.nav-tabs{margin:0}.tab-content{padding:18px 0 0 0;overflow:auto;border-color:#ddd;border-style:solid;border-width:0}.tabbable-bordered{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:0 1px 1px 1px;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}body>.container.tabbable>.nav-tabs{padding-top:15px}.tabs-below>.tab-content{padding:0 0 10px 0}.tabs-below.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 1px 0 1px;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}body>.container.tabs-below.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.tabs-left,.tabs-right{margin-bottom:20px}.tabs-left>.nav-tabs,.tabs-right>.nav-tabs{position:relative;z-index:1;margin-bottom:0}.tabs-left>.tab-content,.tabs-right>.tab-content{overflow:hidden}.tabs-left>.nav-tabs{left:1px}.tabs-left>.nav-tabs>.active>a,.tabs-left>.nav-tabs>.active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-left>.tab-content{padding:0 0 0 19px;border-left-width:1px}.tabs-left.tabbable-bordered{border-width:0 1px 0 0}.tabs-left.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 0 1px 1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}body>.container.tabs-left.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0}.tabs-right>.nav-tabs{right:1px}.tabs-right>.nav-tabs>.active>a,.tabs-right>.nav-tabs>.active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.tabs-right>.tab-content{padding:0 19px 0 0;border-right-width:1px}.tabs-right.tabbable-bordered{border-width:0 0 0 1px}.tabs-right.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 1px 1px 0;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}body>.container.tabs-right.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px}
10 |
--------------------------------------------------------------------------------
/demo/css/bootstrap-responsive.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Responsive v2.2.1
3 | *
4 | * Copyright 2012 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | */
10 |
11 | .clearfix {
12 | *zoom: 1;
13 | }
14 |
15 | .clearfix:before,
16 | .clearfix:after {
17 | display: table;
18 | line-height: 0;
19 | content: "";
20 | }
21 |
22 | .clearfix:after {
23 | clear: both;
24 | }
25 |
26 | .hide-text {
27 | font: 0/0 a;
28 | color: transparent;
29 | text-shadow: none;
30 | background-color: transparent;
31 | border: 0;
32 | }
33 |
34 | .input-block-level {
35 | display: block;
36 | width: 100%;
37 | min-height: 30px;
38 | -webkit-box-sizing: border-box;
39 | -moz-box-sizing: border-box;
40 | box-sizing: border-box;
41 | }
42 |
43 | .hidden {
44 | display: none;
45 | visibility: hidden;
46 | }
47 |
48 | .visible-phone {
49 | display: none !important;
50 | }
51 |
52 | .visible-tablet {
53 | display: none !important;
54 | }
55 |
56 | .hidden-desktop {
57 | display: none !important;
58 | }
59 |
60 | .visible-desktop {
61 | display: inherit !important;
62 | }
63 |
64 | @media (min-width: 768px) and (max-width: 979px) {
65 | .hidden-desktop {
66 | display: inherit !important;
67 | }
68 | .visible-desktop {
69 | display: none !important ;
70 | }
71 | .visible-tablet {
72 | display: inherit !important;
73 | }
74 | .hidden-tablet {
75 | display: none !important;
76 | }
77 | }
78 |
79 | @media (max-width: 767px) {
80 | .hidden-desktop {
81 | display: inherit !important;
82 | }
83 | .visible-desktop {
84 | display: none !important;
85 | }
86 | .visible-phone {
87 | display: inherit !important;
88 | }
89 | .hidden-phone {
90 | display: none !important;
91 | }
92 | }
93 |
94 | @media (min-width: 1200px) {
95 | .row {
96 | margin-left: -30px;
97 | *zoom: 1;
98 | }
99 | .row:before,
100 | .row:after {
101 | display: table;
102 | line-height: 0;
103 | content: "";
104 | }
105 | .row:after {
106 | clear: both;
107 | }
108 | [class*="span"] {
109 | float: left;
110 | min-height: 1px;
111 | margin-left: 30px;
112 | }
113 | .container,
114 | .navbar-static-top .container,
115 | .navbar-fixed-top .container,
116 | .navbar-fixed-bottom .container {
117 | width: 1170px;
118 | }
119 | .span12 {
120 | width: 1170px;
121 | }
122 | .span11 {
123 | width: 1070px;
124 | }
125 | .span10 {
126 | width: 970px;
127 | }
128 | .span9 {
129 | width: 870px;
130 | }
131 | .span8 {
132 | width: 770px;
133 | }
134 | .span7 {
135 | width: 670px;
136 | }
137 | .span6 {
138 | width: 570px;
139 | }
140 | .span5 {
141 | width: 470px;
142 | }
143 | .span4 {
144 | width: 370px;
145 | }
146 | .span3 {
147 | width: 270px;
148 | }
149 | .span2 {
150 | width: 170px;
151 | }
152 | .span1 {
153 | width: 70px;
154 | }
155 | .offset12 {
156 | margin-left: 1230px;
157 | }
158 | .offset11 {
159 | margin-left: 1130px;
160 | }
161 | .offset10 {
162 | margin-left: 1030px;
163 | }
164 | .offset9 {
165 | margin-left: 930px;
166 | }
167 | .offset8 {
168 | margin-left: 830px;
169 | }
170 | .offset7 {
171 | margin-left: 730px;
172 | }
173 | .offset6 {
174 | margin-left: 630px;
175 | }
176 | .offset5 {
177 | margin-left: 530px;
178 | }
179 | .offset4 {
180 | margin-left: 430px;
181 | }
182 | .offset3 {
183 | margin-left: 330px;
184 | }
185 | .offset2 {
186 | margin-left: 230px;
187 | }
188 | .offset1 {
189 | margin-left: 130px;
190 | }
191 | .row-fluid {
192 | width: 100%;
193 | *zoom: 1;
194 | }
195 | .row-fluid:before,
196 | .row-fluid:after {
197 | display: table;
198 | line-height: 0;
199 | content: "";
200 | }
201 | .row-fluid:after {
202 | clear: both;
203 | }
204 | .row-fluid [class*="span"] {
205 | display: block;
206 | float: left;
207 | width: 100%;
208 | min-height: 30px;
209 | margin-left: 2.564102564102564%;
210 | *margin-left: 2.5109110747408616%;
211 | -webkit-box-sizing: border-box;
212 | -moz-box-sizing: border-box;
213 | box-sizing: border-box;
214 | }
215 | .row-fluid [class*="span"]:first-child {
216 | margin-left: 0;
217 | }
218 | .row-fluid .controls-row [class*="span"] + [class*="span"] {
219 | margin-left: 2.564102564102564%;
220 | }
221 | .row-fluid .span12 {
222 | width: 100%;
223 | *width: 99.94680851063829%;
224 | }
225 | .row-fluid .span11 {
226 | width: 91.45299145299145%;
227 | *width: 91.39979996362975%;
228 | }
229 | .row-fluid .span10 {
230 | width: 82.90598290598291%;
231 | *width: 82.8527914166212%;
232 | }
233 | .row-fluid .span9 {
234 | width: 74.35897435897436%;
235 | *width: 74.30578286961266%;
236 | }
237 | .row-fluid .span8 {
238 | width: 65.81196581196582%;
239 | *width: 65.75877432260411%;
240 | }
241 | .row-fluid .span7 {
242 | width: 57.26495726495726%;
243 | *width: 57.21176577559556%;
244 | }
245 | .row-fluid .span6 {
246 | width: 48.717948717948715%;
247 | *width: 48.664757228587014%;
248 | }
249 | .row-fluid .span5 {
250 | width: 40.17094017094017%;
251 | *width: 40.11774868157847%;
252 | }
253 | .row-fluid .span4 {
254 | width: 31.623931623931625%;
255 | *width: 31.570740134569924%;
256 | }
257 | .row-fluid .span3 {
258 | width: 23.076923076923077%;
259 | *width: 23.023731587561375%;
260 | }
261 | .row-fluid .span2 {
262 | width: 14.52991452991453%;
263 | *width: 14.476723040552828%;
264 | }
265 | .row-fluid .span1 {
266 | width: 5.982905982905983%;
267 | *width: 5.929714493544281%;
268 | }
269 | .row-fluid .offset12 {
270 | margin-left: 105.12820512820512%;
271 | *margin-left: 105.02182214948171%;
272 | }
273 | .row-fluid .offset12:first-child {
274 | margin-left: 102.56410256410257%;
275 | *margin-left: 102.45771958537915%;
276 | }
277 | .row-fluid .offset11 {
278 | margin-left: 96.58119658119658%;
279 | *margin-left: 96.47481360247316%;
280 | }
281 | .row-fluid .offset11:first-child {
282 | margin-left: 94.01709401709402%;
283 | *margin-left: 93.91071103837061%;
284 | }
285 | .row-fluid .offset10 {
286 | margin-left: 88.03418803418803%;
287 | *margin-left: 87.92780505546462%;
288 | }
289 | .row-fluid .offset10:first-child {
290 | margin-left: 85.47008547008548%;
291 | *margin-left: 85.36370249136206%;
292 | }
293 | .row-fluid .offset9 {
294 | margin-left: 79.48717948717949%;
295 | *margin-left: 79.38079650845607%;
296 | }
297 | .row-fluid .offset9:first-child {
298 | margin-left: 76.92307692307693%;
299 | *margin-left: 76.81669394435352%;
300 | }
301 | .row-fluid .offset8 {
302 | margin-left: 70.94017094017094%;
303 | *margin-left: 70.83378796144753%;
304 | }
305 | .row-fluid .offset8:first-child {
306 | margin-left: 68.37606837606839%;
307 | *margin-left: 68.26968539734497%;
308 | }
309 | .row-fluid .offset7 {
310 | margin-left: 62.393162393162385%;
311 | *margin-left: 62.28677941443899%;
312 | }
313 | .row-fluid .offset7:first-child {
314 | margin-left: 59.82905982905982%;
315 | *margin-left: 59.72267685033642%;
316 | }
317 | .row-fluid .offset6 {
318 | margin-left: 53.84615384615384%;
319 | *margin-left: 53.739770867430444%;
320 | }
321 | .row-fluid .offset6:first-child {
322 | margin-left: 51.28205128205128%;
323 | *margin-left: 51.175668303327875%;
324 | }
325 | .row-fluid .offset5 {
326 | margin-left: 45.299145299145295%;
327 | *margin-left: 45.1927623204219%;
328 | }
329 | .row-fluid .offset5:first-child {
330 | margin-left: 42.73504273504273%;
331 | *margin-left: 42.62865975631933%;
332 | }
333 | .row-fluid .offset4 {
334 | margin-left: 36.75213675213675%;
335 | *margin-left: 36.645753773413354%;
336 | }
337 | .row-fluid .offset4:first-child {
338 | margin-left: 34.18803418803419%;
339 | *margin-left: 34.081651209310785%;
340 | }
341 | .row-fluid .offset3 {
342 | margin-left: 28.205128205128204%;
343 | *margin-left: 28.0987452264048%;
344 | }
345 | .row-fluid .offset3:first-child {
346 | margin-left: 25.641025641025642%;
347 | *margin-left: 25.53464266230224%;
348 | }
349 | .row-fluid .offset2 {
350 | margin-left: 19.65811965811966%;
351 | *margin-left: 19.551736679396257%;
352 | }
353 | .row-fluid .offset2:first-child {
354 | margin-left: 17.094017094017094%;
355 | *margin-left: 16.98763411529369%;
356 | }
357 | .row-fluid .offset1 {
358 | margin-left: 11.11111111111111%;
359 | *margin-left: 11.004728132387708%;
360 | }
361 | .row-fluid .offset1:first-child {
362 | margin-left: 8.547008547008547%;
363 | *margin-left: 8.440625568285142%;
364 | }
365 | input,
366 | textarea,
367 | .uneditable-input {
368 | margin-left: 0;
369 | }
370 | .controls-row [class*="span"] + [class*="span"] {
371 | margin-left: 30px;
372 | }
373 | input.span12,
374 | textarea.span12,
375 | .uneditable-input.span12 {
376 | width: 1156px;
377 | }
378 | input.span11,
379 | textarea.span11,
380 | .uneditable-input.span11 {
381 | width: 1056px;
382 | }
383 | input.span10,
384 | textarea.span10,
385 | .uneditable-input.span10 {
386 | width: 956px;
387 | }
388 | input.span9,
389 | textarea.span9,
390 | .uneditable-input.span9 {
391 | width: 856px;
392 | }
393 | input.span8,
394 | textarea.span8,
395 | .uneditable-input.span8 {
396 | width: 756px;
397 | }
398 | input.span7,
399 | textarea.span7,
400 | .uneditable-input.span7 {
401 | width: 656px;
402 | }
403 | input.span6,
404 | textarea.span6,
405 | .uneditable-input.span6 {
406 | width: 556px;
407 | }
408 | input.span5,
409 | textarea.span5,
410 | .uneditable-input.span5 {
411 | width: 456px;
412 | }
413 | input.span4,
414 | textarea.span4,
415 | .uneditable-input.span4 {
416 | width: 356px;
417 | }
418 | input.span3,
419 | textarea.span3,
420 | .uneditable-input.span3 {
421 | width: 256px;
422 | }
423 | input.span2,
424 | textarea.span2,
425 | .uneditable-input.span2 {
426 | width: 156px;
427 | }
428 | input.span1,
429 | textarea.span1,
430 | .uneditable-input.span1 {
431 | width: 56px;
432 | }
433 | .thumbnails {
434 | margin-left: -30px;
435 | }
436 | .thumbnails > li {
437 | margin-left: 30px;
438 | }
439 | .row-fluid .thumbnails {
440 | margin-left: 0;
441 | }
442 | }
443 |
444 | @media (min-width: 768px) and (max-width: 979px) {
445 | .row {
446 | margin-left: -20px;
447 | *zoom: 1;
448 | }
449 | .row:before,
450 | .row:after {
451 | display: table;
452 | line-height: 0;
453 | content: "";
454 | }
455 | .row:after {
456 | clear: both;
457 | }
458 | [class*="span"] {
459 | float: left;
460 | min-height: 1px;
461 | margin-left: 20px;
462 | }
463 | .container,
464 | .navbar-static-top .container,
465 | .navbar-fixed-top .container,
466 | .navbar-fixed-bottom .container {
467 | width: 724px;
468 | }
469 | .span12 {
470 | width: 724px;
471 | }
472 | .span11 {
473 | width: 662px;
474 | }
475 | .span10 {
476 | width: 600px;
477 | }
478 | .span9 {
479 | width: 538px;
480 | }
481 | .span8 {
482 | width: 476px;
483 | }
484 | .span7 {
485 | width: 414px;
486 | }
487 | .span6 {
488 | width: 352px;
489 | }
490 | .span5 {
491 | width: 290px;
492 | }
493 | .span4 {
494 | width: 228px;
495 | }
496 | .span3 {
497 | width: 166px;
498 | }
499 | .span2 {
500 | width: 104px;
501 | }
502 | .span1 {
503 | width: 42px;
504 | }
505 | .offset12 {
506 | margin-left: 764px;
507 | }
508 | .offset11 {
509 | margin-left: 702px;
510 | }
511 | .offset10 {
512 | margin-left: 640px;
513 | }
514 | .offset9 {
515 | margin-left: 578px;
516 | }
517 | .offset8 {
518 | margin-left: 516px;
519 | }
520 | .offset7 {
521 | margin-left: 454px;
522 | }
523 | .offset6 {
524 | margin-left: 392px;
525 | }
526 | .offset5 {
527 | margin-left: 330px;
528 | }
529 | .offset4 {
530 | margin-left: 268px;
531 | }
532 | .offset3 {
533 | margin-left: 206px;
534 | }
535 | .offset2 {
536 | margin-left: 144px;
537 | }
538 | .offset1 {
539 | margin-left: 82px;
540 | }
541 | .row-fluid {
542 | width: 100%;
543 | *zoom: 1;
544 | }
545 | .row-fluid:before,
546 | .row-fluid:after {
547 | display: table;
548 | line-height: 0;
549 | content: "";
550 | }
551 | .row-fluid:after {
552 | clear: both;
553 | }
554 | .row-fluid [class*="span"] {
555 | display: block;
556 | float: left;
557 | width: 100%;
558 | min-height: 30px;
559 | margin-left: 2.7624309392265194%;
560 | *margin-left: 2.709239449864817%;
561 | -webkit-box-sizing: border-box;
562 | -moz-box-sizing: border-box;
563 | box-sizing: border-box;
564 | }
565 | .row-fluid [class*="span"]:first-child {
566 | margin-left: 0;
567 | }
568 | .row-fluid .controls-row [class*="span"] + [class*="span"] {
569 | margin-left: 2.7624309392265194%;
570 | }
571 | .row-fluid .span12 {
572 | width: 100%;
573 | *width: 99.94680851063829%;
574 | }
575 | .row-fluid .span11 {
576 | width: 91.43646408839778%;
577 | *width: 91.38327259903608%;
578 | }
579 | .row-fluid .span10 {
580 | width: 82.87292817679558%;
581 | *width: 82.81973668743387%;
582 | }
583 | .row-fluid .span9 {
584 | width: 74.30939226519337%;
585 | *width: 74.25620077583166%;
586 | }
587 | .row-fluid .span8 {
588 | width: 65.74585635359117%;
589 | *width: 65.69266486422946%;
590 | }
591 | .row-fluid .span7 {
592 | width: 57.18232044198895%;
593 | *width: 57.12912895262725%;
594 | }
595 | .row-fluid .span6 {
596 | width: 48.61878453038674%;
597 | *width: 48.56559304102504%;
598 | }
599 | .row-fluid .span5 {
600 | width: 40.05524861878453%;
601 | *width: 40.00205712942283%;
602 | }
603 | .row-fluid .span4 {
604 | width: 31.491712707182323%;
605 | *width: 31.43852121782062%;
606 | }
607 | .row-fluid .span3 {
608 | width: 22.92817679558011%;
609 | *width: 22.87498530621841%;
610 | }
611 | .row-fluid .span2 {
612 | width: 14.3646408839779%;
613 | *width: 14.311449394616199%;
614 | }
615 | .row-fluid .span1 {
616 | width: 5.801104972375691%;
617 | *width: 5.747913483013988%;
618 | }
619 | .row-fluid .offset12 {
620 | margin-left: 105.52486187845304%;
621 | *margin-left: 105.41847889972962%;
622 | }
623 | .row-fluid .offset12:first-child {
624 | margin-left: 102.76243093922652%;
625 | *margin-left: 102.6560479605031%;
626 | }
627 | .row-fluid .offset11 {
628 | margin-left: 96.96132596685082%;
629 | *margin-left: 96.8549429881274%;
630 | }
631 | .row-fluid .offset11:first-child {
632 | margin-left: 94.1988950276243%;
633 | *margin-left: 94.09251204890089%;
634 | }
635 | .row-fluid .offset10 {
636 | margin-left: 88.39779005524862%;
637 | *margin-left: 88.2914070765252%;
638 | }
639 | .row-fluid .offset10:first-child {
640 | margin-left: 85.6353591160221%;
641 | *margin-left: 85.52897613729868%;
642 | }
643 | .row-fluid .offset9 {
644 | margin-left: 79.8342541436464%;
645 | *margin-left: 79.72787116492299%;
646 | }
647 | .row-fluid .offset9:first-child {
648 | margin-left: 77.07182320441989%;
649 | *margin-left: 76.96544022569647%;
650 | }
651 | .row-fluid .offset8 {
652 | margin-left: 71.2707182320442%;
653 | *margin-left: 71.16433525332079%;
654 | }
655 | .row-fluid .offset8:first-child {
656 | margin-left: 68.50828729281768%;
657 | *margin-left: 68.40190431409427%;
658 | }
659 | .row-fluid .offset7 {
660 | margin-left: 62.70718232044199%;
661 | *margin-left: 62.600799341718584%;
662 | }
663 | .row-fluid .offset7:first-child {
664 | margin-left: 59.94475138121547%;
665 | *margin-left: 59.838368402492065%;
666 | }
667 | .row-fluid .offset6 {
668 | margin-left: 54.14364640883978%;
669 | *margin-left: 54.037263430116376%;
670 | }
671 | .row-fluid .offset6:first-child {
672 | margin-left: 51.38121546961326%;
673 | *margin-left: 51.27483249088986%;
674 | }
675 | .row-fluid .offset5 {
676 | margin-left: 45.58011049723757%;
677 | *margin-left: 45.47372751851417%;
678 | }
679 | .row-fluid .offset5:first-child {
680 | margin-left: 42.81767955801105%;
681 | *margin-left: 42.71129657928765%;
682 | }
683 | .row-fluid .offset4 {
684 | margin-left: 37.01657458563536%;
685 | *margin-left: 36.91019160691196%;
686 | }
687 | .row-fluid .offset4:first-child {
688 | margin-left: 34.25414364640884%;
689 | *margin-left: 34.14776066768544%;
690 | }
691 | .row-fluid .offset3 {
692 | margin-left: 28.45303867403315%;
693 | *margin-left: 28.346655695309746%;
694 | }
695 | .row-fluid .offset3:first-child {
696 | margin-left: 25.69060773480663%;
697 | *margin-left: 25.584224756083227%;
698 | }
699 | .row-fluid .offset2 {
700 | margin-left: 19.88950276243094%;
701 | *margin-left: 19.783119783707537%;
702 | }
703 | .row-fluid .offset2:first-child {
704 | margin-left: 17.12707182320442%;
705 | *margin-left: 17.02068884448102%;
706 | }
707 | .row-fluid .offset1 {
708 | margin-left: 11.32596685082873%;
709 | *margin-left: 11.219583872105325%;
710 | }
711 | .row-fluid .offset1:first-child {
712 | margin-left: 8.56353591160221%;
713 | *margin-left: 8.457152932878806%;
714 | }
715 | input,
716 | textarea,
717 | .uneditable-input {
718 | margin-left: 0;
719 | }
720 | .controls-row [class*="span"] + [class*="span"] {
721 | margin-left: 20px;
722 | }
723 | input.span12,
724 | textarea.span12,
725 | .uneditable-input.span12 {
726 | width: 710px;
727 | }
728 | input.span11,
729 | textarea.span11,
730 | .uneditable-input.span11 {
731 | width: 648px;
732 | }
733 | input.span10,
734 | textarea.span10,
735 | .uneditable-input.span10 {
736 | width: 586px;
737 | }
738 | input.span9,
739 | textarea.span9,
740 | .uneditable-input.span9 {
741 | width: 524px;
742 | }
743 | input.span8,
744 | textarea.span8,
745 | .uneditable-input.span8 {
746 | width: 462px;
747 | }
748 | input.span7,
749 | textarea.span7,
750 | .uneditable-input.span7 {
751 | width: 400px;
752 | }
753 | input.span6,
754 | textarea.span6,
755 | .uneditable-input.span6 {
756 | width: 338px;
757 | }
758 | input.span5,
759 | textarea.span5,
760 | .uneditable-input.span5 {
761 | width: 276px;
762 | }
763 | input.span4,
764 | textarea.span4,
765 | .uneditable-input.span4 {
766 | width: 214px;
767 | }
768 | input.span3,
769 | textarea.span3,
770 | .uneditable-input.span3 {
771 | width: 152px;
772 | }
773 | input.span2,
774 | textarea.span2,
775 | .uneditable-input.span2 {
776 | width: 90px;
777 | }
778 | input.span1,
779 | textarea.span1,
780 | .uneditable-input.span1 {
781 | width: 28px;
782 | }
783 | }
784 |
785 | @media (max-width: 767px) {
786 | body {
787 | padding-right: 20px;
788 | padding-left: 20px;
789 | }
790 | .navbar-fixed-top,
791 | .navbar-fixed-bottom,
792 | .navbar-static-top {
793 | margin-right: -20px;
794 | margin-left: -20px;
795 | }
796 | .container-fluid {
797 | padding: 0;
798 | }
799 | .dl-horizontal dt {
800 | float: none;
801 | width: auto;
802 | clear: none;
803 | text-align: left;
804 | }
805 | .dl-horizontal dd {
806 | margin-left: 0;
807 | }
808 | .container {
809 | width: auto;
810 | }
811 | .row-fluid {
812 | width: 100%;
813 | }
814 | .row,
815 | .thumbnails {
816 | margin-left: 0;
817 | }
818 | .thumbnails > li {
819 | float: none;
820 | margin-left: 0;
821 | }
822 | [class*="span"],
823 | .uneditable-input[class*="span"],
824 | .row-fluid [class*="span"] {
825 | display: block;
826 | float: none;
827 | width: 100%;
828 | margin-left: 0;
829 | -webkit-box-sizing: border-box;
830 | -moz-box-sizing: border-box;
831 | box-sizing: border-box;
832 | }
833 | .span12,
834 | .row-fluid .span12 {
835 | width: 100%;
836 | -webkit-box-sizing: border-box;
837 | -moz-box-sizing: border-box;
838 | box-sizing: border-box;
839 | }
840 | .row-fluid [class*="offset"]:first-child {
841 | margin-left: 0;
842 | }
843 | .input-large,
844 | .input-xlarge,
845 | .input-xxlarge,
846 | input[class*="span"],
847 | select[class*="span"],
848 | textarea[class*="span"],
849 | .uneditable-input {
850 | display: block;
851 | width: 100%;
852 | min-height: 30px;
853 | -webkit-box-sizing: border-box;
854 | -moz-box-sizing: border-box;
855 | box-sizing: border-box;
856 | }
857 | .input-prepend input,
858 | .input-append input,
859 | .input-prepend input[class*="span"],
860 | .input-append input[class*="span"] {
861 | display: inline-block;
862 | width: auto;
863 | }
864 | .controls-row [class*="span"] + [class*="span"] {
865 | margin-left: 0;
866 | }
867 | .modal {
868 | position: fixed;
869 | top: 20px;
870 | right: 20px;
871 | left: 20px;
872 | width: auto;
873 | margin: 0;
874 | }
875 | .modal.fade {
876 | top: -100px;
877 | }
878 | .modal.fade.in {
879 | top: 20px;
880 | }
881 | }
882 |
883 | @media (max-width: 480px) {
884 | .nav-collapse {
885 | -webkit-transform: translate3d(0, 0, 0);
886 | }
887 | .page-header h1 small {
888 | display: block;
889 | line-height: 20px;
890 | }
891 | input[type="checkbox"],
892 | input[type="radio"] {
893 | border: 1px solid #ccc;
894 | }
895 | .form-horizontal .control-label {
896 | float: none;
897 | width: auto;
898 | padding-top: 0;
899 | text-align: left;
900 | }
901 | .form-horizontal .controls {
902 | margin-left: 0;
903 | }
904 | .form-horizontal .control-list {
905 | padding-top: 0;
906 | }
907 | .form-horizontal .form-actions {
908 | padding-right: 10px;
909 | padding-left: 10px;
910 | }
911 | .media .pull-left,
912 | .media .pull-right {
913 | display: block;
914 | float: none;
915 | margin-bottom: 10px;
916 | }
917 | .media-object {
918 | margin-right: 0;
919 | margin-left: 0;
920 | }
921 | .modal {
922 | top: 10px;
923 | right: 10px;
924 | left: 10px;
925 | }
926 | .modal-header .close {
927 | padding: 10px;
928 | margin: -10px;
929 | }
930 | .carousel-caption {
931 | position: static;
932 | }
933 | }
934 |
935 | @media (max-width: 979px) {
936 | body {
937 | padding-top: 0;
938 | }
939 | .navbar-fixed-top,
940 | .navbar-fixed-bottom {
941 | position: static;
942 | }
943 | .navbar-fixed-top {
944 | margin-bottom: 20px;
945 | }
946 | .navbar-fixed-bottom {
947 | margin-top: 20px;
948 | }
949 | .navbar-fixed-top .navbar-inner,
950 | .navbar-fixed-bottom .navbar-inner {
951 | padding: 5px;
952 | }
953 | .navbar .container {
954 | width: auto;
955 | padding: 0;
956 | }
957 | .navbar .brand {
958 | padding-right: 10px;
959 | padding-left: 10px;
960 | margin: 0 0 0 -5px;
961 | }
962 | .nav-collapse {
963 | clear: both;
964 | }
965 | .nav-collapse .nav {
966 | float: none;
967 | margin: 0 0 10px;
968 | }
969 | .nav-collapse .nav > li {
970 | float: none;
971 | }
972 | .nav-collapse .nav > li > a {
973 | margin-bottom: 2px;
974 | }
975 | .nav-collapse .nav > .divider-vertical {
976 | display: none;
977 | }
978 | .nav-collapse .nav .nav-header {
979 | color: #777777;
980 | text-shadow: none;
981 | }
982 | .nav-collapse .nav > li > a,
983 | .nav-collapse .dropdown-menu a {
984 | padding: 9px 15px;
985 | font-weight: bold;
986 | color: #777777;
987 | -webkit-border-radius: 3px;
988 | -moz-border-radius: 3px;
989 | border-radius: 3px;
990 | }
991 | .nav-collapse .btn {
992 | padding: 4px 10px 4px;
993 | font-weight: normal;
994 | -webkit-border-radius: 4px;
995 | -moz-border-radius: 4px;
996 | border-radius: 4px;
997 | }
998 | .nav-collapse .dropdown-menu li + li a {
999 | margin-bottom: 2px;
1000 | }
1001 | .nav-collapse .nav > li > a:hover,
1002 | .nav-collapse .dropdown-menu a:hover {
1003 | background-color: #f2f2f2;
1004 | }
1005 | .navbar-inverse .nav-collapse .nav > li > a,
1006 | .navbar-inverse .nav-collapse .dropdown-menu a {
1007 | color: #999999;
1008 | }
1009 | .navbar-inverse .nav-collapse .nav > li > a:hover,
1010 | .navbar-inverse .nav-collapse .dropdown-menu a:hover {
1011 | background-color: #111111;
1012 | }
1013 | .nav-collapse.in .btn-group {
1014 | padding: 0;
1015 | margin-top: 5px;
1016 | }
1017 | .nav-collapse .dropdown-menu {
1018 | position: static;
1019 | top: auto;
1020 | left: auto;
1021 | display: none;
1022 | float: none;
1023 | max-width: none;
1024 | padding: 0;
1025 | margin: 0 15px;
1026 | background-color: transparent;
1027 | border: none;
1028 | -webkit-border-radius: 0;
1029 | -moz-border-radius: 0;
1030 | border-radius: 0;
1031 | -webkit-box-shadow: none;
1032 | -moz-box-shadow: none;
1033 | box-shadow: none;
1034 | }
1035 | .nav-collapse .open > .dropdown-menu {
1036 | display: block;
1037 | }
1038 | .nav-collapse .dropdown-menu:before,
1039 | .nav-collapse .dropdown-menu:after {
1040 | display: none;
1041 | }
1042 | .nav-collapse .dropdown-menu .divider {
1043 | display: none;
1044 | }
1045 | .nav-collapse .nav > li > .dropdown-menu:before,
1046 | .nav-collapse .nav > li > .dropdown-menu:after {
1047 | display: none;
1048 | }
1049 | .nav-collapse .navbar-form,
1050 | .nav-collapse .navbar-search {
1051 | float: none;
1052 | padding: 10px 15px;
1053 | margin: 10px 0;
1054 | border-top: 1px solid #f2f2f2;
1055 | border-bottom: 1px solid #f2f2f2;
1056 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1057 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1058 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1059 | }
1060 | .navbar-inverse .nav-collapse .navbar-form,
1061 | .navbar-inverse .nav-collapse .navbar-search {
1062 | border-top-color: #111111;
1063 | border-bottom-color: #111111;
1064 | }
1065 | .navbar .nav-collapse .nav.pull-right {
1066 | float: none;
1067 | margin-left: 0;
1068 | }
1069 | .nav-collapse,
1070 | .nav-collapse.collapse {
1071 | height: 0;
1072 | overflow: hidden;
1073 | }
1074 | .navbar .btn-navbar {
1075 | display: block;
1076 | }
1077 | .navbar-static .navbar-inner {
1078 | padding-right: 10px;
1079 | padding-left: 10px;
1080 | }
1081 | }
1082 |
1083 | @media (min-width: 980px) {
1084 | .nav-collapse.collapse {
1085 | height: auto !important;
1086 | overflow: visible !important;
1087 | }
1088 | }
1089 |
--------------------------------------------------------------------------------
/dist/angles.min.js:
--------------------------------------------------------------------------------
1 | /*! angles 2013-11-25 */
2 | !function(){var a={}.hasOwnProperty,b=function(b,c){function d(){this.constructor=b}for(var e in c)a.call(c,e)&&(b[e]=c[e]);return d.prototype=c.prototype,b.prototype=new d,b.__super__=c.prototype,b};window.Angles={},function(a,c,d,e){var f,g,h,i,j,k,l,m,n,o;return f=null,a.XMLDocument=function(a){function c(){return g=c.__super__.constructor.apply(this,arguments)}return b(c,a),c.prototype.defaults={name:"untitled",content:""},c.prototype.validate=function(){},c}(d.Model),a.XMLDocumentList=function(c){function d(){return h=d.__super__.constructor.apply(this,arguments)}return b(d,c),d.prototype.model=a.XMLDocument,d}(d.Collection),a.Notification=function(a){function c(){return i=c.__super__.constructor.apply(this,arguments)}return b(c,a),c.prototype.defaults={type:"",info:"",message:"",resource:"",location:{column:-1,row:-1}},c}(d.Model),a.NotificationList=function(c){function d(){return j=d.__super__.constructor.apply(this,arguments)}return b(d,c),d.prototype.model=a.Notification,d}(d.Collection),a.FileSelector=function(d){function e(){return k=e.__super__.constructor.apply(this,arguments)}return b(e,d),e.prototype.initialize=function(){return this.template=c.template($("#file-list-template").html())},e.prototype.render=function(){return this.$el.html(this.template({})),this.collection.each(this.addOne,this),this},e.prototype.addOne=function(b){var c;return c=new a.FileSelectorRow({model:b}),this.$("form").append(c.render().$el)},e}(d.View),a.FileSelectorRow=function(a){function d(){return l=d.__super__.constructor.apply(this,arguments)}return b(d,a),d.prototype.initialize=function(){return this.template=c.template($("#file-item-template").html()),this.listenTo(this.model,"change",this.render),this.listenTo(this.model,"destroy",this.remove)},d.prototype.render=function(){return this.$el.html(this.template(this.model.toJSON())),this},d}(d.View),a.NotificationTable=function(d){function e(){return m=e.__super__.constructor.apply(this,arguments)}return b(e,d),e.prototype.initialize=function(){return this.template=c.template($("#notification-list-template").html())},e.prototype.render=function(){return this.$el.html(this.template({})),this.listenTo(this.collection,"add",this.addOne),this},e.prototype.addOne=function(b){var c;return c=new a.NotificationRow({model:b}),this.$(".notifications").append(c.render().$el)},e}(d.View),a.NotificationRow=function(a){function d(){return n=d.__super__.constructor.apply(this,arguments)}return b(d,a),d.prototype.initialize=function(){return this.template=c.template($("#notification-template").html()),this.listenTo(this.model,"change",this.render),this.listenTo(this.model,"destroy",this.remove)},d.prototype.render=function(){return this.$el.html(this.template(this.model.toJSON())),this},d}(d.View),a.ACEEditorView=function(a){function f(){return o=f.__super__.constructor.apply(this,arguments)}return b(f,a),f.prototype.tagName="div",f.prototype.className="ace-editor",f.prototype.initialize=function(){var a,b,e=this;return a=[],b=this.options.dispatcher||c.clone(d.Events),this.dispatcher=b,b.on("editor:reload",function(){return e.clearAnnotations(),e.setContent()}),b.on("document:save",function(){return e.saveModel()}),b.on("validation:start",function(){return a=[],e.dispatcher.trigger("notification:clear")}),b.on("validation:error",function(b){var c;return a.push(b),c={type:"validation",info:b.type,message:b.text,location:{row:b.row,column:b.column}},e.dispatcher.trigger("notification:push",c)}),b.on("validation:end",function(){var b;return b=e.$editor.getSelection(),e.clearAnnotations(),e.$editor.focus(),a.length>0&&(e.$editor.gotoLine(a[0].row+1,a[0].column,!0),b.selectWordLeft(),b.selectWordLeft()),e.$editor.session.setAnnotations(a)}),b.on("document:switch",function(a){return e.setModel(a)})},f.prototype.render=function(){var a=this;return this.$editor=e.edit(this.el),this.$editor.getSession().on("change",function(b){return a.dispatcher.trigger("editor:change",b)}),this.$editor.getSession().setMode("ace/mode/xml"),e.config.loadModule("ext/angles",function(){var b;return a.$editor.setOptions({enableODDAutocompletion:!0}),b={getCompletions:function(b,c,d,e,f){var g,h,i,j,k,l,m,n;if(null==a.$context)return 0;if(j=a.$context,l=function(a,c){var d,e,f,g,h,i,j,k;return j=[],e=[],d=[],h=!1,g=!1,f="",i=b.getSession().getLength(),k=function(a,c){var f,l,m,n,o,p,q,r,s;if(!(a>i)){for(f=0,q=b.getSession().getTokens(a),m=null,r=0,s=q.length;s>r;r++)if(p=q[r],f+=p.value.length,l=function(){switch(!1){case 0!==j.length:return!0;case j.length!==e.length:return j.pop(),e.pop(),!1;case j[j.length-1]!==e[e.length-1]:return j.pop(),e.pop(),!1;default:return!1}},"meta.tag.tag-name"===p.type&&(n=p.value),f>c)switch(!1){case!("meta.tag"===p.type&&"<"===p.value):h=!0;break;case!("meta.tag.r"===p.type&&">"===p.value&&0===j.length):return n;case!("meta.tag"===p.type&&""===p.value):g=!0;break;case!("meta.tag.r"===p.type&&"/>"===p.value):if(h=!1,g=!1,o=j[j.length-1],null==o&&(o=n),e.push(o),l())return o;break;case!("meta.tag.tag-name"===p.type&&h):if(d.push("<"+p.value+">"),j.push(p.value),h=!1,l())return p.value;break;case!("meta.tag.tag-name"===p.type&&g):if(d.push(""+p.value+">"),e.push(p.value),g=!1,l())return p.value}return k(a+1,0)}},k(a,c)},d=b.getCursorPosition(),k=l(d.row,d.column),i=[],h=j.getChildrenOf(k),null!=h)for(m=0,n=h.length;n>m;m++)g=h[m],i.push({caption:g.ident,snippet:""+g.ident+">"+g.ident+">",meta:"element"});else i.push({caption:"unknown parent",snippet:"",meta:"element"});return i.length>0?f(null,i):void 0}},a.$editor.completers=[b],e.config.on("desc",function(b){return a.dispatcher.trigger("editor:context",b.ident)}),e.config.on("desc:clear",function(){return a.dispatcher.trigger("notification:clear")})}),this},f.prototype.setContent=function(){return this.$editor.setValue(this.model.get("content"))},f.prototype.getContent=function(){return this.$editor.getValue()},f.prototype.getDocument=function(){var a=this;return{getValue:function(){return a.$editor.getValue()},getLength:function(){return a.$editor.session.getDocument().getLength()},getLine:function(b){return a.$editor.session.getDocument().getLine(b)}}},f.prototype.saveModel=function(){var a=this;return this.model.set("content",this.getContent()),this.model.save({success:function(){return a.dispatcher.trigger("editor:reload")},error:function(){return a.dispatcher.trigger("editor:error","Unable to change document")}})},f.prototype.setModel=function(a){return this.model=a,this.dispatcher.trigger("editor:reload")},f.prototype.clearAnnotations=function(){return this.$editor.session.clearAnnotations()},f.prototype.setMode=function(a){return this.$editor.getSession().setMode(a)},f}(d.View)}(window.Angles,_,Backbone,ace)}.call(this),function(){"undefined"!=typeof define&&null!==define&&(define("ext/angles",["require","exports","module","ace/snippets","ace/autocomplete","ace/config","ace/autocomplete/text_completer","ace/editor"],function(a,b){var c,d,e,f,g,h,i,j,k,l;return k=a("ace/snippets").snippetManager,c=a("ace/autocomplete").Autocomplete,f=a("ace/config"),l=a("ace/autocomplete/text_completer"),h={getCompletions:function(a,b,c,d,e){var f;return f=b.$mode.$keywordList||[],f=f.filter(function(a){return 0===a.lastIndexOf(d,0)}),e(null,f.map(function(a){return{name:a,value:a,score:0,meta:"keyword"}}))}},j={getCompletions:function(a,b,c,d,e){var f,g,h;return g=k.$getScope(a),h=k.snippetMap,f=[],[g,"_"].forEach(function(a){var b,c,e,g,i,j;for(e=h[a]||[],j=[],b=g=i=e.length-1;0>=i?0>=g:g>=0;b=0>=i?++g:--g)c=e[b],c.tabTrigger&&0===c.tabTrigger.indexOf(d)?j.push(f.push({caption:c.tabTrigger,snippet:c.content,meta:"snippet"})):j.push(void 0);return j}),e(null,f)}},e=[j,l,h],b.addCompleter=function(a){return e.push(a)},g={name:"expandSnippet",exec:function(a){var b;return b=k.expandWithTab(a),b?void 0:a.execCommand("indent")},bindKey:"tab"},i=function(a,b){var c,d,e;return d=b.session.$mode,c=d.$id,k.files||(k.files={}),c&&!k.files[c]?(e=c.replace("mode","snippets"),f.loadModule(e,function(a){return a?(k.files[c]=a,a.snippets=k.parseSnippetFile(a.snippetText),k.register(a.snippets,a.scope)):void 0})):void 0},d=a("ace/editor").Editor,a("ace/config").defineOptions(d.prototype,"editor",{enableBasicAutocompletion:{set:function(a){return a?(this.completers=e,this.commands.addCommand(c.startCommand)):this.commands.removeCommand(c.startCommand)},value:!1},enableODDAutocompletion:{set:function(a){return a?(this.completers=e,this.commands.addCommand(c.startCommand)):this.commands.removeCommand(c.startCommand)},value:!1},enableSnippets:{set:function(a){return a?(this.commands.addCommand(g),this.on("changeMode",i),i(null,this)):(this.commands.removeCommand(g),this.off("changeMode",i))},value:!1}})}),define("ace/snippets",["require","exports","module","ace/lib/lang","ace/range","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom"],function(a,b){var c,d,f,g,h,i,j,k,l;return j=a("./lib/lang"),d=a("ace/range").Range,c=a("./keyboard/hash_handler").HashHandler,h=a("./tokenizer").Tokenizer,i=d.comparePoints,f=function(){function a(){this.snippetMap={},this.snippetNameMap={},this.variables={}}return a.prototype.getTokenizer=function(){var b,c;return b=function(a,b,c){return a=a.substr(1),/^\d+$/.test(a)&&!c.inFormatString?[{tabstopId:parseInt(a,10)}]:[{text:a}]},c=function(a){return"(?:[^\\\\"+a+"]|\\\\.)"},a.$tokenizer=new h({start:[{regex:/:/,onMatch:function(a,b,c){return c.length&&c[0].expectIf?(c[0].expectIf=!1,c[0].elseBranch=c[0],[c[0]]):":"}},{regex:/\\./,onMatch:function(a,b,c){var d;switch(d=a[1],!1){case!("}"===d&&c.length):a=d;break;case-1==="`$\\".indexOf(d):a=d;break;case!c.inFormatString:switch(!1){case"n"!==d:a="\n";break;case"t"!==d:a="\n";break;case-1==="ulULE".indexOf(d):a={changeCase:d,local:d>"a"}}}return[a]}},{regex:/\}/,onMatch:function(a,b,c){return[c.length?c.shift():a]}},{regex:/\$(?:\d+|\w+)/,onMatch:b},{regex:/\$\{[\dA-Z_a-z]+/,onMatch:function(a,c,d){var e;return e=b(a.substr(1),c,d),d.unshift(e[0]),e},next:"snippetVar"},{regex:/\n/,token:"newline",merge:!1}],snippetVar:[{regex:"\\|"+c("\\|")+"*\\|",onMatch:function(a,b,c){return c[0].choices=a.slice(1,-1).split(",")},next:"start"},{regex:"/("+c("/")+"+)/(?:("+c("/")+"*)/)(\\w*):?",onMatch:function(a,b,c){var d;return d=c[0],d.fmtString=a,a=this.splitRegex.exec(a),d.guard=a[1],d.fmt=a[2],d.flag=a[3],""},next:"start"},{regex:"`"+c("`")+"*`",onMatch:function(a,b,c){return c[0].code=a.splice(1,-1),""},next:"start"},{regex:"\\?",onMatch:function(a,b,c){return c[0]?c[0].expectIf=!0:void 0},next:"start"},{regex:"([^:}\\\\]|\\\\.)*:?",token:"",next:"start"}],formatString:[{regex:"/("+c("/")+"+)/",token:"regex"},{regex:"",onMatch:function(a,b,c){return c.inFormatString=!0},next:"start"}]}),a.prototype.getTokenizer=function(){return a.$tokenizer},a.$tokenizer},a.prototype.tokenizeTmSnippet=function(a,b){return this.getTokenizer().getLineTokens(a,b).tokens.map(function(a){return a.value||a})},a.prototype.$getDefaultValue=function(a,b){var c,d,f;switch(!1){case!/^[A-Z]\d+$/.test(b):return c=b.substr(1),(this.variables[b[0]+"__"]||{})[c];case!/^\d+$/.test(b):return(this.variables.__||{})[b];default:if(b=b.replace(/^TM_/,""),!a)return;switch(f=a.session,b){case"CURRENT_WORD":return d=f.getWordRange();case"SELECTION":case"SELECTED_TEXT":return f.getTextRange(d);case"CURRENT_LINE":return f.getLine(e.getCursorPosition().row);case"LINE_INDEX":return e.getCursorPosition().column;case"LINE_NUMBER":return e.getCursorPosition().row+1;case"SOFT_TABS":return f.getUseSoftTabs()?"YES":"NO";case"TAB_SIZE":return f.getTabSize();case"FILENAME":case"FILEPATH":return"ace.ajax.org";case"FULLNAME":return"Ace"}}},a.prototype.getVariableValue=function(a,b){return this.variables.hasOwnProperty(b)?this.variables[b](a,b)||"":this.$getDefaultValue(a,b)||""},a.prototype.tmStrFormat=function(a,b,c){var d,e,f,g,h=this;return d=b.flag||"",g=b.guard,g=new RegExp(g,d.replace(/[^gi]/,"")),e=this.tokenizeTmSnippet(b.fmt,"formatString"),f=a.replace(g,function(){var a,d,f,g,i,j;for(h.variables.__=arguments,a=h.resolveVariables(e,c),d="E",f=i=0,j=a.length;j>=0?j>i:i>j;f=j>=0?++i:--i)switch(b=a[f],!1){case"object"!=typeof b:a[f]="",b.changeCase&&b.local?(g=a[f+1],g&&"string"==typeof g&&(a[f]="u"===b.changeCase?g[0].toUpperCase():g[0].toLowerCase(),a[f+1]=g.substr(1))):b.changeCase&&(d=b.changeCase);break;case"U"!==d:a[f]=b.toUpperCase();break;case"L"!==d:a[f]=b.toLowerCase()}return a.join("")}),this.variables.__=null,f},a.prototype.resolveVariables=function(a,b){var c,d,e,f,g,h,i;for(f=[],d=function(b){var c,d;return d=a.indexOf(b,c+1),-1!==d?c=d:void 0},e=h=0,i=a.length;i>=0?i>h:h>i;e=i>=0?++h:--h)switch(c=a[e],!1){case"string"!=typeof c:f.push(c);break;case"object"==typeof c:continue;case!c.skip:d(c);break;case!(c.processed=g?0>=f:f>=0;d=0>=g?++f:--f)if(e=a[d],!(e.startRe&&!e.startRe.test(b)||e.endRe&&!e.endRe.test(c)||!e.startRe&&!e.endRe))return e.matchBefore=e.startRe?e.startRe.exec(b):[""],e.matchAfter=e.endRe?e.endRe.exec(c):[""],e.replaceBefore=e.triggerRe?e.triggerRe.exec(b)[0]:"",e.replaceAfter=e.endTriggerRe?e.endTriggerRe.exec(c)[0]:"",e},a.prototype.register=function(a,b){var c,d,e,f,g,h;return f=this.snippetMap,g=this.snippetNameMap,e=this,h=function(a){return a&&!/^\^?\(.*\)\$?$|^\\b$/.test(a)&&(a="(?:"+a+")"),a||""},d=function(a,b,c){return a=h(a),b=h(b),c?(a=b+a,a&&"$"!==a[a.length-1]&&(a+="$")):(a+=b,a&&"^"!==a[0]&&(a="^"+a)),new RegExp(a)},c=function(a){var c,h;return a.scope||(a.scope=b||"_"),b=a.scope,f[b]||(f[b]=[],g[b]={}),c=g[b],a.name&&(h=c[a.name],h&&e.unregister(h),c[a.name]=a),f[b].push(a),a.tabTrigger&&!a.trigger&&(!a.guard&&/^\w/.test(a.tabTrigger)&&(a.guard="\\b"),a.trigger=j.escapeRegExp(a.tabTrigger)),a.startRe=d(a.trigger,a.guard,!0),a.triggerRe=new RegExp(a.trigger,"",!0),a.endRe=d(a.endTrigger,a.endGuard,!0),a.endTriggerRe=new RegExp(a.endTrigger,"",!0)},a.content?c(a):Array.isArray(a)?a.forEach(c):void 0},a.prototype.unregister=function(a,b){var c,d,e;return d=this.snippetMap,e=this.snippetNameMap,c=function(a){var c,f,g;return g=e[a.scope||b],g&&g[a.name]&&(delete g[a.name],f=d[a.scope||b],c=null!=f?f.indexOf(a):void 0,c>=0)?f.splice(c,1):void 0},a.content?c(a):Array.isArray(a)?a.forEach(c):void 0},a.prototype.parseSnippetFile=function(a){var b,c,d,e,f,g,h,i;for(a=a.replace(/\r/,""),e=[],h={},g=/^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm;f=g.exec(a);){if(f[1])try{h=JSON.parse(f[1]),e.push(h)}catch(j){b=j}if(f[4])h.content=f[4].replace(/^\t/gm,""),e.push(h),h={};else switch(d=f[2],i=f[3],d){case"regex":c=/\/((?:[^\/\\]|\\.)*)|$/g,h.guard=c.exec(i)[1],h.trigger=c.exec(i)[1],h.endTrigger=c.exec(i)[1],h.endGuard=c.exec(i)[1];break;case"snippet":h.tabTrigger=i.match(/^\S*/)[0],h.name||(h.name=i);break;default:h[d]=i}}return e},a.prototype.getSnippetByName=function(a,b){var c,d;return c=b&&this.$getScope(b),d=this.snippetNameMap,[c,"_"].some(function(b){var c,e;return e=d[b],e&&(c=e[a]),!!c}),snippet},a}(),g=function(){function a(a){a.tabstopManager?a.tabstopManager:(a.tabstopManager=this,this.$onChange=this.onChange.bind(this),this.$onChangeSelection=j.delayedCall(this.onChangeSelection.bind(this)).schedule,this.$onChangeSession=this.onChangeSession.bind(this),this.$onAfterExec=this.onAfterExec.bind(this),this.attach(a)),this.keyboardHandler=new c,this.keyboardHandler.bindKeys({Tab:function(a){return a.tabstopManager.tabNext(1)},"Shift-Tab":function(a){return a.tabstopManager.tabNext(-1)},Esc:function(a){return a.tabstopManager.detach()},Return:function(){return!1}})}return a.prototype.attach=function(a){return this.index=-1,this.ranges=[],this.tabstops=[],this.selectedTabstop=null,this.editor=a,this.editor.on("change",this.$onChange),this.editor.on("changeSelection",this.$onChangeSelection),this.editor.on("changeSession",this.$onChangeSession),this.editor.commands.on("afterExec",this.$onAfterExec),this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)},a.prototype.detach=function(){return this.tabstops.forEach(this.removeTabstopMarkers,this),this.ranges=null,this.tabstops=null,this.selectedTabstop=null,this.editor.removeListener("change",this.$onChange),this.editor.removeListener("changeSelection",this.$onChangeSelection),this.editor.removeListener("changeSession",this.$onChangeSession),this.editor.commands.removeListener("afterExec",this.$onAfterExec),this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler),this.editor.tabstopManager=null,this.editor=null},a.prototype.onChange=function(a){var b,c,d,e,f,g,h,j,k,l,m,n,o,p,q;if(b=a.data.range,h="r"===a.data.action[0],m=b.start,e=b.end,n=m.row,f=e.row,j=f-n,d=e.column-m.column,h&&(j=-j,d=-d),!this.$inChange&&h&&(o=this.selectedTabstop,c=!o.some(function(a){return i(a.start,m)<=0&&i(a.end,e)>=0})))return this.detach();for(l=this.ranges,g=p=0,q=l.length;q>=0?q>p:p>q;g=q>=0?++p:--p)k=l[g],k.end.row0?(this.removeRange(k),g--):(k.start.row===n&&k.start.column>m.column&&(k.start.column+=d),k.end.row===n&&k.end.column>=m.column&&(k.end.column+=d),k.start.row>=n&&(k.start.row+=j),k.end.row>=n&&(k.end.row+=j),i(k.start,k.end)>0&&this.removeRange(k)));return l.length?void 0:this.detach()},a.prototype.updateLinkedFields=function(){var a,c,d,e,f,g,h,i;if(g=this.selectedTabstop,g.hasLinkedRanges){for(this.$inChange=!0,e=this.editor.session,f=e.getTextRange(g.firstNonLinked),c=h=i=g.length-1;0>=i?0>h:h>0;c=0>=i?++h:--h)d=g[c],d.linked&&(a=b.snippetManager.tmStrFormat(f,d.original),e.replace(d,a));return this.$inChange=!1}},a.prototype.onAfterExec=function(a){return a.command&&!a.command.readOnly?this.updateLinkedFields():void 0},a.prototype.onChangeSelection=function(){var a,b,c,d,e,f,g,h;if(this.editor){for(f=this.editor.selection.lead,a=this.editor.selection.anchor,e=this.editor.selection.isEmpty(),d=g=h=this.ranges.length-1;0>=h?0>=g:g>=0;d=0>=h?++g:--g)if(!this.ranges[d].linked&&(c=this.ranges[d].contains(f.row,f.column),b=e||this.ranges[d].contains(a.row,a.column),c&&b))return;return this.detach()}},a.prototype.onChangeSession=function(){return this.detach()},a.prototype.tabNext=function(a){var b,c;return c=this.tabstops.length-1,b=this.index+(a||1),b=Math.min(Math.max(b,0),c),this.selectTabstop(b),b===c?this.detach():void 0},a.prototype.selectTabstop=function(a){var b,c,d,e,f;if(d=this.tabstops[this.index],d&&this.addTabstopMarkers(d),this.index=a,d=this.tabstops[this.index],null!=d?d.length:void 0){if(this.selectedTabstop=d,this.editor.inVirtualSelectionMode)this.editor.selection.setRange(d.firstNonLinked);else for(c=this.editor.multiSelect,d.hasLinkedRanges&&c.toSingleRange(d.firstNonLinked.clone()),b=e=f=d.length-1;0>=f?0>=e:e>=0;b=0>=f?++e:--e)d.hasLinkedRanges&&d[b].linked||c.addRange(d[b].clone(),!0);return this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler)}},a.prototype.addTabstops=function(a,b,c){var e,f,g,h,i,j=this;return a[0]||(h=d.fromPoints(c,c),l(h.start,b),l(h.end,b),a[0]=[h],a[0].index=0),g=this.index,e=[g,0],i=this.ranges,f=this.editor,a.forEach(function(a){var c,f,l;for(g=f=l=a.length-1;0>=l?0>f:f>0;g=0>=l?++f:--f)h=a[g],c=d.fromPoints(h.start,h.end||h.start),k(c.start,b),k(c.end,b),c.original=h,c.tabstop=a,i.push(c),a[g]=c,h.fmtString?(c.linked=!0,a.hasLinkedRanges=!0):a.firstNonLinked||(a.firstNonLinked=c);return a.firstNonLinked||(a.hasLinkedRanges=!1),e.push(a),j.addTabstopMarkers(a)}),e.push(e.splice(2,1)[0]),this.tabstops.splice.apply(this.tabstops,e)},a.prototype.addTabstopMarkers=function(a){var b;return b=this.editor.session,a.forEach(function(a){return a.markerId?void 0:a.markerId=b.addMarker(a,"ace_snippet-marker","text")})},a.prototype.removeTabstopMarkers=function(a){var b;return b=this.editor.session,a.forEach(function(a){return b.removeMarker(a.markerId),a.markerId=null})},a.prototype.removeRange=function(a){var b;return b=a.tabstop.indexOf(a),a.tabstop.splice(b,1),b=this.ranges.indexOf(a),this.ranges.splice(b,1),this.editor.session.removeMarker(a.markerId)},a}(),k=function(a,b){return 0===a.row&&(a.column+=b.column),a.row+=b.row},l=function(a,b){return a.row===b.row&&(a.column-=b.column),a.row-=b.row},a("./lib/dom").importCssString(".ace_snippet-marker {\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n background: rgba(194, 193, 208, 0.09);\n border: 1px dotted rgba(211, 208, 235, 0.62);\n position: absolute;\n}"),b.snippetManager=new f,b}),define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/event","ace/lib/lang","ace/snippets"],function(a,b){var c,d,e,f,g,h,i,j;return f=a("./keyboard/hash_handler").HashHandler,c=a("./autocomplete/popup").AcePopup,j=a("./autocomplete/util"),g=a("./lib/event"),h=a("./lib/lang"),i=a("./snippets").snippetManager,d=function(){function a(){var a=this;this.keyboardHandler=new f,this.keyboardHandler.bindKeys(this.commands),this.blurListener=this.blurListener.bind(this),this.changeListener=this.changeListener.bind(this),this.mousedownListener=this.mousedownListener.bind(this),this.mousewheelListener=this.mousewheelListener.bind(this),this.changeTimer=h.delayedCall(function(){return a.updateCompletions(!0)})}return a.prototype.$init=function(){var a=this;return this.popup=c(document.body||document.documentElement),this.popup.on("click",function(b){return a.insertMatch(),b.stop()})},a.prototype.openPopup=function(a,b){var c,d,e,f;return this.popup||this.$init(),ace.config._dispatchEvent("desc",{ident:this.completions.filtered[0].caption}),this.popup.setData(this.completions.filtered),f=a.renderer,b||(c=f.layerConfig.lineHeight,d=f.$cursorLayer.getPixelPosition(null,!0),e=a.container.getBoundingClientRect(),d.top+=e.top-f.layerConfig.offset,d.left+=e.left,d.left+=f.$gutterLayer.gutterWidth,this.popup.show(d,c)),f.updateText()},a.prototype.detach=function(){var a;return this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler),this.editor.removeEventListener("changeSelection",this.changeListener),this.editor.removeEventListener("blur",this.changeListener),this.editor.removeEventListener("mousedown",this.changeListener),this.changeTimer.cancel(),null!=(a=this.popup)&&a.hide(),this.activated=!1},a.prototype.changeListener=function(){return this.activated?this.changeTimer.schedule():this.detach()},a.prototype.blurListener=function(){return document.activeElement!==this.editor.textInput.getElement()?this.detach():void 0},a.prototype.mousedownListener=function(){return this.detach()},a.prototype.mousewheelListener=function(){return this.detach()},a.prototype.goTo=function(a){var b,c;switch(c=this.popup.getRow(),b=this.popup.session.getLength()-1,a){case"up":c=0>=c?b:c-1;break;case"down":c=c>=b?0:c+1;break;case"start":c=0;break;case"end":c=b}return this.popup.setRow(c)},a.prototype.insertMatch=function(a){var b,c;return this.detach(),null==a&&(a=this.popup.getData(this.popup.getRow())),a?(null!=(c=a.completer)?c.insertMatch:void 0)?a.completer.insertMatch(this.editor):(this.completions.filterText&&(b=this.editor.selection.getRange(),b.start.column-=this.completions.filterText.length,this.editor.session.remove(b)),a.snippet?i.insertSnippet(this.editor,a.snippet):this.editor.insert(a.value||a)):!1},a.prototype.commands={Up:function(a){return a.completer.goTo("up")},Down:function(a){return a.completer.goTo("down")},"Ctrl-Up|Ctrl-Home":function(a){return a.completer.goTo("start")},"Ctrl-Down|Ctrl-End":function(a){return a.completer.goTo("end")},Esc:function(a){return a.completer.detach()},Space:function(a){return a.completer.detach(),a.insert(" ")},Return:function(a){return a.completer.insertMatch()},"Shift-Return":function(a){return a.completer.insertMatch(!0)},Tab:function(a){return a.completer.insertMatch()},PageUp:function(a){return a.completer.popup.gotoPageDown()},PageDown:function(a){return a.completer.popup.gotoPageUp()}},a.prototype.gatherCompletions=function(a,b){var c,d,e,f,g;return g=a.getSession(),e=a.getCursorPosition(),c=g.getLine(e.row),f=j.retrievePrecedingIdentifier(c,e.column),d=[],j.parForEach(a.completers,function(b,c){return b.getCompletions(a,g,e,f,function(a,b){return a||(d=d.concat(b)),c()})},function(){return d.sort(function(a,b){return b.score-a.score}),b(null,{prefix:f,matches:d})}),!0},a.prototype.showPopup=function(a){return this.editor&&this.detach(),this.activated=!0,this.editor=a,a.completer!==this&&(a.completer&&a.completer.detach(),a.completer=this),a.keyBinding.addKeyboardHandler(this.keyboardHandler),a.on("blur",this.blurListener),a.on("mousedown",this.mousedownListener),this.updateCompletions(),this.changeTimer.cancel()},a.prototype.updateCompletions=function(a){var b=this;return this.gatherCompletions(this.editor,function(c,d){var f;return f=null!=d?d.matches:void 0,(null!=f?f.length:void 0)?(b.completions=new e(f),b.completions.setFilter(d.prefix),b.openPopup(b.editor,a)):b.detach()})},a.prototype.cancelContextMenu=function(){var a,b=this;return a=function(c){return b.editor.off("nativecontextmenu",a),(null!=c?c.domEvent:void 0)?g.stopEvent(c.domEvent):void 0},setTimeout(a,10),this.editor.on("nativecontextmenu",a)},a}(),d.startCommand={name:"startAutocomplete",exec:function(a){return a.completer||(a.completer=new d),a.completer.showPopup(a),a.completer.cancelContextMenu(),a.getSession().insert(a.getCursorPosition(),"<")},bindKey:"<"},e=function(){function a(a){this.all=a,this.filtered=a.concat(),this.filterText=""}return a.prototype.setFilter=function(a){return this.filterText=a},a}(),b.Autocomplete=d,b.FilteredList=e,b}),define("ace/autocomplete/popup",["require","exports","module","ace/edit_session","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom"],function(a,b){var c,d,e,f,g,h,i,j,k;return e=a("ace/edit_session").EditSession,h=a("ace/virtual_renderer").VirtualRenderer,f=a("ace/editor").Editor,g=a("ace/range").Range,j=a("ace/lib/event"),k=a("ace/lib/lang"),i=a("ace/lib/dom"),c=function(a){var b,c;return c=new h(a),c.$maxLines=4,b=new f(c),b.setHighlightActiveLine(!1),b.setShowPrintMargin(!1),b.renderer.setShowGutter(!1),b.renderer.setHighlightGutterLine(!1),b.$mouseHandler.$focusWaitTimout=0,b},d=function(a){var b,d,e,f,h,l;return d=i.createElement("div"),l=new c(d),a&&a.appendChild(d),d.style.display="none",l.renderer.content.style.cursor="default",l.renderer.setStyle("ace_autocomplete"),h=function(){},l.focus=h,l.$isFocused=!0,l.renderer.$cursorLayer.restartTimer=h,l.renderer.$cursorLayer.element.style.opacity=0,l.renderer.$maxLines=8,l.renderer.$keepTextAreaAtCursor=!1,l.setHighlightActiveLine(!0),l.session.highlight(""),l.session.$searchHighlight.clazz="ace_highlight-marker",l.on("mousedown",function(a){var b;return b=a.getDocumentPosition(),l.moveCursorToPosition(b),l.selection.clearSelection(),a.stop()}),f=new g(-1,0,-1,1/0),f.id=l.session.addMarker(f,"ace_line-hover","fullLine"),l.on("mousemove",function(a){var b;return b=a.getDocumentPosition().row,f.start.row=f.end.row=b,l.session._emit("changeBackMarker")}),e=function(){return f.start.row=f.end.row=-1,l.session._emit("changeBackMarker")},j.addListener(l.container,"mouseout",e),l.on("hide",e),l.on("changeSelection",e),l.on("mousewheel",function(a){return setTimeout(function(){return l._signal("mousemove",a)})}),l.session.doc.getLength=function(){return l.data.length},l.session.doc.getLine=function(a){var b;return b=l.data[a],"string"==typeof b?b:b&&b.value||""},b=l.session.bgTokenizer,b.$tokenizeRow=function(a){var b,c,d;return b=l.data[a],d=[],b?("string"==typeof b&&(b={value:b}),b.caption||(b.caption=b.value),d.push({type:b.className||"",value:b.caption}),b.meta&&(c=l.renderer.$size.scrollerWidth/l.renderer.layerConfig.characterWidth,b.meta.length+b.caption.lengthwindow.innerHeight/2+b?(d.style.top="",d.style.bottom=window.innerHeight-a.top+"px"):(a.top+=b,d.style.top=a.top+"px",d.style.bottom=""),d.style.left=a.left+"px",d.style.display="",l.renderer.$textLayer.checkForSizeChanges(),l._signal("show")},l},i.importCssString(".ace_autocomplete.ace-tm .ace_marker-layer .ace_active-line {\n background-color: #abbffe;\n}\n.ace_autocomplete.ace-tm .ace_line-hover {\n border: 1px solid #abbffe;\n position: absolute;\n background: rgba(233,233,253,0.4);\n z-index: 2;\n margin-top: -1px;\n}\n.ace_rightAlignedText {\n color: gray;\n display: inline-block;\n position: absolute;\n right: 4px;\n text-align: right;\n z-index: -1;\n}\n.ace_autocomplete {\n width: 200px;\n height: 120px;\n z-index: 200000;\n background: #f8f8f8;\n border: 1px lightgray solid;\n position: fixed;\n box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n}"),b.AcePopup=d,b}),define("ace/autocomplete/util",["require","exports","module"],function(a,b){var c;return b.parForEach=function(a,b,c){var d,e,f,g,h,i;for(e=0,d=a.length,0===d&&c(),i=[],g=0,h=a.length;h>g;g++)f=a[g],i.push(b(f,function(a,b){return e++,e===d?c(a,b):void 0}));return i},c=/[a-zA-Z_0-9\$-]/,b.retrievePrecedingIdentifier=function(a,b,d){var e,f,g,h;for(d=d||c,e=[],f=g=h=b-1;(0>=h?0>=g:g>=0)&&d.test(a[f]);f=0>=h?++g:--g)e.push(a[f]);
3 | return e.reverse().join("")},b.retrieveFollowingIdentifier=function(a,b,d){var e,f,g,h;for(d=d||c,e=[],f=g=b,h=a.length;(h>=b?h>g:g>h)&&d.test(a[f]);f=h>=b?++g:--g)e.push(a[f]);return e},b}),define("ace/autocomplete/text_completer",["require","exports","module","ace/range"],function(a,b){var c,d,e,f,g;return c=a("ace/range").Range,f=/[^a-zA-Z_0-9\$\-]+/,e=function(a,b){var d;return d=a.getTextRange(c.fromPoints({row:0,column:0},b)),d.split(f).length-1},d=function(a,b){var c,d,e,f;for(d=[],c=e=0,f=b.length;f>=0?f>e:e>f;c=f>=0?++e:--e)0===b[c].lastIndexOf(a,0)&&d.push(b[c]);return d},g=function(a,b){var c,d,g,h;return d=e(a,b),h=a.getValue().split(f),g=Object.create(null),c=h[d],h.forEach(function(a,b){var e,f;return a&&a!==c?(e=Math.abs(d-b),f=h.length-e,g[a]=g[a]?Math.max(f,g[a]):f):void 0}),g},b.getCompletions=function(a,b,c,e,f){var h,i;return i=g(b,c,e),h=d(e,Object.keys(i)),f(null,h.map(function(a){return{name:a,value:a,score:i[a],meta:"local"}}))},b}))}.call(this),function(){Angles.ContextHelp=function(){function a(a){var b;b=this.dispatcher=a.dispatcher,this.$odd={},this.$angles=a.anglesView}return a.prototype.setODD=function(a){return this.$odd=a},a.prototype.getODDfor=function(a){var b,c,d,e;for(b=this.$odd.members,d=0,e=b.length;e>d;d++)if(c=b[d],c.ident===a)return c;return null},a.prototype.getDescOf=function(a){var b;return null!=(b=this.getODDfor(a))?b.desc:void 0},a.prototype.getChildrenOf=function(a){var b;return null!=(b=this.getODDfor(a))?b.children:void 0},a}()}.call(this),function(){var a=function(a,b){return function(){return a.apply(b,arguments)}};Angles.FileUploader=function(){function b(b){this._handleFileSelect=a(this._handleFileSelect,this);var c;c=this.dispatcher=b.dispatcher,this.$angles=b.anglesView,this.storedFiles=b.storedFiles}return b.prototype._handleFileSelect=function(a){var b,c,d=this;return b=a.target.files[0],c=new FileReader,c.onload=function(a){var c,e;return e=d.storedFiles.find(function(a){return a.get("name")===b.name}),null!=e&&e.destroy(),c=d.storedFiles.create({name:b.name,content:a.target.result}),d.dispatcher.trigger("document:switch",c)},c.readAsText(b,"UTF-8")},b.prototype.bind=function(a){return $(a).change(this._handleFileSelect)},b}()}.call(this),function(){Angles.NotificationCenter=function(){function a(a){var b,c=this;b=this.dispatcher=a.dispatcher,this.$angles=a.anglesView,this.$notifications=new Angles.NotificationList,b.on("notification:push",function(a){return c.push(a)}),b.on("notification:clear",function(){return c.clear()})}return a.prototype.push=function(a){return this.$notifications.add(a)},a.prototype.clear=function(){for(var a;a=this.$notifications.first();)a.destroy();return null},a}()}.call(this),function(){Angles.Validator=function(){function a(a){var b;b=this.dispatcher=a.dispatcher,this.$schema={},this.$errors=[],this.$angles=a.anglesView}return a.prototype.displayErrors=function(){var a,b,c,d;for(d=this.errors(),b=0,c=d.length;c>b;b++)a=d[b],this.dispatcher.trigger("validation:error",a);return this.endValidation()},a.prototype.addError=function(a){return this.$errors.push(a)},a.prototype.clearErrors=function(){return this.$errors=[]},a.prototype.endValidation=function(){return this.dispatcher.trigger("validation:end")},a.prototype.setSchema=function(a){return this.$schema=a,this.dispatcher.trigger("validation")},a.prototype.errors=function(){return this.$errors},a.prototype.hasErrors=function(){return 0!==this.$errors.length},a}()}.call(this),function(){var a={}.hasOwnProperty,b=function(b,c){function d(){this.constructor=b}for(var e in c)a.call(c,e)&&(b[e]=c[e]);return d.prototype=c.prototype,b.prototype=new d,b.__super__=c.prototype,b},c=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};Angles.SAXParser=function(){function a(a){this.reset=function(){var b,c=this;return b=sax.parser(!0,{xmlns:!0,noscript:!0,position:!0}),b.onerror=null!=a.error?function(d){return"Text data outside of root node."!==d.message.split(/\n/)[0]&&a.error.call(c,d),b.resume()}:function(a){return"Text data outside of root node."!==a.message.split(/\n/)[0]&&c.validationError(a.message.split(/\n/)[0]),b.resume()},null!=a.characters&&(b.ontext=function(b){return a.characters.call(c,b)}),null!=a.startElement&&(b.onopentag=function(b){return a.startElement.call(c,b)}),null!=a.endElement&&(b.onclosetag=function(b){return a.endElement.call(c,b)}),null!=a.comment&&(b.oncomment=function(b){return a.comment.call(c,b)}),null!=a.startCdata&&(b.onopencdata=function(){return a.startCdata.call(c)}),null!=a.cdata&&(b.oncdata=function(b){return a.cdata.call(c,b)}),null!=a.endCdata&&(b.onclosecdata=function(){return a.endCdata.call(c)}),null!=a.endDocument&&(b.onend=function(){return a.endDocument.call(c)}),b.onstart=null!=a.startDocument?function(){return a.startDocument.call(c)}:function(){},this.$parser=b,this.$errors=[]}}return a.prototype.parse=function(a){var b,c,d,e;for(this.reset(),d=this.$parser,c=a.getLength(),d.onstart(),b=e=0;c>=0?c>=e:e>=c;b=c>=0?++e:--e)d.write(a.getLine(b)+"\n");return d.close(),this.validated()?!0:!1},a.prototype.validationError=function(a,b){var c;return c=this.$parser,this.$errors.push({text:a,row:c.line,column:c.column,type:null!=b?b:"error"})},a.prototype.validated=function(){return 0===this.$errors.length},a}(),Angles.ValidatorSAX=function(a){function d(a){var b=this;d.__super__.constructor.call(this,a),this.dispatcher.on("validation",function(){var a,c;return a=null!=(c=b.$angles)?c.getDocument():void 0,null!=a?(b.dispatcher.trigger("validation:start"),b.validate(b.$angles.getDocument())):void 0})}return b(d,a),d.prototype.checkSchema=function(a,b){var d,e,f,g,h;if(null!=this.$schema)return 1===(null!=b?b.length:void 0)?(this.$schema.hasOwnProperty(null!=(g=b[0])?g.name:void 0)?(f=new RegExp(this.$schema._start,"ig"),null===f.exec(b[0].name+",")&&a.validationError("Invalid root element: "+b[0].name+".")):a.validationError("Invalid root element: "+b[0].name+"."),void 0):(d=b[0].name,e=b[1].name,null==this.$schema[e]?a.validationError("The "+d+" element is not allowed as a child of the "+e+" element."):(c.call(null!=(h=this.$schema[e])?h.children:void 0,d)<0&&a.validationError("The "+d+" element is not allowed as a child of the "+e+" element."),void 0))},d.prototype.checkChildren=function(a,b){var c,d,e;if(null!=this.$schema&&b.length>0&&(d=b[0],c=d.children.join(","),""!==c&&(c+=","),this.$schema.hasOwnProperty(null!=d?d.name:void 0)&&this.$schema[d.name].hasOwnProperty("model")))return e=new RegExp(this.$schema[d.name].model,"ig"),null===e.exec(c)?a.validationError(d.name+" is invalid: one or more required children are missing or its child elements are in the wrong order."):void 0},d.prototype.validate=function(a){var b,c,d=this;return b=[],c=new Angles.SAXParser({startDocument:function(){return b=[]},endDocument:function(){var a,d;return b.length>0?(d=function(){var c,d,e;for(e=[],c=0,d=b.length;d>c;c++)a=b[c],e.push(a.name);return e}(),c.validationError("Unclosed elements at end of document: "+d.join(", "))):void 0},startElement:function(a){return b.length>0&&b[0].children.push(a.local),b.unshift({name:a.local,children:[]}),d.checkSchema(c,b)},characters:function(a){return b.length>0&&null===a.match(/^[\s\r\n]*$/)?b[0].children.push("_text_"):void 0},endElement:function(){return d.checkChildren(c,b),b.shift()}}),c.parse(a),this.$errors=c.$errors,this.displayErrors()},d}(Angles.Validator)}.call(this),function(){var a={}.hasOwnProperty,b=function(b,c){function d(){this.constructor=b}for(var e in c)a.call(c,e)&&(b[e]=c[e]);return d.prototype=c.prototype,b.prototype=new d,b.__super__=c.prototype,b};Angles.ValidatorSRV=function(a){function c(a){var b=this;c.__super__.constructor.call(this,a),this.$validatorUrl=a.validator,this.$requestHandler=null!=a.requestHandler?a.requestHandler:d,this.$validationHandler=null!=a.validationHandler?a.validationHandler:e,this.dispatcher.on("validation",function(){return b.dispatcher.trigger("validation:start"),b.$requestHandler(b)})}var d,e;return b(c,a),d=function(a){var b,c,d=this;return b=a.$angles.getDocument(),c=escape(b.getValue()),$.ajax({url:a.$validatorUrl,type:"POST",crossDomain:!0,processData:!1,data:"schema="+a.$schema+"&document="+c,dataType:"json",success:function(b){return a.$validationHandler(a,b)},error:function(a,b,c){var e;return d.dispatcher.trigger("notification:clear"),c=0===a.status?"Cannot reach server":c,e={type:"Server",info:"Status: "+a.status,message:c,location:{row:-1,column:-1}},d.dispatcher.trigger("notification:push",e)}})},e=function(a,b){var c,d,e;for(a.$errors=[],d=0,e=b.length;e>d;d++)c=b[d],a.$errors.push({text:c.message,row:c.line-1,column:c.column,type:c.type});return a.displayErrors()},c}(Angles.Validator)}.call(this);
--------------------------------------------------------------------------------