<commit_before>/*!
    Copyright (C) 2015 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: ivan@reciprocitylabs.com
    Maintained By: ivan@reciprocitylabs.com
*/
(function ($, can) {
  // a few core CanJS extensions below.
  // Core validation for fields not being "blank", i.e.
  // having no content when outside spaces are trimmed away.
  can.Model.validationMessages.non_blank =
    can.Map.validationMessages.non_blank = 'cannot be blank';

  can.Model.validateNonBlank =
    can.Map.validateNonBlank = function (attrNames, options) {
      this.validate(attrNames, options, function (value) {
        if (_.isUndefined(value) ||
            _.isNull(value) ||
            _.isFunction(value.trim) && value.trim() === '') {
          return this.constructor.validationMessages.non_blank;
        }
      });
    };
  can.Model.validateContact =
    can.Map.validateContact = function (attrNames, options) {
      this.validate(attrNames, options, function (newVal, prop) {
        var reifiedContact = this.contact ? this.contact.reify() : false;
        var hasEmail = reifiedContact ? reifiedContact.email : false;

        // This check will not work until the bug introduced with commit 8a5f600c65b7b45fd34bf8a7631961a6d5a19638
        // is resolved.
        if (!hasEmail) {
          return 'No valid contact selected for assignee';
        }
      });
    };

  // Adding reduce, a generally useful array comprehension.
  //  Bitovi decided against including it in core CanJS, but
  //  adding it here for easy universal use across can.List
  //  as well as arrays.
  if (!can.reduce) {
    can.reduce = function (a, f, i) {
      if (_.isNull(a)) {
        return null;
      }
      return [].reduce.apply(a, arguments.length < 3 ? [f] : [f, i]);
    };
  }

  // Turn camelSpace strings into Camel Space strings
  can.spaceCamelCase = function (string) {
    return can.underscore(string)
      .split('_')
      .map(can.capitalize)
      .join(' ');
  };
  can.camelCaseToUnderscore = function (string) {
    return string.replace(/([A-Z])/g, '_$1').toLowerCase();
  };
})(jQuery, can);
<commit_msg>Add dash case to camel case extension<commit_after>/*!
    Copyright (C) 2015 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: ivan@reciprocitylabs.com
    Maintained By: ivan@reciprocitylabs.com
*/
(function ($, can) {
  // a few core CanJS extensions below.
  // Core validation for fields not being "blank", i.e.
  // having no content when outside spaces are trimmed away.
  can.Model.validationMessages.non_blank =
    can.Map.validationMessages.non_blank = 'cannot be blank';

  can.Model.validateNonBlank =
    can.Map.validateNonBlank = function (attrNames, options) {
      this.validate(attrNames, options, function (value) {
        if (_.isUndefined(value) ||
            _.isNull(value) ||
            _.isFunction(value.trim) && value.trim() === '') {
          return this.constructor.validationMessages.non_blank;
        }
      });
    };
  can.Model.validateContact =
    can.Map.validateContact = function (attrNames, options) {
      this.validate(attrNames, options, function (newVal, prop) {
        var reifiedContact = this.contact ? this.contact.reify() : false;
        var hasEmail = reifiedContact ? reifiedContact.email : false;

        // This check will not work until the bug introduced with commit 8a5f600c65b7b45fd34bf8a7631961a6d5a19638
        // is resolved.
        if (!hasEmail) {
          return 'No valid contact selected for assignee';
        }
      });
    };

  // Adding reduce, a generally useful array comprehension.
  //  Bitovi decided against including it in core CanJS, but
  //  adding it here for easy universal use across can.List
  //  as well as arrays.
  if (!can.reduce) {
    can.reduce = function (a, f, i) {
      if (_.isNull(a)) {
        return null;
      }
      return [].reduce.apply(a, arguments.length < 3 ? [f] : [f, i]);
    };
  }

  // Turn camelSpace strings into Camel Space strings
  can.spaceCamelCase = function (string) {
    return can.underscore(string)
      .split('_')
      .map(can.capitalize)
      .join(' ');
  };
  can.camelCaseToUnderscore = function (string) {
    return string.replace(/([A-Z])/g, '_$1').toLowerCase();
  };
  can.camelCaseToDashCase = function (string) {
    return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  };
})(jQuery, can);
<|endoftext|>


<commit_before>jQuery("document").ready(function(){

    jQuery("#searchAjax").keydown(function(){
        var params = [];
        var searchInput = jQuery(this);
        var rejected = searchInput.attr("rejected") ? "rejected=1" : "";
        var step = searchInput.attr("step") ? "stepId="+searchInput.attr("step") : "";
        params.push(rejected);
        params.push(step);
        if(searchInput.val() != "")
        {
            params.push("smartSearch="+searchInput.val());
            params = params.filter(function(n){ return n != "" });
            //console.log(params.join("&"));
            var dropdownmenu = jQuery(".smartSearchResult");
            jQuery.ajax({
                url:"http://104.236.61.177/web/app.php/ajax/company/search?"+params.join("&")
            }).done(function(result) {
                if (result.result != "nothing")
                {
                    if(result.result.length > 0)
                    {
                        var resultData = result.result.reduce(function (a, b) {
                            return "
"+a.name+"
" + "
"+b.name+"
";
                        });
                        if(typeof resultData === 'object')
                        {
                            resultData = "
"+resultData.name+"
";
                        }
                        dropdownmenu.html(resultData);
                        dropdownmenu.addClass("showSmartSearch");
                        return false;
                    }
                    else
                    {
                        if(dropdownmenu.hasClass("showSmartSearch"))
                        {
                            dropdownmenu.removeClass("showSmartSearch");
                        }
                    }
                }
            });
        }

    });

    var today = new Date();
    var dd = today.getDate();
    var mm = today.getMonth()+1; //January is 0!
    var yyyy = today.getFullYear();
    if(dd<10) {
        dd='0'+dd
    }

    if(mm<10) {
        mm='0'+mm
    }
    jQuery(".table tr a").click(function(e){
        e.stopPropagation();
    });
    jQuery(".table > tbody > tr").click(function(){
        var main_page = jQuery(this).attr('main_page');
        var company_id = jQuery(this).attr('data-id');
        showCompany(company_id,main_page,this);
    });
    $('.panel-body .form-group.date').datepicker({
        format: "yyyy-mm-dd",
        orientation: "bottom auto",
        todayHighlight: true
        //defaultViewDate: { year: yyyy, month: mm, day: dd }
    });
    var date = jQuery("#saleDate");
    if(date.val() == "")
    {
        date.val(yyyy+"-"+mm+"-"+dd);
    }
});

function showCompany(id,main,obj)
{
    if(id)
    {
        var params = "";
        if(main)
        {
            params = "?main_page=1";
        }
        jQuery.ajax({
            url:"http://104.236.61.177/web/app.php/ajax/company/"+id+params
        }).done(function(result) {
            jQuery(".company-card").addClass("empty");
            jQuery(".company-card td").html("");
            if (result != "nothing")
            {
                jQuery(obj).next().removeClass("empty");
                jQuery(obj).next().children("td").html(result);
            }
        });
    }
}

function setStep(id,company_id,button)
{
    if(id)
    {
        jQuery.ajax({
            url: "http://104.236.61.177/web/app.php/ajax/step/"+id+"/"+company_id
        }).done(function(result){
            switch (result.result){
                case "added":
                    jQuery(button).addClass("btn-success");
                    break;
                case "removed":
                    jQuery(button).removeClass("btn-success");
                    break;
            }
        });
    }
}<commit_msg>update<commit_after>jQuery("document").ready(function(){

    jQuery("#searchAjax").keydown(function(){
        var params = [];
        var searchInput = jQuery(this);
        var rejected = searchInput.attr("rejected") ? "rejected=1" : "";
        var step = searchInput.attr("step") ? "stepId="+searchInput.attr("step") : "";
        params.push(rejected);
        params.push(step);
        if(searchInput.val() != "")
        {
            params.push("smartSearch="+searchInput.val());
            params = params.filter(function(n){ return n != "" });
            //console.log(params.join("&"));
            var dropdownmenu = jQuery(".smartSearchResult");
            jQuery.ajax({
                url:"http://104.236.61.177/web/app.php/company/search?"+params.join("&")
            }).done(function(result) {
                if (result.result != "nothing")
                {
                    if(result.result.length > 0)
                    {
                        var resultData = result.result.reduce(function (a, b) {
                            return "
"+a.name+"
" + "
"+b.name+"
";
                        });
                        if(typeof resultData === 'object')
                        {
                            resultData = "
"+resultData.name+"
";
                        }
                        dropdownmenu.html(resultData);
                        dropdownmenu.addClass("showSmartSearch");
                        return false;
                    }
                    else
                    {
                        if(dropdownmenu.hasClass("showSmartSearch"))
                        {
                            dropdownmenu.removeClass("showSmartSearch");
                        }
                    }
                }
            });
        }

    });

    var today = new Date();
    var dd = today.getDate();
    var mm = today.getMonth()+1; //January is 0!
    var yyyy = today.getFullYear();
    if(dd<10) {
        dd='0'+dd
    }

    if(mm<10) {
        mm='0'+mm
    }
    jQuery(".table tr a").click(function(e){
        e.stopPropagation();
    });
    jQuery(".table > tbody > tr").click(function(){
        var main_page = jQuery(this).attr('main_page');
        var company_id = jQuery(this).attr('data-id');
        showCompany(company_id,main_page,this);
    });
    $('.panel-body .form-group.date').datepicker({
        format: "yyyy-mm-dd",
        orientation: "bottom auto",
        todayHighlight: true
        //defaultViewDate: { year: yyyy, month: mm, day: dd }
    });
    var date = jQuery("#saleDate");
    if(date.val() == "")
    {
        date.val(yyyy+"-"+mm+"-"+dd);
    }
});

function showCompany(id,main,obj)
{
    if(id)
    {
        var params = "";
        if(main)
        {
            params = "?main_page=1";
        }
        jQuery.ajax({
            url:"http://104.236.61.177/web/app.php/ajax/company/"+id+params
        }).done(function(result) {
            jQuery(".company-card").addClass("empty");
            jQuery(".company-card td").html("");
            if (result != "nothing")
            {
                jQuery(obj).next().removeClass("empty");
                jQuery(obj).next().children("td").html(result);
            }
        });
    }
}

function setStep(id,company_id,button)
{
    if(id)
    {
        jQuery.ajax({
            url: "http://104.236.61.177/web/app.php/ajax/step/"+id+"/"+company_id
        }).done(function(result){
            switch (result.result){
                case "added":
                    jQuery(button).addClass("btn-success");
                    break;
                case "removed":
                    jQuery(button).removeClass("btn-success");
                    break;
            }
        });
    }
}<|endoftext|>


<commit_before>/**
 * Created by Obscurity on 2017/1/21.
 */

(function ($) {

    'use strict';

    var large = {
        size: "large",
        renderText: false,
        shares: [{
            platform: "qzone",
            icon: "https://qzonestyle.gtimg.cn/ac/qzone_v5/app/app_share/qz_logo.png",
            text: "QQ空间"
        }, {
            platform: "qq"
        }, {
            platform: "wechat",
            icon: "https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_appwx_logo.png",
            text: "微信"
        }, {
            platform: "sinaweibo",
            icon: "https://img.t.sinajs.cn/t4/appstyle/widget/images/shareButton/share_icon_mini.png?id=1375775002754",
            text: "新浪微博"
        }, {
            platform: "douban",
            icon: "https://img3.doubanio.com/pics/fw2douban_s.png",
            text: "豆瓣"
        }]
    };

    var medium = {
        size: "small",
        renderText: false,
        shares: [{
            platform: "qzone",
            icon: "https://qzonestyle.gtimg.cn/ac/qzone_v5/app/app_share/qz_logo.png",
            text: "QQ空间"
        }, {
            platform: "qq"
        }, {
            platform: "wechat",
            icon: "https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_appwx_logo.png",
            text: "微信"
        }, {
            platform: "sinaweibo",
            icon: "https://img.t.sinajs.cn/t4/appstyle/widget/images/shareButton/share_icon_mini.png?id=1375775002754",
            text: "新浪微博"
        }, {
            platform: "douban",
            icon: "https://img3.doubanio.com/pics/fw2douban_s.png",
            text: "豆瓣"
        }]
    };

    var small = {
        size: "small",
        renderText: false,
        shares: [{
            platform: "qzone",
            icon: "https://qzonestyle.gtimg.cn/ac/qzone_v5/app/app_share/qz_logo.png",
            text: "QQ空间"
        }, {
            platform: "qq"
        }, {
            platform: "wechat",
            icon: "https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_appwx_logo.png",
            text: "微信"
        }, {
            platform: "sinaweibo",
            icon: "https://img.t.sinajs.cn/t4/appstyle/widget/images/shareButton/share_icon_mini.png?id=1375775002754",
            text: "新浪微博"
        }, {
            platform: "douban",
            icon: "https://img3.doubanio.com/pics/fw2douban_s.png",
            text: "豆瓣"
        }]
    };

    var sizes = ["small", "medium", "large"];

    var defaults = medium;

    var hShare = function (options) {

        var url = encodeURIComponent(location.href);
        var title = encodeURIComponent(document.title);

        var opts = $.extend({}, defaults, options);

        var _render = function (platform, icon, text, customize, html) {
            if (customize) {
                return html;
            }
            else {
                switch(platform) {
                    case "qzone":
                        return $(_renderQzone(icon, text));
                        break;
                    case "wechat":
                        var wechatEntry = $(_renderWechat(icon, text));
                        wechatEntry.on('click', _renderWechatQECode);
                        return wechatEntry;
                        break;
                    case "sinaweibo":
                        return $(_renderSinaWeibo(icon, text));
                        break;
                    case "renren":
                        return $(_renderRenren(icon, text));
                        break;
                    case "douban":
                        return $(_renderDouban(icon, text));
                        break;
                    default:
                        throw Error("invalid platform");
                }
            }
        };

        var _renderWechatQECode = function () {
            var startX = $(this).offset.left + $(this).width;
            var startY = $(this).offset.top + $(this).height;
            var width = 50, height = 50;
            var panelStyle = "position: absolute; left: " + startX + "px; top: " + startY + "px; width: " + width + "; height: " + height + "px;";
            var imageStyle = "position: absolute; left: " + (startX) + "px; top: " + startY + "px; width: " + width + "; height: " + height + "px;";;
            var panel = $("

");
            panel.on('blur', function () {
                $(this).remove();
            });
            $(document).append(panel);
        };

        var _renderWechat = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "<\/a>";
            }
            else {
                return "<\/a>";
            }
        };

        var _renderQzone = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "<\/a>";
            }
            else {
                return "<\/a>";
            }
        };

        var _renderDouban = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "<a class='hshare hshare-" + size + "'  href=\"javascript:void(function(){var w=window,d=document,e=encodeURIComponent,s1=window.getSelection,s2=d.getSelection,s3=d.selection,s=s1?s1():s2?s2():s3?s3.createRange().text:'',r='https://www.douban.com/recommend/?url='+e(w.location.href)+'&title='+e(d.title)+'&sel='+e(s)+'&v=1',w=450,h=330,x=function(){if(!window.open(r,'douban','toolbar=0,resizable=1,scrollbars=yes,status=1,width='+w+',height='+h+',left='+(screen.width-w)/2+',top='+(screen.height-h)/2))location.href=r+'&r=1'};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})()\">" + text + "";
            }
            else {
                return "<a class='hshare hshare-" + size + "'  href=\"javascript:void(function(){var w=window,d=document,e=encodeURIComponent,s1=window.getSelection,s2=d.getSelection,s3=d.selection,s=s1?s1():s2?s2():s3?s3.createRange().text:'',r='https://www.douban.com/recommend/?url='+e(w.location.href)+'&title='+e(d.title)+'&sel='+e(s)+'&v=1',w=450,h=330,x=function(){if(!window.open(r,'douban','toolbar=0,resizable=1,scrollbars=yes,status=1,width='+w+',height='+h+',left='+(screen.width-w)/2+',top='+(screen.height-h)/2))location.href=r+'&r=1'};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})()\">";
            }
        };

        var _renderRenren = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "";
            }
            else {
                return "";
            }
        };

        var _renderSinaWeibo = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "";
            }
            else {
                return "";
            }
        };

        return this.each(function () {
            var $this = $(this);

            var platforms = opts.shares;

            platforms.forEach(function (plt) {
                var platform = plt.platform || "";
                var icon = plt.icon || "";
                var text = plt.text || "";
                var isCustomized = !!plt.customize;
                var customize = plt.customize || "";
                $this.append($(_render(platform, icon, text, isCustomized, customize)));
            });

        });
    };

    $.fn.extend({
        hshare: hShare
    });

})(jQuery);<commit_msg>增加了一个demo<commit_after>/**
 * Created by Obscurity on 2017/1/21.
 */

(function ($) {

    'use strict';

    var large = {
        size: "large",
        renderText: false,
        shares: [{
            platform: "qzone",
            icon: "https://qzonestyle.gtimg.cn/ac/qzone_v5/app/app_share/qz_logo.png",
            text: "QQ空间"
        }, {
            platform: "qq"
        }, {
            platform: "wechat",
            icon: "https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_appwx_logo.png",
            text: "微信"
        }, {
            platform: "sinaweibo",
            icon: "https://img.t.sinajs.cn/t4/appstyle/widget/images/shareButton/share_icon_mini.png?id=1375775002754",
            text: "新浪微博"
        }, {
            platform: "douban",
            icon: "https://img3.doubanio.com/pics/fw2douban_s.png",
            text: "豆瓣"
        }]
    };

    var medium = {
        size: "small",
        renderText: false,
        shares: [{
            platform: "qzone",
            icon: "https://qzonestyle.gtimg.cn/ac/qzone_v5/app/app_share/qz_logo.png",
            text: "QQ空间"
        }, {
            platform: "qq"
        }, {
            platform: "wechat",
            icon: "https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_appwx_logo.png",
            text: "微信"
        }, {
            platform: "sinaweibo",
            icon: "https://img.t.sinajs.cn/t4/appstyle/widget/images/shareButton/share_icon_mini.png?id=1375775002754",
            text: "新浪微博"
        }, {
            platform: "douban",
            icon: "https://img3.doubanio.com/pics/fw2douban_s.png",
            text: "豆瓣"
        }]
    };

    var small = {
        size: "small",
        renderText: false,
        shares: [{
            platform: "qzone",
            icon: "https://qzonestyle.gtimg.cn/ac/qzone_v5/app/app_share/qz_logo.png",
            text: "QQ空间"
        }, {
            platform: "qq"
        }, {
            platform: "wechat",
            icon: "https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_appwx_logo.png",
            text: "微信"
        }, {
            platform: "sinaweibo",
            icon: "https://img.t.sinajs.cn/t4/appstyle/widget/images/shareButton/share_icon_mini.png?id=1375775002754",
            text: "新浪微博"
        }, {
            platform: "douban",
            icon: "https://img3.doubanio.com/pics/fw2douban_s.png",
            text: "豆瓣"
        }]
    };

    var sizes = ["small", "medium", "large"];

    var defaults = medium;

    var hShare = function (options) {

        var url = encodeURIComponent(location.href);
        var title = encodeURIComponent(document.title);

        var opts = $.extend({}, defaults, options);

        var _render = function (platform, icon, text, customize, html) {
            if (customize) {
                return html;
            }
            else {
                switch(platform) {
                    case "qzone":
                        return $(_renderQzone(icon, text));
                        break;
                    case "wechat":
                        var wechatEntry = $(_renderWechat(icon, text));
                        wechatEntry.on('click', _renderWechatQECode);
                        return wechatEntry;
                        break;
                    case "sinaweibo":
                        return $(_renderSinaWeibo(icon, text));
                        break;
                    case "renren":
                        return $(_renderRenren(icon, text));
                        break;
                    case "douban":
                        return $(_renderDouban(icon, text));
                        break;
                    default:
                        throw Error("invalid platform");
                }
            }
        };

        var _renderWechatQECode = function () {
            var startX = $(this).offset.left + $(this).width;
            var startY = $(this).offset.top + $(this).height;
            var width = 50, height = 50;
            var panelStyle = "position: absolute; left: " + startX + "px; top: " + startY + "px; width: " + width + "; height: " + height + "px;";
            var imageStyle = "position: absolute; left: " + (startX) + "px; top: " + startY + "px; width: " + width + "; height: " + height + "px;";;
            var panel = $("

");
            panel.on('blur', function () {
                $(this).remove();
            });
            $("body").append(panel);
        };

        var _renderWechat = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "<\/a>";
            }
            else {
                return "<\/a>";
            }
        };

        var _renderQzone = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "<\/a>";
            }
            else {
                return "<\/a>";
            }
        };

        var _renderDouban = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "<a class='hshare hshare-" + size + "'  href=\"javascript:void(function(){var w=window,d=document,e=encodeURIComponent,s1=window.getSelection,s2=d.getSelection,s3=d.selection,s=s1?s1():s2?s2():s3?s3.createRange().text:'',r='https://www.douban.com/recommend/?url='+e(w.location.href)+'&title='+e(d.title)+'&sel='+e(s)+'&v=1',w=450,h=330,x=function(){if(!window.open(r,'douban','toolbar=0,resizable=1,scrollbars=yes,status=1,width='+w+',height='+h+',left='+(screen.width-w)/2+',top='+(screen.height-h)/2))location.href=r+'&r=1'};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})()\">" + text + "";
            }
            else {
                return "<a class='hshare hshare-" + size + "'  href=\"javascript:void(function(){var w=window,d=document,e=encodeURIComponent,s1=window.getSelection,s2=d.getSelection,s3=d.selection,s=s1?s1():s2?s2():s3?s3.createRange().text:'',r='https://www.douban.com/recommend/?url='+e(w.location.href)+'&title='+e(d.title)+'&sel='+e(s)+'&v=1',w=450,h=330,x=function(){if(!window.open(r,'douban','toolbar=0,resizable=1,scrollbars=yes,status=1,width='+w+',height='+h+',left='+(screen.width-w)/2+',top='+(screen.height-h)/2))location.href=r+'&r=1'};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})()\">";
            }
        };

        var _renderRenren = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "";
            }
            else {
                return "";
            }
        };

        var _renderSinaWeibo = function (icon, text) {
            var size = sizes.includes(opts.size) ? opts.size : "medium";
            if (opts.renderText) {
                return "" + text + "";
            }
            else {
                return "";
            }
        };

        return this.each(function () {
            var $this = $(this);

            var platforms = opts.shares;

            platforms.forEach(function (plt) {
                var platform = plt.platform || "";
                var icon = plt.icon || "";
                var text = plt.text || "";
                var isCustomized = !!plt.customize;
                var customize = plt.customize || "";
                $this.append($(_render(platform, icon, text, isCustomized, customize)));
            });

        });
    };

    $.fn.extend({
        hshare: hShare
    });

})(jQuery);<|endoftext|>


<commit_before>/*
 * Copyright 2016 resin.io
 *
 * 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.
 */

'use strict'

const _ = require('lodash')
const store = require('../../../models/store')
const analytics = require('../../../modules/analytics')

module.exports = function ($uibModal, $q) {
  /**
   * @summary Open a modal
   * @function
   * @public
   *
   * @param {Object} options - options
   * @param {String} options.template - template contents
   * @param {String} options.controller - controller
   * @param {String} [options.size='sm'] - modal size
   * @param {Object} options.resolve - modal resolves
   * @returns {Object} modal
   *
   * @example
   * ModalService.open({
   *   name: 'my modal',
   *   template: require('./path/to/modal.tpl.html'),
   *   controller: 'DriveSelectorController as modal',
   * });
   */
  this.open = (options = {}) => {
    _.defaults(options, {
      size: 'sm'
    })

    analytics.logEvent('Open modal', {
      name: options.name,
      applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
      flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
    })

    const modal = $uibModal.open({
      animation: true,
      template: options.template,
      controller: options.controller,
      size: options.size,
      resolve: options.resolve
    })

    return {
      close: modal.close,
      result: $q((resolve, reject) => {
        modal.result.then((value) => {
          analytics.logEvent('Modal accepted', {
            name: options.name,
            value,
            applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
            flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
          })

          resolve(value)
        }).catch((error) => {
          // Bootstrap doesn't 'resolve' these but cancels the dialog
          if (error === 'escape key press' || error === 'backdrop click') {
            analytics.logEvent('Modal rejected', {
              name: options.name,
              method: error,
              applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
              flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
            })

            return resolve()
          }

          analytics.logEvent('Modal rejected', {
            name: options.name,
            value: error,
            applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
            flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
          })

          return reject(error)
        })
      })
    }
  }
}
<commit_msg>fix(gui): Fix disappearing modal window<commit_after>/*
 * Copyright 2016 resin.io
 *
 * 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.
 */

'use strict'

const _ = require('lodash')
const store = require('../../../models/store')
const analytics = require('../../../modules/analytics')

module.exports = function ($uibModal, $q) {
  /**
   * @summary Open a modal
   * @function
   * @public
   *
   * @param {Object} options - options
   * @param {String} options.template - template contents
   * @param {String} options.controller - controller
   * @param {String} [options.size='sm'] - modal size
   * @param {Object} options.resolve - modal resolves
   * @returns {Object} modal
   *
   * @example
   * ModalService.open({
   *   name: 'my modal',
   *   template: require('./path/to/modal.tpl.html'),
   *   controller: 'DriveSelectorController as modal',
   * });
   */
  this.open = (options = {}) => {
    _.defaults(options, {
      size: 'sm'
    })

    analytics.logEvent('Open modal', {
      name: options.name,
      applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
      flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
    })

    const modal = $uibModal.open({
      animation: true,
      template: options.template,
      controller: options.controller,
      size: options.size,
      resolve: options.resolve,
      backdrop: 'static'
    })

    return {
      close: modal.close,
      result: $q((resolve, reject) => {
        modal.result.then((value) => {
          analytics.logEvent('Modal accepted', {
            name: options.name,
            value,
            applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
            flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
          })

          resolve(value)
        }).catch((error) => {
          // Bootstrap doesn't 'resolve' these but cancels the dialog
          if (error === 'escape key press') {
            analytics.logEvent('Modal rejected', {
              name: options.name,
              method: error,
              applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
              flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
            })

            return resolve()
          }

          analytics.logEvent('Modal rejected', {
            name: options.name,
            value: error,
            applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
            flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
          })

          return reject(error)
        })
      })
    }
  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Row, Col } from 'react-bootstrap';
import PropTypes from 'prop-types';
import { Grid } from 'react-bootstrap';
import { sectionsProps } from "../../prop-types/section_props";
import { questionsProps } from "../../prop-types/question_props";
import SearchResult from '../SearchResult';

class SurveySectionList extends Component {
  render() {
    if(!this.props.sections || this.props.survey.surveySections.length < 1){
      return (
No Sections Selected
);
    }
    var survey = this.props.survey;
    return (

          {this.props.survey.surveySections.map((section, i) => {
            var sect = this.props.sections[section.sectionId];
            if(!sect) {
              return (
                <Grid className="basic-bg" key={i}>Loading...</Grid>

              );
            } else {
              return (
                <Row key={i}>
                  <Col md={11}>
                    <SearchResult type  ='survey_section'
                                  result={{Source: sect}}
                                  currentUser={{id: -1}}
                                  isEditPage ={true}
                                  index={i} />
                  </Col>
                  <Col md={1}>

                      <button className="btn btn-small btn-default move-up"
                           onClick={(event) => {
                             event.preventDefault();
                             this.props.reorderSection(survey, i, 1);
                           }}>
                        {`Move Up section ${sect.name} on survey`}
                      </button>

                      <button className="btn btn-small btn-default move-down"
                           onClick={(event) => {
                             event.preventDefault();
                             this.props.reorderSection(survey, i, -1);
                           }}>
                        {`Move down section ${sect.name} on survey`}
                      </button>

                      <button className="btn btn-small btn-default delete-section"
                           onClick={(event) => {
                             event.preventDefault();
                             this.props.removeSection(survey, i);
                           }}>
                        {`Delete section ${sect.name} on survey`}
                      </button>

                  </Col>
                </Row>
              );
            }
          }
        )}

    );
  }
}

SurveySectionList.propTypes = {
  survey: PropTypes.object,
  sections:  sectionsProps,
  questions:  questionsProps,
  removeSection:  PropTypes.func,
  reorderSection: PropTypes.func
};

export default SurveySectionList;
<commit_msg>Fixing cucumber test<commit_after>import React, { Component } from 'react';
import { Row, Col } from 'react-bootstrap';
import PropTypes from 'prop-types';
import { Grid } from 'react-bootstrap';
import { sectionsProps } from "../../prop-types/section_props";
import { questionsProps } from "../../prop-types/question_props";
import SearchResult from '../SearchResult';

class SurveySectionList extends Component {
  render() {
    if(!this.props.sections || this.props.survey.surveySections.length < 1){
      return (
No Sections Selected
);
    }
    var survey = this.props.survey;
    return (

          {this.props.survey.surveySections.map((section, i) => {
            var sect = this.props.sections[section.sectionId];
            if(!sect) {
              return (
                <Grid className="basic-bg" key={i}>Loading...</Grid>

              );
            } else {
              return (
                <Row key={i}>
                  <Col md={11} className='survey-section'>
                    <SearchResult type  ='survey_section'
                                  result={{Source: sect}}
                                  currentUser={{id: -1}}
                                  isEditPage ={true}
                                  index={i} />
                  </Col>
                  <Col md={1}>

                      <button className="btn btn-small btn-default move-up"
                           onClick={(event) => {
                             event.preventDefault();
                             this.props.reorderSection(survey, i, 1);
                           }}>
                        {`Move Up section ${sect.name} on survey`}
                      </button>

                      <button className="btn btn-small btn-default move-down"
                           onClick={(event) => {
                             event.preventDefault();
                             this.props.reorderSection(survey, i, -1);
                           }}>
                        {`Move down section ${sect.name} on survey`}
                      </button>

                      <button className="btn btn-small btn-default delete-section"
                           onClick={(event) => {
                             event.preventDefault();
                             this.props.removeSection(survey, i);
                           }}>
                        {`Delete section ${sect.name} on survey`}
                      </button>

                  </Col>
                </Row>
              );
            }
          }
        )}

    );
  }
}

SurveySectionList.propTypes = {
  survey: PropTypes.object,
  sections:  sectionsProps,
  questions:  questionsProps,
  removeSection:  PropTypes.func,
  reorderSection: PropTypes.func
};

export default SurveySectionList;
<|endoftext|>


<commit_before>$(document).ready(function(){
  $('#footer-links').append(" | Fontsize: +");
});
<commit_msg>Added javascript example of adding links to the footer.<commit_after>$(document).ready(function(){
  $('#footer-links').append(" | Google");
});
<|endoftext|>


<commit_before>'use strict';

angular.module('mwComponents', [])

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwPanel
 * @element div
 * @description
 *
 * Wrapper directive for {@link http://getbootstrap.com/components/#panels Bootstraps Panel}.
 *
 * @param {string} mwPanel Panel title
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *      Panel content
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwPanel', function () {
    return {
      restrict: 'A',
      replace: true,
      require: '^?dashboardModule',
      scope: {
        title: '@mwPanel'
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwPanel.html',
      link: function(scope, elm, attr, ctrl){
        if(ctrl){
          scope.isDashboardModule = true;
          scope.closeModule = ctrl.closeModule;
        }
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwSortIndicator
 * @element span
 * @description
 *
 * Displays a sort indicator. Arrow up when sort is active and not reversed arrow down vise versa.
 *
 * @param {boolean} isActive display an arrow up or down when true otherwise an up and down arrow
 * @param {boolean} isReversed display an arrow up or down
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwSortIndicator', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: {
        isActive: '=',
        isReversed: '='
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwSortIndicator.html'
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwAlert
 * @element div
 * @description
 *
 * Wrapper directive for {@link http://getbootstrap.com/components/#alerts Bootstraps Alert}.
 *
 * @param {string} mwAlert Alert type. Can be one of the following:
 *
 * - warning
 * - danger
 * - success
 * - info
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *      Alert content
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwAlert', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: {
        type: '@mwAlert'
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwAlert.html'
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwHeader
 * @element div
 * @description
 *
 * Header bar for content pages.
 *
 * @param {string} title Header title
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *      Header content, Buttons etc...
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwHeader', function ($location, $route) {
    return {
      transclude: true,
      scope: {
        title: '@',
        url: '@',
        showBackButton: '@',
        warningText: '@',
        warningCondition: '='
      },
      templateUrl: 'modules/ui/templates/mwComponents/mwHeader.html',
      link: function (scope, el, attrs, ctrl, $transclude) {

        $transclude(function (clone) {
          if ((!clone || clone.length === 0) && !scope.showBackButton) {
            el.find('.navbar-header').addClass('no-buttons');
          }
        });

        scope.refresh = function () {
          $route.reload();
        };

        scope.back = function () {
          if (attrs.url) {
            $location.path(attrs.url);
          } else {
            window.history.back();
          }
        };

        if (scope.warningText) {
          el.find('.header-popover').popover({
            trigger: 'hover',
            placement: 'bottom',
            container: el.find('.popover-container')
          });
        }
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwIcon
 * @element span
 * @description
 *
 * Wrapper for bootstrap glyphicons.
 *
 * @param {string} mwIcon Glyphicon class suffix. Example suffix for 'glyphicon glyphicon-search' is 'search'
 * @param {string} tooltip Optional string which will be displayed as a tooltip when hovering over the icon
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *
 *
 *  </doc:source>
 * </doc:example>
 */
  .directive('mwIcon', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: { mwIcon: '@'},
      template: function (elm, attr) {
        var isBootstrap = angular.isArray(attr.mwIcon.match(/^fa-/));
        if (isBootstrap) {
          return '';
        } else {
          return '';
        }
      },
      link: function (scope, el, attr) {
        if (attr.tooltip) {
          el.popover({
            trigger: 'hover',
            placement: 'bottom',
            content: attr.tooltip,
            container: 'body'
          });

          attr.$observe('tooltip', function (newVal) {
            el.popover('destroy');
            el.popover({
              trigger: 'hover',
              placement: 'bottom',
              content: newVal,
              container: 'body'
            });
          });
        }

      }
    };
  })

/**
 * @ngdoc directive
 * @name Relution.Common.directive:rlnTooltip
 * @element span
 *
 * @description
 * Creates a tooltip element using Bootstraps popover component.
 *
 * @param {String} mwTooltip Content of the tooltip
 *
 * @example

 */
  .directive('mwTooltip', function () {
    return {
      restrict: 'A',
      scope: {
        text: '@mwTooltip'
      },
      template: '',
      compile: function (elm, attr) {
        if (attr.mwTooltipIcon) {
          elm.find('span').attr('mw-icon', attr.mwTooltipIcon);
        }
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwBadge
 * @element span
 * @description
 *
 * Wrapper for bootstrap labels.
 *
 * @param {string} mwBadge label class suffix. Example: suffix for 'label label-info' is 'search'
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *
 *  </doc:source>
 * </doc:example>
 */
  .directive('mwBadge', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: { mwBadge: '@' },
      transclude: true,
      template: ''
    };
  })

  .directive('mwEmptyState', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: { mwBadge: '@' },
      transclude: true,
      template: '

'
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwFilterableSearch
 * @element div
 * @description
 *
 * Creates a search field to filter by in the sidebar. Search is triggered on keypress 'enter'.
 *
 * @param {filterable} filterable Filterable instance.
 * @param {expression} disabled If expression evaluates to true, input is disabled.
 * @param {string} property The name of the property on which the filtering should happen.
 */
  .directive('mwFilterableSearch', function ($timeout, Loading) {
    return {
      transclude: true,
      scope: {
        filterable: '=',
        mwDisabled: '=',
        property: '@'
//        loading: '='
      },
      templateUrl: 'modules/ui/templates/mwComponents/mwFilterableSearch.html',
      link: function (scope) {
        scope.model = scope.filterable.properties[scope.property];
        scope.inputLength = 0;

        var timeout;

        var search = function () {
          return scope.filterable.applyFilters();
        };

        var throttler = function () {
          scope.searching = true;

          $timeout.cancel(timeout);

          timeout = $timeout(function () {

            search().then(function () {
              $timeout.cancel(timeout);
              scope.searching = false;
            }, function () {
              scope.searching = false;
            });

          }, 500);
        };

        scope.search = function (event) {

          if (!event || event.keyCode === 13) {
            search();
          }
          throttler();
        };

        scope.reset = function () {
          scope.model.value = '';
          search();
        };

        Loading.registerDoneCallback(function(){
          scope.loading = false;
        });

        scope.loading = Loading.isLoading();
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwRating
 * @element span
 * @description
 *
 * Converts a rating number into stars
 *
 * @param {number | expression} mwRating rating score
 * @param {number} max the maximun number of stars
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *
 *  </doc:source>
 * </doc:example>
 */
  .directive('mwRating', function () {
    return {
      restrict: 'A',
      scope: true,
      template: '',
      link: function (scope, elm, attr) {

        elm.addClass('mw-star-rating');

        scope.stars = [];
        var starsMax = scope.$eval(attr.max);

        var buildStars = function (rating) {
          scope.stars = [];

          rating = (rating > starsMax) ? starsMax : rating;
          rating = (rating < 0) ? 0 : rating;

          for (var i = 0; i < Math.floor(rating); i++) {
            scope.stars.push({state: 'fa-star'});
          }

          if (rating - Math.floor(rating) >= 0.5) {
            scope.stars.push({state: 'fa-star-half-full'});
          }

          while (attr.max && scope.stars.length < starsMax) {
            scope.stars.push({state: 'fa-star-o'});
          }
        };

        attr.$observe('mwRating', function (value) {
          buildStars(scope.$eval(value));
        });

      }
    };
  })

  .directive('mwButtonHelp', function (i18n) {
    return {
      restrict: 'A',
      scope: true,
      link: function (scope, elm) {
        var popup;
        elm.addClass('mwButtonHelp');
        var helpIcon = angular.element('
').addClass('help-icon glyphicon glyphicon-question-sign');
        elm.prepend(helpIcon);

        helpIcon.hover(function () {
          buildPopup();
          var targetOffset = angular.element(this).offset();
          angular.element('body').append(popup);
          popup.css('top', targetOffset.top - (popup.height() / 2) + 10 - angular.element(document).scrollTop());
          popup.css('left', targetOffset.left + 40);
        }, function () {
          angular.element('body > .mwButtonPopover').remove();
        });

        var buildPopup = function () {
          popup = angular.element('
' + scope.helpText + '

').addClass('mwButtonPopover popover');
          angular.forEach(scope.hintsToShow, function (hint) {
            popup.find('ul').append('
' + hint.text + '
');
          });
        };

        scope.$watch('hintsToShow', function (newVal) {
          if (newVal.length) {
            helpIcon.show();
          } else {
            helpIcon.hide();
          }
        });

        scope.$on('$destroy', function () {
          if (popup) {
            popup.remove();
          }
        });
      },
      controller: function ($scope) {
        $scope.registeredHints = [];
        $scope.hintsToShow = [];
        $scope.helpText = i18n.get('common.buttonHelp');
        $scope.$on('i18n:localeChanged', function () {
          $scope.helpText = i18n.get('common.buttonHelp');
        });

        var showHelp = function () {
          $scope.hintsToShow = [];
          angular.forEach($scope.registeredHints, function (registered) {
            if (registered.condition) {
              $scope.hintsToShow.push(registered);
            }
          });
        };

        //check if any condition changes
        this.register = function (registered) {
          $scope.$watch(function () {
            return registered.condition;
          }, showHelp);
          $scope.registeredHints.push(registered);
        };

      }
    };
  })

  .directive('mwButtonHelpCondition', function () {
    return {
      restrict: 'A',
      require: '^mwButtonHelp',
      scope: {
        condition: '=mwButtonHelpCondition',
        text: '@mwButtonHelpText'
      },
      link: function (scope, elm, attr, ctrl) {
        ctrl.register(scope);
      }
    };
  })

  .directive('mwOptionGroup', function () {
    return {
      scope: {
        title: '@',
        description: '@'
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwOptionGroup.html',
      link: function (scope, el) {
        scope.randomId = _.uniqueId('option_group_');
        el.find('input').attr('id', scope.randomId);
      }

    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwToggle
 * @element span
 * @description
 *
 * Displays a toggle button to toggle a boolean value
 *
 * @param {expression} mwModel model
 * @param {function} mwChange the function which should be executed when the value has changed
 *
 */
  .directive('mwToggle', function () {
    return {
      scope: {
        mwModel:'=',
        mwDisabled: '=',
        mwChange:'&'
      },
      replace:true,
      templateUrl: 'modules/ui/templates/mwComponents/mwToggle.html',
      link: function (scope) {

        scope.toggle = function(value){
          if(scope.mwModel !== value){
            scope.mwModel = !scope.mwModel;
            scope.mwChange({value: scope.mwModel});
          }
        };
      }
    };
  });

<commit_msg>changed style of initial loading indicator @MDM-3678 // renamed ic_list_noIcon into logo-grey.png and logo_login into logo-login.png<commit_after>'use strict';

angular.module('mwComponents', [])

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwPanel
 * @element div
 * @description
 *
 * Wrapper directive for {@link http://getbootstrap.com/components/#panels Bootstraps Panel}.
 *
 * @param {string} mwPanel Panel title
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *      Panel content
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwPanel', function () {
    return {
      restrict: 'A',
      replace: true,
      require: '^?dashboardModule',
      scope: {
        title: '@mwPanel'
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwPanel.html',
      link: function(scope, elm, attr, ctrl){
        if(ctrl){
          scope.isDashboardModule = true;
          scope.closeModule = ctrl.closeModule;
        }
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwSortIndicator
 * @element span
 * @description
 *
 * Displays a sort indicator. Arrow up when sort is active and not reversed arrow down vise versa.
 *
 * @param {boolean} isActive display an arrow up or down when true otherwise an up and down arrow
 * @param {boolean} isReversed display an arrow up or down
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwSortIndicator', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: {
        isActive: '=',
        isReversed: '='
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwSortIndicator.html'
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwAlert
 * @element div
 * @description
 *
 * Wrapper directive for {@link http://getbootstrap.com/components/#alerts Bootstraps Alert}.
 *
 * @param {string} mwAlert Alert type. Can be one of the following:
 *
 * - warning
 * - danger
 * - success
 * - info
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *      Alert content
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwAlert', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: {
        type: '@mwAlert'
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwAlert.html'
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwHeader
 * @element div
 * @description
 *
 * Header bar for content pages.
 *
 * @param {string} title Header title
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *

 *      Header content, Buttons etc...
 *

 *  </doc:source>
 * </doc:example>
 */
  .directive('mwHeader', function ($location, $route) {
    return {
      transclude: true,
      scope: {
        title: '@',
        url: '@',
        showBackButton: '@',
        warningText: '@',
        warningCondition: '='
      },
      templateUrl: 'modules/ui/templates/mwComponents/mwHeader.html',
      link: function (scope, el, attrs, ctrl, $transclude) {

        $transclude(function (clone) {
          if ((!clone || clone.length === 0) && !scope.showBackButton) {
            el.find('.navbar-header').addClass('no-buttons');
          }
        });

        scope.refresh = function () {
          $route.reload();
        };

        scope.back = function () {
          if (attrs.url) {
            $location.path(attrs.url);
          } else {
            window.history.back();
          }
        };

        if (scope.warningText) {
          el.find('.header-popover').popover({
            trigger: 'hover',
            placement: 'bottom',
            container: el.find('.popover-container')
          });
        }
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwIcon
 * @element span
 * @description
 *
 * Wrapper for bootstrap glyphicons.
 *
 * @param {string} mwIcon Glyphicon class suffix. Example suffix for 'glyphicon glyphicon-search' is 'search'
 * @param {string} tooltip Optional string which will be displayed as a tooltip when hovering over the icon
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *
 *
 *  </doc:source>
 * </doc:example>
 */
  .directive('mwIcon', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: { mwIcon: '@'},
      template: function (elm, attr) {
        var isBootstrap = angular.isArray(attr.mwIcon.match(/^fa-/));
        if (isBootstrap) {
          return '';
        } else {
          return '';
        }
      },
      link: function (scope, el, attr) {
        if (attr.tooltip) {
          el.popover({
            trigger: 'hover',
            placement: 'bottom',
            content: attr.tooltip,
            container: 'body'
          });

          attr.$observe('tooltip', function (newVal) {
            el.popover('destroy');
            el.popover({
              trigger: 'hover',
              placement: 'bottom',
              content: newVal,
              container: 'body'
            });
          });
        }

      }
    };
  })

/**
 * @ngdoc directive
 * @name Relution.Common.directive:rlnTooltip
 * @element span
 *
 * @description
 * Creates a tooltip element using Bootstraps popover component.
 *
 * @param {String} mwTooltip Content of the tooltip
 *
 * @example

 */
  .directive('mwTooltip', function () {
    return {
      restrict: 'A',
      scope: {
        text: '@mwTooltip'
      },
      template: '',
      compile: function (elm, attr) {
        if (attr.mwTooltipIcon) {
          elm.find('span').attr('mw-icon', attr.mwTooltipIcon);
        }
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwBadge
 * @element span
 * @description
 *
 * Wrapper for bootstrap labels.
 *
 * @param {string} mwBadge label class suffix. Example: suffix for 'label label-info' is 'search'
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *
 *  </doc:source>
 * </doc:example>
 */
  .directive('mwBadge', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: { mwBadge: '@' },
      transclude: true,
      template: ''
    };
  })

  .directive('mwEmptyState', function () {
    return {
      restrict: 'A',
      replace: true,
      scope: { mwBadge: '@' },
      transclude: true,
      template: '

'
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwFilterableSearch
 * @element div
 * @description
 *
 * Creates a search field to filter by in the sidebar. Search is triggered on keypress 'enter'.
 *
 * @param {filterable} filterable Filterable instance.
 * @param {expression} disabled If expression evaluates to true, input is disabled.
 * @param {string} property The name of the property on which the filtering should happen.
 */
  .directive('mwFilterableSearch', function ($timeout, Loading) {
    return {
      transclude: true,
      scope: {
        filterable: '=',
        mwDisabled: '=',
        property: '@'
//        loading: '='
      },
      templateUrl: 'modules/ui/templates/mwComponents/mwFilterableSearch.html',
      link: function (scope) {
        scope.model = scope.filterable.properties[scope.property];
        scope.inputLength = 0;

        var timeout;

        var search = function () {
          return scope.filterable.applyFilters();
        };

        var throttler = function () {
          scope.searching = true;

          $timeout.cancel(timeout);

          timeout = $timeout(function () {

            search().then(function () {
              $timeout.cancel(timeout);
              scope.searching = false;
            }, function () {
              scope.searching = false;
            });

          }, 500);
        };

        scope.search = function (event) {

          if (!event || event.keyCode === 13) {
            search();
          }
          throttler();
        };

        scope.reset = function () {
          scope.model.value = '';
          search();
        };

        Loading.registerDoneCallback(function(){
          scope.loading = false;
        });

        scope.loading = Loading.isLoading();
      }
    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwRating
 * @element span
 * @description
 *
 * Converts a rating number into stars
 *
 * @param {number | expression} mwRating rating score
 * @param {number} max the maximun number of stars
 *
 * @example
 * <doc:example>
 *  <doc:source>
 *
 *  </doc:source>
 * </doc:example>
 */
  .directive('mwRating', function () {
    return {
      restrict: 'A',
      scope: true,
      template: '',
      link: function (scope, elm, attr) {

        elm.addClass('mw-star-rating');

        scope.stars = [];
        var starsMax = scope.$eval(attr.max);

        var buildStars = function (rating) {
          scope.stars = [];

          rating = (rating > starsMax) ? starsMax : rating;
          rating = (rating < 0) ? 0 : rating;

          for (var i = 0; i < Math.floor(rating); i++) {
            scope.stars.push({state: 'fa-star'});
          }

          if (rating - Math.floor(rating) >= 0.5) {
            scope.stars.push({state: 'fa-star-half-full'});
          }

          while (attr.max && scope.stars.length < starsMax) {
            scope.stars.push({state: 'fa-star-o'});
          }
        };

        attr.$observe('mwRating', function (value) {
          buildStars(scope.$eval(value));
        });

      }
    };
  })

  .directive('mwButtonHelp', function (i18n) {
    return {
      restrict: 'A',
      scope: true,
      link: function (scope, elm) {
        var popup;
        elm.addClass('mwButtonHelp');
        var helpIcon = angular.element('
').addClass('help-icon glyphicon glyphicon-question-sign');
        elm.prepend(helpIcon);

        helpIcon.hover(function () {
          buildPopup();
          var targetOffset = angular.element(this).offset();
          angular.element('body').append(popup);
          popup.css('top', targetOffset.top - (popup.height() / 2) + 10 - angular.element(document).scrollTop());
          popup.css('left', targetOffset.left + 40);
        }, function () {
          angular.element('body > .mwButtonPopover').remove();
        });

        var buildPopup = function () {
          popup = angular.element('
' + scope.helpText + '

').addClass('mwButtonPopover popover');
          angular.forEach(scope.hintsToShow, function (hint) {
            popup.find('ul').append('
' + hint.text + '
');
          });
        };

        scope.$watch('hintsToShow', function (newVal) {
          if (newVal.length) {
            helpIcon.show();
          } else {
            helpIcon.hide();
          }
        });

        scope.$on('$destroy', function () {
          if (popup) {
            popup.remove();
          }
        });
      },
      controller: function ($scope) {
        $scope.registeredHints = [];
        $scope.hintsToShow = [];
        $scope.helpText = i18n.get('common.buttonHelp');
        $scope.$on('i18n:localeChanged', function () {
          $scope.helpText = i18n.get('common.buttonHelp');
        });

        var showHelp = function () {
          $scope.hintsToShow = [];
          angular.forEach($scope.registeredHints, function (registered) {
            if (registered.condition) {
              $scope.hintsToShow.push(registered);
            }
          });
        };

        //check if any condition changes
        this.register = function (registered) {
          $scope.$watch(function () {
            return registered.condition;
          }, showHelp);
          $scope.registeredHints.push(registered);
        };

      }
    };
  })

  .directive('mwButtonHelpCondition', function () {
    return {
      restrict: 'A',
      require: '^mwButtonHelp',
      scope: {
        condition: '=mwButtonHelpCondition',
        text: '@mwButtonHelpText'
      },
      link: function (scope, elm, attr, ctrl) {
        ctrl.register(scope);
      }
    };
  })

  .directive('mwOptionGroup', function () {
    return {
      scope: {
        title: '@',
        description: '@'
      },
      transclude: true,
      templateUrl: 'modules/ui/templates/mwComponents/mwOptionGroup.html',
      link: function (scope, el) {
        scope.randomId = _.uniqueId('option_group_');
        el.find('input').attr('id', scope.randomId);
      }

    };
  })

/**
 * @ngdoc directive
 * @name mwComponents.directive:mwToggle
 * @element span
 * @description
 *
 * Displays a toggle button to toggle a boolean value
 *
 * @param {expression} mwModel model
 * @param {function} mwChange the function which should be executed when the value has changed
 *
 */
  .directive('mwToggle', function () {
    return {
      scope: {
        mwModel:'=',
        mwDisabled: '=',
        mwChange:'&'
      },
      replace:true,
      templateUrl: 'modules/ui/templates/mwComponents/mwToggle.html',
      link: function (scope) {

        scope.toggle = function(value){
          if(scope.mwModel !== value){
            scope.mwModel = !scope.mwModel;
            scope.mwChange({value: scope.mwModel});
          }
        };
      }
    };
  });

<|endoftext|>


<commit_before>var ActionheroClient = function(options, client){

  var self = this;

  self.callbacks = {};
  self.id = null;
  self.events = {};
  self.rooms = [];
  self.state = 'disconnected';

  self.options = self.defaults();
  for(var i in options){
    self.options[i] = options[i];
  }

  if(client){
    self.client = client;
  }
}

if(typeof Primus === 'undefined'){
  var util = require('util');
  var EventEmitter = require('events').EventEmitter;
  util.inherits(ActionheroClient, EventEmitter);
}else{
  ActionheroClient.prototype = new Primus.EventEmitter();
}

ActionheroClient.prototype.defaults = function(){
  %%DEFAULTS%%
}

////////////////
// CONNECTION //
////////////////

ActionheroClient.prototype.connect = function(callback){
  var self = this;
  self.messageCount = 0;

  if(!self.client){
    self.client = Primus.connect(self.options.url, self.options);
  }else{
    self.client.end();
    self.client.open();
  }

  self.client.on('open', function(){
    self.configure(function(details){
      self.emit('connected');
      if(self.state === 'connected'){
        //
      }else{
        self.state = 'connected';
        if(typeof callback === 'function'){ callback(null, details); }
      }
    });
  })

  self.client.on('error', function(err){
    self.emit('error', err);
  });

  self.client.on('reconnect', function(){
    self.messageCount = 0;
    self.emit('reconnect');
  });

  self.client.on('reconnecting', function(){
    self.emit('reconnecting');
    self.state = 'reconnecting';
    self.emit('disconnected');
  });

  self.client.on('timeout', function(){
    self.state = 'timeout';
    self.emit('timeout');
  });

  self.client.on('close', function(){
    self.messageCount = 0;
    if(self.state !== 'disconnected'){
      self.state = 'disconnected';
      self.emit('disconnected');
    }
  });

  self.client.on('end', function(){
    self.messageCount = 0;
    if(self.state !== 'disconnected'){
      self.state = 'disconnected';
      self.emit('disconnected');
    }
  });

  self.client.on('data', function(data){
    self.handleMessage(data);
  });
}

ActionheroClient.prototype.configure = function(callback){
  var self = this;

  self.rooms.forEach(function(room){
    self.send({event: 'roomAdd', room: room});
  });

  self.detailsView(function(details){
    self.id          = details.data.id;
    self.fingerprint = details.data.fingerprint;
    self.rooms       = details.data.rooms;
    callback(details);
  });
}

///////////////
// MESSAGING //
///////////////

ActionheroClient.prototype.send = function(args, callback){
  // primus will buffer messages when not connected
  var self = this;
  self.messageCount++;
  if(typeof callback === 'function'){
    self.callbacks[self.messageCount] = callback;
  }
  self.client.write(args);
}

ActionheroClient.prototype.handleMessage = function(message){
  var self = this;
  self.emit('message', message);
  if(message.context === 'response'){
    if(typeof self.callbacks[message.messageCount] === 'function'){
      self.callbacks[message.messageCount](message);
    }
    delete self.callbacks[message.messageCount];
  } else if(message.context === 'user'){
    self.emit('say', message);
  } else if(message.context === 'alert'){
    self.emit('alert', message);
  } else if(message.welcome && message.context === 'api'){
    self.welcomeMessage = message.welcome;
    self.emit('welcome', message);
  } else if(message.context === 'api'){
    self.emit('api', message);
  }
}

/////////////
// ACTIONS //
/////////////

ActionheroClient.prototype.action = function(action, params, callback){
  if(!callback && typeof params === 'function'){
    callback = params;
    params = null;
  }
  if(!params){ params = {}; }
  params.action = action;

  if(this.state !== 'connected'){
    this.actionWeb(params, callback);
  }else{
    this.actionWebSocket(params, callback);
  }
}

ActionheroClient.prototype.actionWeb = function(params, callback) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function () {
    var response;
    if(xmlhttp.readyState === 4) {
      if(xmlhttp.status === 200) {
        response = JSON.parse(xmlhttp.responseText);
      }else{
        try{
          response = JSON.parse(xmlhttp.responseText);
        }catch(e){
          response = { error: {statusText: xmlhttp.statusText, responseText: xmlhttp.responseText} };
        }
      }
      callback(response);
    }
  };

  var method = params.httpMethod || 'POST';
  var url = this.options.url + this.options.apiPath + '?action=' + params.action;
  xmlhttp.open(method, url, true);
  xmlhttp.setRequestHeader('Content-Type', 'application/json');
  xmlhttp.send(JSON.stringify(params));
}

ActionheroClient.prototype.actionWebSocket = function(params, callback){
  this.send({event: 'action',params: params}, callback);
}

//////////////
// COMMANDS //
//////////////

ActionheroClient.prototype.say = function(room, message, callback){
  this.send({event: 'say', room: room, message: message}, callback);
}

ActionheroClient.prototype.file = function(file, callback){
  this.send({event: 'file', file: file}, callback);
}

ActionheroClient.prototype.detailsView = function(callback){
  this.send({event: 'detailsView'}, callback);
}

ActionheroClient.prototype.roomView = function(room, callback){
  this.send({event: 'roomView', room: room}, callback);
}

ActionheroClient.prototype.roomAdd = function(room, callback){
  var self = this;
  self.send({event: 'roomAdd', room: room}, function(data){
    self.configure(function(){
      if(typeof callback === 'function'){ callback(data); }
    });
  });
}

ActionheroClient.prototype.roomLeave = function(room, callback){
  var self = this;
  var index = self.rooms.indexOf(room);
  if(index > -1){ self.rooms.splice(index, 1); }
  this.send({event: 'roomLeave', room: room}, function(data){
    self.configure(function(){
      if(typeof callback === 'function'){ callback(data); }
    });
  });
}

ActionheroClient.prototype.documentation = function(callback){
  this.send({event: 'documentation'}, callback);
}

ActionheroClient.prototype.disconnect = function(){
  this.state = 'disconnected';
  this.client.end();
  this.emit('disconnected');
}

// depricated lowercase name
var actionheroClient = ActionheroClient;
<commit_msg>when manually reconnecting to ws, destroy and create a new primus transport<commit_after>var ActionheroClient = function(options, client){

  var self = this;

  self.callbacks = {};
  self.id = null;
  self.events = {};
  self.rooms = [];
  self.state = 'disconnected';

  self.options = self.defaults();
  for(var i in options){
    self.options[i] = options[i];
  }

  if(client){
    self.externalClient = true;
    self.client = client;
  }
}

if(typeof Primus === 'undefined'){
  var util = require('util');
  var EventEmitter = require('events').EventEmitter;
  util.inherits(ActionheroClient, EventEmitter);
}else{
  ActionheroClient.prototype = new Primus.EventEmitter();
}

ActionheroClient.prototype.defaults = function(){
  %%DEFAULTS%%
}

////////////////
// CONNECTION //
////////////////

ActionheroClient.prototype.connect = function(callback){
  var self = this;
  self.messageCount = 0;

  if(self.client && self.externalClient !== true){
    self.client.end();
    self.client.removeAllListeners();
    delete self.client;
  }
  if(self.client && self.externalClient === true){
    self.client.end();
    self.client.open();
  }else{
    self.client = Primus.connect(self.options.url, self.options);
  }

  self.client.on('open', function(){
    self.configure(function(details){
      self.emit('connected');
      if(self.state === 'connected'){
        //
      }else{
        self.state = 'connected';
        if(typeof callback === 'function'){ callback(null, details); }
      }
    });
  })

  self.client.on('error', function(err){
    self.emit('error', err);
  });

  self.client.on('reconnect', function(){
    self.messageCount = 0;
    self.emit('reconnect');
  });

  self.client.on('reconnecting', function(){
    self.emit('reconnecting');
    self.state = 'reconnecting';
    self.emit('disconnected');
  });

  self.client.on('timeout', function(){
    self.state = 'timeout';
    self.emit('timeout');
  });

  self.client.on('close', function(){
    self.messageCount = 0;
    if(self.state !== 'disconnected'){
      self.state = 'disconnected';
      self.emit('disconnected');
    }
  });

  self.client.on('end', function(){
    self.messageCount = 0;
    if(self.state !== 'disconnected'){
      self.state = 'disconnected';
      self.emit('disconnected');
    }
  });

  self.client.on('data', function(data){
    self.handleMessage(data);
  });
}

ActionheroClient.prototype.configure = function(callback){
  var self = this;

  self.rooms.forEach(function(room){
    self.send({event: 'roomAdd', room: room});
  });

  self.detailsView(function(details){
    self.id          = details.data.id;
    self.fingerprint = details.data.fingerprint;
    self.rooms       = details.data.rooms;
    callback(details);
  });
}

///////////////
// MESSAGING //
///////////////

ActionheroClient.prototype.send = function(args, callback){
  // primus will buffer messages when not connected
  var self = this;
  self.messageCount++;
  if(typeof callback === 'function'){
    self.callbacks[self.messageCount] = callback;
  }
  self.client.write(args);
}

ActionheroClient.prototype.handleMessage = function(message){
  var self = this;
  self.emit('message', message);
  if(message.context === 'response'){
    if(typeof self.callbacks[message.messageCount] === 'function'){
      self.callbacks[message.messageCount](message);
    }
    delete self.callbacks[message.messageCount];
  } else if(message.context === 'user'){
    self.emit('say', message);
  } else if(message.context === 'alert'){
    self.emit('alert', message);
  } else if(message.welcome && message.context === 'api'){
    self.welcomeMessage = message.welcome;
    self.emit('welcome', message);
  } else if(message.context === 'api'){
    self.emit('api', message);
  }
}

/////////////
// ACTIONS //
/////////////

ActionheroClient.prototype.action = function(action, params, callback){
  if(!callback && typeof params === 'function'){
    callback = params;
    params = null;
  }
  if(!params){ params = {}; }
  params.action = action;

  if(this.state !== 'connected'){
    this.actionWeb(params, callback);
  }else{
    this.actionWebSocket(params, callback);
  }
}

ActionheroClient.prototype.actionWeb = function(params, callback) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function () {
    var response;
    if(xmlhttp.readyState === 4) {
      if(xmlhttp.status === 200) {
        response = JSON.parse(xmlhttp.responseText);
      }else{
        try{
          response = JSON.parse(xmlhttp.responseText);
        }catch(e){
          response = { error: {statusText: xmlhttp.statusText, responseText: xmlhttp.responseText} };
        }
      }
      callback(response);
    }
  };

  var method = params.httpMethod || 'POST';
  var url = this.options.url + this.options.apiPath + '?action=' + params.action;
  xmlhttp.open(method, url, true);
  xmlhttp.setRequestHeader('Content-Type', 'application/json');
  xmlhttp.send(JSON.stringify(params));
}

ActionheroClient.prototype.actionWebSocket = function(params, callback){
  this.send({event: 'action',params: params}, callback);
}

//////////////
// COMMANDS //
//////////////

ActionheroClient.prototype.say = function(room, message, callback){
  this.send({event: 'say', room: room, message: message}, callback);
}

ActionheroClient.prototype.file = function(file, callback){
  this.send({event: 'file', file: file}, callback);
}

ActionheroClient.prototype.detailsView = function(callback){
  this.send({event: 'detailsView'}, callback);
}

ActionheroClient.prototype.roomView = function(room, callback){
  this.send({event: 'roomView', room: room}, callback);
}

ActionheroClient.prototype.roomAdd = function(room, callback){
  var self = this;
  self.send({event: 'roomAdd', room: room}, function(data){
    self.configure(function(){
      if(typeof callback === 'function'){ callback(data); }
    });
  });
}

ActionheroClient.prototype.roomLeave = function(room, callback){
  var self = this;
  var index = self.rooms.indexOf(room);
  if(index > -1){ self.rooms.splice(index, 1); }
  this.send({event: 'roomLeave', room: room}, function(data){
    self.configure(function(){
      if(typeof callback === 'function'){ callback(data); }
    });
  });
}

ActionheroClient.prototype.documentation = function(callback){
  this.send({event: 'documentation'}, callback);
}

ActionheroClient.prototype.disconnect = function(){
  this.state = 'disconnected';
  this.client.end();
  this.emit('disconnected');
}

// depricated lowercase name
var actionheroClient = ActionheroClient;
<|endoftext|>


<commit_before>(function () {
	var CameleonWindow = function CameleonWindow() {
		Webos.Observable.call(this);

		this.bind('translationsloaded', function() {
			var that = this, t = this._translations;

			this._window = $.w.window.main({
				title: t.get('Cameleon interface switcher'),
				icon: new W.Icon('actions/interface'),
				width: 400,
				resizable: false,
				dialog: true
			});

			var content = this._window.window('content');

			var desc = $.w.label(t.get('To switch between interfaces, choose one and click OK :')).appendTo(content);
			this._uisList = $.w.list().appendTo(content);
			var btnContainer = $.w.buttonContainer().appendTo(content);
			var submitBtn = $.w.button(t.get('OK')).click(function() {
				that._launchUI(that._selectedUI);
			}).appendTo(btnContainer);

			this._init();

			this._window.window('open');
		});

		Webos.TranslatedLibrary.call(this);
	};
	CameleonWindow.prototype = {
		_translationsName: 'cameleon',
		_uisList: $(),
		_selectedUI: null,

		_init: function () {
			var that = this;

			this._window.window('loading', true);

			Webos.UserInterface.getList(function (list) {
				for (var i = 0; i < list.length; i++) {
					(function(ui) {
						var $item = $.w.listItem([(ui.get('displayname') || ui.get('name'))]);

						$item.bind('listitemselect', function() {
							that._selectedUI = ui;
						}).bind('listitemunselect', function() {
							that._selectedUI = null;
						});

						that._uisList.list('content').append($item);
					})(list[i]);
				}

				that._window.window('loading', false);
			});
		},
		_launchUI: function(ui) {
			if (!ui) {
				return;
			}

			this._window.window('loading', true);

			Webos.UserInterface.load(ui.get('name'));
		}
	};

	Webos.inherit(CameleonWindow, Webos.Observable);
	Webos.inherit(CameleonWindow, Webos.TranslatedLibrary);

	window.CameleonWindow = CameleonWindow;
})();<commit_msg>Fixes main window in cameleon.<commit_after>(function () {
	var CameleonWindow = function CameleonWindow() {
		Webos.Observable.call(this);

		this._window = $.w.window.main({
			title: 'Cameleon interface switcher',
			icon: new W.Icon('actions/interface'),
			width: 400,
			resizable: false,
			dialog: true
		});

		this.bind('translationsloaded', function() {
			var that = this, t = this._translations;

			this._window.window('option', 'title', t.get('Cameleon interface switcher'));

			var content = this._window.window('content');

			var desc = $.w.label(t.get('To switch between interfaces, choose one and click OK :')).appendTo(content);
			this._uisList = $.w.list().appendTo(content);
			var btnContainer = $.w.buttonContainer().appendTo(content);
			var submitBtn = $.w.button(t.get('OK')).click(function() {
				that._launchUI(that._selectedUI);
			}).appendTo(btnContainer);

			this._init();

			this._window.window('open');
		});

		Webos.TranslatedLibrary.call(this);
	};
	CameleonWindow.prototype = {
		_translationsName: 'cameleon',
		_uisList: $(),
		_selectedUI: null,

		_init: function () {
			var that = this;

			this._window.window('loading', true);

			Webos.UserInterface.getList(function (list) {
				for (var i = 0; i < list.length; i++) {
					(function(ui) {
						var $item = $.w.listItem([(ui.get('displayname') || ui.get('name'))]);

						$item.bind('listitemselect', function() {
							that._selectedUI = ui;
						}).bind('listitemunselect', function() {
							that._selectedUI = null;
						});

						that._uisList.list('content').append($item);
					})(list[i]);
				}

				that._window.window('loading', false);
			});
		},
		_launchUI: function(ui) {
			if (!ui) {
				return;
			}

			this._window.window('loading', true);

			Webos.UserInterface.load(ui.get('name'));
		}
	};

	Webos.inherit(CameleonWindow, Webos.Observable);
	Webos.inherit(CameleonWindow, Webos.TranslatedLibrary);

	window.CameleonWindow = CameleonWindow;
})();<|endoftext|>