Quellcode durchsuchen

start to remove el from component/view

Adam Shaw vor 8 Jahren
Ursprung
Commit
21322a9993

+ 1 - 1
src/Calendar.ts

@@ -488,7 +488,7 @@ export default class Calendar {
 
       newView.startBatchRender() // so that setElement+setDate rendering are joined
       newView.setElement(
-        $("<div class='fc-view fc-" + viewType + "-view' />").appendTo(this.contentEl)
+        $("<div class='fc-view fc-" + viewType + "-view' />").appendTo(this.contentEl)[0]
       )
 
       this.toolbarsManager.proxyCall('activateButton', viewType)

+ 16 - 11
src/agenda/AgendaView.ts

@@ -8,6 +8,7 @@ import {
   htmlEscape,
   copyOwnProps
 } from '../util'
+import { findElsWithin, makeElement } from '../util/dom'
 import Scroller from '../common/Scroller'
 import View from '../View'
 import TimeGrid from './TimeGrid'
@@ -80,24 +81,26 @@ export default class AgendaView extends View {
     let timeGridWrapEl
     let timeGridEl
 
-    this.el.addClass('fc-agenda-view').html(this.renderSkeletonHtml())
+    this.el.classList.add('fc-agenda-view')
+    this.el.innerHTML = this.renderSkeletonHtml()
 
     this.scroller.render()
 
     timeGridWrapEl = this.scroller.el
     timeGridWrapEl.classList.add('fc-time-grid-container')
-    timeGridEl = $('<div class="fc-time-grid" />').appendTo(timeGridWrapEl)
+    timeGridEl = makeElement('div', { className: 'fc-time-grid' })
+    timeGridWrapEl.appendChild(timeGridEl)
 
-    this.el.find('.fc-body > tr > td').append(timeGridWrapEl)
+    this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl)
 
-    this.timeGrid.headContainerEl = this.el[0].querySelector('.fc-head-container')
+    this.timeGrid.headContainerEl = this.el.querySelector('.fc-head-container')
     this.timeGrid.setElement(timeGridEl)
 
     if (this.dayGrid) {
-      this.dayGrid.setElement(this.el.find('.fc-day-grid'))
+      this.dayGrid.setElement(this.el.querySelector('.fc-day-grid'))
 
       // have the day-grid extend it's coordinate area over the <hr> dividing the two grids
-      this.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight()
+      this.dayGrid.bottomCoordPadding = (this.el.querySelector('.fc-divider') as HTMLElement).offsetHeight
     }
   }
 
@@ -174,7 +177,7 @@ export default class AgendaView extends View {
     super.updateSize(totalHeight, isAuto, isResize)
 
     // make all axis cells line up, and record the width so newly created axis cells will have it
-    this.axisWidth = matchCellWidths(this.el.find('.fc-axis'))
+    this.axisWidth = matchCellWidths($(this.el.querySelectorAll('.fc-axis')))
 
     // hack to give the view some height prior to timeGrid's columns being rendered
     // TODO: separate setting height from scroller VS timeGrid.
@@ -187,12 +190,14 @@ export default class AgendaView extends View {
     }
 
     // set of fake row elements that must compensate when scroller has scrollbars
-    let noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)')
+    let noScrollRowEls: HTMLElement[] = findElsWithin(this.el, '.fc-row').filter((node) => {
+      return !this.scroller.el.contains(node)
+    })
 
     // reset all dimensions back to the original state
     this.timeGrid.bottomRuleEl.style.display = 'none' // will be shown later if this <hr> is necessary
     this.scroller.clear() // sets height to 'auto' and clears overflow
-    uncompensateScroll(noScrollRowEls)
+    uncompensateScroll($(noScrollRowEls))
 
     // limit number of events in the all-day area
     if (this.dayGrid) {
@@ -216,7 +221,7 @@ export default class AgendaView extends View {
       if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
 
         // make the all-day and header rows lines up
-        compensateScroll(noScrollRowEls, scrollbarWidths)
+        compensateScroll($(noScrollRowEls), scrollbarWidths)
 
         // the scrollbar compensation might have changed text flow, which might affect height, so recalculate
         // and reapply the desired height to the scroller.
@@ -239,7 +244,7 @@ export default class AgendaView extends View {
   // given a desired total height of the view, returns what the height of the scroller should be
   computeScrollerHeight(totalHeight) {
     return totalHeight -
-      subtractInnerElHeight(this.el, $(this.scroller.el)) // everything that's NOT the scroller
+      subtractInnerElHeight($(this.el), $(this.scroller.el)) // everything that's NOT the scroller
   }
 
 

+ 15 - 14
src/agenda/TimeGrid.ts

@@ -1,6 +1,7 @@
 import * as $ from 'jquery'
 import * as moment from 'moment'
 import { isInt, divideDurationByDuration, htmlEscape } from '../util'
+import { htmlToElement, findElsWithin, makeElement, removeElement } from '../util/dom'
 import InteractiveDateComponent from '../component/InteractiveDateComponent'
 import BusinessHourRenderer from '../component/renderers/BusinessHourRenderer'
 import StandardInteractionsMixin from '../component/interactions/StandardInteractionsMixin'
@@ -11,7 +12,6 @@ import ComponentFootprint from '../models/ComponentFootprint'
 import TimeGridEventRenderer from './TimeGridEventRenderer'
 import TimeGridHelperRenderer from './TimeGridHelperRenderer'
 import TimeGridFillRenderer from './TimeGridFillRenderer'
-import { htmlToElement, findElsWithin } from '../util/dom';
 
 /* A component that renders one or more columns of vertical time slots
 ----------------------------------------------------------------------------------------------------------------------*/
@@ -57,6 +57,7 @@ export default class TimeGrid extends InteractiveDateComponent {
   colCoordCache: any
   slatCoordCache: any
 
+  rootBgContainerEl: HTMLElement
   bottomRuleEl: HTMLElement // hidden by default
   contentSkeletonEl: HTMLElement
   colContainerEls: HTMLElement[] // containers for each column
@@ -199,20 +200,20 @@ export default class TimeGrid extends InteractiveDateComponent {
   renderSkeleton() {
     let theme = this.view.calendar.theme
 
-    this.el.html(
+    this.el.innerHTML =
       '<div class="fc-bg"></div>' +
       '<div class="fc-slats"></div>' +
       '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" style="display:none" />'
-    )
 
-    this.bottomRuleEl = this.el[0].querySelector('hr')
+    this.rootBgContainerEl = this.el.querySelector('.fc-bg')
+    this.slatContainerEl = this.el.querySelector('.fc-slats')
+    this.bottomRuleEl = this.el.querySelector('.fc-divider')
   }
 
 
   renderSlats() {
     let theme = this.view.calendar.theme
 
-    this.slatContainerEl = this.el[0].querySelector('.fc-slats')
     this.slatContainerEl.innerHTML =
       '<table class="' + theme.getClass('tableGrid') + '">' +
         this.renderSlatRowHtml() +
@@ -288,13 +289,12 @@ export default class TimeGrid extends InteractiveDateComponent {
       this.headContainerEl.innerHTML = this.renderHeadHtml()
     }
 
-    this.el.find('> .fc-bg').html(
+    this.rootBgContainerEl.innerHTML =
       '<table class="' + theme.getClass('tableGrid') + '">' +
         this.renderBgTrHtml(0) + // row=0
       '</table>'
-    )
 
-    this.colEls = findElsWithin(this.el[0], '.fc-day, .fc-disabled-day')
+    this.colEls = findElsWithin(this.el, '.fc-day, .fc-disabled-day')
 
     this.colCoordCache = new CoordCache({
       els: this.colEls,
@@ -349,13 +349,13 @@ export default class TimeGrid extends InteractiveDateComponent {
     this.businessContainerEls = findElsWithin(skeletonEl, '.fc-business-container')
 
     this.bookendCells($(skeletonEl.getElementsByTagName('tr'))) // TODO: do this on string level
-    this.el.append(skeletonEl)
+    this.el.appendChild(skeletonEl)
   }
 
 
   unrenderContentSkeleton() {
     if (this.contentSkeletonEl) { // defensive :(
-      this.contentSkeletonEl.remove()
+      removeElement(this.contentSkeletonEl)
       this.contentSkeletonEl = null
       this.colContainerEls = null
       this.helperContainerEls = null
@@ -438,9 +438,10 @@ export default class TimeGrid extends InteractiveDateComponent {
 
     // render an arrow over the axis
     if (segs.length > 0) { // is the current time in view?
-      nodes.push($('<div class="fc-now-indicator fc-now-indicator-arrow"></div>')
-        .css('top', top)
-        .appendTo(this.el.find('.fc-content-skeleton'))[0])
+      let arrowEl = makeElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' })
+      arrowEl.style.top = top + 'px'
+      this.contentSkeletonEl.appendChild(arrowEl)
+      nodes.push(arrowEl)
     }
 
     this.nowIndicatorEls = nodes
@@ -450,7 +451,7 @@ export default class TimeGrid extends InteractiveDateComponent {
   unrenderNowIndicator() {
     if (this.nowIndicatorEls) {
       this.nowIndicatorEls.forEach(function(el) {
-        el.parentNode.removeChild(el)
+        removeElement(el)
       })
       this.nowIndicatorEls = null
     }

+ 9 - 6
src/basic/BasicView.ts

@@ -8,6 +8,7 @@ import {
   undistributeHeight,
   htmlEscape
 } from '../util'
+import { makeElement } from '../util/dom'
 import Scroller from '../common/Scroller'
 import View from '../View'
 import BasicViewDateProfileGenerator from './BasicViewDateProfileGenerator'
@@ -78,17 +79,19 @@ export default class BasicView extends View {
     let dayGridContainerEl
     let dayGridEl
 
-    this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml())
+    this.el.classList.add('fc-basic-view')
+    this.el.innerHTML = this.renderSkeletonHtml()
 
     this.scroller.render()
 
     dayGridContainerEl = this.scroller.el
     dayGridContainerEl.classList.add('fc-day-grid-container')
-    dayGridEl = $('<div class="fc-day-grid" />').appendTo(dayGridContainerEl)
+    dayGridEl = makeElement('div', { className: 'fc-day-grid' })
+    dayGridContainerEl.appendChild(dayGridEl)
 
-    this.el.find('.fc-body > tr > td').append(dayGridContainerEl)
+    this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl)
 
-    this.dayGrid.headContainerEl = this.el.find('.fc-head-container')[0]
+    this.dayGrid.headContainerEl = this.el.querySelector('.fc-head-container')
     this.dayGrid.setElement(dayGridEl)
   }
 
@@ -171,7 +174,7 @@ export default class BasicView extends View {
       // Make sure all week number cells running down the side have the same width.
       // Record the width for cells created later.
       this.weekNumberWidth = matchCellWidths(
-        this.el.find('.fc-week-number')
+        $(this.el.querySelectorAll('.fc-week-number'))
       )
     }
 
@@ -223,7 +226,7 @@ export default class BasicView extends View {
   // given a desired total height of the view, returns what the height of the scroller should be
   computeScrollerHeight(totalHeight) {
     return totalHeight -
-      subtractInnerElHeight(this.el, $(this.scroller.el)) // everything that's NOT the scroller
+      subtractInnerElHeight($(this.el), $(this.scroller.el)) // everything that's NOT the scroller
   }
 
 

+ 7 - 9
src/basic/DayGrid.ts

@@ -13,7 +13,7 @@ import { default as DayTableMixin, DayTableInterface } from '../component/DayTab
 import DayGridEventRenderer from './DayGridEventRenderer'
 import DayGridHelperRenderer from './DayGridHelperRenderer'
 import DayGridFillRenderer from './DayGridFillRenderer'
-import { makeElement, htmlToElements } from '../util/dom'
+import { makeElement, htmlToElements, findElsWithin, removeElement } from '../util/dom'
 
 
 /* A component that renders a grid of whole-days that runs horizontally. There can be multiple rows, one per week.
@@ -116,10 +116,10 @@ export default class DayGrid extends InteractiveDateComponent {
     for (row = 0; row < rowCnt; row++) {
       html += this.renderDayRowHtml(row, this.isRigid)
     }
-    this.el.html(html)
+    this.el.innerHTML = html
 
-    this.rowEls = this.el.find('.fc-row').toArray()
-    this.cellEls = this.el.find('.fc-day, .fc-disabled-day').toArray()
+    this.rowEls = findElsWithin(this.el, '.fc-row')
+    this.cellEls = findElsWithin(this.el, '.fc-day, .fc-disabled-day')
 
     this.rowCoordCache = new CoordCache({
       els: this.rowEls,
@@ -587,9 +587,7 @@ export default class DayGrid extends InteractiveDateComponent {
     let rowStruct = this.eventRenderer.rowStructs[row]
 
     if (rowStruct.moreEls) {
-      rowStruct.moreEls.forEach(function(moreEl) {
-        moreEl.parentNode.removeChild(moreEl)
-      })
+      rowStruct.moreEls.forEach(removeElement)
       rowStruct.moreEls = null
     }
 
@@ -658,7 +656,7 @@ export default class DayGrid extends InteractiveDateComponent {
     let themeClass = view.calendar.theme.getClass('popover')
 
     if (this.rowCnt === 1) {
-      topEl = view.el[0] // will cause the popover to cover any sort of header
+      topEl = view.el // will cause the popover to cover any sort of header
     } else {
       topEl = this.rowEls[row] // will align with top of row
     }
@@ -666,7 +664,7 @@ export default class DayGrid extends InteractiveDateComponent {
     options = {
       className: 'fc-more-popover' + (themeClass ? ' ' + themeClass : ''),
       content: this.renderSegPopoverContent(row, col, segs),
-      parentEl: view.el[0], // attach to root of view. guarantees outside of scrollbars.
+      parentEl: view.el, // attach to root of view. guarantees outside of scrollbars.
       top: topEl.getBoundingClientRect().top,
       autoHide: true, // when the user clicks elsewhere, hide the popover
       viewportConstrain: this.opt('popoverViewportConstrain'),

+ 2 - 2
src/basic/DayGridEventRenderer.ts

@@ -1,6 +1,6 @@
 import * as $ from 'jquery'
 import { htmlEscape, cssToStr } from '../util'
-import { makeElement } from '../util/dom'
+import { makeElement, removeElement } from '../util/dom'
 import EventRenderer from '../component/renderers/EventRenderer'
 import DayGrid from './DayGrid'
 
@@ -49,7 +49,7 @@ export default class DayGridEventRenderer extends EventRenderer {
     let rowStruct
 
     while ((rowStruct = rowStructs.pop())) {
-      rowStruct.tbodyEl.remove()
+      removeElement(rowStruct.tbodyEl)
     }
 
     this.rowStructs = null

+ 2 - 1
src/common/MouseFollower.ts

@@ -4,6 +4,7 @@ import {
   getEvX,
   getEvIsTouch
 } from '../util'
+import { removeElement } from '../util/dom'
 import { default as ListenerMixin, ListenerInterface } from './ListenerMixin'
 
 export interface MouseFollowerOptions {
@@ -144,7 +145,7 @@ export default class MouseFollower {
   // Removes the tracking element if it has already been created
   removeElement() {
     if (this.el) {
-      this.el.remove()
+      removeElement(this.el)
       this.el = null
     }
   }

+ 2 - 2
src/common/Popover.ts

@@ -15,7 +15,7 @@ Options:
 
 import * as $ from 'jquery'
 import { getScrollParent } from '../util'
-import { listenViaDelegation, appendContentTo, ElementContent } from '../util/dom'
+import { listenViaDelegation, appendContentTo, ElementContent, removeElement } from '../util/dom'
 import { default as ListenerMixin, ListenerInterface } from './ListenerMixin'
 
 export interface PopoverOptions {
@@ -110,7 +110,7 @@ export default class Popover {
     this.hide()
 
     if (this.el) {
-      this.el.remove()
+      removeElement(this.el)
       this.el = null
     }
 

+ 4 - 3
src/component/Component.ts

@@ -1,11 +1,12 @@
+import { removeElement } from '../util/dom'
 import Model from '../common/Model'
 
 export default class Component extends Model {
 
-  el: JQuery
+  el: HTMLElement
 
 
-  setElement(el) {
+  setElement(el: HTMLElement) {
     this.el = el
     this.bindGlobalHandlers()
     this.renderSkeleton()
@@ -18,7 +19,7 @@ export default class Component extends Model {
     this.unrenderSkeleton()
     this.unbindGlobalHandlers()
 
-    this.el.remove()
+    removeElement(this.el)
     // NOTE: don't null-out this.el in case the View was destroyed within an API callback.
     // We don't null-out the View's other jQuery element references upon destroy,
     //  so we shouldn't kill this.el either.

+ 4 - 4
src/component/InteractiveDateComponent.ts

@@ -65,14 +65,14 @@ export default abstract class InteractiveDateComponent extends DateComponent {
     super.setElement(el)
 
     if (this.dateClicking) {
-      this.dateClicking.bindToEl(el)
+      this.dateClicking.bindToEl($(el))
     }
 
     if (this.dateSelecting) {
-      this.dateSelecting.bindToEl(el)
+      this.dateSelecting.bindToEl($(el))
     }
 
-    this.bindAllSegHandlersToEl(el)
+    this.bindAllSegHandlersToEl($(el))
   }
 
 
@@ -111,7 +111,7 @@ export default abstract class InteractiveDateComponent extends DateComponent {
   bindDateHandlerToEl(el, name, handler) {
     // attach a handler to the grid's root element.
     // jQuery will take care of unregistering them when removeElement gets called.
-    this.el.on(name, (ev) => {
+    this.el.addEventListener(name, (ev) => {
       if (
         !$(ev.target).is(
           this.segSelector + ':not(.fc-helper),' + // directly on an event element

+ 1 - 1
src/component/interactions/EventDragging.ts

@@ -141,7 +141,7 @@ export default class EventDragging extends Interaction {
         isDragging = false
         mouseFollower = new MouseFollower(seg.el[0], {
           additionalClass: 'fc-dragging',
-          parentEl: view.el[0],
+          parentEl: view.el,
           opacity: dragListener.isTouch ? null : this.opt('dragOpacity'),
           revertDuration: this.opt('dragRevertDuration'),
           zIndex: 2 // one above the .fc-view

+ 8 - 6
src/list/ListView.ts

@@ -36,13 +36,15 @@ export default class ListView extends View {
 
 
   renderSkeleton() {
-    this.el.addClass(
-      'fc-list-view ' +
-      this.calendar.theme.getClass('listView')
-    )
+    this.el.classList.add('fc-list-view')
+
+    let themeClass = this.calendar.theme.getClass('listView')
+    if (themeClass) {
+      this.el.classList.add(themeClass)
+    }
 
     this.scroller.render()
-    this.el.append(this.scroller.el)
+    this.el.appendChild(this.scroller.el)
 
     this.contentEl = this.scroller.scrollEl // shortcut
   }
@@ -66,7 +68,7 @@ export default class ListView extends View {
 
   computeScrollerHeight(totalHeight) {
     return totalHeight -
-      subtractInnerElHeight(this.el, $(this.scroller.el)) // everything that's NOT the scroller
+      subtractInnerElHeight($(this.el), $(this.scroller.el)) // everything that's NOT the scroller
   }
 
 

+ 6 - 0
src/util/dom.ts

@@ -60,3 +60,9 @@ export function findElsWithin(container: HTMLElement, selector: string): HTMLEle
     container.querySelectorAll(selector)
   )
 }
+
+export function removeElement(el: HTMLElement) {
+  if (el.parentNode) {
+    el.parentNode.removeChild(el)
+  }
+}