reorderable.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // TODO: it'd be great to merge it with the other canReorder functionality
  2. var FLEX_PROPERTIES = /align\-items|box\-align|box\-pack|flex|justify/;
  3. var BORDER_PROPERTIES = /^border\-(top|right|bottom|left|color|style|width|radius)/;
  4. function canReorder(left, right) {
  5. for (var i = right.length - 1; i >= 0; i--) {
  6. for (var j = left.length - 1; j >= 0; j--) {
  7. if (!canReorderSingle(left[j], right[i]))
  8. return false;
  9. }
  10. }
  11. return true;
  12. }
  13. function canReorderSingle(left, right) {
  14. var leftName = left[0];
  15. var leftValue = left[1];
  16. var leftNameRoot = left[2];
  17. var leftSelector = left[5];
  18. var leftInSpecificSelector = left[6];
  19. var rightName = right[0];
  20. var rightValue = right[1];
  21. var rightNameRoot = right[2];
  22. var rightSelector = right[5];
  23. var rightInSpecificSelector = right[6];
  24. if (leftName == 'font' && rightName == 'line-height' || rightName == 'font' && leftName == 'line-height')
  25. return false;
  26. if (FLEX_PROPERTIES.test(leftName) && FLEX_PROPERTIES.test(rightName))
  27. return false;
  28. if (leftNameRoot == rightNameRoot && unprefixed(leftName) == unprefixed(rightName) && (vendorPrefixed(leftName) ^ vendorPrefixed(rightName)))
  29. return false;
  30. if (leftNameRoot == 'border' && BORDER_PROPERTIES.test(rightNameRoot) && (leftName == 'border' || leftName == rightNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
  31. return false;
  32. if (rightNameRoot == 'border' && BORDER_PROPERTIES.test(leftNameRoot) && (rightName == 'border' || rightName == leftNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
  33. return false;
  34. if (leftNameRoot == 'border' && rightNameRoot == 'border' && leftName != rightName && (isSideBorder(leftName) && isStyleBorder(rightName) || isStyleBorder(leftName) && isSideBorder(rightName)))
  35. return false;
  36. if (leftNameRoot != rightNameRoot)
  37. return true;
  38. if (leftName == rightName && leftNameRoot == rightNameRoot && (leftValue == rightValue || withDifferentVendorPrefix(leftValue, rightValue)))
  39. return true;
  40. if (leftName != rightName && leftNameRoot == rightNameRoot && leftName != leftNameRoot && rightName != rightNameRoot)
  41. return true;
  42. if (leftName != rightName && leftNameRoot == rightNameRoot && leftValue == rightValue)
  43. return true;
  44. if (rightInSpecificSelector && leftInSpecificSelector && !inheritable(leftNameRoot) && !inheritable(rightNameRoot) && selectorsDoNotOverlap(rightSelector, leftSelector))
  45. return true;
  46. return false;
  47. }
  48. function vendorPrefixed(name) {
  49. return /^\-(?:moz|webkit|ms|o)\-/.test(name);
  50. }
  51. function unprefixed(name) {
  52. return name.replace(/^\-(?:moz|webkit|ms|o)\-/, '');
  53. }
  54. function sameBorderComponent(name1, name2) {
  55. return name1.split('-').pop() == name2.split('-').pop();
  56. }
  57. function isSideBorder(name) {
  58. return name == 'border-top' || name == 'border-right' || name == 'border-bottom' || name == 'border-left';
  59. }
  60. function isStyleBorder(name) {
  61. return name == 'border-color' || name == 'border-style' || name == 'border-width';
  62. }
  63. function withDifferentVendorPrefix(value1, value2) {
  64. return vendorPrefixed(value1) && vendorPrefixed(value2) && value1.split('-')[1] != value2.split('-')[2];
  65. }
  66. function selectorsDoNotOverlap(s1, s2) {
  67. for (var i = 0, l = s1.length; i < l; i++) {
  68. for (var j = 0, m = s2.length; j < m; j++) {
  69. if (s1[i][0] == s2[j][0])
  70. return false;
  71. }
  72. }
  73. return true;
  74. }
  75. function inheritable(name) {
  76. // According to http://www.w3.org/TR/CSS21/propidx.html
  77. // Others will be catched by other, preceeding rules
  78. return name == 'font' || name == 'line-height' || name == 'list-style';
  79. }
  80. module.exports = {
  81. canReorder: canReorder,
  82. canReorderSingle: canReorderSingle
  83. };