|
1 | | -/*! jQuery Ctrl - v0.1.0 - 2014-07-21 |
| 1 | +/*! jQuery Ctrl - v0.1.0 - 2014-07-23 |
2 | 2 | * https://github.com/zengohm/jquery-ctrl |
3 | 3 | * Copyright (c) 2014 Zeng Ohm; Licensed MIT */ |
4 | | -(function ($) { |
| 4 | +(function (factory) { |
| 5 | + if (typeof define === 'function' && define.amd) { |
| 6 | + // AMD |
| 7 | + define(['jquery'], factory); |
| 8 | + } else if (typeof exports === 'object') { |
| 9 | + // CommonJS |
| 10 | + factory(require('jquery')); |
| 11 | + } else { |
| 12 | + // Browser globals |
| 13 | + factory(jQuery); |
| 14 | + } |
| 15 | +}(function ($) { |
5 | 16 | var NODE_STATUS_NORMAL = 0; |
6 | 17 | var NODE_STATUS_COVER = 1; |
7 | 18 | var NODE_STATUS_LAST = 2; |
8 | 19 |
|
9 | | - var modules = {}; |
10 | | - |
11 | 20 | var bindingTypes = {}; |
12 | 21 |
|
| 22 | + var createCtrl = function(modelData,$element){ |
| 23 | + return { |
| 24 | + model:new ModelObject(modelData), |
| 25 | + ctrl: $element |
| 26 | + }; |
| 27 | + }; |
| 28 | + |
13 | 29 | // Static method. |
14 | 30 | $.ctrl = function (ctrlName, init) { |
15 | | - var thisCtrl = { |
16 | | - model: {}, |
17 | | - init: init, |
18 | | - ctrl: $('[jq-ctrl="' + ctrlName + '"]') |
19 | | - }; |
20 | | - modules[ctrlName] = thisCtrl; |
21 | | - thisCtrl.init(thisCtrl.model); |
| 31 | + var modelData = {}; |
| 32 | + init(modelData); |
| 33 | + var thisCtrl = createCtrl(modelData,$('[jq-ctrl="' + ctrlName + '"]')); |
22 | 34 | bindingInit(thisCtrl); |
23 | 35 | }; |
24 | 36 |
|
|
37 | 49 | break; |
38 | 50 | } |
39 | 51 | } |
40 | | - initElement($(this)); |
| 52 | + if(!(node_status & NODE_STATUS_COVER)) { |
| 53 | + initElement($(this)); |
| 54 | + } |
41 | 55 | } |
42 | 56 | }); |
43 | 57 | }; |
|
46 | 60 |
|
47 | 61 |
|
48 | 62 | bindingTypes.text = function(node,model,onChangeTasks){ |
49 | | - if(node.nodeName.substr(0,1)==='#' && node.data.match(/\{\{\w+\}\}/)){ |
| 63 | + if(node.nodeName.substr(0,1)==='#' && node.data.match(/\{\{[\w\.]+\}\}/)){ |
50 | 64 | var template = node.data; |
51 | 65 | onChangeTasks.push(function(){ |
52 | | - node.data = template.replace(/\{\{(\w+)\}\}/g, function (match, key) { |
53 | | - return model[key]; |
| 66 | + node.data = template.replace(/\{\{([\w\.]+)\}\}/g, function (match, key) { |
| 67 | + return model.get(key); |
54 | 68 | }); |
55 | 69 | }); |
56 | 70 | onChangeTasks[onChangeTasks.length-1](); |
|
65 | 79 | if(element === srcElement){ |
66 | 80 | return false; |
67 | 81 | } |
68 | | - $(element).val(model[modelName]); |
| 82 | + $(element).val(model.get(modelName)); |
69 | 83 | }); |
70 | 84 | onChangeTasks[onChangeTasks.length-1](); |
71 | 85 | $(element).bind('keypress change keyup',function(){ |
72 | | - model[modelName] = $(this).val(); |
| 86 | + model.set(modelName,$(this).val()); |
73 | 87 | for(var i in onChangeTasks){ |
74 | 88 | onChangeTasks[i](this); |
75 | 89 | } |
|
85 | 99 | var allowAttributes = ['jq-src','jq-href']; |
86 | 100 | var onChangeDelegate = function(element,attribute,template) { |
87 | 101 | onChangeTasks.push(function(){ |
88 | | - element.setAttribute(attribute.substr(3),template.replace(/\{\{(\w+)\}\}/g, function (match, key) { |
89 | | - return model[key]; |
| 102 | + element.setAttribute(attribute.substr(3),template.replace(/\{\{([\w\.]+)\}\}/g, function (match, key) { |
| 103 | + return model.get(key); |
90 | 104 | })); |
91 | 105 | }); |
92 | 106 | }; |
|
108 | 122 |
|
109 | 123 | var onChangeDelegate = function(element,attribute,template) { |
110 | 124 | onChangeTasks.push(function () { |
111 | | - element.setAttribute(attribute, template.replace(/\{\{(\w+)\}\}/g, function (match, key) { |
112 | | - return model[key]; |
| 125 | + element.setAttribute(attribute, template.replace(/\{\{([\w\.]+)\}\}/g, function (match, key) { |
| 126 | + return model.get(key); |
113 | 127 | })); |
114 | 128 | }); |
115 | 129 | }; |
|
120 | 134 | } |
121 | 135 | var template = attributes[i].value; |
122 | 136 | var attribute = attributes[i].name; |
123 | | - if(template.match(/\{\{(\w+)\}\}/)){ |
| 137 | + if(template.match(/\{\{([\w\.]+)\}\}/)){ |
124 | 138 | onChangeDelegate(element,attribute,template); |
125 | 139 | onChangeTasks[onChangeTasks.length-1](null); |
126 | 140 | } |
|
133 | 147 | return NODE_STATUS_NORMAL; |
134 | 148 | } |
135 | 149 | onChangeTasks.push(function () { |
136 | | - $(element).css(model[modelName]); |
| 150 | + $(element).css(model.get(modelName)); |
137 | 151 | }); |
138 | 152 | onChangeTasks[onChangeTasks.length-1](null); |
139 | 153 | return NODE_STATUS_NORMAL; |
|
144 | 158 | return NODE_STATUS_NORMAL; |
145 | 159 | } |
146 | 160 | onChangeTasks.push(function () { |
147 | | - $(element).attr('disabled',model[modelName]); |
| 161 | + $(element).attr('disabled',model.get(modelName)); |
148 | 162 | }); |
149 | 163 | onChangeTasks[onChangeTasks.length-1](null); |
150 | 164 | return NODE_STATUS_NORMAL; |
|
171 | 185 | onChangeTasks.push(function(){ |
172 | 186 | $(element).empty(); |
173 | 187 | var modelName = element.getAttribute('jq-model'); |
174 | | - if(keyName === null){ |
175 | | - for(var i in model[listName]){ |
176 | | - $(element).append('<option>' + model[listName][i] + '</option>'); |
| 188 | + var list = model.get(listName); |
| 189 | + if(list && typeof(list[0])==='object' && Object.keys(list[0]).length===1 && list[0][Object.keys(list[0])[0]] instanceof Array ) { |
| 190 | + for (var g in list){ |
| 191 | + var $group = $('<optgroup></optgroup>'); |
| 192 | + var groupKey = Object.keys(list[g])[0]; |
| 193 | + $group.attr('label',groupKey); |
| 194 | + var subList = list[g][groupKey]; |
| 195 | + if(keyName === null){ |
| 196 | + for(var gi in subList){ |
| 197 | + $group.append('<option value="'+subList[gi]+'">' + subList[gi] + '</option>'); |
| 198 | + } |
| 199 | + }else{ |
| 200 | + for (var gk in subList) { |
| 201 | + $group.append('<option value="' + subList[gk][keyName] + '">' + subList[gk]['valueName'] + '</option>'); |
| 202 | + } |
| 203 | + } |
| 204 | + $(element).append($group); |
177 | 205 | } |
178 | 206 | }else{ |
179 | | - for(var k in model[listName]){ |
180 | | - $(element).append('<option value="' + model[listName][k][keyName] + '">' + model[listName][k]['valueName'] + '</option>'); |
| 207 | + if(keyName === null) { |
| 208 | + for(var i in list){ |
| 209 | + $(element).append('<option>' + list[i] + '</option>'); |
| 210 | + } |
| 211 | + }else{ |
| 212 | + for (var k in list) { |
| 213 | + $(element).append('<option value="' + list[k][keyName] + '">' + list[k]['valueName'] + '</option>'); |
| 214 | + } |
181 | 215 | } |
182 | 216 | } |
183 | | - $(element).val(model[modelName]); |
| 217 | + $(element).val(model.get(modelName)); |
184 | 218 | }); |
185 | 219 | onChangeTasks[onChangeTasks.length-1](null); |
| 220 | + $(element).removeAttr('jq-options'); |
186 | 221 | return NODE_STATUS_COVER; |
187 | 222 | }; |
188 | 223 | bindingTypes.jqIf = function(element,model,onChangeTasks){ |
|
202 | 237 | } |
203 | 238 | onChangeTasks.push(function(){ |
204 | 239 | $(element).remove(); |
205 | | - if(model[query]){ |
| 240 | + if(model.get(query)){ |
206 | 241 | $(element).insertAfter(startComment); |
207 | 242 | } |
208 | 243 | }); |
|
212 | 247 |
|
213 | 248 | bindingTypes.jqRepeat = function(element,model,onChangeTasks){ |
214 | 249 | var query, match; |
215 | | - if(typeof(element.getAttribute)!=='function' || !(query = element.getAttribute('jq-repeat')) || !(match = query.match(/(\w+)\s+in\s+(\w+)/))){ |
| 250 | + if(typeof(element.getAttribute)!=='function' || !(query = element.getAttribute('jq-repeat')) || !(match = query.match(/(\w+)\s+in\s+([\w\.]+)/))){ |
216 | 251 | return NODE_STATUS_NORMAL; |
217 | 252 | } |
218 | 253 | var modelName = match[2]; |
|
228 | 263 | parent.appendChild(endComment); |
229 | 264 | } |
230 | 265 |
|
231 | | - var repeatRowDelegate = function(row){ |
232 | | - return template.replace(/\{\{([\w\.]+)\}\}/g,function(match,key){ |
233 | | - if(key.substr(0,rowName.length+1) === (rowName+'.')){ |
234 | | - return row[key.substr(rowName.length+1)]; |
235 | | - } |
236 | | - }); |
| 266 | + var repeatRowDelegate = function(subModel){ |
| 267 | + var $row = $(template.replace(/\{\{([\w\.]+)\}\}/g,function(match,key){ |
| 268 | + return subModel.get(key)?subModel.get(key):match; |
| 269 | + })); |
| 270 | + $row.removeAttr('jq-repeat'); |
| 271 | + var subCtrl = createCtrl(subModel.getData(),$row); |
| 272 | + bindingInit(subCtrl); |
| 273 | + return $row; |
237 | 274 | }; |
238 | 275 |
|
239 | 276 |
|
|
243 | 280 | currentNode = currentNode.nextSibling; |
244 | 281 | $(currentNode).prev().remove(); |
245 | 282 | } |
246 | | - var html = ''; |
247 | | - var list = model[modelName]; |
| 283 | + var list = model.get(modelName); |
248 | 284 | for(var i in list){ |
249 | | - html+= repeatRowDelegate(list[i]); |
| 285 | + var subModel = model.clone(); |
| 286 | + subModel.getData()[rowName] = list[i]; |
| 287 | + repeatRowDelegate(subModel).insertAfter(startComment); |
250 | 288 | } |
251 | | - $(html).insertAfter(startComment); |
252 | 289 |
|
253 | 290 | }); |
254 | 291 | onChangeTasks[onChangeTasks.length-1](null); |
255 | 292 | return NODE_STATUS_COVER; |
256 | 293 | }; |
257 | 294 |
|
258 | | -}(jQuery)); |
| 295 | + var ModelObject = function(data){ |
| 296 | + if(typeof(data) === 'undefined' || !data){ |
| 297 | + data = {}; |
| 298 | + } |
| 299 | + var model = data; |
| 300 | + |
| 301 | + this.set = function(key,value){ |
| 302 | + var keys = key.split('.'); |
| 303 | + var lastKey = keys.pop(); |
| 304 | + var current = model; |
| 305 | + for(var i in keys){ |
| 306 | + if(typeof(current[keys[i]]) === 'undefined'){ |
| 307 | + current[keys[i]] = {}; |
| 308 | + } |
| 309 | + current = current[keys[i]]; |
| 310 | + } |
| 311 | + current[lastKey] = value; |
| 312 | + return value; |
| 313 | + }; |
| 314 | + |
| 315 | + this.get = function(key){ |
| 316 | + var keys = key.split('.'); |
| 317 | + var current = model; |
| 318 | + for(var i in keys){ |
| 319 | + current = current[keys[i]]; |
| 320 | + if(!current){ |
| 321 | + return null; |
| 322 | + } |
| 323 | + } |
| 324 | + return current; |
| 325 | + }; |
| 326 | + |
| 327 | + this.subModel = function(key){ |
| 328 | + return new ModelObject(this.get(key)); |
| 329 | + }; |
| 330 | + |
| 331 | + this.getData = function(){ |
| 332 | + return model; |
| 333 | + }; |
| 334 | + |
| 335 | + this.clone = function(){ |
| 336 | + return new ModelObject($.extend(true,{},model)); |
| 337 | + }; |
| 338 | + }; |
| 339 | +})); |
0 commit comments