summaryrefslogtreecommitdiffstats
path: root/src/doc.js
blob: 65545ebc6aeca8892f0b9e2d0f15d97d92ba79e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// ### This module accounts for the main svg document

//
SVG.Doc = function(element) {
  /* ensure the presence of a html element */
  this.parent = typeof element == 'string' ?
    document.getElementById(element) :
    element
  
  /* If the target is an svg element, use that element as the main wrapper.
     This allows svg.js to work with svg documents as well. */
  this.constructor
    .call(this, this.parent.nodeName == 'svg' ? this.parent : SVG.create('svg'))
  
  /* set svg element attributes */
  this
    .attr({ xmlns: SVG.ns, version: '1.1', width: '100%', height: '100%' })
    .attr('xlink', SVG.xlink, SVG.ns)
  
  /* create the <defs> node */
  this._defs = new SVG.Defs
  this.node.appendChild(this._defs.node)
  
  /* ensure correct rendering */
  if (this.parent.nodeName != 'svg')
    this.stage()
}

// Inherits from SVG.Container
SVG.Doc.prototype = new SVG.Container

//
SVG.extend(SVG.Doc, {
  // Hack for safari preventing text to be rendered in one line.
  // Basically it sets the position of the svg node to absolute
  // when the dom is loaded, and resets it to relative a few milliseconds later.
  // It also handles sub-pixel offset rendering properly.
  stage: function() {
    var check
      , element = this
      , wrapper = document.createElement('div')

    /* set temporary wrapper to position relative */
    wrapper.style.cssText = 'position:relative;height:100%;'

    /* put element into wrapper */
    element.parent.appendChild(wrapper)
    wrapper.appendChild(element.node)

    /* check for dom:ready */
    check = function() {
      if (document.readyState === 'complete') {
        element.style('position:absolute;')
        setTimeout(function() {
          /* set position back to relative */
          element.style('position:relative;')

          /* remove temporary wrapper */
          element.parent.removeChild(element.node.parentNode)
          element.node.parentNode.removeChild(element.node)
          element.parent.appendChild(element.node)

          /* after wrapping is done, fix sub-pixel offset */
          element.fixSubPixelOffset()
          
          /* make sure sub-pixel offset is fixed every time the window is resized */
          SVG.on(window, 'resize', function() {
            element.fixSubPixelOffset()
          })
          
        }, 5)
      } else {
        setTimeout(check, 10)
      }
    }

    check()

    return this
  }

  // Creates and returns defs element
, defs: function() {
    return this._defs
  }

  // Fix for possible sub-pixel offset. See:
  // https://bugzilla.mozilla.org/show_bug.cgi?id=608812
, fixSubPixelOffset: function() {
    var pos = this.node.getScreenCTM()
  
    this
      .style('left', (-pos.e % 1) + 'px')
      .style('top',  (-pos.f % 1) + 'px')
  }
  
})