-
Notifications
You must be signed in to change notification settings - Fork 5
/
concerto-behaviors.html
199 lines (181 loc) · 5.9 KB
/
concerto-behaviors.html
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<script>
var ConcertoBehaviors = ConcertoBehaviors || {};
ConcertoBehaviors.Utils = {
/**
* Prepend a base path to a URL as needed.
*
* If a base is supplied and the URL is not absolute, prepend the base to
* return an absolute URL.
*/
resolveURL: function(url, base) {
var r = new RegExp('^(?:[a-z]+:)?//', 'i');
if (!url || !base || r.test(url)) {
return url;
}
return base + url;
},
/**
* Prepends a base to a path if not already prefixed with it
*
* Does not care about absolute URLs.
*/
prefixWithBase: function(path, base) {
bl = base.length;
pl = path.length;
if (pl > bl && bl != 0 && path.substring(0, bl) == base)
{
return path;
}
return base + path;
},
/**
* Use iterative binary search to find optimal content font size given
* the element's dimensions as constraints.
*/
optimalFontSize: function(element, content) {
var disable = !!parseInt(element.config['disable_text_autosize']);
var maxSize = parseInt(element.config['max_text_autosize']);
if (element.parentNode && !disable) {
// Font size and container constraints
maxSize = (!isNaN(maxSize) && typeof maxSize !== 'undefined' && maxSize > 4) ? maxSize : 200;
var minSize = 4;
var maxWidth = element.parentNode.offsetWidth;
var maxHeight = element.parentNode.offsetHeight;
// Binary search to find optimal font size
while (maxSize > minSize + 1) {
// calculate mid point of max and min font sizes
midSize = Math.floor((maxSize - minSize) / 2) + minSize;
// set content node font size to mid point
content.style.fontSize = midSize + "px";
// check if content node exceeds height constraint
if (!(content.offsetHeight <= maxHeight && content.offsetWidth <= maxWidth)) {
// continue search on smaller font sizes
maxSize = midSize;
} else {
// continue search on larger font sizes
minSize = midSize;
}
}
// Set final font size
content.style.fontSize = minSize + "px";
}
}
};
ConcertoBehaviors.ContentFactory = {
types: {},
/**
* Normalize the type names for consistent registration / lookup.
* We use a lower case non-punctuated string because some content types are
* CamelCase on the server but Regularcase in JavaScript (like HtmlText).
*/
normalizeTypeName: function(typeName) {
var basicName = typeName.replace(/\W/g, '');
return basicName.toLowerCase();
},
/**
* Initialize a new content element.
*/
getType: function (typeName) {
typeName = this.normalizeTypeName(typeName);
return this.types[typeName] ? new this.types[typeName] : undefined;
},
/**
* Register the content type described by the current page in the
* ContentFactory.
*
* This method should be called from each piece of content which inherits from
* concerto-content. It attempts to automatically determine what Polymer
* element is being defined and setup an event listener to register it once
* Polymer has finished loading all elements.
*
* Registers a content element class with a type.
*/
registerContent: function(contentName, klass) {
var name = contentName.replace(/^concerto-/, '');
var content = window[klass];
if (!content) {
// Do not register content types which do not have a public constructor.
console.warn("Content type '" + contentName + "' does not appear to have a public constructor and cannot be registered");
return;
}
var proto = content.prototype;
name = this.normalizeTypeName(name);
this.types[name] = content;
console.info("Registered content type " + name);
}
};
ConcertoBehaviors.BaseContent = {
properties: {
baseUrl: {
type: String,
reflectToAttribute: true
},
title: String,
contentId: {
type: Number,
reflectToAttribute: true
},
duration: {
type: Number,
reflectToAttribute: true
},
cssText: {
type: String,
observer: '_cssTextChanged'
},
autoLoad: {
type: Boolean,
value: true
},
opened: {
type: Boolean,
value: false,
reflectToAttribute: true
},
config: {
type: Object,
reflectToAttribute: true
}
},
/**
* Apply the new cssText back to the element.
*/
_cssTextChanged: function() {
this.style.cssText = this.cssText;
},
/**
* Indicate that this content has finished loaded and can be displayed
* in the field.
*
* Currently this involves firing the `load` event, but the details may
* change.
*/
_loaded: function() {
this.fire('load', this);
},
/**
* Load the values from a JSON Map which map to attributes
* of this element.
*/
fromJSON: function(data) {
Object.keys(data).forEach(function(key) {
if (key in this) {
if (typeof data[key] == 'object') {
this.setAttribute(key.toLowerCase(), JSON.stringify(data[key]));
} else {
this.setAttribute(key.toLowerCase(), data[key]);
// TODO! @gabe please look at this and see why the prior line is not setting all the base properties
// I had to add the following line so that the contentId property
// would be set on the content types. The "contentId" property must
// be set here so we prevent reloading the same content in the
// loadNextContent method in ConcertoField.
this[key] = data[key];
}
}
}.bind(this));
if (this.autoLoad) {
this._loaded();
}
}
};
</script>