123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859 |
- /* global -Misago */
- /* exported Misago */
- (function () {
- 'use strict';
- window.Misago = function() {
- var ns = Object.getPrototypeOf(this);
- var self = this;
- // Context data
- this.context = {
- // Empty settings
- SETTINGS: {}
- };
- // Services
- this._services = [];
- this.addService = function(name, factory, order) {
- this._services.push({
- name: name,
- item: factory,
- after: this.get(order, 'after'),
- before: this.get(order, 'before')
- });
- };
- this._initServices = function(services) {
- var ordered_services = new ns.OrderedList(services).order(false);
- ordered_services.forEach(function (item) {
- var factory = null;
- if (item.item.factory !== undefined) {
- factory = item.item.factory;
- } else {
- factory = item.item;
- }
- var service_instance = factory(self);
- if (service_instance) {
- self[item.name] = service_instance;
- }
- });
- };
- this._destroyServices = function(services) {
- var ordered_services = new ns.OrderedList(services).order();
- ordered_services.reverse();
- ordered_services.forEach(function (item) {
- if (item.destroy !== undefined) {
- item.destroy(self);
- }
- });
- };
- this.registerCoreServices = function() {
- this.addService('conf', ns.Conf);
- this.addService('component', ns.ComponentFactory);
- this.addService('router', ns.RouterFactory);
- this.addService('api', ns.Api);
- this.addService('outlet', ns.Outlet);
- this.addService('title', ns.PageTitle);
- this.addService('start-routing', ns.startRouting);
- };
- // App init/destory
- this.setup = false;
- this.init = function(setup) {
- this.setup = {
- fixture: ns.get(setup, 'fixture', null),
- in_test: ns.get(setup, 'in_test', false)
- };
- this._initServices(this._services);
- };
- this.destroy = function() {
- this._destroyServices();
- };
- };
- }());
- (function (ns) {
- 'use strict';
- var persistent = function(el, isInit, context) {
- context.retain = true;
- };
- ns.ForumLayout = {
- view: function(ctrl, _) {
- return [
- _.component(ns.ForumNavbar),
- m('#router-fixture', {config: persistent}),
- _.component(ns.ForumFooter)
- ];
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- var self = {
- controller: function() {
- var _ = self.container;
- _.setTitle(_.settings.forum_index_title);
- },
- view: function() {
- return m('.container', [
- m('h1', 'Forum index page!'),
- m('p', 'Lorem ipsum dolor met sit amet elit.'),
- m('p', 'Sequar elit dolor nihi putto.')
- ]);
- }
- };
- ns.IndexPage = self;
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- var legalPageFactory = function(type_name, default_title) {
- var dashed_type_name = type_name.replace(/_/g, '-');
- var self = {
- is_destroyed: true,
- controller: function() {
- var _ = self.container;
- self.is_destroyed = false;
- if (ns.get(_.settings, type_name + '_link')) {
- window.location = ns.get(_.settings, type_name + '_link');
- } else {
- self.vm.init(_);
- }
- return {
- onunload: function() {
- self.is_destroyed = true;
- }
- };
- },
- vm: {
- is_busy: false,
- is_ready: false,
- content: null,
- init: function(_) {
- var vm = this;
- if (vm.is_ready) {
- _.setTitle(vm.title);
- } else {
- _.setTitle();
- if (!vm.is_busy) {
- vm.is_busy = true;
- _.api.one('legal-pages', dashed_type_name).then(function(data) {
- vm.title = data.title || default_title;
- vm.body = data.body;
- vm.is_busy = false;
- vm.is_ready = true;
- if (!self.is_destroyed) {
- _.setTitle(vm.title);
- m.redraw();
- }
- });
- }
- }
- }
- },
- view: function() {
- var _ = this.container;
- if (this.vm.is_ready) {
- return m('.page.page-legal.page-legal-' + dashed_type_name, [
- _.component(ns.PageHeader, {title: this.vm.title}),
- m('.container',
- m.trust(this.vm.body)
- )
- ]);
- } else {
- return _.component(ns.LoadingPage);
- }
- }
- };
- return self;
- };
- ns.TermsOfServicePage = legalPageFactory(
- 'terms_of_service', gettext('Terms of service'));
- ns.PrivacyPolicyPage = legalPageFactory(
- 'privacy_policy', gettext('Privacy policy'));
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.Loader = {
- view: function() {
- return m('.loader.sk-folding-cube', [
- m('.sk-cube1.sk-cube'),
- m('.sk-cube2.sk-cube'),
- m('.sk-cube4.sk-cube'),
- m('.sk-cube3.sk-cube')
- ]);
- }
- };
- ns.LoadingPage = {
- view: function(ctrl, _) {
- return m('.page.page-loading',
- _.component(ns.Loader)
- );
- }
- };
- } (Misago.prototype));
- (function (ns) {
- 'use strict';
- var setupMarkup = function(el, isInit, context) {
- context.retain = true;
- };
- ns.MisagoMarkup = {
- view: function(ctrl, content) {
- return m('article.misago-markup', {config: setupMarkup}, m.trust(content));
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.PageHeader = {
- view: function(ctrl, options) {
- return m('.page-header',
- m('.container', [
- m('h1', options.title),
- ])
- );
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- var legalLink = function(_, legal_type, default_title) {
- var url = ns.get(_.settings, legal_type + '_link');
- if (!url && ns.get(_.settings, legal_type)) {
- url = _.router.url(legal_type);
- }
- if (url) {
- return m('li',
- m('a', {href: url}, ns.get(_.settings, legal_type + '_title', default_title))
- );
- } else {
- return null;
- }
- };
- ns.FooterNav = {
- isVisible: function(settings) {
- return [
- !!settings.forum_footnote,
- !!settings.terms_of_service,
- !!settings.terms_of_service_link,
- !!settings.privacy_policy,
- !!settings.privacy_policy_link
- ].indexOf(true) !== -1;
- },
- view: function(ctrl, _) {
- var items = [];
- if (_.settings.forum_footnote) {
- items.push(m('li.forum-footnote', m.trust(_.settings.forum_footnote)));
- }
- items.push(legalLink(_, 'terms_of_service', gettext('Terms of service')));
- items.push(legalLink(_, 'privacy_policy', gettext('Privacy policy')));
- return m('ul.list-inline.footer-nav', items);
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.ForumFooter = {
- view: function(ctrl, _) {
- var nav = null;
- if (ns.FooterNav.isVisible(_.settings)) {
- nav = _.component(ns.FooterNav);
- }
- return m('footer.forum-footer', [
- m('.container',
- m('.footer-content', [
- nav,
- _.component(ns.FooterMisagoBranding)
- ])
- )
- ]);
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.FooterMisagoBranding = {
- view: function() {
- return m('a.misago-branding[href=http://misago-project.org]', [
- "powered by ", m('strong', "misago")
- ]);
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.BrandFull = {
- view: function(ctrl, branding, _) {
- var children = [
- m('img', {
- src: _.router.staticUrl('misago/img/site-logo.png'),
- alt: _.settings.forum_name
- })
- ];
- if (branding) {
- children.push(branding);
- }
- return m('a.navbar-brand', {href: _.router.url('index')}, children);
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.ForumNavbar = {
- view: function(ctrl, _) {
- var desktop_navbar = [];
- if (_.settings.forum_branding_display) {
- desktop_navbar.push(_.component(ns.BrandFull, _.settings.forum_branding_text));
- }
- desktop_navbar.push(m('ul.nav.navbar-nav', [
- m('li', m("a", {config: m.route, href: _.router.url('index')}, 'Index')),
- m('li', m("a", {config: m.route, href: _.router.url('test')}, 'Test'))
- ]));
- return m('nav.navbar.navbar-default.navbar-static-top[role="navigation"]', [
- m('.container.navbar-full.hidden-xs.hidden-sm', desktop_navbar)
- ]);
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- var Api = function(_) {
- // Ajax implementation
- var cookie_regex = new RegExp(_.context.CSRF_COOKIE_NAME + '\=([^;]*)');
- this.csrf_token = ns.get(document.cookie.match(cookie_regex), 0).split('=')[1];
- this.ajax = function(method, url, data, progress) {
- var deferred = m.deferred();
- var ajax_settings = {
- url: url,
- method: method,
- headers: {
- 'X-CSRFToken': this.csrf_token
- },
- data: data | {},
- dataType: 'json',
- success: function(data) {
- deferred.resolve(data);
- },
- error: function(jqXHR) {
- deferred.reject(jqXHR);
- }
- };
- if (progress) {
- return; // not implemented... yet!
- }
- $.ajax(ajax_settings);
- return deferred.promise;
- };
- this.get = function(url) {
- var preloaded_data = ns.pop(_.preloaded_data, url);
- if (preloaded_data) {
- var deferred = m.deferred();
- deferred.resolve(preloaded_data);
- return deferred.promise;
- } else {
- return this.ajax('GET', url);
- }
- };
- this.post = function(url) {
- return this.ajax('POST', url);
- };
- // API
- this.buildUrl = function(model, call, querystrings) {
- var url = _.router.base_url;
- url += 'api/' + model + '/';
- return url;
- };
- this.one = function(model, id) {
- var url = this.buildUrl(model) + id + '/';
- return this.get(url);
- };
- this.many = function(model, filters) {
- };
- this.call = function(model, target, call, data) {
- };
- };
- ns.Api = function(_) {
- return new Api(_);
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.ComponentFactory = function(_) {
- // Component factory
- _.component = function() {
- var arguments_array = [];
- for (var i = 0; i < arguments.length; i += 1) {
- arguments_array.push(arguments[i]);
- }
- arguments_array.push(_);
- return m.component.apply(undefined, arguments_array);
- };
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.Conf = function(_) {
- _.settings = ns.get(_.context, 'SETTINGS', {});
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.Outlet = {
- factory: function(_) {
- if (_.setup.fixture) {
- m.mount(document.getElementById(_.setup.fixture),
- _.component(ns.ForumLayout));
- }
- },
- destroy: function(_) {
- if (_.setup.fixture) {
- m.mount(_.setup.fixture, null);
- }
- }
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- var Router = function(_) {
- var self = this;
- this.base_url = $('base').attr('href');
- this.static_url = ns.get(_.context, 'STATIC_URL', '/');
- this.media_url = ns.get(_.context, 'MEDIA_URL', '/');
- // Routing
- this.urls = {};
- this.reverses = {};
- var populatePatterns = function(urlconf) {
- urlconf.patterns().forEach(function(url) {
- // set service container on component
- url.component.container = _;
- var final_pattern = self.base_url + url.pattern;
- final_pattern = final_pattern.replace('//', '/');
- self.urls[final_pattern] = url.component;
- self.reverses[url.name] = final_pattern;
- });
- };
- this.startRouting = function(urlconf, fixture) {
- populatePatterns(urlconf);
- this.fixture = fixture;
- m.route.mode = 'pathname';
- m.route(fixture, '/', this.urls);
- };
- this.url = function(name) {
- return this.reverses[name];
- };
- // Delegate clicks
- this.delegate_element = null;
- this.delegate_name = 'click.misago-router';
- this.cleanUrl = function(url) {
- if (!url) { return; }
- // Is link relative?
- var is_relative = url.substr(0, 1) === '/' && url.substr(0, 2) !== '//';
- // If link contains host, validate to see if its outgoing
- if (!is_relative) {
- var location = window.location;
- // If protocol matches current one, strip it from string
- // otherwhise stop handler
- if (url.substr(0, 2) !== '//') {
- var protocol = url.substr(0, location.protocol.length + 2);
- if (protocol !== location.protocol + '//') { return; }
- url = url.substr(location.protocol.length + 2);
- } else {
- url = url.substr(2);
- }
- // Host checks out?
- if (url.substr(0, location.host.length) !== location.host) { return; }
- url = url.substr(location.host.length);
- }
- // Is link within Ember app?
- if (url.substr(0, this.base_url.length) !== this.base_url) { return; }
- // Is link to media/static/avatar server?
- if (url.substr(0, this.static_url.length) === this.static_url) { return; }
- if (url.substr(0, this.media_url.length) === this.media_url) { return; }
- var avatars_url = '/user-avatar/';
- if (url.substr(0, avatars_url.length) === avatars_url) { return; }
- return url;
- };
- this.delegateClicks = function(element) {
- this.delegate_element = element;
- $(this.delegate_element).on(this.delegate_name, 'a', function(e) {
- var clean_url = self.cleanUrl(e.target.href);
- if (clean_url) {
- if (clean_url != m.route()) {
- m.route(clean_url);
- }
- e.preventDefault();
- }
- });
- };
- this.destroy = function() {
- $(this.delegate_element).off(this.delegate_name);
- };
- // Media/Static url
- var prefixUrl = function(prefix) {
- return function(url) {
- return prefix + url;
- };
- };
- this.staticUrl = prefixUrl(this.static_url);
- this.mediaUrl = prefixUrl(this.media_url);
- };
- ns.RouterFactory = function(_) {
- return new Router(_);
- };
- ns.startRouting = function(_) {
- _.router.startRouting(ns.urls, document.getElementById('router-fixture'));
- _.router.delegateClicks(document.getElementById(_.setup.fixture));
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.PageTitle = function(_) {
- _._setTitle = function(title) {
- if (typeof title === 'string') {
- title = {title: title};
- }
- var complete_title = title.title;
- if (typeof title.page !== 'undefined' && title.page > 1) {
- complete_title += ' (' + interpolate(gettext('page %(page)s'), { page:title.page }, true) + ')';
- }
- if (typeof title.parent !== 'undefined') {
- complete_title += ' | ' + title.parent;
- }
- document.title = complete_title + ' | ' + this.settings.forum_name;
- };
- _.setTitle = function(title) {
- if (title) {
- this._setTitle(title);
- } else {
- document.title = this.settings.forum_name;
- }
- };
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.has = function(obj, key) {
- if (obj !== undefined) {
- return obj.hasOwnProperty(key);
- } else {
- return false;
- }
- };
- ns.get = function(obj, key, value) {
- if (ns.has(obj, key)) {
- return obj[key];
- } else if (value !== undefined) {
- return value;
- } else {
- return undefined;
- }
- };
- ns.pop = function(obj, key, value) {
- var returnValue = ns.get(obj, key, value);
- if (ns.has(obj, key)) {
- delete obj[key];
- }
- return returnValue;
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.OrderedList = function(items) {
- this.is_ordered = false;
- this._items = items || [];
- this.add = function(key, item, order) {
- this._items.push({
- key: key,
- item: item,
- after: ns.get(order, 'after'),
- before: ns.get(order, 'before')
- });
- };
- this.get = function(key, value) {
- for (var i = 0; i < this._items.length; i++) {
- if (this._items[i].key === key) {
- return this._items[i].item;
- }
- }
- return value;
- };
- this.has = function(key) {
- return this.get(key) !== undefined;
- };
- this.values = function() {
- var values = [];
- for (var i = 0; i < this._items.length; i++) {
- values.push(this._items[i].item);
- }
- return values;
- };
- this.order = function(values_only) {
- if (!this.is_ordered) {
- this._items = this._order(this._items);
- this.is_ordered = true;
- }
- if (values_only || typeof values_only === 'undefined') {
- return this.values();
- } else {
- return this._items;
- }
- };
- this._order = function(unordered) {
- // Index of unordered items
- var index = [];
- unordered.forEach(function (item) {
- index.push(item.key);
- });
- // Ordered items
- var ordered = [];
- var ordering = [];
- // First pass: register items that
- // don't specify their order
- unordered.forEach(function (item) {
- if (!item.after && !item.before) {
- ordered.push(item);
- ordering.push(item.key);
- }
- });
- // Second pass: keep iterating items
- // until we hit iterations limit or finish
- // ordering list
- function insertItem(item) {
- var insertAt = -1;
- if (ordering.indexOf(item.key) === -1) {
- if (item.after) {
- insertAt = ordering.indexOf(item.after);
- if (insertAt !== -1) {
- insertAt += 1;
- }
- } else if (item.before) {
- insertAt = ordering.indexOf(item.before);
- }
- if (insertAt !== -1) {
- ordered.splice(insertAt, 0, item);
- ordering.splice(insertAt, 0, item.key);
- }
- }
- }
- var iterations = 200;
- while (iterations > 0 && index.length !== ordering.length) {
- iterations -= 1;
- unordered.forEach(insertItem);
- }
- return ordered;
- };
- };
- } (Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.startsWith = function(string, beginning) {
- return string.indexOf(beginning) === 0;
- };
- ns.endsWith = function(string, tail) {
- return string.indexOf(tail, string.length - tail.length) !== -1;
- };
- }(Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.UrlConfInvalidComponentError = function() {
- this.message = 'component argument should be array or object';
- };
- ns.UrlConf = function() {
- var self = this;
- this._patterns = [];
- this.patterns = function() {
- return this._patterns;
- };
- var prefixPattern = function(prefix, pattern) {
- return (prefix + pattern).replace('//', '/');
- };
- var include = function(prefix, patterns) {
- for (var i = 0; i < patterns.length; i ++) {
- self.url(prefixPattern(prefix, patterns[i].pattern),
- patterns[i].component,
- patterns[i].name);
- }
- };
- this.url = function(pattern, component, name) {
- if (typeof component !== 'object') {
- throw new ns.UrlConfInvalidComponentError();
- }
- if (pattern === '') {
- pattern = '/';
- }
- if (component instanceof ns.UrlConf) {
- include(pattern, component.patterns());
- } else {
- this._patterns.push({
- pattern: pattern,
- component: component,
- name: name
- });
- }
- };
- };
- } (Misago.prototype));
- (function (ns) {
- 'use strict';
- ns.loadingPage = function(_) {
- return m('.page.page-loading', _.component(ns.Loader));
- };
- } (Misago.prototype));
- (function (ns, UrlConf) {
- 'use strict';
- var urls = new UrlConf();
- urls.url('/', ns.IndexPage, 'index');
- // Legal pages
- urls.url('/terms-of-service/', ns.TermsOfServicePage, 'terms_of_service');
- urls.url('/privacy-policy/', ns.PrivacyPolicyPage, 'privacy_policy');
- ns.urls = urls;
- } (Misago.prototype, Misago.prototype.UrlConf));
|