1
|
|
|
/** |
2
|
|
|
* The constructor. |
3
|
|
|
* See Mivhal.defaults for available options. |
4
|
|
|
* |
5
|
|
|
* @param {DOMElement} selection |
6
|
|
|
* @param {Object} options |
7
|
|
|
*/ |
8
|
|
|
function Mivhak( selection, options ) |
9
|
|
|
{ |
10
|
|
|
// Bail if there are no resources |
11
|
|
|
if(!selection.getElementsByTagName('PRE').length) return; |
|
|
|
|
12
|
|
|
|
13
|
|
|
this.$selection = $( selection ); |
14
|
|
|
this.setOptions( options ); |
15
|
|
|
this.init(); |
16
|
|
|
} |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Check if a given string represents a supported method |
20
|
|
|
* @param {string} method |
21
|
|
|
*/ |
22
|
|
|
Mivhak.methodExists = function( method ) |
23
|
|
|
{ |
24
|
|
|
return typeof method === 'string' && Mivhak.methods[method]; |
25
|
|
|
}; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Initiate Mivhak. |
29
|
|
|
*/ |
30
|
|
|
Mivhak.prototype.init = function() |
31
|
|
|
{ |
32
|
|
|
this.initState(); |
33
|
|
|
this.parseResources(); |
34
|
|
|
this.createUI(); |
35
|
|
|
this.applyOptions(); |
36
|
|
|
this.callMethod('showTab',0); // Show first tab initially |
37
|
|
|
}; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Apply the options that were set by the user. This function is called when |
41
|
|
|
* Mivhak is initiated, and every time the options are updated. |
42
|
|
|
*/ |
43
|
|
|
Mivhak.prototype.applyOptions = function() |
44
|
|
|
{ |
45
|
|
|
this.callMethod('setHeight', this.options.height); |
46
|
|
|
this.callMethod('setAccentColor', this.options.accentColor); |
47
|
|
|
if(this.options.collapsed) this.callMethod('collapse'); |
|
|
|
|
48
|
|
|
if(!this.options.topbar) this.$selection.addClass('mivhak-no-topbar'); |
|
|
|
|
49
|
|
|
else this.$selection.removeClass('mivhak-no-topbar'); |
50
|
|
|
|
51
|
|
|
// If the theme option was set through jQuery, set the attribute |
52
|
|
|
this.$selection.attr('miv-theme',this.options.theme); |
53
|
|
|
|
54
|
|
|
this.createCaption(); |
55
|
|
|
this.createLivePreview(); |
56
|
|
|
}; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Initiate this instance's state. |
60
|
|
|
*/ |
61
|
|
|
Mivhak.prototype.initState = function() |
62
|
|
|
{ |
63
|
|
|
this.state = { |
64
|
|
|
lineWrap: true, |
65
|
|
|
collapsed: false, |
66
|
|
|
height: 0, |
67
|
|
|
activeTab: null, // Updated by tabs.showTab |
68
|
|
|
resources: [] // Generated by parseResources() |
69
|
|
|
}; |
70
|
|
|
}; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Set or update this instance's options. |
74
|
|
|
* @param {object} options |
75
|
|
|
*/ |
76
|
|
|
Mivhak.prototype.setOptions = function( options ) |
77
|
|
|
{ |
78
|
|
|
// If options were already set, update them |
79
|
|
|
if( typeof this.options !== 'undefined' ) |
80
|
|
|
this.options = $.extend(true, {}, this.options, options, readAttributes(this.$selection[0])); |
|
|
|
|
81
|
|
|
|
82
|
|
|
// Otherwise, merge them with the defaults |
83
|
|
|
else this.options = $.extend(true, {}, Mivhak.defaults, options, readAttributes(this.$selection[0])); |
84
|
|
|
}; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Call one of Mivhak's methods. See Mivhak.methods for available methods. |
88
|
|
|
* To apply additional arguments, simply pass the arguments after the methodName |
89
|
|
|
* i.e. callMethod('methodName', arg1, arg2). |
90
|
|
|
* This method is also called internally when making a method call through jQuery |
91
|
|
|
* i.e. $('#el').mivhak('methodName', arg1, arg2); |
92
|
|
|
* |
93
|
|
|
* @param {string} methodName |
94
|
|
|
*/ |
95
|
|
|
Mivhak.prototype.callMethod = function( methodName ) |
96
|
|
|
{ |
97
|
|
|
if(Mivhak.methodExists(methodName)) |
98
|
|
|
{ |
99
|
|
|
// Call the method with the original arguments, removing the method's name from the list |
100
|
|
|
var args = []; |
101
|
|
|
Array.prototype.push.apply( args, arguments ); |
102
|
|
|
args.shift(); |
103
|
|
|
Mivhak.methods[methodName].apply(this, args); |
104
|
|
|
} |
105
|
|
|
}; |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Create the user interface. |
109
|
|
|
*/ |
110
|
|
|
Mivhak.prototype.createUI = function() |
111
|
|
|
{ |
112
|
|
|
this.tabs = Mivhak.render('tabs',{mivhakInstance: this}); |
113
|
|
|
this.topbar = Mivhak.render('top-bar',{mivhakInstance: this}); |
114
|
|
|
this.notifier = Mivhak.render('notifier'); |
115
|
|
|
|
116
|
|
|
this.$selection.prepend(this.tabs.$el); |
117
|
|
|
this.$selection.prepend(this.topbar.$el); |
118
|
|
|
this.tabs.$el.prepend(this.notifier.$el); |
119
|
|
|
}; |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Calculate the height in pixels. |
123
|
|
|
* |
124
|
|
|
* auto: Automatically calculate the height based on the number of lines. |
125
|
|
|
* min: Calculate the height based on the height of the tab with the maximum number of lines |
126
|
|
|
* max: Calculate the height based on the height of the tab with the minimum number of lines |
127
|
|
|
* average: Calculate the height based on the average height of all tabs |
128
|
|
|
* |
129
|
|
|
* @param {string|number} h One of (auto|min|max|average) or a custom number |
130
|
|
|
* @returns {Number} |
131
|
|
|
*/ |
132
|
|
|
Mivhak.prototype.calculateHeight = function(h) |
133
|
|
|
{ |
134
|
|
|
var heights = [], |
135
|
|
|
padding = this.options.padding*2, |
136
|
|
|
i = this.tabs.tabs.length; |
137
|
|
|
|
138
|
|
|
while(i--) |
139
|
|
|
heights.unshift(getEditorHeight($(this.tabs.tabs[i].resource.pre))+padding); |
|
|
|
|
140
|
|
|
|
141
|
|
|
if('average' === h) return average(heights); |
|
|
|
|
142
|
|
|
if('min' === h) return min(heights); |
|
|
|
|
143
|
|
|
if('max' === h) return max(heights); |
|
|
|
|
144
|
|
|
if('auto' === h) return getEditorHeight($(this.activeTab.resource.pre))+padding; |
|
|
|
|
145
|
|
|
if(!isNaN(h)) return parseInt(h); |
|
|
|
|
146
|
|
|
return heights[0]; |
147
|
|
|
}; |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Loop through each PRE element inside this.$selection and store it's options |
151
|
|
|
* in this.resources, merging it with the default option values. |
152
|
|
|
*/ |
153
|
|
|
Mivhak.prototype.parseResources = function() |
154
|
|
|
{ |
155
|
|
|
var $this = this; |
156
|
|
|
|
157
|
|
|
this.resources = new Resources(); |
|
|
|
|
158
|
|
|
this.$selection.find('pre').each(function(){ |
159
|
|
|
$this.resources.add(this); |
160
|
|
|
}); |
161
|
|
|
}; |
162
|
|
|
|
163
|
|
|
Mivhak.prototype.createCaption = function() |
164
|
|
|
{ |
165
|
|
|
if(this.options.caption) |
166
|
|
|
{ |
167
|
|
|
if(!this.caption) |
168
|
|
|
{ |
169
|
|
|
this.caption = Mivhak.render('caption',{text: this.options.caption}); |
170
|
|
|
this.$selection.append(this.caption.$el); |
171
|
|
|
} |
172
|
|
|
else this.caption.setText(this.options.caption); |
|
|
|
|
173
|
|
|
} |
174
|
|
|
else this.$selection.addClass('mivhak-no-caption'); |
|
|
|
|
175
|
|
|
}; |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Create the live preview iframe window |
179
|
|
|
*/ |
180
|
|
|
Mivhak.prototype.createLivePreview = function() |
181
|
|
|
{ |
182
|
|
|
if(this.options.runnable && typeof this.preview === 'undefined') |
183
|
|
|
{ |
184
|
|
|
this.preview = Mivhak.render('live-preview',{resources: this.resources}); |
185
|
|
|
this.tabs.$el.append(this.preview.$el); |
186
|
|
|
} |
187
|
|
|
}; |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Remove all generated elements, data and events. |
191
|
|
|
* |
192
|
|
|
* TODO: keep initial HTML |
193
|
|
|
*/ |
194
|
|
|
Mivhak.prototype.destroy = function() |
195
|
|
|
{ |
196
|
|
|
this.$selection.empty(); |
197
|
|
|
}; |
198
|
|
|
|
199
|
|
|
/* test-code */ |
200
|
|
|
testapi.mivhak = Mivhak; |
|
|
|
|
201
|
|
|
/* end-test-code */ |
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.
Consider:
If you or someone else later decides to put another statement in, only the first statement will be executed.
In this case the statement
b = 42
will always be executed, while the logging statement will be executed conditionally.ensures that the proper code will be executed conditionally no matter how many statements are added or removed.