angularJS扩展指令集成部分jquery ui/plugin

最近一直研究angularjs,其双向绑定的确很强大,看中文社区,官方文档,参考github的ui示例,大概摸索下angularjs的开发方式——和传统的dom编程完全不同,jquery再锋利在angularjs的设计理念中,只能作为幕后者。AMD/CMD虽然能和angularjs一起使用,但angularjs自己的module设计,尤其是自动注入特性,比amd/cmd优越。和jquery plugin的扩展方式一样,amd/cmd期望以另一个非官方标准来积累js扩展,angularjs也是如此,开发者要作出选择,或组合或取舍。

 

言归正传:贴下一个简单以cmd形式扩展angularjs指令实现结合jquery/plugin的代码,需要的童鞋可以参考下,照此思路可以把jquery的有用的功能移植到angularjs的应用中来

 

// file ng.config.js
define(function(require){
	return {
		init: function(){
			// 默认配置
			var conf = {};

			conf.date = {dateFormat: 'yy-mm-dd'};
			conf.autocomplete = {minChars: 3, maxItemsToShow: 20};

			var md = angular.module('ng.config', []);
			md.value('ng.config', conf);
		}
	};
});

// file ng.filter.js
define(function(require){
	return {
		init: function(){
			var md = angular.module('ng.filter', []);

			// 过滤器方法都会执行两次。。。吐血
			// http://stackoverflow.com/questions/11676901/is-this-normal-for-angularjs-filtering

			// 日期格式转换
			md.filter('formatDate', function(){
				return function(value, format){
					if (!value)
						return value;

					return value.format(format || 'yyyy-MM-dd');
				};
			});
		}
	};
});

// file ng.service.js
define(function(require){
	return {
		init: function(){
			var md = angular.module('ng.service', []);

			// 注册服务
			// 全局变量获取,一种约定
			md.factory('uiGetPageData', ['$window', function(win){
				return function(key){
					var pageData = win.pageData;
					return pageData ? pageData[key] : null;
				};
			}]);

			// 日志
			md.factory('uiLog', ['$window', function(win){
				return function(msg, level){
					if(typeof(msg) != 'string')
						msg = JSON.stringify(msg);

					level = level || 'INFO';
					if(win.console && win.console.log)
						win.console.log('[' + level + ']' + msg);
				};
			}]);

			// 服务请求过滤
			md.factory('uiRequest', ['uiLog', function(log){
				return {
					filter: function(params, conf, skipLl){
						if(!conf)
							conf = {dateFormat: 'yyyy-MM-dd'};

						var r = {};
						if(params){
							for(key in params){
								if(skipLl && skipLl.contains(key))
									continue;

								var val = params[key];
								if(angular.isDate(val)){
									r[key] = val.format(conf.dateFormat);
								}else{
									r[key] = val;
								}
							}
						}
						return r;
					}
				};
			}]);

			// 验证服务
			md.factory('uiValid', function(){
				return {
					check: function(val, rule){
					}
				};
			});
		}
	};
});

// file ng.ui.js
define(function(require){
	require('ng/ng.config').init();
	require('ng/ng.service').init();
	require('ng/ng.filter').init();

	require('jquery.autocomplete');
	require('jquery.bgiframe');
	require('jquery.datepicker');
	require('jquery.hotkeys');

	var ag = window.angular;
	return {
		init: function(){
			var md = ag.module('ng.ui', ['ng.config', 'ng.service', 'ng.filter']);
			
			// 日期选择器
			// *** *** *** *** *** *** *** *** *** ***
			// *** *** *** *** *** *** *** *** *** ***
			md.directive('uiDate', ['ng.config', 'uiLog', function(conf, log){
				'use strict';
				var options = {};
				if(ag.isObject(conf.date)){
					ag.extend(options, conf.date);
				}
				return {
					restrict: 'A',
					require: 'ngModel',
					link: function(scope, el, attrs, ctrl){
						var getOptions = function(){
							return ag.extend(options, scope.$eval(attrs.uiDate));
						};

						var init = function(){
							var opts = getOptions();
							log('Init datepicker : ');
							log(opts);

							if(ctrl){
								// update model when datepicker value changes
								var updateModel = function(){
									scope.$apply(function(){
										var date = el.datepicker("getDate");
										ctrl.$setViewValue(date);
									});
								};

								if(opts.onSelect){
									var userHandler = opts.onSelect;
									opts.onSelect = function(value, picker){
										updateModel();
										return userHandler(value, picker);
									};
								}else{
									opts.onSelect = function(value, picker){
										updateModel();
									};
								}

								// datepicker后无法按键了
//								el.bind('change', updateModel);

								// Update the date picker when the model changes
								ctrl.$render = function(){
									var date = ctrl.$viewValue;
									if (ag.isDefined(date) && date !== null && !ag.isDate(date)){
										throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string');
									}

									el.datepicker("setDate", date);
								};
							}

							// If we don't destroy the old one it doesn't update properly when the config changes
							el.datepicker('destroy');
							// Create the new datepicker widget
							el.datepicker(opts);
							// Force a render to override whatever is in the input text box
							ctrl.$render();
						};

						// Watch for changes to the directives options
						scope.$watch(getOptions, init, true);
					}
				};
			}]);

			// 自动填充
			// *** *** *** *** *** *** *** *** *** ***
			// *** *** *** *** *** *** *** *** *** ***
			md.directive('uiAutocomplete', ['ng.config', 'uiLog', function(conf, log){
				'use strict';
				var options = {};
				if(ag.isObject(conf.autocomplete)){
					ag.extend(options, conf.autocomplete);
				}
				return {
					restrict: 'A',
					require: 'ngModel',
					link: function(scope, el, attrs, ctrl){
						var getOptions = function(){
							return ag.extend(options, scope.$eval(attrs.uiAutocomplete));
						};

						var init = function(){
							var opts = getOptions();
							log('Init autocomplete : ');
							log(opts);

							if(!opts.url || !opts.targetModel){
								log('Init autocomplete fail : url/targetModel required!');
								return;
							}

							if(ctrl){
								ctrl.$render = function(){
									// 自动填充如果没有填充的显示值,就默认取填充值
									var showLabel = ctrl.$viewValue;
									if(!showLabel){
										var targetModel = opts.targetModel;

										var showValue;
										if(targetModel.contains('.')){
											var arr = targetModel.split(/\./);
											var i = 0;
											var targetScope = scope;

											for(; i < arr.length; i++){
												var key = arr[i];
												if(i == arr.length - 1){
													showValue = targetScope[key];
												}else{
													if(!targetScope[key])
														break;
													targetScope = targetScope[key];
												}
											}
										}else{
											showValue = scope[targetModel];
										}
										if(showValue){
											ctrl.$setViewValue(showValue);
											el.val(showValue);
										}
									}
								};
							}

							// json : 
							// [{data: {result: i}, value: 'Col' + i}]
							el.autocomplete({
								url: opts.url, 
								minChars: opts.minChars, 
								maxItemsToShow: opts.maxItemsToShow, 
								remoteDataType: 'json', 
								useCache: false,
								processData: function(data) {
									var i, r = [];
									for(i = 0; i < data.length; i++){
										var item = data[i];
										r.push({data: {result: item.v}, value: item.v + '-' + item.l});
									}
									return r;
								},
								onItemSelect: function(item){
									var val = item.data.result;
									var showLabel = item.value;

									var targetModel = opts.targetModel;

									if(targetModel.contains('.')){
										var arr = targetModel.split(/\./);
										var i = 0;
										var targetScope = scope;

										for(; i < arr.length; i++){
											var key = arr[i];
											if(i == arr.length - 1){
												targetScope[key] = val;
											}else{
												if(!targetScope[key])
													targetScope[key] = {};
												targetScope = targetScope[key];
											}
										}
									}else{
										scope[targetModel] = val;
									}

									scope.$apply(function(){
										ctrl.$setViewValue(showLabel);
									});
								}
							});

							ctrl.$render();
						};

						// Watch for changes to the directives options
						scope.$watch(getOptions, init, true);
					}
				};
			}]);

			// 快捷键
			// *** *** *** *** *** *** *** *** *** ***
			// *** *** *** *** *** *** *** *** *** ***
			md.directive('uiShortkey', ['ng.config', 'uiLog', function(conf, log){
				'use strict';
				var options = {};
				return {
					restrict: 'A',
					link: function(scope, el, attrs, ctrl){
						var getOptions = function(){
							return ag.extend(options, scope.$eval(attrs.uiShortkey));
						};

						var init = function(){
							var opts = getOptions();
							log('Init shortkey : ');
							log(opts);

							if(!opts.key || !opts.method){
								log('Init shortkey fail : key/method required!');
								return;
							}

							$.hotkeys.add(opts.key, function(){
								var fn = scope[opts.method];
								if(fn)
									fn.call();
							});
						};

						// Watch for changes to the directives options
						scope.$watch(getOptions, init, true);
					}
				};
			}]);

			// 布局相关
			// *** *** *** *** *** *** *** *** *** ***
			// *** *** *** *** *** *** *** *** *** ***
			md.directive('uiLayoutCol', ['ng.config', 'uiLog', function(conf, log){
				'use strict';
				return {
					restrict: 'A',
					link: function(scope, el, attrs, ctrl){
						if('TR' != el[0].nodeName)
							return;

						log('Relayout...');

						var _tds = el.children('td');
						if(_tds.size() == 2){
							_tds.filter(':first').addClass('l');
							_tds.filter(':last').addClass('r');
						}else if(_tds.size() == 4){
							_tds.filter(':even').addClass('l2');
							_tds.filter(':odd').addClass('r2');
						}else if(_tds.size() == 6){
							_tds.eq(0).addClass('l3');
							_tds.eq(1).addClass('r3');
							_tds.eq(2).addClass('l3');
							_tds.eq(3).addClass('r3');
							_tds.eq(4).addClass('l3');
							_tds.eq(5).addClass('r3last');
						}

						// siblings tr set td text-align to right if exists label 
						el.siblings('tr').children('td').filter(function(){
							return $(this).find('label').size() > 0;
						}).addClass('ar');

						// set vertical-align = middle for label
			//			el.siblings('tr').children('td').each(function(){
			//				var _td = $(this);
			//				if(_td.find('label').size() > 0){
			//					_td.addClass('ar');
			//					_td.find('label').addClass('vm');
			//				}
			//			});
					}
				};
			}]);
		}
	};
});

 

 

 

内容概要:本文全面介绍了数据流图(DFD)的概念、构元素及其重要性。数据流图是从数据传递和加工的角度,以图形方式表达系统逻辑功能、数据流向和变换过程的工具。文章详细解释了数据流图的四个基本元素:数据流、加工、数据存储和外部实体,并通过实例说明了这些元素在实际场景中的应用。文中强调了数据流图在软件开发需求分析和业务流程优化中的关键作用,通过绘制顶层、中层和底层数据流图,逐步细化系统功能,确保数据流向和处理逻辑的清晰性。此外,文章还指出了常见绘制误区及解决方法,并以在线购物系统为例进行了实战分析,展示了从需求分析到数据流图绘制的全过程。 适合人群:软件工程师、业务分析师、系统设计师以及对系统分析与设计感兴趣的初学者。 使用场景及目标:①帮助开发团队在需求分析阶段清晰展示数据流动和处理过程,避免理解偏差;②辅助企业梳理和优化业务流程,识别效率低下的环节,提升运营效率;③为系统设计和开发提供详细的逻辑框架,确保各模块的功能明确,减少开发错误。 阅读建议:本文内容详实,涵盖了从理论到实践的各个方面。建议读者在学习过程中结合实际项目背景,逐步掌握数据流图的绘制技巧,并通过反复练习和优化,加深对系统分析与设计的理解。
资源下载链接为: https://pan.quark.cn/s/5c50e6120579 《CoffeeTime_0.99.rar:主板BIOS修改工具详述》 在计算机硬件领域,BIOS(基本输入输出系统)是计算机启动时最先加载的软件,它负责初始化硬件设备,并为操作系统提供基本的交互功能。不过,随着处理器技术的持续进步,部分主板可能无法原生支持更新的CPU型号。为解决这一问题,一些技术爱好者和专业人士会通过修改主板BIOS,也就是俗称的“魔改”,来提升其兼容性。本文将深入剖析名为“CoffeeTime_0.99.rar”的工具,它是一款专门用于主板BIOS修改,以实现对第6、7、8、9代英特尔CPU支持的工具。 我们先来看“CoffeeTime.exe”,这是该工具的主程序文件。通常情况下,它会配备一套直观易用的用户界面,方便用户对BIOS进行修改操作。不过,在使用该工具之前,用户必须具备一定的电脑硬件知识,因为一旦操作失误,就可能导致系统运行不稳定,甚至无法启动。对于初学者而言,谨慎操作至关重要,否则可能会造不可挽回的损失。 “readme.txt”是软件包中常见的文档,一般会包含使用指南、注意事项以及开发者提供的其他重要信息。在使用CoffeeTime之前,用户务必要仔细阅读该文件,因为里面可能包含了如何正确运行程序、避免错误操作以及解压后具体步骤等关键内容。 “bin”和“data”是两个文件夹,它们可能包含了用于BIOS修改的各种二进制文件和数据。“bin”文件夹通常会包含特定版本的BIOS固件或用于修改的工具,而“data”文件夹则可能包含更新CPU微码、识别信息等必要的数据文件。在进行BIOS修改的过程中,这些文件会被程序调用,从而实现对原有BIOS的扩展或修正。 BIOS的修改过程一般包含以下步骤:首先,备份原始BIOS,这是在进行任何修改前的必要步骤,以便
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值