<commit_before>function koreBotChat() {
    var bot = require('/KoreBot.js').instance();
    var botMessages = {
        message: "Message...",
        connecting: "Connecting...",
        reconnecting: "Reconnecting..."
    };

    var helpers = {
        'nl2br': function (str) {
            str = str.replace(/(?:\r\n|\r|\n)/g, '
');
            return str;
        },
        'formatAMPM': function (date) {
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var ampm = hours >= 12 ? 'pm' : 'am';
            hours = hours % 12;
            hours = hours ? hours : 12; // the hour '0' should be '12'
            minutes = minutes < 10 ? '0'+minutes : minutes;
            var strTime = hours + ':' + minutes + ' ' + ampm;
            return strTime;
        },
        'formatDate': function (date) {
            var d = new Date(date);
            return d.toDateString() + " at " + helpers.formatAMPM(d);
        }
    };
    function chatWindow(cfg) {
        this.config = {
            "chatTitle": "Kore Bot Chat",
            "container": "body",
            "allowIframe": false
        };
        if (cfg && cfg.chatContainer) {
            delete cfg.chatContainer;
        }
        $.extend(this.config, cfg);
        this.init();
    }

    chatWindow.prototype.init = function () {
        var me = this;
        var _botInfo = $.extend({}, me.config.botOptions);
        _botInfo.botInfo = {chatBot:_botInfo.botInfo.name,taskBotId :_botInfo.botInfo._id};
        var tempTitle = _botInfo.botInfo.chatBot;
        me.config.botMessages = botMessages;

        me.config.chatTitle = me.config.botMessages.connecting;
        var chatWindowHtml = $(me.getChatTemplate()).tmpl(me.config);
        me.config.chatContainer = chatWindowHtml;

        me.config.chatTitle = tempTitle;
        bot.init(_botInfo);
        me.render(chatWindowHtml);
    };

    chatWindow.prototype.destroy = function () {
        var me = this;
        $('.kore-chat-overlay').hide();
        bot.close();
        if (me.config && me.config.chatContainer) {
            me.config.chatContainer.remove();
        }
    };

    chatWindow.prototype.resetWindow = function() {
        var me = this;
        me.config.chatContainer.find('.kore-chat-header .header-title').html( me.config.botMessages.reconnecting);
        me.config.chatContainer.find('.chat-container').html("");
        bot.close();
        bot.init(me.config.botOptions);
    };

    chatWindow.prototype.bindEvents = function () {
        var me = this;
        var _chatContainer = me.config.chatContainer;
        _chatContainer.draggable({
                handle: _chatContainer.find(".kore-chat-header .header-title"),
                containment: "html"
        }).resizable({
                handles: "n, e, w, s",
                containment: "parent"
        });

        _chatContainer.off('keyup', '.chatInputBox').on('keyup', '.chatInputBox', function (event) {
            var _footerContainer = $(me.config.container).find('.kore-chat-footer');
            var _bodyContainer = $(me.config.container).find('.kore-chat-body');
            _bodyContainer.css('bottom', _footerContainer.outerHeight());
        });
        _chatContainer.off('keydown', '.chatInputBox').on('keydown', '.chatInputBox', function (event) {
            var _this = $(this);
            var _footerContainer = $(me.config.container).find('.kore-chat-footer');
            var _bodyContainer = $(me.config.container).find('.kore-chat-body');
            _bodyContainer.css('bottom', _footerContainer.outerHeight());
            if (event.keyCode === 13) {
                event.preventDefault();
                me.sendMessage(_this);
                return;
            }
        });

        _chatContainer.off('click', '.sendChat').on('click', '.sendChat', function (event) {
            var _footerContainer = $(me.config.container).find('.kore-chat-footer');
            me.sendMessage(_footerContainer.find('.chatInputBox'));
        });

        _chatContainer.on('click','li a',function(e){
            e.preventDefault();
            var a_link = $(this).attr('href');
            if(me.config.allowIframe === true){
                me.openPopup(a_link);
            }
            else{
                var _tempWin = window.open(a_link,"_blank");
            }
        });

        _chatContainer.off('click', '.close-btn').on('click', '.close-btn', function (event) {
            me.destroy();
        });

        _chatContainer.off('click', '.minimize-btn').on('click', '.minimize-btn', function (event) {
            if (me.minimized === true) {
                _chatContainer.removeClass("minimize");
                me.minimized = false;
                if(me.expanded === false){
                    _chatContainer.draggable({
                        handle: _chatContainer.find(".kore-chat-header .header-title"),
                        containment: "html"
                    });
                }
            } else
            {
                _chatContainer.addClass("minimize");
                if(me.expanded === false && _chatContainer.hasClass("ui-draggable")) {
                    _chatContainer.draggable("destroy");
                }
                _chatContainer.find('.minimized-title').html("Talk to "+ me.config.chatTitle);
                me.minimized = true;
            }
        });

        _chatContainer.off('click', '.expand-btn').on('click', '.expand-btn', function (event) {
            if($('.kore-chat-overlay').length === 0) {
                $(me.config.container).append('

');
            }
            if (me.expanded === true) {
                $('.kore-chat-overlay').hide();
                $(this).attr('title',"Expand");
                _chatContainer.removeClass("expanded");
                me.expanded = false;
                _chatContainer.draggable({
                    handle: _chatContainer.find(".kore-chat-header .header-title"),
                    containment: "html"
                }).resizable({
                        handles: "n, e, w, s",
                        containment: "parent"
                });
            } else {
                $('.kore-chat-overlay').show();
                $(this).attr('title',"Collapse");
                _chatContainer.addClass("expanded");
                _chatContainer.draggable("destroy").resizable("destroy");
                me.expanded = true;
            }
            var container_pos_left = _chatContainer.position().left + _chatContainer.width();
            if(container_pos_left > $(window).width()){
                _chatContainer.css('left',_chatContainer.position().left - (container_pos_left - $(window).width() + 10)  + "px" );
            }
        });
        $('body').on('click','.kore-chat-overlay, .kore-chat-window .minimize-btn',function(){
            if(me.expanded === true){
                $('.kore-chat-window .expand-btn').trigger('click');
            }
        });

        _chatContainer.off('click', '.minimized').on('click', '.minimized,.minimized-title', function (event) {
            _chatContainer.removeClass("minimize");
            me.minimized = false;
            _chatContainer.draggable({
                handle: _chatContainer.find(".kore-chat-header .header-title"),
                containment: "html"
            });
        });

        _chatContainer.off('click', '.reload-btn').on('click', '.reload-btn',function(event){
            $(this).addClass("disabled").prop('disabled',true);
            me.resetWindow();
        });
        bot.on("open", function (response) {
            var _chatInput = _chatContainer.find('.kore-chat-footer .chatInputBox');
            _chatContainer.find('.kore-chat-header .header-title').html(me.config.chatTitle).attr('title',me.config.chatTitle);
            _chatContainer.find('.kore-chat-header .disabled').prop('disabled',false).removeClass("disabled");
            _chatInput.focus();
        });

        bot.on("message", function (message) {
            if(me.popupOpened === true){
                $('.kore-auth-popup .close-popup').trigger("click");
            }
            var tempData = JSON.parse(message.data);

            if (tempData.from === "bot" && tempData.type === "bot_response")
            {
                me.renderMessage(tempData);
            }
            else if(tempData.from === "self" && tempData.type === "user_message"){
                var tempmsg = tempData.message;

                var msgData = {
                    'type': "currentUser",
                    "message": [{
                        'type': 'text',
                        'cInfo': {'body':tempmsg.body},
                        'clientMessageId': tempData.id
                    }],
                    "createdOn": tempData.id
                };
                me.renderMessage(msgData);
            }
        });
    };

    chatWindow.prototype.bindIframeEvents = function(authPopup){
        var me = this;
        authPopup.on('click','.close-popup',function(){
           $(this).closest('.kore-auth-popup').remove();
           $('.kore-auth-layover').remove();
           me.popupOpened = false;
        });

        var ifram = authPopup.find('iframe')[0];

        ifram.addEventListener('onload',function(){
            console.log(this);
        },true);
    };

    chatWindow.prototype.render = function (chatWindowHtml) {
        var me = this;
        $(me.config.container).append(chatWindowHtml);

        if (me.config.container !== "body") {
            $(me.config.container).addClass('pos-relative');
            $(me.config.chatContainer).addClass('pos-absolute');
        }

        me.bindEvents();
    };

    chatWindow.prototype.sendMessage = function (chatInput) {
        var me = this;
        if (chatInput.text().trim() === "") {
            return;
        }
        var _bodyContainer = $(me.config.chatContainer).find('.kore-chat-body');
        var _footerContainer = $(me.config.chatContainer).find('.kore-chat-footer');
        var clientMessageId = new Date().getTime();

        var msgData = {
            'type': "currentUser",
            "message": [{
                'type': 'text',
                'cInfo': {'body':chatInput.text()},
                'clientMessageId': clientMessageId
            }],
            "createdOn": clientMessageId
        };

        var messageToBot = {};
        messageToBot["clientMessageId"] = clientMessageId;
        messageToBot["message"] = {body: chatInput.text(), attachments: []};
        messageToBot["resourceid"] = '/bot.message';

        bot.sendMessage(messageToBot, function messageSent() {

        });
        chatInput.html("");
        _bodyContainer.css('bottom', _footerContainer.outerHeight());

        me.renderMessage(msgData);
    };

    chatWindow.prototype.renderMessage = function (msgData) {
        var me = this;
        var _chatContainer = $(me.config.chatContainer).find('.chat-container');

        var messageHtml = $(me.getChatTemplate("message")).tmpl({
            'msgData': msgData,
            'helpers':helpers
        });

        _chatContainer.append(messageHtml);

        //me.formatMessages(messageHtml);
        _chatContainer.animate({
            scrollTop: _chatContainer.prop("scrollHeight")
        }, 0);
    };

    chatWindow.prototype.formatMessages = function (msgContainer){
    /*adding target to a tags */
        $(msgContainer).find('a').attr('target','_blank');
    };

    chatWindow.prototype.openPopup = function(link_url){
        var me = this;
        var popupHtml = $(me.getChatTemplate("popup")).tmpl({
            "link_url":link_url
        });
        $(me.config.container).append(popupHtml);
        me.popupOpened = true;
        me.bindIframeEvents($(popupHtml));
    };

    chatWindow.prototype.getChatTemplate = function (tempType) {
        var chatFooterTemplate =
                '
 \

 \

Press enter to send
 \

';

        var chatWindowTemplate = '';

        var msgTemplate = ' ';
        if (tempType === "message") {
            return msgTemplate;
        } else if(tempType === "popup"){
            return popupTemplate;
        } else {
            return chatWindowTemplate;
        }
    };

    var chatInitialize;

    window.onbeforeunload = function(){
        if (chatInitialize && $(chatInitialize.config.chatContainer).length > 0) {
            chatInitialize.destroy();
            return null;
        }
    }

    this.show = function (cfg) {
        if ($('body').find('.kore-chat-window').length > 0)
        {
            return false;
        }
		delete chatInitialize;
        chatInitialize = new chatWindow(cfg);
        return this;
    };
    this.destroy = function () {
        if (chatInitialize && chatInitialize.destroy) {
            chatInitialize.destroy();
        }
    };
    return {
        show: show,
        destroy: destroy
    };
}<commit_msg>sdk changes<commit_after>function koreBotChat() {
    var bot = require('/KoreBot.js').instance();
    var botMessages = {
        message: "Message...",
        connecting: "Connecting...",
        reconnecting: "Reconnecting..."
    };

    var helpers = {
        'nl2br': function (str) {
            str = str.replace(/(?:\r\n|\r|\n)/g, '
');
            return str;
        },
        'formatAMPM': function (date) {
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var ampm = hours >= 12 ? 'pm' : 'am';
            hours = hours % 12;
            hours = hours ? hours : 12; // the hour '0' should be '12'
            minutes = minutes < 10 ? '0'+minutes : minutes;
            var strTime = hours + ':' + minutes + ' ' + ampm;
            return strTime;
        },
        'formatDate': function (date) {
            var d = new Date(date);
            return d.toDateString() + " at " + helpers.formatAMPM(d);
        }
    };
    function chatWindow(cfg) {
        this.config = {
            "chatTitle": "Kore Bot Chat",
            "container": "body",
            "allowIframe": false
        };
        if (cfg && cfg.chatContainer) {
            delete cfg.chatContainer;
        }
        this.config = $.extend(this.config, cfg);
        this.init();
    }

    chatWindow.prototype.init = function () {
        var me = this;
        var _botInfo = $.extend({}, me.config.botOptions);
        _botInfo.botInfo = {chatBot:_botInfo.botInfo.name,taskBotId :_botInfo.botInfo._id};
        var tempTitle = _botInfo.botInfo.chatBot;
        me.config.botMessages = botMessages;

        me.config.chatTitle = me.config.botMessages.connecting;
        var chatWindowHtml = $(me.getChatTemplate()).tmpl(me.config);
        me.config.chatContainer = chatWindowHtml;

        me.config.chatTitle = tempTitle;
        bot.init(_botInfo);
        me.render(chatWindowHtml);
    };

    chatWindow.prototype.destroy = function () {
        var me = this;
        $('.kore-chat-overlay').hide();
        bot.close();
        if (me.config && me.config.chatContainer) {
            me.config.chatContainer.remove();
        }
    };

    chatWindow.prototype.resetWindow = function() {
        var me = this;
        me.config.chatContainer.find('.kore-chat-header .header-title').html( me.config.botMessages.reconnecting);
        me.config.chatContainer.find('.chat-container').html("");
        bot.close();
        bot.init(me.config.botOptions);
    };

    chatWindow.prototype.bindEvents = function () {
        var me = this;
        var _chatContainer = me.config.chatContainer;
        _chatContainer.draggable({
                handle: _chatContainer.find(".kore-chat-header .header-title"),
                containment: "html"
        }).resizable({
                handles: "n, e, w, s",
                containment: "parent"
        });

        _chatContainer.off('keyup', '.chatInputBox').on('keyup', '.chatInputBox', function (event) {
            var _footerContainer = $(me.config.container).find('.kore-chat-footer');
            var _bodyContainer = $(me.config.container).find('.kore-chat-body');
            _bodyContainer.css('bottom', _footerContainer.outerHeight());
        });
        _chatContainer.off('keydown', '.chatInputBox').on('keydown', '.chatInputBox', function (event) {
            var _this = $(this);
            var _footerContainer = $(me.config.container).find('.kore-chat-footer');
            var _bodyContainer = $(me.config.container).find('.kore-chat-body');
            _bodyContainer.css('bottom', _footerContainer.outerHeight());
            if (event.keyCode === 13) {
                event.preventDefault();
                me.sendMessage(_this);
                return;
            }
        });

        _chatContainer.off('click', '.sendChat').on('click', '.sendChat', function (event) {
            var _footerContainer = $(me.config.container).find('.kore-chat-footer');
            me.sendMessage(_footerContainer.find('.chatInputBox'));
        });

        _chatContainer.on('click','li a',function(e){
            e.preventDefault();
            var a_link = $(this).attr('href');
            if(me.config.allowIframe === true){
                me.openPopup(a_link);
            }
            else{
                var _tempWin = window.open(a_link,"_blank");
            }
        });

        _chatContainer.off('click', '.close-btn').on('click', '.close-btn', function (event) {
            me.destroy();
        });

        _chatContainer.off('click', '.minimize-btn').on('click', '.minimize-btn', function (event) {
            if (me.minimized === true) {
                _chatContainer.removeClass("minimize");
                me.minimized = false;
                if(me.expanded === false){
                    _chatContainer.draggable({
                        handle: _chatContainer.find(".kore-chat-header .header-title"),
                        containment: "html"
                    });
                }
            } else
            {
                _chatContainer.addClass("minimize");
                if(me.expanded === false && _chatContainer.hasClass("ui-draggable")) {
                    _chatContainer.draggable("destroy");
                }
                _chatContainer.find('.minimized-title').html("Talk to "+ me.config.chatTitle);
                me.minimized = true;
            }
        });

        _chatContainer.off('click', '.expand-btn').on('click', '.expand-btn', function (event) {
            if($('.kore-chat-overlay').length === 0) {
                $(me.config.container).append('

');
            }
            if (me.expanded === true) {
                $('.kore-chat-overlay').hide();
                $(this).attr('title',"Expand");
                _chatContainer.removeClass("expanded");
                me.expanded = false;
                _chatContainer.draggable({
                    handle: _chatContainer.find(".kore-chat-header .header-title"),
                    containment: "html"
                }).resizable({
                        handles: "n, e, w, s",
                        containment: "parent"
                });
            } else {
                $('.kore-chat-overlay').show();
                $(this).attr('title',"Collapse");
                _chatContainer.addClass("expanded");
                _chatContainer.draggable("destroy").resizable("destroy");
                me.expanded = true;
            }
            var container_pos_left = _chatContainer.position().left + _chatContainer.width();
            if(container_pos_left > $(window).width()){
                _chatContainer.css('left',_chatContainer.position().left - (container_pos_left - $(window).width() + 10)  + "px" );
            }
        });
        $('body').on('click','.kore-chat-overlay, .kore-chat-window .minimize-btn',function(){
            if(me.expanded === true){
                $('.kore-chat-window .expand-btn').trigger('click');
            }
        });

        _chatContainer.off('click', '.minimized').on('click', '.minimized,.minimized-title', function (event) {
            _chatContainer.removeClass("minimize");
            me.minimized = false;
            _chatContainer.draggable({
                handle: _chatContainer.find(".kore-chat-header .header-title"),
                containment: "html"
            });
        });

        _chatContainer.off('click', '.reload-btn').on('click', '.reload-btn',function(event){
            $(this).addClass("disabled").prop('disabled',true);
            me.resetWindow();
        });
        bot.on("open", function (response) {
            var _chatInput = _chatContainer.find('.kore-chat-footer .chatInputBox');
            _chatContainer.find('.kore-chat-header .header-title').html(me.config.chatTitle).attr('title',me.config.chatTitle);
            _chatContainer.find('.kore-chat-header .disabled').prop('disabled',false).removeClass("disabled");
            _chatInput.focus();
        });

        bot.on("message", function (message) {
            if(me.popupOpened === true){
                $('.kore-auth-popup .close-popup').trigger("click");
            }
            var tempData = JSON.parse(message.data);

            if (tempData.from === "bot" && tempData.type === "bot_response")
            {
                me.renderMessage(tempData);
            }
            else if(tempData.from === "self" && tempData.type === "user_message"){
                var tempmsg = tempData.message;

                var msgData = {
                    'type': "currentUser",
                    "message": [{
                        'type': 'text',
                        'cInfo': {'body':tempmsg.body},
                        'clientMessageId': tempData.id
                    }],
                    "createdOn": tempData.id
                };
                me.renderMessage(msgData);
            }
        });
    };

    chatWindow.prototype.bindIframeEvents = function(authPopup){
        var me = this;
        authPopup.on('click','.close-popup',function(){
           $(this).closest('.kore-auth-popup').remove();
           $('.kore-auth-layover').remove();
           me.popupOpened = false;
        });

        var ifram = authPopup.find('iframe')[0];

        ifram.addEventListener('onload',function(){
            console.log(this);
        },true);
    };

    chatWindow.prototype.render = function (chatWindowHtml) {
        var me = this;
        $(me.config.container).append(chatWindowHtml);

        if (me.config.container !== "body") {
            $(me.config.container).addClass('pos-relative');
            $(me.config.chatContainer).addClass('pos-absolute');
        }

        me.bindEvents();
    };

    chatWindow.prototype.sendMessage = function (chatInput) {
        var me = this;
        if (chatInput.text().trim() === "") {
            return;
        }
        var _bodyContainer = $(me.config.chatContainer).find('.kore-chat-body');
        var _footerContainer = $(me.config.chatContainer).find('.kore-chat-footer');
        var clientMessageId = new Date().getTime();

        var msgData = {
            'type': "currentUser",
            "message": [{
                'type': 'text',
                'cInfo': {'body':chatInput.text()},
                'clientMessageId': clientMessageId
            }],
            "createdOn": clientMessageId
        };

        var messageToBot = {};
        messageToBot["clientMessageId"] = clientMessageId;
        messageToBot["message"] = {body: chatInput.text(), attachments: []};
        messageToBot["resourceid"] = '/bot.message';

        bot.sendMessage(messageToBot, function messageSent() {

        });
        chatInput.html("");
        _bodyContainer.css('bottom', _footerContainer.outerHeight());

        me.renderMessage(msgData);
    };

    chatWindow.prototype.renderMessage = function (msgData) {
        var me = this;
        var _chatContainer = $(me.config.chatContainer).find('.chat-container');

        var messageHtml = $(me.getChatTemplate("message")).tmpl({
            'msgData': msgData,
            'helpers':helpers
        });

        _chatContainer.append(messageHtml);

        //me.formatMessages(messageHtml);
        _chatContainer.animate({
            scrollTop: _chatContainer.prop("scrollHeight")
        }, 0);
    };

    chatWindow.prototype.formatMessages = function (msgContainer){
    /*adding target to a tags */
        $(msgContainer).find('a').attr('target','_blank');
    };

    chatWindow.prototype.openPopup = function(link_url){
        var me = this;
        var popupHtml = $(me.getChatTemplate("popup")).tmpl({
            "link_url":link_url
        });
        $(me.config.container).append(popupHtml);
        me.popupOpened = true;
        me.bindIframeEvents($(popupHtml));
    };

    chatWindow.prototype.getChatTemplate = function (tempType) {
        var chatFooterTemplate =
                '
 \

 \

Press enter to send
 \

';

        var chatWindowTemplate = '';

        var msgTemplate = ' ';
        if (tempType === "message") {
            return msgTemplate;
        } else if(tempType === "popup"){
            return popupTemplate;
        } else {
            return chatWindowTemplate;
        }
    };

    var chatInitialize;

    window.onbeforeunload = function(){
        if (chatInitialize && $(chatInitialize.config.chatContainer).length > 0) {
            chatInitialize.destroy();
            return null;
        }
    }

    this.show = function (cfg) {
        if ($('body').find('.kore-chat-window').length > 0)
        {
            return false;
        }
		delete chatInitialize;
        chatInitialize = new chatWindow(cfg);
        return this;
    };
    this.destroy = function () {
        if (chatInitialize && chatInitialize.destroy) {
            chatInitialize.destroy();
        }
    };
    return {
        show: show,
        destroy: destroy
    };
}<|endoftext|>


<commit_before>define([
  'dojo/_base/declare',
  'dojo/_base/lang',
  'dojo/_base/array',
  'dijit/_WidgetBase',
  'dijit/_TemplatedMixin',
  'dojo/text!./templates/Urireferencer.html',
  './controllers/UriController',
  'dojo/dom-construct',
  'dojo/dom-class',
  'dojo/on',
  'dojo/query',
  'dojo/NodeList-traverse'
], function (
  declare,
  lang,
  array,
  WidgetBase,
  TemplatedMixin,
  template,
  UriController,
  domConstruct,
  domClass,
  on,
  query
) {
  return declare([WidgetBase, TemplatedMixin], {

    templateString: template,
    uriUrl: null,
    controller: null,
    ssoToken: null,
    checkUri: null,
    totalCount: 0,

    postCreate: function () {
      this.inherited(arguments);
      this.controller = new UriController({
        uriUrl: this.uriUrl,
        ssoToken: this.ssoToken
      })
    },

    startup: function () {
      this.controller.checkUri(this.checkUri).then(lang.hitch(this, function(data) {
        this.referenceCount.innerHTML = data.count;
        array.forEach(data.applications, lang.hitch(this, function(app) {
          this._createExpanderElement(app);
        }));
        this.referenceLoadingMessage.style.display = 'none';
        this.expanderControls.style.display = 'inline-block';
      }))
    },

    checkUri: function(uri) {
      this.referenceLoadingMessage.style.display = 'none';
      this.expanderControls.style.display = 'none';

      domConstruct.empty(this.expanderContainer);

      this.controller.checkUri(uri).then(lang.hitch(this, function(data) {
        this.referenceCount.innerHTML = data.count;
        array.forEach(data.applications, lang.hitch(this, function(app) {
          this._createExpanderElement(app);
        }));
        this.referenceLoadingMessage.style.display = 'none';
        this.expanderControls.style.display = 'inline-block';
      }))
    },

    _createExpanderElement: function(app) {
      var exp = domConstruct.create('div', { 'class': 'expander' }, this.expanderContainer);
      var header = domConstruct.create('div', { 'class': 'expander-header' }, exp);
      var content = domConstruct.create('div', { 'class': 'expander-content' }, exp);

      domConstruct.create('div', { 'class': 'expander-icon' }, header);

      var title = '' + app.title + ' (' +
        (app.count ? app.count : (app.success ? '0' : 'fout bij controleren')) + ' referenties)';

      domConstruct.create('h5', { innerHTML: title }, header);

      var ul = domConstruct.create('ul', { 'class': 'nodisk', style: 'padding-left: 20px;' }, content);

      if (app.success && app.has_references) {
        array.forEach(app.items, lang.hitch(this, function(item) {
          domConstruct.create('li', { innerHTML: ' ' + item.title + ''}, ul);
        }));
      } else {
        if (!app.success) {
          domConstruct.create('li', { innerHTML: 'Er ging iets mis bij het controleren van de referenties.'}, ul);
        } else {
          domConstruct.create('li', { innerHTML: 'Er zijn geen referenties gevonden.'}, ul);
        }
      }

      on(header, 'click', lang.hitch(this, function(evt) {
        this._toggleExpander(evt);
      }));
    },

    _toggleExpander: function(evt) {
      evt ? evt.preventDefault() : null;
      var expander = evt.target.closest('.expander');
      var container = expander.closest('.expander-container');

      // Close other expanded elements // Excluded here because of showAll/closeAll
      //query(container).children('.expander').forEach(function(child) {
      //  if (child != expander) {
      //    if (domClass.contains(child, 'expander-expanded')){
      //      domClass.remove(child, 'expander-expanded');
      //    }
      //  }
      //});

      // Toggle this element
      if (domClass.contains(expander, 'expander-expanded')) {
        domClass.remove(expander, 'expander-expanded');
      } else {
        domClass.add(expander, 'expander-expanded');
      }
    },

    _openAll: function(evt) {
      evt ? evt.preventDefault() : null;
      query(this.expanderContainer).children('.expander').forEach(function(child) {
        domClass.add(child, 'expander-expanded');
      });
    },

    _closeAll: function(evt) {
      evt ? evt.preventDefault() : null;
      query(this.expanderContainer).children('.expander').forEach(function(child) {
        domClass.remove(child, 'expander-expanded');
      });
    }
  });
});
<commit_msg>fix voor refresh<commit_after>define([
  'dojo/_base/declare',
  'dojo/_base/lang',
  'dojo/_base/array',
  'dijit/_WidgetBase',
  'dijit/_TemplatedMixin',
  'dojo/text!./templates/Urireferencer.html',
  './controllers/UriController',
  'dojo/dom-construct',
  'dojo/dom-class',
  'dojo/on',
  'dojo/query',
  'dojo/NodeList-traverse'
], function (
  declare,
  lang,
  array,
  WidgetBase,
  TemplatedMixin,
  template,
  UriController,
  domConstruct,
  domClass,
  on,
  query
) {
  return declare([WidgetBase, TemplatedMixin], {

    templateString: template,
    uriUrl: null,
    controller: null,
    ssoToken: null,
    checkUri: null,
    totalCount: 0,

    postCreate: function () {
      this.inherited(arguments);
      this.controller = new UriController({
        uriUrl: this.uriUrl,
        ssoToken: this.ssoToken
      })
    },

    startup: function () {
      this.controller.checkUri(this.checkUri).then(lang.hitch(this, function(data) {
        this.referenceCount.innerHTML = data.count;
        array.forEach(data.applications, lang.hitch(this, function(app) {
          this._createExpanderElement(app);
        }));
        this.referenceLoadingMessage.style.display = 'none';
        this.expanderControls.style.display = 'inline-block';
      }))
    },

    recheckUri: function(uri) {
      this.referenceLoadingMessage.style.display = 'none';
      this.expanderControls.style.display = 'none';

      domConstruct.empty(this.expanderContainer);

      this.controller.checkUri(uri).then(lang.hitch(this, function(data) {
        this.referenceCount.innerHTML = data.count;
        array.forEach(data.applications, lang.hitch(this, function(app) {
          this._createExpanderElement(app);
        }));
        this.referenceLoadingMessage.style.display = 'none';
        this.expanderControls.style.display = 'inline-block';
      }))
    },

    _createExpanderElement: function(app) {
      var exp = domConstruct.create('div', { 'class': 'expander' }, this.expanderContainer);
      var header = domConstruct.create('div', { 'class': 'expander-header' }, exp);
      var content = domConstruct.create('div', { 'class': 'expander-content' }, exp);

      domConstruct.create('div', { 'class': 'expander-icon' }, header);

      var title = '' + app.title + ' (' +
        (app.count ? app.count : (app.success ? '0' : 'fout bij controleren')) + ' referenties)';

      domConstruct.create('h5', { innerHTML: title }, header);

      var ul = domConstruct.create('ul', { 'class': 'nodisk', style: 'padding-left: 20px;' }, content);

      if (app.success && app.has_references) {
        array.forEach(app.items, lang.hitch(this, function(item) {
          domConstruct.create('li', { innerHTML: ' ' + item.title + ''}, ul);
        }));
      } else {
        if (!app.success) {
          domConstruct.create('li', { innerHTML: 'Er ging iets mis bij het controleren van de referenties.'}, ul);
        } else {
          domConstruct.create('li', { innerHTML: 'Er zijn geen referenties gevonden.'}, ul);
        }
      }

      on(header, 'click', lang.hitch(this, function(evt) {
        this._toggleExpander(evt);
      }));
    },

    _toggleExpander: function(evt) {
      evt ? evt.preventDefault() : null;
      var expander = evt.target.closest('.expander');
      var container = expander.closest('.expander-container');

      // Close other expanded elements // Excluded here because of showAll/closeAll
      //query(container).children('.expander').forEach(function(child) {
      //  if (child != expander) {
      //    if (domClass.contains(child, 'expander-expanded')){
      //      domClass.remove(child, 'expander-expanded');
      //    }
      //  }
      //});

      // Toggle this element
      if (domClass.contains(expander, 'expander-expanded')) {
        domClass.remove(expander, 'expander-expanded');
      } else {
        domClass.add(expander, 'expander-expanded');
      }
    },

    _openAll: function(evt) {
      evt ? evt.preventDefault() : null;
      query(this.expanderContainer).children('.expander').forEach(function(child) {
        domClass.add(child, 'expander-expanded');
      });
    },

    _closeAll: function(evt) {
      evt ? evt.preventDefault() : null;
      query(this.expanderContainer).children('.expander').forEach(function(child) {
        domClass.remove(child, 'expander-expanded');
      });
    }
  });
});
<|endoftext|>


<commit_before>const Util = require('./util');
const _ = require('lodash');
const path = require('path');

module.exports = class BackendUtil {

    constructor(vm) {
        this.util = new Util(vm);
    }

    createCrud(entity, config) {
        config = config || {};
        config.dest = config.dest || 'backend/src/main/java/' + config.package.lower.replace(/\./g, '/') + '/' + config.project.lower + '/';
        const fromPath = 'backend/src/main/java/app/';

        const template = Object.assign(entity, {
            project: config.project,
            package: config.package
        });

        const files = [
            'entity/_pojo.java',
            'bc/_pojoBC.java',
            'dao/_pojoDAO.java',
            'service/_pojoREST.java',
        ];

        files.map((file) => {
            let from = path.join(fromPath, file);
            let to = path.join(config.dest, _.replace(file, /_pojo/g, template.name.capital));

            this.util.copyTpl(from, to, template);
        });
    }

    createFromEntity(entity, config) {
        config = config || {};
        config.dest = config.dest || 'backend/src/main/java/' + config.package.replace(/\./g, '/').toLowerCase() + '/' + config.project.toLowerCase() + '/';
        const fromPath = 'backend/src/main/java/app/';
        const template = Object.assign(entity, {
            project: config.project,
            package: config.package
        });
        const files = [
            'bc/_pojoBC.java',
            'dao/_pojoDAO.java',
            'service/_pojoREST.java',
        ];

        files.map((file) => {
            let from = path.join(fromPath, file);
            let to = path.join(config.dest, _.replace(file, /_pojo/g, template.name.capital));

            this.util.copyTpl(from, to, template);
        });
    }
};
<commit_msg>Adiciona entity em persistence.xml<commit_after>const Util = require('./util');
const _ = require('lodash');
const path = require('path');
const cheerio = require('cheerio');

module.exports = class BackendUtil {

    constructor(vm) {
        this.util = new Util(vm);
        this.vm = vm;
        this.fs = vm.fs;
    }

    createCrud(entity, config) {
        config = config || {};
        config.dest = config.dest || 'backend/src/main/java/' + config.package.lower.replace(/\./g, '/') + '/' + config.project.lower + '/';
        const fromPath = 'backend/src/main/java/app/';

        const template = Object.assign(entity, {
            project: config.project,
            package: config.package
        });

        const files = [
            'entity/_pojo.java',
            'bc/_pojoBC.java',
            'dao/_pojoDAO.java',
            'service/_pojoREST.java',
        ];

        files.map((file) => {
            let from = path.join(fromPath, file);
            let to = path.join(config.dest, _.replace(file, /_pojo/g, template.name.capital));

            this.util.copyTpl(from, to, template);
        });

        // Adicionar imports no app.module.ts
        this._addEntityToPersistenceXml(template);
    }

    createFromEntity(entity, config) {
        config = config || {};
        config.dest = config.dest || 'backend/src/main/java/' + config.package.replace(/\./g, '/').toLowerCase() + '/' + config.project.toLowerCase() + '/';
        const fromPath = 'backend/src/main/java/app/';
        const template = Object.assign(entity, {
            project: config.project,
            package: config.package
        });
        const files = [
            'bc/_pojoBC.java',
            'dao/_pojoDAO.java',
            'service/_pojoREST.java',
        ];

        files.map((file) => {
            let from = path.join(fromPath, file);
            let to = path.join(config.dest, _.replace(file, /_pojo/g, template.name.capital));

            this.util.copyTpl(from, to, template);
        });

        // Adicionar imports no app.module.ts
        this._addEntityToPersistenceXml(template);
    }

    _addEntityToPersistenceXml(template) {
        var templatePath = this.vm.destinationPath('backend/src/main/resources/META-INF/persistence.xml');
        this.fs.copy(templatePath, templatePath, {
            process: function (content) {
                let puName = template.project.lower + 'PU';
                let xml = cheerio.load(content.toString(), {
                    xmlMode: true
                });
                let node = xml('persistence-unit[name='+ puName +']');
                if (node.length < 1) { // if not found the app PU, get the first one
                    node = xml('persistence-unit');
                }

                let lastClassNode = xml(node).find('class').last();
                lastClassNode.after('\n\t<class>' + template.package.lower + '.' + template.project.lower + '.entity.' + template.name.capital + '</class>');

                return xml.html();
            }
        });
        this.fs.commit(function () { });
    }
};
<|endoftext|>


<commit_before>$(document).ready(function() {
  // nav
  // nav clase
  $(".nav a").on("click", function(){
   $(".nav").find(".active").removeClass("active");
   $(this).parent().addClass("active");
});
  // new
  $('.navbar-collapse a').click(function (e) {
        $('.navbar-collapse').collapse('toggle');
      });
  // end new
    $('nav').affix({
      offset: {
        top: function() { return  $('#imagen-inicial').height(); }
      }
     });

  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html, body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });

  /*

  // Animación
  var $window           = $(window),
      win_height_padded = $window.height() * 1.1,
      isTouch           = Modernizr.touch;

  if (isTouch) { $('.revealOnScroll').addClass('animated'); }

  $window.on('scroll', revealOnScroll);

  function revealOnScroll() {
    var scrolled = $window.scrollTop(),
        win_height_padded = $window.height() * 1.1;

    // Showed...
    $(".revealOnScroll:not(.animated)").each(function () {
      var $this     = $(this),
          offsetTop = $this.offset().top;

      if (scrolled + win_height_padded > offsetTop) {
        if ($this.data('timeout')) {
          window.setTimeout(function(){
            $this.addClass('animated ' + $this.data('animation'));
          }, parseInt($this.data('timeout'),10));
        } else {
          $this.addClass('animated ' + $this.data('animation'));
        }
      }
    });
    // Hidden...
   $(".revealOnScroll.animated").each(function (index) {
      var $this     = $(this),
          offsetTop = $this.offset().top;
      if (scrolled + win_height_padded < offsetTop) {
        $(this).removeClass('animated fadeInUp flipInX lightSpeedIn')
      }
    });
  }

  revealOnScroll();

  */
});
<commit_msg>Update script.js<commit_after>$(document).ready(function() {
  // nav
  // nav clase
  $(".nav a").on("click", function(){
   $(".nav").find(".active").removeClass("active");
   $(this).parent().addClass("active");
});
  // new
 /* $('.navbar-collapse a').click(function (e) {
        $('.navbar-collapse').collapse('toggle');
      });*/
  // end new
    $('nav').affix({
      offset: {
        top: function() { return  $('#imagen-inicial').height(); }
      }
     });

  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html, body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });

  // Animación
  var $window           = $(window),
      win_height_padded = $window.height() * 1.1,
      isTouch           = Modernizr.touch;

  if (isTouch) { $('.revealOnScroll').addClass('animated'); }

  $window.on('scroll', revealOnScroll);

  function revealOnScroll() {
    var scrolled = $window.scrollTop(),
        win_height_padded = $window.height() * 1.1;

    // Showed...
    $(".revealOnScroll:not(.animated)").each(function () {
      var $this     = $(this),
          offsetTop = $this.offset().top;

      if (scrolled + win_height_padded > offsetTop) {
        if ($this.data('timeout')) {
          window.setTimeout(function(){
            $this.addClass('animated ' + $this.data('animation'));
          }, parseInt($this.data('timeout'),10));
        } else {
          $this.addClass('animated ' + $this.data('animation'));
        }
      }
    });
    // Hidden...
   $(".revealOnScroll.animated").each(function (index) {
      var $this     = $(this),
          offsetTop = $this.offset().top;
      if (scrolled + win_height_padded < offsetTop) {
        $(this).removeClass('animated fadeInUp flipInX lightSpeedIn')
      }
    });
  }

  revealOnScroll();

});
<|endoftext|>


<commit_before>var Alloy = require('alloy'),
	_ = Alloy._,
	Backbone = Alloy.Backbone;

var WM = module.exports = {
	navWindows: [],

	/**
	 * Open given Window in a new Ti.UI.iOS.NavigationWindow on iOS and return it. Do nothing on other platforms
	 *
	 * @param {Ti.UI.Window} win Window to open in NavigationWindow
	 *
	 * @return {Ti.UI.iOS.NavigationWindow} Created NavigationWindow
	 */
	createNewNavWindow: function(win) {
		if (OS_IOS) {
			var navWindow = Ti.UI.iOS.createNavigationWindow({
				backgroundColor: '#fff',

				window: win
			});
			navWindow.id = 'navWindow_' + _.uniqueId();

			WM.navWindows.push(navWindow);

			// Store reference in the root Window to the NavigationWindow
			win.navWin = navWindow;

			return navWindow;
		} else
			return win;
	},

	/**
	 * Open given Window in a the last created Ti.UI.iOS.NavigationWindow on iOS. Just open the Window on other platforms
	 *
	 * @param {Ti.UI.Window} win Window to open in NavigationWindow
	 */
	openWinInActiveNavWindow: function(win) {
		if (OS_IOS) {
			if (!WM.navWindows.length)
				WM.createNewNavWindow(win).open();
			else
				_.last(WM.navWindows).openWindow(win);
		} else
			win.open();
	},

	/**
	 * Open the given Window.
	 *
	 * @param {Ti.UI.Window} win Window to open
	 */
	openWin: function(win) {
		if (win.createStack) {
			addWinToStack(win.createStack, win);
		} else if (win.addToStack) {
			addWinToStack(win.addToStack, win);
		}

		if (OS_IOS) {
			// Sometimes we accidentally set modal and navGroup to true.
			// In that case 'modal' should be preferred, because modal windows are always opened in a new NavWindow
			if (win.navGroup && win.modalWin)
				win.navGroup = false;

			// Show SideMenu button and replace current centerWindow with this new Window
			if (win.showSideMenu) {
				// Show sideMenu button
				var sideMenuButton = Alloy.createWidget('rebel.MenuBarButton', {
					buttonType: 'hamburger'
				});
				win.leftNavButton = sideMenuButton.getView();
				sideMenuButton.on('click', WM.toggleLeftNavDrawer);

				// Create SideMenu if not yet created.
				// Else replace current centerWindow with this Window
				setupNavDrawer({
					centerWin: WM.createNewNavWindow(win)
				});
			}
			// If window should be Modal Window
			// Also add it to a new navigationGroup
			else if (win.modalWin) {
				var navWin = WM.createNewNavWindow(win);
				navWin.open({
					modal: true
				});
			}
			// If window should be part of NavigationGroup
			else if (win.navGroup) {
				WM.openWinInActiveNavWindow(win);
			}
			// Else, just open the Window
			else
				win.open();
		} else if (OS_ANDROID) {
			if (win.showSideMenu) {
				// Create SideMenu if not yet created.
				setupNavDrawer({
					centerWin: win
				});

				win.addEventListener('open', onOpenTopWindow);
			} else
				win.addEventListener('open', onOpenSubWindow);

			win.open();
		} else
			win.open();
	},

	/**
	 * Close the given Window

	 * @param {Ti.UI.Window} win Window to close
	 */
	closeWin: function(win) {
		if (OS_IOS) {
			// If Window is a NavigationWindow, clean up root Window as well
			if (win.window) {
				win.window.fireEvent('close');

				if (win.window.leftNavButton)
					win.window.leftNavButton.removeEventListener('click', WM.toggleLeftNavDrawer);

				win.window = null;

				WM.navWindows.pop();
			}

			// If Window is a root Window of a NavigationWindow, close the NavigationWindow instead
			if (win.navWin) {
				var navWin = win.navWin;
				win.navWin = null;

				WM.closeWin(navWin);
			} else
				win.close();
		} else
			win.close();
	},

	/**
	 * Open or Close the left-side Navigation Drawer (if exists)
	 */
	toggleLeftNavDrawer: function() {
		if (_navDrawer)
			_navDrawer.toggleLeftWindow();
	},

	/**
	 * Close the Stack of Windows with given name
	 *
	 * @param {String} name Name of Stack to close
	 */
	killStack: function(name) {
		if (_windowStacks[name])
			_.each(_windowStacks[name], function(win) {
				WM.closeWin(win);
			});
	}

};

/**
 * @property {Object} _windowStacks Dictionary of stacks of Windows. Each element contains an array of one or more windows
 */
_windowStacks = {};

/**
 * Add given Window to stack with given name
 * @private
 *
 * @param {String} name Stack to add given Window to
 * @param {Ti.UI.Window} win Window to add
 */
function addWinToStack(name, win) {
	if (!_windowStacks[name])
		_windowStacks[name] = [];

	_windowStacks[name].push(win);
}

if (OS_ANDROID) {

	/**
	 * On Android: Handle open event of Sub window. It adds the Android backbutton and closes it on click
	 * @private
	 *
	 * @param {Object} evt Event details
	 */
	function onOpenSubWindow(evt) {
		var win = this;

		if (this.activity) {
			//Setup the ActionBar for 1> level windows
			var actionBar = this.activity.actionBar;
			if (actionBar && !this.navBarHidden) {
				actionBar.displayHomeAsUp = true;
				actionBar.icon = '/images/generic/logoTransparentSmall.png';
				actionBar.onHomeIconItemSelected = function() {
					win.close();
				};
			}

			this.activity.onPrepareOptionsMenu = createOptionsMenu;

			this.activity.invalidateOptionsMenu();
		}
	}

	/**
	 * On Android: Handle open event of Top window. It opens the NavigationDrawer
	 * @private
	 *
	 * @param {Object} evt Event details
	 */
	function onOpenTopWindow(evt) {
		if (this.activity) {
			//Setup ActionBar for level 1 windows
			var actionBar = this.activity.actionBar;
			if (actionBar && !this.navBarHidden) {
				actionBar.displayHomeAsUp = false;
				actionBar.icon = '/images/generic/hamburger.png';

				actionBar.onHomeIconItemSelected = function() {
					if (_navDrawerAndroid) {
						_navDrawerAndroid.toggleDrawer();
					}
				};
			}

			// Close app when clicking back button
			this.addEventListener('androidback', onBackButtonClick);

			this.activity.onPrepareOptionsMenu = createOptionsMenu;

			this.activity.invalidateOptionsMenu();
		}
	}

	function onBackButtonClick(evt) {
		this.removeEventListener('androidback', onBackButtonClick);

		// Go back to home
		// Ti.Android.currentActivity.finish();
		var intent = Ti.Android.createIntent({
			action: Ti.Android.ACTION_MAIN
		});
		intent.addCategory(Ti.Android.CATEGORY_HOME);
		Ti.Android.currentActivity.startActivity(intent);
	}

	function createOptionsMenu(evt) {
		var menu = evt.menu,
			menuItem;

		// Settings
		// if (F.load('Acl').isLoggedin() && !menu.findItem(998)) {
		// 	menuItem = menu.add({
		// 		itemId: 998,
		// 		title: L('menuSettings'),
		// 		showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER,
		// 		order: 998
		// 	});
		// 	menuItem.addEventListener('click', onOpenSettings);
		// }

		// Feedback
		// if (!menu.findItem(998)) {
		// 	menuItem = menu.add({
		// 		itemId: 998,
		// 		title: L('menuSettings'),
		// 		showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER,
		// 		order: 998
		// 	});
		// 	menuItem.addEventListener('click', onOpenSettings);
		// }

		// Help
		if (!menu.findItem(999)) {
			menuItem = menu.add({
				itemId: 999,
				title: L('Help'),
				showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER,
				order: 999
			});
			menuItem.addEventListener('click', onOpenHelp);
		}

		// this.invalidateOptionsMenu();
	}

	function onOpenSettings() {
		Alloy.createController('Settings');
	}

	function onOpenHelp() {
		var Acl = require('Acl'),
			emailDialog = Ti.UI.createEmailDialog();

		emailDialog.subject = "I could use some help!";
		emailDialog.toRecipients = [Alloy.CFG.supportEmail];

		var message = "\n\r\n\r\n\r --- \n\r";

		if (Acl.isLoggedin()) {
			var user = Acl.getLoggedinUser();

			message = message + 'User: ' + user.get('name') + ' (' + user.id + ')' + "\n\r";
		}

		message = message + 'Version: ' + Ti.App.getVersion() + "\n\r" +
			'Phone model: ' + Ti.Platform.model + "\n\r" +
			'OS: ' + Ti.Platform.osname + ' ' + Ti.Platform.version + "\n\r" +
			'';

		emailDialog.messageBody = message;
		emailDialog.open();
	}
}
/**
 * @property {Ti.UI.Window} _navDrawer The Navigation Drawer window
 * @private
 */
_navDrawer = null;

if (OS_ANDROID)
	_centerWin = null;

/**
 * Setup Navigation Drawer module
 * @private
 *
 * @param {Object} config Configuration for module
 */
function setupNavDrawer(config) {
	// Setup NavDrawer module on iOS
	if (OS_IOS) {
		if (!_navDrawer) {
			_navDrawer = require('RebelFrame/SideMenu/' + Alloy.CFG.sideMenuType);
			_navDrawer.setup(config);

			_navDrawer.on('open', onNavBarOpen);
			_navDrawer.on('close', onNavBarClose);
		} else {
			// Replace current centerWindow with new centerWindow
			_navDrawer.setCenterWindow(config.centerWin);
		}
	} else if (OS_ANDROID) {
		if (!_navDrawer) {
			// Make reference to new centerWindow, so we can close later
			_centerWin = config.centerWin;

			// Create NavigationDrawer for Android
			_navDrawer = Alloy.createWidget('c.SideMenu');
			_navDrawer.attach(config.centerWin);
			_navDrawer.on('navigate', function(evt) {
				// Open new win
				// Close old win
			});
		} else {
			_navDrawer.attach(config.centerWin);

			// Close old centerWindow
			WM.closeWin(_centerWin);

			// Make reference to new centerWindow, so we can close later
			_centerWin = config.centerWin;
		}
	}
}

function onNavBarOpen(evt) {
	WM.trigger('navbaropen', evt);
}

function onNavBarClose(evt) {
	WM.trigger('navbarclose', evt);
}<commit_msg>Add support for tabGroups<commit_after>var Alloy = require('alloy'),
	_ = Alloy._,
	Backbone = Alloy.Backbone;

var WM = module.exports = {
	navWindows: [],

	/**
	 * Open given Window in a new Ti.UI.iOS.NavigationWindow on iOS and return it. Do nothing on other platforms
	 *
	 * @param {Ti.UI.Window} win Window to open in NavigationWindow
	 *
	 * @return {Ti.UI.iOS.NavigationWindow} Created NavigationWindow
	 */
	createNewNavWindow: function(win) {
		if (OS_IOS) {
			var navWindow = Ti.UI.iOS.createNavigationWindow({
				backgroundColor: '#fff',

				window: win
			});
			navWindow.id = 'navWindow_' + _.uniqueId();

			WM.navWindows.push(navWindow);

			// Store reference in the root Window to the NavigationWindow
			win.navWin = navWindow;

			return navWindow;
		} else
			return win;
	},

	/**
	 * Open given Window in a the last created Ti.UI.iOS.NavigationWindow on iOS. Just open the Window on other platforms
	 *
	 * @param {Ti.UI.Window} win Window to open in NavigationWindow
	 */
	openWinInActiveNavWindow: function(win) {
		if (OS_IOS) {
			if (!WM.navWindows.length) {
				if(Alloy.Globals.tabGroup)
					Alloy.Globals.tabGroup.activeTab.open(win);
				else
					WM.createNewNavWindow(win).open();
			}
			else
				_.last(WM.navWindows).openWindow(win);
		} else
			win.open();
	},

	/**
	 * Open the given Window.
	 *
	 * @param {Ti.UI.Window} win Window to open
	 */
	openWin: function(win) {
		if (win.createStack) {
			addWinToStack(win.createStack, win);
		} else if (win.addToStack) {
			addWinToStack(win.addToStack, win);
		}

		if (OS_IOS) {
			// Sometimes we accidentally set modal and navGroup to true.
			// In that case 'modal' should be preferred, because modal windows are always opened in a new NavWindow
			if (win.navGroup && win.modalWin)
				win.navGroup = false;

			// Show SideMenu button and replace current centerWindow with this new Window
			if (win.showSideMenu) {
				// Show sideMenu button
				var sideMenuButton = Alloy.createWidget('rebel.MenuBarButton', {
					buttonType: 'hamburger'
				});
				win.leftNavButton = sideMenuButton.getView();
				sideMenuButton.on('click', WM.toggleLeftNavDrawer);

				// Create SideMenu if not yet created.
				// Else replace current centerWindow with this Window
				setupNavDrawer({
					centerWin: WM.createNewNavWindow(win)
				});
			}
			// If window should be Modal Window
			// Also add it to a new navigationGroup
			else if (win.modalWin) {
				var navWin = WM.createNewNavWindow(win);
				navWin.open({
					modal: true
				});
			}
			// If window should be part of NavigationGroup
			else if (win.navGroup) {
				WM.openWinInActiveNavWindow(win);
			}
			// Else, just open the Window
			else
				win.open();
		} else if (OS_ANDROID) {
			if (win.showSideMenu) {
				// Create SideMenu if not yet created.
				setupNavDrawer({
					centerWin: win
				});

				win.addEventListener('open', onOpenTopWindow);
			} else
				win.addEventListener('open', onOpenSubWindow);

			win.open();
		} else
			win.open();
	},

	/**
	 * Close the given Window

	 * @param {Ti.UI.Window} win Window to close
	 */
	closeWin: function(win) {
		if (OS_IOS) {
			// If Window is a NavigationWindow, clean up root Window as well
			if (win.window) {
				win.window.fireEvent('close');

				if (win.window.leftNavButton)
					win.window.leftNavButton.removeEventListener('click', WM.toggleLeftNavDrawer);

				win.window = null;

				WM.navWindows.pop();
			}

			// If Window is a root Window of a NavigationWindow, close the NavigationWindow instead
			if (win.navWin) {
				var navWin = win.navWin;
				win.navWin = null;

				WM.closeWin(navWin);
			} else
				win.close();
		} else
			win.close();
	},

	/**
	 * Open or Close the left-side Navigation Drawer (if exists)
	 */
	toggleLeftNavDrawer: function() {
		if (_navDrawer)
			_navDrawer.toggleLeftWindow();
	},

	/**
	 * Close the Stack of Windows with given name
	 *
	 * @param {String} name Name of Stack to close
	 */
	killStack: function(name) {
		if (_windowStacks[name])
			_.each(_windowStacks[name], function(win) {
				WM.closeWin(win);
			});
	}

};

/**
 * @property {Object} _windowStacks Dictionary of stacks of Windows. Each element contains an array of one or more windows
 */
_windowStacks = {};

/**
 * Add given Window to stack with given name
 * @private
 *
 * @param {String} name Stack to add given Window to
 * @param {Ti.UI.Window} win Window to add
 */
function addWinToStack(name, win) {
	if (!_windowStacks[name])
		_windowStacks[name] = [];

	_windowStacks[name].push(win);
}

if (OS_ANDROID) {

	/**
	 * On Android: Handle open event of Sub window. It adds the Android backbutton and closes it on click
	 * @private
	 *
	 * @param {Object} evt Event details
	 */
	function onOpenSubWindow(evt) {
		var win = this;

		if (this.activity) {
			//Setup the ActionBar for 1> level windows
			var actionBar = this.activity.actionBar;
			if (actionBar && !this.navBarHidden) {
				actionBar.displayHomeAsUp = true;
				actionBar.icon = '/images/generic/logoTransparentSmall.png';
				actionBar.onHomeIconItemSelected = function() {
					win.close();
				};
			}

			this.activity.onPrepareOptionsMenu = createOptionsMenu;

			this.activity.invalidateOptionsMenu();
		}
	}

	/**
	 * On Android: Handle open event of Top window. It opens the NavigationDrawer
	 * @private
	 *
	 * @param {Object} evt Event details
	 */
	function onOpenTopWindow(evt) {
		if (this.activity) {
			//Setup ActionBar for level 1 windows
			var actionBar = this.activity.actionBar;
			if (actionBar && !this.navBarHidden) {
				actionBar.displayHomeAsUp = false;
				actionBar.icon = '/images/generic/hamburger.png';

				actionBar.onHomeIconItemSelected = function() {
					if (_navDrawerAndroid) {
						_navDrawerAndroid.toggleDrawer();
					}
				};
			}

			// Close app when clicking back button
			this.addEventListener('androidback', onBackButtonClick);

			this.activity.onPrepareOptionsMenu = createOptionsMenu;

			this.activity.invalidateOptionsMenu();
		}
	}

	function onBackButtonClick(evt) {
		this.removeEventListener('androidback', onBackButtonClick);

		// Go back to home
		// Ti.Android.currentActivity.finish();
		var intent = Ti.Android.createIntent({
			action: Ti.Android.ACTION_MAIN
		});
		intent.addCategory(Ti.Android.CATEGORY_HOME);
		Ti.Android.currentActivity.startActivity(intent);
	}

	function createOptionsMenu(evt) {
		var menu = evt.menu,
			menuItem;

		// Settings
		// if (F.load('Acl').isLoggedin() && !menu.findItem(998)) {
		// 	menuItem = menu.add({
		// 		itemId: 998,
		// 		title: L('menuSettings'),
		// 		showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER,
		// 		order: 998
		// 	});
		// 	menuItem.addEventListener('click', onOpenSettings);
		// }

		// Feedback
		// if (!menu.findItem(998)) {
		// 	menuItem = menu.add({
		// 		itemId: 998,
		// 		title: L('menuSettings'),
		// 		showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER,
		// 		order: 998
		// 	});
		// 	menuItem.addEventListener('click', onOpenSettings);
		// }

		// Help
		if (!menu.findItem(999)) {
			menuItem = menu.add({
				itemId: 999,
				title: L('Help'),
				showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER,
				order: 999
			});
			menuItem.addEventListener('click', onOpenHelp);
		}

		// this.invalidateOptionsMenu();
	}

	function onOpenSettings() {
		Alloy.createController('Settings');
	}

	function onOpenHelp() {
		var Acl = require('Acl'),
			emailDialog = Ti.UI.createEmailDialog();

		emailDialog.subject = "I could use some help!";
		emailDialog.toRecipients = [Alloy.CFG.supportEmail];

		var message = "\n\r\n\r\n\r --- \n\r";

		if (Acl.isLoggedin()) {
			var user = Acl.getLoggedinUser();

			message = message + 'User: ' + user.get('name') + ' (' + user.id + ')' + "\n\r";
		}

		message = message + 'Version: ' + Ti.App.getVersion() + "\n\r" +
			'Phone model: ' + Ti.Platform.model + "\n\r" +
			'OS: ' + Ti.Platform.osname + ' ' + Ti.Platform.version + "\n\r" +
			'';

		emailDialog.messageBody = message;
		emailDialog.open();
	}
}
/**
 * @property {Ti.UI.Window} _navDrawer The Navigation Drawer window
 * @private
 */
_navDrawer = null;

if (OS_ANDROID)
	_centerWin = null;

/**
 * Setup Navigation Drawer module
 * @private
 *
 * @param {Object} config Configuration for module
 */
function setupNavDrawer(config) {
	// Setup NavDrawer module on iOS
	if (OS_IOS) {
		if (!_navDrawer) {
			_navDrawer = require('RebelFrame/SideMenu/' + Alloy.CFG.sideMenuType);
			_navDrawer.setup(config);

			_navDrawer.on('open', onNavBarOpen);
			_navDrawer.on('close', onNavBarClose);
		} else {
			// Replace current centerWindow with new centerWindow
			_navDrawer.setCenterWindow(config.centerWin);
		}
	} else if (OS_ANDROID) {
		if (!_navDrawer) {
			// Make reference to new centerWindow, so we can close later
			_centerWin = config.centerWin;

			// Create NavigationDrawer for Android
			_navDrawer = Alloy.createWidget('c.SideMenu');
			_navDrawer.attach(config.centerWin);
			_navDrawer.on('navigate', function(evt) {
				// Open new win
				// Close old win
			});
		} else {
			_navDrawer.attach(config.centerWin);

			// Close old centerWindow
			WM.closeWin(_centerWin);

			// Make reference to new centerWindow, so we can close later
			_centerWin = config.centerWin;
		}
	}
}

function onNavBarOpen(evt) {
	WM.trigger('navbaropen', evt);
}

function onNavBarClose(evt) {
	WM.trigger('navbarclose', evt);
}
<|endoftext|>


<commit_before>define([
	"dojo/_base/kernel",
	"dojo/_base/lang",
	"dojo/on",
	"dojo/aspect",
	"dojo/has",
	"./Grid",
	"put-selector/put",
	"dojo/_base/sniff"
], function(kernel, lang, on, aspect, has, Grid, put){

var activeCell, activeValue; // tracks cell currently being edited, and its value

function updateInputValue(input, value){
	// common code for updating value of a standard input
	input.value = value;
	if(input.type == "radio" || input.type == "checkbox"){
		input.checked = !!value;
	}
}

function dataFromValue(value, oldValue){
	// Default logic for translating values from editors;
	// tries to preserve type if possible.
	if(typeof oldValue == "number"){
		value = isNaN(value) ? value : parseFloat(value);
	}else if(typeof oldValue == "boolean"){
		value = value == "true" ? true : value == "false" ? false : value;
	}else if(oldValue instanceof Date){
		var asDate = new Date(value);
		value = isNaN(asDate.getTime()) ? value : asDate;
	}
	return value;
}

// intermediary frontend to dataFromValue for HTML and widget editors
function dataFromEditor(column, cmp){
	if(typeof cmp.get == "function"){ // widget
		return dataFromValue(cmp.get("value"));
	}else{ // HTML input
		return dataFromValue(
			cmp[cmp.type == "checkbox" || cmp.type == "radio"  ? "checked" : "value"]);
	}
}

function setProperty(grid, cellElement, oldValue, value){
	// Updates dirty hash and fires dgrid-datachange event for a changed value.
	var cell, row, column;
	if(oldValue.valueOf() != value.valueOf()){
		cell = grid.cell(cellElement);
		row = cell.row;
		column = cell.column;
		if(column.field && row){
			// TODO: remove rowId in lieu of cell (or grid.row/grid.cell)
			// (keeping for the moment for back-compat, but will note in changes)
			if(on.emit(cellElement, "dgrid-datachange", {
						grid: this,
						cell: cell,
						rowId: row.id,
						oldValue: oldValue,
						value: value,
						bubbles: true,
						cancelable: true
					})){
				if (grid.updateDirty){
					// for OnDemandGrid: update dirty data, and save if autoSave is true
					grid.updateDirty(row.id, column.field, value);
					// perform auto-save (if applicable) in next tick to avoid
					// unintentional mishaps due to order of handler execution
					column.autoSave && setTimeout(function(){ grid._trackError("save"); }, 0);
				}
			}else{
				// else keep the value the same
				return oldValue;
			}
		}
	}
	return value;
}

// intermediary frontend to setProperty for HTML and widget editors
function setPropertyFromEditor(grid, column, cmp) {
	var value;
	if(!cmp.isValid || cmp.isValid()){
		value = setProperty(grid, (cmp.domNode || cmp).parentNode,
			activeCell ? activeValue : cmp._dgridLastValue,
			dataFromEditor(column, cmp));

		if(activeCell){ // for editors with editOn defined
			activeValue = value;
		}else{ // for always-on editors, update _dgridLastValue immediately
			cmp._dgridLastValue = value;
		}
	}
}

// editor creation/hookup/placement logic

function createEditor(column){
	// Creates an editor instance based on column definition properties,
	// and hooks up events.
	var editor = column.editor,
		editOn = column.editOn,
		grid = column.grid,
		isWidget = typeof editor != "string", // string == standard HTML input
		args, cmp, node, putstr, handleChange;

	args = column.editorArgs || {};
	if(typeof args == "function"){ args = args.call(grid, column); }

	if(isWidget){
		cmp = new editor(args);
		node = cmp.focusNode || cmp.domNode;

		// Add dgrid-input to className to make consistent with HTML inputs.
		// (Can't do this using className argument to constructor; causes issues)
		node.className += " dgrid-input";

		// For editOn editors, connect to onBlur rather than onChange, since
		// the latter is delayed by setTimeouts in Dijit and will fire too late.
		cmp.connect(cmp, editOn ? "onBlur" : "onChange", function(){
			if(!cmp._dgridIgnoreChange){
				setPropertyFromEditor(grid, column, this);
			}
		});
	}else{
		handleChange = function(evt){
			var target = evt.target;
			if("_dgridLastValue" in target && target.className.indexOf("dgrid-input") > -1){
				setPropertyFromEditor(grid, column, target);
			}
		};

		// considerations for standard HTML form elements
		if(!column.grid._hasInputListener){
			// register one listener at the top level that receives events delegated
			grid._hasInputListener = true;
			grid.on("change", function(evt){ handleChange(evt); });
			// also register a focus listener
		}

		putstr = editor == "textarea" ? "textarea" :
			"input[type=" + editor + "]";
		cmp = node = put(putstr + ".dgrid-input", lang.mixin({
			name: column.field,
			tabIndex: isNaN(column.tabIndex) ? -1 : column.tabIndex
		}, args));

		if(has("ie") < 9 || (has("ie") && has("quirks"))){
			// IE<9 / quirks doesn't fire change events for all the right things,
			// and it doesn't bubble.
			if(editor == "radio" || editor == "checkbox"){
				// listen for clicks since IE doesn't fire change events properly for checks/radios
				on(cmp, "click", function(evt){ handleChange(evt); });
			}else{
				on(cmp, "change", function(evt){ handleChange(evt); });
			}
		}
	}

	// XXX: stop mousedown propagation to prevent confusing Keyboard mixin logic
	// with certain widgets; perhaps revising KB's `handledEvent` would be better.
	on(node, "mousedown", function(evt){ evt.stopPropagation(); });

	return cmp;
}

function createSharedEditor(column, originalRenderCell){
	// Creates an editor instance with additional considerations for
	// shared usage across an entire column (for columns with editOn specified).

	var cmp = createEditor(column),
		isWidget = cmp.domNode,
		node = cmp.domNode || cmp,
		focusNode = cmp.focusNode || node,
		reset = isWidget ?
			function(){ cmp.set("value", cmp._dgridLastValue); } :
			function(){
				updateInputValue(cmp, cmp._dgridLastValue);
				// call setProperty again in case we need to revert a previous change
				setPropertyFromEditor(column.grid, column, cmp);
			},
		keyHandle;

	function onblur(){
		var parentNode = node.parentNode,
			renderedNode;

		// remove the editor from the cell
		parentNode.removeChild(node);

		// pass new value to original renderCell implementation for this cell
		Grid.appendIfNode(parentNode, originalRenderCell(
			column.grid.row(parentNode).data, activeValue, parentNode));

		// reset state now that editor is deactivated
		activeCell = activeValue = null;
		column._editorBlurHandle.pause();
	}

	function dismissOnKey(evt){
		// Contains logic for reacting to enter/escape keypresses to save/cancel edits.
		// Returns boolean specifying whether this key event should dismiss the field.
		var key = evt.keyCode || evt.which;

		if(key == 27){ // escape: revert + dismiss
			reset();
			activeValue = cmp._dgridLastValue;
			focusNode.blur();
		}else if(key == 13 && column.dismissOnEnter !== false){ // enter: dismiss
			// FIXME: Opera is "reverting" even in this case
			focusNode.blur();
		}
	}

	// hook up enter/esc key handling
	keyHandle = on(focusNode, "keydown", dismissOnKey);

	// hook up blur handler, but don't activate until widget is activated
	(column._editorBlurHandle = on.pausable(cmp, "blur", onblur)).pause();

	return cmp;
}

function showEditor(cmp, column, cell, value){
	// Places a shared editor into the newly-active cell in the column.
	// Also called when rendering an editor in an "always-on" editor column.

	var grid = column.grid,
		editor = column.editor,
		isWidget = cmp.domNode;

	// for regular inputs, we can update the value before even showing it
	if(!isWidget){ updateInputValue(cmp, value); }

	cell.innerHTML = "";
	put(cell, cmp.domNode || cmp);

	if(isWidget){
		// For widgets, ensure startup is called before setting value,
		// to maximize compatibility with flaky widgets like dijit/form/Select.
		if (!cmp._started){ cmp.startup(); }

		// Set value, but ensure it isn't processed as a user-generated change.
		// (Clear flag on a timeout to wait for delayed onChange to fire first)
		cmp._dgridIgnoreChange = true;
		cmp.set("value", value);
		setTimeout(function(){ cmp._dgridIgnoreChange = false; }, 0);
	}
	// track previous value for short-circuiting or in case we need to revert
	cmp._dgridLastValue = value;
	// if this is an editor with editOn, also reset activeValue
	if(activeCell){ activeValue = value; }
}

// editor column plugin function

return function(column, editor, editOn){
	// summary:
	//		Adds editing capability to a column's cells.

	var originalRenderCell = column.renderCell || Grid.defaultRenderCell,
		isWidget, cleanupAdded;

	// accept arguments as parameters to editor function, or from column def,
	// but normalize to column def.
	column.editor = editor = editor || column.editor;
	column.editOn = editOn = editOn || column.editOn;

	isWidget = typeof editor != "string";

	// warn for widgetArgs -> editorArgs; TODO: remove @ 1.0
	if (column.widgetArgs) {
		kernel.deprecated("column.widgetArgs", "use column.editorArgs instead",
			"dgrid 1.0");
		column.editorArgs = column.widgetArgs;
	}

	column.renderCell = editOn ? function(object, value, cell, options){
		// On first run, create one shared widget/input which will be swapped into
		// the active cell.
		if(!column.editorInstance){
			column.editorInstance = createSharedEditor(column, originalRenderCell);
		}

		if (!cleanupAdded && isWidget) {
			cleanupAdded = true;
			// clean up shared widget instance when the grid is destroyed
			aspect.before(column.grid, "destroy", function(){
				column.editorInstance.destroyRecursive();
			});
		}

		// TODO: Consider using event delegation
		// (Would require using dgrid's focus events for activating on focus,
		// which we already advocate in README for optimal use)

		// in IE<8, cell is the child of the td due to the extra padding node
		on(cell.tagName == "TD" ? cell : cell.parentNode,
				editOn, function(){
			var cmp = column.editorInstance,
				grid = column.grid,
				field = column.field,
				row, dirty, value;

			if(activeCell != this &&
					(!column.canEdit || column.canEdit(object, value))){
				activeCell = this;

				// retrieve latest value; if retrieving from row, run through column.get
				row = grid.row(cell);
				dirty = grid.dirty && grid.dirty[row.id];
				value = (dirty && field in dirty) ? dirty[field] :
					column.get ? column.get(row.data) : row.data[field];
				showEditor(cmp, column, cell, value);

				// focus / blur-handler-resume logic is surrounded in a setTimeout
				// to play nice with Keyboard's dgrid-cellfocusin as an editOn event
				setTimeout(function(){
					// focus the newly-placed control
					cmp.focus && cmp.focus(); // supported by form widgets and HTML inputs
					// resume blur handler once editor is focused
					column._editorBlurHandle && column._editorBlurHandle.resume();
				}, 0);
			}
		});
		// initially render content in non-edit mode
		return originalRenderCell(object, value, cell, options);
	} : function(object, value, cell, options){
		// always-on: create editor immediately upon rendering each cell
		var grid = column.grid,
			cmp = createEditor(column);
		showEditor(cmp, column, cell, value);

		if(isWidget){
			// maintain reference for later cleanup
			cell.widget = cmp;

			if(!cleanupAdded){
				cleanupAdded = true;

				// add advice for cleaning up widgets in this column
				aspect.before(grid, "removeRow", function(rowElement){
					// destroy our widget during the row removal operation
					var cellElement = grid.cell(rowElement, column.id).element,
						widget = (cellElement.contents || cellElement).widget;
					widget && widget.destroyRecursive();
				});
			}
		}
	};

	return column;
};
});
<commit_msg>Implement better check for editor value changes; thanks kriszyp<commit_after>define([
	"dojo/_base/kernel",
	"dojo/_base/lang",
	"dojo/on",
	"dojo/aspect",
	"dojo/has",
	"./Grid",
	"put-selector/put",
	"dojo/_base/sniff"
], function(kernel, lang, on, aspect, has, Grid, put){

var activeCell, activeValue; // tracks cell currently being edited, and its value

function updateInputValue(input, value){
	// common code for updating value of a standard input
	input.value = value;
	if(input.type == "radio" || input.type == "checkbox"){
		input.checked = !!value;
	}
}

function dataFromValue(value, oldValue){
	// Default logic for translating values from editors;
	// tries to preserve type if possible.
	if(typeof oldValue == "number"){
		value = isNaN(value) ? value : parseFloat(value);
	}else if(typeof oldValue == "boolean"){
		value = value == "true" ? true : value == "false" ? false : value;
	}else if(oldValue instanceof Date){
		var asDate = new Date(value);
		value = isNaN(asDate.getTime()) ? value : asDate;
	}
	return value;
}

// intermediary frontend to dataFromValue for HTML and widget editors
function dataFromEditor(column, cmp){
	if(typeof cmp.get == "function"){ // widget
		return dataFromValue(cmp.get("value"));
	}else{ // HTML input
		return dataFromValue(
			cmp[cmp.type == "checkbox" || cmp.type == "radio"  ? "checked" : "value"]);
	}
}

function setProperty(grid, cellElement, oldValue, value){
	// Updates dirty hash and fires dgrid-datachange event for a changed value.
	var cell, row, column;
	// test whether old and new values are inequal, with coercion (e.g. for Dates)
	if(!(oldValue >= value && oldValue <= value)){
		cell = grid.cell(cellElement);
		row = cell.row;
		column = cell.column;
		if(column.field && row){
			// TODO: remove rowId in lieu of cell (or grid.row/grid.cell)
			// (keeping for the moment for back-compat, but will note in changes)
			if(on.emit(cellElement, "dgrid-datachange", {
						grid: this,
						cell: cell,
						rowId: row.id,
						oldValue: oldValue,
						value: value,
						bubbles: true,
						cancelable: true
					})){
				if (grid.updateDirty){
					// for OnDemandGrid: update dirty data, and save if autoSave is true
					grid.updateDirty(row.id, column.field, value);
					// perform auto-save (if applicable) in next tick to avoid
					// unintentional mishaps due to order of handler execution
					column.autoSave && setTimeout(function(){ grid._trackError("save"); }, 0);
				}
			}else{
				// else keep the value the same
				return oldValue;
			}
		}
	}
	return value;
}

// intermediary frontend to setProperty for HTML and widget editors
function setPropertyFromEditor(grid, column, cmp) {
	var value;
	if(!cmp.isValid || cmp.isValid()){
		value = setProperty(grid, (cmp.domNode || cmp).parentNode,
			activeCell ? activeValue : cmp._dgridLastValue,
			dataFromEditor(column, cmp));

		if(activeCell){ // for editors with editOn defined
			activeValue = value;
		}else{ // for always-on editors, update _dgridLastValue immediately
			cmp._dgridLastValue = value;
		}
	}
}

// editor creation/hookup/placement logic

function createEditor(column){
	// Creates an editor instance based on column definition properties,
	// and hooks up events.
	var editor = column.editor,
		editOn = column.editOn,
		grid = column.grid,
		isWidget = typeof editor != "string", // string == standard HTML input
		args, cmp, node, putstr, handleChange;

	args = column.editorArgs || {};
	if(typeof args == "function"){ args = args.call(grid, column); }

	if(isWidget){
		cmp = new editor(args);
		node = cmp.focusNode || cmp.domNode;

		// Add dgrid-input to className to make consistent with HTML inputs.
		// (Can't do this using className argument to constructor; causes issues)
		node.className += " dgrid-input";

		// For editOn editors, connect to onBlur rather than onChange, since
		// the latter is delayed by setTimeouts in Dijit and will fire too late.
		cmp.connect(cmp, editOn ? "onBlur" : "onChange", function(){
			if(!cmp._dgridIgnoreChange){
				setPropertyFromEditor(grid, column, this);
			}
		});
	}else{
		handleChange = function(evt){
			var target = evt.target;
			if("_dgridLastValue" in target && target.className.indexOf("dgrid-input") > -1){
				setPropertyFromEditor(grid, column, target);
			}
		};

		// considerations for standard HTML form elements
		if(!column.grid._hasInputListener){
			// register one listener at the top level that receives events delegated
			grid._hasInputListener = true;
			grid.on("change", function(evt){ handleChange(evt); });
			// also register a focus listener
		}

		putstr = editor == "textarea" ? "textarea" :
			"input[type=" + editor + "]";
		cmp = node = put(putstr + ".dgrid-input", lang.mixin({
			name: column.field,
			tabIndex: isNaN(column.tabIndex) ? -1 : column.tabIndex
		}, args));

		if(has("ie") < 9 || (has("ie") && has("quirks"))){
			// IE<9 / quirks doesn't fire change events for all the right things,
			// and it doesn't bubble.
			if(editor == "radio" || editor == "checkbox"){
				// listen for clicks since IE doesn't fire change events properly for checks/radios
				on(cmp, "click", function(evt){ handleChange(evt); });
			}else{
				on(cmp, "change", function(evt){ handleChange(evt); });
			}
		}
	}

	// XXX: stop mousedown propagation to prevent confusing Keyboard mixin logic
	// with certain widgets; perhaps revising KB's `handledEvent` would be better.
	on(node, "mousedown", function(evt){ evt.stopPropagation(); });

	return cmp;
}

function createSharedEditor(column, originalRenderCell){
	// Creates an editor instance with additional considerations for
	// shared usage across an entire column (for columns with editOn specified).

	var cmp = createEditor(column),
		isWidget = cmp.domNode,
		node = cmp.domNode || cmp,
		focusNode = cmp.focusNode || node,
		reset = isWidget ?
			function(){ cmp.set("value", cmp._dgridLastValue); } :
			function(){
				updateInputValue(cmp, cmp._dgridLastValue);
				// call setProperty again in case we need to revert a previous change
				setPropertyFromEditor(column.grid, column, cmp);
			},
		keyHandle;

	function onblur(){
		var parentNode = node.parentNode,
			renderedNode;

		// remove the editor from the cell
		parentNode.removeChild(node);

		// pass new value to original renderCell implementation for this cell
		Grid.appendIfNode(parentNode, originalRenderCell(
			column.grid.row(parentNode).data, activeValue, parentNode));

		// reset state now that editor is deactivated
		activeCell = activeValue = null;
		column._editorBlurHandle.pause();
	}

	function dismissOnKey(evt){
		// Contains logic for reacting to enter/escape keypresses to save/cancel edits.
		// Returns boolean specifying whether this key event should dismiss the field.
		var key = evt.keyCode || evt.which;

		if(key == 27){ // escape: revert + dismiss
			reset();
			activeValue = cmp._dgridLastValue;
			focusNode.blur();
		}else if(key == 13 && column.dismissOnEnter !== false){ // enter: dismiss
			// FIXME: Opera is "reverting" even in this case
			focusNode.blur();
		}
	}

	// hook up enter/esc key handling
	keyHandle = on(focusNode, "keydown", dismissOnKey);

	// hook up blur handler, but don't activate until widget is activated
	(column._editorBlurHandle = on.pausable(cmp, "blur", onblur)).pause();

	return cmp;
}

function showEditor(cmp, column, cell, value){
	// Places a shared editor into the newly-active cell in the column.
	// Also called when rendering an editor in an "always-on" editor column.

	var grid = column.grid,
		editor = column.editor,
		isWidget = cmp.domNode;

	// for regular inputs, we can update the value before even showing it
	if(!isWidget){ updateInputValue(cmp, value); }

	cell.innerHTML = "";
	put(cell, cmp.domNode || cmp);

	if(isWidget){
		// For widgets, ensure startup is called before setting value,
		// to maximize compatibility with flaky widgets like dijit/form/Select.
		if (!cmp._started){ cmp.startup(); }

		// Set value, but ensure it isn't processed as a user-generated change.
		// (Clear flag on a timeout to wait for delayed onChange to fire first)
		cmp._dgridIgnoreChange = true;
		cmp.set("value", value);
		setTimeout(function(){ cmp._dgridIgnoreChange = false; }, 0);
	}
	// track previous value for short-circuiting or in case we need to revert
	cmp._dgridLastValue = value;
	// if this is an editor with editOn, also reset activeValue
	if(activeCell){ activeValue = value; }
}

// editor column plugin function

return function(column, editor, editOn){
	// summary:
	//		Adds editing capability to a column's cells.

	var originalRenderCell = column.renderCell || Grid.defaultRenderCell,
		isWidget, cleanupAdded;

	// accept arguments as parameters to editor function, or from column def,
	// but normalize to column def.
	column.editor = editor = editor || column.editor;
	column.editOn = editOn = editOn || column.editOn;

	isWidget = typeof editor != "string";

	// warn for widgetArgs -> editorArgs; TODO: remove @ 1.0
	if (column.widgetArgs) {
		kernel.deprecated("column.widgetArgs", "use column.editorArgs instead",
			"dgrid 1.0");
		column.editorArgs = column.widgetArgs;
	}

	column.renderCell = editOn ? function(object, value, cell, options){
		// On first run, create one shared widget/input which will be swapped into
		// the active cell.
		if(!column.editorInstance){
			column.editorInstance = createSharedEditor(column, originalRenderCell);
		}

		if (!cleanupAdded && isWidget) {
			cleanupAdded = true;
			// clean up shared widget instance when the grid is destroyed
			aspect.before(column.grid, "destroy", function(){
				column.editorInstance.destroyRecursive();
			});
		}

		// TODO: Consider using event delegation
		// (Would require using dgrid's focus events for activating on focus,
		// which we already advocate in README for optimal use)

		// in IE<8, cell is the child of the td due to the extra padding node
		on(cell.tagName == "TD" ? cell : cell.parentNode,
				editOn, function(){
			var cmp = column.editorInstance,
				grid = column.grid,
				field = column.field,
				row, dirty, value;

			if(activeCell != this &&
					(!column.canEdit || column.canEdit(object, value))){
				activeCell = this;

				// retrieve latest value; if retrieving from row, run through column.get
				row = grid.row(cell);
				dirty = grid.dirty && grid.dirty[row.id];
				value = (dirty && field in dirty) ? dirty[field] :
					column.get ? column.get(row.data) : row.data[field];
				showEditor(cmp, column, cell, value);

				// focus / blur-handler-resume logic is surrounded in a setTimeout
				// to play nice with Keyboard's dgrid-cellfocusin as an editOn event
				setTimeout(function(){
					// focus the newly-placed control
					cmp.focus && cmp.focus(); // supported by form widgets and HTML inputs
					// resume blur handler once editor is focused
					column._editorBlurHandle && column._editorBlurHandle.resume();
				}, 0);
			}
		});
		// initially render content in non-edit mode
		return originalRenderCell(object, value, cell, options);
	} : function(object, value, cell, options){
		// always-on: create editor immediately upon rendering each cell
		var grid = column.grid,
			cmp = createEditor(column);
		showEditor(cmp, column, cell, value);

		if(isWidget){
			// maintain reference for later cleanup
			cell.widget = cmp;

			if(!cleanupAdded){
				cleanupAdded = true;

				// add advice for cleaning up widgets in this column
				aspect.before(grid, "removeRow", function(rowElement){
					// destroy our widget during the row removal operation
					var cellElement = grid.cell(rowElement, column.id).element,
						widget = (cellElement.contents || cellElement).widget;
					widget && widget.destroyRecursive();
				});
			}
		}
	};

	return column;
};
});
<|endoftext|>