Blame view

mustache/js/classes/Page.js 6.33 KB
5a739853   patrick.he   commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  //this is basic class for loading page/layout data from json or csv files
  
  module.exports = function(params) {
   require('require-csv')//lightweight class for parsing possible csv data
   var fs = require("fs"),
  	 engine = params["engine"]
  
  
  
   var $type = params["type"] || "page" //page or layout?
   var $name = params["name"] //page or layout name
   var $main_template = null
   var $partials = {} //will hold all compiled partials that will be passed onto the base Mustache template for further processing
   var $vars = {} //holds the variables and data that will be accessed in mustache via page.variableName or layout.variableName
  
   var $data_dir = ''
   var $views_dir = ''
  
   this.initiate = function(callback) {//reading and initiate page data from json file
      $data_dir = params.path['data'];
  	var filename = $data_dir +"/"+$type+"s/"+ $name + '.json';
  	var data = fs.readFileSync(filename, 'utf-8')
  	$vars = JSON.parse(data);
  	
  	if('alias' in $vars) {
  		$name = $vars['alias'];
  		filename = $data_dir +"/"+$type+"s/"+ $name + '.json';
  		data = fs.readFileSync(filename, 'utf-8')
  		$vars = extend(JSON.parse(data), $vars)
  	}
  
  	
  	if($type != "layout" && !("layout" in $vars)) $vars["layout"] = "default";
  
  	map_script_names();
  	//now load all data relating to this page
  	load_data($data_dir)
  
  	var wait_for_compression = false;
  
  	//load inline scripts and styles
  	$views_dir = params.path['views'];
  	if($type == 'page') {
  		if(fs.existsSync($views_dir + '/assets/scripts/' + $name + '.js')) {
  			if(params.compressor) {
  				wait_for_compression = true;
  				params.compressor.compress($views_dir + '/assets/scripts/' + $name + '.js', {
  					charset: 'utf8',
  					type: 'js'
  				}, function(err, data, extra) {
  					if(err) console.log(err);
  					$vars['inline_scripts'] = data;
  					callback.call();
  				});
  			} 
  			else $vars['inline_scripts'] = fs.readFileSync($views_dir + '/assets/scripts/' + $name + '.js' , 'utf-8');
  		}
  		if(fs.existsSync($views_dir + '/assets/styles/' + $name + '.css')) {
  			$vars['inline_styles'] = fs.readFileSync($views_dir + '/assets/styles/' + $name + '.css' , 'utf-8')
  		}
  	}
  
  	if( !wait_for_compression && typeof callback === "function" ) callback.call();
  
   }
  
  
   /**
    This functions loads the data related to each page or layout
    for a page we load all files in the related directory
    for a layout we check the "datas-sources" attribute of our layout_file.json and load them
    In your real world application you can load data only when it is needed according to each page inside controllers
   */
   var load_data = function(data_dir) {
  	var data_files = {}
  
  	var format = new RegExp("([0-9a-z\\-_]+)\\.(json|csv)$" , "i");
  
  	//see if there's a folder for partial data relating to this page or layout
  	//if so iterate all json/csv files and load the data
  	var partial_data_folder = data_dir + "/"+$type +"s/partials/" + $name;
  	var stats;
  	if(fs.existsSync(partial_data_folder) && (stats = fs.statSync(partial_data_folder)) && stats.isDirectory()) {
  		var files = fs.readdirSync(partial_data_folder)
  		files.forEach(function (name) {
  			var filename;//file name, which we use as the variable name
  			if (! (filename = name.match(format)) ) return;
  			data_files[filename[1]] = partial_data_folder + "/" + name;
  		})
  	}
  
  
  	for(var var_name in data_files) if(data_files.hasOwnProperty(var_name)) {
  
  		var new_data
  		try {
  			if(data_files[var_name].match(/\.json$/i)) {
  				new_data = fs.readFileSync(data_files[var_name] , 'utf-8');
  				new_data = JSON.parse(new_data);
  			} else if(data_files[var_name].match(/\.csv$/i)) {
  				//load csv data into an array
  				var csv_data = require(data_files[var_name]);
  				
  				//now convert it to json
  				var csv_header = csv_data[0];
  				var length = csv_data.length;
  
  				var json_data = []
  				for(var i = 1 ; i < length; i++) {
  					var csv_row = csv_data[i];
  					var json_row = {}
  					for(var j = 0; j < csv_row.length; j++) {
  						json_row[csv_header[j]] = csv_row[j];
  					}
  					//for example if we have "status":"pending" , add this to it as well : "pending":true
  					if("status" in json_row) json_row[json_row["status"].toLowerCase()] = true;
  					json_data.push(json_row);
  				}
  				
  				new_data = json_data
  			}
  		} catch(e) {
  			console.log("Invalid JSON Data File : " + data_files[var_name]);
  			continue;
  		}
  		
  		$vars[var_name.replace(/\./g , '_')] = new_data
  		//here we replace '.' with '_' in variable names, so template compiler can recognize it as a variable not an object
  		//for example change sidebar.navList to sidebar_navList , because sidebar is not an object
  
  	}
  
  
    return true;
   }
  
  
   //in our page's data file, we save short script/style names, which we must map to original file names
   //this way we can easily only change the script-mapping file and changes will be reflected
   var map_script_names = function() {
  	var mappables = ["script" , "style"]
  	for(var m in mappables) {
  	  var which = mappables[m]
  	  if($vars[which+'s']) {//if we have $vars["scripts"] or $vars["styles"]
  		var page_scripts = $vars[which+'s'];
  		var map_json = JSON.parse(fs.readFileSync($data_dir + "/common/"+which+"-mapping"+(params.path['minified'] ? '.min' : '')+".json"));
  		var mapped_scripts = [];
  		for(var i in page_scripts) {
  			if(page_scripts[i] in map_json) {
  				if(typeof map_json[page_scripts[i]] == "string") mapped_scripts.push(map_json[page_scripts[i]])
  				else if(typeof map_json[page_scripts[i]] == "object") //two or more scripts should be included for this to work, like dataTables, jQuery UI, etc ...
  				{
  					for(var m in map_json[page_scripts[i]])
  						mapped_scripts.push(map_json[page_scripts[i]][m])
  				}
  			}
  		}
  		$vars[which+'s'] = mapped_scripts;
  
  		if(('ie_'+which+'s') in $vars) {
  			var ie_scripts = $vars['ie_'+which+'s'];//ie_scripts || ie_styles
  			var ie_mapped_scripts = [];
  			for(var i in ie_scripts) if(map_json[ie_scripts[i].name])
  			{
  				ie_mapped_scripts.push({"version" : ie_scripts[i].version , "file_name" : map_json[ie_scripts[i].name]})
  			}
  
  			$vars['ie_'+which+'s'] = ie_mapped_scripts
  		}
  	  }
  	}
   }
   
  
  
  
  
  
  
   this.get_template = function() {
  	var template_file = $views_dir+"/"+$type+"s/"+$name + '.mustache';
  	if(fs.existsSync(template_file)) {
  		return params.engine.compile(fs.readFileSync(template_file , 'utf-8'));
  	} 
  	return null;
   }
   this.get_vars = function() {
  	return $vars;
   }
   this.get_var = function(name , undefined) {
  	return name in $vars ? $vars[name] : undefined;
   }
   this.get_name= function() {
  	return $name;
   }
  
   
  }