select.js 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505
  1. ;(function($) {
  2. "use strict";
  3. $.fn.transitionEnd = function(callback) {
  4. var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
  5. i, dom = this;
  6. function fireCallBack(e) {
  7. /*jshint validthis:true */
  8. if (e.target !== this) return;
  9. callback.call(this, e);
  10. for (i = 0; i < events.length; i++) {
  11. dom.off(events[i], fireCallBack);
  12. }
  13. }
  14. if (callback) {
  15. for (i = 0; i < events.length; i++) {
  16. dom.on(events[i], fireCallBack);
  17. }
  18. }
  19. return this;
  20. };
  21. $.support = (function() {
  22. var support = {
  23. touch: !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch)
  24. };
  25. return support;
  26. })();
  27. $.touchEvents = {
  28. start: $.support.touch ? 'touchstart' : 'mousedown',
  29. move: $.support.touch ? 'touchmove' : 'mousemove',
  30. end: $.support.touch ? 'touchend' : 'mouseup'
  31. };
  32. $.getTouchPosition = function(e) {
  33. e = e.originalEvent || e; //jquery wrap the originevent
  34. if(e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend') {
  35. return {
  36. x: e.targetTouches[0].pageX,
  37. y: e.targetTouches[0].pageY
  38. };
  39. } else {
  40. return {
  41. x: e.pageX,
  42. y: e.pageY
  43. };
  44. }
  45. };
  46. $.fn.scrollHeight = function() {
  47. return this[0].scrollHeight;
  48. };
  49. $.fn.transform = function(transform) {
  50. for (var i = 0; i < this.length; i++) {
  51. var elStyle = this[i].style;
  52. elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform;
  53. }
  54. return this;
  55. };
  56. $.fn.transition = function(duration) {
  57. if (typeof duration !== 'string') {
  58. duration = duration + 'ms';
  59. }
  60. for (var i = 0; i < this.length; i++) {
  61. var elStyle = this[i].style;
  62. elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration;
  63. }
  64. return this;
  65. };
  66. $.getTranslate = function (el, axis) {
  67. var matrix, curTransform, curStyle, transformMatrix;
  68. // automatic axis detection
  69. if (typeof axis === 'undefined') {
  70. axis = 'x';
  71. }
  72. curStyle = window.getComputedStyle(el, null);
  73. if (window.WebKitCSSMatrix) {
  74. // Some old versions of Webkit choke when 'none' is passed; pass
  75. // empty string instead in this case
  76. transformMatrix = new WebKitCSSMatrix(curStyle.webkitTransform === 'none' ? '' : curStyle.webkitTransform);
  77. }
  78. else {
  79. transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
  80. matrix = transformMatrix.toString().split(',');
  81. }
  82. if (axis === 'x') {
  83. //Latest Chrome and webkits Fix
  84. if (window.WebKitCSSMatrix)
  85. curTransform = transformMatrix.m41;
  86. //Crazy IE10 Matrix
  87. else if (matrix.length === 16)
  88. curTransform = parseFloat(matrix[12]);
  89. //Normal Browsers
  90. else
  91. curTransform = parseFloat(matrix[4]);
  92. }
  93. if (axis === 'y') {
  94. //Latest Chrome and webkits Fix
  95. if (window.WebKitCSSMatrix)
  96. curTransform = transformMatrix.m42;
  97. //Crazy IE10 Matrix
  98. else if (matrix.length === 16)
  99. curTransform = parseFloat(matrix[13]);
  100. //Normal Browsers
  101. else
  102. curTransform = parseFloat(matrix[5]);
  103. }
  104. return curTransform || 0;
  105. };
  106. $.requestAnimationFrame = function (callback) {
  107. if (window.requestAnimationFrame) return window.requestAnimationFrame(callback);
  108. else if (window.webkitRequestAnimationFrame) return window.webkitRequestAnimationFrame(callback);
  109. else if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame(callback);
  110. else {
  111. return window.setTimeout(callback, 1000 / 60);
  112. }
  113. };
  114. $.cancelAnimationFrame = function (id) {
  115. if (window.cancelAnimationFrame) return window.cancelAnimationFrame(id);
  116. else if (window.webkitCancelAnimationFrame) return window.webkitCancelAnimationFrame(id);
  117. else if (window.mozCancelAnimationFrame) return window.mozCancelAnimationFrame(id);
  118. else {
  119. return window.clearTimeout(id);
  120. }
  121. };
  122. $.fn.join = function(arg) {
  123. return this.toArray().join(arg);
  124. }
  125. })($);
  126. +(function ($) {
  127. "use strict";
  128. $.Template7 = $.t7 = (function () {
  129. function isArray(arr) {
  130. return Object.prototype.toString.apply(arr) === '[object Array]';
  131. }
  132. function isObject(obj) {
  133. return obj instanceof Object;
  134. }
  135. function isFunction(func) {
  136. return typeof func === 'function';
  137. }
  138. var cache = {};
  139. function helperToSlices(string) {
  140. var helperParts = string.replace(/[{}#}]/g, '').split(' ');
  141. var slices = [];
  142. var shiftIndex, i, j;
  143. for (i = 0; i < helperParts.length; i++) {
  144. var part = helperParts[i];
  145. if (i === 0) slices.push(part);
  146. else {
  147. if (part.indexOf('"') === 0) {
  148. // Plain String
  149. if (part.match(/"/g).length === 2) {
  150. // One word string
  151. slices.push(part);
  152. }
  153. else {
  154. // Find closed Index
  155. shiftIndex = 0;
  156. for (j = i + 1; j < helperParts.length; j++) {
  157. part += ' ' + helperParts[j];
  158. if (helperParts[j].indexOf('"') >= 0) {
  159. shiftIndex = j;
  160. slices.push(part);
  161. break;
  162. }
  163. }
  164. if (shiftIndex) i = shiftIndex;
  165. }
  166. }
  167. else {
  168. if (part.indexOf('=') > 0) {
  169. // Hash
  170. var hashParts = part.split('=');
  171. var hashName = hashParts[0];
  172. var hashContent = hashParts[1];
  173. if (hashContent.match(/"/g).length !== 2) {
  174. shiftIndex = 0;
  175. for (j = i + 1; j < helperParts.length; j++) {
  176. hashContent += ' ' + helperParts[j];
  177. if (helperParts[j].indexOf('"') >= 0) {
  178. shiftIndex = j;
  179. break;
  180. }
  181. }
  182. if (shiftIndex) i = shiftIndex;
  183. }
  184. var hash = [hashName, hashContent.replace(/"/g,'')];
  185. slices.push(hash);
  186. }
  187. else {
  188. // Plain variable
  189. slices.push(part);
  190. }
  191. }
  192. }
  193. }
  194. return slices;
  195. }
  196. function stringToBlocks(string) {
  197. var blocks = [], i, j, k;
  198. if (!string) return [];
  199. var _blocks = string.split(/({{[^{^}]*}})/);
  200. for (i = 0; i < _blocks.length; i++) {
  201. var block = _blocks[i];
  202. if (block === '') continue;
  203. if (block.indexOf('{{') < 0) {
  204. blocks.push({
  205. type: 'plain',
  206. content: block
  207. });
  208. }
  209. else {
  210. if (block.indexOf('{/') >= 0) {
  211. continue;
  212. }
  213. if (block.indexOf('{#') < 0 && block.indexOf(' ') < 0 && block.indexOf('else') < 0) {
  214. // Simple variable
  215. blocks.push({
  216. type: 'variable',
  217. contextName: block.replace(/[{}]/g, '')
  218. });
  219. continue;
  220. }
  221. // Helpers
  222. var helperSlices = helperToSlices(block);
  223. var helperName = helperSlices[0];
  224. var helperContext = [];
  225. var helperHash = {};
  226. for (j = 1; j < helperSlices.length; j++) {
  227. var slice = helperSlices[j];
  228. if (isArray(slice)) {
  229. // Hash
  230. helperHash[slice[0]] = slice[1] === 'false' ? false : slice[1];
  231. }
  232. else {
  233. helperContext.push(slice);
  234. }
  235. }
  236. if (block.indexOf('{#') >= 0) {
  237. // Condition/Helper
  238. var helperStartIndex = i;
  239. var helperContent = '';
  240. var elseContent = '';
  241. var toSkip = 0;
  242. var shiftIndex;
  243. var foundClosed = false, foundElse = false, foundClosedElse = false, depth = 0;
  244. for (j = i + 1; j < _blocks.length; j++) {
  245. if (_blocks[j].indexOf('{{#') >= 0) {
  246. depth ++;
  247. }
  248. if (_blocks[j].indexOf('{{/') >= 0) {
  249. depth --;
  250. }
  251. if (_blocks[j].indexOf('{{#' + helperName) >= 0) {
  252. helperContent += _blocks[j];
  253. if (foundElse) elseContent += _blocks[j];
  254. toSkip ++;
  255. }
  256. else if (_blocks[j].indexOf('{{/' + helperName) >= 0) {
  257. if (toSkip > 0) {
  258. toSkip--;
  259. helperContent += _blocks[j];
  260. if (foundElse) elseContent += _blocks[j];
  261. }
  262. else {
  263. shiftIndex = j;
  264. foundClosed = true;
  265. break;
  266. }
  267. }
  268. else if (_blocks[j].indexOf('else') >= 0 && depth === 0) {
  269. foundElse = true;
  270. }
  271. else {
  272. if (!foundElse) helperContent += _blocks[j];
  273. if (foundElse) elseContent += _blocks[j];
  274. }
  275. }
  276. if (foundClosed) {
  277. if (shiftIndex) i = shiftIndex;
  278. blocks.push({
  279. type: 'helper',
  280. helperName: helperName,
  281. contextName: helperContext,
  282. content: helperContent,
  283. inverseContent: elseContent,
  284. hash: helperHash
  285. });
  286. }
  287. }
  288. else if (block.indexOf(' ') > 0) {
  289. blocks.push({
  290. type: 'helper',
  291. helperName: helperName,
  292. contextName: helperContext,
  293. hash: helperHash
  294. });
  295. }
  296. }
  297. }
  298. return blocks;
  299. }
  300. var Template7 = function (template) {
  301. var t = this;
  302. t.template = template;
  303. function getCompileFn(block, depth) {
  304. if (block.content) return compile(block.content, depth);
  305. else return function () {return ''; };
  306. }
  307. function getCompileInverse(block, depth) {
  308. if (block.inverseContent) return compile(block.inverseContent, depth);
  309. else return function () {return ''; };
  310. }
  311. function getCompileVar(name, ctx) {
  312. var variable, parts, levelsUp = 0, initialCtx = ctx;
  313. if (name.indexOf('../') === 0) {
  314. levelsUp = name.split('../').length - 1;
  315. var newDepth = ctx.split('_')[1] - levelsUp;
  316. ctx = 'ctx_' + (newDepth >= 1 ? newDepth : 1);
  317. parts = name.split('../')[levelsUp].split('.');
  318. }
  319. else if (name.indexOf('@global') === 0) {
  320. ctx = '$.Template7.global';
  321. parts = name.split('@global.')[1].split('.');
  322. }
  323. else if (name.indexOf('@root') === 0) {
  324. ctx = 'ctx_1';
  325. parts = name.split('@root.')[1].split('.');
  326. }
  327. else {
  328. parts = name.split('.');
  329. }
  330. variable = ctx;
  331. for (var i = 0; i < parts.length; i++) {
  332. var part = parts[i];
  333. if (part.indexOf('@') === 0) {
  334. if (i > 0) {
  335. variable += '[(data && data.' + part.replace('@', '') + ')]';
  336. }
  337. else {
  338. variable = '(data && data.' + name.replace('@', '') + ')';
  339. }
  340. }
  341. else {
  342. if (isFinite(part)) {
  343. variable += '[' + part + ']';
  344. }
  345. else {
  346. if (part.indexOf('this') === 0) {
  347. variable = part.replace('this', ctx);
  348. }
  349. else {
  350. variable += '.' + part;
  351. }
  352. }
  353. }
  354. }
  355. return variable;
  356. }
  357. function getCompiledArguments(contextArray, ctx) {
  358. var arr = [];
  359. for (var i = 0; i < contextArray.length; i++) {
  360. if (contextArray[i].indexOf('"') === 0) arr.push(contextArray[i]);
  361. else {
  362. arr.push(getCompileVar(contextArray[i], ctx));
  363. }
  364. }
  365. return arr.join(', ');
  366. }
  367. function compile(template, depth) {
  368. depth = depth || 1;
  369. template = template || t.template;
  370. if (typeof template !== 'string') {
  371. throw new Error('Template7: Template must be a string');
  372. }
  373. var blocks = stringToBlocks(template);
  374. if (blocks.length === 0) {
  375. return function () { return ''; };
  376. }
  377. var ctx = 'ctx_' + depth;
  378. var resultString = '(function (' + ctx + ', data) {\n';
  379. if (depth === 1) {
  380. resultString += 'function isArray(arr){return Object.prototype.toString.apply(arr) === \'[object Array]\';}\n';
  381. resultString += 'function isFunction(func){return (typeof func === \'function\');}\n';
  382. resultString += 'function c(val, ctx) {if (typeof val !== "undefined") {if (isFunction(val)) {return val.call(ctx);} else return val;} else return "";}\n';
  383. }
  384. resultString += 'var r = \'\';\n';
  385. var i, j, context;
  386. for (i = 0; i < blocks.length; i++) {
  387. var block = blocks[i];
  388. // Plain block
  389. if (block.type === 'plain') {
  390. resultString += 'r +=\'' + (block.content).replace(/\r/g, '\\r').replace(/\n/g, '\\n').replace(/'/g, '\\' + '\'') + '\';';
  391. continue;
  392. }
  393. var variable, compiledArguments;
  394. // Variable block
  395. if (block.type === 'variable') {
  396. variable = getCompileVar(block.contextName, ctx);
  397. resultString += 'r += c(' + variable + ', ' + ctx + ');';
  398. }
  399. // Helpers block
  400. if (block.type === 'helper') {
  401. if (block.helperName in t.helpers) {
  402. compiledArguments = getCompiledArguments(block.contextName, ctx);
  403. resultString += 'r += ($.Template7.helpers.' + block.helperName + ').call(' + ctx + ', ' + (compiledArguments && (compiledArguments + ', ')) +'{hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
  404. }
  405. else {
  406. if (block.contextName.length > 0) {
  407. throw new Error('Template7: Missing helper: "' + block.helperName + '"');
  408. }
  409. else {
  410. variable = getCompileVar(block.helperName, ctx);
  411. resultString += 'if (' + variable + ') {';
  412. resultString += 'if (isArray(' + variable + ')) {';
  413. resultString += 'r += ($.Template7.helpers.each).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
  414. resultString += '}else {';
  415. resultString += 'r += ($.Template7.helpers.with).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
  416. resultString += '}}';
  417. }
  418. }
  419. }
  420. }
  421. resultString += '\nreturn r;})';
  422. return eval.call(window, resultString);
  423. }
  424. t.compile = function (template) {
  425. if (!t.compiled) {
  426. t.compiled = compile(template);
  427. }
  428. return t.compiled;
  429. };
  430. };
  431. Template7.prototype = {
  432. options: {},
  433. helpers: {
  434. 'if': function (context, options) {
  435. if (isFunction(context)) { context = context.call(this); }
  436. if (context) {
  437. return options.fn(this, options.data);
  438. }
  439. else {
  440. return options.inverse(this, options.data);
  441. }
  442. },
  443. 'unless': function (context, options) {
  444. if (isFunction(context)) { context = context.call(this); }
  445. if (!context) {
  446. return options.fn(this, options.data);
  447. }
  448. else {
  449. return options.inverse(this, options.data);
  450. }
  451. },
  452. 'each': function (context, options) {
  453. var ret = '', i = 0;
  454. if (isFunction(context)) { context = context.call(this); }
  455. if (isArray(context)) {
  456. if (options.hash.reverse) {
  457. context = context.reverse();
  458. }
  459. for (i = 0; i < context.length; i++) {
  460. ret += options.fn(context[i], {first: i === 0, last: i === context.length - 1, index: i});
  461. }
  462. if (options.hash.reverse) {
  463. context = context.reverse();
  464. }
  465. }
  466. else {
  467. for (var key in context) {
  468. i++;
  469. ret += options.fn(context[key], {key: key});
  470. }
  471. }
  472. if (i > 0) return ret;
  473. else return options.inverse(this);
  474. },
  475. 'with': function (context, options) {
  476. if (isFunction(context)) { context = context.call(this); }
  477. return options.fn(context);
  478. },
  479. 'join': function (context, options) {
  480. if (isFunction(context)) { context = context.call(this); }
  481. return context.join(options.hash.delimiter || options.hash.delimeter);
  482. },
  483. 'js': function (expression, options) {
  484. var func;
  485. if (expression.indexOf('return')>=0) {
  486. func = '(function(){'+expression+'})';
  487. }
  488. else {
  489. func = '(function(){return ('+expression+')})';
  490. }
  491. return eval.call(this, func).call(this);
  492. },
  493. 'js_compare': function (expression, options) {
  494. var func;
  495. if (expression.indexOf('return')>=0) {
  496. func = '(function(){'+expression+'})';
  497. }
  498. else {
  499. func = '(function(){return ('+expression+')})';
  500. }
  501. var condition = eval.call(this, func).call(this);
  502. if (condition) {
  503. return options.fn(this, options.data);
  504. }
  505. else {
  506. return options.inverse(this, options.data);
  507. }
  508. }
  509. }
  510. };
  511. var t7 = function (template, data) {
  512. if (arguments.length === 2) {
  513. var instance = new Template7(template);
  514. var rendered = instance.compile()(data);
  515. instance = null;
  516. return (rendered);
  517. }
  518. else return new Template7(template);
  519. };
  520. t7.registerHelper = function (name, fn) {
  521. Template7.prototype.helpers[name] = fn;
  522. };
  523. t7.unregisterHelper = function (name) {
  524. Template7.prototype.helpers[name] = undefined;
  525. delete Template7.prototype.helpers[name];
  526. };
  527. t7.compile = function (template, options) {
  528. var instance = new Template7(template, options);
  529. return instance.compile();
  530. };
  531. t7.options = Template7.prototype.options;
  532. t7.helpers = Template7.prototype.helpers;
  533. return t7;
  534. })();
  535. })($);
  536. + function($) {
  537. "use strict";
  538. var Picker = function (params) {
  539. var p = this;
  540. var defaults = {
  541. updateValuesOnMomentum: false,
  542. updateValuesOnTouchmove: true,
  543. rotateEffect: false,
  544. momentumRatio: 7,
  545. freeMode: false,
  546. // Common settings
  547. scrollToInput: true,
  548. inputReadOnly: true,
  549. toolbar: true,
  550. toolbarCloseText: '完成',
  551. title: '请选择',
  552. toolbarTemplate: '<div class="toolbar">\
  553. <div class="toolbar-inner">\
  554. <a href="javascript:;" class="picker-button close-picker">{{closeText}}</a>\
  555. <h1 class="title">{{title}}</h1>\
  556. </div>\
  557. </div>',
  558. };
  559. params = params || {};
  560. for (var def in defaults) {
  561. if (typeof params[def] === 'undefined') {
  562. params[def] = defaults[def];
  563. }
  564. }
  565. p.params = params;
  566. p.cols = [];
  567. p.initialized = false;
  568. // Inline flag
  569. p.inline = p.params.container ? true : false;
  570. // 3D Transforms origin bug, only on safari
  571. var originBug = $.device.ios || (navigator.userAgent.toLowerCase().indexOf('safari') >= 0 && navigator.userAgent.toLowerCase().indexOf('chrome') < 0) && !$.device.android;
  572. // Should be converted to popover
  573. function isPopover() {
  574. var toPopover = false;
  575. if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
  576. if (!p.inline && p.params.input) {
  577. if (p.params.onlyInPopover) toPopover = true;
  578. else {
  579. if ($.device.ios) {
  580. toPopover = $.device.ipad ? true : false;
  581. }
  582. else {
  583. if ($(window).width() >= 768) toPopover = true;
  584. }
  585. }
  586. }
  587. return toPopover;
  588. }
  589. function inPopover() {
  590. if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
  591. else return false;
  592. }
  593. // Value
  594. p.setValue = function (arrValues, transition) {
  595. var valueIndex = 0;
  596. for (var i = 0; i < p.cols.length; i++) {
  597. if (p.cols[i] && !p.cols[i].divider) {
  598. p.cols[i].setValue(arrValues[valueIndex], transition);
  599. valueIndex++;
  600. }
  601. }
  602. };
  603. p.updateValue = function () {
  604. var newValue = [];
  605. var newDisplayValue = [];
  606. for (var i = 0; i < p.cols.length; i++) {
  607. if (!p.cols[i].divider) {
  608. newValue.push(p.cols[i].value);
  609. newDisplayValue.push(p.cols[i].displayValue);
  610. }
  611. }
  612. if (newValue.indexOf(undefined) >= 0) {
  613. return;
  614. }
  615. p.value = newValue;
  616. p.displayValue = newDisplayValue;
  617. if (p.params.onChange) {
  618. p.params.onChange(p, p.value, p.displayValue);
  619. }
  620. if (p.input && p.input.length > 0) {
  621. $(p.input).val(p.params.formatValue ? p.params.formatValue(p, p.value, p.displayValue) : p.value.join(' '));
  622. $(p.input).trigger('change');
  623. }
  624. };
  625. // Columns Handlers
  626. p.initPickerCol = function (colElement, updateItems) {
  627. var colContainer = $(colElement);
  628. var colIndex = colContainer.index();
  629. var col = p.cols[colIndex];
  630. if (col.divider) return;
  631. col.container = colContainer;
  632. col.wrapper = col.container.find('.picker-items-col-wrapper');
  633. col.items = col.wrapper.find('.picker-item');
  634. var i, j;
  635. var wrapperHeight, itemHeight, itemsHeight, minTranslate, maxTranslate;
  636. col.replaceValues = function (values, displayValues) {
  637. col.destroyEvents();
  638. col.values = values;
  639. col.displayValues = displayValues;
  640. var newItemsHTML = p.columnHTML(col, true);
  641. col.wrapper.html(newItemsHTML);
  642. col.items = col.wrapper.find('.picker-item');
  643. col.calcSize();
  644. col.setValue(col.values[0] || '', 0, true);
  645. col.initEvents();
  646. };
  647. col.calcSize = function () {
  648. if (!col.values.length) return;
  649. if (p.params.rotateEffect) {
  650. col.container.removeClass('picker-items-col-absolute');
  651. if (!col.width) col.container.css({width:''});
  652. }
  653. var colWidth, colHeight;
  654. colWidth = 0;
  655. colHeight = col.container[0].offsetHeight;
  656. wrapperHeight = col.wrapper[0].offsetHeight;
  657. itemHeight = col.items[0].offsetHeight;
  658. itemsHeight = itemHeight * col.items.length;
  659. minTranslate = colHeight / 2 - itemsHeight + itemHeight / 2;
  660. maxTranslate = colHeight / 2 - itemHeight / 2;
  661. if (col.width) {
  662. colWidth = col.width;
  663. if (parseInt(colWidth, 10) === colWidth) colWidth = colWidth + 'px';
  664. col.container.css({width: colWidth});
  665. }
  666. if (p.params.rotateEffect) {
  667. if (!col.width) {
  668. col.items.each(function () {
  669. var item = $(this);
  670. item.css({width:'auto'});
  671. colWidth = Math.max(colWidth, item[0].offsetWidth);
  672. item.css({width:''});
  673. });
  674. col.container.css({width: (colWidth + 2) + 'px'});
  675. }
  676. col.container.addClass('picker-items-col-absolute');
  677. }
  678. };
  679. col.calcSize();
  680. col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)').transition(0);
  681. var activeIndex = 0;
  682. var animationFrameId;
  683. // Set Value Function
  684. col.setValue = function (newValue, transition, valueCallbacks) {
  685. if (typeof transition === 'undefined') transition = '';
  686. var newActiveIndex = col.wrapper.find('.picker-item[data-picker-value="' + newValue + '"]').index();
  687. if(typeof newActiveIndex === 'undefined' || newActiveIndex === -1) {
  688. col.value = col.displayValue = newValue;
  689. return;
  690. }
  691. var newTranslate = -newActiveIndex * itemHeight + maxTranslate;
  692. // Update wrapper
  693. col.wrapper.transition(transition);
  694. col.wrapper.transform('translate3d(0,' + (newTranslate) + 'px,0)');
  695. // Watch items
  696. if (p.params.updateValuesOnMomentum && col.activeIndex && col.activeIndex !== newActiveIndex ) {
  697. $.cancelAnimationFrame(animationFrameId);
  698. col.wrapper.transitionEnd(function(){
  699. $.cancelAnimationFrame(animationFrameId);
  700. });
  701. updateDuringScroll();
  702. }
  703. // Update items
  704. col.updateItems(newActiveIndex, newTranslate, transition, valueCallbacks);
  705. };
  706. col.updateItems = function (activeIndex, translate, transition, valueCallbacks) {
  707. if (typeof translate === 'undefined') {
  708. translate = $.getTranslate(col.wrapper[0], 'y');
  709. }
  710. if(typeof activeIndex === 'undefined') activeIndex = -Math.round((translate - maxTranslate)/itemHeight);
  711. if (activeIndex < 0) activeIndex = 0;
  712. if (activeIndex >= col.items.length) activeIndex = col.items.length - 1;
  713. var previousActiveIndex = col.activeIndex;
  714. col.activeIndex = activeIndex;
  715. //去掉 .picker-after-selected, .picker-before-selected 以提高性能
  716. col.wrapper.find('.picker-selected').removeClass('picker-selected');
  717. if (p.params.rotateEffect) {
  718. col.items.transition(transition);
  719. }
  720. var selectedItem = col.items.eq(activeIndex).addClass('picker-selected').transform('');
  721. if (valueCallbacks || typeof valueCallbacks === 'undefined') {
  722. // Update values
  723. col.value = selectedItem.attr('data-picker-value');
  724. col.displayValue = col.displayValues ? col.displayValues[activeIndex] : col.value;
  725. // On change callback
  726. if (previousActiveIndex !== activeIndex) {
  727. if (col.onChange) {
  728. col.onChange(p, col.value, col.displayValue);
  729. }
  730. p.updateValue();
  731. }
  732. }
  733. // Set 3D rotate effect
  734. if (!p.params.rotateEffect) {
  735. return;
  736. }
  737. var percentage = (translate - (Math.floor((translate - maxTranslate)/itemHeight) * itemHeight + maxTranslate)) / itemHeight;
  738. col.items.each(function () {
  739. var item = $(this);
  740. var itemOffsetTop = item.index() * itemHeight;
  741. var translateOffset = maxTranslate - translate;
  742. var itemOffset = itemOffsetTop - translateOffset;
  743. var percentage = itemOffset / itemHeight;
  744. var itemsFit = Math.ceil(col.height / itemHeight / 2) + 1;
  745. var angle = (-18*percentage);
  746. if (angle > 180) angle = 180;
  747. if (angle < -180) angle = -180;
  748. // Far class
  749. if (Math.abs(percentage) > itemsFit) item.addClass('picker-item-far');
  750. else item.removeClass('picker-item-far');
  751. // Set transform
  752. item.transform('translate3d(0, ' + (-translate + maxTranslate) + 'px, ' + (originBug ? -110 : 0) + 'px) rotateX(' + angle + 'deg)');
  753. });
  754. };
  755. function updateDuringScroll() {
  756. animationFrameId = $.requestAnimationFrame(function () {
  757. col.updateItems(undefined, undefined, 0);
  758. updateDuringScroll();
  759. });
  760. }
  761. // Update items on init
  762. if (updateItems) col.updateItems(0, maxTranslate, 0);
  763. var allowItemClick = true;
  764. var isTouched, isMoved, touchStartY, touchCurrentY, touchStartTime, touchEndTime, startTranslate, returnTo, currentTranslate, prevTranslate, velocityTranslate, velocityTime;
  765. function handleTouchStart (e) {
  766. if (isMoved || isTouched) return;
  767. e.preventDefault();
  768. isTouched = true;
  769. var position = $.getTouchPosition(e);
  770. touchStartY = touchCurrentY = position.y;
  771. touchStartTime = (new Date()).getTime();
  772. allowItemClick = true;
  773. startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
  774. }
  775. function handleTouchMove (e) {
  776. if (!isTouched) return;
  777. e.preventDefault();
  778. allowItemClick = false;
  779. var position = $.getTouchPosition(e);
  780. touchCurrentY = position.y;
  781. if (!isMoved) {
  782. // First move
  783. $.cancelAnimationFrame(animationFrameId);
  784. isMoved = true;
  785. startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
  786. col.wrapper.transition(0);
  787. }
  788. e.preventDefault();
  789. var diff = touchCurrentY - touchStartY;
  790. currentTranslate = startTranslate + diff;
  791. returnTo = undefined;
  792. // Normalize translate
  793. if (currentTranslate < minTranslate) {
  794. currentTranslate = minTranslate - Math.pow(minTranslate - currentTranslate, 0.8);
  795. returnTo = 'min';
  796. }
  797. if (currentTranslate > maxTranslate) {
  798. currentTranslate = maxTranslate + Math.pow(currentTranslate - maxTranslate, 0.8);
  799. returnTo = 'max';
  800. }
  801. // Transform wrapper
  802. col.wrapper.transform('translate3d(0,' + currentTranslate + 'px,0)');
  803. // Update items
  804. col.updateItems(undefined, currentTranslate, 0, p.params.updateValuesOnTouchmove);
  805. // Calc velocity
  806. velocityTranslate = currentTranslate - prevTranslate || currentTranslate;
  807. velocityTime = (new Date()).getTime();
  808. prevTranslate = currentTranslate;
  809. }
  810. function handleTouchEnd (e) {
  811. if (!isTouched || !isMoved) {
  812. isTouched = isMoved = false;
  813. return;
  814. }
  815. isTouched = isMoved = false;
  816. col.wrapper.transition('');
  817. if (returnTo) {
  818. if (returnTo === 'min') {
  819. col.wrapper.transform('translate3d(0,' + minTranslate + 'px,0)');
  820. }
  821. else col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)');
  822. }
  823. touchEndTime = new Date().getTime();
  824. var velocity, newTranslate;
  825. if (touchEndTime - touchStartTime > 300) {
  826. newTranslate = currentTranslate;
  827. }
  828. else {
  829. velocity = Math.abs(velocityTranslate / (touchEndTime - velocityTime));
  830. newTranslate = currentTranslate + velocityTranslate * p.params.momentumRatio;
  831. }
  832. newTranslate = Math.max(Math.min(newTranslate, maxTranslate), minTranslate);
  833. // Active Index
  834. var activeIndex = -Math.floor((newTranslate - maxTranslate)/itemHeight);
  835. // Normalize translate
  836. if (!p.params.freeMode) newTranslate = -activeIndex * itemHeight + maxTranslate;
  837. // Transform wrapper
  838. col.wrapper.transform('translate3d(0,' + (parseInt(newTranslate,10)) + 'px,0)');
  839. // Update items
  840. col.updateItems(activeIndex, newTranslate, '', true);
  841. // Watch items
  842. if (p.params.updateValuesOnMomentum) {
  843. updateDuringScroll();
  844. col.wrapper.transitionEnd(function(){
  845. $.cancelAnimationFrame(animationFrameId);
  846. });
  847. }
  848. // Allow click
  849. setTimeout(function () {
  850. allowItemClick = true;
  851. }, 100);
  852. }
  853. function handleClick(e) {
  854. if (!allowItemClick) return;
  855. $.cancelAnimationFrame(animationFrameId);
  856. /*jshint validthis:true */
  857. var value = $(this).attr('data-picker-value');
  858. col.setValue(value);
  859. }
  860. col.initEvents = function (detach) {
  861. var method = detach ? 'off' : 'on';
  862. col.container[method]($.touchEvents.start, handleTouchStart);
  863. col.container[method]($.touchEvents.move, handleTouchMove);
  864. col.container[method]($.touchEvents.end, handleTouchEnd);
  865. col.items[method]('click', handleClick);
  866. };
  867. col.destroyEvents = function () {
  868. col.initEvents(true);
  869. };
  870. col.container[0].f7DestroyPickerCol = function () {
  871. col.destroyEvents();
  872. };
  873. col.initEvents();
  874. };
  875. p.destroyPickerCol = function (colContainer) {
  876. colContainer = $(colContainer);
  877. if ('f7DestroyPickerCol' in colContainer[0]) colContainer[0].f7DestroyPickerCol();
  878. };
  879. // Resize cols
  880. function resizeCols() {
  881. if (!p.opened) return;
  882. for (var i = 0; i < p.cols.length; i++) {
  883. if (!p.cols[i].divider) {
  884. p.cols[i].calcSize();
  885. p.cols[i].setValue(p.cols[i].value, 0, false);
  886. }
  887. }
  888. }
  889. $(window).on('resize', resizeCols);
  890. // HTML Layout
  891. p.columnHTML = function (col, onlyItems) {
  892. var columnItemsHTML = '';
  893. var columnHTML = '';
  894. if (col.divider) {
  895. columnHTML += '<div class="picker-items-col picker-items-col-divider ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '">' + col.content + '</div>';
  896. }
  897. else {
  898. for (var j = 0; j < col.values.length; j++) {
  899. columnItemsHTML += '<div class="picker-item" data-picker-value="' + col.values[j] + '">' + (col.displayValues ? col.displayValues[j] : col.values[j]) + '</div>';
  900. }
  901. columnHTML += '<div class="picker-items-col ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '"><div class="picker-items-col-wrapper">' + columnItemsHTML + '</div></div>';
  902. }
  903. return onlyItems ? columnItemsHTML : columnHTML;
  904. };
  905. p.layout = function () {
  906. var pickerHTML = '';
  907. var pickerClass = '';
  908. var i;
  909. p.cols = [];
  910. var colsHTML = '';
  911. for (i = 0; i < p.params.cols.length; i++) {
  912. var col = p.params.cols[i];
  913. colsHTML += p.columnHTML(p.params.cols[i]);
  914. p.cols.push(col);
  915. }
  916. pickerClass = 'weui-picker-modal picker-columns ' + (p.params.cssClass || '') + (p.params.rotateEffect ? ' picker-3d' : '') + (p.params.cols.length === 1 ? ' picker-columns-single' : '');
  917. pickerHTML =
  918. '<div class="' + (pickerClass) + '">' +
  919. (p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText).replace(/{{title}}/g, p.params.title) : '') +
  920. '<div class="picker-modal-inner picker-items">' +
  921. colsHTML +
  922. '<div class="picker-center-highlight"></div>' +
  923. '</div>' +
  924. '</div>';
  925. p.pickerHTML = pickerHTML;
  926. };
  927. // Input Events
  928. function openOnInput(e) {
  929. e.preventDefault();
  930. if (p.opened) return;
  931. p.open();
  932. if (p.params.scrollToInput && !isPopover()) {
  933. var pageContent = p.input.parents('.content');
  934. if (pageContent.length === 0) return;
  935. var paddingTop = parseInt(pageContent.css('padding-top'), 10),
  936. paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
  937. pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
  938. pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
  939. newPaddingBottom;
  940. var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
  941. if (inputTop > pageHeight) {
  942. var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
  943. if (scrollTop + pageHeight > pageScrollHeight) {
  944. newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
  945. if (pageHeight === pageScrollHeight) {
  946. newPaddingBottom = p.container.height();
  947. }
  948. pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
  949. }
  950. pageContent.scrollTop(scrollTop, 300);
  951. }
  952. }
  953. }
  954. function closeOnHTMLClick(e) {
  955. if (inPopover()) return;
  956. if (p.input && p.input.length > 0) {
  957. if (e.target !== p.input[0] && $(e.target).parents('.weui-picker-modal').length === 0) p.close();
  958. }
  959. else {
  960. if ($(e.target).parents('.weui-picker-modal').length === 0) p.close();
  961. }
  962. }
  963. if (p.params.input) {
  964. p.input = $(p.params.input);
  965. if (p.input.length > 0) {
  966. if (p.params.inputReadOnly) p.input.prop('readOnly', true);
  967. if (!p.inline) {
  968. p.input.on('click', openOnInput);
  969. }
  970. if (p.params.inputReadOnly) {
  971. p.input.on('focus mousedown', function (e) {
  972. e.preventDefault();
  973. });
  974. }
  975. }
  976. }
  977. if (!p.inline) $('html').on('click', closeOnHTMLClick);
  978. // Open
  979. function onPickerClose() {
  980. p.opened = false;
  981. if (p.input && p.input.length > 0) p.input.parents('.page-content').css({'padding-bottom': ''});
  982. if (p.params.onClose) p.params.onClose(p);
  983. // Destroy events
  984. p.container.find('.picker-items-col').each(function () {
  985. p.destroyPickerCol(this);
  986. });
  987. }
  988. p.opened = false;
  989. p.open = function () {
  990. var toPopover = isPopover();
  991. if (!p.opened) {
  992. // Layout
  993. p.layout();
  994. // Append
  995. if (toPopover) {
  996. p.pickerHTML = '<div class="popover popover-picker-columns"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
  997. p.popover = $.popover(p.pickerHTML, p.params.input, true);
  998. p.container = $(p.popover).find('.weui-picker-modal');
  999. $(p.popover).on('close', function () {
  1000. onPickerClose();
  1001. });
  1002. }
  1003. else if (p.inline) {
  1004. p.container = $(p.pickerHTML);
  1005. p.container.addClass('picker-modal-inline');
  1006. $(p.params.container).append(p.container);
  1007. }
  1008. else {
  1009. p.container = $($.openPicker(p.pickerHTML));
  1010. $(p.container)
  1011. .on('close', function () {
  1012. onPickerClose();
  1013. });
  1014. }
  1015. // Store picker instance
  1016. p.container[0].f7Picker = p;
  1017. // Init Events
  1018. p.container.find('.picker-items-col').each(function () {
  1019. var updateItems = true;
  1020. if ((!p.initialized && p.params.value) || (p.initialized && p.value)) updateItems = false;
  1021. p.initPickerCol(this, updateItems);
  1022. });
  1023. // Set value
  1024. if (!p.initialized) {
  1025. if (p.params.value) {
  1026. p.setValue(p.params.value, 0);
  1027. }
  1028. }
  1029. else {
  1030. if (p.value) p.setValue(p.value, 0);
  1031. }
  1032. }
  1033. // Set flag
  1034. p.opened = true;
  1035. p.initialized = true;
  1036. if (p.params.onOpen) p.params.onOpen(p);
  1037. };
  1038. // Close
  1039. p.close = function (force) {
  1040. if (!p.opened || p.inline) return;
  1041. if (inPopover()) {
  1042. $.closePicker(p.popover);
  1043. return;
  1044. }
  1045. else {
  1046. $.closePicker(p.container);
  1047. return;
  1048. }
  1049. };
  1050. // Destroy
  1051. p.destroy = function () {
  1052. p.close();
  1053. if (p.params.input && p.input.length > 0) {
  1054. p.input.off('click focus', openOnInput);
  1055. $(p.input).data('picker', null);
  1056. }
  1057. $('html').off('click', closeOnHTMLClick);
  1058. $(window).off('resize', resizeCols);
  1059. };
  1060. if (p.inline) {
  1061. p.open();
  1062. }
  1063. return p;
  1064. };
  1065. $(document).on("click", ".close-picker", function() {
  1066. var pickerToClose = $('.weui-picker-modal.weui-picker-modal-visible');
  1067. if (pickerToClose.length > 0) {
  1068. $.closePicker(pickerToClose);
  1069. }
  1070. });
  1071. //修复picker会滚动页面的bug
  1072. $(document).on($.touchEvents.move, ".picker-modal-inner", function(e) {
  1073. e.preventDefault();
  1074. });
  1075. $.openPicker = function(tpl, className, callback) {
  1076. if(typeof className === "function") {
  1077. callback = className;
  1078. className = undefined;
  1079. }
  1080. $.closePicker();
  1081. var container = $("<div class='weui-picker-container "+ (className || "") + "'></div>").appendTo(document.body);
  1082. container.show();
  1083. container.addClass("weui-picker-container-visible");
  1084. //关于布局的问题,如果直接放在body上,则做动画的时候会撑开body高度而导致滚动条变化。
  1085. var dialog = $(tpl).appendTo(container);
  1086. dialog.width(); //通过取一次CSS值,强制浏览器不能把上下两行代码合并执行,因为合并之后会导致无法出现动画。
  1087. dialog.addClass("weui-picker-modal-visible");
  1088. callback && container.on("close", callback);
  1089. return dialog;
  1090. }
  1091. $.updatePicker = function(tpl) {
  1092. var container = $(".weui-picker-container-visible");
  1093. if(!container[0]) return false;
  1094. container.html("");
  1095. var dialog = $(tpl).appendTo(container);
  1096. dialog.addClass("weui-picker-modal-visible");
  1097. return dialog;
  1098. }
  1099. $.closePicker = function(container, callback) {
  1100. if(typeof container === "function") callback = container;
  1101. $(".weui-picker-modal-visible").removeClass("weui-picker-modal-visible").transitionEnd(function() {
  1102. $(this).parent().remove();
  1103. callback && callback();
  1104. }).trigger("close");
  1105. };
  1106. $.fn.picker = function(params) {
  1107. var args = arguments;
  1108. return this.each(function() {
  1109. if(!this) return;
  1110. var $this = $(this);
  1111. var picker = $this.data("picker");
  1112. if(!picker) {
  1113. params = $.extend({ input: this }, params || {}) // https://github.com/lihongxun945/jquery-weui/issues/432
  1114. var inputValue = $this.val();
  1115. if(params.value === undefined && inputValue !== "") {
  1116. params.value = (params.cols && params.cols.length > 1) ? inputValue.split(" ") : [inputValue];
  1117. }
  1118. var p = $.extend({input: this}, params);
  1119. picker = new Picker(p);
  1120. $this.data("picker", picker);
  1121. }
  1122. if(typeof params === typeof "a") {
  1123. picker[params].apply(picker, Array.prototype.slice.call(args, 1));
  1124. }
  1125. });
  1126. };
  1127. }($);
  1128. /* global $:true */
  1129. + function($) {
  1130. "use strict";
  1131. var defaults;
  1132. var selects = [];
  1133. var Select = function(input, config) {
  1134. var self = this;
  1135. this.config = config;
  1136. //init empty data
  1137. this.data = {
  1138. values: '',
  1139. titles: '',
  1140. origins: [],
  1141. length: 0
  1142. };
  1143. this.$input = $(input);
  1144. this.$input.prop("readOnly", true);
  1145. this.initConfig();
  1146. config = this.config;
  1147. this.$input.click($.proxy(this.open, this));
  1148. selects.push(this)
  1149. }
  1150. Select.prototype.initConfig = function() {
  1151. this.config = $.extend({}, defaults, this.config);
  1152. var config = this.config;
  1153. if(!config.items || !config.items.length) return;
  1154. config.items = config.items.map(function(d, i) {
  1155. if(typeof d == typeof "a") {
  1156. return {
  1157. title: d,
  1158. value: d
  1159. };
  1160. }
  1161. return d;
  1162. });
  1163. this.tpl = $.t7.compile("<div class='weui-picker-modal weui-select-modal'>" + config.toolbarTemplate + (config.multi ? config.checkboxTemplate : config.radioTemplate) +"<p class='closeBtn close-select' style='text-align:center'>取消</p>"+"</div>");
  1164. if(config.input !== undefined) this.$input.val(config.input);
  1165. this.parseInitValue();
  1166. this._init = true;
  1167. }
  1168. Select.prototype.updateInputValue = function(values, titles) {
  1169. var v, t;
  1170. if(this.config.multi) {
  1171. v = values.join(this.config.split);
  1172. t = titles.join(this.config.split);
  1173. } else {
  1174. v = values[0];
  1175. t = titles[0];
  1176. }
  1177. //caculate origin data
  1178. var origins = [];
  1179. this.config.items.forEach(function(d) {
  1180. values.each(function(i, dd) {
  1181. if(d.value == dd) origins.push(d);
  1182. });
  1183. });
  1184. this.$input.val(t).data("values", v);
  1185. this.$input.attr("value", t).attr("data-values", v);
  1186. var data = {
  1187. values: v,
  1188. titles: t,
  1189. valuesArray: values,
  1190. titlesArray: titles,
  1191. origins: origins,
  1192. length: origins.length
  1193. };
  1194. this.data = data;
  1195. this.$input.trigger("change", data);
  1196. this.config.onChange && this.config.onChange.call(this, data);
  1197. }
  1198. Select.prototype.parseInitValue = function() {
  1199. var value = this.$input.val();
  1200. var items = this.config.items;
  1201. //如果input为空,只有在第一次初始化的时候才保留默认选择。因为后来就是用户自己取消了全部选择,不能再为他选中默认值。
  1202. if( !this._init && (value === undefined || value == null || value === "")) return;
  1203. var titles = this.config.multi ? value.split(this.config.split) : [value];
  1204. for(var i=0;i<items.length;i++) {
  1205. items[i].checked = false;
  1206. for(var j=0;j<titles.length;j++) {
  1207. if(items[i].title === titles[j]) {
  1208. items[i].checked = true;
  1209. }
  1210. }
  1211. }
  1212. }
  1213. Select.prototype._bind = function(dialog) {
  1214. var self = this,
  1215. config = this.config;
  1216. dialog.on("change", function(e) {
  1217. var checked = dialog.find("input:checked");
  1218. var values = checked.map(function() {
  1219. return $(this).val();
  1220. });
  1221. var titles = checked.map(function() {
  1222. return $(this).data("title");
  1223. });
  1224. self.updateInputValue(values, titles);
  1225. if(config.autoClose && !config.multi) self.close();
  1226. })
  1227. .on("click", ".close-select", function() {
  1228. self.close();
  1229. });
  1230. }
  1231. //更新数据
  1232. Select.prototype.update = function(config) {
  1233. this.config = $.extend({}, this.config, config);
  1234. this.initConfig();
  1235. if(this._open) {
  1236. this._bind($.updatePicker(this.getHTML()));
  1237. }
  1238. }
  1239. Select.prototype.open = function(values, titles) {
  1240. if(this._open) return;
  1241. // open picker 会默认关掉其他的,但是 onClose 不会被调用,所以这里先关掉其他select
  1242. for (var i = 0; i < selects.length; i++ ) {
  1243. var s = selects[i];
  1244. if (s === this) continue;
  1245. if (s._open) {
  1246. if(!s.close()) return false; // 其他的select由于某些条件限制关闭失败。
  1247. }
  1248. }
  1249. this.parseInitValue();
  1250. var config = this.config;
  1251. var dialog = this.dialog = $.openPicker(this.getHTML());
  1252. this._bind(dialog);
  1253. this._open = true;
  1254. if(config.onOpen) config.onOpen(this);
  1255. }
  1256. Select.prototype.close = function(callback, force) {
  1257. if (!this._open) return false;
  1258. var self = this,
  1259. beforeClose = this.config.beforeClose;
  1260. if(typeof callback === typeof true) {
  1261. force === callback;
  1262. }
  1263. if(!force) {
  1264. if(beforeClose && typeof beforeClose === 'function' && beforeClose.call(this, this.data.values, this.data.titles) === false) {
  1265. return false
  1266. }
  1267. if(this.config.multi) {
  1268. if(this.config.min !== undefined && this.data.length < this.config.min) {
  1269. // $.toast("请至少选择"+this.config.min+"个", "text");
  1270. return false
  1271. }
  1272. if(this.config.max !== undefined && this.data.length > this.config.max) {
  1273. // $.toast("最多只能选择"+this.config.max+"个", "text");
  1274. return false
  1275. }
  1276. }
  1277. }
  1278. $.closePicker(function() {
  1279. self.onClose();
  1280. callback && callback();
  1281. });
  1282. return true
  1283. }
  1284. Select.prototype.onClose = function() {
  1285. this._open = false;
  1286. if(this.config.onClose) this.config.onClose(this);
  1287. }
  1288. Select.prototype.getHTML = function(callback) {
  1289. var config = this.config;
  1290. return this.tpl({
  1291. items: config.items,
  1292. title: config.title,
  1293. closeText: config.closeText
  1294. })
  1295. }
  1296. $.fn.select = function(params, args) {
  1297. return this.each(function() {
  1298. var $this = $(this);
  1299. if(!$this.data("weui-select")) $this.data("weui-select", new Select(this, params));
  1300. var select = $this.data("weui-select");
  1301. if(typeof params === typeof "a") select[params].call(select, args);
  1302. return select;
  1303. });
  1304. }
  1305. defaults = $.fn.select.prototype.defaults = {
  1306. items: [],
  1307. input: undefined, //输入框的初始值
  1308. title: "请选择",
  1309. multi: false,
  1310. closeText: "确定",
  1311. autoClose: true, //是否选择完成后自动关闭,只有单选模式下才有效
  1312. onChange: undefined, //function
  1313. beforeClose: undefined, // function 关闭之前,如果返回false则阻止关闭
  1314. onClose: undefined, //function
  1315. onOpen: undefined, //function
  1316. split: ",", //多选模式下的分隔符
  1317. min: undefined, //多选模式下可用,最少选择数
  1318. max: undefined, //单选模式下可用,最多选择数
  1319. toolbarTemplate: '<div class="toolbar">\
  1320. <div class="toolbar-inner">\
  1321. <a href="javascript:;" class="picker-button close-select">{{closeText}}</a>\
  1322. <h1 class="title">{{title}}</h1>\
  1323. </div>\
  1324. </div>',
  1325. radioTemplate:
  1326. '<div class="weui-cells weui-cells_radio">\
  1327. {{#items}}\
  1328. <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">\
  1329. <div class="weui-cell__bd weui-cell_primary">\
  1330. <p>{{this.title}}</p>\
  1331. </div>\
  1332. <div class="weui-cell__ft">\
  1333. <input type="radio" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}">\
  1334. <span class="weui-icon-checked"></span>\
  1335. </div>\
  1336. </label>\
  1337. {{/items}}\
  1338. </div>',
  1339. checkboxTemplate:
  1340. '<div class="weui-cells weui-cells_checkbox">\
  1341. {{#items}}\
  1342. <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">\
  1343. <div class="weui-cell__bd weui-cell_primary">\
  1344. <p>{{this.title}}</p>\
  1345. </div>\
  1346. <div class="weui-cell__ft">\
  1347. <input type="checkbox" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}" >\
  1348. <span class="weui-icon-checked"></span>\
  1349. </div>\
  1350. </label>\
  1351. {{/items}}\
  1352. </div>',
  1353. }
  1354. }($);