<commit_before>/*global app, me, client*/
"use strict";

var _ = require('underscore');
var async = require('async');
var uuid = require('node-uuid');
var htmlify = require('../helpers/htmlify');
var HumanModel = require('human-model');
var Resources = require('./resources');
var Messages = require('./messages');
var Message = require('./message');
var avatarHandler = require('../helpers/avatarHandler');

module.exports = HumanModel.define({
    initialize: function (attrs) {
        if (attrs.jid) {
            this.id = attrs.jid.full;
        }
        var self = this;
        this.resources.bind("add remove reset", function(){
            self.membersCount = self.resources.length;
        });
    },
    type: 'muc',
    props: {
        id: ['string', true],
        name: 'string',
        autoJoin: ['bool', false, false],
        nick: 'string',
        jid: 'object'
    },
    session: {
        subject: 'string',
        activeContact: ['bool', false, false],
        lastInteraction: 'date',
        lastSentMessage: 'object',
        unreadCount: ['number', false, 0],
        persistent: ['bool', false, false],
        joined: ['bool', true, false],
        membersCount: ['number', false, 0],
    },
    derived: {
        displayName: {
            deps: ['name', 'jid'],
            fn: function () {
                var disp = this.name;
                if (!disp) disp = this.jid.jid;
                return disp.split('@')[0];
            }
        },
        displayUnreadCount: {
            deps: ['unreadCount'],
            fn: function () {
                if (this.unreadCount > 0) {
                    if (this.unreadCount < 100)
                      return this.unreadCount.toString();
                    else
                      return '99+'
                }
                return '';
            }
        },
        displaySubject: {
            deps: ['subject'],
            fn: function () {
                return htmlify.toHTML(this.subject);
            }
        },
        hasUnread: {
            deps: ['unreadCount'],
            fn: function () {
                return this.unreadCount > 0;
            }
        }
    },
    collections: {
        resources: Resources,
        messages: Messages
    },
    getName: function (jid) {
        var nickname = jid.split('/')[1];
        var name = nickname;
        var xmppContact = me.getContact(nickname);
        if (xmppContact) {
            name = xmppContact.displayName;
        }
        return name != '' ? name : nickname;
    },
    getNickname: function (jid) {
        var nickname = jid.split('/')[1];
        return nickname != this.getName(jid) ? nickname : '';
    },
    getAvatar: function (jid) {
        var avatar = avatarHandler.getGravatar('').uri;
        var xmppContact = me.getContact(jid.split('/')[1]);
        if (xmppContact) {
            avatar = xmppContact.avatar;
        }
        return avatar;
    },
    addMessage: function (message, notify) {
        message.owner = me.jid.bare;

        var self = this;

        var mentions = [];
        var toMe = false;
        this.resources.forEach(function (resource) {
            if (message.body.toLowerCase().indexOf('@' + resource.mucDisplayName) >= 0) {
                mentions.push('@' + resource.mucDisplayName);
                if (resource.mucDisplayName === self.nick)
                    toMe = true;
            }
        });
        if (message.body.toLowerCase().indexOf('@all') >= 0) {
            mentions.push('@all');
        }
        message.mentions = mentions;

        var mine = message.from.resource === this.nick;

        if (mine) {
            message._mucMine = true;
        }

        if (notify && (!this.activeContact || (this.activeContact && !app.state.focused)) && !mine) {
            this.unreadCount++;
            if (toMe) {
                app.notifications.create(this.displayName, {
                    body: message.body,
                    icon: this.avatar,
                    tag: this.id,
                    onclick: _.bind(app.navigate, app, '/groupchat/' + encodeURIComponent(this.jid))
                });
                if (me.soundEnabled)
                    app.soundManager.play('threetone-alert');
            }
            else
            {
                if (me.soundEnabled)
                    app.soundManager.play('ding');
            }
        }

        message.acked = true;

        if (mine) {
            this.lastSentMessage = message;
        }

        var existing = Message.idLookup(message.from['full'], message.mid);
        if (existing) {
            existing.set(message);
            existing.save();
        } else {
            this.messages.add(message);
            message.save();
        }

        var newInteraction = new Date(message.created);
        if (!this.lastInteraction || this.lastInteraction < newInteraction) {
            this.lastInteraction = newInteraction;
        }
    },
    join: function (manual) {
        if (!this.nick) {
            this.nick = me.jid.local;
        }
        this.messages.reset();
        this.resources.reset();

        client.joinRoom(this.jid, this.nick, {
            joinMuc: {
                history: {
                    maxstanzas: 50
                }
            }
        });

        if (manual) {
            var form = {
                fields: [
                    {
                      type: 'hidden',
                      name: 'FORM_TYPE',
                      value: 'http://jabber.org/protocol/muc#roomconfig'
                    },
                    {
                      type: 'boolean',
                      name: 'muc#roomconfig_changesubject',
                      value: true
                    },
                    {
                      type: 'boolean',
                      name: 'muc#roomconfig_persistentroom',
                      value: true
                    },
                ]
            };
            client.configureRoom(this.jid, form, function(err, resp) {
                if (err) return;
            });

            if (SERVER_CONFIG.domain && SERVER_CONFIG.admin) {
                var self = this;
                client.setRoomAffiliation(this.jid, SERVER_CONFIG.admin + '@' + SERVER_CONFIG.domain, 'owner', 'administration', function(err, resp) {
                    if (err) return;
                    client.setRoomAffiliation(self.jid, me.jid, 'none', 'administration');
                });
            }
        }

        var self = this;
        // After a reconnection
        client.on('muc:join', function (pres) {
            if (self.messages.length) {
                self.fetchHistory(true);
            }
        });
    },
    fetchHistory: function(allInterval) {
        var self = this;
        app.whenConnected(function () {
            var filter = {
                'to': self.jid,
                rsm: {
                    max: 40,
                    before: !allInterval
                }
            };

            if (allInterval) {
                var lastMessage = self.messages.last();
                if (lastMessage && lastMessage.created) {
                    var start = new Date(lastMessage.created);
                    filter.start = start.toISOString();
                }
            } else {
                var firstMessage = self.messages.first();
                if (firstMessage && firstMessage.created) {
                    var end = new Date(firstMessage.created);
                    filter.end = end.toISOString();
                }
            }

            client.searchHistory(filter, function (err, res) {
                if (err) return;

                var results = res.mamResult.items || [];

                results.forEach(function (result) {
                    var msg = result.forwarded.message;

                    msg.mid = msg.id;
                    delete msg.id;

                    if (!msg.delay) {
                        msg.delay = result.forwarded.delay;
                    }

                    if (msg.replace) {
                        var original = Message.idLookup(msg.from[msg.type == 'groupchat' ? 'full' : 'bare'], msg.replace);
                        // Drop the message if editing a previous, but
                        // keep it if it didn't actually change an
                        // existing message.
                        if (original && original.correct(msg)) return;
                    }

                    var message = new Message(msg);
                    message.archivedId = result.id;
                    message.acked = true;

                    self.addMessage(message, false);
                });

                if (allInterval) {
                  self.trigger('refresh');
                  if (results.length == 40)
                      self.fetchHistory(true);
                }
            });
        });
    },
    leave: function () {
        this.resources.reset();
        client.leaveRoom(this.jid, this.nick);
    }
});
<commit_msg>attempt1<commit_after>/*global app, me, client*/
"use strict";

var _ = require('underscore');
var async = require('async');
var uuid = require('node-uuid');
var htmlify = require('../helpers/htmlify');
var HumanModel = require('human-model');
var Resources = require('./resources');
var Messages = require('./messages');
var Message = require('./message');
var avatarHandler = require('../helpers/avatarHandler');

module.exports = HumanModel.define({
    initialize: function (attrs) {
        if (attrs.jid) {
            this.id = attrs.jid.full;
        }
        var self = this;
        this.resources.bind("add remove reset", function(){
            self.membersCount = self.resources.length;
        });
    },
    type: 'muc',
    props: {
        id: ['string', true],
        name: 'string',
        autoJoin: ['bool', false, false],
        nick: 'string',
        jid: 'object'
    },
    session: {
        subject: 'string',
        activeContact: ['bool', false, false],
        lastInteraction: 'date',
        lastSentMessage: 'object',
        unreadCount: ['number', false, 0],
        persistent: ['bool', false, false],
        joined: ['bool', true, false],
        membersCount: ['number', false, 0],
    },
    derived: {
        displayName: {
            deps: ['name', 'jid'],
            fn: function () {
                var disp = this.name;
                if (!disp) disp = this.jid.jid;
                return disp.split('@')[0];
            }
        },
        displayUnreadCount: {
            deps: ['unreadCount'],
            fn: function () {
                if (this.unreadCount > 0) {
                    if (this.unreadCount < 100)
                      return this.unreadCount.toString();
                    else
                      return '99+'
                }
                return '';
            }
        },
        displaySubject: {
            deps: ['subject'],
            fn: function () {
                return htmlify.toHTML(this.subject);
            }
        },
        hasUnread: {
            deps: ['unreadCount'],
            fn: function () {
                return this.unreadCount > 0;
            }
        }
    },
    collections: {
        resources: Resources,
        messages: Messages
    },
    getName: function (jid) {
        var nickname = jid.split('/')[1];
        var name = nickname;
        var xmppContact = me.getContact(nickname);
        if (xmppContact) {
            name = xmppContact.displayName;
        }
        return name != '' ? name : nickname;
    },
    getNickname: function (jid) {
        var nickname = jid.split('/')[1];
        return nickname != this.getName(jid) ? nickname : '';
    },
    getAvatar: function (jid) {
        var avatar = avatarHandler.getGravatar('').uri;
        var xmppContact = me.getContact(jid.split('/')[1]);
        if (xmppContact) {
            avatar = xmppContact.avatar;
        }
        return avatar;
    },
    addMessage: function (message, notify) {
        message.owner = me.jid.bare;

        var self = this;

        var mentions = [];
        var toMe = false;
        this.resources.forEach(function (resource) {
            if (message.body.toLowerCase().indexOf(resource.mucDisplayName) >= 0) {
                mentions.push(resource.mucDisplayName);
                if (resource.mucDisplayName === self.nick)
                    toMe = true;
            }
        });
        if (message.body.toLowerCase().indexOf('all: ') >= 0) {
            mentions.push('all:');
        }
        message.mentions = mentions;

        var mine = message.from.resource === this.nick;

        if (mine) {
            message._mucMine = true;
        }

        if (notify && (!this.activeContact || (this.activeContact && !app.state.focused)) && !mine) {
            this.unreadCount++;
            if (toMe) {
                app.notifications.create(this.displayName, {
                    body: message.body,
                    icon: this.avatar,
                    tag: this.id,
                    onclick: _.bind(app.navigate, app, '/groupchat/' + encodeURIComponent(this.jid))
                });
                if (me.soundEnabled)
                    app.soundManager.play('threetone-alert');
            }
            else
            {
                if (me.soundEnabled)
                    app.soundManager.play('ding');
            }
        }

        message.acked = true;

        if (mine) {
            this.lastSentMessage = message;
        }

        var existing = Message.idLookup(message.from['full'], message.mid);
        if (existing) {
            existing.set(message);
            existing.save();
        } else {
            this.messages.add(message);
            message.save();
        }

        var newInteraction = new Date(message.created);
        if (!this.lastInteraction || this.lastInteraction < newInteraction) {
            this.lastInteraction = newInteraction;
        }
    },
    join: function (manual) {
        if (!this.nick) {
            this.nick = me.jid.local;
        }
        this.messages.reset();
        this.resources.reset();

        client.joinRoom(this.jid, this.nick, {
            joinMuc: {
                history: {
                    maxstanzas: 50
                }
            }
        });

        if (manual) {
            var form = {
                fields: [
                    {
                      type: 'hidden',
                      name: 'FORM_TYPE',
                      value: 'http://jabber.org/protocol/muc#roomconfig'
                    },
                    {
                      type: 'boolean',
                      name: 'muc#roomconfig_changesubject',
                      value: true
                    },
                    {
                      type: 'boolean',
                      name: 'muc#roomconfig_persistentroom',
                      value: true
                    },
                ]
            };
            client.configureRoom(this.jid, form, function(err, resp) {
                if (err) return;
            });

            if (SERVER_CONFIG.domain && SERVER_CONFIG.admin) {
                var self = this;
                client.setRoomAffiliation(this.jid, SERVER_CONFIG.admin + '@' + SERVER_CONFIG.domain, 'owner', 'administration', function(err, resp) {
                    if (err) return;
                    client.setRoomAffiliation(self.jid, me.jid, 'none', 'administration');
                });
            }
        }

        var self = this;
        // After a reconnection
        client.on('muc:join', function (pres) {
            if (self.messages.length) {
                self.fetchHistory(true);
            }
        });
    },
    fetchHistory: function(allInterval) {
        var self = this;
        app.whenConnected(function () {
            var filter = {
                'to': self.jid,
                rsm: {
                    max: 40,
                    before: !allInterval
                }
            };

            if (allInterval) {
                var lastMessage = self.messages.last();
                if (lastMessage && lastMessage.created) {
                    var start = new Date(lastMessage.created);
                    filter.start = start.toISOString();
                }
            } else {
                var firstMessage = self.messages.first();
                if (firstMessage && firstMessage.created) {
                    var end = new Date(firstMessage.created);
                    filter.end = end.toISOString();
                }
            }

            client.searchHistory(filter, function (err, res) {
                if (err) return;

                var results = res.mamResult.items || [];

                results.forEach(function (result) {
                    var msg = result.forwarded.message;

                    msg.mid = msg.id;
                    delete msg.id;

                    if (!msg.delay) {
                        msg.delay = result.forwarded.delay;
                    }

                    if (msg.replace) {
                        var original = Message.idLookup(msg.from[msg.type == 'groupchat' ? 'full' : 'bare'], msg.replace);
                        // Drop the message if editing a previous, but
                        // keep it if it didn't actually change an
                        // existing message.
                        if (original && original.correct(msg)) return;
                    }

                    var message = new Message(msg);
                    message.archivedId = result.id;
                    message.acked = true;

                    self.addMessage(message, false);
                });

                if (allInterval) {
                  self.trigger('refresh');
                  if (results.length == 40)
                      self.fetchHistory(true);
                }
            });
        });
    },
    leave: function () {
        this.resources.reset();
        client.leaveRoom(this.jid, this.nick);
    }
});
<|endoftext|>


<commit_before>var MalinkyAjaxPaging = function ($) {
    var init = function () {
        function debounce(a, t, n) {
            var o;
            return function () {
                var i = this,
                        e = arguments,
                        p = function () {
                            o = null, n || a.apply(i, e)
                        },
                        m = n && !o;
                clearTimeout(o), o = setTimeout(p, t), m && a.apply(i, e)
            }
        }
        var mymapAjaxLoader = mapAjaxLoader,
                mymapCssLoadMore = mapCssLoadMore,
                mymapCssLoadMoreButton = mapCssLoadMoreButton,
                mymapInfiniteScrollBuffer = mapInfiniteScrollBuffer,
                mymapLoadingTimer = "",
                mymapLoadingMorePostsText = mapLoadingMorePostsText,
                mymapLoadMoreButtonText = mapLoadMoreButtonText,
                mymapPaginationClass = mapPaginationClass,
                mymapPaginationClassPixelsToDocBottom = mapPaginationClassPixelsToDocBottom,
                mymapPagingType = mapPagingType,
                mymapPostsWrapperClass = mapPostsWrapperClass,
                mymapPostClass = mapPostClass,
                mymapNextPageSelector = mapNextPageSelector,
                mymapNextPageUrl = mapNextPageUrl,
                mymapPaginatorCount = mapPaginatorCount,
                mymapUserCallback = mapUserCallback,
                infiniteScrollRunning = !1,
                mapLoadPosts = function () {
                    $.ajax({
                        type: "GET",
                        url: mymapNextPageUrl,
                        dataType: "html",
                        success: function (a) {
                            var t = $.parseHTML(a),
                                    n = ($(t).find(mymapPostsWrapperClass), mapPaginatorTotalCount(t));
                            mapAddPaginatorCount(t, n);
                            var o = $(t).find(mymapPostsWrapperClass + '[data-paginator-count="' + mymapPaginatorCount + '"] ' + mymapPostClass),
                                    i = $(mymapPostsWrapperClass + '[data-paginator-count="' + mymapPaginatorCount + '"] ' + mymapPostClass).last(),
                                    e = $(mymapPostsWrapperClass + '[data-paginator-count="' + mymapPaginatorCount + '"] ' + mymapPostClass);
                            if (i.after(o), "infinite-scroll" != mymapPagingType && "load-more" != mymapPagingType || (1 == n ? mapIsLastPage(t, mymapNextPageSelector) ? mymapNextPageUrl = $(t).find(mymapNextPageSelector).attr("href") : ($('#malinky-ajax-pagination-button[data-paginator-count="' + mymapPaginatorCount + '"]').parent().remove(), window.removeEventListener("scroll", mapInfiniteScroll)) : mapIsLastPage(t, mymapNextPageSelector + '[data-paginator-count="' + mymapPaginatorCount + '"]') ? mymapNextPageUrl = $(t).find(mymapNextPageSelector + '[data-paginator-count="' + mymapPaginatorCount + '"]').attr("href") : ($('#malinky-ajax-pagination-button[data-paginator-count="' + mymapPaginatorCount + '"]').parent().remove(), window.removeEventListener("scroll", mapInfiniteScroll))), "pagination" == mymapPagingType) {
                                e.remove(), history.pushState(null, null, mymapNextPageUrl);
                                var p = $(t).find(mymapPaginationClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').first();
                                $(mymapPaginationClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').replaceWith(p)
                            }
                            mapLoaded()
                        },
                        error: function (a, t) {
                            mapFailed()
                        },
                        complete: function (requestObj) {
                            "pagination" == mymapPagingType && $("body,html").animate({
                                scrollTop: $(mymapPostsWrapperClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').offset().top - 150
                            }, 400), "infinite-scroll" == mymapPagingType && (infiniteScrollRunning = !1), "load-more" == mymapPagingType && $('#malinky-ajax-pagination-button[data-paginator-count="' + mymapPaginatorCount + '"]').removeClass("malinky-load-more__button-disable");
                            var mapResponse = $.parseHTML(requestObj.responseText),
                                    paginatorTotalCountAjax = mapPaginatorTotalCount(mapResponse);
                            mapAddPaginatorCount(mapResponse, paginatorTotalCountAjax);
                            var $mapLoadedPosts = $(mapResponse).find(mymapPostsWrapperClass + '[data-paginator-count="' + mymapPaginatorCount + '"] ' + mymapPostClass);
                            !function (loadedPosts, url) {
                                eval(mymapUserCallback)
                            }($mapLoadedPosts, this.url)
                        }
                    })
                },
                mapPaginatorTotalCount = function (a) {
                    var t = 0;
                    for (var n in malinkySettings)
                        $(a).find(malinkySettings[n].posts_wrapper).length && $(a).find(malinkySettings[n].post_wrapper).length && $(a).find(malinkySettings[n].pagination_wrapper).length && t++;
                    return t
                },
                mapAddPaginatorCount = function (a, t) {
                    var n = 1;
                    for (var o in malinkySettings)
                        $(a).find(malinkySettings[o].posts_wrapper).length && $(a).find(malinkySettings[o].post_wrapper).length && $(a).find(malinkySettings[o].pagination_wrapper).length && (1 == t ? ($(a).find(malinkySettings[o].posts_wrapper).attr("data-paginator-count", n), $(a).find(malinkySettings[o].pagination_wrapper).attr("data-paginator-count", n)) : ($(a).find(malinkySettings[o].posts_wrapper).attr("data-paginator-count", n), $(a).find(malinkySettings[o].posts_wrapper + " " + malinkySettings[o].pagination_wrapper).attr("data-paginator-count", n), $(a).find(malinkySettings[o].posts_wrapper + " " + malinkySettings[o].next_page_selector).attr("data-paginator-count", n), n++))
                },
                mapIsLastPage = function (a, t) {
                    return $(a).find(t).length
                },
                mapAddLoader = function () {
                    $(mymapPaginationClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').last().before('
' + mymapAjaxLoader + "
")
                },
                mapLoading = function () {
                    $('.malinky-ajax-pagination-loading[data-paginator-count="' + mymapPaginatorCount + '"]').show(), "load-more" != mymapPagingType && "infinite-scroll" != mymapPagingType || $('#malinky-ajax-pagination-button[data-paginator-count="' + mymapPaginatorCount + '"]').text(mymapLoadingMorePostsText)
                },
                mapLoaded = function () {
                    $('.malinky-ajax-pagination-loading[data-paginator-count="' + mymapPaginatorCount + '"]').hide(), "load-more" != mymapPagingType && "infinite-scroll" != mymapPagingType || $('#malinky-ajax-pagination-button[data-paginator-count="' + mymapPaginatorCount + '"]').text(mymapLoadMoreButtonText), clearTimeout(mapLoadingTimer)
                },
                mapFailed = function () {
                    $('.malinky-ajax-pagination-loading[data-paginator-count="' + mymapPaginatorCount + '"]').hide(), clearTimeout(mapLoadingTimer)
                },
                mapInfiniteScroll = debounce(function () {
                    if (!infiniteScrollRunning) {
                        var a = ($(document).height() - $(window).scrollTop() - $(window).height(), $(mymapPostsWrapperClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').offset().top),
                                t = $(mymapPostsWrapperClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').outerHeight();
                        $(window).height() + $(window).scrollTop() + mymapInfiniteScrollBuffer > a + t && (infiniteScrollRunning = !0, mapLoading(), mapLoadPosts())
                    }
                }, 250);
        "infinite-scroll" == mymapPagingType ? $(mymapNextPageSelector + '[data-paginator-count="' + mymapPaginatorCount + '"]').attr("href") && (mapAddLoader(), $(mymapPaginationClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').remove(), window.addEventListener("scroll", mapInfiniteScroll)) : "load-more" == mymapPagingType ? $(mymapNextPageSelector + '[data-paginator-count="' + mymapPaginatorCount + '"]').attr("href") && ($(mymapPaginationClass + '[data-paginator-count="' + mymapPaginatorCount + '"]').last().after('
' + mapLoadMoreButtonText + "
"), mapAddLoader(), $(mymapPaginationClass + '[data-paginator-count="' + mymapPaginatorCount + '"]:not(:has(>a#malinky-ajax-pagination-button[data-paginator-count="' + mymapPaginatorCount + '"]))').remove(), $('#malinky-ajax-pagination-button[data-paginator-count="' + mymapPaginatorCount + '"]').click(function (a) {
            a.preventDefault(), $(this).addClass("malinky-load-more__button-disable"), mapLoadingTimer = setTimeout(mapLoading, 750), mapLoadPosts()
        })) : "pagination" == mymapPagingType && (mapAddLoader(), $(document).on("click", mymapPaginationClass + '[data-paginator-count="' + mymapPaginatorCount + '"]', function (a) {
            a.preventDefault(), mapLoadingTimer = setTimeout(mapLoading, 750), mymapNextPageUrl = a.target.href, mapLoadPosts()
        }), window.addEventListener("popstate", function (a) {
            mymapNextPageUrl = document.URL, mapLoadPosts()
        }))
    },
            paginatorCount = 0,
            paginatorCountSetUp = 1,
            paginatorTotalCount = 0;
    for (var key in malinkySettings)
        $(malinkySettings[key].posts_wrapper).length && $(malinkySettings[key].post_wrapper).length && $(malinkySettings[key].pagination_wrapper).length && $(malinkySettings[key].next_page_selector).length && paginatorTotalCount++;
    for (var key in malinkySettings)
        if ($(malinkySettings[key].posts_wrapper).length && $(malinkySettings[key].post_wrapper).length && $(malinkySettings[key].pagination_wrapper).length && $(malinkySettings[key].next_page_selector).length) {
            1 == paginatorTotalCount ? ($(malinkySettings[key].posts_wrapper).attr("data-paginator-count", paginatorCountSetUp), $(malinkySettings[key].pagination_wrapper).attr("data-paginator-count", paginatorCountSetUp), $(malinkySettings[key].next_page_selector).attr("data-paginator-count", paginatorCountSetUp)) : ($(malinkySettings[key].posts_wrapper).attr("data-paginator-count", paginatorCountSetUp), $(malinkySettings[key].posts_wrapper + " " + malinkySettings[key].pagination_wrapper).attr("data-paginator-count", paginatorCountSetUp), $(malinkySettings[key].posts_wrapper + " " + malinkySettings[key].next_page_selector).attr("data-paginator-count", paginatorCountSetUp), paginatorCountSetUp++);
            var mapAjaxLoader = malinkySettings[key].ajax_loader,
                    mapCssLoadMore = malinkySettings[key].malinky_load_more,
                    mapCssLoadMoreButton = malinkySettings[key].malinky_load_more_button,
                    mapInfiniteScrollBuffer = parseInt(malinkySettings[key].infinite_scroll_buffer),
                    mapLoadingTimer = "",
                    mapLoadingMorePostsText = malinkySettings[key].loading_more_posts_text,
                    mapLoadMoreButtonText = malinkySettings[key].load_more_button_text,
                    mapPaginationClass = malinkySettings[key].pagination_wrapper,
                    mapPaginationClassPixelsToDocBottom = $(document).height() - $(mapPaginationClass).offset().top,
                    mapPagingType = malinkySettings[key].paging_type,
                    mapPostsWrapperClass = malinkySettings[key].posts_wrapper,
                    mapPostClass = malinkySettings[key].post_wrapper,
                    mapNextPageSelector = malinkySettings[key].next_page_selector,
                    mapPaginatorCount = ++paginatorCount,
                    mapUserCallback = malinkySettings[key].callback_function;
            if (1 == paginatorTotalCount)
                var mapNextPageUrl = $(malinkySettings[key].next_page_selector).attr("href");
            else
                var mapNextPageUrl = $(malinkySettings[key].posts_wrapper + " " + malinkySettings[key].next_page_selector).attr("href");
            init()
        }
}(jQuery);<commit_msg>deleted obsolete file<commit_after><|endoftext|>


<commit_before>import React from 'react/addons';
import httpify from 'httpify';
import {
	Container,
	Mixins,
	UI
} from 'touchstonejs';

module.exports = React.createClass({
	mixins: [Mixins.Transitions],
	statics: {
		navigationBar: 'main',
		getNavigation () {
			return {
				title: 'Ratings'
			}
		}
	},

	getInitialState () {
		return {
			sessionName: ''
		}
	},

	createGuid () {
		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
			var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
			return v.toString(16);
		});
	},

	join () {
		var self = this;

		if (this.state.sessionName) {
			console.log('joining...', this.state.sessionName, this.createGuid());

			httpify({
				method: 'POST',
				url: 'http://xebia-innovation-day-rater.appspot.com/session',
				headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
				body: JSON.stringify({ Guid: self.createGuid(), Name: this.state.sessionName }),
				timeout: 20000
			}, (err, res) => {
				if (err) {
					console.error('failed to POST session', err);
					return;
				}
				console.log('response body', res.body);
				self.transitionTo('main:rate', { transition: 'reveal-from-bottom' });
			});
		}
	},

	onChange (event) {
		this.setState({
			sessionName: event.target.value
		})
	},

	render () {
		return (
			<Container>
				<UI.Group>
					<UI.GroupHeader>Greetings, stranger</UI.GroupHeader>
					<UI.GroupBody>
						<UI.GroupInner>

Welcome to the Ratings app. Join a session to start rating the talks.

						</UI.GroupInner>
					</UI.GroupBody>
				</UI.Group>
				<UI.Group>
					<UI.GroupHeader>Join session</UI.GroupHeader>
					<UI.GroupBody>
						<UI.Input ref="sessionName" value={this.state.sessionName} onChange={this.onChange} placeholder="Session Name"/>
						<UI.Button type="primary" onTap={this.join}>JOIN SESSION</UI.Button>
					</UI.GroupBody>
				</UI.Group>
			</Container>
		);
	}
});
<commit_msg>Do not create new session when joining<commit_after>import React from 'react/addons';
import Timers from 'react-timers';
import httpify from 'httpify';
import {
	Container,
	Mixins,
	UI
} from 'touchstonejs';

module.exports = React.createClass({
	mixins: [Mixins.Transitions, Timers()],
	statics: {
		navigationBar: 'main',
		getNavigation () {
			return {
				title: 'Ratings'
			}
		}
	},

	getInitialState () {
		return {
			alertbar: {
				visible: false,
				text: ''
			},
			sessionName: ''
		}
	},

	createGuid () {
		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
			var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
			return v.toString(16);
		});
	},

	join () {
		var self = this;

		if (this.state.sessionName) {
			console.log('join session', this.state.sessionName);

			httpify({
				method: 'GET',
				url: 'http://xebia-innovation-day-rater.appspot.com/session?name=' + this.state.sessionName,
				headers: {'Accept': 'application/json'},
				timeout: 20000
			}, (err, res) => {
				if (err) {
					console.error('failed to GET session', err);
					this.showAlert('Could not find session');
					this.setTimeout(function () {
						this.hideAlert();
					}, 1000);
				} else {
					console.log('found session', res.body);
					self.transitionTo('main:rate', {transition: 'reveal-from-bottom'});
				}
			});
		}
	},

	onChange (event) {
		this.setState({
			sessionName: event.target.value
		})
	},

	showAlert(message) {
		this.setState({
			alertbar: {
				visible: true,
				text: message
			}
		});
	},

	hideAlert() {
		this.setState({
			alertbar: {
				visible: false,
				text: ''
			}
		});
	},

	render () {
		return (
			<Container>
				<UI.Group>
					<UI.Alertbar type={'warning'} visible={this.state.alertbar.visible} animated>{this.state.alertbar.text || ''}</UI.Alertbar>
					<UI.GroupHeader>Greetings, stranger</UI.GroupHeader>
					<UI.GroupBody>
						<UI.GroupInner>

Welcome to the Ratings app. Join a session to start rating the talks.

						</UI.GroupInner>
					</UI.GroupBody>
				</UI.Group>
				<UI.Group>
					<UI.GroupHeader>Join session</UI.GroupHeader>
					<UI.GroupBody>
						<UI.Input ref="sessionName" value={this.state.sessionName} onChange={this.onChange} placeholder="Session Name"/>
						<UI.Button type="primary" onTap={this.join}>JOIN SESSION</UI.Button>
					</UI.GroupBody>
				</UI.Group>
			</Container>
		);
	}
});
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import {omit, groupBy} from 'lodash'
import RenderField from '../Object/RenderField'
import ObjectValueContainer from '../Object/ObjectContainer'
import Button from 'part:@sanity/components/buttons/default'
import Dialog from 'part:@sanity/components/dialogs/fullscreen'
import ImageTool from '@sanity/imagetool'
import _HotspotImage from '@sanity/imagetool/HotspotImage'
import createImageLoader from './common/createImageLoader'
import {DEFAULT_CROP} from '@sanity/imagetool/constants'
import ImageInputFieldset from 'part:@sanity/components/imageinput/fieldset'

const DEFAULT_HOTSPOT = {
  height: 1,
  width: 1,
  x: 0.5,
  y: 0.5
}

const HotspotImage = createImageLoader(_HotspotImage, image => {
  return {srcAspectRatio: image.width / image.height}
})

const ASPECT_RATIOS = [
  ['Landscape', 16 / 9],
  ['Portrait', 9 / 16],
  ['Square', 1],
  ['Panorama', 4]
]

export default class ImageInput extends React.PureComponent {
  static propTypes = {
    field: PropTypes.shape({
      fields: PropTypes.array
    }),
    value: PropTypes.object,
    onChange: PropTypes.func,
    onEnter: PropTypes.func,
    uploadFn: PropTypes.func.isRequired,
    materializeReferenceFn: PropTypes.func.isRequired,
    level: PropTypes.number,
    validation: PropTypes.object
  }
  static valueContainer = ObjectValueContainer

  state = {
    status: 'ready',
    error: null,
    progress: null,
    uploadingImage: null,
    materializedImage: null,
    isAdvancedEditOpen: false
  }

  subscription = null

  componentDidMount() {
    const {value} = this.props
    const imageReference = value.getAttribute('asset')
    this.materializeImageRef(imageReference)
  }

  componentWillReceiveProps(nextProps) {
    const nextRef = nextProps.value.getAttribute('asset')
    if (this.props.value.getAttribute('asset') !== nextRef) {
      this.cancel()
      this.materializeImageRef(nextRef)
    }
  }

  upload(image) {
    this.cancel()
    this.setState({uploadingImage: image})

    this.subscription = this.props.uploadFn(image).subscribe({
      next: this.handleUploadProgress,
      error: this.handleUploadError
    })
  }

  materializeImageRef(ref) {
    if (ref.isEmpty()) {
      this.setState({materializedImage: null})
      return
    }
    const {materializeReferenceFn} = this.props
    materializeReferenceFn(ref.refId).then(materialized => {
      this.setState({materializedImage: materialized})
    })
  }

  componentWillUnmount() {
    // todo: fix this properly by unsubscribing to upload observable without cancelling it
    this._unmounted = true
  }

  cancel() {
    if (this.subscription) {
      this.subscription.unsubscribe()
    }
  }

  hasField(fieldName) {
    return this.props.field.fields.find(field => field.name === fieldName)
  }

  createSetIfMissingPatch() {
    return {
      type: 'setIfMissing',
      value: {
        _type: this.props.value.context.field.type,
        asset: {_type: 'reference'}
      }
    }
  }

  setStateIfMounted(nextState) {
    if (!this._unmounted) {
      this.setState(nextState)
    }
  }

  handleUploadProgress = event => {
    if (event.type === 'progress' && event.stage === 'upload') {
      this.setStateIfMounted({
        status: 'pending',
        progress: {percent: event.percent}
      })
    }

    if (event.type === 'complete') {
      const {onChange} = this.props
      onChange({
        patch: [
          this.createSetIfMissingPatch(),
          {
            type: 'set',
            path: ['asset'],
            value: {_ref: event.id}
          }
        ]
      })
      this.setStateIfMounted({
        uploadingImage: null,
        status: 'complete'
      })
    }
  }

  handleUploadError = error => {
    this.setState({
      status: 'error',
      error: error
    })
  }

  handleSelect = images => {
    this.upload(images[0])
  }

  handleClearValue = event => {
    event.preventDefault()
    const {onChange} = this.props
    onChange({patch: {type: 'unset'}})
  }

  handleCancel = () => {
    this.cancel()
    this.setState({
      status: 'cancelled',
      error: null,
      progress: null,
      uploadingImage: null
    })
  }

  handleFieldChange = (event, fieldName) => {
    const {onChange} = this.props

    const patch = [
      this.createSetIfMissingPatch(),
      {
        ...event.patch,
        path: [fieldName, ...(event.patch.path || [])]
      }
    ]
    onChange({patch})
  }

  handleFieldEnter = (event, fieldName) => {
    this.props.onEnter(fieldName)
  }

  handleEditBtnClick = event => {
    this.setState({isAdvancedEditOpen: true})
  }

  handleEditDialogClose = event => {
    this.setState({isAdvancedEditOpen: false})
  }

  renderFields(fields) {
    return fields.map(field => this.renderField(field))
  }

  handleImageToolChange = newValue => {
    const {onChange} = this.props
    onChange({
      patch: [
        this.createSetIfMissingPatch(),
        {
          type: 'merge',
          value: {
            crop: newValue.crop,
            hotspot: newValue.hotspot
          }
        }
      ]
    })
  }

  getImageUrl() {
    const {uploadingImage, materializedImage} = this.state
    if (uploadingImage) {
      return uploadingImage.previewUrl
    }
    if (materializedImage && materializedImage.url) {
      return `${materializedImage.url}?w=500`
    }
    return null
  }

  isImageToolEnabled() {
    return this.hasField('hotspot') && this.hasField('crop')
  }

  renderImageTool() {
    const {value} = this.props
    const hotspot = value.getAttribute('hotspot').toJSON() || DEFAULT_HOTSPOT
    const crop = value.getAttribute('crop').toJSON() || DEFAULT_CROP

    const {uploadingImage, materializedImage} = this.state

    const imageUrl = uploadingImage ? uploadingImage.previewUrl : (materializedImage || {}).url
    return (

            <ImageTool value={{hotspot, crop}} src={imageUrl} onChange={this.handleImageToolChange} />

            {ASPECT_RATIOS.map(([title, ratio]) => {
              return (

{title}

                  <HotspotImage hotspot={hotspot} crop={crop} src={imageUrl} aspectRatio={ratio} />

              )
            })}

    )
  }
  renderAdvancedEdit(fields) {
    const grouped = groupBy(fields, field => {
      if (field.name === 'hotspot' || field.name === 'crop') {
        return 'imagetool'
      }
      return 'other'
    })
    return (
      <Dialog title="Edit details" onClose={this.handleEditDialogClose} isOpen>
        {grouped.imagetool && this.renderImageTool()}
        {grouped.other && this.renderFields(grouped.other)}
        <Button onClick={this.handleEditDialogClose}>Close</Button>
      </Dialog>
    )
  }

  renderField(field) {
    const {value, validation, level} = this.props
    const fieldValidation = validation && validation.fields[field.name]

    const fieldValue = value.getAttribute(field.name)

    return (
      <RenderField
        key={field.name}
        fieldName={field.name}
        field={field}
        value={fieldValue}
        onChange={this.handleFieldChange}
        onEnter={this.handleFieldEnter}
        validation={fieldValidation}
        level={level + 1}
      />
    )
  }

  render() {
    const {status, progress, isAdvancedEditOpen} = this.state
    const {field, level, value} = omit(this.props,
      'uploadFn',
      'materializeReferenceFn',
      'onChange',
      'onEnter',
      'validation',
      'focus'
    )
    const fieldGroups = Object.assign({asset: [], highlighted: [], other: []}, groupBy(field.fields, fieldDef => {
      if (fieldDef.name === 'asset') {
        return 'asset'
      }
      if (fieldDef.options && fieldDef.options.isHighlighted) {
        return 'highlighted'
      }
      return 'other'
    }))

    const imageUrl = this.getImageUrl()

    const isImageToolEnabled = this.isImageToolEnabled()

    return (
      <ImageInputFieldset
        status={status}
        legend={field.title}
        level={level}
        percent={progress && progress.percent}
        onSelect={this.handleSelect}
        onCancel={this.handleCancel}
        onClear={this.handleClearValue}
        hotspotImage={{
          hotspot: isImageToolEnabled ? value.getAttribute('hotspot').get() : DEFAULT_HOTSPOT,
          crop: isImageToolEnabled ? value.getAttribute('crop').get() : DEFAULT_CROP,
          imageUrl: imageUrl
        }}
      >
        {fieldGroups.highlighted.length > 0 && this.renderFields(fieldGroups.highlighted)}
        {isAdvancedEditOpen && this.renderAdvancedEdit(fieldGroups.highlighted.concat(fieldGroups.other))}
      </ImageInputFieldset>
    )
  }
}
<commit_msg>fixing image input<commit_after>import React, {PropTypes} from 'react'
import {omit, groupBy} from 'lodash'
import RenderField from '../Object/RenderField'
import ObjectValueContainer from '../Object/ObjectContainer'
import Button from 'part:@sanity/components/buttons/default'
import Dialog from 'part:@sanity/components/dialogs/fullscreen'
import ImageTool from '@sanity/imagetool'
import _HotspotImage from '@sanity/imagetool/HotspotImage'
import createImageLoader from './common/createImageLoader'
import {DEFAULT_CROP} from '@sanity/imagetool/constants'
import ImageInputFieldset from 'part:@sanity/components/imageinput/fieldset'

const DEFAULT_HOTSPOT = {
  height: 1,
  width: 1,
  x: 0.5,
  y: 0.5
}

const HotspotImage = createImageLoader(_HotspotImage, image => {
  return {srcAspectRatio: image.width / image.height}
})

const ASPECT_RATIOS = [
  ['Landscape', 16 / 9],
  ['Portrait', 9 / 16],
  ['Square', 1],
  ['Panorama', 4]
]

export default class ImageInput extends React.PureComponent {
  static propTypes = {
    field: PropTypes.shape({
      fields: PropTypes.array
    }),
    value: PropTypes.object,
    onChange: PropTypes.func,
    onEnter: PropTypes.func,
    uploadFn: PropTypes.func.isRequired,
    materializeReferenceFn: PropTypes.func.isRequired,
    level: PropTypes.number,
    validation: PropTypes.object
  }
  static valueContainer = ObjectValueContainer

  state = {
    status: 'ready',
    error: null,
    progress: null,
    uploadingImage: null,
    materializedImage: null,
    isAdvancedEditOpen: false
  }

  subscription = null

  componentDidMount() {
    const {value} = this.props
    const imageReference = value.getAttribute('asset')
    this.materializeImageRef(imageReference)
  }

  componentWillReceiveProps(nextProps) {
    const nextRef = nextProps.value.getAttribute('asset')
    if (this.props.value.getAttribute('asset') !== nextRef) {
      this.cancel()
      this.materializeImageRef(nextRef)
    }
  }

  upload(image) {
    this.cancel()
    this.setState({uploadingImage: image})

    this.subscription = this.props.uploadFn(image).subscribe({
      next: this.handleUploadProgress,
      error: this.handleUploadError
    })
  }

  materializeImageRef(ref) {
    if (ref.isEmpty()) {
      this.setState({materializedImage: null})
      return
    }
    const {materializeReferenceFn} = this.props
    materializeReferenceFn(ref.refId).then(materialized => {
      this.setState({materializedImage: materialized})
    })
  }

  componentWillUnmount() {
    // todo: fix this properly by unsubscribing to upload observable without cancelling it
    this._unmounted = true
  }

  cancel() {
    if (this.subscription) {
      this.subscription.unsubscribe()
    }
  }

  hasField(fieldName) {
    if (this.props.field && this.props.field.fields) {
      return this.props.field.fields.find(field => field.name === fieldName)
    }
    return false
  }

  createSetIfMissingPatch() {
    return {
      type: 'setIfMissing',
      value: {
        _type: this.props.value.context.field.type,
        asset: {_type: 'reference'}
      }
    }
  }

  setStateIfMounted(nextState) {
    if (!this._unmounted) {
      this.setState(nextState)
    }
  }

  handleUploadProgress = event => {
    if (event.type === 'progress' && event.stage === 'upload') {
      this.setStateIfMounted({
        status: 'pending',
        progress: {percent: event.percent}
      })
    }

    if (event.type === 'complete') {
      const {onChange} = this.props
      onChange({
        patch: [
          this.createSetIfMissingPatch(),
          {
            type: 'set',
            path: ['asset'],
            value: {_ref: event.id}
          }
        ]
      })
      this.setStateIfMounted({
        uploadingImage: null,
        status: 'complete'
      })
    }
  }

  handleUploadError = error => {
    this.setState({
      status: 'error',
      error: error
    })
  }

  handleSelect = images => {
    this.upload(images[0])
  }

  handleClearValue = event => {
    event.preventDefault()
    const {onChange} = this.props
    onChange({patch: {type: 'unset'}})
  }

  handleCancel = () => {
    this.cancel()
    this.setState({
      status: 'cancelled',
      error: null,
      progress: null,
      uploadingImage: null
    })
  }

  handleFieldChange = (event, fieldName) => {
    const {onChange} = this.props

    const patch = [
      this.createSetIfMissingPatch(),
      {
        ...event.patch,
        path: [fieldName, ...(event.patch.path || [])]
      }
    ]
    onChange({patch})
  }

  handleFieldEnter = (event, fieldName) => {
    this.props.onEnter(fieldName)
  }

  handleEditBtnClick = event => {
    this.setState({isAdvancedEditOpen: true})
  }

  handleEditDialogClose = event => {
    this.setState({isAdvancedEditOpen: false})
  }

  renderFields(fields) {
    return fields.map(field => this.renderField(field))
  }

  handleImageToolChange = newValue => {
    const {onChange} = this.props
    onChange({
      patch: [
        this.createSetIfMissingPatch(),
        {
          type: 'merge',
          value: {
            crop: newValue.crop,
            hotspot: newValue.hotspot
          }
        }
      ]
    })
  }

  getImageUrl() {
    const {uploadingImage, materializedImage} = this.state
    if (uploadingImage) {
      return uploadingImage.previewUrl
    }
    if (materializedImage && materializedImage.url) {
      return `${materializedImage.url}?w=500`
    }
    return null
  }

  isImageToolEnabled() {
    return this.hasField('hotspot') && this.hasField('crop')
  }

  renderImageTool() {
    const {value} = this.props
    const hotspot = value.getAttribute('hotspot').toJSON() || DEFAULT_HOTSPOT
    const crop = value.getAttribute('crop').toJSON() || DEFAULT_CROP

    const {uploadingImage, materializedImage} = this.state

    const imageUrl = uploadingImage ? uploadingImage.previewUrl : (materializedImage || {}).url
    return (

            <ImageTool value={{hotspot, crop}} src={imageUrl} onChange={this.handleImageToolChange} />

            {ASPECT_RATIOS.map(([title, ratio]) => {
              return (

{title}

                  <HotspotImage hotspot={hotspot} crop={crop} src={imageUrl} aspectRatio={ratio} />

              )
            })}

    )
  }
  renderAdvancedEdit(fields) {
    const grouped = groupBy(fields, field => {
      if (field.name === 'hotspot' || field.name === 'crop') {
        return 'imagetool'
      }
      return 'other'
    })
    return (
      <Dialog title="Edit details" onClose={this.handleEditDialogClose} isOpen>
        {grouped.imagetool && this.renderImageTool()}
        {grouped.other && this.renderFields(grouped.other)}
        <Button onClick={this.handleEditDialogClose}>Close</Button>
      </Dialog>
    )
  }

  renderField(field) {
    const {value, validation, level} = this.props
    const fieldValidation = validation && validation.fields[field.name]

    const fieldValue = value.getAttribute(field.name)

    return (
      <RenderField
        key={field.name}
        fieldName={field.name}
        field={field}
        value={fieldValue}
        onChange={this.handleFieldChange}
        onEnter={this.handleFieldEnter}
        validation={fieldValidation}
        level={level + 1}
      />
    )
  }

  render() {
    const {status, progress, isAdvancedEditOpen} = this.state
    const {field, level, value} = omit(this.props,
      'uploadFn',
      'materializeReferenceFn',
      'onChange',
      'onEnter',
      'validation',
      'focus'
    )
    const fieldGroups = Object.assign({asset: [], highlighted: [], other: []}, groupBy(field.fields, fieldDef => {
      if (fieldDef.name === 'asset') {
        return 'asset'
      }
      if (fieldDef.options && fieldDef.options.isHighlighted) {
        return 'highlighted'
      }
      return 'other'
    }))

    const imageUrl = this.getImageUrl()

    const isImageToolEnabled = this.isImageToolEnabled()

    return (
      <ImageInputFieldset
        status={status}
        legend={field.title}
        level={level}
        percent={progress && progress.percent}
        onSelect={this.handleSelect}
        onCancel={this.handleCancel}
        onClear={this.handleClearValue}
        hotspotImage={{
          hotspot: isImageToolEnabled ? value.getAttribute('hotspot').get() : DEFAULT_HOTSPOT,
          crop: isImageToolEnabled ? value.getAttribute('crop').get() : DEFAULT_CROP,
          imageUrl: imageUrl
        }}
        showContent={fieldGroups.highlighted.length > 0}
      >
        {fieldGroups.highlighted.length > 0 && this.renderFields(fieldGroups.highlighted)}
        {isAdvancedEditOpen && this.renderAdvancedEdit(fieldGroups.highlighted.concat(fieldGroups.other))}
      </ImageInputFieldset>
    )
  }
}
<|endoftext|>


<commit_before>/*
Language: HTML, XML
Category: common
*/

function(hljs) {
  var XML_IDENT_RE = '[A-Za-z0-9\\._:-]+';
  var TAG_INTERNALS = {
    endsWithParent: true,
    illegal: /</,
    relevance: 0,
    contains: [
      {
        className: 'attr',
        begin: XML_IDENT_RE,
        relevance: 0
      },
      {
        begin: /=\s*/,
        relevance: 0,
        contains: [
          {
            className: 'string',
            endsParent: true,
            variants: [
              {begin: /"/, end: /"/},
              {begin: /'/, end: /'/},
              {begin: /[^\s"'=<>`]+/}
            ]
          }
        ]
      }
    ]
  };
  return {
    aliases: ['html', 'xhtml', 'rss', 'atom', 'xjb', 'xsd', 'xsl', 'plist', 'wsf'],
    case_insensitive: true,
    contains: [
      {
        className: 'meta',
        begin: '<!DOCTYPE', end: '>',
        relevance: 10,
        contains: [{begin: '\\[', end: '\\]'}]
      },
      hljs.COMMENT(
        '<!--',
        '-->',
        {
          relevance: 10
        }
      ),
      {
        begin: '<\\!\\[CDATA\\[', end: '\\]\\]>',
        relevance: 10
      },
      {
        className: 'meta',
        begin: /<\?xml/, end: /\?>/, relevance: 10
      },
      {
        begin: /<\?(php)?/, end: /\?>/,
        subLanguage: 'php',
        contains: [
          // We don't want the php closing tag ?> to close the PHP block when
          // inside any of the following blocks:
          {begin: '/\\*', end: '\\*/', skip: true},
          {begin: 'b"', end: '"', skip: true},
          {begin: 'b\'', end: '\'', skip: true},
          hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null, className: null, contains: null, skip: true}),
          hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null, className: null, contains: null, skip: true})
        ]
      },
      {
        className: 'tag',
        /*
        The lookahead pattern (?=...) ensures that 'begin' only matches
        '<style' as a single word, followed by a whitespace or an
        ending braket. The '$' is needed for the lexeme to be recognized
        by hljs.subMode() that tests lexemes outside the stream.
        */
        begin: '<style(?=\\s|>|$)', end: '>',
        keywords: {name: 'style'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '</style>', returnEnd: true,
          subLanguage: ['css', 'xml']
        }
      },
      {
        className: 'tag',
        // See the comment in the <style tag about the lookahead pattern
        begin: '<script(?=\\s|>|$)', end: '>',
        keywords: {name: 'script'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '\<\/script\>', returnEnd: true,
          subLanguage: ['actionscript', 'javascript', 'handlebars', 'xml', 'vbscript']
        }
      },
      {
        className: 'tag',
        begin: '</?', end: '/?>',
        contains: [
          {
            className: 'name', begin: /[^\/><\s]+/, relevance: 0
          },
          TAG_INTERNALS
        ]
      }
    ]
  };
}
<commit_msg>fix(xml): Add svg as alias (#2164)<commit_after>/*
Language: HTML, XML
Category: common
*/

function(hljs) {
  var XML_IDENT_RE = '[A-Za-z0-9\\._:-]+';
  var TAG_INTERNALS = {
    endsWithParent: true,
    illegal: /</,
    relevance: 0,
    contains: [
      {
        className: 'attr',
        begin: XML_IDENT_RE,
        relevance: 0
      },
      {
        begin: /=\s*/,
        relevance: 0,
        contains: [
          {
            className: 'string',
            endsParent: true,
            variants: [
              {begin: /"/, end: /"/},
              {begin: /'/, end: /'/},
              {begin: /[^\s"'=<>`]+/}
            ]
          }
        ]
      }
    ]
  };
  return {
    aliases: ['html', 'xhtml', 'rss', 'atom', 'xjb', 'xsd', 'xsl', 'plist', 'wsf', 'svg'],
    case_insensitive: true,
    contains: [
      {
        className: 'meta',
        begin: '<!DOCTYPE', end: '>',
        relevance: 10,
        contains: [{begin: '\\[', end: '\\]'}]
      },
      hljs.COMMENT(
        '<!--',
        '-->',
        {
          relevance: 10
        }
      ),
      {
        begin: '<\\!\\[CDATA\\[', end: '\\]\\]>',
        relevance: 10
      },
      {
        className: 'meta',
        begin: /<\?xml/, end: /\?>/, relevance: 10
      },
      {
        begin: /<\?(php)?/, end: /\?>/,
        subLanguage: 'php',
        contains: [
          // We don't want the php closing tag ?> to close the PHP block when
          // inside any of the following blocks:
          {begin: '/\\*', end: '\\*/', skip: true},
          {begin: 'b"', end: '"', skip: true},
          {begin: 'b\'', end: '\'', skip: true},
          hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null, className: null, contains: null, skip: true}),
          hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null, className: null, contains: null, skip: true})
        ]
      },
      {
        className: 'tag',
        /*
        The lookahead pattern (?=...) ensures that 'begin' only matches
        '<style' as a single word, followed by a whitespace or an
        ending braket. The '$' is needed for the lexeme to be recognized
        by hljs.subMode() that tests lexemes outside the stream.
        */
        begin: '<style(?=\\s|>|$)', end: '>',
        keywords: {name: 'style'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '</style>', returnEnd: true,
          subLanguage: ['css', 'xml']
        }
      },
      {
        className: 'tag',
        // See the comment in the <style tag about the lookahead pattern
        begin: '<script(?=\\s|>|$)', end: '>',
        keywords: {name: 'script'},
        contains: [TAG_INTERNALS],
        starts: {
          end: '\<\/script\>', returnEnd: true,
          subLanguage: ['actionscript', 'javascript', 'handlebars', 'xml', 'vbscript']
        }
      },
      {
        className: 'tag',
        begin: '</?', end: '/?>',
        contains: [
          {
            className: 'name', begin: /[^\/><\s]+/, relevance: 0
          },
          TAG_INTERNALS
        ]
      }
    ]
  };
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Class constructor for Layout MDL component.
 * Implements MDL component design pattern defined at:
 * https://github.com/jasonmayes/mdl-component-design-pattern
 * @param {HTMLElement} element The element that will be upgraded.
 */
function MaterialLayout(element) {
  'use strict';

  this.element_ = element;

  // Initialize instance.
  this.init();
}

/**
 * Store constants in one place so they can be updated easily.
 * @enum {string | number}
 * @private
 */
MaterialLayout.prototype.Constant_ = {
  MAX_WIDTH: '(max-width: 1024px)',
  TAB_SCROLL_PIXELS: 100,

  MENU_ICON: 'menu',
  CHEVRON_LEFT: 'chevron_left',
  CHEVRON_RIGHT: 'chevron_right'
};

/**
 * Modes.
 * @enum {number}
 * @private
 */
MaterialLayout.prototype.Mode_ = {
  STANDARD: 0,
  SEAMED: 1,
  WATERFALL: 2,
  SCROLL: 3
};

/**
 * Store strings for class names defined by this component that are used in
 * JavaScript. This allows us to simply change it in one place should we
 * decide to modify at a later date.
 * @enum {string}
 * @private
 */
MaterialLayout.prototype.CssClasses_ = {
  CONTAINER: 'mdl-layout__container',
  HEADER: 'mdl-layout__header',
  DRAWER: 'mdl-layout__drawer',
  CONTENT: 'mdl-layout__content',
  DRAWER_BTN: 'mdl-layout__drawer-button',

  ICON: 'material-icons',

  JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
  RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container',
  RIPPLE: 'mdl-ripple',
  RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',

  HEADER_SEAMED: 'mdl-layout__header--seamed',
  HEADER_WATERFALL: 'mdl-layout__header--waterfall',
  HEADER_SCROLL: 'mdl-layout__header--scroll',

  FIXED_HEADER: 'mdl-layout--fixed-header',
  OBFUSCATOR: 'mdl-layout__obfuscator',

  TAB_BAR: 'mdl-layout__tab-bar',
  TAB_CONTAINER: 'mdl-layout__tab-bar-container',
  TAB: 'mdl-layout__tab',
  TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button',
  TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button',
  TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button',
  PANEL: 'mdl-layout__tab-panel',

  HAS_DRAWER: 'has-drawer',
  HAS_TABS: 'has-tabs',
  HAS_SCROLLING_HEADER: 'has-scrolling-header',
  CASTING_SHADOW: 'is-casting-shadow',
  IS_COMPACT: 'is-compact',
  IS_SMALL_SCREEN: 'is-small-screen',
  IS_DRAWER_OPEN: 'is-visible',
  IS_ACTIVE: 'is-active',
  IS_UPGRADED: 'is-upgraded',
  IS_ANIMATING: 'is-animating',

  ON_LARGE_SCREEN : 'mdl-layout--large-screen-only',
  ON_SMALL_SCREEN  : 'mdl-layout--small-screen-only'

};

/**
 * Handles scrolling on the content.
 * @private
 */
MaterialLayout.prototype.contentScrollHandler_ = function() {
  'use strict';

  if (this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)) {
    return;
  }

  if (this.content_.scrollTop > 0 &&
      !this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
    this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
    this.header_.classList.add(this.CssClasses_.IS_COMPACT);
    this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
  } else if (this.content_.scrollTop <= 0 &&
      this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
    this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
    this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
    this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
  }
};

/**
 * Handles changes in screen size.
 * @private
 */
MaterialLayout.prototype.screenSizeHandler_ = function() {
  'use strict';

  if (this.screenSizeMediaQuery_.matches) {
    this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN);
  } else {
    this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN);
    // Collapse drawer (if any) when moving to a large screen size.
    if (this.drawer_) {
      this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
    }
  }
};

/**
 * Handles toggling of the drawer.
 * @param {Element} drawer The drawer container element.
 * @private
 */
MaterialLayout.prototype.drawerToggleHandler_ = function() {
  'use strict';

  this.drawer_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN);
};

/**
 * Handles (un)setting the `is-animating` class
 */
MaterialLayout.prototype.headerTransitionEndHandler = function() {
  'use strict';

  this.header_.classList.remove(this.CssClasses_.IS_ANIMATING);
};

/**
 * Handles expanding the header on click
 */
MaterialLayout.prototype.headerClickHandler = function() {
  'use strict';

  if (this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
    this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
    this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
  }
};

/**
 * Reset tab state, dropping active classes
 * @private
 */
MaterialLayout.prototype.resetTabState_ = function(tabBar) {
  'use strict';

  for (var k = 0; k < tabBar.length; k++) {
    tabBar[k].classList.remove(this.CssClasses_.IS_ACTIVE);
  }
};

/**
 * Reset panel state, droping active classes
 * @private
 */
MaterialLayout.prototype.resetPanelState_ = function(panels) {
  'use strict';

  for (var j = 0; j < panels.length; j++) {
    panels[j].classList.remove(this.CssClasses_.IS_ACTIVE);
  }
};

/**
 * Initialize element.
 */
MaterialLayout.prototype.init = function() {
  'use strict';

  if (this.element_) {
    var container = document.createElement('div');
    container.classList.add(this.CssClasses_.CONTAINER);
    this.element_.parentElement.insertBefore(container, this.element_);
    this.element_.parentElement.removeChild(this.element_);
    container.appendChild(this.element_);

    var directChildren = this.element_.childNodes;
    for (var c = 0; c < directChildren.length; c++) {
      var child = directChildren[c];
      if (child.classList &&
          child.classList.contains(this.CssClasses_.HEADER)) {
        this.header_ = child;
      }

      if (child.classList &&
          child.classList.contains(this.CssClasses_.DRAWER)) {
        this.drawer_ = child;
      }

      if (child.classList &&
          child.classList.contains(this.CssClasses_.CONTENT)) {
        this.content_ = child;
      }
    }

    if (this.header_) {
      this.tabBar_ = this.header_.querySelector('.' + this.CssClasses_.TAB_BAR);
    }

    var mode = this.Mode_.STANDARD;

    // Keep an eye on screen size, and add/remove auxiliary class for styling
    // of small screens.
    this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH);
    this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this));
    this.screenSizeHandler_();

    if (this.header_) {
      if (this.header_.classList.contains(this.CssClasses_.HEADER_SEAMED)) {
        mode = this.Mode_.SEAMED;
      } else if (this.header_.classList.contains(
          this.CssClasses_.HEADER_WATERFALL)) {
        mode = this.Mode_.WATERFALL;
        this.header_.addEventListener('transitionend',
          this.headerTransitionEndHandler.bind(this));
        this.header_.addEventListener('click',
          this.headerClickHandler.bind(this));
      } else if (this.header_.classList.contains(
          this.CssClasses_.HEADER_SCROLL)) {
        mode = this.Mode_.SCROLL;
        container.classList.add(this.CssClasses_.HAS_SCROLLING_HEADER);
      }

      if (mode === this.Mode_.STANDARD) {
        this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
        if (this.tabBar_) {
          this.tabBar_.classList.add(this.CssClasses_.CASTING_SHADOW);
        }
      } else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) {
        this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
        if (this.tabBar_) {
          this.tabBar_.classList.remove(this.CssClasses_.CASTING_SHADOW);
        }
      } else if (mode === this.Mode_.WATERFALL) {
        // Add and remove shadows depending on scroll position.
        // Also add/remove auxiliary class for styling of the compact version of
        // the header.
        this.content_.addEventListener('scroll',
            this.contentScrollHandler_.bind(this));
        this.contentScrollHandler_();
      }
    }

    // Add drawer toggling button to our layout, if we have an openable drawer.
    if (this.drawer_) {
      var drawerButton = document.createElement('div');
      drawerButton.classList.add(this.CssClasses_.DRAWER_BTN);

      if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) {
        //If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well.
        drawerButton.classList.add(this.CssClasses_.ON_LARGE_SCREEN);
      } else if (this.drawer_.classList.contains(this.CssClasses_.ON_SMALL_SCREEN)) {
        //If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well.
        drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN);
      }
      var drawerButtonIcon = document.createElement('i');
      drawerButtonIcon.classList.add(this.CssClasses_.ICON);
      drawerButtonIcon.textContent = this.Constant_.MENU_ICON;
      drawerButton.appendChild(drawerButtonIcon);
      drawerButton.addEventListener('click',
          this.drawerToggleHandler_.bind(this));

      // Add a class if the layout has a drawer, for altering the left padding.
      // Adds the HAS_DRAWER to the elements since this.header_ may or may
      // not be present.
      this.element_.classList.add(this.CssClasses_.HAS_DRAWER);

      // If we have a fixed header, add the button to the header rather than
      // the layout.
      if (this.element_.classList.contains(this.CssClasses_.FIXED_HEADER)) {
        this.header_.insertBefore(drawerButton, this.header_.firstChild);
      } else {
        this.element_.insertBefore(drawerButton, this.content_);
      }

      var obfuscator = document.createElement('div');
      obfuscator.classList.add(this.CssClasses_.OBFUSCATOR);
      this.element_.appendChild(obfuscator);
      obfuscator.addEventListener('click',
          this.drawerToggleHandler_.bind(this));
    }

    // Initialize tabs, if any.
    if (this.header_ && this.tabBar_) {
      this.element_.classList.add(this.CssClasses_.HAS_TABS);

      var tabContainer = document.createElement('div');
      tabContainer.classList.add(this.CssClasses_.TAB_CONTAINER);
      this.header_.insertBefore(tabContainer, this.tabBar_);
      this.header_.removeChild(this.tabBar_);

      var leftButton = document.createElement('div');
      leftButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
      leftButton.classList.add(this.CssClasses_.TAB_BAR_LEFT_BUTTON);
      var leftButtonIcon = document.createElement('i');
      leftButtonIcon.classList.add(this.CssClasses_.ICON);
      leftButtonIcon.textContent = this.Constant_.CHEVRON_LEFT;
      leftButton.appendChild(leftButtonIcon);
      leftButton.addEventListener('click', function() {
        this.tabBar_.scrollLeft -= this.Constant_.TAB_SCROLL_PIXELS;
      }.bind(this));

      var rightButton = document.createElement('div');
      rightButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
      rightButton.classList.add(this.CssClasses_.TAB_BAR_RIGHT_BUTTON);
      var rightButtonIcon = document.createElement('i');
      rightButtonIcon.classList.add(this.CssClasses_.ICON);
      rightButtonIcon.textContent = this.Constant_.CHEVRON_RIGHT;
      rightButton.appendChild(rightButtonIcon);
      rightButton.addEventListener('click', function() {
        this.tabBar_.scrollLeft += this.Constant_.TAB_SCROLL_PIXELS;
      }.bind(this));

      tabContainer.appendChild(leftButton);
      tabContainer.appendChild(this.tabBar_);
      tabContainer.appendChild(rightButton);

      // Add and remove buttons depending on scroll position.
      var tabScrollHandler = function() {
        if (this.tabBar_.scrollLeft > 0) {
          leftButton.classList.add(this.CssClasses_.IS_ACTIVE);
        } else {
          leftButton.classList.remove(this.CssClasses_.IS_ACTIVE);
        }

        if (this.tabBar_.scrollLeft <
            this.tabBar_.scrollWidth - this.tabBar_.offsetWidth) {
          rightButton.classList.add(this.CssClasses_.IS_ACTIVE);
        } else {
          rightButton.classList.remove(this.CssClasses_.IS_ACTIVE);
        }
      }.bind(this);

      this.tabBar_.addEventListener('scroll', tabScrollHandler);
      tabScrollHandler();

      if (this.tabBar_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) {
        this.tabBar_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
      }

      // Select element tabs, document panels
      var tabs = this.tabBar_.querySelectorAll('.' + this.CssClasses_.TAB);
      var panels = this.content_.querySelectorAll('.' + this.CssClasses_.PANEL);

      // Create new tabs for each tab element
      for (var i = 0; i < tabs.length; i++) {
        new MaterialLayoutTab(tabs[i], tabs, panels, this);
      }
    }

    this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
  }
};

function MaterialLayoutTab(tab, tabs, panels, layout) {
  'use strict';

  if (tab) {
    if (layout.tabBar_.classList.contains(
        layout.CssClasses_.JS_RIPPLE_EFFECT)) {
      var rippleContainer = document.createElement('span');
      rippleContainer.classList.add(layout.CssClasses_.RIPPLE_CONTAINER);
      rippleContainer.classList.add(layout.CssClasses_.JS_RIPPLE_EFFECT);
      var ripple = document.createElement('span');
      ripple.classList.add(layout.CssClasses_.RIPPLE);
      rippleContainer.appendChild(ripple);
      tab.appendChild(rippleContainer);
    }

    tab.addEventListener('click', function(e) {
      e.preventDefault();
      var href = tab.href.split('#')[1];
      var panel = layout.content_.querySelector('#' + href);
      layout.resetTabState_(tabs);
      layout.resetPanelState_(panels);
      tab.classList.add(layout.CssClasses_.IS_ACTIVE);
      panel.classList.add(layout.CssClasses_.IS_ACTIVE);
    });

  }
}

// The component registers itself. It can assume componentHandler is available
// in the global scope.
componentHandler.register({
  constructor: MaterialLayout,
  classAsString: 'MaterialLayout',
  cssClass: 'mdl-js-layout'
});
<commit_msg>Catch scrolling when drawer is open (fixes #1076) (Closes #1282)<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Class constructor for Layout MDL component.
 * Implements MDL component design pattern defined at:
 * https://github.com/jasonmayes/mdl-component-design-pattern
 * @param {HTMLElement} element The element that will be upgraded.
 */
function MaterialLayout(element) {
  'use strict';

  this.element_ = element;

  // Initialize instance.
  this.init();
}

/**
 * Store constants in one place so they can be updated easily.
 * @enum {string | number}
 * @private
 */
MaterialLayout.prototype.Constant_ = {
  MAX_WIDTH: '(max-width: 1024px)',
  TAB_SCROLL_PIXELS: 100,

  MENU_ICON: 'menu',
  CHEVRON_LEFT: 'chevron_left',
  CHEVRON_RIGHT: 'chevron_right'
};

/**
 * Modes.
 * @enum {number}
 * @private
 */
MaterialLayout.prototype.Mode_ = {
  STANDARD: 0,
  SEAMED: 1,
  WATERFALL: 2,
  SCROLL: 3
};

/**
 * Store strings for class names defined by this component that are used in
 * JavaScript. This allows us to simply change it in one place should we
 * decide to modify at a later date.
 * @enum {string}
 * @private
 */
MaterialLayout.prototype.CssClasses_ = {
  CONTAINER: 'mdl-layout__container',
  HEADER: 'mdl-layout__header',
  DRAWER: 'mdl-layout__drawer',
  CONTENT: 'mdl-layout__content',
  DRAWER_BTN: 'mdl-layout__drawer-button',

  ICON: 'material-icons',

  JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
  RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container',
  RIPPLE: 'mdl-ripple',
  RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',

  HEADER_SEAMED: 'mdl-layout__header--seamed',
  HEADER_WATERFALL: 'mdl-layout__header--waterfall',
  HEADER_SCROLL: 'mdl-layout__header--scroll',

  FIXED_HEADER: 'mdl-layout--fixed-header',
  OBFUSCATOR: 'mdl-layout__obfuscator',

  TAB_BAR: 'mdl-layout__tab-bar',
  TAB_CONTAINER: 'mdl-layout__tab-bar-container',
  TAB: 'mdl-layout__tab',
  TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button',
  TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button',
  TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button',
  PANEL: 'mdl-layout__tab-panel',

  HAS_DRAWER: 'has-drawer',
  HAS_TABS: 'has-tabs',
  HAS_SCROLLING_HEADER: 'has-scrolling-header',
  CASTING_SHADOW: 'is-casting-shadow',
  IS_COMPACT: 'is-compact',
  IS_SMALL_SCREEN: 'is-small-screen',
  IS_DRAWER_OPEN: 'is-visible',
  IS_ACTIVE: 'is-active',
  IS_UPGRADED: 'is-upgraded',
  IS_ANIMATING: 'is-animating',

  ON_LARGE_SCREEN : 'mdl-layout--large-screen-only',
  ON_SMALL_SCREEN  : 'mdl-layout--small-screen-only'

};

/**
 * Handles scrolling on the content.
 * @private
 */
MaterialLayout.prototype.contentScrollHandler_ = function() {
  'use strict';

  if (this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)) {
    return;
  }

  if (this.content_.scrollTop > 0 &&
      !this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
    this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
    this.header_.classList.add(this.CssClasses_.IS_COMPACT);
    this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
  } else if (this.content_.scrollTop <= 0 &&
      this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
    this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
    this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
    this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
  }
};

/**
 * Handles changes in screen size.
 * @private
 */
MaterialLayout.prototype.screenSizeHandler_ = function() {
  'use strict';

  if (this.screenSizeMediaQuery_.matches) {
    this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN);
  } else {
    this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN);
    // Collapse drawer (if any) when moving to a large screen size.
    if (this.drawer_) {
      this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
    }
  }
};

/**
 * Handles toggling of the drawer.
 * @param {Element} drawer The drawer container element.
 * @private
 */
MaterialLayout.prototype.drawerToggleHandler_ = function() {
  'use strict';

  this.drawer_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN);
};

/**
 * Handles (un)setting the `is-animating` class
 */
MaterialLayout.prototype.headerTransitionEndHandler = function() {
  'use strict';

  this.header_.classList.remove(this.CssClasses_.IS_ANIMATING);
};

/**
 * Handles expanding the header on click
 */
MaterialLayout.prototype.headerClickHandler = function() {
  'use strict';

  if (this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
    this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
    this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
  }
};

/**
 * Reset tab state, dropping active classes
 * @private
 */
MaterialLayout.prototype.resetTabState_ = function(tabBar) {
  'use strict';

  for (var k = 0; k < tabBar.length; k++) {
    tabBar[k].classList.remove(this.CssClasses_.IS_ACTIVE);
  }
};

/**
 * Reset panel state, droping active classes
 * @private
 */
MaterialLayout.prototype.resetPanelState_ = function(panels) {
  'use strict';

  for (var j = 0; j < panels.length; j++) {
    panels[j].classList.remove(this.CssClasses_.IS_ACTIVE);
  }
};

/**
 * Initialize element.
 */
MaterialLayout.prototype.init = function() {
  'use strict';

  if (this.element_) {
    var container = document.createElement('div');
    container.classList.add(this.CssClasses_.CONTAINER);
    this.element_.parentElement.insertBefore(container, this.element_);
    this.element_.parentElement.removeChild(this.element_);
    container.appendChild(this.element_);

    var directChildren = this.element_.childNodes;
    for (var c = 0; c < directChildren.length; c++) {
      var child = directChildren[c];
      if (child.classList &&
          child.classList.contains(this.CssClasses_.HEADER)) {
        this.header_ = child;
      }

      if (child.classList &&
          child.classList.contains(this.CssClasses_.DRAWER)) {
        this.drawer_ = child;
      }

      if (child.classList &&
          child.classList.contains(this.CssClasses_.CONTENT)) {
        this.content_ = child;
      }
    }

    if (this.header_) {
      this.tabBar_ = this.header_.querySelector('.' + this.CssClasses_.TAB_BAR);
    }

    var mode = this.Mode_.STANDARD;

    // Keep an eye on screen size, and add/remove auxiliary class for styling
    // of small screens.
    this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH);
    this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this));
    this.screenSizeHandler_();

    if (this.header_) {
      if (this.header_.classList.contains(this.CssClasses_.HEADER_SEAMED)) {
        mode = this.Mode_.SEAMED;
      } else if (this.header_.classList.contains(
          this.CssClasses_.HEADER_WATERFALL)) {
        mode = this.Mode_.WATERFALL;
        this.header_.addEventListener('transitionend',
          this.headerTransitionEndHandler.bind(this));
        this.header_.addEventListener('click',
          this.headerClickHandler.bind(this));
      } else if (this.header_.classList.contains(
          this.CssClasses_.HEADER_SCROLL)) {
        mode = this.Mode_.SCROLL;
        container.classList.add(this.CssClasses_.HAS_SCROLLING_HEADER);
      }

      if (mode === this.Mode_.STANDARD) {
        this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
        if (this.tabBar_) {
          this.tabBar_.classList.add(this.CssClasses_.CASTING_SHADOW);
        }
      } else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) {
        this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
        if (this.tabBar_) {
          this.tabBar_.classList.remove(this.CssClasses_.CASTING_SHADOW);
        }
      } else if (mode === this.Mode_.WATERFALL) {
        // Add and remove shadows depending on scroll position.
        // Also add/remove auxiliary class for styling of the compact version of
        // the header.
        this.content_.addEventListener('scroll',
            this.contentScrollHandler_.bind(this));
        this.contentScrollHandler_();
      }
    }

    var eatEvent = function(ev) {
      ev.preventDefault();
    };

    // Add drawer toggling button to our layout, if we have an openable drawer.
    if (this.drawer_) {
      var drawerButton = document.createElement('div');
      drawerButton.classList.add(this.CssClasses_.DRAWER_BTN);

      if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) {
        //If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well.
        drawerButton.classList.add(this.CssClasses_.ON_LARGE_SCREEN);
      } else if (this.drawer_.classList.contains(this.CssClasses_.ON_SMALL_SCREEN)) {
        //If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well.
        drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN);
      }
      var drawerButtonIcon = document.createElement('i');
      drawerButtonIcon.classList.add(this.CssClasses_.ICON);
      drawerButtonIcon.textContent = this.Constant_.MENU_ICON;
      drawerButton.appendChild(drawerButtonIcon);
      drawerButton.addEventListener('click',
          this.drawerToggleHandler_.bind(this));

      // Add a class if the layout has a drawer, for altering the left padding.
      // Adds the HAS_DRAWER to the elements since this.header_ may or may
      // not be present.
      this.element_.classList.add(this.CssClasses_.HAS_DRAWER);

      this.drawer_.addEventListener('mousewheel', eatEvent);

      // If we have a fixed header, add the button to the header rather than
      // the layout.
      if (this.element_.classList.contains(this.CssClasses_.FIXED_HEADER)) {
        this.header_.insertBefore(drawerButton, this.header_.firstChild);
      } else {
        this.element_.insertBefore(drawerButton, this.content_);
      }

      var obfuscator = document.createElement('div');
      obfuscator.classList.add(this.CssClasses_.OBFUSCATOR);
      this.element_.appendChild(obfuscator);
      obfuscator.addEventListener('click',
          this.drawerToggleHandler_.bind(this));
      obfuscator.addEventListener('mousewheel', eatEvent);
    }

    // Initialize tabs, if any.
    if (this.header_ && this.tabBar_) {
      this.element_.classList.add(this.CssClasses_.HAS_TABS);

      var tabContainer = document.createElement('div');
      tabContainer.classList.add(this.CssClasses_.TAB_CONTAINER);
      this.header_.insertBefore(tabContainer, this.tabBar_);
      this.header_.removeChild(this.tabBar_);

      var leftButton = document.createElement('div');
      leftButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
      leftButton.classList.add(this.CssClasses_.TAB_BAR_LEFT_BUTTON);
      var leftButtonIcon = document.createElement('i');
      leftButtonIcon.classList.add(this.CssClasses_.ICON);
      leftButtonIcon.textContent = this.Constant_.CHEVRON_LEFT;
      leftButton.appendChild(leftButtonIcon);
      leftButton.addEventListener('click', function() {
        this.tabBar_.scrollLeft -= this.Constant_.TAB_SCROLL_PIXELS;
      }.bind(this));

      var rightButton = document.createElement('div');
      rightButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
      rightButton.classList.add(this.CssClasses_.TAB_BAR_RIGHT_BUTTON);
      var rightButtonIcon = document.createElement('i');
      rightButtonIcon.classList.add(this.CssClasses_.ICON);
      rightButtonIcon.textContent = this.Constant_.CHEVRON_RIGHT;
      rightButton.appendChild(rightButtonIcon);
      rightButton.addEventListener('click', function() {
        this.tabBar_.scrollLeft += this.Constant_.TAB_SCROLL_PIXELS;
      }.bind(this));

      tabContainer.appendChild(leftButton);
      tabContainer.appendChild(this.tabBar_);
      tabContainer.appendChild(rightButton);

      // Add and remove buttons depending on scroll position.
      var tabScrollHandler = function() {
        if (this.tabBar_.scrollLeft > 0) {
          leftButton.classList.add(this.CssClasses_.IS_ACTIVE);
        } else {
          leftButton.classList.remove(this.CssClasses_.IS_ACTIVE);
        }

        if (this.tabBar_.scrollLeft <
            this.tabBar_.scrollWidth - this.tabBar_.offsetWidth) {
          rightButton.classList.add(this.CssClasses_.IS_ACTIVE);
        } else {
          rightButton.classList.remove(this.CssClasses_.IS_ACTIVE);
        }
      }.bind(this);

      this.tabBar_.addEventListener('scroll', tabScrollHandler);
      tabScrollHandler();

      if (this.tabBar_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) {
        this.tabBar_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
      }

      // Select element tabs, document panels
      var tabs = this.tabBar_.querySelectorAll('.' + this.CssClasses_.TAB);
      var panels = this.content_.querySelectorAll('.' + this.CssClasses_.PANEL);

      // Create new tabs for each tab element
      for (var i = 0; i < tabs.length; i++) {
        new MaterialLayoutTab(tabs[i], tabs, panels, this);
      }
    }

    this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
  }
};

function MaterialLayoutTab(tab, tabs, panels, layout) {
  'use strict';

  if (tab) {
    if (layout.tabBar_.classList.contains(
        layout.CssClasses_.JS_RIPPLE_EFFECT)) {
      var rippleContainer = document.createElement('span');
      rippleContainer.classList.add(layout.CssClasses_.RIPPLE_CONTAINER);
      rippleContainer.classList.add(layout.CssClasses_.JS_RIPPLE_EFFECT);
      var ripple = document.createElement('span');
      ripple.classList.add(layout.CssClasses_.RIPPLE);
      rippleContainer.appendChild(ripple);
      tab.appendChild(rippleContainer);
    }

    tab.addEventListener('click', function(e) {
      e.preventDefault();
      var href = tab.href.split('#')[1];
      var panel = layout.content_.querySelector('#' + href);
      layout.resetTabState_(tabs);
      layout.resetPanelState_(panels);
      tab.classList.add(layout.CssClasses_.IS_ACTIVE);
      panel.classList.add(layout.CssClasses_.IS_ACTIVE);
    });

  }
}

// The component registers itself. It can assume componentHandler is available
// in the global scope.
componentHandler.register({
  constructor: MaterialLayout,
  classAsString: 'MaterialLayout',
  cssClass: 'mdl-js-layout'
});
<|endoftext|>


<commit_before>var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}

var instantiate = function (id) {
  var dependencies = defs[id].dependencies;
  var definition = defs[id].definition;
  var instances = [];
  for (var i = 0; i < dependencies.length; ++i)
    instances.push(dem(dependencies[i]));
  defs[id].instance = definition.apply(null, instances);
  if (defs[id] === undefined)
     throw 'required module [' + id + '] is could not be defined (definition function returned undefined)';
};

var def = function (id, dependencies, definition) {
  if (typeof id !== 'string')
    throw 'invalid module definition, module id must be defined and be a string';
  if (dependencies === undefined)
    throw 'invalid module definition, dependencies must be specified';
  if (definition === undefined)
    throw 'invalid module definition, definition function must be specified';
  defs[id] = {
    dependencies: dependencies,
    definition: definition,
    instance: undefined
  };
};

var dem = function (id) {
  if (defs[id] === undefined)
    throw 'required module [' + id + '] is not defined';
  if (defs[id].instance === undefined)
    instantiate(id);
  return defs[id].instance;
};

var req = function (ids, callback) {
  var instances = [];
  for (var i = 0; i < ids.length; ++i)
    instances.push(dem(ids[i]));
  callback.apply(null, callback);
};

var ephox = this.ephox || {};

ephox.bolt = {
  module: {
    api: {
      define: def,
      require: req,
      demand: dem
    }
  }
};
<commit_msg>inline compilation.<commit_after>var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}

var register = function (id) {
  var module = demand(id);
  var fragments = id.split('.');
  var target = Function('return this')();
  for (var i = 0; i < fragments.length - 1; ++i) {
    if (target[fragments[i]] === undefined)
      target[fragments[i]] = {};
    target = target[fragments[i]];
  }
  target[framgents.length - 1] = module;
};

var instantiate = function (id) {
  var dependencies = defs[id].dependencies;
  var definition = defs[id].definition;
  var instances = [];
  for (var i = 0; i < dependencies.length; ++i)
    instances.push(dem(dependencies[i]));
  defs[id].instance = definition.apply(null, instances);
  if (defs[id] === undefined)
     throw 'required module [' + id + '] could not be defined (definition function returned undefined)';
};

var def = function (id, dependencies, definition) {
  if (typeof id !== 'string')
    throw 'invalid module definition, module id must be defined and be a string';
  if (dependencies === undefined)
    throw 'invalid module definition, dependencies must be specified';
  if (definition === undefined)
    throw 'invalid module definition, definition function must be specified';
  defs[id] = {
    dependencies: dependencies,
    definition: definition,
    instance: undefined
  };
};

var dem = function (id) {
  if (defs[id] === undefined)
    throw 'required module [' + id + '] is not defined';
  if (defs[id].instance === undefined)
    instantiate(id);
  return defs[id].instance;
};

var req = function (ids, callback) {
  var instances = [];
  for (var i = 0; i < ids.length; ++i)
    instances.push(dem(ids[i]));
  callback.apply(null, callback);
};

var ephox = this.ephox || {};

ephox.bolt = {
  module: {
    api: {
      define: def,
      require: req,
      demand: dem
    }
  }
};
<|endoftext|>


<commit_before>function Interpreter() {
  var that = Object.create(Interpreter.prototype);

  return that;
}

<commit_msg>Symbol closure instructionMaker functions copied to Interpreter private _symbolParse methods.<commit_after>function Interpreter() {
  var that = Object.create(Interpreter.prototype);

  return that;
}

Interpreter.prototype
._terminalParser = function(codePointer) {
  var lexeme = codePointer.parse(token);
  if(!lexeme) {
    return null;
  }

  var instruction = function() {
    return interpretation.apply(this, lexeme);
  };

  return instruction;
};

Interpreter.prototype
._nonTerminalSequenceParser = function(codePointer) {
  var instructions = [];
  var lastMade = true;

  var makeInstructionIfAllPreviousWasSuccessful = function(symbol) {
    lastMade = lastMade && symbol(codePointer);
    instructions.push(lastMade);
  };

  symbols.map(makeInstructionIfAllPreviousWasSuccessful);

  if(!lastMade) {
    return null;
  }

  var instruction = function() {
    var that = this;
    var lastResult;
    instructions.map(function(instruction) {
      lastResult = instruction.call(that);
    });

    return lastResult;
  };

  return instruction;
};

Interpreter.prototype
._nonTerminalAlternativeParser = function(codePointer) {
  var that = this;
  var backup = codePointer.backup();
  var instruction = alternatives.reduce(function(instruction, alternative) {
    if(!instruction)codePointer.restore(backup);
    return instruction || alternative.call(that, codePointer);
  }, null);

  return instruction;
};

Interpreter.prototype
._nonTerminalAsteriskParser = function(codePointer) {
  var instructions = [];
  var madeInstruction = true;
  while(madeInstruction) {
    var backup = codePointer.backup();
    madeInstruction = symbol(codePointer);
    if(madeInstruction){
      instructions.push(madeInstruction);
    } else {
      codePointer.restore(backup);
    }

  }

  var instruction = function() {
    var lastResult;
    var that = this;
    instructions.map(function(instruction) {
      lastResult = instruction.call(that);
    });

    return lastResult;
  };

  return instruction;
};

<|endoftext|>