flexlayout-rails 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +37 -0
- data/LICENSE.txt +20 -0
- data/README.md +140 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/flexlayout-rails.gemspec +79 -0
- data/lib/flexlayout-rails.rb +6 -0
- data/spec/regions/img/lorem-ipsum-logo.jpeg +0 -0
- data/spec/regions/index.html +120 -0
- data/spec/regions/js/detection.js +9 -0
- data/spec/regions/js/layout.js +43 -0
- data/spec/regions/js/setup.js +0 -0
- data/spec/spec_helper.rb +12 -0
- data/vendor/assets/javascripts/feature-detects/cssregions.js +6 -0
- data/vendor/assets/javascripts/flexie.js +2039 -0
- data/vendor/assets/javascripts/flexie.min.js +1 -0
- data/vendor/assets/javascripts/jquery.lettering.js +66 -0
- data/vendor/assets/javascripts/jquery.lettering.min.js +13 -0
- data/vendor/assets/javascripts/regions.jquery.js +204 -0
- data/vendor/assets/javascripts/regions.jquery.min.js +7 -0
- data/vendor/assets/javascripts/template_layout/jquery/jquery.tpl_layout1.1.6.js +1256 -0
- data/vendor/assets/javascripts/template_layout/jquery/jquery.tpl_layout1.1.6.min.js +1 -0
- data/vendor/assets/javascripts/template_layout/templateLayout.compiler.js +1049 -0
- data/vendor/assets/javascripts/template_layout/templateLayout.generator.js +615 -0
- data/vendor/assets/javascripts/template_layout/templateLayout.js +339 -0
- metadata +158 -0
@@ -0,0 +1 @@
|
|
1
|
+
(function(d){var e,o="";var a;var c=[];var s;var r=0;var q=false;var i=[];var j=jQuery.fn.css;jQuery.fn.css=function(w,y){var x=o+"display";var v=o+"position";var u=false,B=false;if(y){if(w==x&&y.indexOf('"')!=-1){u=true}else{if(w==v&&y.length==1){B=true}else{return j.apply(this,arguments)}}var A=this;var z;d.each(a,function(D,C){if(u){if(A.is(D)){z=D}}else{d.each(C.chars,function(E,F){if(A.is(F.selector)){z=F.selector}})}});d.each(i,function(C,D){if(D.selector==z){if(u){D.properties[x]=y}else{if(B){D.properties[v]=y}}}});b(i);k()}else{return j.apply(this,arguments)}};d.templateLayoutShowOnReady=function(){document.write("<style> body {visibility:hidden} </style>");q=true};d.setTemplateLayout=function(v,u){if(l()){p();return false}setTimeout(function(){d(window).resize(k)},100);if(typeof v=="string"){v={file:v}}if(u){v.prefix=u}if(v){if(v.prefix){o="-"+v.prefix+"-"}if(v.delay){r=v.delay}if(v.fallback){d("."+v.fallback).remove()}}if(!v){n()}else{e="";if(v.text){e=v.text;d("head").append("<style>"+e+"</style>")}if(v.file){d.get(v.file,function(w){e+=w;k()})}if(!v.file&&!e){n();return false}if(e){k()}}};d.redoTemplateLayout=k;function p(){if(q){d("body").css("visibility","visible");q=false}}function n(){var u=d("style");if(!u.length){return}if(u.text()){e=u.text();k()}else{d.get(document.location.href,function(w){var v=w.match(/<style.*?>([\s\S]*?)<\/style>/);e=v?v[1]:"";k()})}}function f(){e=e.replace(/\/\*[\s\S]*?\*\//g,"");var u=e.split("}");d.each(u,function(){var x=d.trim(this);if(!x){return}var v=h(x);if(!v){return}if(v.selector.indexOf(",")!=-1){var w=v.selector.split(",");d.each(w,function(y,z){i.push({selector:d.trim(z),properties:v.properties})})}else{i.push(v)}});return i}function h(y){if(y.indexOf("@")===0||y.indexOf("{")==-1){return false}var x=y.split("{");var w=d.trim(x[0]);var u=x[1].split(";");var v={};d.each(u,function(){var A=this.split(":");var z=d.trim(A[0]).toLowerCase();var B=d.trim(A[1]);v[z]=B});return{selector:w,properties:v}}function g(F){var C=F.replace(/\n|\r/g," ");var D=C.split('"');var I=[];var w=[];var z={};for(var y=2,x=D.length;y<x;y+=2){var u=D[y];var H="auto";if(u.indexOf("/")!=-1){var E=u.match(/\/\s*(\S+)(.*)/);H=d.trim(E[1])}if(d.trim(u)&&y==x-1){var G=d.trim(D[x-1]).replace(/^\/\s*\S+\s*/,"");if(G&&G.indexOf("/")==-1){if(G.indexOf("(")!=-1){var v=G.match(/minmax(\(.*?\))/g);d.each(v,function(K,J){var L=J.replace(/\s*/g,"");G=G.replace(J,L)})}G=G.replace(/\(\)/,"");w=G.split(/\s+/)}}var B=D[y-1].replace(/[^a-z@\.]/gi,"");B=d.trim(B).split("");d.each(B,function(){z[this]=true});if(H.indexOf("-")==0){return false}I.push({chars:B,height:H})}var A=I[0].chars.length;while(w.length>A){w.pop()}while(w.length<A){w.push("*")}return{rows:I,widths:w,chars:z}}function b(y){var x={};var v={};var u=0;var w=[];d.each(y,function(z,K){var I=K.properties;var D=K.selector;var A=o+"display";var C=o+"position";var G=false;if(D.indexOf("::slot(")!=-1){var H=D.match(/slot\((.)\)/);if(H&&H.length>1){var B=H[1];var J=D.split("::slot")[0];var F={};d.each(I,function(M,N){if(M.indexOf("background")==0||M.indexOf("overflow")!=-1||M.indexOf("vertical-align")!=-1){F[M]=N}});v[J+"|"+B]=F}}if(I[C]&&I[C].length==1){var E=I[C];x[D]={chr:E,props:I};G=true}else{if(I[C]=="same"){c.push(D)}}if(I[A]&&I[A].indexOf('"')!=-1){var L=g(I[A]);if(!L){return}w.push({sel:D,rows:L.rows,widths:L.widths,chars:L.chars,properties:I,pseudo_props:{},num:u,slotEl:G});u++}});w.sort(function(A,z){return !z.slotEl});d.each(w,function(A,z){a[z.sel]=z});d.each(x,function(D,F){var B=false;var E=false;d.each(a,function(G,I){if(G==D){x[G].tplEl=true}if(!I.chars[F.chr]){return}var H=d(D).parents();if(H.is(G)){var K;var J=0;H.each(function(){if(H[J]==d(G)[0]){K=J}J++});if(B===false||K<B){B=K;E=G}}});var z=F.tplEl||false;if(E){var A=E+"|"+F.chr;var C=v[A]||false;a[E].chars[F.chr]={selector:D,props:F.props,pseudo_props:C,tplEl:z,cur_sel:E}}})}function l(){var x='"@"';var w=d("<p></p>");var u=true;try{w.get(0).style.display=x}catch(v){u=false}u=(w.css("display")==x);w.remove();return u}function t(R,O){var Q=R.widths;var D=R.rows;var G=R.properties;var E=[],P=[];var x=d(O);var F=R.chars;d.each(F,function(S,T){if(T!==true){T.slot_w=1;T.slot_h=1}});R.margins=0;function K(V,U){var S=[];d.each(F,function(Y,Z){var X=Z.props.width||"auto";if(Z.col==V&&Z.slot_w==1){var W=A({width:X,top:"auto",left:"auto"},Z.el.clone()).w;S.push(W)}});var T=U.split("-")[0];return Math[T].apply({},S)}function A(V,T){var S=d("<div></div>");S.css({visibility:"hidden",margin:0,padding:0,position:"absolute"});if(T){S.append(T)}if(V){S.css(V)}x.append(S);var U={w:S.width(),h:S.height()};S.remove();return U}function H(V,T,X){var U="auto",S="auto";if(V=="h"){S=T}else{U=T;if(U=="min-content"||U=="max-content"){return K(X,U)}}var W=A({height:S,width:U});return W[V]}function I(V){var T=0;for(var U=V.row;U<V.slot_h+V.row&&U<P.length;U++){T+=P[U]}var S=parseInt(V.el.css("margin-top"));if(S<0){T-=S}return T}function M(T,S,V){var W=F[S].props[T]+"";var U=W;if(W.indexOf("%")!=-1&&T=="width"){U=V*parseInt(W)/100}return U}function y(X){var W=0;for(var T=X.col;T<X.slot_w+X.col;T++){W+=E[T]}var V=X.el.outerWidth(true)-X.el.width();if(V){W-=V}if(X.tplEl){if(D[X.row].height&&D[X.row].height!="*"){a[X.selector].properties.height=D[X.row].height}a[X.selector].properties.width=W;var U=new t(a[X.selector],X.selector);var S=U.make();X.genHeight=S.height;return S.width}return W}function w(T){var S=T.css("border-top-width");var U=T.clone();U.each(function(){d(this).css("position","static")});return A(0,U).h}function C(){if(R.slotEl){G.height=x.height()}if(G.height){x.height(G.height);var S=x.height()}else{var U=0}var V=0;var T=[];d.each(D,function(Y,Z){var X=0;d.each(F,function(ad,ae){if(ae.row==Y){if(ae.props.height){ae.el.height(ae.props.height)}else{ae.el.height("auto")}if(!T[Y]){T[Y]=0}var ac;if(ae.genHeight){ac=ae.genHeight}else{if(ae.slot_h==1){ac=w(ae.el)}else{var ab=w(ae.el)/ae.slot_h;for(var aa=Y;aa<ae.slot_h;aa++){T[aa]=ab}}}if(X<T[Y]){X=T[Y]}if(X<ac){X=ac}}});if(G.height&&G.height!="auto"){V++;X=0}else{if(Z.height!="*"&&Z.height!="auto"){X=H("h",Z.height)}}P[Y]=X;U+=X});if(V){var W=S/V;d.each(D,function(X,Y){if(Y.height=="*"||Y.height=="auto"){P[X]=W}})}else{x.height(U)}}function L(){var W=0;var V=0;if(R.slotEl){x.width(x.width())}x.width(G.width||"100%");var U=x.width();E=[];var T=0;d.each(Q,function(aa,Y){if(Y=="fit-content"){Y=Q[aa]="minmax(min-content,max-content)"}if(Y=="*"||Y=="auto"){V++;W=0}else{if(Y.indexOf("minmax")===0){var ab=Y.match(/\((.*?),(.*?)\)/);var Z=ab[1];var X=ab[2];W=H("w",X,aa);U-=W}else{W=H("w",Y,aa);U-=W}}E.push(W);T+=W});if(U<0){d.each(Q,function(aa,Y){if(Y.indexOf("minmax")!=-1){var ab=Y.match(/\((.*?),(.*?)\)/);var Z=ab[1];var X=ab[2];min_pixels=H("w",Z,aa);E[aa]+=U;U=0;if(E[aa]<min_pixels){E[aa]=min_pixels}}})}var S=U/V;d.each(Q,function(Y,X){if(X=="*"||X=="auto"){E[Y]=S}})}function v(V,U){var S=U||0;var T=V.row;if(F["@"]&&!V.isHolder){S=-1*H("h",x.css("top"))}d.each(P,function(W){if(W<T){S+=this}});return S}function N(U){var T=U.col;var S=0;if(F["@"]&&!U.isHolder){S=-1*H("w",x.css("left"))}d.each(E,function(V){if(V<T){S+=this}});return S}function u(S){d.each(c,function(T,V){var U=d(V);U.each(function(){var X=d(this);var W=false;S.el.each(function(){var Y=d(this);if(!W){W=Y}else{W[W.length++]=Y[0]}if(Y.next()[0]==X[0]){W[W.length++]=X[0]}});if(W.length>1){S.el=W;S.multi=true}})})}function z(){var S=false;var U={};if(x.is("body")){return}d.each(G,function(X,Y){if(X.indexOf("background")===0){S=true;U[X]=Y}});if(!S){return}var W="jq_tpl_bg-"+R.num;var V=x.offset();var T=d("#"+W);if(!T.length){T=d('<div id="'+W+'"></div>');T.css(U)}T.css({"z-index":-2,position:"absolute",top:V.top,left:V.left,width:x.width(),height:x.height()});d("body").append(T)}function B(V,aa){if(aa.pseudo_props){var U=aa.el.offset();var T="jq_tpl"+R.num+"_slot-"+V;var ab=d("#"+T);var X=aa.pseudo_props;if(!ab.length){ab=d('<div id="'+T+'"></div>');d("body").append(ab)}var ac=aa.el.outerWidth(true);var W=I(aa);ab.css({display:"block",position:"absolute","z-index":(R.num-10),top:U.top,left:U.left,width:ac,height:W});if(d("body").is(O)){if(!R.margins){var S=d('<p style="position:static;margin:0;display:block;visibility:hidden;"></p>');x.append(S);R.margins=S.offset();R.margins.left-=parseFloat(x.css("padding-left"));R.margins.top-=parseFloat(x.css("padding-top"));S.remove()}ab.css("left",U.left-R.margins.left);ab.css("top",U.top-R.margins.top)}ab.css(X);if(X["vertical-align"]){var Z=0;var Y=X["vertical-align"];switch(Y){case"middle":Z=W/2-aa.el.height()/2;break;case"bottom":Z=W-aa.el.height();break;case"baseline":Z=W-aa.el.height();break;default:break}aa.el.css("top",v(aa)+Z)}}}function J(){d.each(D,function(S,T){d.each(T.chars,function(U,V){if(V=="."){return}if(V=="@"){F["@"]={selector:O,isHolder:true}}var W=F[V];W.el=d(W.selector);if(U>0&&T.chars[U-1]==V){if(W.slot_h==1){W.slot_w++}}if(S>0&&D[S-1].chars[U]==V){W.slot_h++}if(isNaN(W.row)){W.row=S}if(isNaN(W.col)){W.col=U}if(!W.el.parents().is(O)&&!W.el.is(O)){delete W;return}if(W.el.length>1){W.multi=true}u(W)})});delete F["."]}this.make=function(){x.css("position","relative");J();L();if(F["@"]){F["@"].el.css("left",N(F["@"]))}d.each(F,function(U,V){var T=V.el;var S=y(V);if(V.props.width){S=M("width",U,S)}T.css({display:"block",position:"absolute",width:S});T.css("left",N(V))});C();if(F["@"]){F["@"].el.css("top",v(F["@"]))}d.each(F,function(U,X){if(X.tplEl){a[X.selector].genTop=v(X)}var T=v(X);var W=I(X);var S=T;var V=false;if(X.pseudo_props){if(X.pseudo_props.overflow=="hidden"){V=true}}X.el.each(function(Y){if(Y>0){S+=X.el.eq(Y-1).outerHeight(true)}d(this).css("top",S);if(X.props.height){W=M("height",U,W);d(this).height(W)}if(V){var Z=W-S+T;var ab=(S-T>W);var aa=(X.el.height()+S-T>W);if(ab||aa){d(this).height(ab?0:Z);d(this).css("overflow","hidden")}}});if(X.tplEl){X.el.height(I(X))}B(U,X)});z();if(R.genTop&&F["@"]){F["@"].el.css("top",v(F["@"],R.genTop))}return{height:x.height(),width:x.width()}}}function m(w,u){var v=new t(u,w);v.make()}function k(){if(!a){a={};i=f();var u={};b(i)}setTimeout(function(){d.each(a,m);p()},r);r=0}})(jQuery);
|
@@ -0,0 +1,1049 @@
|
|
1
|
+
/*!
|
2
|
+
* templateLayout.compiler module
|
3
|
+
* Copyright (c) 2011 Pablo Escalada
|
4
|
+
*
|
5
|
+
* Contributor(s):
|
6
|
+
* César Acebal
|
7
|
+
*
|
8
|
+
* MIT Licensed
|
9
|
+
*/
|
10
|
+
(function (templateLayout) {
|
11
|
+
var compiler, log, rootTemplate;
|
12
|
+
log = wef.logger("templateLayout.compiler");
|
13
|
+
log.info("load compiler module");
|
14
|
+
|
15
|
+
function parseDisplay(displayValue) {
|
16
|
+
/*
|
17
|
+
* Name: ‘display’
|
18
|
+
* New value: <display-type>? && [ [ <string> [ / <row-height> ]? ]+ ] <col-width>*
|
19
|
+
* Percentages: N/A
|
20
|
+
* Computed value: specified value
|
21
|
+
*
|
22
|
+
* The <display-type> is one of the following keywords. An omitted keyword is equivalent to ‘block’.
|
23
|
+
* <display-type> = inline | block | list-item | inline-block | table | inline-table
|
24
|
+
* | table-row-group | table-header-group | table-footer-group | table-row
|
25
|
+
* | table-column-group | table-column | table-cell | table-caption | none
|
26
|
+
*
|
27
|
+
* Each <string> consist of one or more at signs (“@”), letters (or digits, see <letter> below),
|
28
|
+
* periods (“.”) and spaces
|
29
|
+
*
|
30
|
+
* Each <row-height> sets the height of the preceding row. The default is ‘auto’.
|
31
|
+
* The values can be as follows:
|
32
|
+
* <length> An explicit height for that row. Negative values make the template illegal. If the length is
|
33
|
+
* expressed in ‘gr’ units, these refer to the inherited grid, not the grid defined by the template itself.
|
34
|
+
* auto The row's height is determined by its contents.
|
35
|
+
* * (asterisk) All rows with an asterisk will be of equal height.
|
36
|
+
*
|
37
|
+
* Each <col-width> can be one of the following:
|
38
|
+
* <length> An explicit width for that column. Negative values make the template illegal.
|
39
|
+
* * (asterisk.) All columns with a ‘*’ have the same width. See the algorithm below.
|
40
|
+
* max-content, min-content, minmax(p,q), fit-content
|
41
|
+
*/
|
42
|
+
log.info("compiling display...");
|
43
|
+
log.debug("display source: ", displayValue);
|
44
|
+
/**
|
45
|
+
* @namespace Preprocessed template display info
|
46
|
+
* @name DisplayMetadata
|
47
|
+
*/
|
48
|
+
var displayMetadata =
|
49
|
+
/**
|
50
|
+
* @lends DisplayMetadata#
|
51
|
+
*/
|
52
|
+
{
|
53
|
+
/**
|
54
|
+
* Display type. Currently unused
|
55
|
+
* @type string
|
56
|
+
*/
|
57
|
+
displayType:undefined,
|
58
|
+
/**
|
59
|
+
* Array of rows. strings are cleaned
|
60
|
+
* @type string[]
|
61
|
+
*/
|
62
|
+
grid:[],
|
63
|
+
/**
|
64
|
+
* Array of columnns widths
|
65
|
+
* @type string[]
|
66
|
+
*/
|
67
|
+
widths:[]
|
68
|
+
},
|
69
|
+
allRefExp = /\s*(none|inline)?\s*(:?(\"[A-Za-z0-9\.@ ]+\")\s*(:?\/ ?(\*|\d+(:?px|%)))?)\s*((:?(:?(:?\d+(:?px|%))|\*)\s*)*)/gi,
|
70
|
+
found,
|
71
|
+
displayTypeFound,
|
72
|
+
gridNotFound,
|
73
|
+
completed;
|
74
|
+
//all without displayType (:?(\"[A-Za-z0-9\.@ ]+\")\s*(:?\/(\*|\d+(:?em|px|%)))?\s*)((:?(:?(:?\d+(:?em|px|%))|\*) *)*)
|
75
|
+
// /\s*(inline|block|list-item|inline-block|table|inline-table|table-row-group|table-header-group|table-footer-group|table-row|table-column-group|table-column|table-cell|table-caption|none)?\s*(:?(\"[A-Za-z0-9\.@ ]+\")\s*(:?\/(\*|\d+(:?em|px|%)))?\s*)((:?(:?(:?\d+(:?em|px|%))|\*) *)*)/g
|
76
|
+
if (displayValue !== undefined) {
|
77
|
+
while ((found = allRefExp.exec(displayValue)) !== null) {
|
78
|
+
if (completed) {
|
79
|
+
log.error("Invalid template, invalid width definition");
|
80
|
+
throw new Error("Invalid template, width definition");
|
81
|
+
}
|
82
|
+
if (found[1]) {
|
83
|
+
if (displayTypeFound) {
|
84
|
+
log.error("Invalid template, multiple display type");
|
85
|
+
throw new Error("Invalid template, multiple display type");
|
86
|
+
}
|
87
|
+
displayMetadata.displayType = found[1];
|
88
|
+
displayTypeFound = true;
|
89
|
+
}
|
90
|
+
if (found[3]) {
|
91
|
+
if (gridNotFound) {
|
92
|
+
log.error("Invalid template, invalid grid definition");
|
93
|
+
throw new Error("Invalid template, invalid grid definition");
|
94
|
+
}
|
95
|
+
displayMetadata.grid.push({rowText:found[3].replace(/"/g, "").replace(/\s*/, ""), height:undefined});
|
96
|
+
} else {
|
97
|
+
gridNotFound = true;
|
98
|
+
}
|
99
|
+
if (found[5]) {
|
100
|
+
if (!displayMetadata.grid[displayMetadata.grid.length - 1]) {
|
101
|
+
log.error("Invalid template, invalid height definition");
|
102
|
+
throw new Error("Invalid template, height definition");
|
103
|
+
}
|
104
|
+
displayMetadata.grid[displayMetadata.grid.length - 1].height = found[5];
|
105
|
+
}
|
106
|
+
if (found[7]) {
|
107
|
+
displayMetadata.widths = found[7].split(/\s+/);
|
108
|
+
completed = true;
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
log.info("display result: ", displayMetadata);
|
113
|
+
return displayMetadata;
|
114
|
+
}
|
115
|
+
|
116
|
+
/**
|
117
|
+
* @namespace Top level template. Used as "fake page template"
|
118
|
+
*/
|
119
|
+
rootTemplate = function () {
|
120
|
+
|
121
|
+
var that =
|
122
|
+
/**
|
123
|
+
* @lends rootTemplate#
|
124
|
+
*/
|
125
|
+
{
|
126
|
+
/**
|
127
|
+
* Inserts given template into TOM.
|
128
|
+
* If template "isRoot", inserts here, else looks inside TOM and
|
129
|
+
* inserts in place.
|
130
|
+
*
|
131
|
+
* @param {Template}aTemplate the template
|
132
|
+
*/
|
133
|
+
insert:function (aTemplate) {
|
134
|
+
log.info("add template ", aTemplate.selectorText);
|
135
|
+
if (aTemplate.isRoot()) {
|
136
|
+
log.debug("insert as root", aTemplate);
|
137
|
+
that.rows.push(aTemplate);
|
138
|
+
return true;
|
139
|
+
} else {
|
140
|
+
log.debug("search position :", aTemplate.position.position);
|
141
|
+
return that.rows.some(function (element) {
|
142
|
+
return element.insert(aTemplate);
|
143
|
+
});
|
144
|
+
}
|
145
|
+
},
|
146
|
+
/**
|
147
|
+
* Templates stored into the root template
|
148
|
+
* @type gridRow[]
|
149
|
+
*/
|
150
|
+
rows:[]
|
151
|
+
};
|
152
|
+
|
153
|
+
return that;
|
154
|
+
}();
|
155
|
+
|
156
|
+
function parsePosition(positionValue) {
|
157
|
+
var positionMetadata, matched, positionRegExp;
|
158
|
+
/*
|
159
|
+
* Name: position
|
160
|
+
* New value: <letter> | same
|
161
|
+
* Percentages: N/A
|
162
|
+
* Computed value: ‘<letter>’ or ‘static’; see text
|
163
|
+
*
|
164
|
+
* <letter> must be a single letter or digit, with category Lu, Ll, Lt or Nd in Unicode [UNICODE]),
|
165
|
+
* or a “@” symbol
|
166
|
+
*/
|
167
|
+
log.info("compiling position...");
|
168
|
+
log.debug("position source: ", positionValue);
|
169
|
+
/**
|
170
|
+
* @namespace Preprocessed template position info
|
171
|
+
* @name PositionMetadata
|
172
|
+
*/
|
173
|
+
positionMetadata =
|
174
|
+
/**
|
175
|
+
* @lends PositionMetadata#
|
176
|
+
*/
|
177
|
+
{
|
178
|
+
/**
|
179
|
+
* Position string
|
180
|
+
* @type string
|
181
|
+
*/
|
182
|
+
position:null
|
183
|
+
};
|
184
|
+
positionRegExp = /^\s*(same|[a-zA-Z0-9])\s*$/i;
|
185
|
+
if (positionValue !== undefined) {
|
186
|
+
matched = positionValue.match(positionRegExp);
|
187
|
+
if (matched === null) {
|
188
|
+
log.info("Unexpected value at ", positionValue);
|
189
|
+
//throw new Error("Unexpected value at ", positionValue);
|
190
|
+
return positionMetadata;
|
191
|
+
}
|
192
|
+
positionMetadata.position = matched[1];
|
193
|
+
}
|
194
|
+
log.info("position result: ", positionMetadata);
|
195
|
+
return positionMetadata;
|
196
|
+
}
|
197
|
+
|
198
|
+
function parseProperties(rule) {
|
199
|
+
var preProcessTemplate = {};
|
200
|
+
log.info("compiling properties...");
|
201
|
+
log.debug("properties source: ", rule);
|
202
|
+
preProcessTemplate.selectorText = rule.selectorText;
|
203
|
+
preProcessTemplate.display = parseDisplay(rule.declaration[templateLayout.fn.constants.DISPLAY]);
|
204
|
+
preProcessTemplate.position = parsePosition(rule.declaration[templateLayout.fn.constants.POSITION]);
|
205
|
+
log.info("properties result: ", preProcessTemplate);
|
206
|
+
return preProcessTemplate;
|
207
|
+
}
|
208
|
+
|
209
|
+
/**
|
210
|
+
* Creates a compiler
|
211
|
+
*
|
212
|
+
* @class CSS template compiler
|
213
|
+
*/
|
214
|
+
compiler = function () {
|
215
|
+
return new compiler.prototype.init();
|
216
|
+
};
|
217
|
+
|
218
|
+
/**
|
219
|
+
* Extension point.
|
220
|
+
* Elements added to compiler.fn extend compiler functionality
|
221
|
+
*/
|
222
|
+
compiler.fn = compiler.prototype;
|
223
|
+
|
224
|
+
compiler.prototype = {
|
225
|
+
constructor:compiler,
|
226
|
+
/**
|
227
|
+
* @ignore
|
228
|
+
*/
|
229
|
+
init:function () {
|
230
|
+
return this;
|
231
|
+
},
|
232
|
+
/**
|
233
|
+
* Compiles given parser data</p>
|
234
|
+
*
|
235
|
+
* @param {ParserBufferEntry[]}buffer parser generated data
|
236
|
+
* @returns {rootTemplate} Template Object Model
|
237
|
+
*/
|
238
|
+
compile:function (buffer) {
|
239
|
+
var selectorText, preProcessTemplate, inserted, template;
|
240
|
+
log.info("compile...");
|
241
|
+
log.debug("buffer: ", buffer);
|
242
|
+
|
243
|
+
for (selectorText in buffer) {
|
244
|
+
if (buffer.hasOwnProperty(selectorText)) {
|
245
|
+
log.debug("next buffer element: ", selectorText);
|
246
|
+
log.group();
|
247
|
+
preProcessTemplate = parseProperties(buffer[selectorText]);
|
248
|
+
if (this.isEmptyDisplay(preProcessTemplate.display) && this.isEmptyPosition(preProcessTemplate.position)) {
|
249
|
+
log.groupEnd();
|
250
|
+
log.info("preProcess: empty template", preProcessTemplate);
|
251
|
+
} else {
|
252
|
+
log.debug("preProcess:", preProcessTemplate);
|
253
|
+
template = compiler.fn.templateBuilder(preProcessTemplate).createTemplate();
|
254
|
+
inserted = rootTemplate.insert(template);
|
255
|
+
log.groupEnd();
|
256
|
+
log.info("element insertion...", inserted ? "[OK]" : "ERROR!");
|
257
|
+
}
|
258
|
+
}
|
259
|
+
}
|
260
|
+
log.debug("compile... OK");
|
261
|
+
return rootTemplate;
|
262
|
+
},
|
263
|
+
/**
|
264
|
+
* Checks if display is empty
|
265
|
+
* @param {DisplayMetadata}display compiled display
|
266
|
+
* @returns {boolean}true if display.grid.length === 0
|
267
|
+
*/
|
268
|
+
isEmptyDisplay:function (display) {
|
269
|
+
return display.grid.length === 0;
|
270
|
+
},
|
271
|
+
/**
|
272
|
+
* Checks is position is empty
|
273
|
+
* @param {PositionMetadata}position compiled position
|
274
|
+
* @returns {boolean}true if position.position === null
|
275
|
+
*/
|
276
|
+
isEmptyPosition:function (position) {
|
277
|
+
return position.position === null;
|
278
|
+
}
|
279
|
+
};
|
280
|
+
|
281
|
+
compiler.prototype.init.prototype = compiler.prototype;
|
282
|
+
|
283
|
+
templateLayout.fn.compiler = compiler;
|
284
|
+
|
285
|
+
(function (global) {
|
286
|
+
var gridSlot;
|
287
|
+
log.info("load gridSlot module...");
|
288
|
+
|
289
|
+
/**
|
290
|
+
* Creates a slot.
|
291
|
+
*
|
292
|
+
* @param {string}slotText slot identifier
|
293
|
+
* @param {integer}rowIndex row index
|
294
|
+
* @param {integer}colIndex column index
|
295
|
+
* @param {Object}[options] optional initialization
|
296
|
+
* @param {integer}options.rowSpan row span number
|
297
|
+
* @param {integer}options.colSpan column span number
|
298
|
+
* @param {boolean}options.allowDisconnected row span number
|
299
|
+
* @param {boolean}options.allowColSpan row span number
|
300
|
+
* @param {boolean}options.allowRowSpan row span number
|
301
|
+
*
|
302
|
+
* @class Template slot.
|
303
|
+
* Features:
|
304
|
+
* <ul>
|
305
|
+
* <li>column and row span</li>
|
306
|
+
* <li>disconnected regions</li>
|
307
|
+
* </ul>
|
308
|
+
*/
|
309
|
+
gridSlot = function (slotText, rowIndex, colIndex, options) {
|
310
|
+
log.debug("slot", slotText + "...");
|
311
|
+
return new gridSlot.prototype.init(slotText, rowIndex, colIndex, options);
|
312
|
+
};
|
313
|
+
|
314
|
+
gridSlot.prototype = {
|
315
|
+
constructor:gridSlot,
|
316
|
+
/**
|
317
|
+
* slot identifier
|
318
|
+
* @type string
|
319
|
+
*/
|
320
|
+
slotText:undefined,
|
321
|
+
/**
|
322
|
+
* row index. If row spans, topmost row index
|
323
|
+
* @type integer
|
324
|
+
*/
|
325
|
+
rowIndex:undefined,
|
326
|
+
/**
|
327
|
+
* column index. If column spans, leftmost column index
|
328
|
+
* @type integer
|
329
|
+
*/
|
330
|
+
colIndex:undefined,
|
331
|
+
/**
|
332
|
+
* row span number
|
333
|
+
* @type integer
|
334
|
+
*/
|
335
|
+
rowSpan:1,
|
336
|
+
/**
|
337
|
+
* column span number
|
338
|
+
* @type integer
|
339
|
+
*/
|
340
|
+
colSpan:1,
|
341
|
+
/**
|
342
|
+
* Can exists more than one group of slots with the same identifier?
|
343
|
+
* @type boolean
|
344
|
+
*/
|
345
|
+
allowDisconnected:false,
|
346
|
+
/**
|
347
|
+
* is column span allowed?
|
348
|
+
* @type boolean
|
349
|
+
*/
|
350
|
+
allowColSpan:false,
|
351
|
+
/**
|
352
|
+
* is row span allowed?
|
353
|
+
* @type boolean
|
354
|
+
*/
|
355
|
+
allowRowSpan:false,
|
356
|
+
/**
|
357
|
+
* HTML node that maps the slot
|
358
|
+
* @type HTMLElement
|
359
|
+
*/
|
360
|
+
htmlNode:undefined,
|
361
|
+
/**
|
362
|
+
* Stores the sum of children heights
|
363
|
+
* @type integer
|
364
|
+
*/
|
365
|
+
contentHeight:0,
|
366
|
+
|
367
|
+
/**
|
368
|
+
* @ignore
|
369
|
+
* see gridSlot.constructor
|
370
|
+
*/
|
371
|
+
init:function (slotText, rowIndex, colIndex, options) {
|
372
|
+
this.slotText = slotText;
|
373
|
+
this.rowIndex = rowIndex;
|
374
|
+
this.colIndex = colIndex;
|
375
|
+
this.contentHeight = 0;
|
376
|
+
//options
|
377
|
+
this.rowSpan = 1;
|
378
|
+
this.colSpan = 1;
|
379
|
+
this.height = "auto";
|
380
|
+
|
381
|
+
this.allowDisconnected = false;
|
382
|
+
this.allowColSpan = true;
|
383
|
+
this.allowRowSpan = true;
|
384
|
+
this.htmlNode = undefined;
|
385
|
+
wef.extend(this, options, ["rowSpan", "colSpan", "allowDisconnected", "allowColSpan", "allowRowSpan"]);
|
386
|
+
}
|
387
|
+
};
|
388
|
+
|
389
|
+
/**
|
390
|
+
* Extension point
|
391
|
+
*/
|
392
|
+
gridSlot.fn = gridSlot.prototype;
|
393
|
+
gridSlot.prototype.init.prototype = gridSlot.prototype;
|
394
|
+
|
395
|
+
global.gridSlot = gridSlot;
|
396
|
+
log.info("load gridSlot module... [OK]");
|
397
|
+
})(compiler.fn);
|
398
|
+
|
399
|
+
|
400
|
+
(function (global) {
|
401
|
+
var gridRow;
|
402
|
+
log.info("load gridRow module...");
|
403
|
+
/**
|
404
|
+
* Creates a row
|
405
|
+
*
|
406
|
+
* @param {string}rowText row slots identifiers
|
407
|
+
* @param {integer}rowIndex row index
|
408
|
+
* @param {gridSlot[]}slots row gridSlot elements
|
409
|
+
* @param {Object}[options] optional initialization
|
410
|
+
* @param {string}options.height row height as string
|
411
|
+
*
|
412
|
+
* @class Template row. Store {@link gridSlot} elements
|
413
|
+
*/
|
414
|
+
gridRow = function (rowText, rowIndex, slots, options) {
|
415
|
+
log.debug("row...");
|
416
|
+
return new gridRow.prototype.init(rowText, rowIndex, slots, options);
|
417
|
+
};
|
418
|
+
gridRow.prototype = {
|
419
|
+
constructor:gridRow,
|
420
|
+
/**
|
421
|
+
* Row slots identifiers
|
422
|
+
* @type string
|
423
|
+
*/
|
424
|
+
rowText:undefined,
|
425
|
+
/**
|
426
|
+
* Row index
|
427
|
+
* @type integer
|
428
|
+
*/
|
429
|
+
rowIndex:undefined,
|
430
|
+
/**
|
431
|
+
* Slots row gridSlot elements
|
432
|
+
* @type gridSlot[]
|
433
|
+
*/
|
434
|
+
slots:[],
|
435
|
+
/**
|
436
|
+
* Number of slots in row
|
437
|
+
* @type integer
|
438
|
+
*/
|
439
|
+
length:undefined,
|
440
|
+
/**
|
441
|
+
* Row height as string
|
442
|
+
* @type string
|
443
|
+
*/
|
444
|
+
height:undefined,
|
445
|
+
/**
|
446
|
+
* @ignore
|
447
|
+
* see constructor
|
448
|
+
*/
|
449
|
+
init:function (rowText, rowIndex, slots, options) {
|
450
|
+
this.rowText = rowText;
|
451
|
+
this.rowIndex = rowIndex;
|
452
|
+
this.slots = slots;
|
453
|
+
this.length = this.rowText.length;
|
454
|
+
//options
|
455
|
+
this.height = undefined;
|
456
|
+
wef.extend(this, options, ["height"]);
|
457
|
+
}
|
458
|
+
};
|
459
|
+
/**
|
460
|
+
* Extension point
|
461
|
+
*/
|
462
|
+
gridRow.fn = gridRow.prototype;
|
463
|
+
gridRow.prototype.init.prototype = gridRow.prototype;
|
464
|
+
|
465
|
+
global.gridRow = gridRow;
|
466
|
+
log.info("load gridRow module... [OK]");
|
467
|
+
})(compiler.fn);
|
468
|
+
|
469
|
+
|
470
|
+
(function (global) {
|
471
|
+
var grid;
|
472
|
+
log.info("load grid module...");
|
473
|
+
/**
|
474
|
+
* Creates a template grid
|
475
|
+
*
|
476
|
+
* @param {gridRow[]}rows template rows
|
477
|
+
* @param [options] optional initialization
|
478
|
+
*
|
479
|
+
* @class Template grid, represented as a tabular structure
|
480
|
+
*/
|
481
|
+
grid = function (rows, options) {
|
482
|
+
log.debug("grid...");
|
483
|
+
return new grid.prototype.init(rows, options);
|
484
|
+
};
|
485
|
+
|
486
|
+
grid.prototype = {
|
487
|
+
constructor:grid,
|
488
|
+
/**
|
489
|
+
* Template rows
|
490
|
+
* @type gridRow[]
|
491
|
+
*/
|
492
|
+
rows:undefined,
|
493
|
+
/**
|
494
|
+
* Hash table like structure that stores nested Template objects.
|
495
|
+
* <ul>
|
496
|
+
* <li>key = template position</li>
|
497
|
+
* <li>value = array of template objects</li>
|
498
|
+
* <ul>
|
499
|
+
*
|
500
|
+
* @type Object
|
501
|
+
*/
|
502
|
+
filledSlots:undefined,
|
503
|
+
/**
|
504
|
+
* columns widths
|
505
|
+
* @type string[]
|
506
|
+
*/
|
507
|
+
widths:[],
|
508
|
+
/**
|
509
|
+
* minimums columns widths
|
510
|
+
* @type string[]
|
511
|
+
*/
|
512
|
+
minWidths:[],
|
513
|
+
/**
|
514
|
+
* preferred columns widths
|
515
|
+
* @type string[]
|
516
|
+
*/
|
517
|
+
preferredWidths:[],
|
518
|
+
/**
|
519
|
+
* Number of rows
|
520
|
+
* @type integer
|
521
|
+
*/
|
522
|
+
rowNumber:undefined,
|
523
|
+
/**
|
524
|
+
* Number of columns
|
525
|
+
* @type integer
|
526
|
+
*/
|
527
|
+
colNumber:undefined,
|
528
|
+
/**
|
529
|
+
* @ignore
|
530
|
+
*/
|
531
|
+
init:function (rows, options) {
|
532
|
+
this.rows = rows;
|
533
|
+
this.filledSlots = {};
|
534
|
+
//options
|
535
|
+
this.widths = [];
|
536
|
+
this.minWidths = [];
|
537
|
+
this.preferredWidths = [];
|
538
|
+
wef.extend(this, options, ["widths", "minWidths", "preferredWidths"]);
|
539
|
+
this.colNumber = this.widths.length;
|
540
|
+
this.rowNumber = rows.length;
|
541
|
+
},
|
542
|
+
/**
|
543
|
+
* Checks if grid contains specified slot identifier
|
544
|
+
*
|
545
|
+
* @param {string}slotIdentifier slot identifier
|
546
|
+
* @returns {boolean} true if rows[i].rowText contains slotIdentifier,
|
547
|
+
* else if not
|
548
|
+
*/
|
549
|
+
hasSlot:function hasSlot(slotIdentifier) {
|
550
|
+
var result;
|
551
|
+
result = this.rows.some(function (row) {
|
552
|
+
var regExp = new RegExp(slotIdentifier);
|
553
|
+
return regExp.exec(row.rowText);
|
554
|
+
});
|
555
|
+
log.debug("hasSlot " + slotIdentifier + "?", result ? "yes" : "no");
|
556
|
+
return result;
|
557
|
+
},
|
558
|
+
/**
|
559
|
+
* Gets the "@" slot OR topmost left slot
|
560
|
+
*/
|
561
|
+
getDefaultSlot:function () {
|
562
|
+
var firstLetterSlot, definedDefaultSlot = false;
|
563
|
+
this.rows.forEach(function (row) {
|
564
|
+
if (definedDefaultSlot) {
|
565
|
+
return; //skip row
|
566
|
+
}
|
567
|
+
Array.prototype.some.call(row.rowText, function (slotText, slotIndex) {
|
568
|
+
if (slotText === "@") {
|
569
|
+
definedDefaultSlot = row.slots[slotIndex];
|
570
|
+
return true;
|
571
|
+
}
|
572
|
+
if (!firstLetterSlot && slotText !== ".") {
|
573
|
+
firstLetterSlot = row.slots[slotIndex];
|
574
|
+
return false; //continue searching @
|
575
|
+
}
|
576
|
+
});
|
577
|
+
});
|
578
|
+
return definedDefaultSlot || firstLetterSlot;
|
579
|
+
},
|
580
|
+
/**
|
581
|
+
* Traverses this grid and its children and insert the given
|
582
|
+
* template in place
|
583
|
+
* @param {template}aTemplate given template
|
584
|
+
* @returns {boolean} true if inserted, false if not
|
585
|
+
*/
|
586
|
+
setTemplate:function (aTemplate) {
|
587
|
+
var row, tmp, result;
|
588
|
+
if (this.hasSlot(aTemplate.position.position)) {
|
589
|
+
//push template
|
590
|
+
tmp = this.filledSlots[aTemplate.position.position] || [];
|
591
|
+
tmp.push(aTemplate);
|
592
|
+
this.filledSlots[aTemplate.position.position] = tmp;
|
593
|
+
log.debug("grid [" + aTemplate.position.position + "] =", aTemplate);
|
594
|
+
return true;
|
595
|
+
} else {
|
596
|
+
result = this.rows.some(function (row) {
|
597
|
+
var result;
|
598
|
+
result = row.slots.some(function (slotId) {
|
599
|
+
var result;
|
600
|
+
result = this.filledSlots[slotId.slotText] && this.filledSlots[slotId.slotText].some(function (currentTemplate) {
|
601
|
+
return !currentTemplate.isLeaf() && currentTemplate.insert(aTemplate);
|
602
|
+
}, this);
|
603
|
+
if (!result) {
|
604
|
+
log.debug("not found, try another slot");
|
605
|
+
}
|
606
|
+
return result;
|
607
|
+
}, this);
|
608
|
+
if (!result) {
|
609
|
+
log.debug("not found, try another row");
|
610
|
+
}
|
611
|
+
return result;
|
612
|
+
}, this);
|
613
|
+
if (!result) {
|
614
|
+
log.debug("not found, try another branch");
|
615
|
+
}
|
616
|
+
return result;
|
617
|
+
}
|
618
|
+
}
|
619
|
+
};
|
620
|
+
/**
|
621
|
+
* Extension point
|
622
|
+
*/
|
623
|
+
grid.fn = grid.prototype;
|
624
|
+
grid.prototype.init.prototype = grid.prototype;
|
625
|
+
|
626
|
+
global.grid = grid;
|
627
|
+
log.info("load grid module... [OK]");
|
628
|
+
})(compiler.fn);
|
629
|
+
|
630
|
+
(function (global) {
|
631
|
+
var template;
|
632
|
+
log.info("load template module...");
|
633
|
+
/**
|
634
|
+
* Creates a template
|
635
|
+
*
|
636
|
+
* @param {string}selectorText CSS selector
|
637
|
+
* @param {PositionMetadata}position raw position information
|
638
|
+
* @param {DisplayMetadata}display raw display information
|
639
|
+
* @param {grid}grid its physical structure
|
640
|
+
*
|
641
|
+
* @class A Template has a grid, the raw information generated by
|
642
|
+
* the preprocessor and a link to the DOM reference node
|
643
|
+
*/
|
644
|
+
template = function (selectorText, position, display, grid) {
|
645
|
+
log.debug("template...");
|
646
|
+
return new template.prototype.init(selectorText, position, display, grid);
|
647
|
+
};
|
648
|
+
|
649
|
+
template.prototype = {
|
650
|
+
constructor:template,
|
651
|
+
/**
|
652
|
+
* Link to parent template. Unused
|
653
|
+
*/
|
654
|
+
parentTemplate:undefined,
|
655
|
+
/**
|
656
|
+
* CSS selector
|
657
|
+
* @type string
|
658
|
+
*/
|
659
|
+
selectorText:undefined,
|
660
|
+
/**
|
661
|
+
* Raw display information
|
662
|
+
* @type DisplayMetadata
|
663
|
+
*/
|
664
|
+
display:undefined,
|
665
|
+
/**
|
666
|
+
* Raw position information
|
667
|
+
* @type PositionMetadata
|
668
|
+
*/
|
669
|
+
position:undefined,
|
670
|
+
/**
|
671
|
+
* Its grid, the physical representation
|
672
|
+
* @type grid
|
673
|
+
*/
|
674
|
+
grid:undefined,
|
675
|
+
/**
|
676
|
+
* A link to the DOM reference node
|
677
|
+
* @type HTMLElement
|
678
|
+
*/
|
679
|
+
htmlNode:undefined,
|
680
|
+
/**
|
681
|
+
* @ignore
|
682
|
+
*/
|
683
|
+
init:function (selectorText, position, display, grid) {
|
684
|
+
this.selectorText = selectorText;
|
685
|
+
this.display = display;
|
686
|
+
this.position = position;
|
687
|
+
this.grid = grid;
|
688
|
+
this.htmlNode = undefined;
|
689
|
+
},
|
690
|
+
/**
|
691
|
+
* Checks if has parent
|
692
|
+
*
|
693
|
+
* @returns {boolean} true if doesn't have a position value,
|
694
|
+
* false if not
|
695
|
+
*/
|
696
|
+
isRoot:function () {
|
697
|
+
return this.position.position === null;
|
698
|
+
},
|
699
|
+
/**
|
700
|
+
* Checks if has children
|
701
|
+
*
|
702
|
+
* @returns {boolean} true if has a grid value, false if not
|
703
|
+
*/
|
704
|
+
isLeaf:function () {
|
705
|
+
return this.display.grid.length === 0;
|
706
|
+
},
|
707
|
+
/**
|
708
|
+
* Insert given template in this template or its children.
|
709
|
+
* Calls grid.setTemplate()
|
710
|
+
*
|
711
|
+
* @param aTemplate given template
|
712
|
+
* @returns {boolean} true if inserted, false if not
|
713
|
+
*/
|
714
|
+
insert:function (aTemplate) {
|
715
|
+
log.debug("trying to insert into ", this);
|
716
|
+
return this.grid.setTemplate(aTemplate);
|
717
|
+
}
|
718
|
+
};
|
719
|
+
/**
|
720
|
+
* Extension point
|
721
|
+
*/
|
722
|
+
template.fn = template.prototype;
|
723
|
+
template.prototype.init.prototype = template.prototype;
|
724
|
+
|
725
|
+
global.template = template;
|
726
|
+
log.info("load template module... [OK]");
|
727
|
+
})(compiler.fn);
|
728
|
+
|
729
|
+
(function (global) {
|
730
|
+
var templateBuilder;
|
731
|
+
log.info("load templateBuilder module...");
|
732
|
+
|
733
|
+
/**
|
734
|
+
* Creates a gridBuffer
|
735
|
+
*
|
736
|
+
* @class {@link templateBuilder} temporal data structure.
|
737
|
+
* Only for internal use. Doesn´t check array index
|
738
|
+
* @name GridBuffer
|
739
|
+
*/
|
740
|
+
function GridBuffer() {
|
741
|
+
this._rows = [];
|
742
|
+
}
|
743
|
+
|
744
|
+
GridBuffer.prototype =
|
745
|
+
/**
|
746
|
+
* @lends GridBuffer#
|
747
|
+
*/
|
748
|
+
{
|
749
|
+
constructor:GridBuffer,
|
750
|
+
/**
|
751
|
+
* Array of rows
|
752
|
+
* @type gridRow[]
|
753
|
+
* @public
|
754
|
+
*/
|
755
|
+
_rows:[],
|
756
|
+
/**
|
757
|
+
* Add the slot to _rows
|
758
|
+
* @param {gridSlot}slot the slot
|
759
|
+
*/
|
760
|
+
add:function (slot) {
|
761
|
+
if (!Array.isArray(this._rows[slot.rowIndex])) {
|
762
|
+
this._rows[slot.rowIndex] = [];
|
763
|
+
}
|
764
|
+
this._rows[slot.rowIndex][slot.colIndex] = slot;
|
765
|
+
},
|
766
|
+
/**
|
767
|
+
* Gets the slot with the specified slot Text
|
768
|
+
* @param {string}slotText slot text
|
769
|
+
* @returns {gridSlot} the specified slot
|
770
|
+
*/
|
771
|
+
getSlot:function (slotText) {
|
772
|
+
var result = [];
|
773
|
+
this._rows.forEach(function (row) {
|
774
|
+
row.forEach(function (slot) {
|
775
|
+
if (slot.slotText === slotText) {
|
776
|
+
result.push(slot);
|
777
|
+
}
|
778
|
+
}, this);
|
779
|
+
}, this);
|
780
|
+
return result;
|
781
|
+
},
|
782
|
+
/**
|
783
|
+
* Gets rows
|
784
|
+
* @returns {gridRow[]} _rows
|
785
|
+
*/
|
786
|
+
getRows:function () {
|
787
|
+
return this._rows;
|
788
|
+
},
|
789
|
+
/**
|
790
|
+
* Gets the specified row in _rows
|
791
|
+
* @param index row index
|
792
|
+
* @returns {gridRow} the specified row
|
793
|
+
*/
|
794
|
+
getRow:function (index) {
|
795
|
+
return this._rows[index];
|
796
|
+
}
|
797
|
+
};
|
798
|
+
|
799
|
+
/**
|
800
|
+
* @class
|
801
|
+
*/
|
802
|
+
templateBuilder = function (source) {
|
803
|
+
log.debug("templateBuilder...");
|
804
|
+
return new templateBuilder.prototype.init(source);
|
805
|
+
};
|
806
|
+
|
807
|
+
templateBuilder.prototype = {
|
808
|
+
constructor:templateBuilder,
|
809
|
+
buffer:undefined,
|
810
|
+
source:undefined,
|
811
|
+
init:function (source) {
|
812
|
+
this.source = source;
|
813
|
+
this.buffer = new GridBuffer();
|
814
|
+
},
|
815
|
+
createTemplate:function () {
|
816
|
+
var display, grid, gridRows, gridOptions = {}, heights;
|
817
|
+
display = this.source.display;
|
818
|
+
grid = null;
|
819
|
+
if (display.grid.length > 0) {
|
820
|
+
this._addGrid(this.source.display);
|
821
|
+
|
822
|
+
heights = this._normalizeHeights(this.source.display);
|
823
|
+
gridRows = this.buffer.getRows().map(function (row, index) {
|
824
|
+
return compiler.fn.gridRow(this.source.display.grid[index].rowText, index, row, {height:heights[index]});
|
825
|
+
}, this);
|
826
|
+
|
827
|
+
gridOptions.widths = this._normalizeWidths(this.source.display.widths);
|
828
|
+
gridOptions.minWidths = gridOptions.widths.map(function (col) {
|
829
|
+
return templateBuilder.fn._getMinWidth(col);
|
830
|
+
});
|
831
|
+
gridOptions.preferredWidths = gridOptions.widths.map(function (col) {
|
832
|
+
return templateBuilder.fn._getPreferredWidth(col);
|
833
|
+
});
|
834
|
+
grid = compiler.fn.grid(gridRows, gridOptions);
|
835
|
+
} else {
|
836
|
+
//TODO:fixme
|
837
|
+
}
|
838
|
+
|
839
|
+
return compiler.fn.template(this.source.selectorText, this.source.position, display, grid);
|
840
|
+
},
|
841
|
+
_addGrid:function (display) {
|
842
|
+
if (display.grid.length > 0) {
|
843
|
+
display.grid.forEach(function (row, rowIndex) {
|
844
|
+
this._addGridRow(row, rowIndex);
|
845
|
+
}, this);
|
846
|
+
}
|
847
|
+
},
|
848
|
+
checkRowSpan:function (slotText, rowIndex, colIndex) {
|
849
|
+
var previousRow, oldRowSpan, candidateRowSpan, slotGroups;
|
850
|
+
slotGroups = this.buffer.getSlot(slotText);
|
851
|
+
if (!slotGroups[0].allowRowSpan) {
|
852
|
+
log.info("Slot don't allow row span");
|
853
|
+
return false;
|
854
|
+
}
|
855
|
+
|
856
|
+
if (rowIndex > 0) {
|
857
|
+
return slotGroups.some(function (slot) {
|
858
|
+
previousRow = this.source.display.grid[rowIndex - 1];
|
859
|
+
if (previousRow.rowText.charAt(colIndex) === slotText) {
|
860
|
+
oldRowSpan = slot.rowSpan;
|
861
|
+
candidateRowSpan = (rowIndex - slot.rowIndex) + 1;
|
862
|
+
if (candidateRowSpan == oldRowSpan) {
|
863
|
+
//do nothing
|
864
|
+
log.debug("Slot row span... [OK]");
|
865
|
+
return true;
|
866
|
+
}
|
867
|
+
if (candidateRowSpan == oldRowSpan + 1) {
|
868
|
+
slot.rowSpan++;
|
869
|
+
this.buffer.add(slot);
|
870
|
+
log.debug("Slot row span... [OK]");
|
871
|
+
return true;
|
872
|
+
} else {
|
873
|
+
return false;
|
874
|
+
}
|
875
|
+
} else {
|
876
|
+
return false;
|
877
|
+
}
|
878
|
+
}, this);
|
879
|
+
} else {
|
880
|
+
return false;
|
881
|
+
}
|
882
|
+
},
|
883
|
+
checkColSpan:function (slotText, row, colIndex) {
|
884
|
+
var slotGroups, oldColSpan, candidateColSpan;
|
885
|
+
slotGroups = this.buffer.getSlot(slotText);
|
886
|
+
if (!slotGroups[0].allowColSpan) {
|
887
|
+
log.info("Slot don't allow col span");
|
888
|
+
return false;
|
889
|
+
}
|
890
|
+
if (colIndex > 0) {
|
891
|
+
return slotGroups.some(function (slot) {
|
892
|
+
if (row.rowText[colIndex - 1] === slotText) {
|
893
|
+
oldColSpan = slot.colSpan;
|
894
|
+
candidateColSpan = (colIndex - slot.colIndex) + 1;
|
895
|
+
if (candidateColSpan == oldColSpan + 1) {
|
896
|
+
slot.colSpan++;
|
897
|
+
this.buffer.add(slot);
|
898
|
+
log.debug("Slot col span... [OK]");
|
899
|
+
return true;
|
900
|
+
} else {
|
901
|
+
return false;
|
902
|
+
}
|
903
|
+
} else {
|
904
|
+
return false;
|
905
|
+
}
|
906
|
+
}, this);
|
907
|
+
} else {
|
908
|
+
return false;
|
909
|
+
}
|
910
|
+
},
|
911
|
+
_addGridRow:function (row, rowIndex) {
|
912
|
+
var identifiers, colSpan, rowSpan, regions;
|
913
|
+
identifiers = Array.prototype.map.call(row.rowText, function (substring) {
|
914
|
+
return substring.charAt(0);
|
915
|
+
});
|
916
|
+
|
917
|
+
identifiers.forEach(function (slotText, colIndex) {
|
918
|
+
//slot doesn't exist
|
919
|
+
if (this.buffer.getSlot(slotText).length === 0) {
|
920
|
+
this._addGridSlot(slotText, rowIndex, colIndex, 1, 1);
|
921
|
+
return; //no span or region violations
|
922
|
+
}
|
923
|
+
|
924
|
+
if (this.buffer.getSlot(slotText)[0].allowColSpan) {
|
925
|
+
colSpan = this.checkColSpan(slotText, row, colIndex);
|
926
|
+
} else {
|
927
|
+
colSpan = false;
|
928
|
+
}
|
929
|
+
|
930
|
+
if (this.buffer.getSlot(slotText)[0].allowRowSpan) {
|
931
|
+
rowSpan = this.checkRowSpan(slotText, rowIndex, colIndex);
|
932
|
+
} else {
|
933
|
+
rowSpan = false;
|
934
|
+
}
|
935
|
+
|
936
|
+
if (this.buffer.getSlot(slotText)[0].allowDisconnected) {
|
937
|
+
//TODO: region check
|
938
|
+
log.info("Slot allow disconnected regions");
|
939
|
+
this._addGridSlot(slotText, rowIndex, colIndex, 1, 1);
|
940
|
+
regions = true;
|
941
|
+
} else {
|
942
|
+
regions = false;
|
943
|
+
}
|
944
|
+
|
945
|
+
if (!colSpan && !rowSpan && !regions) {
|
946
|
+
throw new Error("Invalid template definition at \"" + slotText + "\"");
|
947
|
+
}
|
948
|
+
|
949
|
+
}, this);
|
950
|
+
},
|
951
|
+
_addGridSlot:function (slotText, rowIndex, colIndex, rowSpan, colSpan) {
|
952
|
+
var options, allowDisconnected, allowColSpan, allowRowSpan;
|
953
|
+
|
954
|
+
if (slotText === ".") {
|
955
|
+
allowDisconnected = true;
|
956
|
+
allowColSpan = false;
|
957
|
+
allowRowSpan = false;
|
958
|
+
} else {
|
959
|
+
allowDisconnected = false;
|
960
|
+
allowColSpan = true;
|
961
|
+
allowRowSpan = true;
|
962
|
+
}
|
963
|
+
options = {
|
964
|
+
rowSpan:rowSpan,
|
965
|
+
colSpan:colSpan,
|
966
|
+
allowDisconnected:allowDisconnected,
|
967
|
+
allowColSpan:allowColSpan,
|
968
|
+
allowRowSpan:allowRowSpan
|
969
|
+
};
|
970
|
+
this.buffer.add(compiler.fn.gridSlot(slotText, rowIndex, colIndex, options));
|
971
|
+
},
|
972
|
+
_getMinWidth:function (width) {
|
973
|
+
if (width === "*") {
|
974
|
+
return "0px";
|
975
|
+
} else {
|
976
|
+
return width;
|
977
|
+
}
|
978
|
+
},
|
979
|
+
_getPreferredWidth:function (width) {
|
980
|
+
if (width === "*") {
|
981
|
+
return "9999px";
|
982
|
+
} else {
|
983
|
+
return width;
|
984
|
+
}
|
985
|
+
},
|
986
|
+
_normalizeWidths:function (widths) {
|
987
|
+
var i, tmp = [], dotColumn;
|
988
|
+
|
989
|
+
function checkDotColumn(row) {
|
990
|
+
return row.rowText.charAt(i) === ".";
|
991
|
+
}
|
992
|
+
|
993
|
+
for (i = 0; i < this._getMaxColNumber(this.source.display.grid); i++) {
|
994
|
+
if (widths[i] === undefined) {
|
995
|
+
tmp[i] = "*";
|
996
|
+
} else {
|
997
|
+
if (/-/.test(widths[i])) {
|
998
|
+
throw new Error("Invalid argument: negative width not allowed");
|
999
|
+
}
|
1000
|
+
}
|
1001
|
+
if (this.source.display.grid.every(checkDotColumn)) {
|
1002
|
+
tmp[i] = "0px";
|
1003
|
+
}
|
1004
|
+
if (widths[i] !== undefined) {
|
1005
|
+
tmp[i] = widths[i];
|
1006
|
+
}
|
1007
|
+
}
|
1008
|
+
return tmp;
|
1009
|
+
},
|
1010
|
+
_normalizeHeights:function (display) {
|
1011
|
+
var dotLineRegExp = /^\.+$/, negativeHeight = /-/, i, tmp = [];
|
1012
|
+
for (i = 0; i < display.grid.length; i++) {
|
1013
|
+
if (display.grid[i].height === undefined) {
|
1014
|
+
tmp[i] = "auto";
|
1015
|
+
} else {
|
1016
|
+
if (negativeHeight.test(display.grid[i].rowText)) {
|
1017
|
+
throw new Error("Invalid argument: negative height not allowed");
|
1018
|
+
}
|
1019
|
+
}
|
1020
|
+
if (dotLineRegExp.test(display.grid[i].rowText)) {
|
1021
|
+
tmp[i] = "0px";
|
1022
|
+
}
|
1023
|
+
//can overwrite dotLine rule
|
1024
|
+
if (display.grid[i].height !== undefined) {
|
1025
|
+
tmp[i] = display.grid[i].height;
|
1026
|
+
}
|
1027
|
+
}
|
1028
|
+
return tmp;
|
1029
|
+
},
|
1030
|
+
_getMaxColNumber:function (grid) {
|
1031
|
+
if (grid.length === 0) {
|
1032
|
+
return 0;
|
1033
|
+
}
|
1034
|
+
return grid.reduce(function (last, row) {
|
1035
|
+
return last > row.rowText.length ? last : row.rowText.length;
|
1036
|
+
}, 0);
|
1037
|
+
}
|
1038
|
+
};
|
1039
|
+
|
1040
|
+
templateBuilder.fn = templateBuilder.prototype;
|
1041
|
+
templateBuilder.prototype.init.prototype = templateBuilder.prototype;
|
1042
|
+
|
1043
|
+
global.templateBuilder = templateBuilder;
|
1044
|
+
log.info("load templateBuilder module... [OK]");
|
1045
|
+
})(compiler.fn);
|
1046
|
+
|
1047
|
+
log.info("compiler module load... [OK]");
|
1048
|
+
|
1049
|
+
})(window.templateLayout);
|