Skip to content

Commit

Permalink
chore: Replace jQuery with native API calls (#86)
Browse files Browse the repository at this point in the history
* Remove jQuery from dev convenience utilities
* Remove jquery and jquery types from dependencies
* Removed jQuery from notification center panel
* Removed jQuery from viewPort lib
* Remove jQuery from ActiveRundownView
* Removed jQuery from VideoEditMonitor
* Removed jQuery from ClockView
* Removed jQuery from PrompterView
** Replace references to removed method PrompterViewInner#getScrollPosition() with window.scrollY
* Removed jQuery from RundownView
* Removed jQuery from RundownFullscreenControls
* Removed jQuery from SegmentTimeline renderers
* Removed jQuery from SegmentTimeline
* Removed jQuery from SegmentTimelineLine
* Removed jQuery from SegmentTimelineZoomControls
* Removed jQuery from SourceLayerItem
* Removed jQuery from TimelineGrid
* Removed jQuery from AdLibPanel
* Removed jQuery from Shelf component
* Removed jQuery entry from startup dependency omission list
* getElementWidth util now replicates jQuery width() behavior
* Remove jQuery from SegmentTimelineContainer
* Implement client lib loadscript() without using jQuery
  • Loading branch information
gundelsby committed Jun 12, 2019
1 parent 08b4a2c commit a35b80d
Show file tree
Hide file tree
Showing 37 changed files with 4,022 additions and 3,620 deletions.
70 changes: 70 additions & 0 deletions meteor/client/__tests__/utils/dimensions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { getElementWidth, getElementHeight } from '../../utils/dimensions'
import { createSandbox } from 'sinon'

const sandbox = createSandbox()

describe('client/utils/dimensions', () => {
let getComputedStyle

beforeEach(() => {
getComputedStyle = sandbox.stub(window, 'getComputedStyle')
})

afterEach(() => {
sandbox.restore()
})

describe('getElementWidth', () => {
test('returns width from getComputedStyle when it has a numeric value', () => {
const expected = 20;
const element = document.createElement('div');
getComputedStyle.withArgs(element).returns({ width: expected })

const actual = getElementWidth(element)

expect(actual).toEqual(expected)
})

test('returns element.offsetWidth - computed horizontal padding when computed width is auto', () => {
const paddingLeft = 10
const paddingRight = 15
const offsetWidth = 63
const expected = offsetWidth - paddingLeft - paddingRight

const element = document.createElement('div');
Object.defineProperty(element, 'offsetWidth', { value: offsetWidth })
getComputedStyle.withArgs(element).returns({ width: 'auto', paddingLeft, paddingRight })

const actual = getElementWidth(element)

expect(actual).toEqual(expected)
})
})

describe('getElementHeight', () => {
test('returns height from getComputedStyle when it has a numeric value', () => {
const expected = 20;
const element = document.createElement('div');
getComputedStyle.withArgs(element).returns({ height: expected })

const actual = getElementHeight(element)

expect(actual).toEqual(expected)
})

test('returns element.scrollHeight - computed vertical padding when computed height is auto', () => {
const paddingTop = 8
const paddingBottom = 9
const scrollHeight = 37
const expected = scrollHeight - paddingTop - paddingBottom

const element = document.createElement('div');
Object.defineProperty(element, 'scrollHeight', { value: scrollHeight })
getComputedStyle.withArgs(element).returns({ height: 'auto', paddingTop, paddingBottom })

const actual = getElementHeight(element)

expect(actual).toEqual(expected)
})
})
})
95 changes: 95 additions & 0 deletions meteor/client/__tests__/utils/positions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { getElementDocumentOffset } from '../../utils/positions'

describe('getElementDocumentOffset', () => {
const emptyRect: ClientRect = {
top: 0,
left: 0,
bottom: 0,
right: 0,
height: 0,
width: 0
}

test('should return null for null input', () => {
const actual = getElementDocumentOffset(null)

expect(actual).toBe(null)
})


describe('{top}', () => {
test('should be 0 when bounding client rect top is 0 and window.scrollY is 0', () => {
Object.defineProperty(window, 'scrollY', { value: 0 })
const container = document.createElement('div');
container.getBoundingClientRect = (): ClientRect => {
return Object.assign({}, emptyRect, { top: 0 })
}

const actual = getElementDocumentOffset(container)

expect(actual).toHaveProperty('top', 0)
})

test('should be 20 when bounding client rect top is 20 and window.scrollY is 0', () => {
Object.defineProperty(window, 'scrollY', { value: 0 })
const container = document.createElement('div');
container.getBoundingClientRect = (): ClientRect => {
return Object.assign({}, emptyRect, { top: 20 })
}

const actual = getElementDocumentOffset(container)

expect(actual).toHaveProperty('top', 20)
})

test('should be 31 when bounding client rect top is 10 and window.scrollY is 21', () => {
Object.defineProperty(window, 'scrollY', { value: 21 })
const container = document.createElement('div');
container.getBoundingClientRect = (): ClientRect => {
return Object.assign({}, emptyRect, { top: 10 })
}

const actual = getElementDocumentOffset(container)

expect(actual).toHaveProperty('top', 31)
})
})

describe('{left}', () => {
test('should be 0 when bounding client rect left is 0 and window.scrollX is 0', () => {
Object.defineProperty(window, 'scrollY', { value: 0 })
const container = document.createElement('div');
container.getBoundingClientRect = (): ClientRect => {
return Object.assign({}, emptyRect, { left: 0 })
}

const actual = getElementDocumentOffset(container)

expect(actual).toHaveProperty('left', 0)
})

test('should be 18 when bounding client rect left is 18 and window.scrollX is 0', () => {
Object.defineProperty(window, 'scrollX', { value: 0 })
const container = document.createElement('div');
container.getBoundingClientRect = (): ClientRect => {
return Object.assign({}, emptyRect, { left: 18 })
}

const actual = getElementDocumentOffset(container)

expect(actual).toHaveProperty('left', 18)
})

test('should be 42 when bounding client rect left is 2 and window.scrollX is 40', () => {
Object.defineProperty(window, 'scrollX', { value: 40 })
const container = document.createElement('div');
container.getBoundingClientRect = (): ClientRect => {
return Object.assign({}, emptyRect, { left: 2 })
}

const actual = getElementDocumentOffset(container)

expect(actual).toHaveProperty('left', 42)
})
})
})
3 changes: 0 additions & 3 deletions meteor/client/lib/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Session } from 'meteor/session'
import { Meteor } from 'meteor/meteor'
import { Tracker } from 'meteor/tracker'
import * as _ from 'underscore'
import * as $ from 'jquery'

// Note: These things are convenience functions to be used during development:

Expand All @@ -14,7 +13,6 @@ Meteor.startup(() => {
})
})

window['$'] = $
window['Collections'] = Collections
window['executeFunction'] = PeripheralDeviceAPI.executeFunction
window['getCurrentTime'] = getCurrentTime
Expand Down Expand Up @@ -48,5 +46,4 @@ export function expectToRunWithin (name, time: number = 1000) {
console.error('Expected to run within ' + time + 'ms: ' + name)
}, time)
expectToRunWithinCache[name] = timeout

}
61 changes: 35 additions & 26 deletions meteor/client/lib/lib.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,63 @@
import * as _ from 'underscore'
import * as React from 'react'

export function multilineText (txt: string) {
export {multilineText, isEventInInputField, loadScript}

function multilineText (txt: string) {
return _.map((txt + '').split('\n'), (line: string, i) => {
return <p key={i}>{line}</p>
})
}
export function isEventInInputField (e: Event) {

function isEventInInputField (e: Event) {
// @ts-ignore localName
return (e && e.target && ['textarea', 'input'].indexOf(e.target.localName + '') !== -1)
}

const loadScriptCache: {[url: string]: {
status: 'loading' | 'ok',
callbacks: Array<(err?: any) => void>
}} = {}
export function loadScript (url: string, callback: (err?: any) => void) {

function doCallback (url:string, err?: any) {
loadScriptCache[url].callbacks.forEach((cb) => {
cb(err)
})
loadScriptCache[url].status = 'ok'
}

function loadScript (url: string, callback: (err?: any) => void) {
if ((loadScriptCache[url] || {}).status === 'ok') {
// already loaded
callback()
} else if ((loadScriptCache[url] || {}).status === 'loading') {
return
}

if ((loadScriptCache[url] || {}).status === 'loading') {
loadScriptCache[url].callbacks.push(callback)
} else {
loadScriptCache[url] = {
status: 'loading',
callbacks: [callback]
}
const doCallback = (err?: any) => {
loadScriptCache[url].callbacks.forEach((cb) => {
cb(err)
})
loadScriptCache[url].status = 'ok'
}
$.ajax({
url: url,
dataType: 'script',
success: () => {
doCallback()
},
error: (err) => {
doCallback(err)
}
})
return
}

loadScriptCache[url] = {
status: 'loading',
callbacks: [callback]
}

const script:HTMLScriptElement = document.createElement('script')
script.onerror = (error) => {
doCallback(url, error)
}
script.onload = () => {
doCallback(url)
}

document.head.appendChild(script)
script.src = url
}
/**
* Wrapper around fetch(), which doesn't rejects the promise if the result is an error
*/
export function fetchFrom (input: RequestInfo, init?: RequestInit) {

return fetch(input, init)
.then((response) => {
// Read the body:
Expand Down

0 comments on commit a35b80d

Please sign in to comment.