最近一直研究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'); // } // }); } }; }]); } }; });
相关推荐
jquery UI 与plugin 开发实战 开发富界面
《jQuery全能权威指南:jQuery Core+jQuery Plugin+jQuery UI+jQuery Mobile》的阅读对象是具有一些HTML 、CSS和JavaScript知识的开发者,内容覆盖了jQuery知识体系的全部内容,包括jQuery Core、jQuery Plugin 、...
一个jquery开发的标签功能加强插件,可以生成或删除标签,还能对输入重复标签进行检查,和JQuery autocomplete插件配合实现自动完成功能。演示地址:http://www.jq22.com/jquery-info426
derby_plugin derby_ui_plugin derby Eclipse插件
作为一款万能播放器插件,总能少了对媒体控制的接口呢。由是偶利用空闲时间把这个插件完善了一下。使之具体播放、暂停、停止的功能。
jQuery Media Plugin Demo
最近网上源码难找了,在这里给大家提供一份癞子斗地主源码,可用的哦[img=http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/42.gif][/img]!!!在这里先上图给大家参考[img=...
jQuery grid view plugin - jQuery表格插件
[Interactions] Draggable Droppable Resizable Selectable Sortable ...These demos showcase some common uses of each jQuery UI plugin. Simply copy and paste code from the demos to get started.
struts2-jquery-plugin-3.1.0.jar
angularjs-plugin用于IDE环境中angularjs开发
是一个基于jQuery ui的日历插件应用讲解实例,下载即可应用。
由于本人最近使用derby数据库,需要在eclipse中连接,网上查询资料说需要用到这2个插件才能连接,根据网友提示去官网找了半天没有找到下载地址,为了方便其他人所以我把这...10.8.2.zip,derby_ui_doc_plugin_1.1.3.zip
jQuery IP address plugin
@ superset-ui 支持 UI的软件包的集合,... @superset-ui/plugin-*软件包通常较新且质量更高。 它们不依赖viz.py (包含可视化特定的python代码)并与/api/v1/query/接口的主要区别在于,新的通用终结点旨在提供所有可
最新的struts2-jquery-plugin插件3.3.3,包括jquery-ui和grid,使用标签实现。
JQuery Cycle Plugin
《jQuery全能权威指南:jQuery Core+jQuery Plugin+jQuery UI+jQuery Mobile》的阅读对象是具有一些HTML、CSS和JavaScript知识的开发者,内容覆盖了jQuery知识体系的全部内容,包括jQuery Core、jQuery Plugin、...
JQuery validation plugin学习资料
jQuery Rater Star Plugin 基于jQuery的投票插件 星星评价