Galerie mk2
[redakcja.git] / platforma / static / js / app.js
1 /*global Class*/
2 var editor;
3 var panel_hooks;
4
5
6 // prevent a console.log from blowing things up if we are on a browser that
7 // does not support it
8 if (typeof console === 'undefined') {
9   window.console = {} ;
10   console.log = console.info = console.warn = console.error = function(){};
11 }
12
13
14 (function(){
15   // Classes
16   var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
17   this.Class = function(){};
18   Class.extend = function(prop) {
19     var _super = this.prototype;
20     initializing = true;
21     var prototype = new this();
22     initializing = false;
23     for (var name in prop) {
24       prototype[name] = typeof prop[name] == "function" &&
25         typeof _super[name] == "function" && fnTest.test(prop[name]) ?
26         (function(name, fn){
27           return function() {
28             var tmp = this._super;
29             this._super = _super[name];
30             var ret = fn.apply(this, arguments);       
31             this._super = tmp;           
32             return ret;
33           };
34         })(name, prop[name]) :
35         prop[name];
36     }   
37     function Class() {
38       if ( !initializing && this.init )
39         this.init.apply(this, arguments);
40     }
41     Class.prototype = prototype;
42     Class.constructor = Class;
43     Class.extend = arguments.callee;   
44     return Class;
45   };
46   
47   // Templates
48   var cache = {};
49
50   this.render_template = function render_template(str, data){
51     // Figure out if we're getting a template, or if we need to
52     // load the template - and be sure to cache the result.    
53     var fn = !/^[\d\s-_]/.test(str) ?
54       cache[str] = cache[str] ||
55         render_template(document.getElementById(str).innerHTML) :
56
57       // Generate a reusable function that will serve as a template
58       // generator (and which will be cached).
59       
60       new Function("obj",
61         "var p=[],print=function(){p.push.apply(p,arguments);};" +
62
63         // Introduce the data as local variables using with(){}
64         "with(obj){p.push('" +
65
66         // Convert the template into pure JavaScript       
67         str
68           .replace(/[\r\t\n]/g, " ")
69           .split("<%").join("\t")
70           .replace(/((^|%>)[^\t]*)'/g, "$1\r")
71           .replace(/\t=(.*?)%>/g, "',$1,'")
72           .split("\t").join("');")
73           .split("%>").join("p.push('")
74           .split("\r").join("\\'")
75       + "');}return p.join('');");
76
77       // Provide some basic currying to the user
78     return data ? fn( data ) : fn;
79   };
80 })();
81
82
83 (function() {
84   var slice = Array.prototype.slice;
85   
86   function update(array, args) {
87     var arrayLength = array.length, length = args.length;
88     while (length--) array[arrayLength + length] = args[length];
89     return array;
90   };
91   
92   function merge(array, args) {
93     array = slice.call(array, 0);
94     return update(array, args);
95   };
96   
97   Function.prototype.bind = function(context) {
98     if (arguments.length < 2 && typeof arguments[0] === 'undefined') {
99       return this;
100     } 
101     var __method = this;
102     var args = slice.call(arguments, 1);
103     return function() {
104       var a = merge(args, arguments);
105       return __method.apply(context, a);
106     }
107   }
108   
109 })();
110
111
112 var Editor = Editor || {};
113
114 // Obiekt implementujący wzorzec KVC/KVO
115 Editor.Object = Class.extend({
116   _className: 'Editor.Object',
117   _observers: {},
118   _guid: null,
119   
120   init: function() {
121     this._observers = {};
122   },
123   
124   description: function() {
125     return this._className + '(guid = ' + this.guid() + ')';
126   },
127   
128   addObserver: function(observer, property, callback) {
129     // console.log('Add observer', observer.description(), 'to', this.description(), '[', property, ']');
130     if (!this._observers[property]) {
131       this._observers[property] = {}
132     }
133     this._observers[property][observer.guid()] = callback;
134     return this;
135   },
136   
137   removeObserver: function(observer, property) {
138     if (!property) {
139       for (var property in this._observers) {
140         this.removeObserver(observer, property)
141       }
142     } else {
143       // console.log('Remove observer', observer.description(), 'from', this.description(), '[', property, ']');
144       delete this._observers[property][observer.guid()];
145     }
146     return this;
147   },
148   
149   notifyObservers: function(property) {
150     var currentValue = this[property];
151     for (var guid in this._observers[property]) {
152       // console.log(this._observers[property][guid]);
153       // console.log('Notifying', guid, 'of', this.description(), '[', property, ']');
154       this._observers[property][guid](property, currentValue, this);
155     }
156     return this;
157   },
158   
159   guid: function() {
160     if (!this._guid) {
161       this._guid = ('editor-' + Editor.Object._lastGuid++);
162     }
163     return this._guid;
164   },
165   
166   get: function(property) {
167     return this[property];
168   },
169   
170   set: function(property, value) {
171     if (this[property] != value) {
172       this[property] = value;
173       this.notifyObservers(property);
174     }
175     return this;
176   },
177   
178   dispose: function() {
179     delete this._observers;
180   }
181 });
182
183 // Handle JSON error responses in uniform way
184 function parseXHRError(response)
185 {
186     var message = ""
187     try {
188       var json = $.evalJSON(response.responseText);
189
190       if(json.reason == 'xml-parse-error') {
191           message = json.message.replace(/(line\s+)(\d+)(\s+)/i,
192             "<a class='xml-editor-ref' href='#xml-$2-1'>$1$2$3</a>");
193
194           message = message.replace(/(line\s+)(\d+)(\,\s*column\s+)(\d+)/i,
195             "<a class='xml-editor-ref' href='#xml-$2-$4'>$1$2$3$4</a>");
196       }
197       else {
198         message = json.message || json.reason || "Nieznany błąd :((";
199       }
200
201     } catch(e) {
202         // not a valid JSON response
203         message = response.statusText;
204     }
205     return message;
206 }
207
208 Editor.Object._lastGuid = 0;
209
210 var panels = [];