summaryrefslogtreecommitdiffstats
path: root/src/text.js
blob: 22ec5bc0e024f2cf601b362557e65354cf12a848 (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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// List font style attributes as they should be applied to style 
var _styleAttr = ('size family weight stretch variant style').split(' ')

SVG.Text = function() {
  this.constructor.call(this, SVG.create('text'))
  
  /* define default style */
  this.styles = {
    'font-size':    16
  , 'font-family':  'Helvetica, Arial, sans-serif'
  , 'text-anchor':  'start'
  }
  
  this._leading = 1.2
  this._base = 0.276666666
}

// Inherit from SVG.Element
SVG.Text.prototype = new SVG.Shape

//
SVG.extend(SVG.Text, {
  // Move over x-axis
  x: function(x, a) {
    /* act as getter */
    if (x == null) return a ? this.attr('x') : this.bbox().x
    
    /* set x taking anchor in mind */
    if (!a) {
      a = this.style('text-anchor')
      x = a == 'start' ? x : a == 'end' ? x + this.bbox().width : x + this.bbox().width / 2
    }
    
    return this.attr('x', x)
  }
  // Move center over x-axis
, cx: function(x, a) {
    return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)
  }
  // Move center over y-axis
, cy: function(y, a) {
    return y == null ? this.bbox().cy : this.y(a ? y : y - this.bbox().height / 2)
  }
  // Move element to given x and y values
, move: function(x, y, a) {
    return this.x(x, a).y(y)
  }
  // Move element by its center
, center: function(x, y, a) {
    return this.cx(x, a).cy(y, a)
  }
  // Set the text content
, text: function(text) {
    /* act as getter */
    if (text == null)
      return this.content
    
    /* remove existing lines */
    this.clear()
    
    /* update the content */
    this.content = SVG.regex.isBlank.test(text) ? 'text' : text
    
    var i, il
      , lines = text.split('\n')
    
    /* build new lines */
    for (i = 0, il = lines.length; i < il; i++)
      this.tspan(lines[i])
      
    return this.attr('textLength', 1).attr('textLength', null)
  }
  // Create a tspan
, tspan: function(text) {
    var tspan = new SVG.TSpan().text(text)
    
    /* add new tspan */
    this.node.appendChild(tspan.node)
    this.lines.push(tspan)
    
    return tspan.attr('style', this.style())
  }
  // Set font size
, size: function(size) {
    return this.attr('font-size', size)
  }
  // Set / get leading
, leading: function(value) {
    /* act as getter */
    if (value == null)
      return this._leading
    
    /* act as setter */
    this._leading = value
    
    return this.rebuild('leading', value)
  }
  // rebuild appearance type
, rebuild: function() {
    var i, il
      , size = this.styles['font-size']
    
    /* define position of all lines */
    for (i = 0, il = this.lines.length; i < il; i++)
      this.lines[i].attr({
        dy: size * this._leading - (i == 0 ? size * this._base : 0)
      , x: (this.attr('x') || 0)
      , style: this.style()
      })
    
    return this
  }
  // Clear all lines
, clear: function() {
    /* remove existing child nodes */
    while (this.node.hasChildNodes())
      this.node.removeChild(this.node.lastChild)
    
    this.lines = []
    
    return this
  }
  
})

//
SVG.extend(SVG.Container, {
  // Create text element
  text: function(text) {
    return this.put(new SVG.Text().text(text))
  }

})

// tspan class
SVG.TSpan = function() {
  this.constructor.call(this, SVG.create('tspan'))
}

// Inherit from SVG.Shape
SVG.TSpan.prototype = new SVG.Shape

// Include the container object
SVG.extend(SVG.TSpan, {
  // Set text content
  text: function(text) {
    this.node.appendChild(document.createTextNode(text))
    
    return this
  }
  
})