marley 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,159 @@
1
+ body {background: #C9DE96; color: #000; font:13px/1.231 sans-serif; *font-size:small;height: 100%; min-height: 100%;}
2
+ #main_menu__section {
3
+ background: #fff;
4
+ border: 1px solid #398235;
5
+ border-radius: 1em;
6
+ box-shadow: 0 0 10px rgba(51,51,51,0.5);
7
+ margin: 2em auto;
8
+ width: 90%;
9
+ height:90%;
10
+ position:relative;
11
+ }
12
+ #main_menu__section > .navigation {
13
+ display:block;
14
+ float:left;
15
+ width:20%;
16
+ height:85%;
17
+ overflow:auto;
18
+ text-align:center;
19
+ }
20
+ .navigation{
21
+ display:inline-block;
22
+ padding:.3em;
23
+ margin:0;
24
+ }
25
+
26
+ .content{
27
+ float:left;
28
+ width:75%;
29
+ height:85%;
30
+ overflow:auto;
31
+ margin:0 1em;
32
+ }
33
+
34
+ input, textarea {
35
+ border: 1px solid #398235;
36
+ line-height: 1.5em;
37
+ margin: 0;
38
+ }
39
+ textarea {
40
+ height: 10em;
41
+ line-height: 1.25em;
42
+ margin: .5em 0;
43
+ width: 100%%;
44
+ overflow: auto;
45
+ }
46
+ .hidden {display: none;}
47
+ .editable {
48
+ border: 1px dotted #398235;
49
+ cursor: pointer;
50
+ padding: 2px 5px;
51
+ }
52
+ .editable:after {
53
+ content: "\270E";
54
+ font-size: 125%;
55
+ padding: 0 0 0 3px;
56
+ }
57
+ .editing span,.editable input,.editable textarea{display:none;}
58
+ .editing input[type=text] {
59
+ background: #DCFCBD;
60
+ padding: 1px 5px;
61
+ }
62
+ .editing input[type=submit] {
63
+ float: none;
64
+ margin: 0 0 0 5px;
65
+ }
66
+ label {
67
+ color: #398235;
68
+ display: inline-block;
69
+ font: bold 85%/1.5em sans-serif;
70
+ width: 10em;
71
+ text-align:right;
72
+ padding: 0 .5em 0 0;
73
+ }
74
+ input[type=button],
75
+ input[type=submit],
76
+ .navigation li a,
77
+ .instanceActions a {
78
+ background: -webkit-linear-gradient(top, #c9de96 0%, #398235 100%);
79
+ background: -moz-linear-gradient(top, #c9de96 0%, #398235 100%);
80
+ background: linear-gradient(top, #c9de96 0%,#398235 100%);
81
+ border: 1px solid #398235;
82
+ border-radius: 1em;
83
+ color: #fff;
84
+ font: bold 93% sans-serif;
85
+ padding: .5em 1em;
86
+ text-decoration: none;
87
+ text-transform: uppercase;
88
+ }
89
+ .navigation li a {
90
+ display:block;
91
+ text-align:center;
92
+ min-width:15em;
93
+ }
94
+ input[type=button]:hover,
95
+ .navigation li a:hover,
96
+ .instanceActions a:hover {
97
+ background: -webkit-linear-gradient(top, #398235 0%, #c9de96 100%);
98
+ background: -moz-linear-gradient(top, #398235 0%, #c9de96 100%);
99
+ background: linear-gradient(top, #398235 0%,#c9de96 100%);
100
+ color: #fff;
101
+ cursor: pointer;
102
+ }
103
+
104
+ h1{
105
+ background: #398235;
106
+ border-bottom: 1px solid #398235;
107
+ border-radius: .5em;
108
+ color: #fff;
109
+ font: bold 167%/150% "Rockwell STD", Rockwell, sans-serif;
110
+ margin: 0 0 1em;
111
+ text-align: center;
112
+ }
113
+ #main_menu__section > h1 {
114
+ border-bottom-left-radius: 0;
115
+ border-bottom-right-radius: 0;
116
+ }
117
+ .navigation .navigation {padding:0;font-size:90%;}
118
+ .navigation h1 {
119
+ width:100%;
120
+ padding:0;
121
+ margin:0;
122
+ border:none;
123
+ background:#C9DE96;
124
+ color: #050;
125
+ }
126
+ .navigation h1:hover {cursor:pointer;}
127
+ .navigation h1:after {
128
+ padding:0 0 0 .5em;
129
+ content: "\25B4";
130
+ }
131
+ .collapsed h1:after {
132
+ content: "\25BE";
133
+ }
134
+ .navigation li { list-style:none; margin: 1em 0; }
135
+ li.collapsed ul{display:none;}
136
+
137
+ .instanceContainer {
138
+ position:relative;
139
+ border: 1px solid #398235;
140
+ border-radius: .5em;
141
+ margin: .5em 0;
142
+ }
143
+ .instanceContainer .instanceContainer{margin:0 0 2em 2em;}
144
+ .colContainer div {
145
+ display: inline-block;
146
+ }
147
+ .instanceActions {overflow: hidden;}
148
+ .instanceActions a,
149
+ .instance input[type=submit],
150
+ .instance input[type=button]{
151
+ float: right;
152
+ margin: 0;
153
+ width: auto;
154
+ }
155
+ .errorCol {background: #febebe;}
156
+ .errorMsg {
157
+ color: #EA8989;
158
+ font: bold italic 77% sans-serif;
159
+ }
@@ -0,0 +1,87 @@
1
+ RESTRICT_HIDE=1;
2
+ RESTRICT_RO=2;
3
+ RESTRICT_REQ=4;
4
+ NAME_INDEX=1;
5
+ TYPE_INDEX=PROPS_INDEX=2;
6
+ RESTRICTIONS_INDEX=2;
7
+ VALUE_INDEX=3;
8
+ String.prototype.humanize=function(){return pl.map(this.replace(/^_/,'').split('_'),function(w){return w[0].toUpperCase()+w.slice(1)}).join(' ');}
9
+ pl(function(){
10
+ r.call(_jamaica_json,'body');
11
+ pl('.content:empty').remove();
12
+ var contents=pl('.content');
13
+ if (contents.get().length===0){
14
+ pl('#main_menu__section').append('<div id="current_content" class="content active"></div>');
15
+ }else{
16
+ contents.appendTo('#main_menu__section');
17
+ }
18
+ pl.win_bind('form','submit',j.formSubmit);
19
+ pl.win_bind('.navigation li a','click',j.menuClick);
20
+ pl.win_bind('.navigation li h1','click',j.toggleNav);
21
+ pl.win_bind('.editable','click',j.toggleColStat);
22
+ pl.win_bind('.editing input,.editing textarea','keydown',j.colEditKeydown);
23
+ pl.win_bind('.instanceAction','click',j.instanceActionClick);
24
+ pl.win_bind('input[value=delete]','click',j.deleteInstance);
25
+ });
26
+
27
+ j={
28
+ ajax_defaults:{
29
+ load:function(){pl('body').css('cursor','wait')},
30
+ always:function(){pl('body').css('cursor','default');},
31
+ success:function(json){pl(this).parent(2).replaceWith(r.call(json).toDom()); },
32
+ error:function(stat,json){
33
+ var err=JSON.parse(json);
34
+ var attrs=err[1];
35
+ var frm_id=this.id;
36
+ if (attrs.error_type=='validation') {
37
+ for (col in attrs.error_details) {
38
+ pl('#'+frm_id+' [id$=__'+col+']').addClass('errorCol').after(r.call(["p",{"class":"errorMsg"},attrs.error_details[col]]).toDom());
39
+ }
40
+ }
41
+ },
42
+ },
43
+ make_ajax_params:function(params){
44
+ return pl.extend(params,
45
+ pl.extend(pl.get_callbacks.call(this,j.ajax_defaults),{
46
+ dataType:'json',
47
+ url:this.href || this.action,
48
+ type: this.method ? this.method.toUpperCase() : 'GET'
49
+ })
50
+ );
51
+ },
52
+ menuClick:function(e){
53
+ e.preventDefault();
54
+ pl.ajax(j.make_ajax_params.call(this,{success:function(json){r.call(json,'#current_content')}}));
55
+ },
56
+ formSubmit:function(e){
57
+ e.preventDefault();
58
+ pl.ajax(j.make_ajax_params.call(this,{data:pl.serialize(this.id)}))
59
+ },
60
+ toggleNav:function(e){
61
+ pl(pl(this).parents('li').elements[0]).toggleClass('collapsed');
62
+ },
63
+ toggleColStat:function(e){
64
+ p=this.selector ? this : pl(this);
65
+ p.toggleClass("editing").toggleClass("editable");
66
+ if(p.hasClass("editing")){
67
+ if (p.children('input[type=submit]').get().length==0) p.append(pl('<input>',{type:'submit',value:'save'}).get());
68
+ p.children().get()[0].focus();
69
+ } else {
70
+ p.children('input[type=text],textarea').val(p.children('span').html())
71
+ }
72
+ },
73
+ colEditKeydown:function(e){
74
+ if (e.keyCode==27){
75
+ j.toggleColStat.call(pl(this).parents('.editing'));
76
+ }
77
+ },
78
+ instanceActionClick:function(e){
79
+ var frm=pl(this).parents('form');
80
+ var url=frm.attr('action')+'/'+pl(this).attr('class').replace(/.* /,'');
81
+ pl.ajax(j.make_ajax_params.call({href:url},{success:function(json){frm.after(r.call(json).toDom())}}))
82
+ },
83
+ deleteInstance:function(e){
84
+ var frm=pl(this).parents('form');
85
+ pl.ajax({url:frm.attr('action'),type:'POST',data:{_method:'delete'},success:function(){frm.remove()}})
86
+ },
87
+ }
@@ -0,0 +1,47 @@
1
+ pl.extend({
2
+ get_callbacks: function(fn){
3
+ var that=this;
4
+ var cb={};
5
+ if (pl.type(fn,'fn')) {
6
+ cb=function() {
7
+ fn.apply(that,arguments);
8
+ }
9
+ } else {
10
+ for (i in fn) {
11
+ cb[i]=pl.get_callbacks.call(that,fn[i]);
12
+ }
13
+ }
14
+ return cb;
15
+ },
16
+ win_bind:function(selector,evt,fn){
17
+ window.addEventListener(evt, function(e){
18
+ var elems=pl(selector).get();
19
+ if (elems===e.target || pl.filter(elems, function(el){return el==e.target}).length > 0){
20
+ fn.call(e.target,e);
21
+ }
22
+ });
23
+ },
24
+ /*
25
+ selectedBy: function(elem,selector) {
26
+ var elems=pl(selector).get()
27
+ return (elems===elem || pl.filter(elems, function(el){return el==elem}).length > 0)
28
+ },
29
+ parents: function(elem, selector) {
30
+ var ret=[]; var p;
31
+ if (pl.type(elem,'str')) elem=pl(elem).get();
32
+ if (p=elem.parentNode){
33
+ if( !selector||pl.selectedBy(p,selector)) ret.push(p);
34
+ return ret.concat(pl.parents(p,selector));
35
+ }
36
+ },
37
+ */
38
+ });
39
+ /*pl.extend(pl.fn,{
40
+ selectedBy: function(selector) {
41
+ return pl.selectedBy(this.get(),selector);
42
+ },
43
+ parents: function(selector) {
44
+ return pl.parents(this.elements[0], selector);
45
+ },
46
+ },true);
47
+ */
@@ -0,0 +1,187 @@
1
+ r=function(target){
2
+ this.isNodeSpec=function(){return this[0] && pl.type(this[0],'str') && this[1] && pl.type(this[1], 'obj')};
3
+ this.nodeType=this[0];
4
+ this.attrs=this[1];
5
+ this.content=this[2];
6
+ this.toDom=r.domFuncs[pl.type(this)];
7
+ if (target) {
8
+ var t=pl.type(target,'str') ? pl(target) : target;
9
+ var d=this.toDom();
10
+ if (pl.type(d,'arr')){
11
+ t.html('');
12
+ pl.each(d,function(i,e){ t.append(e); });
13
+ } else {
14
+ t.html(d);
15
+ }
16
+ }
17
+ return this;
18
+ }
19
+ r.colTypes={
20
+ "password":function(props) {
21
+ props.type="password";
22
+ return ["input",props];
23
+ },
24
+ "clob":function(props) {
25
+ var v=props.value;
26
+ delete props.value;
27
+ return ["textarea",props,v];
28
+ },
29
+ "image":function(props){
30
+ props.type="file";
31
+ return["input",props]
32
+ },
33
+ "many_to_one":function(props) {
34
+ var hprops=JSON.parse(JSON.stringify(props));
35
+ hprops.type="hidden";
36
+ hprops.name=j.id2name(hprops.id);
37
+ hprops.value=props.value[0];
38
+ props.type="text";
39
+ props.value=props.value[1];
40
+ props.id=props.id.replace(/_id$/,"");
41
+ props.name=j.id2name(props.id);
42
+ return [["input",hprops],["input",props]]
43
+ }
44
+ };
45
+ r.actionTypes={
46
+ "get":function(actions){
47
+ pl.type(actions,'str') ?
48
+ this.push(["a",{"class":"instanceAction "+actions},actions.humanize()]) :
49
+ pl.map(actions,function(action){
50
+ this.push( ["a",{"class":"instanceAction "+action},action.humanize()]);
51
+ });
52
+ },
53
+ "post":function(){},
54
+ "put":function(){},
55
+ "delete":function(){
56
+ this.push(['input',{"type":"button", "value":"delete"}])
57
+ }
58
+ };
59
+ r.id2name=function (s) {
60
+ parts=s.split('__');
61
+ name=parts.shift();
62
+ pl.each(parts,function(i,part){name+='['+part+']'});
63
+ return name;
64
+ };
65
+ r.nodeTypes={
66
+ "link":function(l){
67
+ return ["a",{"href":l.attrs.url},l.attrs.title];
68
+ },
69
+ "msg":function(m){
70
+ return ["div",{"class":"message"},[["h2",{},m[1].title],["p",{},m[1].description]]];
71
+ },
72
+ "section":function(m){
73
+ if (r.sectionTypes[m.attrs.name]){ return r.sectionTypes[m.attrs.name]};
74
+ var attrs=m.attrs;
75
+ var nav=pl.map(attrs.navigation,function(i){return ["li",{},[i]]});
76
+ return ["div",{"class":"section","id":attrs.name+"__section"},
77
+ [ ["h1",{},attrs.title],
78
+ ["div",{"class":"menuDescription"},attrs.description],
79
+ ["ul",{"class":"navigation"},nav],
80
+ ["div",{"class":attrs.name+"__content content"},m.content]]
81
+ ];
82
+ },
83
+ "instance":function(i) {
84
+ if (r.instanceTypes[i.attrs.name]){ return r.instanceTypes[i.attrs.name]};
85
+ var ctl;
86
+ var attrs=i.attrs;
87
+ var instance_id=attrs.new_rec ? 'new' : attrs.url.replace(/.*\//,'')
88
+ if (attrs.search){
89
+ attrs.new_rec=true;
90
+ var frm=["form",{"action":attrs.url,"method":"get","class":"search","id":attrs.name+'__search__form'}];
91
+ } else {
92
+ var frm=["form",{"action":attrs.url,"method":"post","class":attrs.name+"Instance instance","id":attrs.name+'__'+instance_id+'__form'}];
93
+ }
94
+ var contents=attrs.description ? [["div",{"class":"form_description"}, attrs.description]] : [];
95
+ if(! attrs.new_rec){
96
+ contents.push(["input",{"type":"hidden","name":"_method","value":"put"}])
97
+ }
98
+ pl.each(attrs.schema, function(i,col){
99
+ var props={"id":attrs.name+"__"+col[1]};
100
+ props.name=r.id2name(props.id);
101
+ props.value=col[VALUE_INDEX] || "";
102
+ if(col[RESTRICTIONS_INDEX] & RESTRICT_HIDE) {
103
+ if (props.value.constructor==Array) {props.value=props.value[0];} //many_to_one
104
+ if (col[RESTRICTIONS_INDEX] & RESTRICT_RO) {
105
+ //should there be anything here??
106
+ } else {
107
+ props.type="hidden";
108
+ contents.push(["input",props]);
109
+ }
110
+ } else{
111
+ if (col[RESTRICTIONS_INDEX] & RESTRICT_RO) {
112
+ if (props.value.constructor==Array) {props.value=props.value[1];} //many_to_one
113
+ delete props.name;
114
+ var v=props.value;
115
+ delete props.value;
116
+ //ugly as all fucking shit. Will suffice for now.
117
+ //if(col[0]=="clob"){ v=$.map(v.split("\n"),function(p){return [["p",{},p]]}) }
118
+ //if(col[0]=="clob"){ v=pl('<div>') }
119
+ ctl=["div",props,v];
120
+ } else {
121
+ if (c=r.colTypes[col[0]]) {
122
+ ctl=c(props);
123
+ } else {
124
+ props["type"]='text';
125
+ props["class"] || (props["class"]="")
126
+ props["class"]+=col[0];
127
+ ctl=["input",props];
128
+ }
129
+ if (! attrs.new_rec) {
130
+ var show_val;
131
+ if (ctl[1].constructor==Array){ //many to one
132
+ show_val=ctl[1][1].value
133
+ } else if (col[0]=="image") {
134
+ show_val=["img",{"src":ctl[1].value}]
135
+ //} else if(col[0]=="clob"){ //ugly as all fucking shit. Will suffice for now.
136
+ //show_val=$.map(col[VALUE_INDEX].split("\n"),function(p){return [["p",{},p]]})
137
+ //show_val=pl('<div>').html(col[VALUE_INDEX]);
138
+ } else {
139
+ show_val=ctl[1].value || ctl[2] //textarea value
140
+ }
141
+ ctl=["div",{"class":"editable col"},[ctl,["span",{},show_val]]]
142
+ }
143
+ }
144
+ contents.push(["div",{"class":props.id+"ColContainer colContainer"},[["label",{"for":props.id},col[1].humanize()+":"],ctl]]);
145
+ }
146
+ });
147
+ if (attrs.search){
148
+ contents.push(["input",{"type":"submit","value":"Search"}]);
149
+ } else {
150
+ contents.push(["input",{"type":"submit","value":"Save","class":"submit " + (attrs.new_rec ? "" : "hidden")}]);
151
+ }
152
+ if ((! attrs.new_rec) && (actions=attrs.actions)){
153
+ actions_dom=["div",{"class":"instanceActions"},[]];
154
+ for (var k in actions) {
155
+ r.actionTypes[k].call(actions_dom[2],actions[k])
156
+ }
157
+ contents.push(actions_dom);
158
+ }
159
+ frm.push(contents);
160
+ var content=i.content || [];
161
+ content.unshift(frm);
162
+ return ["div",{"class":"instanceContainer"},content];
163
+ }
164
+ };
165
+ r.instanceTypes={}
166
+ r.sectionTypes={}
167
+ r.domFuncs={
168
+ 'str' : function(){ return document.createTextNode(this);},
169
+ 'int' : function(){ return document.createTextNode(this);},
170
+ 'obj' : function(){return this;},
171
+ 'arr' : function(){
172
+ if(this.isNodeSpec()) {
173
+ if (node_type=r.nodeTypes[this.nodeType]) {
174
+ return r.call(node_type(this)).toDom();
175
+ } else {
176
+ var dom=pl('<'+ this.nodeType+'>',this.attrs);
177
+ if(this.content){ r.call(this.content, dom);}
178
+ return dom.get();
179
+ }
180
+ } else {
181
+ return pl.map(this, function(e){return r.call(e).toDom()})
182
+ }
183
+ }
184
+ };
185
+ r.toDom=function(){
186
+ r.domFuncs[pl.type(this)].call(this);
187
+ };