flexlayout-rails 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|