|
| 1 | +export default function jqLiteExtrasRegister(element) { |
| 2 | + var convertToPx, css, getStyle, isWindow; |
| 3 | + // angular implementation blows up if elem is the window |
| 4 | + css = angular.element.prototype.css; |
| 5 | + |
| 6 | + element.prototype.css = function (name, value) { |
| 7 | + let self = this; |
| 8 | + let elem = self[0]; |
| 9 | + if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) { |
| 10 | + return css.call(self, name, value); |
| 11 | + } |
| 12 | + }; |
| 13 | + |
| 14 | + // as defined in angularjs v1.0.5 |
| 15 | + isWindow = (obj) => obj && obj.document && obj.location && obj.alert && obj.setInterval; |
| 16 | + |
| 17 | + function scrollTo(self, direction, value) { |
| 18 | + let elem = self[0]; |
| 19 | + let [method, prop, preserve] = { |
| 20 | + top: [ |
| 21 | + 'scrollTop', |
| 22 | + 'pageYOffset', |
| 23 | + 'scrollLeft' |
| 24 | + ], |
| 25 | + left: [ |
| 26 | + 'scrollLeft', |
| 27 | + 'pageXOffset', |
| 28 | + 'scrollTop' |
| 29 | + ] |
| 30 | + }[direction]; |
| 31 | + |
| 32 | + if (isWindow(elem)) { |
| 33 | + if (angular.isDefined(value)) { |
| 34 | + return elem.scrollTo(self[preserve].call(self), value); |
| 35 | + } |
| 36 | + |
| 37 | + return (prop in elem) ? elem[prop] : elem.document.documentElement[method]; |
| 38 | + } else { |
| 39 | + if (angular.isDefined(value)) { |
| 40 | + elem[method] = value; |
| 41 | + } |
| 42 | + |
| 43 | + return elem[method]; |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + if (window.getComputedStyle) { |
| 48 | + getStyle = (elem) => window.getComputedStyle(elem, null); |
| 49 | + convertToPx = (elem, value) => parseFloat(value); |
| 50 | + } else { |
| 51 | + getStyle = (elem) => elem.currentStyle; |
| 52 | + convertToPx = (elem, value) => { |
| 53 | + let left, result, rs, rsLeft, style; |
| 54 | + let core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source; |
| 55 | + let rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i'); |
| 56 | + |
| 57 | + if (!rnumnonpx.test(value)) { |
| 58 | + return parseFloat(value); |
| 59 | + } |
| 60 | + |
| 61 | + // ported from JQuery |
| 62 | + style = elem.style; |
| 63 | + left = style.left; |
| 64 | + rs = elem.runtimeStyle; |
| 65 | + rsLeft = rs && rs.left; |
| 66 | + if (rs) { |
| 67 | + rs.left = style.left; |
| 68 | + } |
| 69 | + // put in the new values to get a computed style out |
| 70 | + style.left = value; |
| 71 | + result = style.pixelLeft; |
| 72 | + style.left = left; |
| 73 | + if (rsLeft) { |
| 74 | + rs.left = rsLeft; |
| 75 | + } |
| 76 | + return result; |
| 77 | + }; |
| 78 | + } |
| 79 | + |
| 80 | + function getMeasurements(elem, measure) { |
| 81 | + let base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB; |
| 82 | + |
| 83 | + if (isWindow(elem)) { |
| 84 | + base = document.documentElement[{height: 'clientHeight', width: 'clientWidth'}[measure]]; |
| 85 | + |
| 86 | + return { |
| 87 | + base: base, |
| 88 | + padding: 0, |
| 89 | + border: 0, |
| 90 | + margin: 0 |
| 91 | + }; |
| 92 | + } |
| 93 | + |
| 94 | + // Start with offset property |
| 95 | + [ |
| 96 | + base, |
| 97 | + dirA, |
| 98 | + dirB |
| 99 | + ] = { |
| 100 | + width: [ |
| 101 | + elem.offsetWidth, |
| 102 | + 'Left', |
| 103 | + 'Right' |
| 104 | + ], |
| 105 | + height: [ |
| 106 | + elem.offsetHeight, |
| 107 | + 'Top', |
| 108 | + 'Bottom' |
| 109 | + ] |
| 110 | + }[measure]; |
| 111 | + |
| 112 | + computedStyle = getStyle(elem); |
| 113 | + paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0; |
| 114 | + paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0; |
| 115 | + borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0; |
| 116 | + borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0; |
| 117 | + computedMarginA = computedStyle['margin' + dirA]; |
| 118 | + computedMarginB = computedStyle['margin' + dirB]; |
| 119 | + |
| 120 | + // I do not care for width for now, so this hack is irrelevant |
| 121 | + // if ( !supportsPercentMargin ) |
| 122 | + // computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA ) |
| 123 | + // computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB ) |
| 124 | + marginA = convertToPx(elem, computedMarginA) || 0; |
| 125 | + marginB = convertToPx(elem, computedMarginB) || 0; |
| 126 | + |
| 127 | + return { |
| 128 | + base: base, |
| 129 | + padding: paddingA + paddingB, |
| 130 | + border: borderA + borderB, |
| 131 | + margin: marginA + marginB |
| 132 | + }; |
| 133 | + } |
| 134 | + |
| 135 | + function getWidthHeight(elem, direction, measure) { |
| 136 | + let computedStyle, result; |
| 137 | + |
| 138 | + let measurements = getMeasurements(elem, direction); |
| 139 | + |
| 140 | + if (measurements.base > 0) { |
| 141 | + return { |
| 142 | + base: measurements.base - measurements.padding - measurements.border, |
| 143 | + outer: measurements.base, |
| 144 | + outerfull: measurements.base + measurements.margin |
| 145 | + }[measure]; |
| 146 | + } |
| 147 | + |
| 148 | + // Fall back to computed then uncomputed css if necessary |
| 149 | + computedStyle = getStyle(elem); |
| 150 | + result = computedStyle[direction]; |
| 151 | + |
| 152 | + if (result < 0 || result === null) { |
| 153 | + result = elem.style[direction] || 0; |
| 154 | + } |
| 155 | + |
| 156 | + // Normalize "", auto, and prepare for extra |
| 157 | + result = parseFloat(result) || 0; |
| 158 | + |
| 159 | + return { |
| 160 | + base: result - measurements.padding - measurements.border, |
| 161 | + outer: result, |
| 162 | + outerfull: result + measurements.padding + measurements.border + measurements.margin |
| 163 | + }[measure]; |
| 164 | + } |
| 165 | + |
| 166 | + // define missing methods |
| 167 | + return angular.forEach({ |
| 168 | + before(newElem) { |
| 169 | + var children, elem, i, j, parent, ref, self; |
| 170 | + self = this; |
| 171 | + elem = self[0]; |
| 172 | + parent = self.parent(); |
| 173 | + children = parent.contents(); |
| 174 | + if (children[0] === elem) { |
| 175 | + return parent.prepend(newElem); |
| 176 | + } else { |
| 177 | + for (i = j = 1, ref = children.length - 1; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) { |
| 178 | + if (children[i] === elem) { |
| 179 | + angular.element(children[i - 1]).after(newElem); |
| 180 | + return; |
| 181 | + } |
| 182 | + } |
| 183 | + throw new Error('invalid DOM structure ' + elem.outerHTML); |
| 184 | + } |
| 185 | + }, |
| 186 | + height (value){ |
| 187 | + var self; |
| 188 | + self = this; |
| 189 | + if (angular.isDefined(value)) { |
| 190 | + if (angular.isNumber(value)) { |
| 191 | + value = value + 'px'; |
| 192 | + } |
| 193 | + return css.call(self, 'height', value); |
| 194 | + } else { |
| 195 | + return getWidthHeight(this[0], 'height', 'base'); |
| 196 | + } |
| 197 | + }, |
| 198 | + outerHeight(option) { |
| 199 | + return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer'); |
| 200 | + }, |
| 201 | + |
| 202 | + /* |
| 203 | + The offset setter method is not implemented |
| 204 | + */ |
| 205 | + offset(value) { |
| 206 | + let docElem, win; |
| 207 | + let self = this; |
| 208 | + let box = { |
| 209 | + top: 0, |
| 210 | + left: 0 |
| 211 | + }; |
| 212 | + let elem = self[0]; |
| 213 | + let doc = elem && elem.ownerDocument; |
| 214 | + |
| 215 | + if (arguments.length) { |
| 216 | + if (value === undefined) { |
| 217 | + return self; |
| 218 | + } |
| 219 | + // TODO: implement setter |
| 220 | + throw new Error('offset setter method is not implemented'); |
| 221 | + } |
| 222 | + |
| 223 | + if (!doc) { |
| 224 | + return; |
| 225 | + } |
| 226 | + |
| 227 | + docElem = doc.documentElement; |
| 228 | + |
| 229 | + // TODO: Make sure it's not a disconnected DOM node |
| 230 | + |
| 231 | + if (elem.getBoundingClientRect != null) { |
| 232 | + box = elem.getBoundingClientRect(); |
| 233 | + } |
| 234 | + |
| 235 | + win = doc.defaultView || doc.parentWindow; |
| 236 | + |
| 237 | + return { |
| 238 | + top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0), |
| 239 | + left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0) |
| 240 | + }; |
| 241 | + }, |
| 242 | + scrollTop(value) { |
| 243 | + return scrollTo(this, 'top', value); |
| 244 | + }, |
| 245 | + scrollLeft(value) { |
| 246 | + return scrollTo(this, 'left', value); |
| 247 | + } |
| 248 | + }, (value, key) => { |
| 249 | + if (!element.prototype[key]) { |
| 250 | + return element.prototype[key] = value; |
| 251 | + } |
| 252 | + }); |
| 253 | +} |
0 commit comments