<commit_before>define(function (require, exports, module) {
    var itemview = require('./itemview');
    var view = require('./view');
    var layouts = require('./layoutviews');
    var collectionview = require('./collections-views');
    var collectionlayout = require('./collections-layouts');
    var utils = require('./utils');
    var regions = require('./region');

    var views = {
        View: view.FamousView,

        layouts: {
            LayoutView: layouts.FamousLayoutView
        },

        items: {
            ItemView: itemview.FamousItemView
        },

        collections: {
            CollectionView: collectionview.FamousCollectionView,
            horizontalLayout: collectionlayout.horizontalLayout,
            verticalLayout: collectionlayout.verticalLayout
        }
    };

    // shortcuts

    exports.View = view.FamousView;
    exports.ItemView = itemview.FamousItemView;
    exports.LayoutView = layouts.FamousLayoutView;
    exports.CollectionView = collectionview.FamousCollectionView;
    exports.Region = regions.FamousRegion;

    // fully qualified -
    exports.utils = utils;
    exports.views  = views;
});
<commit_msg>Update init.js<commit_after>define(function (require, exports, module) {
    var itemview = require('./itemview');
    var view = require('./view');
    var layouts = require('./layoutviews');
    var collectionview = require('./collections-views');
    var collectionlayout = require('./collections-layouts');
    var utils = require('./utils');
    var regions = require('./region');

    var views = {
        View: view.FamousView,

        layouts: {
            LayoutView: layouts.FamousLayoutView
        },

        items: {
            ItemView: itemview.FamousItemView
        },

        collections: {
            CollectionView: collectionview.FamousCollectionView,
            horizontalLayout: collectionlayout.horizontalLayout,
            verticalLayout: collectionlayout.verticalLayout
        }
    };

    // shortcuts
    exports.View = view.FamousView;
    exports.ItemView = itemview.FamousItemView;
    exports.LayoutView = layouts.FamousLayoutView;
    exports.CollectionView = collectionview.FamousCollectionView;
    exports.Region = regions.FamousRegion;

    // fully qualified -
    exports.utils = utils;
    exports.views  = views;
});
<|endoftext|>


<commit_before>(function() {
    "use strict";
    var swf, PlayerDivID = "TimbreFlashPlayerDiv";
    var isEnabled = getFlashPlayerVersion(0) >= 10;

    function TimbreFlashPlayer(sys, opts) {
        var timerId = 0;

        if (!document.getElementById(PlayerDivID)) {
            if (!isEnabled) {
                console.warn("TimbreFlashPlayer requires Flash Player 10.");
                return;
            }
            initialize(opts || {});
        }

        this.maxSamplerate     = 44100;
        this.defaultSamplerate = 44100;
        this.env = "flash";

        this.play = function() {
            var onaudioprocess;
            var interleaved = new Array(sys.streamsize * sys.channels);
            var streammsec  = sys.streammsec;
            var written = 0;
            var writtenIncr = sys.streamsize / sys.samplerate * 1000;
            var start = Date.now();

            onaudioprocess = function() {
                if (written > Date.now() - start) {
                    return;
                }
                var inL = sys.strmL;
                var inR = sys.strmR;
                var i = interleaved.length;
                var j = inL.length;
                sys.process();
                while (j--) {
                    interleaved[--i] = (inR[j] * 32768)|0;
                    interleaved[--i] = (inL[j] * 32768)|0;
                }
                swf.writeAudio(interleaved.join(" "));
                written += writtenIncr;
            };

            swf.setup(sys.channels, sys.samplerate);
            timerId = setInterval(onaudioprocess, streammsec);
        };

        this.pause = function() {
            if (timerId !== 0) {
                swf.cancel();
                clearInterval(timerId);
                timerId = 0;
            }
        };

    }

    function initialize(opts) {
        var o, p;
        var swfSrc  = opts.src || "TimbreFlashPlayer.swf";
        var swfName = swfSrc + "?" + (+new Date());
        var swfId   = opts.id  || "TimbreFlashPlayer";
        var div = document.createElement("div");
        div.id = PlayerDivID;
        div.style.display = "inline";
        div.width  = 1;
        div.height = 1;
        document.body.appendChild(div);

        if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
            // ns
            o = document.createElement("object");
            o.id = swfId;
            o.classid = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
            o.width  = 1;
            o.height = 1;
            o.setAttribute("data", swfName);
            o.setAttribute("type", "application/x-shockwave-flash");
            p = document.createElement("param");
            p.setAttribute("name", "allowScriptAccess");
            p.setAttribute("value", "always");
            o.appendChild(p);
            div.appendChild(o);
        } else {
            // ie
            o = '<object id="' + swfId + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1">';
            o += '<param name="movie" value="' + swfName + '" />';
            o += '<param name="bgcolor" value="#FFFFFF" />';
            o += '<param name="quality" value="high" />';
            o += '<param name="allowScriptAccess" value="always" />';
            o += '</object>';
            div.innerHTML = o;
        }
        swf = document[swfId];
    }

    // get Flash player version numbers. argument requires sub numbers.
    function getFlashPlayerVersion(subs) {
        try {
            return (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) ?
                navigator.plugins["Shockwave Flash"].description.match(/([0-9]+)/)[subs] :
                (new ActiveXObject("ShockwaveFlash.ShockwaveFlash")).GetVariable("$version").match(/([0-9]+)/)[subs];
        } catch (e) {
            return -1;
        }
    }

    Object.defineProperties(TimbreFlashPlayer, {
        isEnabled: {
            get: function() {
                return isEnabled;
            }
        }
    });

    if (window.timbre) {
        window.timbre.FlashPlayer = TimbreFlashPlayer;
    } else {
        window.TimbreFlashPlayer  = TimbreFlashPlayer;
    }
})();
<commit_msg>fix: jsHint<commit_after>(function() {
    "use strict";

    // get Flash player version numbers. argument requires sub numbers.
    function getFlashPlayerVersion(subs) {
        try {
            return (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) ?
                navigator.plugins["Shockwave Flash"].description.match(/([0-9]+)/)[subs] :
                (new ActiveXObject("ShockwaveFlash.ShockwaveFlash")).GetVariable("$version").match(/([0-9]+)/)[subs];
        } catch (e) {
            return -1;
        }
    }

    var swf, PlayerDivID = "TimbreFlashPlayerDiv";
    var isEnabled = getFlashPlayerVersion(0) >= 10;

    function TimbreFlashPlayer(sys, opts) {
        var timerId = 0;

        if (!document.getElementById(PlayerDivID)) {
            if (!isEnabled) {
                console.warn("TimbreFlashPlayer requires Flash Player 10.");
                return;
            }
            initialize(opts || {});
        }

        this.maxSamplerate     = 44100;
        this.defaultSamplerate = 44100;
        this.env = "flash";

        this.play = function() {
            var onaudioprocess;
            var interleaved = new Array(sys.streamsize * sys.channels);
            var streammsec  = sys.streammsec;
            var written = 0;
            var writtenIncr = sys.streamsize / sys.samplerate * 1000;
            var start = Date.now();

            onaudioprocess = function() {
                if (written > Date.now() - start) {
                    return;
                }
                var inL = sys.strmL;
                var inR = sys.strmR;
                var i = interleaved.length;
                var j = inL.length;
                sys.process();
                while (j--) {
                    interleaved[--i] = (inR[j] * 32768)|0;
                    interleaved[--i] = (inL[j] * 32768)|0;
                }
                swf.writeAudio(interleaved.join(" "));
                written += writtenIncr;
            };

            swf.setup(sys.channels, sys.samplerate);
            timerId = setInterval(onaudioprocess, streammsec);
        };

        this.pause = function() {
            if (timerId !== 0) {
                swf.cancel();
                clearInterval(timerId);
                timerId = 0;
            }
        };

    }

    function initialize(opts) {
        var o, p;
        var swfSrc  = opts.src || "TimbreFlashPlayer.swf";
        var swfName = swfSrc + "?" + (+new Date());
        var swfId   = opts.id  || "TimbreFlashPlayer";
        var div = document.createElement("div");
        div.id = PlayerDivID;
        div.style.display = "inline";
        div.width  = 1;
        div.height = 1;
        document.body.appendChild(div);

        if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
            // ns
            o = document.createElement("object");
            o.id = swfId;
            o.classid = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
            o.width  = 1;
            o.height = 1;
            o.setAttribute("data", swfName);
            o.setAttribute("type", "application/x-shockwave-flash");
            p = document.createElement("param");
            p.setAttribute("name", "allowScriptAccess");
            p.setAttribute("value", "always");
            o.appendChild(p);
            div.appendChild(o);
        } else {
            // ie
            o = '<object id="' + swfId + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1">';
            o += '<param name="movie" value="' + swfName + '" />';
            o += '<param name="bgcolor" value="#FFFFFF" />';
            o += '<param name="quality" value="high" />';
            o += '<param name="allowScriptAccess" value="always" />';
            o += '</object>';
            div.innerHTML = o;
        }
        swf = document[swfId];
    }

    Object.defineProperties(TimbreFlashPlayer, {
        isEnabled: {
            get: function() {
                return isEnabled;
            }
        }
    });

    if (window.timbre) {
        window.timbre.FlashPlayer = TimbreFlashPlayer;
    } else {
        window.TimbreFlashPlayer  = TimbreFlashPlayer;
    }
})();
<|endoftext|>


<commit_before>/* global set_panel_html, Ajax, command_url, api */

var hyperion = {
  SID_HYPERION: "urn:otakup0pe:serviceId:Hyperion1",
  SID_SPOWER: "urn:upnp-org:serviceId:SwitchPower1",
  SID_DIMMING: "urn:upnp-org:serviceId:Dimming1",
  SID_HUEBULB: "urn:intvelt-com:serviceId:HueColors1",
  SID_VSWITCH: "urn:upnp-org:serviceId:VSwitch1"
};

function device_selection_callback(device_id) {
  var html = '';
  var device_ids = get_device_state(device_id, hyperion.SID_HYPERION, 'include_devices', 1).split(',');
  var included_devices = device_ids.map(function(id) {
    return {
      id: id,
      name: api.getRoomObject(api.getDeviceAttribute(id, 'room')).name + ' - ' + api.getDeviceAttribute(id, 'name')
    };
  });

  html += '
';
  html += '
Available Devices		Included Devices	';
  html += '
<select multiple size="10" id="available_devices">';
  for ( var i_devices = 0; i_devices < jsonp.ud.devices.length ; i_devices++ ) {
    var this_device = jsonp.ud.devices[i_devices];
    var this_id = parseInt(this_device.id, 10);
    // check to see if it's an included device
    var valid = true;
    for ( var i_check = 0 ; i_check < device_ids.length ; i_check++ ) {
      if ( parseInt(device_ids[i_check], 10) == this_id ) {
        valid = false;
        break;
      }
    }
    if ( valid ) {
      var these_services = device_services(this_id);
      valid = false;
      // check if it's a device we can use
      if ( these_services.length > 0 ) {
        if ( these_services.indexOf(hyperion.SID_SPOWER) >= 0 ||
             these_services.indexOf(hyperion.SID_DIMMING) >= 0 ) {
          valid = ( these_services.indexOf(hyperion.SID_HUEBULB) == -1 &&
                   ! is_hyperion(this_id) &&
                   these_services.indexOf(hyperion.VSWITCH == -1) );
        }
      }
    }
    if ( valid ) {
      var room = api.getRoomObject(jsonp.ud.devices[i_devices].room);
      var name = jsonp.ud.devices[i_devices].name;
      if ( room ) {
        name = room.name + ' - ' + name;
      }
      html += '<option value="' + jsonp.ud.devices[i_devices].id + '">' + name + '</option>';
    }
  }
  html += '</select>	';
  html += '';
  html += '<button type="button" onclick="add_device(' + device_id + ')">--></button>
';
  html += '<button type="button" onclick="remove_device(' + device_id + ')"><--</button>';
  html += '	';
  html += '<select multiple size="10" id="included_devices">';
  for ( var i_idevices = 0 ; i_idevices < included_devices.length ; i_idevices++ ) {
    html += '<option value="' + included_devices[i_idevices].id + '">' + included_devices[i_idevices].name + '</option>';
  }
  html += '</select>

';
  set_panel_html(html);
}

function time_settings_callback(device_id) {
  var html = '';
  html += 'Daytime starts at <select id="morning_hour" onchange="save_hour(' + device_id + ', \'Morning\')">';
  var morning_hour = get_device_state(device_id, hyperion.SID_HYPERION, 'MorningHour', 1);
  var morning_minute = get_device_state(device_id, hyperion.SID_HYPERION, 'MorningMinute', 1);
  var sunrise_grace = get_device_state(device_id, hyperion.SID_HYPERION, 'SunriseGrace', 1);
  for ( var i_day_hour = 0 ; i_day_hour < 24 ; i_day_hour++ ) {
    var day_hour_selected = false;
    var s_day_hour = i_day_hour.toString();
    if ( i_day_hour == morning_hour ) {
      day_hour_selected = true;
    }
    html += '<option';
    if ( day_hour_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_day_hour + '">' + s_day_hour + '</option>';
  }
  html += '</select>:<select id="morning_minute" onchange="save_minute(' + device_id + ', \'Morning\')">';
  for ( var i_day_minute = 0 ; i_day_minute < 60 ; i_day_minute++ ) {
    var day_minute_selected = false;
    var s_day_minute = i_day_minute.toString();
    if ( i_day_minute == morning_minute ) {
      day_minute_selected = true;
    }
    html += '<option';
    if ( day_minute_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_day_minute + '">' + s_day_minute + '</option>';
  }
  html += '</select> with a pre-sunrise grace period of ';
  html += '<input id="sunrise_grace" type="text" onchange="save_grace(' + device_id + ', \'Sunrise\')" value="' + sunrise_grace + '" style="width: 100px"/> seconds.';
  html += "
";
  var night_hour = get_device_state(device_id, hyperion.SID_HYPERION, 'NightHour', 1);
  var night_minute = get_device_state(device_id, hyperion.SID_HYPERION, 'NightMinute', 1);
  var sunset_grace = get_device_state(device_id, hyperion.SID_HYPERION, 'SunsetGrace', 1);
  html += 'Nighttime starts at <select id="night_hour" onchange="save_hour(' + device_id + ', \'Night\')">';
  for ( var i_night_hour = 0 ; i_night_hour < 24 ; i_night_hour++ ) {
    var night_hour_selected = false;
    var s_night_hour = i_night_hour.toString();
    if ( i_night_hour == night_hour ) {
      night_hour_selected = true;
    }
    html += '<option';
    if ( night_hour_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_night_hour + '">' + s_night_hour + '</option>';
  }
  html += '</select>:<select id="night_minute" onchange="save_minute(' + device_id + ', \'Night\');">';
  for ( var i_night_minute = 0 ; i_night_minute < 60 ; i_night_minute++ ) {
    var night_minute_selected = false;
    var s_night_minute = i_night_minute.toString();
    if ( i_night_minute == night_minute ) {
      night_minute_selected = true;
    }
    html += '<option';
    if ( night_minute_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_night_minute + '">' + s_night_minute + '</option>';
  }
  html += '</select> with a pre-sunset grace period of ';
  html += '<input id="sunset_grace" type="text" value="' + sunset_grace + '" onchange="save_grace(' + device_id + ', \'Sunset\');" style="width: 100px"/> seconds.';

  set_panel_html(html);
}

function save_hour(device_id, name)
{
  var obj = {
    'Name': name
  };
  if ( name == 'Morning' ) {
    obj.Hour = jQuery('#morning_hour').val();
  } else {
    obj.Hour = jQuery('#night_hour').val();
  }
  call_action(device_id, hyperion.SID_HYPERION, 'SetHour', obj);
}

function save_minute(device_id, name)
{
  var obj = {
    'Name': name
  };
  if ( name == 'Morning' ) {
    obj.Minute = jQuery('#morning_minute').val();
  } else {
    obj.Minute = jQuery('#night_minute').val();
  }
  call_action(device_id, hyperion.SID_HYPERION, 'SetMinute', obj);
}

function save_grace(device_id, name)
{
  var obj = {
    'Name': name
  };
  if ( name == 'Sunrise' ) {
    obj.Time = jQuery('#sunrise_grace').val();
  } else {
    obj.Time = jQuery('#sunset_grace').val();
  }
  call_action(device_id, hyperion.SID_HYPERION, 'SetGrace', obj);
}

function call_action(device_id, sid, action, args) {
  var o = {
    'id': 'lu_action',
    'output_format':'json',
    'DeviceNum':device_id,
    'serviceId': sid,
    'action': action
  };
  var k;
  for (k in args ) {
    o[k] = args[k];
  };
  new Ajax.Request(command_url + '/data_request', {
    method: 'get',
    parameters: o
  });
}

function device_services(device_id) {
  var device = jsonp.ud.devices[api.getDeviceIndex(device_id)];
  var services = [];
  if ( device.ControlURLs ) {
    for ( var key in device.ControlURLs ) {
      services.push(device.ControlURLs[key].service);
    }
  }
  return services;
}

function is_hyperion(device_id) {
  var device = jsonp.ud.devices[api.getDeviceIndex(device_id)];
  if ( device.id_parent ) {
    var parent_services = device_services(device.id_parent);
    return parent_services.indexOf(hyperion.SID_HYPERION) >= 0;
  }
  return false;
}

function add_device(device_id) {
  var selected = $('#available_devices option:selected').selected();
  console.log(JSON.stringify(selected));
}

function remove_device(device_id) {
  var selected = $('#included_devices option:selected').selected();
  console.log(JSON.stringify(selected));
}
<commit_msg>proper filtering of vswitch<commit_after>/* global set_panel_html, Ajax, command_url, api */

var hyperion = {
  SID_HYPERION: "urn:otakup0pe:serviceId:Hyperion1",
  SID_SPOWER: "urn:upnp-org:serviceId:SwitchPower1",
  SID_DIMMING: "urn:upnp-org:serviceId:Dimming1",
  SID_HUEBULB: "urn:intvelt-com:serviceId:HueColors1",
  SID_VSWITCH: "urn:upnp-org:serviceId:VSwitch1"
};

function device_selection_callback(device_id) {
  var html = '';
  var device_ids = get_device_state(device_id, hyperion.SID_HYPERION, 'include_devices', 1).split(',');
  var included_devices = device_ids.map(function(id) {
    return {
      id: id,
      name: api.getRoomObject(api.getDeviceAttribute(id, 'room')).name + ' - ' + api.getDeviceAttribute(id, 'name')
    };
  });

  html += '
';
  html += '
Available Devices		Included Devices	';
  html += '
<select multiple size="10" id="available_devices">';
  for ( var i_devices = 0; i_devices < jsonp.ud.devices.length ; i_devices++ ) {
    var this_device = jsonp.ud.devices[i_devices];
    var this_id = parseInt(this_device.id, 10);
    // check to see if it's an included device
    var valid = true;
    for ( var i_check = 0 ; i_check < device_ids.length ; i_check++ ) {
      if ( parseInt(device_ids[i_check], 10) == this_id ) {
        valid = false;
        break;
      }
    }
    if ( valid ) {
      var these_services = device_services(this_id);
      valid = false;
      // check if it's a device we can use
      if ( these_services.length > 0 ) {
        if ( these_services.indexOf(hyperion.SID_SPOWER) >= 0 ||
             these_services.indexOf(hyperion.SID_DIMMING) >= 0 ) {
          valid = ( these_services.indexOf(hyperion.SID_HUEBULB) == -1 &&
                    ! is_hyperion(this_id) &&
                    these_services.indexOf(hyperion.SID_VSWITCH) == -1 );
        }
      }
    }
    if ( valid ) {
      var room = api.getRoomObject(jsonp.ud.devices[i_devices].room);
      var name = jsonp.ud.devices[i_devices].name;
      if ( room ) {
        name = room.name + ' - ' + name;
      }
      html += '<option value="' + jsonp.ud.devices[i_devices].id + '">' + name + '</option>';
    }
  }
  html += '</select>	';
  html += '';
  html += '<button type="button" onclick="add_device(' + device_id + ')">--></button>
';
  html += '<button type="button" onclick="remove_device(' + device_id + ')"><--</button>';
  html += '	';
  html += '<select multiple size="10" id="included_devices">';
  for ( var i_idevices = 0 ; i_idevices < included_devices.length ; i_idevices++ ) {
    html += '<option value="' + included_devices[i_idevices].id + '">' + included_devices[i_idevices].name + '</option>';
  }
  html += '</select>

';
  set_panel_html(html);
}

function time_settings_callback(device_id) {
  var html = '';
  html += 'Daytime starts at <select id="morning_hour" onchange="save_hour(' + device_id + ', \'Morning\')">';
  var morning_hour = get_device_state(device_id, hyperion.SID_HYPERION, 'MorningHour', 1);
  var morning_minute = get_device_state(device_id, hyperion.SID_HYPERION, 'MorningMinute', 1);
  var sunrise_grace = get_device_state(device_id, hyperion.SID_HYPERION, 'SunriseGrace', 1);
  for ( var i_day_hour = 0 ; i_day_hour < 24 ; i_day_hour++ ) {
    var day_hour_selected = false;
    var s_day_hour = i_day_hour.toString();
    if ( i_day_hour == morning_hour ) {
      day_hour_selected = true;
    }
    html += '<option';
    if ( day_hour_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_day_hour + '">' + s_day_hour + '</option>';
  }
  html += '</select>:<select id="morning_minute" onchange="save_minute(' + device_id + ', \'Morning\')">';
  for ( var i_day_minute = 0 ; i_day_minute < 60 ; i_day_minute++ ) {
    var day_minute_selected = false;
    var s_day_minute = i_day_minute.toString();
    if ( i_day_minute == morning_minute ) {
      day_minute_selected = true;
    }
    html += '<option';
    if ( day_minute_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_day_minute + '">' + s_day_minute + '</option>';
  }
  html += '</select> with a pre-sunrise grace period of ';
  html += '<input id="sunrise_grace" type="text" onchange="save_grace(' + device_id + ', \'Sunrise\')" value="' + sunrise_grace + '" style="width: 100px"/> seconds.';
  html += "
";
  var night_hour = get_device_state(device_id, hyperion.SID_HYPERION, 'NightHour', 1);
  var night_minute = get_device_state(device_id, hyperion.SID_HYPERION, 'NightMinute', 1);
  var sunset_grace = get_device_state(device_id, hyperion.SID_HYPERION, 'SunsetGrace', 1);
  html += 'Nighttime starts at <select id="night_hour" onchange="save_hour(' + device_id + ', \'Night\')">';
  for ( var i_night_hour = 0 ; i_night_hour < 24 ; i_night_hour++ ) {
    var night_hour_selected = false;
    var s_night_hour = i_night_hour.toString();
    if ( i_night_hour == night_hour ) {
      night_hour_selected = true;
    }
    html += '<option';
    if ( night_hour_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_night_hour + '">' + s_night_hour + '</option>';
  }
  html += '</select>:<select id="night_minute" onchange="save_minute(' + device_id + ', \'Night\');">';
  for ( var i_night_minute = 0 ; i_night_minute < 60 ; i_night_minute++ ) {
    var night_minute_selected = false;
    var s_night_minute = i_night_minute.toString();
    if ( i_night_minute == night_minute ) {
      night_minute_selected = true;
    }
    html += '<option';
    if ( night_minute_selected ) {
      html += ' selected';
    }
    html += ' value="' + s_night_minute + '">' + s_night_minute + '</option>';
  }
  html += '</select> with a pre-sunset grace period of ';
  html += '<input id="sunset_grace" type="text" value="' + sunset_grace + '" onchange="save_grace(' + device_id + ', \'Sunset\');" style="width: 100px"/> seconds.';

  set_panel_html(html);
}

function save_hour(device_id, name)
{
  var obj = {
    'Name': name
  };
  if ( name == 'Morning' ) {
    obj.Hour = jQuery('#morning_hour').val();
  } else {
    obj.Hour = jQuery('#night_hour').val();
  }
  call_action(device_id, hyperion.SID_HYPERION, 'SetHour', obj);
}

function save_minute(device_id, name)
{
  var obj = {
    'Name': name
  };
  if ( name == 'Morning' ) {
    obj.Minute = jQuery('#morning_minute').val();
  } else {
    obj.Minute = jQuery('#night_minute').val();
  }
  call_action(device_id, hyperion.SID_HYPERION, 'SetMinute', obj);
}

function save_grace(device_id, name)
{
  var obj = {
    'Name': name
  };
  if ( name == 'Sunrise' ) {
    obj.Time = jQuery('#sunrise_grace').val();
  } else {
    obj.Time = jQuery('#sunset_grace').val();
  }
  call_action(device_id, hyperion.SID_HYPERION, 'SetGrace', obj);
}

function call_action(device_id, sid, action, args) {
  var o = {
    'id': 'lu_action',
    'output_format':'json',
    'DeviceNum':device_id,
    'serviceId': sid,
    'action': action
  };
  var k;
  for (k in args ) {
    o[k] = args[k];
  };
  new Ajax.Request(command_url + '/data_request', {
    method: 'get',
    parameters: o
  });
}

function device_services(device_id) {
  var device = jsonp.ud.devices[api.getDeviceIndex(device_id)];
  var services = [];
  if ( device.ControlURLs ) {
    for ( var key in device.ControlURLs ) {
      services.push(device.ControlURLs[key].service);
    }
  }
  return services;
}

function is_hyperion(device_id) {
  var device = jsonp.ud.devices[api.getDeviceIndex(device_id)];
  if ( device.id_parent ) {
    var parent_services = device_services(device.id_parent);
    return parent_services.indexOf(hyperion.SID_HYPERION) >= 0;
  }
  return false;
}

function add_device(device_id) {
  $('#available_devices option:selected')
    .selected()
    .each(function(i, obj) {
      console.log("#" + i + ' ' + JSON.stringify(obj));
    });
}

function remove_device(device_id) {
    $('#included_devices option:selected')
    .selected()
    .each(function(i, obj) {
      console.log("#" + i + ' ' + JSON.stringify(obj));
    });
}
<|endoftext|>


<commit_before>/**
 * Loads a Wavefront .mtl file specifying materials
 *
 * @author angelxuanchang
 */

THREE.MTLLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

};

THREE.MTLLoader.prototype = {

	constructor: THREE.MTLLoader,

	/**
	 * Loads and parses a MTL asset from a URL.
	 *
	 * @param {String} url - URL to the MTL file.
	 * @param {Function} [onLoad] - Callback invoked with the loaded object.
	 * @param {Function} [onProgress] - Callback for download progress.
	 * @param {Function} [onError] - Callback for download errors.
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to load.
	 */
	load: function ( url, onLoad, onProgress, onError ) {

		var scope = this;

		var loader = new THREE.FileLoader( this.manager );
		loader.setPath( this.path );
		loader.load( url, function ( text ) {

			onLoad( scope.parse( text ) );

		}, onProgress, onError );

	},

	/**
	 * Set base path for resolving references.
	 * If set this path will be prepended to each loaded and found reference.
	 *
	 * @see setTexturePath
	 * @param {String} path
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setPath: function ( path ) {

		this.path = path;

	},

	/**
	 * Set base path for resolving texture references.
	 * If set this path will be prepended found texture reference.
	 * If not set and setPath is, it will be used as texture base path.
	 *
	 * @see setPath
	 * @param {String} path
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.setTexturePath( 'assets/textures/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setTexturePath: function ( path ) {

		this.texturePath = path;

	},

	setBaseUrl: function ( path ) {

		console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' );

		this.setTexturePath( path );

	},

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;

	},

	setMaterialOptions: function ( value ) {

		this.materialOptions = value;

	},

	/**
	 * Parses a MTL file.
	 *
	 * @param {String} text - Content of MTL file
	 * @return {THREE.MTLLoader.MaterialCreator}
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to parse.
	 */
	parse: function ( text ) {

		var lines = text.split( '\n' );
		var info = {};
		var delimiter_pattern = /\s+/;
		var materialsInfo = {};

		for ( var i = 0; i < lines.length; i ++ ) {

			var line = lines[ i ];
			line = line.trim();

			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {

				// Blank line or comment ignore
				continue;

			}

			var pos = line.indexOf( ' ' );

			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
			key = key.toLowerCase();

			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
			value = value.trim();

			if ( key === 'newmtl' ) {

				// New material

				info = { name: value };
				materialsInfo[ value ] = info;

			} else if ( info ) {

				if ( key === 'ka' || key === 'kd' || key === 'ks' ) {

					var ss = value.split( delimiter_pattern, 3 );
					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];

				} else {

					info[ key ] = value;

				}

			}

		}

		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions );
		materialCreator.setCrossOrigin( this.crossOrigin );
		materialCreator.setManager( this.manager );
		materialCreator.setMaterials( materialsInfo );
		return materialCreator;

	}

};

/**
 * Create a new THREE-MTLLoader.MaterialCreator
 * @param baseUrl - Url relative to which textures are loaded
 * @param options - Set of options on how to construct the materials
 *                  side: Which side to apply the material
 *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
 *                  wrap: What type of wrapping to apply for textures
 *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
 *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
 *                                Default: false, assumed to be already normalized
 *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
 *                                  Default: false
 * @constructor
 */

THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) {

	this.baseUrl = baseUrl || '';
	this.options = options;
	this.materialsInfo = {};
	this.materials = {};
	this.materialsArray = [];
	this.nameLookup = {};

	this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;

};

THREE.MTLLoader.MaterialCreator.prototype = {

	constructor: THREE.MTLLoader.MaterialCreator,

	crossOrigin: 'Anonymous',

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;

	},

	setManager: function ( value ) {

		this.manager = value;

	},

	setMaterials: function ( materialsInfo ) {

		this.materialsInfo = this.convert( materialsInfo );
		this.materials = {};
		this.materialsArray = [];
		this.nameLookup = {};

	},

	convert: function ( materialsInfo ) {

		if ( ! this.options ) return materialsInfo;

		var converted = {};

		for ( var mn in materialsInfo ) {

			// Convert materials info into normalized form based on options

			var mat = materialsInfo[ mn ];

			var covmat = {};

			converted[ mn ] = covmat;

			for ( var prop in mat ) {

				var save = true;
				var value = mat[ prop ];
				var lprop = prop.toLowerCase();

				switch ( lprop ) {

					case 'kd':
					case 'ka':
					case 'ks':

						// Diffuse color (color under white light) using RGB values

						if ( this.options && this.options.normalizeRGB ) {

							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];

						}

						if ( this.options && this.options.ignoreZeroRGBs ) {

							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {

								// ignore

								save = false;

							}

						}

						break;

					default:

						break;

				}

				if ( save ) {

					covmat[ lprop ] = value;

				}

			}

		}

		return converted;

	},

	preload: function () {

		for ( var mn in this.materialsInfo ) {

			this.create( mn );

		}

	},

	getIndex: function ( materialName ) {

		return this.nameLookup[ materialName ];

	},

	getAsArray: function () {

		var index = 0;

		for ( var mn in this.materialsInfo ) {

			this.materialsArray[ index ] = this.create( mn );
			this.nameLookup[ mn ] = index;
			index ++;

		}

		return this.materialsArray;

	},

	create: function ( materialName ) {

		if ( this.materials[ materialName ] === undefined ) {

			this.createMaterial_( materialName );

		}

		return this.materials[ materialName ];

	},

	createMaterial_: function ( materialName ) {

		// Create material

		var scope = this;
		var mat = this.materialsInfo[ materialName ];
		var params = {

			name: materialName,
			side: this.side

		};

		function resolveURL( baseUrl, url ) {

			if ( typeof url !== 'string' || url === '' )
				return '';

			// Absolute URL
			if ( /^https?:\/\//i.test( url ) ) return url;

			return baseUrl + url;

		}

		function setMapForType( mapType, value ) {

			if ( params[ mapType ] ) return; // Keep the first encountered texture

			var texParams = scope.getTextureParams( value, params );
			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );

			map.repeat.copy( texParams.scale );
			map.offset.copy( texParams.offset );

			map.wrapS = scope.wrap;
			map.wrapT = scope.wrap;

			params[ mapType ] = map;

		}

		for ( var prop in mat ) {

			var value = mat[ prop ];
			var n;

			if ( value === '' ) continue;

			switch ( prop.toLowerCase() ) {

				// Ns is material specular exponent

				case 'kd':

					// Diffuse color (color under white light) using RGB values

					params.color = new THREE.Color().fromArray( value );

					break;

				case 'ks':

					// Specular color (color when light is reflected from shiny surface) using RGB values
					params.specular = new THREE.Color().fromArray( value );

					break;

				case 'map_kd':

					// Diffuse texture map

					setMapForType( "map", value );

					break;

				case 'map_ks':

					// Specular map

					setMapForType( "specularMap", value );

					break;

				case 'norm':

					setMapForType( "normalMap", value );

					break;

				case 'map_bump':
				case 'bump':

					// Bump texture map

					setMapForType( "bumpMap", value );

					break;

				case 'ns':

					// The specular exponent (defines the focus of the specular highlight)
					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.

					params.shininess = parseFloat( value );

					break;

				case 'd':
					n = parseFloat( value );

					if ( n < 1 ) {

						params.opacity = n;
						params.transparent = true;

					}

					break;

				case 'tr':
					n = parseFloat( value );

					if ( this.options && this.options.invertTrProperty ) n = 1 - n;

					if ( n < 1 ) {

						params.opacity = n;
						params.transparent = true;

					}

					break;

				default:
					break;

			}

		}

		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
		return this.materials[ materialName ];

	},

	getTextureParams: function ( value, matParams ) {

		var texParams = {

			scale: new THREE.Vector2( 1, 1 ),
			offset: new THREE.Vector2( 0, 0 )

		 };

		var items = value.split( /\s+/ );
		var pos;

		pos = items.indexOf( '-bm' );

		if ( pos >= 0 ) {

			matParams.bumpScale = parseFloat( items[ pos + 1 ] );
			items.splice( pos, 2 );

		}

		pos = items.indexOf( '-s' );

		if ( pos >= 0 ) {

			texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		pos = items.indexOf( '-o' );

		if ( pos >= 0 ) {

			texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		texParams.url = items.join( ' ' ).trim();
		return texParams;

	},

	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {

		var texture;
		var loader = THREE.Loader.Handlers.get( url );
		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;

		if ( loader === null ) {

			loader = new THREE.TextureLoader( manager );

		}

		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
		texture = loader.load( url, onLoad, onProgress, onError );

		if ( mapping !== undefined ) texture.mapping = mapping;

		return texture;

	}

};
<commit_msg>Update MTLLoader.js<commit_after>/**
 * Loads a Wavefront .mtl file specifying materials
 *
 * @author angelxuanchang
 */

THREE.MTLLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

};

THREE.MTLLoader.prototype = {

	constructor: THREE.MTLLoader,

	/**
	 * Loads and parses a MTL asset from a URL.
	 *
	 * @param {String} url - URL to the MTL file.
	 * @param {Function} [onLoad] - Callback invoked with the loaded object.
	 * @param {Function} [onProgress] - Callback for download progress.
	 * @param {Function} [onError] - Callback for download errors.
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to load.
	 */
	load: function ( url, onLoad, onProgress, onError ) {

		var scope = this;

		var loader = new THREE.FileLoader( this.manager );
		loader.setPath( this.path );
		loader.load( url, function ( text ) {

			onLoad( scope.parse( text ) );

		}, onProgress, onError );

	},

	/**
	 * Set base path for resolving references.
	 * If set this path will be prepended to each loaded and found reference.
	 *
	 * @see setTexturePath
	 * @param {String} path
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setPath: function ( path ) {

		this.path = path;

	},

	/**
	 * Set base path for resolving texture references.
	 * If set this path will be prepended found texture reference.
	 * If not set and setPath is, it will be used as texture base path.
	 *
	 * @see setPath
	 * @param {String} path
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.setTexturePath( 'assets/textures/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setTexturePath: function ( path ) {

		this.texturePath = path;

	},

	setBaseUrl: function ( path ) {

		console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' );

		this.setTexturePath( path );

	},

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;

	},

	setMaterialOptions: function ( value ) {

		this.materialOptions = value;

	},

	/**
	 * Parses a MTL file.
	 *
	 * @param {String} text - Content of MTL file
	 * @return {THREE.MTLLoader.MaterialCreator}
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to parse.
	 */
	parse: function ( text ) {

		var lines = text.split( '\n' );
		var info = {};
		var delimiter_pattern = /\s+/;
		var materialsInfo = {};

		for ( var i = 0; i < lines.length; i ++ ) {

			var line = lines[ i ];
			line = line.trim();

			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {

				// Blank line or comment ignore
				continue;

			}

			var pos = line.indexOf( ' ' );

			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
			key = key.toLowerCase();

			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
			value = value.trim();

			if ( key === 'newmtl' ) {

				// New material

				info = { name: value };
				materialsInfo[ value ] = info;

			} else if ( info ) {

				if ( key === 'ka' || key === 'kd' || key === 'ks' ) {

					var ss = value.split( delimiter_pattern, 3 );
					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];

				} else {

					info[ key ] = value;

				}

			}

		}

		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions );
		materialCreator.setCrossOrigin( this.crossOrigin );
		materialCreator.setManager( this.manager );
		materialCreator.setMaterials( materialsInfo );
		return materialCreator;

	}

};

/**
 * Create a new THREE-MTLLoader.MaterialCreator
 * @param baseUrl - Url relative to which textures are loaded
 * @param options - Set of options on how to construct the materials
 *                  side: Which side to apply the material
 *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
 *                  wrap: What type of wrapping to apply for textures
 *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
 *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
 *                                Default: false, assumed to be already normalized
 *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
 *                                  Default: false
 * @constructor
 */

THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) {

	this.baseUrl = baseUrl || '';
	this.options = options;
	this.materialsInfo = {};
	this.materials = {};
	this.materialsArray = [];
	this.nameLookup = {};

	this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;

};

THREE.MTLLoader.MaterialCreator.prototype = {

	constructor: THREE.MTLLoader.MaterialCreator,

	crossOrigin: 'Anonymous',

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;

	},

	setManager: function ( value ) {

		this.manager = value;

	},

	setMaterials: function ( materialsInfo ) {

		this.materialsInfo = this.convert( materialsInfo );
		this.materials = {};
		this.materialsArray = [];
		this.nameLookup = {};

	},

	convert: function ( materialsInfo ) {

		if ( ! this.options ) return materialsInfo;

		var converted = {};

		for ( var mn in materialsInfo ) {

			// Convert materials info into normalized form based on options

			var mat = materialsInfo[ mn ];

			var covmat = {};

			converted[ mn ] = covmat;

			for ( var prop in mat ) {

				var save = true;
				var value = mat[ prop ];
				var lprop = prop.toLowerCase();

				switch ( lprop ) {

					case 'kd':
					case 'ka':
					case 'ks':

						// Diffuse color (color under white light) using RGB values

						if ( this.options && this.options.normalizeRGB ) {

							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];

						}

						if ( this.options && this.options.ignoreZeroRGBs ) {

							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {

								// ignore

								save = false;

							}

						}

						break;

					default:

						break;

				}

				if ( save ) {

					covmat[ lprop ] = value;

				}

			}

		}

		return converted;

	},

	preload: function () {

		for ( var mn in this.materialsInfo ) {

			this.create( mn );

		}

	},

	getIndex: function ( materialName ) {

		return this.nameLookup[ materialName ];

	},

	getAsArray: function () {

		var index = 0;

		for ( var mn in this.materialsInfo ) {

			this.materialsArray[ index ] = this.create( mn );
			this.nameLookup[ mn ] = index;
			index ++;

		}

		return this.materialsArray;

	},

	create: function ( materialName ) {

		if ( this.materials[ materialName ] === undefined ) {

			this.createMaterial_( materialName );

		}

		return this.materials[ materialName ];

	},

	createMaterial_: function ( materialName ) {

		// Create material

		var scope = this;
		var mat = this.materialsInfo[ materialName ];
		var params = {

			name: materialName,
			side: this.side

		};

		function resolveURL( baseUrl, url ) {

			if ( typeof url !== 'string' || url === '' )
				return '';

			// Absolute URL
			if ( /^https?:\/\//i.test( url ) ) return url;

			return baseUrl + url;

		}

		function setMapForType( mapType, value ) {

			if ( params[ mapType ] ) return; // Keep the first encountered texture

			var texParams = scope.getTextureParams( value, params );
			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );

			map.repeat.copy( texParams.scale );
			map.offset.copy( texParams.offset );

			map.wrapS = scope.wrap;
			map.wrapT = scope.wrap;

			params[ mapType ] = map;

		}

		for ( var prop in mat ) {

			var value = mat[ prop ];
			var n;

			if ( value === '' ) continue;

			switch ( prop.toLowerCase() ) {

				// Ns is material specular exponent

				case 'kd':

					// Diffuse color (color under white light) using RGB values

					params.color = new THREE.Color().fromArray( value );

					break;

				case 'ks':

					// Specular color (color when light is reflected from shiny surface) using RGB values
					params.specular = new THREE.Color().fromArray( value );

					break;

				case 'map_kd':

					// Diffuse texture map

					setMapForType( "map", value );

					break;

				case 'map_ks':

					// Specular map

					setMapForType( "specularMap", value );

					break;

				case 'norm':

					setMapForType( "normalMap", value );

					break;

				case 'map_bump':
				case 'bump':

					// Bump texture map

					setMapForType( "bumpMap", value );

					break;

				case 'ns':

					// The specular exponent (defines the focus of the specular highlight)
					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.

					params.shininess = parseFloat( value );

					break;

				case 'd':
					n = parseFloat( value );

					if ( n < 1 ) {

						params.opacity = n;
						params.transparent = true;

					}

					break;

				case 'tr':
					n = parseFloat( value );

					if ( this.options && this.options.invertTrProperty ) n = 1 - n;

					if ( n > 0 ) {

						params.opacity = 1 - n;
						params.transparent = true;

					}

					break;

				default:
					break;

			}

		}

		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
		return this.materials[ materialName ];

	},

	getTextureParams: function ( value, matParams ) {

		var texParams = {

			scale: new THREE.Vector2( 1, 1 ),
			offset: new THREE.Vector2( 0, 0 )

		 };

		var items = value.split( /\s+/ );
		var pos;

		pos = items.indexOf( '-bm' );

		if ( pos >= 0 ) {

			matParams.bumpScale = parseFloat( items[ pos + 1 ] );
			items.splice( pos, 2 );

		}

		pos = items.indexOf( '-s' );

		if ( pos >= 0 ) {

			texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		pos = items.indexOf( '-o' );

		if ( pos >= 0 ) {

			texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		texParams.url = items.join( ' ' ).trim();
		return texParams;

	},

	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {

		var texture;
		var loader = THREE.Loader.Handlers.get( url );
		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;

		if ( loader === null ) {

			loader = new THREE.TextureLoader( manager );

		}

		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
		texture = loader.load( url, onLoad, onProgress, onError );

		if ( mapping !== undefined ) texture.mapping = mapping;

		return texture;

	}

};
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

// You can view the full text of each annotation by running mocha test/annotations_test.js
// Current output:
//
// Main text annotation for carelink/basal/temp-percent-create-scheduled:
// We are calculating the temp basal rates here by applying the percentage of the temp basal to your current schedule, but Demo did not directly provide us with these rate changes.
//
// Main text annotation for carelink/basal/off-schedule-rate:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your basal rate here.
//
// Main text annotation for carelink/settings/basal-mismatch:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your basal settings here.
//
// Main text annotation for carelink/settings/wizard-mismatch:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your bolus wizard settings here.
//
// Main text annotation for carelink/settings/activeSchedule-mismatch:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your active basal pattern here.
//
// Main text annotation for carelink/device-overlap-boundary:
// We are not showing data here because we've received datasets from multiple pumps that are in conflict. Demo did not provide enough information to distinguish the data from each pump.
//
// Main text annotation for diasend/basal/temp-basal-fabrication:
// The Demo .xls file doesn't report temp basals directly, so we have to infer from other evidence where you might have been using a temp basal rate. We think this segment could be a temp basal, but it may not be.
//
// Main text annotation for diasend/basal/temp-duration-truncated:
// Because of how the Demo .xls file reports the data, we've truncated what may have been a temp basal here to a maximum duration of 120 hours.
//
// Main text annotation for diasend/bolus/extended:
// The Demo .xls file doesn't report the split between the intitial and the extended delivery during a combo bolus. All we can display is the duration of the combo bolus and the total dose delivered.
//
// Main text annotation for basal/intersects-incomplete-suspend
// Within this basal segment, we are omitting a suspend event that didn't end. This may have resulted from switching to a new device. As a result, this basal segment may be inaccurate.
//
// Main text annotation for stats-insufficient-data:
// There is not enough data to show this statistic.
//
// Lead text annotation for stats-insufficient-data:
// Why is this grey?

var format = require('../../../data/util/format');

var definitions = {
  LEAD_TEXT: {
    'stats-insufficient-data': function() {
      return 'Why is this grey?';
    },
    'stats-how-calculated': function() {
      return 'What is this?';
    }
  },
  MAIN_TEXT: {
    'carelink/basal/temp-percent-create-scheduled': function(source, defs) {
      var a = "We are calculating the temp basal rates here by applying the percentage of the temp basal to your current schedule, but ";
      var b = " did not directly provide us with these rate changes.";
      return defs.stitch(a, b, source);
    },
    'carelink/basal/off-schedule-rate': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your basal rate here.";
      return defs.stitch(a, b, source);
    },
    'carelink/settings/basal-mismatch': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your basal settings here.";
      return defs.stitch(a, b, source);
    },
    'carelink/settings/wizard-mismatch': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your bolus wizard settings here.";
      return defs.stitch(a, b, source);
    },
    'carelink/settings/activeSchedule-mismatch': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your active basal pattern here.";
      return defs.stitch(a, b, source);
    },
    'carelink/device-overlap-boundary': function(source, defs) {
      var a = "We are not showing data here because we've received datasets from multiple pumps that are in conflict.";
      var b = " did not provide enough information to distinguish the data from each pump.";
      return defs.stitch(a, b, source);
    },
    'diasend/basal/temp-basal-fabrication': function(source, defs) {
      var a = "The ";
      var b = " .xls file doesn't report temp basals directly, so we have to infer from other evidence where you might have been using a temp basal rate. We think this segment could be a temp basal, but it may not be.";
      return defs.stitch(a, b, source);
    },
    'diasend/basal/temp-duration-truncated': function(source, defs) {
      var a = "Because of how the ";
      var b = " .xls file reports the data, we've truncated what may have been a temp basal here to a maximum duration of 120 hours.";
      return defs.stitch(a, b, source);
    },
    'diasend/bolus/extended': function(source, defs) {
      var a = "The ";
      var b = " .xls file doesn't report the split between the intitial and the extended delivery during a combo bolus. All we can display is the duration of the combo bolus and the total dose delivered.";
      return defs.stitch(a, b, source);
    },
    'basal/intersects-incomplete-susppend': function() {
      return "Within this basal segment, we are omitting a suspend event that didn't end. This may have resulted from switching to a new device. As a result, this basal segment may be inaccurate.";
    },
    'stats-insufficient-data': function() {
      return 'There is not enough data to show this statistic.';
    },
    'stats-how-calculated-ratio': function() {
      return 'This is the balance between basal insulin and bolus insulin. Depending on your age, activity, weight, and doctor, the goal for this ratio will vary. We will only show numbers if there is enough basal data - 24 hours in the one day view and 7 days in the two week view.';
    },
    'stats-how-calculated-range-cbg': function() {
      return 'This shows the percentage of time your CGM was in range. Time in range helps to see how you are doing overall. We will only show a number if there is enough data - readings for at least 75% of the day in the one day view, and 75% of the day for at least half of the days shown in the two week view.';
    },
    'stats-how-calculated-range-smbg': function() {
      return "When there isn't enough CGM data, this shows how many of your fingerstick readings were in range. Readings in range can help to see how you are doing overall. We will only show a number if there is enough data - at least 4 readings in the one day view, and at least 4 readings for at least half of the days shown in the two week view.";
    },
    'stats-how-calculated-average-cbg': function() {
      return 'This shows the average blood glucose from your CGM. We will only show a number if there is enough data - readings for at least 75% of the day in the one day view, and readings for at least 75% of the day for at least half of the days shown in the two week view.';
    },
    'stats-how-calculated-average-smbg': function() {
      return "When there isn't enough CGM data to calculate an average from, this shows the average blood glucose from your fingerstick readings. We will only show a number if there is enough data - at least 4 readings in the one day view, and at least 4 readings for at least half of the days shown in the two week view.";
    }
  },
  default: function(source) {
    if (source == null) {
      return "We can't be 100% certain of the data displayed here.";
    }
    var a = "We can't be 100% certain of the data displayed here because of how ";
    var b = " reports the data.";
    return this.stitch(a, b, source);
  },
  main: function(annotation, source) {
    var a, b;
    if (this.MAIN_TEXT[annotation.code] != null) {
      return this.MAIN_TEXT[annotation.code](source, this);
    }
    else {
      return this.default(source);
    }
  },
  stitch: function(a, b, source) {
    var sourceText = source === 'carelink' ? ' CareLink' : format.capitalize(source);
    return a + sourceText + b;
  },
  lead: function(code) {
    code = code || '';
    if (this.LEAD_TEXT[code] != null) {
      return this.LEAD_TEXT[code]();
    }
    else {
      return false;
    }
  }
};

module.exports = definitions;
<commit_msg>new text of stats widget explainer tooltips signed off on by @brandonarbiter<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

// You can view the full text of each annotation by running mocha test/annotations_test.js
// Current output:
//
// Main text annotation for carelink/basal/temp-percent-create-scheduled:
// We are calculating the temp basal rates here by applying the percentage of the temp basal to your current schedule, but Demo did not directly provide us with these rate changes.
//
// Main text annotation for carelink/basal/off-schedule-rate:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your basal rate here.
//
// Main text annotation for carelink/settings/basal-mismatch:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your basal settings here.
//
// Main text annotation for carelink/settings/wizard-mismatch:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your bolus wizard settings here.
//
// Main text annotation for carelink/settings/activeSchedule-mismatch:
// You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how Demo reports the data, we can't be 100% certain of your active basal pattern here.
//
// Main text annotation for carelink/device-overlap-boundary:
// We are not showing data here because we've received datasets from multiple pumps that are in conflict. Demo did not provide enough information to distinguish the data from each pump.
//
// Main text annotation for diasend/basal/temp-basal-fabrication:
// The Demo .xls file doesn't report temp basals directly, so we have to infer from other evidence where you might have been using a temp basal rate. We think this segment could be a temp basal, but it may not be.
//
// Main text annotation for diasend/basal/temp-duration-truncated:
// Because of how the Demo .xls file reports the data, we've truncated what may have been a temp basal here to a maximum duration of 120 hours.
//
// Main text annotation for diasend/bolus/extended:
// The Demo .xls file doesn't report the split between the intitial and the extended delivery during a combo bolus. All we can display is the duration of the combo bolus and the total dose delivered.
//
// Main text annotation for basal/intersects-incomplete-suspend
// Within this basal segment, we are omitting a suspend event that didn't end. This may have resulted from switching to a new device. As a result, this basal segment may be inaccurate.
//
// Main text annotation for stats-insufficient-data:
// There is not enough data to show this statistic.
//
// Lead text annotation for stats-insufficient-data:
// Why is this grey?

var format = require('../../../data/util/format');

var definitions = {
  LEAD_TEXT: {
    'stats-insufficient-data': function() {
      return 'Why is this grey?';
    },
    'stats-how-calculated': function() {
      return 'What is this?';
    }
  },
  MAIN_TEXT: {
    'carelink/basal/temp-percent-create-scheduled': function(source, defs) {
      var a = "We are calculating the temp basal rates here by applying the percentage of the temp basal to your current schedule, but ";
      var b = " did not directly provide us with these rate changes.";
      return defs.stitch(a, b, source);
    },
    'carelink/basal/off-schedule-rate': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your basal rate here.";
      return defs.stitch(a, b, source);
    },
    'carelink/settings/basal-mismatch': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your basal settings here.";
      return defs.stitch(a, b, source);
    },
    'carelink/settings/wizard-mismatch': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your bolus wizard settings here.";
      return defs.stitch(a, b, source);
    },
    'carelink/settings/activeSchedule-mismatch': function(source, defs) {
      var a = "You may have changed pumps recently - perhaps because you had to have your pump replaced due to malfuction. As a result of how ";
      var b = " reports the data, we can't be 100% certain of your active basal pattern here.";
      return defs.stitch(a, b, source);
    },
    'carelink/device-overlap-boundary': function(source, defs) {
      var a = "We are not showing data here because we've received datasets from multiple pumps that are in conflict.";
      var b = " did not provide enough information to distinguish the data from each pump.";
      return defs.stitch(a, b, source);
    },
    'diasend/basal/temp-basal-fabrication': function(source, defs) {
      var a = "The ";
      var b = " .xls file doesn't report temp basals directly, so we have to infer from other evidence where you might have been using a temp basal rate. We think this segment could be a temp basal, but it may not be.";
      return defs.stitch(a, b, source);
    },
    'diasend/basal/temp-duration-truncated': function(source, defs) {
      var a = "Because of how the ";
      var b = " .xls file reports the data, we've truncated what may have been a temp basal here to a maximum duration of 120 hours.";
      return defs.stitch(a, b, source);
    },
    'diasend/bolus/extended': function(source, defs) {
      var a = "The ";
      var b = " .xls file doesn't report the split between the intitial and the extended delivery during a combo bolus. All we can display is the duration of the combo bolus and the total dose delivered.";
      return defs.stitch(a, b, source);
    },
    'basal/intersects-incomplete-susppend': function() {
      return "Within this basal segment, we are omitting a suspend event that didn't end. This may have resulted from switching to a new device. As a result, this basal segment may be inaccurate.";
    },
    'stats-insufficient-data': function() {
      return 'There is not enough data to show this statistic.';
    },
    'stats-how-calculated-ratio': function() {
      return 'Basal insulin keeps your glucose within your target range when you are not eating.  Bolus insulin is mostly used to cover the carbohydrates you eat or to bring a high glucose back into your target range. This ratio allows you to compare how much of the insulin you are taking is used for each purpose. We will only show numbers if there is enough basal data - 24 hours in the one day view and 7 days in the two week view.';
    },
    'stats-how-calculated-range-cbg': function() {
      return 'With diabetes, any time in range is hard to achieve! This shows the percentage of time your CGM was in range, which can help you see how you are doing overall. We will only show a number if there is enough data - readings for at least 75% of the day in the one day view, and 75% of the day for at least half of the days shown in the two week view.';
    },
    'stats-how-calculated-range-smbg': function() {
      return 'With diabetes, any reading in range is hard to achieve! This shows how many of your finger stick readings were in range, which can help you see how you are doing overall. We will only show a number if there is enough data - at least 4 readings in the one day view, and at least 4 readings for at least half of the days shown in the two week view.';
    },
    'stats-how-calculated-average-cbg': function() {
      return 'To get one number that gives you a rough idea of your glucose level we add together all of the CGM glucose readings you have and then divide them by the number of glucose readings. We will only show a number if there is enough data - readings for at least 75% of the day in the one day view, and readings for at least 75% of the day for at least half of the days shown in the two week view.';
    },
    'stats-how-calculated-average-smbg': function() {
      return 'To get one number that gives you a rough idea of your glucose level, we add together all of the fingerstick readings you have and then divide them by the number of readings. We will only show a number if there is enough data - at least 4 readings in the one day view, and at least 4 readings for at least half of the days shown in the two week view.';
    }
  },
  default: function(source) {
    if (source == null) {
      return "We can't be 100% certain of the data displayed here.";
    }
    var a = "We can't be 100% certain of the data displayed here because of how ";
    var b = " reports the data.";
    return this.stitch(a, b, source);
  },
  main: function(annotation, source) {
    var a, b;
    if (this.MAIN_TEXT[annotation.code] != null) {
      return this.MAIN_TEXT[annotation.code](source, this);
    }
    else {
      return this.default(source);
    }
  },
  stitch: function(a, b, source) {
    var sourceText = source === 'carelink' ? ' CareLink' : format.capitalize(source);
    return a + sourceText + b;
  },
  lead: function(code) {
    code = code || '';
    if (this.LEAD_TEXT[code] != null) {
      return this.LEAD_TEXT[code]();
    }
    else {
      return false;
    }
  }
};

module.exports = definitions;
<|endoftext|>


<commit_before>module.exports = {

    id: 'permissions',
    defaultConfig: {
        allowedUserNames: [],
        message: '⛔ you are not authorized'
    },

    plugin(bot, pluginConfig) {

        bot.mod('message', (data) => {
            const userId = data.message.from.id;
            if (pluginConfig.allowedUserNames.indexOf(data.message.from.username) < 0) {
                data.message = {};
                bot.sendMessage(userId, pluginConfig.message);
            }

            return data;
        });
    }
};
<commit_msg>Update permissions.js<commit_after>module.exports = {

    id: 'permissions',
    defaultConfig: {
        allowedUserIds: [],
        allowedChannels: [],
        message: '⛔ you are not authorized'
    },

    plugin(bot, pluginConfig) {

        bot.mod('message', (data) => {
            if (data.message.chat.type === 'channel') {
                const chatId = data.message.chat.id;
                if (!pluginConfig.allowedChannels.includes(chatId)) {
                    data.message = {};
                    bot.sendMessage(chatId, pluginConfig.message);
                }
            } else {
                const userId = data.message.from.id;
                if (!pluginConfig.allowedUserIds.includes(userId)) {
                    data.message = {};
                    bot.sendMessage(userId, pluginConfig.message);
                }
            }

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


<commit_before>(function ($) {
    'use strict';

    var Panel = function (form, url) {
        this.form = form;
        this.url = url ? url : $(form).data('panels-url');

        if (!this.url) {
            return false;
        }

        if (!this.isEligible()) {
            return false;
        }

        //run an initial evaluation with current form's settings.
        this.evaluateWithServer();

        //Observe the form.
        this.observe();
    };

    /**
     * Eligible forms contain panels.
     *
     * @return {Boolean} True if there is/are panel(s).
     */
    Panel.prototype.isEligible = function () {
        return $(this.form).has('[data-provide="dynamic-panel"]').length ? true : false;
    };

    Panel.prototype.buildData = function () {
        var data = {};
        $(this.form).find(':input').each(function () {
            var name = $(this).attr('name');
            var value = $(this).val();
            if (typeof name !== 'undefined' && typeof value !== 'undefined' ) {
                data[name] = value;
            }
        });

        return data;
    };

    Panel.prototype.hidePanels = function (panels) {
        if (typeof panels === 'undefined') {
            return;
        }

        if (!(panels instanceof Array)) {
            return;
        }

        var that = this;
        panels.forEach(function (cur) {
            var current = cur;
            var $panel = $(that.form).find('[data-provide="dynamic-panel"]');
            $panel.each(function () {
                var title = $(this).find('[data-title="dynamic-panel-title"]').text();
                if (current === title) {
                    if (!$(this).hasClass('hidden')) {
                        $(this).addClass('hidden');
                        $(this).find(':input').attr('disabled', true);
                    }
                }
            });
        });
    };

    Panel.prototype.resetPanels = function () {
        $(this.form).find('[data-provide="dynamic-panel"].hidden').find(':input').attr('disabled', false);
        $(this.form).find('[data-provide="dynamic-panel"]').removeClass('hidden');
    };

    Panel.prototype.observe = function () {
        var that = this;
        $(this.form).find(':input').change(function () {
            that.evaluateWithServer();
        });

        $(this.form).find(':input').on('ifChanged', function(event) {
            that.evaluateWithServer();
        });
    };

    Panel.prototype.evaluateWithServer = function () {
        var that = this;
        $.ajax({
            url: that.url,
            type: 'POST',
            data: that.buildData(),
            dataType: 'json',
            headers: {
                'Authorization': 'Bearer ' + api_options.token
            },
            success: function (data) {
                if (data.success) {
                    that.resetPanels();
                    that.hidePanels(data.data.fail);
                }
            },
        });
    };

    $(document).ready(function () {
        if ($('input[name=formPanel]').val() != undefined ) {
            $('input[name=formPanel]').each(function (i) {
                let url = $(this).data('panels-url');
                let form = $(this).closest('form');

                new Panel(form, url);
            });
        } else {
            $('form[data-panels-url]').each(function (i) {
                new Panel(this);
            });
        }
    });

})(jQuery);
<commit_msg>Invert control statement (task #14853)<commit_after>(function ($) {
    'use strict';

    var Panel = function (form, url) {
        this.form = form;
        this.url = url ? url : $(form).data('panels-url');

        if (!this.url) {
            return false;
        }

        if (!this.isEligible()) {
            return false;
        }

        //run an initial evaluation with current form's settings.
        this.evaluateWithServer();

        //Observe the form.
        this.observe();
    };

    /**
     * Eligible forms contain panels.
     *
     * @return {Boolean} True if there is/are panel(s).
     */
    Panel.prototype.isEligible = function () {
        return $(this.form).has('[data-provide="dynamic-panel"]').length ? true : false;
    };

    Panel.prototype.buildData = function () {
        var data = {};
        $(this.form).find(':input').each(function () {
            var name = $(this).attr('name');
            if (typeof name === 'undefined') {
                return;
            }

            var value = $(this).val();
            if (typeof value === 'undefined') {
                return;
            }

            data[name] = value;
        });

        return data;
    };

    Panel.prototype.hidePanels = function (panels) {
        if (typeof panels === 'undefined') {
            return;
        }

        if (!(panels instanceof Array)) {
            return;
        }

        var that = this;
        panels.forEach(function (cur) {
            var current = cur;
            var $panel = $(that.form).find('[data-provide="dynamic-panel"]');
            $panel.each(function () {
                var title = $(this).find('[data-title="dynamic-panel-title"]').text();
                if (current === title) {
                    if (!$(this).hasClass('hidden')) {
                        $(this).addClass('hidden');
                        $(this).find(':input').attr('disabled', true);
                    }
                }
            });
        });
    };

    Panel.prototype.resetPanels = function () {
        $(this.form).find('[data-provide="dynamic-panel"].hidden').find(':input').attr('disabled', false);
        $(this.form).find('[data-provide="dynamic-panel"]').removeClass('hidden');
    };

    Panel.prototype.observe = function () {
        var that = this;
        $(this.form).find(':input').change(function () {
            that.evaluateWithServer();
        });

        $(this.form).find(':input').on('ifChanged', function(event) {
            that.evaluateWithServer();
        });
    };

    Panel.prototype.evaluateWithServer = function () {
        var that = this;
        $.ajax({
            url: that.url,
            type: 'POST',
            data: that.buildData(),
            dataType: 'json',
            headers: {
                'Authorization': 'Bearer ' + api_options.token
            },
            success: function (data) {
                if (data.success) {
                    that.resetPanels();
                    that.hidePanels(data.data.fail);
                }
            },
        });
    };

    $(document).ready(function () {
        if ($('input[name=formPanel]').val() != undefined ) {
            $('input[name=formPanel]').each(function (i) {
                let url = $(this).data('panels-url');
                let form = $(this).closest('form');

                new Panel(form, url);
            });
        } else {
            $('form[data-panels-url]').each(function (i) {
                new Panel(this);
            });
        }
    });

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

var utils    = require('./utils');
var config   = require('../config');
var Registry = require('./registry');
var markdown = require('markdown').markdown;

var options;
var registry;

function renderListPage (page, req, reply) {
	registry.packages(page, function (packages) {
		reply.view('index', {
			title: options.title,
			searchUrl: config.search.url,
			enableSearch: config.search.enable,
			packages: packages,
			nextPage: page + 1
		});
	});
};

function renderPackagePage (req, reply) {
	registry.packageInfo(req.url.pathname.slice(1, req.url.pathname.length), function (_package) {
		_package.readme = markdown.toHTML(_package.readme);
		reply.view('package', {
			'title': options.title,
			'package': _package
		});
	});
};

function renderError (req, reply) {
	reply.view('error', {
		title: options.title,
		error: 'fatal error'
	});
};

function render (req, reply) {
	var path = req.url.pathname;

	if (path === '/') {
		renderListPage(0, req, reply);
	}
	else if (path.indexOf(config.page.url) !== -1) {
		var page = parseInt(path.replace(config.page.url, ''), 10);
		if (isNaN(page)) {
			// TODO: fix me: throw error or redirect to
			// index instead of rendering page 0
			renderListPage(0, req, reply);
		}
		else {
			renderListPage(page, req, reply);
		}
	}
	else {
		renderPackagePage(req, reply);
	}
};

module.exports.setup = function (_options, callback) {
	options = _options;
	registry = new Registry(_options);
	registry.init(callback);
};

module.exports.preIntercept = function (req, reply) {
    if (utils.isSearchRequest(req)) {
        //search(req, reply);
        //return;
    }

    if (utils.shouldRenderHtml(req)) {
        render(req, reply);
        return;
    }

	reply();
};

module.exports.postIntercept = function (req, reply) {
	if (req.response && req.response.isBoom && utils.shouldRenderHtml(req)) {
	    renderError(req, reply);
	    return;
	}

	reply();
};<commit_msg>jshint fixes<commit_after>'use strict';

var utils    = require('./utils');
var config   = require('../config');
var Registry = require('./registry');
var markdown = require('markdown').markdown;

var options;
var registry;

function renderListPage(page, req, reply) {
	registry.packages(page, function (packages) {
		reply.view('index', {
			title: options.title,
			searchUrl: config.search.url,
			enableSearch: config.search.enable,
			packages: packages,
			nextPage: page + 1
		});
	});
}

function renderPackagePage(req, reply) {
	registry.packageInfo(req.url.pathname.slice(1, req.url.pathname.length), function (_package) {
		_package.readme = markdown.toHTML(_package.readme);
		reply.view('package', {
			'title': options.title,
			'package': _package
		});
	});
}

function renderError(req, reply) {
	reply.view('error', {
		title: options.title,
		error: 'fatal error'
	});
}

function render(req, reply) {
	var path = req.url.pathname;

	if (path === '/') {
		renderListPage(0, req, reply);
	}
	else if (path.indexOf(config.page.url) !== -1) {
		var page = parseInt(path.replace(config.page.url, ''), 10);
		if (isNaN(page)) {
			// TODO: fix me: throw error or redirect to
			// index instead of rendering page 0
			renderListPage(0, req, reply);
		}
		else {
			renderListPage(page, req, reply);
		}
	}
	else {
		renderPackagePage(req, reply);
	}
}

module.exports.setup = function (_options, callback) {
	options = _options;
	registry = new Registry(_options);
	registry.init(callback);
};

module.exports.preIntercept = function (req, reply) {
    if (utils.isSearchRequest(req)) {
        //search(req, reply);
        //return;
    }

    if (utils.shouldRenderHtml(req)) {
        render(req, reply);
        return;
    }

	reply();
};

module.exports.postIntercept = function (req, reply) {
	if (req.response && req.response.isBoom && utils.shouldRenderHtml(req)) {
	    renderError(req, reply);
	    return;
	}

	reply();
};<|endoftext|>


<commit_before>(function() {
  'use strict';
  var http = require('http');
  var levelup = require('levelup');
  var lidInfoDB = levelup('lid-info.leveldb');
  var lidDB = levelup('lid.leveldb');
  var patronDB = levelup('patron.leveldb');
  var relatedDB = levelup('related.leveldb');
  var maxSamples = 1000;
  var relatedCount = 100;

  function related(lid, res) {
    var t0 = Date.now();
    relatedDB.get(lid, function(err, data) {
      if (err || !data) {
        lidDB.get(lid, function(err, patrons) {
          if (err) {
            return res.end('{"error":"local id not found"}');
          }
          patrons = JSON.parse(patrons);
          patrons = patrons.slice(0, maxSamples);
          var coloans = {};

          function traverse() {
            if (patrons.length === 0) {
              return summariseResult();
            }
            var patron = patrons.pop();
            patronDB.get(patron, function(err, data) {
              if (err || !data) {
                console.log(err, data);
                return traverse();
              }
              var books = JSON.parse(data);
              for (var i = 0; i < books.length; ++i) {
                coloans[books[i]] = (coloans[books[i]] || 0) + 1;
              }
              traverse();
            });
          }
          traverse();

          function summariseResult() {
            var result = Object.keys(coloans).map(function(coloan) {
              var n = coloans[coloan];
              var total = +coloan.split(',')[1];
              var weight = n / Math.log(total + 10) * 1000 | 0;
              return [coloan.split(',')[0], weight];
            });
            result.sort(function(a, b) {
              return b[1] - a[1];
            });
            console.log('time:', (Date.now() - t0) / 1000);
            result = JSON.stringify(result.slice(0, relatedCount));
            relatedDB.put(lid, result);
            return res.end(result);
          }
        });
      } else {
        return res.end(data);
      }
    });
  }

  http.createServer(function(req, res) {
    res.writeHead(200, {
      'Content-Type': 'application/json; charset=utf-8',
      'Access-Control-Allow-Origin': '*'
    });

    var urlParts = req.url.split('/');
    if (urlParts[1] === 'info') {
      lidInfoDB.get(urlParts[2], function(err, data) {
        res.end(err ? '{"error":"local id not found"}' : data);
      });
    } else if (urlParts[1] === 'related') {
      related(urlParts[2], res);
    } else {
      res.end('{"error":"unsupported method"}');
    }
  }).listen(process.env.PORT || 1337, '0.0.0.0');
})();
<commit_msg>jsbeautifier<commit_after>(function() {
  'use strict';
  var http = require('http');
  var levelup = require('levelup');
  var lidInfoDB = levelup('lid-info.leveldb');
  var lidDB = levelup('lid.leveldb');
  var patronDB = levelup('patron.leveldb');
  var relatedDB = levelup('related.leveldb');
  var maxSamples = 1000;
  var relatedCount = 100;

  function related(lid, res) {
    var t0 = Date.now();
    relatedDB.get(lid, function(err, data) {
      if (data && !err) {
        return res.end(data);
      }
        lidDB.get(lid, function(err, patrons) {
          if (err) {
            return res.end('{"error":"local id not found"}');
          }
          patrons = JSON.parse(patrons);
          patrons = patrons.slice(0, maxSamples);
          var coloans = {};

          function traverse() {
            if (patrons.length === 0) {
              return summariseResult();
            }
            var patron = patrons.pop();
            patronDB.get(patron, function(err, data) {
              if (err || !data) {
                console.log(err, data);
                return traverse();
              }
              var books = JSON.parse(data);
              for (var i = 0; i < books.length; ++i) {
                coloans[books[i]] = (coloans[books[i]] || 0) + 1;
              }
              traverse();
            });
          }
          traverse();

          function summariseResult() {
            var result = Object.keys(coloans).map(function(coloan) {
              var n = coloans[coloan];
              var total = +coloan.split(',')[1];
              var weight = n / Math.log(total + 10) * 1000 | 0;
              return [coloan.split(',')[0], weight];
            });
            result.sort(function(a, b) {
              return b[1] - a[1];
            });
            console.log('time:', (Date.now() - t0) / 1000);
            result = JSON.stringify(result.slice(0, relatedCount));
            relatedDB.put(lid, result);
            return res.end(result);
          }
        });
    });
  }

  http.createServer(function(req, res) {
    res.writeHead(200, {
      'Content-Type': 'application/json; charset=utf-8',
      'Access-Control-Allow-Origin': '*'
    });

    var urlParts = req.url.split('/');
    if (urlParts[1] === 'info') {
      lidInfoDB.get(urlParts[2], function(err, data) {
        res.end(err ? '{"error":"local id not found"}' : data);
      });
    } else if (urlParts[1] === 'related') {
      related(urlParts[2], res);
    } else {
      res.end('{"error":"unsupported method"}');
    }
  }).listen(process.env.PORT || 1337, '0.0.0.0');
})();
<|endoftext|>