记录拖动排序

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
  9. <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
  10. <script src="https://cdn.staticfile.org/angular.js/1.6.6/angular.min.js"></script>
  11. <script src="./sortable.js"></script>
  12. </head>
  13. <body ng-app="app">
  14. <div ng-controller="sortCtrl">
  15. <ul ui-sortable="sortableOptions" ng-model="data">
  16. <li ng-repeat="item in data ">
  17. <span>{{item.name}}, {{item.age}}</span>
  18. </li>
  19. </ul>
  20. </div>
  21. </body>
  22.  
  23. <script>
  24. angular.module("app", ["ui.sortable"])
  25. .controller("sortCtrl", function($scope, $timeout) {
  26. $scope.cannotSort = false;
  27. $scope.data = [{
  28. "name": "allen",
  29. "age": 21,
  30. "i": 0
  31. }, {
  32. "name": "bob",
  33. "age": 18,
  34. "i": 1
  35. }, {
  36. "name": "curry",
  37. "age": 25,
  38. "i": 2
  39. }, {
  40. "name": "david",
  41. "age": 30,
  42. "i": 3
  43. }];
  44.  
  45. $scope.sortableOptions = {
  46. // 数据有变化
  47. update: function(e, ui) {
  48. console.log("update");
  49. //需要使用延时方法,否则会输出原始数据的顺序,可能是BUG?
  50. $timeout(function() {
  51. var resArr = [];
  52. for (var i = 0; i < $scope.data.length; i++) {
  53. resArr.push($scope.data[i].i);
  54. }
  55. console.log(resArr);
  56. })
  57.  
  58. },
  59.  
  60. // 完成拖拽动作
  61. stop: function(e, ui) {
  62. //do nothing
  63. console.log("do nothing");
  64. }
  65. }
  66. })
  67. </script>
  68.  
  69. </html>
  1. sortable.js
  1. /*
  2. jQuery UI Sortable plugin wrapper
  3.  
  4. @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
  5. */
  6. angular
  7. .module('ui.sortable', [])
  8. .value('uiSortableConfig', {
  9. // the default for jquery-ui sortable is "> *", we need to restrict this to
  10. // ng-repeat items
  11. // if the user uses
  12. items: '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'
  13. })
  14. .directive('uiSortable', [
  15. 'uiSortableConfig',
  16. '$timeout',
  17. '$log',
  18. function(uiSortableConfig, $timeout, $log) {
  19. return {
  20. require: '?ngModel',
  21. scope: {
  22. ngModel: '=',
  23. uiSortable: '=',
  24. ////Expression bindings from html.
  25. create: '&uiSortableCreate',
  26. // helper:'&uiSortableHelper',
  27. start: '&uiSortableStart',
  28. activate: '&uiSortableActivate',
  29. // sort:'&uiSortableSort',
  30. // change:'&uiSortableChange',
  31. // over:'&uiSortableOver',
  32. // out:'&uiSortableOut',
  33. beforeStop: '&uiSortableBeforeStop',
  34. update: '&uiSortableUpdate',
  35. remove: '&uiSortableRemove',
  36. receive: '&uiSortableReceive',
  37. deactivate: '&uiSortableDeactivate',
  38. stop: '&uiSortableStop'
  39. },
  40. link: function(scope, element, attrs, ngModel) {
  41. var savedNodes;
  42. var helper;
  43.  
  44. function combineCallbacks(first, second) {
  45. var firstIsFunc = typeof first === 'function';
  46. var secondIsFunc = typeof second === 'function';
  47. if (firstIsFunc && secondIsFunc) {
  48. return function() {
  49. first.apply(this, arguments);
  50. second.apply(this, arguments);
  51. };
  52. } else if (secondIsFunc) {
  53. return second;
  54. }
  55. return first;
  56. }
  57.  
  58. function getSortableWidgetInstance(element) {
  59. // this is a fix to support jquery-ui prior to v1.11.x
  60. // otherwise we should be using `element.sortable('instance')`
  61. var data = element.data('ui-sortable');
  62. if (
  63. data &&
  64. typeof data === 'object' &&
  65. data.widgetFullName === 'ui-sortable'
  66. ) {
  67. return data;
  68. }
  69. return null;
  70. }
  71.  
  72. function setItemChildrenWidth(item) {
  73. item.children().each(function() {
  74. var $el = angular.element(this);
  75.  
  76. // Preserve the with of the element
  77. $el.width($el.width());
  78. });
  79. }
  80.  
  81. function dummyHelper(e, item) {
  82. return item;
  83. }
  84.  
  85. function patchSortableOption(key, value) {
  86. if (callbacks[key]) {
  87. if (key === 'stop') {
  88. // call apply after stop
  89. value = combineCallbacks(value, function() {
  90. scope.$apply();
  91. });
  92.  
  93. value = combineCallbacks(value, afterStop);
  94. }
  95. // wrap the callback
  96. value = combineCallbacks(callbacks[key], value);
  97. } else if (wrappers[key]) {
  98. value = wrappers[key](value);
  99. }
  100.  
  101. // patch the options that need to have values set
  102. if (!value && (key === 'items' || key === 'ui-model-items')) {
  103. value = uiSortableConfig.items;
  104. }
  105.  
  106. return value;
  107. }
  108.  
  109. function patchUISortableOptions(
  110. newOpts,
  111. oldOpts,
  112. sortableWidgetInstance
  113. ) {
  114. function addDummyOptionKey(value, key) {
  115. if (!(key in opts)) {
  116. // add the key in the opts object so that
  117. // the patch function detects and handles it
  118. opts[key] = null;
  119. }
  120. }
  121. // for this directive to work we have to attach some callbacks
  122. angular.forEach(callbacks, addDummyOptionKey);
  123.  
  124. // only initialize it in case we have to
  125. // update some options of the sortable
  126. var optsDiff = null;
  127.  
  128. if (oldOpts) {
  129. // reset deleted options to default
  130. var defaultOptions;
  131. angular.forEach(oldOpts, function(oldValue, key) {
  132. if (!newOpts || !(key in newOpts)) {
  133. if (key in directiveOpts) {
  134. if (key === 'ui-floating') {
  135. opts[key] = 'auto';
  136. } else {
  137. opts[key] = patchSortableOption(key, undefined);
  138. }
  139. return;
  140. }
  141.  
  142. if (!defaultOptions) {
  143. defaultOptions = angular.element.ui.sortable().options;
  144. }
  145. var defaultValue = defaultOptions[key];
  146. defaultValue = patchSortableOption(key, defaultValue);
  147.  
  148. if (!optsDiff) {
  149. optsDiff = {};
  150. }
  151. optsDiff[key] = defaultValue;
  152. opts[key] = defaultValue;
  153. }
  154. });
  155. }
  156.  
  157. newOpts = angular.extend({}, newOpts);
  158. // update changed options
  159. // handle the custom option of the directive first
  160. angular.forEach(newOpts, function(value, key) {
  161. if (key in directiveOpts) {
  162. if (
  163. key === 'ui-floating' &&
  164. (value === false || value === true) &&
  165. sortableWidgetInstance
  166. ) {
  167. sortableWidgetInstance.floating = value;
  168. }
  169.  
  170. if (
  171. key === 'ui-preserve-size' &&
  172. (value === false || value === true)
  173. ) {
  174. var userProvidedHelper = opts.helper;
  175. newOpts.helper = function(e, item) {
  176. if (opts['ui-preserve-size'] === true) {
  177. setItemChildrenWidth(item);
  178. }
  179. return (userProvidedHelper || dummyHelper).apply(
  180. this,
  181. arguments
  182. );
  183. };
  184. }
  185.  
  186. opts[key] = patchSortableOption(key, value);
  187. }
  188. });
  189.  
  190. // handle the normal option of the directive
  191. angular.forEach(newOpts, function(value, key) {
  192. if (key in directiveOpts) {
  193. // the custom option of the directive are already handled
  194. return;
  195. }
  196.  
  197. value = patchSortableOption(key, value);
  198.  
  199. if (!optsDiff) {
  200. optsDiff = {};
  201. }
  202. optsDiff[key] = value;
  203. opts[key] = value;
  204. });
  205.  
  206. return optsDiff;
  207. }
  208.  
  209. function getPlaceholderElement(element) {
  210. var placeholder = element.sortable('option', 'placeholder');
  211.  
  212. // placeholder.element will be a function if the placeholder, has
  213. // been created (placeholder will be an object). If it hasn't
  214. // been created, either placeholder will be false if no
  215. // placeholder class was given or placeholder.element will be
  216. // undefined if a class was given (placeholder will be a string)
  217. if (
  218. placeholder &&
  219. placeholder.element &&
  220. typeof placeholder.element === 'function'
  221. ) {
  222. var result = placeholder.element();
  223. // workaround for jquery ui 1.9.x,
  224. // not returning jquery collection
  225. result = angular.element(result);
  226. return result;
  227. }
  228. return null;
  229. }
  230.  
  231. function getPlaceholderExcludesludes(element, placeholder) {
  232. // exact match with the placeholder's class attribute to handle
  233. // the case that multiple connected sortables exist and
  234. // the placeholder option equals the class of sortable items
  235. var notCssSelector = opts['ui-model-items'].replace(/[^,]*>/g, '');
  236. var excludes = element.find(
  237. '[class="' +
  238. placeholder.attr('class') +
  239. '"]:not(' +
  240. notCssSelector +
  241. ')'
  242. );
  243. return excludes;
  244. }
  245.  
  246. function hasSortingHelper(element, ui) {
  247. var helperOption = element.sortable('option', 'helper');
  248. return (
  249. helperOption === 'clone' ||
  250. (typeof helperOption === 'function' &&
  251. ui.item.sortable.isCustomHelperUsed())
  252. );
  253. }
  254.  
  255. function getSortingHelper(element, ui /*, savedNodes*/) {
  256. var result = null;
  257. if (
  258. hasSortingHelper(element, ui) &&
  259. element.sortable('option', 'appendTo') === 'parent'
  260. ) {
  261. // The .ui-sortable-helper element (that's the default class name)
  262. result = helper;
  263. }
  264. return result;
  265. }
  266.  
  267. // thanks jquery-ui
  268. function isFloating(item) {
  269. return (
  270. /left|right/.test(item.css('float')) ||
  271. /inline|table-cell/.test(item.css('display'))
  272. );
  273. }
  274.  
  275. function getElementContext(elementScopes, element) {
  276. for (var i = 0; i < elementScopes.length; i++) {
  277. var c = elementScopes[i];
  278. if (c.element[0] === element[0]) {
  279. return c;
  280. }
  281. }
  282. }
  283.  
  284. function afterStop(e, ui) {
  285. ui.item.sortable._destroy();
  286. }
  287.  
  288. // return the index of ui.item among the items
  289. // we can't just do ui.item.index() because there it might have siblings
  290. // which are not items
  291. function getItemIndex(item) {
  292. return item
  293. .parent()
  294. .find(opts['ui-model-items'])
  295. .index(item);
  296. }
  297.  
  298. var opts = {};
  299.  
  300. // directive specific options
  301. var directiveOpts = {
  302. 'ui-floating': undefined,
  303. 'ui-model-items': uiSortableConfig.items,
  304. 'ui-preserve-size': undefined
  305. };
  306.  
  307. var callbacks = {
  308. create: null,
  309. start: null,
  310. activate: null,
  311. // sort: null,
  312. // change: null,
  313. // over: null,
  314. // out: null,
  315. beforeStop: null,
  316. update: null,
  317. remove: null,
  318. receive: null,
  319. deactivate: null,
  320. stop: null
  321. };
  322.  
  323. var wrappers = {
  324. helper: null
  325. };
  326.  
  327. angular.extend(
  328. opts,
  329. directiveOpts,
  330. uiSortableConfig,
  331. scope.uiSortable
  332. );
  333.  
  334. if (!angular.element.fn || !angular.element.fn.jquery) {
  335. $log.error(
  336. 'ui.sortable: jQuery should be included before AngularJS!'
  337. );
  338. return;
  339. }
  340.  
  341. function wireUp() {
  342. // When we add or remove elements, we need the sortable to 'refresh'
  343. // so it can find the new/removed elements.
  344. scope.$watchCollection('ngModel', function() {
  345. // Timeout to let ng-repeat modify the DOM
  346. $timeout(
  347. function() {
  348. // ensure that the jquery-ui-sortable widget instance
  349. // is still bound to the directive's element
  350. if (!!getSortableWidgetInstance(element)) {
  351. element.sortable('refresh');
  352. }
  353. },
  354. 0,
  355. false
  356. );
  357. });
  358.  
  359. callbacks.start = function(e, ui) {
  360. if (opts['ui-floating'] === 'auto') {
  361. // since the drag has started, the element will be
  362. // absolutely positioned, so we check its siblings
  363. var siblings = ui.item.siblings();
  364. var sortableWidgetInstance = getSortableWidgetInstance(
  365. angular.element(e.target)
  366. );
  367. sortableWidgetInstance.floating = isFloating(siblings);
  368. }
  369.  
  370. // Save the starting position of dragged item
  371. var index = getItemIndex(ui.item);
  372. ui.item.sortable = {
  373. model: ngModel.$modelValue[index],
  374. index: index,
  375. source: element,
  376. sourceList: ui.item.parent(),
  377. sourceModel: ngModel.$modelValue,
  378. cancel: function() {
  379. ui.item.sortable._isCanceled = true;
  380. },
  381. isCanceled: function() {
  382. return ui.item.sortable._isCanceled;
  383. },
  384. isCustomHelperUsed: function() {
  385. return !!ui.item.sortable._isCustomHelperUsed;
  386. },
  387. _isCanceled: false,
  388. _isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed,
  389. _destroy: function() {
  390. angular.forEach(ui.item.sortable, function(value, key) {
  391. ui.item.sortable[key] = undefined;
  392. });
  393. },
  394. _connectedSortables: [],
  395. _getElementContext: function(element) {
  396. return getElementContext(this._connectedSortables, element);
  397. }
  398. };
  399. };
  400.  
  401. callbacks.activate = function(e, ui) {
  402. var isSourceContext = ui.item.sortable.source === element;
  403. var savedNodesOrigin = isSourceContext
  404. ? ui.item.sortable.sourceList
  405. : element;
  406. var elementContext = {
  407. element: element,
  408. scope: scope,
  409. isSourceContext: isSourceContext,
  410. savedNodesOrigin: savedNodesOrigin
  411. };
  412. // save the directive's scope so that it is accessible from ui.item.sortable
  413. ui.item.sortable._connectedSortables.push(elementContext);
  414.  
  415. // We need to make a copy of the current element's contents so
  416. // we can restore it after sortable has messed it up.
  417. // This is inside activate (instead of start) in order to save
  418. // both lists when dragging between connected lists.
  419. savedNodes = savedNodesOrigin.contents();
  420. helper = ui.helper;
  421.  
  422. // If this list has a placeholder (the connected lists won't),
  423. // don't inlcude it in saved nodes.
  424. var placeholder = getPlaceholderElement(element);
  425. if (placeholder && placeholder.length) {
  426. var excludes = getPlaceholderExcludesludes(
  427. element,
  428. placeholder
  429. );
  430. savedNodes = savedNodes.not(excludes);
  431. }
  432. };
  433.  
  434. callbacks.update = function(e, ui) {
  435. // Save current drop position but only if this is not a second
  436. // update that happens when moving between lists because then
  437. // the value will be overwritten with the old value
  438. if (!ui.item.sortable.received) {
  439. ui.item.sortable.dropindex = getItemIndex(ui.item);
  440. var droptarget = ui.item
  441. .parent()
  442. .closest(
  443. '[ui-sortable], [data-ui-sortable], [x-ui-sortable]'
  444. );
  445. ui.item.sortable.droptarget = droptarget;
  446. ui.item.sortable.droptargetList = ui.item.parent();
  447.  
  448. var droptargetContext = ui.item.sortable._getElementContext(
  449. droptarget
  450. );
  451. ui.item.sortable.droptargetModel =
  452. droptargetContext.scope.ngModel;
  453.  
  454. // Cancel the sort (let ng-repeat do the sort for us)
  455. // Don't cancel if this is the received list because it has
  456. // already been canceled in the other list, and trying to cancel
  457. // here will mess up the DOM.
  458. element.sortable('cancel');
  459. }
  460.  
  461. // Put the nodes back exactly the way they started (this is very
  462. // important because ng-repeat uses comment elements to delineate
  463. // the start and stop of repeat sections and sortable doesn't
  464. // respect their order (even if we cancel, the order of the
  465. // comments are still messed up).
  466. var sortingHelper =
  467. !ui.item.sortable.received &&
  468. getSortingHelper(element, ui, savedNodes);
  469. if (sortingHelper && sortingHelper.length) {
  470. // Restore all the savedNodes except from the sorting helper element.
  471. // That way it will be garbage collected.
  472. savedNodes = savedNodes.not(sortingHelper);
  473. }
  474. var elementContext = ui.item.sortable._getElementContext(element);
  475. savedNodes.appendTo(elementContext.savedNodesOrigin);
  476.  
  477. // If this is the target connected list then
  478. // it's safe to clear the restored nodes since:
  479. // update is currently running and
  480. // stop is not called for the target list.
  481. if (ui.item.sortable.received) {
  482. savedNodes = null;
  483. }
  484.  
  485. // If received is true (an item was dropped in from another list)
  486. // then we add the new item to this list otherwise wait until the
  487. // stop event where we will know if it was a sort or item was
  488. // moved here from another list
  489. if (ui.item.sortable.received && !ui.item.sortable.isCanceled()) {
  490. scope.$apply(function() {
  491. ngModel.$modelValue.splice(
  492. ui.item.sortable.dropindex,
  493. 0,
  494. ui.item.sortable.moved
  495. );
  496. });
  497. scope.$emit('ui-sortable:moved', ui);
  498. }
  499. };
  500.  
  501. callbacks.stop = function(e, ui) {
  502. // If the received flag hasn't be set on the item, this is a
  503. // normal sort, if dropindex is set, the item was moved, so move
  504. // the items in the list.
  505. var wasMoved =
  506. 'dropindex' in ui.item.sortable &&
  507. !ui.item.sortable.isCanceled();
  508.  
  509. if (wasMoved && !ui.item.sortable.received) {
  510. scope.$apply(function() {
  511. ngModel.$modelValue.splice(
  512. ui.item.sortable.dropindex,
  513. 0,
  514. ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]
  515. );
  516. });
  517. scope.$emit('ui-sortable:moved', ui);
  518. } else if (
  519. !wasMoved &&
  520. !angular.equals(
  521. element.contents().toArray(),
  522. savedNodes.toArray()
  523. )
  524. ) {
  525. // if the item was not moved
  526. // and the DOM element order has changed,
  527. // then restore the elements
  528. // so that the ngRepeat's comment are correct.
  529.  
  530. var sortingHelper = getSortingHelper(element, ui, savedNodes);
  531. if (sortingHelper && sortingHelper.length) {
  532. // Restore all the savedNodes except from the sorting helper element.
  533. // That way it will be garbage collected.
  534. savedNodes = savedNodes.not(sortingHelper);
  535. }
  536. var elementContext = ui.item.sortable._getElementContext(
  537. element
  538. );
  539. savedNodes.appendTo(elementContext.savedNodesOrigin);
  540. }
  541.  
  542. // It's now safe to clear the savedNodes and helper
  543. // since stop is the last callback.
  544. savedNodes = null;
  545. helper = null;
  546. };
  547.  
  548. callbacks.receive = function(e, ui) {
  549. // An item was dropped here from another list, set a flag on the
  550. // item.
  551. ui.item.sortable.received = true;
  552. };
  553.  
  554. callbacks.remove = function(e, ui) {
  555. // Workaround for a problem observed in nested connected lists.
  556. // There should be an 'update' event before 'remove' when moving
  557. // elements. If the event did not fire, cancel sorting.
  558. if (!('dropindex' in ui.item.sortable)) {
  559. element.sortable('cancel');
  560. ui.item.sortable.cancel();
  561. }
  562.  
  563. // Remove the item from this list's model and copy data into item,
  564. // so the next list can retrive it
  565. if (!ui.item.sortable.isCanceled()) {
  566. scope.$apply(function() {
  567. ui.item.sortable.moved = ngModel.$modelValue.splice(
  568. ui.item.sortable.index,
  569. 1
  570. )[0];
  571. });
  572. }
  573. };
  574.  
  575. // setup attribute handlers
  576. angular.forEach(callbacks, function(value, key) {
  577. callbacks[key] = combineCallbacks(callbacks[key], function() {
  578. var attrHandler = scope[key];
  579. var attrHandlerFn;
  580. if (
  581. typeof attrHandler === 'function' &&
  582. (
  583. 'uiSortable' +
  584. key.substring(0, 1).toUpperCase() +
  585. key.substring(1)
  586. ).length &&
  587. typeof (attrHandlerFn = attrHandler()) === 'function'
  588. ) {
  589. attrHandlerFn.apply(this, arguments);
  590. }
  591. });
  592. });
  593.  
  594. wrappers.helper = function(inner) {
  595. if (inner && typeof inner === 'function') {
  596. return function(e, item) {
  597. var oldItemSortable = item.sortable;
  598. var index = getItemIndex(item);
  599.  
  600. item.sortable = {
  601. model: ngModel.$modelValue[index],
  602. index: index,
  603. source: element,
  604. sourceList: item.parent(),
  605. sourceModel: ngModel.$modelValue,
  606. _restore: function() {
  607. angular.forEach(item.sortable, function(value, key) {
  608. item.sortable[key] = undefined;
  609. });
  610.  
  611. item.sortable = oldItemSortable;
  612. }
  613. };
  614.  
  615. var innerResult = inner.apply(this, arguments);
  616. item.sortable._restore();
  617. item.sortable._isCustomHelperUsed = item !== innerResult;
  618. return innerResult;
  619. };
  620. }
  621. return inner;
  622. };
  623.  
  624. scope.$watchCollection(
  625. 'uiSortable',
  626. function(newOpts, oldOpts) {
  627. // ensure that the jquery-ui-sortable widget instance
  628. // is still bound to the directive's element
  629. var sortableWidgetInstance = getSortableWidgetInstance(element);
  630. if (!!sortableWidgetInstance) {
  631. var optsDiff = patchUISortableOptions(
  632. newOpts,
  633. oldOpts,
  634. sortableWidgetInstance
  635. );
  636.  
  637. if (optsDiff) {
  638. element.sortable('option', optsDiff);
  639. }
  640. }
  641. },
  642. true
  643. );
  644.  
  645. patchUISortableOptions(opts);
  646. }
  647.  
  648. function init() {
  649. if (ngModel) {
  650. wireUp();
  651. } else {
  652. $log.info('ui.sortable: ngModel not provided!', element);
  653. }
  654.  
  655. // Create sortable
  656. element.sortable(opts);
  657. }
  658.  
  659. function initIfEnabled() {
  660. if (scope.uiSortable && scope.uiSortable.disabled) {
  661. return false;
  662. }
  663.  
  664. init();
  665.  
  666. // Stop Watcher
  667. initIfEnabled.cancelWatcher();
  668. initIfEnabled.cancelWatcher = angular.noop;
  669.  
  670. return true;
  671. }
  672.  
  673. initIfEnabled.cancelWatcher = angular.noop;
  674.  
  675. if (!initIfEnabled()) {
  676. initIfEnabled.cancelWatcher = scope.$watch(
  677. 'uiSortable.disabled',
  678. initIfEnabled
  679. );
  680. }
  681. }
  682. };
  683. }
  684. ]);

sortable结合angularjs实现拖动排序的更多相关文章

  1. 基于Metronic的Bootstrap开发框架经验总结(13)--页面链接收藏夹功能的实现2(利用Sortable进行拖动排序)

    在上篇随笔<基于Metronic的Bootstrap开发框架经验总结(12)--页面链接收藏夹功能的实现>上,我介绍了链接收藏夹功能的实现,以及对收藏记录的排序处理.该篇随笔主要使用功能按 ...

  2. 锋利的jQuery-7--query ui效果库--拖动排序插件sortable

    一个简单的拖动排序效果,具体请参看jQuery ui官网demo. jquery ui :http://jqueryui.com/ sortable例子:http://jqueryui.com/sor ...

  3. Element-UI标签页el-tabs组件的拖动排序实现

    ElementUI的标签页组件支持动态添加删除,如下图: 但是这个组件不支持标签之间的拖动排序.那么我们自己怎样实现这个功能呢? 有一个叫vuedraggable的组件(https://github. ...

  4. jquery 鼠标拖动排序Li或Table

    1.前端页面 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="拖动排序Li或Ta ...

  5. 记一个react拖动排序中的坑:key

    在做一个基于react的应用的时候遇到了对列表拖动排序的需求.当使用sortable对列表添加排序支持后发现一个问题:数据正确排序了,但是dom的顺序却乱了,找了一会儿原因后发现是因为在渲染数据的时候 ...

  6. elementui---表格拖动排序的问题

    刚刚用elementui的表格,需要用到一个拖动排序的需求,简单弄了下,使用 Sorttable 来做还是挺快的,但是发现一个问题,拖动排序显示不正常. <el-table :data=&quo ...

  7. android可拖动排序GridView实现

    经常使用今日头条.网易新闻的同学们应该都会注意到用于管理多个频道的可拖动排序GridView,下面介绍一下可拖动的DragGridView的实现方法.代码放在GitHub上https://github ...

  8. RecyclerView-- 侧滑删除和拖动排序

    实现这么个功能我们不需要再去继承RecyclerView,只需要去了解ItemTouchHelper这个类即可,接下来我们就去看看都有些什么 ItemTouchHelper.Callback 默认需要 ...

  9. IOS UITableView拖动排序功能

    UITbableView作为列表展示信息,除了展示的功能,有时还会用到删除,排序等功能,下面就来讲解一下如何实现排序. 排序是当表格进入编辑状态后,在单元格的右侧会出现一个按钮,点击按钮,就可以拖动单 ...

随机推荐

  1. 搭建 Http Dynamic Streaming 点播/直播服务器

    1.        HTTP Origin Module的处理数据流: a)         客户端发送媒体索引请求到Apache.例如: http://www.example.com/media/  ...

  2. ACM学习历程—HDU5423 Rikka with Tree(搜索)

    Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...

  3. [转]angularjs的provider~ (Provider, Value, Constant, Service, Factory, Decorator)

    用AngularJS做项目,但凡用过什么service啊,factory啊,provider啊,开始的时候晕没晕?!晕没晕?!感觉干的事儿都差不多啊,到底用哪个啊?!别告诉我你们几个就是为了跟我炫耀兄 ...

  4. 桥接以及Mercury MW54R中继

    家里连个路由器,一个是比较先进的TP-Link的TL-WR842N(100M),另外一个是比较古老的水星(Mercury) MW54R(54M),我们知道新的路由器都有WDS功能,方便作为副路由器(中 ...

  5. Impala的JDBC无法连接

    这是因为客户端连接的JDBC是Impala的master机器,而不是DataNode:因为JDBC的服务宿主是Impalad,而Impalad只是部署在DataNode

  6. for循环中的条件执行循序

    问题: public class Main { public static void main(String[] args) { int i,n,length = 0; for(i=1;length& ...

  7. Hadoop十年

    于 2006 年 1 月 28 日诞生的它改变了企业对数据的存储.处理和分析的过程,加速了大数据的发展,形成了自己的极其火爆的技术生态圈,并受到非常广泛的应用.在此为大家梳理 Hadoop 这十年的变 ...

  8. HDOJ1251(前缀匹配---分块查找&map应用)

    分块查找算法 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm ...

  9. jquery 键盘事件的使用方法详解

    转自:https://www.jb51.net/article/123579.htm jQuery处理键盘事件有三个函数,根据事件发生的顺序分别是: jquery 代码: 1.  keydown(); ...

  10. HTTP返回码中301与302的区别

    一.官方说法 301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于: 301 redirect: 301 代表永久性转移(Permanently Moved). 302 ...