ffe5a01d651e8a13e43450063c158b83ad256eba
[redakcja.git] / redakcja / static / js / wiki_img / base.js
1 (function($)
2 {
3         var noop = function() { };
4
5         $.wiki = {
6                 perspectives: {},
7                 cls: {},
8                 state: {
9                         "version": 1,
10                         "perspectives": {
11                 "CodeMirrorPerspective": {}
12                         }
13                 }
14         };
15
16         $.wiki.loadConfig = function() {
17                 if(!window.localStorage)
18                         return;
19
20                 try {
21                         var value = window.localStorage.getItem(CurrentDocument.id) || "{}";
22                         var config = JSON.parse(value);
23
24                         if (config.version == $.wiki.state.version) {
25                                 $.wiki.state.perspectives = $.extend($.wiki.state.perspectives, config.perspectives);
26                         }
27                 } catch(e) {
28                         console.log("Failed to load config, using default.");
29                 }
30
31                 console.log("Loaded:", $.wiki.state, $.wiki.state.version);
32         };
33
34         $(window).bind('unload', function() {
35                 if(window.localStorage)
36                         window.localStorage.setItem(CurrentDocument.id, JSON.stringify($.wiki.state));
37         })
38
39
40         $.wiki.activePerspective = function() {
41                 return this.perspectives[$("#tabs li.active").attr('id')];
42         };
43
44         $.wiki.exitContext = function() {
45                 var ap = this.activePerspective();
46                 if(ap) ap.onExit();
47                 return ap;
48         };
49
50         $.wiki.enterContext = function(ap) {
51                 if(ap) ap.onEnter();
52         };
53
54         $.wiki.isDirty = function() {
55                 var ap = this.activePerspective();
56                 return (!!CurrentDocument && CurrentDocument.has_local_changes) || ap.dirty();
57         };
58
59         $.wiki.newTab = function(doc, title, klass) {
60                 var base_id = 'id' + Math.floor(Math.random()* 5000000000);
61                 var id = (''+klass)+'_' + base_id;
62                 var $tab = $('<li id="'+id+'" data-ui-related="'+base_id+'" data-ui-jsclass="'+klass+'" >'
63                                 + title + '<img src="'+STATIC_URL+'icons/close.png" class="tabclose"></li>');
64                 var $view = $('<div class="editor '+klass+'" id="'+base_id+'"> </div>');
65
66                 this.perspectives[id] = new $.wiki[klass]({
67                         doc: doc,
68                         id: id,
69                         base_id: base_id,
70                 });
71
72                 $('#tabs').append($tab);
73                 $view.hide().appendTo('#editor');
74                 return {
75                         tab: $tab[0],
76                         view: $view[0],
77                 };
78         };
79
80         $.wiki.initTab = function(options) {
81                 var klass = $(options.tab).attr('data-ui-jsclass');
82
83                 return new $.wiki[klass]({
84                         doc: options.doc,
85                         id: $(options.tab).attr('id'),
86                         callback: function() {
87                                 $.wiki.perspectives[this.perspective_id] = this;
88                                 if(options.callback)
89                                         options.callback.call(this);
90                         }
91                 });
92         };
93
94         $.wiki.perspectiveForTab = function(tab) { // element or id
95                 return this.perspectives[ $(tab).attr('id')];
96         }
97
98         $.wiki.switchToTab = function(tab){
99                 var self = this;
100                 var $tab = $(tab);
101
102                 if($tab.length != 1)
103                         $tab = $(DEFAULT_PERSPECTIVE);
104
105                 var $old = $tab.closest('.tabs').find('.active');
106
107                 $old.each(function(){
108                         $(this).removeClass('active');
109                         self.perspectives[$(this).attr('id')].onExit();
110                         $('#' + $(this).attr('data-ui-related')).hide();
111                 });
112
113                 /* show new */
114                 $tab.addClass('active');
115                 $('#' + $tab.attr('data-ui-related')).show();
116
117                 console.log($tab);
118                 console.log($.wiki.perspectives);
119
120                 $.wiki.perspectives[$tab.attr('id')].onEnter();
121         };
122
123         /*
124          * Basic perspective.
125          */
126         $.wiki.Perspective = function(options) {
127                 if(!options) return;
128
129                 this.doc = options.doc;
130                 if (options.id) {
131                         this.perspective_id = options.id;
132                 }
133                 else {
134                         this.perspective_id = '';
135                 }
136
137                 if(options.callback)
138                         options.callback.call(this);
139         };
140
141         $.wiki.Perspective.prototype.config = function() {
142                 return $.wiki.state.perspectives[this.perspective_id];
143         }
144
145         $.wiki.Perspective.prototype.toString = function() {
146                 return this.perspective_id;
147         };
148
149         $.wiki.Perspective.prototype.dirty = function() {
150                 return true;
151         };
152
153         $.wiki.Perspective.prototype.onEnter = function () {
154                 // called when perspective in initialized
155                 if (!this.noupdate_hash_onenter) {
156                         document.location.hash = '#' + this.perspective_id;
157                 }
158         };
159
160         $.wiki.Perspective.prototype.onExit = function () {
161                 // called when user switches to another perspective
162                 if (!this.noupdate_hash_onenter) {
163                         document.location.hash = '';
164                 }
165         };
166
167         $.wiki.Perspective.prototype.destroy = function() {
168                 // pass
169         };
170
171         $.wiki.Perspective.prototype.freezeState = function () {
172                 // free UI state (don't store data here)
173         };
174
175         $.wiki.Perspective.prototype.unfreezeState = function (frozenState) {
176                 // restore UI state
177         };
178
179         /*
180          * Stub rendering (used in generating history)
181          */
182         $.wiki.renderStub = function(params)
183         {
184                 params = $.extend({ 'filters': {} }, params);
185                 var $elem = params.stub.clone();
186                 $elem.removeClass('row-stub');
187                 params.container.append($elem);
188
189                 $('*[data-stub-value]', $elem).each(function() {
190                         var $this = $(this);
191                         var field = $this.attr('data-stub-value');
192
193                         var value = params.data[field];
194
195                         if(params.filters[field])
196                                 value = params.filters[field](value);
197
198                         if(value === null || value === undefined) return;
199
200                         if(!$this.attr('data-stub-target')) {
201                                 $this.text(value);
202                         }
203                         else {
204                                 $this.attr($this.attr('data-stub-target'), value);
205                                 $this.removeAttr('data-stub-target');
206                                 $this.removeAttr('data-stub-value');
207                         }
208                 });
209
210                 $elem.show();
211                 return $elem;
212         };
213
214         /*
215          * Dialogs
216          */
217         function GenericDialog(element) {
218                 if(!element) return;
219
220                 var self = this;
221
222                 self.$elem = $(element);
223
224                 if(!self.$elem.attr('data-ui-initialized')) {
225                         console.log("Initializing dialog", this);
226                         self.initialize();
227                         self.$elem.attr('data-ui-initialized', true);
228                 }
229
230                 self.show();
231         };
232
233         GenericDialog.prototype = {
234
235                 /*
236                 * Steps to follow when the dialog in first loaded on page.
237                 */
238                 initialize: function(){
239                         var self = this;
240
241                         /* bind buttons */
242                         $('button[data-ui-action]', self.$elem).click(function(event) {
243                                 event.preventDefault();
244
245                                 var action = $(this).attr('data-ui-action');
246                                 console.log("Button pressed, action: ", action);
247
248                                 try {
249                                         self[action + "Action"].call(self);
250                                 } catch(e) {
251                                         console.log("Action failed:", e);
252                                         // always hide on cancel
253                                         if(action == 'cancel')
254                                                 self.hide();
255                                 }
256                         });
257                 },
258
259                 /*
260                  * Prepare dialog for user. Clear any unnessary data.
261                 */
262                 show: function() {
263                         $.blockUI({
264                                 message: this.$elem,
265                                 css: {
266                                         'top': '25%',
267                                         'left': '25%',
268                                         'width': '50%'
269                                 }
270                         });
271                 },
272
273                 hide: function(){
274                         $.unblockUI();
275                 },
276
277                 cancelAction: function() {
278                         this.hide();
279                 },
280
281                 doneAction: function() {
282                         this.hide();
283                 },
284
285                 clearForm: function() {
286                         $("*[data-ui-error-for]", this.$elem).text('');
287                 },
288
289                 reportErrors: function(errors) {
290                         var global = $("*[data-ui-error-for='__all__']", this.$elem);
291                         var unassigned = [];
292
293                         for (var field_name in errors)
294                         {
295                                 var span = $("*[data-ui-error-for='"+field_name+"']", this.$elem);
296
297                                 if(!span.length) {
298                                         unassigned.push(field_name);
299                                         continue;
300                                 }
301
302                                 span.text(errors[field_name].join(' '));
303                         }
304
305                         if(unassigned.length > 0)
306                                 global.text( global.text() + 'W formularzu wystąpiły błędy');
307                 }
308         };
309
310         $.wiki.cls.GenericDialog = GenericDialog;
311
312         $.wiki.showDialog = function(selector, options) {
313                 var elem = $(selector);
314
315                 if(elem.length != 1) {
316                         console.log("Failed to show dialog:", selector, elem);
317                         return false;
318                 }
319
320                 try {
321                     var klass = elem.attr('data-ui-jsclass');
322                         return new $.wiki.cls[klass](elem, options);
323                 } catch(e) {
324                         console.log("Failed to show dialog", selector, klass, e);
325                         return false;
326                 }
327         };
328
329 })(jQuery);