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 changesvar 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 changesctrl.$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 changesel.datepicker('destroy');// Create the new datepicker widgetel.datepicker(opts);// Force a render to override whatever is in the input text boxctrl.$render();};// Watch for changes to the directives optionsscope.$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 optionsscope.$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 optionsscope.$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');// }// });}};}]);}}; });
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!