<commit_before>/**
 *
 * Basic WiFi Manager for Linux based systems, like Raspberry Pi.
 * For network generation the generation is:
 *
 * 1. Generate the configuration file based on passed in SSID & network password.
 * 2. Start the HOSTAPD service based on the configuration file.
 * 3. Start the DHCP service.
 *
 *
 * If this code works it was created by Ken W. Alger on 8/28/2015.
 * If not, I don't know who wrote it.
 *
 */

var fs = require('fs');

var COMMANDS = {
    dhcp: 'sudo service udhcpd start',
    dhcp_disable: 'sudo service udhcpd stop',
    host: 'sudo service hostapd start',
    host_disable: 'sudo service hostapd stop',
    host_status: 'sudo service hostapd status'
};

/**
 * Configuration of the Hostapd service
 * https://w1.fi/hostapd/
 *
 * hostapd is a user space daemon for access point and authentication servers.
 *
 */

var startHostapdService = require('child_process').exec,
    sudo_hostapd = startHostapdService(COMMANDS.host);

var stopHostapdService = require('child_process').exec,
    sudo_stopHostpd = stopHostapdService(COMMANDS.host_disable);

/**
 * Configures the start of the DHCP service, we are utilizing udhcpd
 * http://manpages.ubuntu.com/manpages/hardy/man8/udhcpd.8.html
 *
 * A very small DHCP server which negotiates leases with DHCP clients
 *
 */

var startDHCPService = require('child_process').exec,
    sudo_udhcpd = startDHCPService(COMMANDS.dhcp);

var stopDHCPService = require('child_process').exec,
    sudo_stopDHCP = stopDHCPService(COMMANDS.dhcp_disable);

/**
 * defaultValues for the hostapd.conf file
 *
 * @type {{interface: string, driver: string, ssid: string, hw_mode: string, channel: string, macaddr_acl: string, auth_algs: string, ignore_broadcast_ssid: string, wpa: string, wpa_passphrase: string, wpa_key_mgmt: string, wpa_pairwise: string, rsn_pairwise: string}}
 */

var defaultValues = {
    interface: "wlan0",
    driver: "rtl871xdrv",
    //ssid: "thingsSDK",
    hw_mode: "g",
    channel: "6",
    macaddr_acl: "0",
    auth_algs: "1",
    ignore_broadcast_ssid: "0",
    wpa: "2",
    //wpa_passphrase: "Chalkers",
    wpa_key_mgmt: "WPA-PSK",
    wpa_pairwise: "TKIP",
    rsn_pairwise: "CCMP"
};

/**
 * Generates the configuration key:value pairs for the configuration file.
 */

var fileoutput = Object.keys(defaultValues).map(function(key){
    return key + "=" + defaultValues[key];
}).join("\n");

function BasicManager () {

}

/**
 * createAdHocNetwork() configures the hostapd.conf file based on the ssid and password variables supplied and then
 * starts the required services.
 *
 * @param ssid The broadcasted network name
 * @param wpa_passphrase The password for network access
 */

BasicManager.prototype.createAdHocNetwork = function (ssid, wpa_passphrase) {

    ssid = typeof ssid !== undefined ? ssid : 'thingsSDK';
    wpa_passphrase = typeof wpa_passphrase !== undefined ? wpa_passphrase : 'Chalkers';

    // Generate the hostapd.conf file required for the WiFi Network

    fs.writeFile("/etc/hostapd/hostapd.conf",
        fileoutput + "\n" +
        "ssid=" + ssid + "\n" +
        "wpa_passphrase=" + wpa_passphrase + "\n",
        function (err)  {
            if(err) {
                return console.log(err);
            }

            console.log("[WIFIMANAGER] hostapd.conf was successfully saved.");
            console.info("[WIFIMANAGER] Network name: " + ssid);
            console.info("[WIFIMANAGER] Network password: " + wpa_passphrase);

        }
    );

    // Start the hostapd (wifi management service)
    // Using user: thingssdk, sudo access to start services restricted in the /etc/sudoer file

    console.log("[WIFIMANAGER] Attempting to start HOSTAPD service for network " + ssid + ".");
    sudo_hostapd.stdout.on('data', function(data) {
        console.log('Starting HOSTAPD service - stdout: ' + data);
    });

    // Start the DHCP Server

    console.log("[WIFIMANAGER] Attempting to start UDHCPD service.");
    sudo_udhcpd.stdout.on('data', function(data) {
        console.log('Starting UDHCPD service - stdout: ' + data);
    });
};

BasicManager.prototype.connect = function() {
    //TODO: Connect the device to a network
};

BasicManager.prototype.isConnected = function() {
    //TODO: Check to see if the device is connected to any network
};

BasicManager.prototype.isAdHocNetwork = function() {
    //TODO: Check to see if the network to which the device is connected is an AdHoc network

    // if isConnected() is false, then we don't need to continue
    // if isConnected() is true, then check if network SSID is the same as the created network
}

/**
 * stopAdHocNetwork() stops the required services.
 */
BasicManager.prototype.stopAdHocNetwork = function() {

    // Stop the DHCP Service
    sudo_stopDHCP.stdout.on('data', function (data) {
        console.log('Stopping the DHCP Service: \n' + data);
    });

    // Stop the Wifi Management Service
    sudo_stopHostpd.stdout.on('data', function(data) {
        console.log('Stopping Hostapd Service = stdout: \n' + data) ;
    });
};

//BasicManager.createAdHocNetwork("someNetwork", "password");
module.exports = BasicManager;<commit_msg>fs.writeFileSync<commit_after>/**
 *
 * Basic WiFi Manager for Linux based systems, like Raspberry Pi.
 * For network generation the generation is:
 *
 * 1. Generate the configuration file based on passed in SSID & network password.
 * 2. Start the HOSTAPD service based on the configuration file.
 * 3. Start the DHCP service.
 *
 *
 * If this code works it was created by Ken W. Alger on 8/28/2015.
 * If not, I don't know who wrote it.
 *
 */

var fs = require('fs');

var COMMANDS = {
    dhcp: 'sudo service udhcpd start',
    dhcp_disable: 'sudo service udhcpd stop',
    host: 'sudo service hostapd start',
    host_disable: 'sudo service hostapd stop',
    host_status: 'sudo service hostapd status'
};

/**
 * Configuration of the Hostapd service
 * https://w1.fi/hostapd/
 *
 * hostapd is a user space daemon for access point and authentication servers.
 *
 */

var startHostapdService = require('child_process').exec,
    sudo_hostapd = startHostapdService(COMMANDS.host);

var stopHostapdService = require('child_process').exec,
    sudo_stopHostpd = stopHostapdService(COMMANDS.host_disable);

/**
 * Configures the start of the DHCP service, we are utilizing udhcpd
 * http://manpages.ubuntu.com/manpages/hardy/man8/udhcpd.8.html
 *
 * A very small DHCP server which negotiates leases with DHCP clients
 *
 */

var startDHCPService = require('child_process').exec,
    sudo_udhcpd = startDHCPService(COMMANDS.dhcp);

var stopDHCPService = require('child_process').exec,
    sudo_stopDHCP = stopDHCPService(COMMANDS.dhcp_disable);

/**
 * defaultValues for the hostapd.conf file
 *
 * @type {{interface: string, driver: string, ssid: string, hw_mode: string, channel: string, macaddr_acl: string, auth_algs: string, ignore_broadcast_ssid: string, wpa: string, wpa_passphrase: string, wpa_key_mgmt: string, wpa_pairwise: string, rsn_pairwise: string}}
 */

var defaultValues = {
    interface: "wlan0",
    driver: "rtl871xdrv",
    //ssid: "thingsSDK",
    hw_mode: "g",
    channel: "6",
    macaddr_acl: "0",
    auth_algs: "1",
    ignore_broadcast_ssid: "0",
    wpa: "2",
    //wpa_passphrase: "Chalkers",
    wpa_key_mgmt: "WPA-PSK",
    wpa_pairwise: "TKIP",
    rsn_pairwise: "CCMP"
};

/**
 * Generates the configuration key:value pairs for the configuration file.
 */

var fileoutput = Object.keys(defaultValues).map(function(key){
    return key + "=" + defaultValues[key];
}).join("\n");

function BasicManager () {

}

/**
 * createAdHocNetwork() configures the hostapd.conf file based on the ssid and password variables supplied and then
 * starts the required services.
 *
 * @param ssid The broadcasted network name
 * @param wpa_passphrase The password for network access
 */

BasicManager.prototype.createAdHocNetwork = function (ssid, wpa_passphrase) {

    ssid = typeof ssid !== undefined ? ssid : 'thingsSDK';
    wpa_passphrase = typeof wpa_passphrase !== undefined ? wpa_passphrase : 'Chalkers';

    // Generate the hostapd.conf file required for the WiFi Network

    fs.writeFileSync("/etc/hostapd/hostapd.conf",
        fileoutput + "\n" +
        "ssid=" + ssid + "\n" +
        "wpa_passphrase=" + wpa_passphrase + "\n",
        function (err)  {
            if(err) {
                return console.log(err);
            }

            console.log("[WIFIMANAGER] hostapd.conf was successfully saved.");
            console.info("[WIFIMANAGER] Network name: " + ssid);
            console.info("[WIFIMANAGER] Network password: " + wpa_passphrase);

        }
    );

    // Start the hostapd (wifi management service)
    // Using user: thingssdk, sudo access to start services restricted in the /etc/sudoer file

    console.log("[WIFIMANAGER] Attempting to start HOSTAPD service for network " + ssid + ".");
    sudo_hostapd.stdout.on('data', function(data) {
        console.log('Starting HOSTAPD service - stdout: ' + data);
    });

    // Start the DHCP Server

    console.log("[WIFIMANAGER] Attempting to start UDHCPD service.");
    sudo_udhcpd.stdout.on('data', function(data) {
        console.log('Starting UDHCPD service - stdout: ' + data);
    });
};

BasicManager.prototype.connect = function() {
    //TODO: Connect the device to a network
};

BasicManager.prototype.isConnected = function() {
    //TODO: Check to see if the device is connected to any network
};

BasicManager.prototype.isAdHocNetwork = function() {
    //TODO: Check to see if the network to which the device is connected is an AdHoc network

    // if isConnected() is false, then we don't need to continue
    // if isConnected() is true, then check if network SSID is the same as the created network
}

/**
 * stopAdHocNetwork() stops the required services.
 */
BasicManager.prototype.stopAdHocNetwork = function() {

    // Stop the DHCP Service
    sudo_stopDHCP.stdout.on('data', function (data) {
        console.log('Stopping the DHCP Service: \n' + data);
    });

    // Stop the Wifi Management Service
    sudo_stopHostpd.stdout.on('data', function(data) {
        console.log('Stopping Hostapd Service = stdout: \n' + data) ;
    });
};

//BasicManager.createAdHocNetwork("someNetwork", "password");
module.exports = BasicManager;<|endoftext|>


<commit_before>var seleniumServer = require('selenium-server');
var phantomjs = require('phantomjs-prebuilt')

module.exports = {
	"src_folders": ["tests"],
	"output_folder": "reports",
	"custom_commands_path": "",
	"custom_assertions_path": "",
	"page_objects_path": "",
	"globals_path": "",

	"selenium": {
		"start_process": true,
		"server_path": seleniumServer.path,
		"host": "127.0.0.1",
		"port": 4444,
		"cli_args": {
			"webdriver.chrome.driver": "./bin/drivers/chromedriver",
			"webdriver.gecko.driver" : "./bin/drivers/geckodriver"
		}
	},

	"test_settings": {
		"default": {
			"launch_url": "localhost",
			"selenium_host": "localhost",
			"selenium_port": 4444,
			"pathname": "/wd/hub",
			"silent": true,
			"screenshots": {
				"enabled": false,
				"path": ""
			},
			"desiredCapabilities": {
				"browserName": "chrome"
			}
		},

		"ci": {
			"desiredCapabilities": {
				"browserName": "firefox"
			}
		},

		"phantom": {
			"desiredCapabilities": {
				"browserName": "phantomjs",
				"phantomjs.binary.path": phantomjs.path,
			}
		}
	}
}
<commit_msg>Add correct URL to config<commit_after>var seleniumServer = require('selenium-server');
var phantomjs = require('phantomjs-prebuilt')

module.exports = {
	"src_folders": ["tests"],
	"output_folder": "reports",
	"custom_commands_path": "",
	"custom_assertions_path": "",
	"page_objects_path": "",
	"globals_path": "",

	"selenium": {
		"start_process": true,
		"server_path": seleniumServer.path,
		"host": "127.0.0.1",
		"port": 4444,
		"cli_args": {
			"webdriver.chrome.driver": "./bin/drivers/chromedriver",
			"webdriver.gecko.driver" : "./bin/drivers/geckodriver"
		}
	},

	"test_settings": {
		"default": {
			"launch_url": "http://dev.matthewroach.me/login/",
			"selenium_host": "localhost",
			"selenium_port": 4444,
			"pathname": "/wd/hub",
			"silent": true,
			"screenshots": {
				"enabled": false,
				"path": ""
			},
			"desiredCapabilities": {
				"browserName": "chrome"
			}
		},

		"ci": {
			"desiredCapabilities": {
				"browserName": "firefox"
			}
		},

		"phantom": {
			"desiredCapabilities": {
				"browserName": "phantomjs",
				"phantomjs.binary.path": phantomjs.path,
			}
		}
	}
}
<|endoftext|>


<commit_before>export default {
  SHROUDED_SUFFOCATION: {
    id: 279703,
    name: 'Shrouded Suffocation',
    icon: 'ability_rogue_garrote',
  },
  DOUBLE_DOSE: {
    id: 273009,
    name: 'Double Dose',
    icon: 'ability_rogue_shadowstrikes',
  },
  PERFORATE: {
    id: 277673,
    name: 'Perforate',
    icon: 'ability_backstab',
  },
  THE_FIRST_DANCE: {
    id: 278981,
    name: 'The First Dance',
    icon: 'ability_rogue_shadowdance',
  },
};
<commit_msg>Update rogue.js<commit_after>export default {
  SHROUDED_SUFFOCATION: {
    id: 279703,
    name: 'Shrouded Suffocation',
    icon: 'ability_rogue_garrote',
  },
  DOUBLE_DOSE: {
    id: 273009,
    name: 'Double Dose',
    icon: 'ability_rogue_shadowstrikes',
  },
  PERFORATE: {
    id: 277673,
    name: 'Perforate',
    icon: 'ability_backstab',
  },

  //Outlaw Specific Azerite Traits
  KEEP_YOUR_WITS_ABOUT_YOU: {
    id: 288979,
    name: 'Keep Your Wits About You',
    icon: 'ability_warrior_punishingblow',
  },
  //Subtelty Specific Azerite Traits
  THE_FIRST_DANCE: {
    id: 278981,
    name: 'The First Dance',
    icon: 'ability_rogue_shadowdance',
  },
  NIGHTS_VENGEANCE
  },

  //Assassination Specific Azerite Traits

};
<|endoftext|>


<commit_before>/**
 * WP Present - admin.js
 *
 */

// Hide the description fields as fast as possible
/*
jQuery('label[for="description"]').parent().parent().hide();
jQuery('#tag-description').closest('.form-field').hide();
jQuery('#description').closest('.form-field').hide();
jQuery('.column-description').hide();
*/

// jQuery Modal Things
jQuery(document).ready(function($) {

	if( 'undefined' == typeof(tinymce) ) {
//		alert( 'tinymce init' );
//		tinymce.execCommand('mceRemoveControl',true,'editor_slide');
//		tinymce.execCommand('mceAddControl',true,'editor_slide');
	}

	$('#add-button, .widget-control-edit').on('click', function(e) {

		e.preventDefault();

		$button = $(this);

		var $parentWidget = $button.parents('.widget');
		var $widgetPreview = $parentWidget.find('.widget-preview');

		// Send the contents from the widget to the editor
		var contentEditor  = $widgetPreview.html();
		var widgetID = $parentWidget.find('.slide-id').val();

		$('#editor_slide-tmce').click(); //Necessary on subsequent loads of the editor
		$( "#dialog" ).dialog({
		  autoOpen: true,
		  width: 600,
		  height: 600,
		  modal: false,
		  buttons: {
			"Save": function() {
				var editorContents = tinymce.get('editor_slide').getContent();
				var params = { content:editorContents };
				// Send the contents of the existing post
				$.ajax({
					url: ajaxurl + '?action=update_slide&id=' + widgetID,
					type: 'POST',
				  	data: jQuery.param(params),
				  	success: function(result) {
						// Return the excerpt from the editor
						$widgetPreview.html( result );
				  }
				});
				closeModal();
			},
			Cancel: function() {
				closeModal();
			}
		  },
		  create: function() {
				tinymce.execCommand('mceRemoveControl',true,'editor_slide');
				tinymce.execCommand('mceAddControl',true,'editor_slide');

//				tinymce.ScriptLoader.load('customizer.js');

				// Load a script from a specific URL using the global script loader
		        //tinymce.ScriptLoader.load('http://localhost/sandbox/wp-includes/js/admin-bar.min.js');

		  },
		  open: function() {

				// Load the contents of the existing post
				$.ajax({
				  url: ajaxurl + '?action=get_slide&id=' + widgetID,
				  success: function(contentEditor) {
				  	tinymce.get('editor_slide').setContent(contentEditor);
				  }
				});

				// Hack for getting the reveal class added to tinymce editor body
				var $editorIframe = $('#editor_slide_ifr').contents();
				$editorIframe.find('body').addClass('reveal');

		  },
		  close: function() {
				closeModal();
		  }
		});
	});

	function closeModal() {
		tinymce.execCommand('mceRemoveControl',true,'editor_slide');
		$( '#dialog' ).dialog( "close" );
//		console.log('tinymce shutdown');
	}

	// Expand slide details
	$('.widget-title-action').on('click', function(e) {
		$( this ).parents('.widget').children('.widget-inside').toggle();
	});

});

jQuery(document).ready(function($){

	function backfillSlides() {
		var numSlides = WPP_NumSlides;
		var numExisting = $('#container > .column').size();

		//alert( 'existing: ' + numExisting + ', needed: ' + numSlides );

		for (var col=numExisting+1;col<=numSlides;col++){
			$('#container').append( '

'+col+'

' );
		}
		$('#container').append( '

' );
	}

	// Make the outer container resizeable
	$( "#outer-container" ).resizable();

	// Resize the container assuming only 1 slide per column
	// 25px is to allow for the padding between cells
	$('#container').width( ( $( ".portlet" ).length ) * ($( ".column" ).width()+25) );

	backfillSlides();

	$( ".column-inner" ).sortable({
		connectWith: ".column-inner",
		stop: function( event, ui ) {
			updateColumns();
		}
	});

	$( "#container" ).sortable({
		stop: function( event, ui ) {
			updateColumns();
		}
	});

	updateColumns();

	$( ".column-inner" ).disableSelection();

	// Not part of the other stuff;
	$('#tidy-button').click(function(e) {
		e.preventDefault();
		consolidateColumns();
	});

	function updateColumns() {

		var columns = { }; // Creates a new object
		var i = 1;
		$( '.column-inner' ).each(function( index ) {

			var $order = $(this).sortable( "toArray" );
			columns['col-'+i] = $order;
			i++;

//			console.log( 'index ' + index );
//			console.log( 'order ' + $order );
//			console.log(columns);
		});

		//console.log(columns);
		var encoded = JSON.stringify( columns );
		$('#description').val(encoded);
	}

	function consolidateColumns(){ // AKA "Tidy Button"

		var numCols = $('.column').length;
//		console.log(numCols);

		$('.column').each(function(outerIndex){

			// Don't have a col 0
			var outerIndex = outerIndex + 1;

			// Fixes the condition where we are looking at the last item
			if( outerIndex >= numCols )
				return;

			var $outerCol = $(this);
			var $innerCol = $outerCol.children('.column-inner');

			var innerHTML = $innerCol.html().trim();
			var outerHTML = $outerCol.html().trim();

			if( typeof(innerHTML) !== 'string' || '' == innerHTML ) {
				var $nextOuterCol = $('#col-'+(outerIndex+1));
				var $nextInnerCol = $nextOuterCol.children('.column-inner');

				var nextInnerHTML = $nextInnerCol.html().trim();
				var nextOuterHTML = $nextOuterCol.html().trim();

				$outerCol.html(nextOuterHTML);
				$nextOuterCol.html(outerHTML);
			}
		} );

		//Finally refresh description array
		$( ".column-inner" ).sortable({
			connectWith: ".column-inner",
			stop: (function( event, ui ) {
				updateColumns();
			}),
			create: (function( event, ui ) {
				updateColumns();
			})
		});
		updateColumns();
	} // end consolidate

	// Append an inner column to each column that doesn't contain any slides.
	jQuery('.column' ).not(":has(div.column-inner)").append('

');
	$( ".column-inner" ).sortable({
		connectWith: ".column-inner",
		stop: function( event, ui ) {
			updateColumns();
		}
	});

	// Prevent the post from being published or updated if no primary category is selected
	$(document).on('.button', '#publishing-action', function() {
		//if( $('#ione_primary_category_select_id' ).val() < 0 ) {
			alert( 'You must first select a Primary Category.' );
			return false;
		//}
		//else{
//			// Ensure the category checkbox corresponding to the selected primary category is checked
//			var checkbox_id = 'in-category-' + $('#ione_primary_category_select_id' ).val();
//			$('#'+checkbox_id).attr('checked', true);
		//}
	} );
	return false;

});<commit_msg>Adds column selection<commit_after>/**
 * WP Present - admin.js
 *
 */

// Hide the description fields as fast as possible
/*
jQuery('label[for="description"]').parent().parent().hide();
jQuery('#tag-description').closest('.form-field').hide();
jQuery('#description').closest('.form-field').hide();
jQuery('.column-description').hide();
*/

// jQuery Modal Things
jQuery(document).ready(function($) {

	if( 'undefined' == typeof(tinymce) ) {
//		alert( 'tinymce init' );
//		tinymce.execCommand('mceRemoveControl',true,'editor_slide');
//		tinymce.execCommand('mceAddControl',true,'editor_slide');
	}

	/* Column click columns */
	function activate_column( $col ) {
		$('.widget-title').css('background', '');
		$('.widget-title').removeClass('active');
		//if there are no active columns.
		$col.css('background', 'cyan');
		$col.addClass('active');
	}
	activate_column( $('#col-1').children('.widget-top').children('.widget-title') );

	$('.column').children('.widget-top').children('.widget-title').on('click', function() {
		$col = $(this);
		activate_column($col);
	});

	$('#add-button, .widget-control-edit').on('click', function(e) {

		e.preventDefault();

		$button = $(this);

		var $parentWidget = $button.parents('.widget');
		var $widgetPreview = $parentWidget.find('.widget-preview');

		// Send the contents from the widget to the editor
		var contentEditor  = $widgetPreview.html();
		var widgetID = $parentWidget.find('.slide-id').val();

		$('#editor_slide-tmce').click(); //Necessary on subsequent loads of the editor
		$( "#dialog" ).dialog({
		  autoOpen: true,
		  width: 600,
		  height: 600,
		  modal: false,
		  buttons: {
			"Save": function() {
				var editorContents = tinymce.get('editor_slide').getContent();
				var params = { content:editorContents };
				// Send the contents of the existing post
				$.ajax({
					url: ajaxurl + '?action=update_slide&id=' + widgetID,
					type: 'POST',
				  	data: jQuery.param(params),
				  	success: function(result) {
						// Return the excerpt from the editor
						$widgetPreview.html( result );
				  }
				});
				closeModal();
			},
			Cancel: function() {
				closeModal();
			}
		  },
		  create: function() {
				tinymce.execCommand('mceRemoveControl',true,'editor_slide');
				tinymce.execCommand('mceAddControl',true,'editor_slide');

//				tinymce.ScriptLoader.load('customizer.js');

				// Load a script from a specific URL using the global script loader
		        //tinymce.ScriptLoader.load('http://localhost/sandbox/wp-includes/js/admin-bar.min.js');

		  },
		  open: function() {

				// Load the contents of the existing post
				$.ajax({
				  url: ajaxurl + '?action=get_slide&id=' + widgetID,
				  success: function(contentEditor) {
				  	tinymce.get('editor_slide').setContent(contentEditor);
				  }
				});

				// Hack for getting the reveal class added to tinymce editor body
				var $editorIframe = $('#editor_slide_ifr').contents();
				$editorIframe.find('body').addClass('reveal');

		  },
		  close: function() {
				closeModal();
		  }
		});
	});

	function closeModal() {
		tinymce.execCommand('mceRemoveControl',true,'editor_slide');
		$( '#dialog' ).dialog( "close" );
//		console.log('tinymce shutdown');
	}

	// Expand slide details
	$('.widget-title-action').on('click', function(e) {
		$( this ).parents('.widget').children('.widget-inside').toggle();
	});

});

jQuery(document).ready(function($){

	function backfillSlides() {
		var numSlides = WPP_NumSlides;
		var numExisting = $('#container > .column').size();

		//alert( 'existing: ' + numExisting + ', needed: ' + numSlides );

		for (var col=numExisting+1;col<=numSlides;col++){
			$('#container').append( '

'+col+'

' );
		}
		$('#container').append( '

' );
	}

	// Make the outer container resizeable
	$( "#outer-container" ).resizable();

	// Resize the container assuming only 1 slide per column
	// 25px is to allow for the padding between cells
	$('#container').width( ( $( ".portlet" ).length ) * ($( ".column" ).width()+25) );

	backfillSlides();

	$( ".column-inner" ).sortable({
		connectWith: ".column-inner",
		stop: function( event, ui ) {
			updateColumns();
		}
	});

	$( "#container" ).sortable({
		stop: function( event, ui ) {
			updateColumns();
		}
	});

	updateColumns();

	$( ".column-inner" ).disableSelection();

	// Not part of the other stuff;
	$('#tidy-button').click(function(e) {
		e.preventDefault();
		consolidateColumns();
	});

	function updateColumns() {

		var columns = { }; // Creates a new object
		var i = 1;
		$( '.column-inner' ).each(function( index ) {

			var $order = $(this).sortable( "toArray" );
			columns['col-'+i] = $order;
			i++;

//			console.log( 'index ' + index );
//			console.log( 'order ' + $order );
//			console.log(columns);
		});

		//console.log(columns);
		var encoded = JSON.stringify( columns );
		$('#description').val(encoded);
	}

	function consolidateColumns(){ // AKA "Tidy Button"

		var numCols = $('.column').length;
//		console.log(numCols);

		$('.column').each(function(outerIndex){

			// Don't have a col 0
			var outerIndex = outerIndex + 1;

			// Fixes the condition where we are looking at the last item
			if( outerIndex >= numCols )
				return;

			var $outerCol = $(this);
			var $innerCol = $outerCol.children('.column-inner');

			var innerHTML = $innerCol.html().trim();
			var outerHTML = $outerCol.html().trim();

			if( typeof(innerHTML) !== 'string' || '' == innerHTML ) {
				var $nextOuterCol = $('#col-'+(outerIndex+1));
				var $nextInnerCol = $nextOuterCol.children('.column-inner');

				var nextInnerHTML = $nextInnerCol.html().trim();
				var nextOuterHTML = $nextOuterCol.html().trim();

				$outerCol.html(nextOuterHTML);
				$nextOuterCol.html(outerHTML);
			}
		} );

		//Finally refresh description array
		$( ".column-inner" ).sortable({
			connectWith: ".column-inner",
			stop: (function( event, ui ) {
				updateColumns();
			}),
			create: (function( event, ui ) {
				updateColumns();
			})
		});
		updateColumns();
	} // end consolidate

	// Append an inner column to each column that doesn't contain any slides.
	jQuery('.column' ).not(":has(div.column-inner)").append('

');
	$( ".column-inner" ).sortable({
		connectWith: ".column-inner",
		stop: function( event, ui ) {
			updateColumns();
		}
	});

	// Prevent the post from being published or updated if no primary category is selected
	$(document).on('.button', '#publishing-action', function() {
		//if( $('#ione_primary_category_select_id' ).val() < 0 ) {
			alert( 'You must first select a Primary Category.' );
			return false;
		//}
		//else{
//			// Ensure the category checkbox corresponding to the selected primary category is checked
//			var checkbox_id = 'in-category-' + $('#ione_primary_category_select_id' ).val();
//			$('#'+checkbox_id).attr('checked', true);
		//}
	} );
	return false;

});<|endoftext|>


<commit_before>lingcod.rest.kmlEditor = function(options){

    if(!options || !options.url || !options.appendTo || !options.gex || !options.ge || !options.div || !options.client){
        throw('kmlEditor needs url, appendTo, ge, gex, client, and div options');
    }

    var kmlLoaded = function(e, kml){
        tbar.setEnabled(true);
        $(tree).unbind('kmlLoaded', kmlLoaded);
        var configs = options.client.parseDocument(kml.getKml());
        while(create_menu.getItemCount() > 0){
            create_menu.removeItemAt(0);
        }
        for(var key in configs){
            var config = configs[key];
            var item = new goog.ui.MenuItem(config.title);
            create_menu.addItem(item);
            item.mm_data = config;
        }
        that.kmlEl.addClass('kmlEditor');
        var a = that.kmlEl.find('> .marinemap-tree-category > a');
        that.kmlEl.find('> .marinemap-tree-category > span.badges').remove();
        that.el.find('h1').text(a.text());
        a.hide();
    }

    var that = {};

    that.el = $('

');

    that.kmlEl = that.el.find('.kmllist');

    // var create_menu_children = function(){
    //     var children = [];
    //     var attr = new goog.ui.MenuItem('View Attributes');
    //     children.push(attr);
    //     var edit = new goog.ui.MenuItem('Edit');
    //     children.push(edit);
    //     var copy = new goog.ui.MenuItem('Copy');
    //     children.push(copy);
    //     var share = new goog.ui.MenuItem('Share');
    //     children.push(share);
    //     children.push(new goog.ui.MenuSeparator());
    //     return children;
    // }

    var refresh = function(callback){
        tbar.setEnabled(false);
        var cback = function(e, kmlObject){
            tbar.setEnabled(true);
            $(tree).unbind('kmlLoaded', cback);
            callback(e, kmlObject);
        }
        $(tree).bind('kmlLoaded', cback);
        tree.refresh(true);
        setSelectionMenuItemEnabled(false);
    }

    that.refresh = refresh;

    var setSelectionMenuItemEnabled = function(enabled){
        for(var i=0;i<enableWhenSelected.length;i++){
            enableWhenSelected[i].setEnabled(enabled);
        }
    }

    var tbar = new goog.ui.Toolbar();
    var create_menu = new goog.ui.Menu();

    if (!options.shared) {
        var create_button = new goog.ui.ToolbarMenuButton('Create New', create_menu);
        tbar.addChild(create_button, true);
        goog.events.listen(create_menu, 'action', function(e) {
            tree.clearSelection();
            options.client.create(e.target.mm_data, {
                success: function(location){
                    refresh(function(){
                        var node = tree.getNodesById(location);
                        tree.selectNode(node, tree.lookup(node));
                        options.client.show(tree.lookup(node));
                    });
                },
                error: function(){
                    alert('An error occured while saving your data. If the problem persists, please contact an administrator at help@marinemap.org.');
                }
            });
        });
    }

    // For testing purposes only, will be removed on launch
    var ref = new goog.ui.ToolbarButton('Refresh');
    ref.setEnabled(true);
    goog.events.listen(ref, 'action', function(e) {
        refresh();
    });
    tbar.addChild(ref, true);

    tbar.addChild(new goog.ui.ToolbarSeparator(), true);

    var attr = new goog.ui.ToolbarButton('Attributes');
    attr.setEnabled(false);
    attr.setTooltip("Show the selected feature's attributes");
    goog.events.listen(attr, 'action', function(e) {
        options.client.show(tree.lookup(that.selected));
    });
    tbar.addChild(attr, true);

    if (!options.shared) {
        var edit = new goog.ui.ToolbarButton('Edit');
        edit.setEnabled(false);
        goog.events.listen(edit, 'action', function(e) {
            tbar.setEnabled(false);
            options.ge.setBalloon(null);
            var kmlObject = tree.lookup(that.selected);
            kmlObject.setVisibility(false);
            options.client.update(kmlObject, {
                success: function(location){
                    tbar.setEnabled(true);
                    refresh(function(){
                        var node = tree.getNodesById(location);
                        tree.selectNode(node, tree.lookup(node));
                        options.client.show(tree.lookup(node));
                    });
                },
                cancel: function(){
                    tbar.setEnabled(true);
                    kmlObject.setVisibility(true);
                    tree.selectById(kmlObject.getId());
                },
                error: function(){
                    tbar.setEnabled(true);
                    alert('An error occured while saving your data. If the problem persists, please contact an administrator at help@marinemap.org.');
                    kmlObject.setVisibility(true);
                    tree.selectById(kmlObject.getId());
                }
            });
        });
        tbar.addChild(edit, true);
    }

    if (!options.shared) {
        var del = new goog.ui.ToolbarButton('Delete');
        del.setEnabled(false);
        goog.events.listen(del, 'action', function(e) {
            tbar.setEnabled(false);
            var kmlObject = tree.lookup(that.selected);
            options.client.destroy(kmlObject, {
                success: function(location){
                    tbar.setEnabled(true);
                    refresh();
                },
                error: function(){
                    tbar.setEnabled(true);
                    alert('An error occured while trying to delete this feature.');
                },
                cancel: function(){
                    tbar.setEnabled(true);
                }
            });
        });
        tbar.addChild(del, true);
    }

    var export_menu = new goog.ui.Menu();
    // export_menu.addItem(new goog.ui.MenuItem('to kml (Google Earth)'));
    // export_menu.addItem(new goog.ui.MenuItem('to shapefile'));
    var export_button = new goog.ui.ToolbarMenuButton('Export', export_menu);
    export_button.setEnabled(false);
    tbar.addChild(export_button, true);

    var copy = new goog.ui.ToolbarButton('Copy');
    copy.setEnabled(false);
    copy.setTooltip("Copy the selected feature");
    goog.events.listen(copy, 'action', function(e) {
        kmlObject = tree.lookup(that.selected);
        options.client.copy(kmlObject, {
            success: function(location){
                tbar.setEnabled(true);
                // MP TODO : If we're in the shared shapes panel,
                // switch to myshapes and refresh on that kml-tree
                refresh(function(){
                    tree.clearSelection();
                    var node = tree.getNodesById(location);
                    tree.selectNode(node, tree.lookup(node));
                    options.client.show(tree.lookup(node));
                });
            },
            error: function(){
                tbar.setEnabled(true);
                alert('An error occured while copying. If the problem persists, please contact an administrator at help@marinemap.org.');
                kmlObject.setVisibility(true);
                tree.selectById(kmlObject.getId());
            }
        });
    });
    tbar.addChild(copy, true);

    if (!options.shared) {
        var share = new goog.ui.ToolbarButton('Share');
        share.setEnabled(false);
        share.setTooltip("Share the selected feature");
        goog.events.listen(share, 'action', function(e) {
            options.client.share(tree.lookup(that.selected));
        });
        tbar.addChild(share, true);
    }

    if (options.shared) {
        var enableWhenSelected = [attr, export_button, copy];
    } else {
        var enableWhenSelected = [attr, edit, del, export_button, copy, share];
    }

    tbar.render(that.el.find('.toolbar')[0]);

    $(options.appendTo).append(that.el);

    var visitFunction = function(kmlObject, config){
        var self = $(kmlObject.getKml()).find('>Placemark>atom\\:link[rel=self], >NetworkLink>atom\\:link[rel=self]');
        if(self.length === 1){
            config.fireEvents = true;
            config.select = true;
            config['customClass'] = self.attr('mm:model') || '';
        }
        return config;
    };

    var tree = lingcod.kmlTree({
        url: options.url,
        ge: options.ge,
        gex: options.gex,
        animate: false,
        map_div: options.div,
        element: that.kmlEl,
        trans: lingcod.options.media_url + 'common/images/transparent.gif',
        title: false,
        visitFunction: visitFunction,
        bustCache: true,
        restoreState: true,
        supportItemIcon: true
    });
    that.tree = tree;

    that.clearSelection = tree.clearSelection;

    $(tree).bind('select', function(e, node, kmlObject){
        if(options.client.inShowState){
            var selectedTab = options.client.panel.getEl().find('.ui-tabs-selected:first a').text();
            options.client.show(kmlObject, {success: function(){
                options.client.panel.getEl().find('.ui-tabs li:contains('+selectedTab+') a').click();
            }});
        }
        that.selected = node;
        setSelectionMenuItemEnabled(!!node);
        // clear export menu
        while(export_menu.getItemCount() > 0){
            var item = export_menu.getItemAt(0);
            export_menu.removeItemAt(0);
            item.dispose();
        }
        if(that.selected){
            addExportItems(export_menu, kmlObject);
        }
    });

    var addExportItems = function(menu, kmlObject){
        $(kmlObject.getKml()).find('atom\\:link[rel=alt]').each(function(){
            var title = $(this).attr('title');
            var href = $(this).attr('href');
            var item = new goog.ui.MenuItem(title);
            menu.addItem(item);
            goog.events.listen(item, 'action', function(e) {
                window.location = href;
            });
        });
    }

    $(tree).bind('dblclick', function(e, node, kmlObject){
        options.client.show(kmlObject);
    });

    $(options.client).bind('saving', function(e, msg){
        tree.showLoading(msg);
    });

    $(options.client).bind('doneSaving', function(e, msg){
        tree.hideLoading();
    });

    tbar.setEnabled(false);
    $(tree).bind('kmlLoaded', kmlLoaded);
    tree.load(true);

    return that;
}
<commit_msg>No longer showing attributes of copy after copying.<commit_after>lingcod.rest.kmlEditor = function(options){

    if(!options || !options.url || !options.appendTo || !options.gex || !options.ge || !options.div || !options.client){
        throw('kmlEditor needs url, appendTo, ge, gex, client, and div options');
    }

    var kmlLoaded = function(e, kml){
        tbar.setEnabled(true);
        $(tree).unbind('kmlLoaded', kmlLoaded);
        var configs = options.client.parseDocument(kml.getKml());
        while(create_menu.getItemCount() > 0){
            create_menu.removeItemAt(0);
        }
        for(var key in configs){
            var config = configs[key];
            var item = new goog.ui.MenuItem(config.title);
            create_menu.addItem(item);
            item.mm_data = config;
        }
        that.kmlEl.addClass('kmlEditor');
        var a = that.kmlEl.find('> .marinemap-tree-category > a');
        that.kmlEl.find('> .marinemap-tree-category > span.badges').remove();
        that.el.find('h1').text(a.text());
        a.hide();
    }

    var that = {};

    that.el = $('

');

    that.kmlEl = that.el.find('.kmllist');

    // var create_menu_children = function(){
    //     var children = [];
    //     var attr = new goog.ui.MenuItem('View Attributes');
    //     children.push(attr);
    //     var edit = new goog.ui.MenuItem('Edit');
    //     children.push(edit);
    //     var copy = new goog.ui.MenuItem('Copy');
    //     children.push(copy);
    //     var share = new goog.ui.MenuItem('Share');
    //     children.push(share);
    //     children.push(new goog.ui.MenuSeparator());
    //     return children;
    // }

    var refresh = function(callback){
        tbar.setEnabled(false);
        var cback = function(e, kmlObject){
            tbar.setEnabled(true);
            $(tree).unbind('kmlLoaded', cback);
            callback(e, kmlObject);
        }
        $(tree).bind('kmlLoaded', cback);
        tree.refresh(true);
        setSelectionMenuItemEnabled(false);
    }

    that.refresh = refresh;

    var setSelectionMenuItemEnabled = function(enabled){
        for(var i=0;i<enableWhenSelected.length;i++){
            enableWhenSelected[i].setEnabled(enabled);
        }
    }

    var tbar = new goog.ui.Toolbar();
    var create_menu = new goog.ui.Menu();

    if (!options.shared) {
        var create_button = new goog.ui.ToolbarMenuButton('Create New', create_menu);
        tbar.addChild(create_button, true);
        goog.events.listen(create_menu, 'action', function(e) {
            tree.clearSelection();
            options.client.create(e.target.mm_data, {
                success: function(location){
                    refresh(function(){
                        var node = tree.getNodesById(location);
                        tree.selectNode(node, tree.lookup(node));
                        options.client.show(tree.lookup(node));
                    });
                },
                error: function(){
                    alert('An error occured while saving your data. If the problem persists, please contact an administrator at help@marinemap.org.');
                }
            });
        });
    }

    // For testing purposes only, will be removed on launch
    var ref = new goog.ui.ToolbarButton('Refresh');
    ref.setEnabled(true);
    goog.events.listen(ref, 'action', function(e) {
        refresh();
    });
    tbar.addChild(ref, true);

    tbar.addChild(new goog.ui.ToolbarSeparator(), true);

    var attr = new goog.ui.ToolbarButton('Attributes');
    attr.setEnabled(false);
    attr.setTooltip("Show the selected feature's attributes");
    goog.events.listen(attr, 'action', function(e) {
        options.client.show(tree.lookup(that.selected));
    });
    tbar.addChild(attr, true);

    if (!options.shared) {
        var edit = new goog.ui.ToolbarButton('Edit');
        edit.setEnabled(false);
        goog.events.listen(edit, 'action', function(e) {
            tbar.setEnabled(false);
            options.ge.setBalloon(null);
            var kmlObject = tree.lookup(that.selected);
            kmlObject.setVisibility(false);
            options.client.update(kmlObject, {
                success: function(location){
                    tbar.setEnabled(true);
                    refresh(function(){
                        var node = tree.getNodesById(location);
                        tree.selectNode(node, tree.lookup(node));
                        options.client.show(tree.lookup(node));
                    });
                },
                cancel: function(){
                    tbar.setEnabled(true);
                    kmlObject.setVisibility(true);
                    tree.selectById(kmlObject.getId());
                },
                error: function(){
                    tbar.setEnabled(true);
                    alert('An error occured while saving your data. If the problem persists, please contact an administrator at help@marinemap.org.');
                    kmlObject.setVisibility(true);
                    tree.selectById(kmlObject.getId());
                }
            });
        });
        tbar.addChild(edit, true);
    }

    if (!options.shared) {
        var del = new goog.ui.ToolbarButton('Delete');
        del.setEnabled(false);
        goog.events.listen(del, 'action', function(e) {
            tbar.setEnabled(false);
            var kmlObject = tree.lookup(that.selected);
            options.client.destroy(kmlObject, {
                success: function(location){
                    tbar.setEnabled(true);
                    refresh();
                },
                error: function(){
                    tbar.setEnabled(true);
                    alert('An error occured while trying to delete this feature.');
                },
                cancel: function(){
                    tbar.setEnabled(true);
                }
            });
        });
        tbar.addChild(del, true);
    }

    var export_menu = new goog.ui.Menu();
    // export_menu.addItem(new goog.ui.MenuItem('to kml (Google Earth)'));
    // export_menu.addItem(new goog.ui.MenuItem('to shapefile'));
    var export_button = new goog.ui.ToolbarMenuButton('Export', export_menu);
    export_button.setEnabled(false);
    tbar.addChild(export_button, true);

    var copy = new goog.ui.ToolbarButton('Copy');
    copy.setEnabled(false);
    copy.setTooltip("Copy the selected feature");
    goog.events.listen(copy, 'action', function(e) {
        kmlObject = tree.lookup(that.selected);
        options.client.copy(kmlObject, {
            success: function(location){
                tbar.setEnabled(true);
                // MP TODO : If we're in the shared shapes panel,
                // switch to myshapes and refresh on that kml-tree
                refresh(function(){
                    tree.clearSelection();
                    var node = tree.getNodesById(location);
                    tree.selectNode(node, tree.lookup(node));
                    // options.client.show(tree.lookup(node));
                });
            },
            error: function(){
                tbar.setEnabled(true);
                alert('An error occured while copying. If the problem persists, please contact an administrator at help@marinemap.org.');
                kmlObject.setVisibility(true);
                tree.selectById(kmlObject.getId());
            }
        });
    });
    tbar.addChild(copy, true);

    if (!options.shared) {
        var share = new goog.ui.ToolbarButton('Share');
        share.setEnabled(false);
        share.setTooltip("Share the selected feature");
        goog.events.listen(share, 'action', function(e) {
            options.client.share(tree.lookup(that.selected));
        });
        tbar.addChild(share, true);
    }

    if (options.shared) {
        var enableWhenSelected = [attr, export_button, copy];
    } else {
        var enableWhenSelected = [attr, edit, del, export_button, copy, share];
    }

    tbar.render(that.el.find('.toolbar')[0]);

    $(options.appendTo).append(that.el);

    var visitFunction = function(kmlObject, config){
        var self = $(kmlObject.getKml()).find('>Placemark>atom\\:link[rel=self], >NetworkLink>atom\\:link[rel=self]');
        if(self.length === 1){
            config.fireEvents = true;
            config.select = true;
            config['customClass'] = self.attr('mm:model') || '';
        }
        return config;
    };

    var tree = lingcod.kmlTree({
        url: options.url,
        ge: options.ge,
        gex: options.gex,
        animate: false,
        map_div: options.div,
        element: that.kmlEl,
        trans: lingcod.options.media_url + 'common/images/transparent.gif',
        title: false,
        visitFunction: visitFunction,
        bustCache: true,
        restoreState: true,
        supportItemIcon: true
    });
    that.tree = tree;

    that.clearSelection = tree.clearSelection;

    $(tree).bind('select', function(e, node, kmlObject){
        if(options.client.inShowState){
            var selectedTab = options.client.panel.getEl().find('.ui-tabs-selected:first a').text();
            options.client.show(kmlObject, {success: function(){
                options.client.panel.getEl().find('.ui-tabs li:contains('+selectedTab+') a').click();
            }});
        }
        that.selected = node;
        setSelectionMenuItemEnabled(!!node);
        // clear export menu
        while(export_menu.getItemCount() > 0){
            var item = export_menu.getItemAt(0);
            export_menu.removeItemAt(0);
            item.dispose();
        }
        if(that.selected){
            addExportItems(export_menu, kmlObject);
        }
    });

    var addExportItems = function(menu, kmlObject){
        $(kmlObject.getKml()).find('atom\\:link[rel=alt]').each(function(){
            var title = $(this).attr('title');
            var href = $(this).attr('href');
            var item = new goog.ui.MenuItem(title);
            menu.addItem(item);
            goog.events.listen(item, 'action', function(e) {
                window.location = href;
            });
        });
    }

    $(tree).bind('dblclick', function(e, node, kmlObject){
        options.client.show(kmlObject);
    });

    $(options.client).bind('saving', function(e, msg){
        tree.showLoading(msg);
    });

    $(options.client).bind('doneSaving', function(e, msg){
        tree.hideLoading();
    });

    tbar.setEnabled(false);
    $(tree).bind('kmlLoaded', kmlLoaded);
    tree.load(true);

    return that;
}
<|endoftext|>


<commit_before>/*
 * app.js: Core Application object for managing plugins and features in broadway
 *
 * (C) 2011, Nodejitsu Inc.
 * MIT LICENSE
 *
 */

var utile = require('utile'),
    async = utile.async,
    events = require('eventemitter2'),
    bootstrapper = require('./bootstrapper'),
    common = require('./common'),
    constants = require('./constants'),
    features = require('./features');

var App = exports.App = function (options) {
  //
  // Setup options and `App` constants.
  //
  var self       = this;
  options        = options || {};
  this.root      = options.root;
  this.delimiter = options.delimiter || constants.DELIMITER;

  //
  // Inherit from `EventEmitter2`
  //
  events.EventEmitter2.call(this, {
    delimiter: this.delimiter,
    wildcard: true
  });

  //
  // Setup other relevant options such as the plugins
  // for this instance.
  //
  this.options      = options;
  this.env          = options.env || process.env['NODE_ENV'] || 'development'
  this.plugins      = options.plugins || {};
  this.initialized  = false;
  this.bootstrapper = options.bootstrapper || bootstrapper;
  this.initializers = {};

  //
  // Bootstrap this instance
  //
  this.bootstrapper.bootstrap(this);
};

//
// Inherit from `EventEmitter2`.
//
utile.inherits(App, events.EventEmitter2);

//
// ### function init (options, callback)
// #### @options {Object} **Optional** Additional options to initialize with.
// #### @callback {function} Continuation to respond to when complete.
// Initializes this instance by the following procedure:
//
// 1. Initializes all plugins (starting with `core`).
// 2. Creates all directories in `this.config.directories` (if any).
// 3. Ensures the files in the core directory structure conform to the
//    features required by this application.
//
App.prototype.init = function (options, callback) {
  if (!callback && typeof options === 'function') {
    callback = options;
    options = {};
  }

  var self = this;
  options = options   || {};
  callback = callback || function () {};
  this.options = common.mixin({}, this.options, options);

  function onComplete() {
    self.initialized = true;
    self.emit('init');
    callback();
  }

  function ensureFeatures (err) {
    return err
      ? onError(err)
      : features.ensure(this, onComplete);
  }

  function initPlugin(plugin, next) {
    if (typeof self.initializers[plugin] === 'function') {
      return self.initializers[plugin].call(self, function (err) {
        if (err) {
          return next(err);
        }

        self.emit(['plugin', plugin, 'init']);
        self.initializers[plugin] = true;
        next();
      });
    }

    next();
  }

  function initPlugins() {
    async.forEach(Object.keys(self.initializers), initPlugin, ensureFeatures);
  }

  //
  // Emit and respond with any errors that may short
  // circuit the process.
  //
  function onError(err) {
    self.emit(['error', 'init'], err);
    callback(err);
  }

  //
  // Run the bootstrapper, initialize plugins, and
  // ensure features for this instance.
  //
  this.bootstrapper.init(this, initPlugins);
};

//
// ### function use(plugin, callback)
// Attachs the plugin with the specific name to this `App` instance.
//
App.prototype.use = function (plugin, options, callback) {
  options = options || {};

  var name = plugin.name,
      self = this;

  if (this.plugins[name] && this.plugins[name].detach) {
    this.plugins[name].detach(this);
  }

  //
  // Setup state on this instance for the specified plugin
  //
  this.plugins[name] = plugin;
  this.options[name] = common.mixin({}, options, this.options[name] || {});

  //
  // Attach the specified plugin to this instance, extending
  // the `App` with new functionality.
  //
  if (this.plugins[name].attach && options.attach !== false) {
    this.plugins[name].attach.call(this, options);
  }

  //
  // Setup the initializer only if `options.init` is
  // not false. This allows for some plugins to be lazy-loaded
  //
  if (options.init === false) {
    return;
  }

  if (!this.initialized) {
    this.initializers[name] = plugin.init || true;
  }
  else if (plugin.init) {
    plugin.init.call(this, function (err) {
      var args = err
        ? [['plugin', name, 'error'], err]
        : [['plugin', name, 'init']];

      self.emit.apply(self, args);
      if (callback) {
        return err ? callback(err) : callback();
      }
    });
  }
};

//
// ### function inspect ()
// Inspects the modules and features used by the current
// application directory structure
//
App.prototype.inspect = function () {

};<commit_msg>[fix] Set `.env` and dont initialize multiple times<commit_after>/*
 * app.js: Core Application object for managing plugins and features in broadway
 *
 * (C) 2011, Nodejitsu Inc.
 * MIT LICENSE
 *
 */

var utile = require('utile'),
    async = utile.async,
    events = require('eventemitter2'),
    bootstrapper = require('./bootstrapper'),
    common = require('./common'),
    constants = require('./constants'),
    features = require('./features');

var App = exports.App = function (options) {
  //
  // Setup options and `App` constants.
  //
  var self       = this;
  options        = options || {};
  this.root      = options.root;
  this.delimiter = options.delimiter || constants.DELIMITER;

  //
  // Inherit from `EventEmitter2`
  //
  events.EventEmitter2.call(this, {
    delimiter: this.delimiter,
    wildcard: true
  });

  //
  // Setup other relevant options such as the plugins
  // for this instance.
  //
  this.options      = options;
  this.env          = options.env || process.env['NODE_ENV'] || 'development'
  this.plugins      = options.plugins || {};
  this.initialized  = false;
  this.bootstrapper = options.bootstrapper || bootstrapper;
  this.initializers = {};

  //
  // Bootstrap this instance
  //
  this.bootstrapper.bootstrap(this);
};

//
// Inherit from `EventEmitter2`.
//
utile.inherits(App, events.EventEmitter2);

//
// ### function init (options, callback)
// #### @options {Object} **Optional** Additional options to initialize with.
// #### @callback {function} Continuation to respond to when complete.
// Initializes this instance by the following procedure:
//
// 1. Initializes all plugins (starting with `core`).
// 2. Creates all directories in `this.config.directories` (if any).
// 3. Ensures the files in the core directory structure conform to the
//    features required by this application.
//
App.prototype.init = function (options, callback) {
  if (!callback && typeof options === 'function') {
    callback = options;
    options = {};
  }

  if (this.initialized) {
    return callback();
  }

  var self = this;
  options = options   || {};
  callback = callback || function () {};
  this.env = options.env || this.env;
  this.options = common.mixin({}, this.options, options);

  function onComplete() {
    self.initialized = true;
    self.emit('init');
    callback();
  }

  function ensureFeatures (err) {
    return err
      ? onError(err)
      : features.ensure(this, onComplete);
  }

  function initPlugin(plugin, next) {
    if (typeof self.initializers[plugin] === 'function') {
      return self.initializers[plugin].call(self, function (err) {
        if (err) {
          return next(err);
        }

        self.emit(['plugin', plugin, 'init']);
        self.initializers[plugin] = true;
        next();
      });
    }

    next();
  }

  function initPlugins() {
    async.forEach(Object.keys(self.initializers), initPlugin, ensureFeatures);
  }

  //
  // Emit and respond with any errors that may short
  // circuit the process.
  //
  function onError(err) {
    self.emit(['error', 'init'], err);
    callback(err);
  }

  //
  // Run the bootstrapper, initialize plugins, and
  // ensure features for this instance.
  //
  this.bootstrapper.init(this, initPlugins);
};

//
// ### function use(plugin, callback)
// Attachs the plugin with the specific name to this `App` instance.
//
App.prototype.use = function (plugin, options, callback) {
  options = options || {};

  var name = plugin.name,
      self = this;

  if (this.plugins[name] && this.plugins[name].detach) {
    this.plugins[name].detach(this);
  }

  //
  // Setup state on this instance for the specified plugin
  //
  this.plugins[name] = plugin;
  this.options[name] = common.mixin({}, options, this.options[name] || {});

  //
  // Attach the specified plugin to this instance, extending
  // the `App` with new functionality.
  //
  if (this.plugins[name].attach && options.attach !== false) {
    this.plugins[name].attach.call(this, options);
  }

  //
  // Setup the initializer only if `options.init` is
  // not false. This allows for some plugins to be lazy-loaded
  //
  if (options.init === false) {
    return;
  }

  if (!this.initialized) {
    this.initializers[name] = plugin.init || true;
  }
  else if (plugin.init) {
    plugin.init.call(this, function (err) {
      var args = err
        ? [['plugin', name, 'error'], err]
        : [['plugin', name, 'init']];

      self.emit.apply(self, args);
      if (callback) {
        return err ? callback(err) : callback();
      }
    });
  }
};

//
// ### function inspect ()
// Inspects the modules and features used by the current
// application directory structure
//
App.prototype.inspect = function () {

};<|endoftext|>


<commit_before>
/********************************************************************
 Copyright (c) 2013-2015 - Kazuichi Takashiro

 This file is part of Orchard Hut.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 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
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 takashiro@qq.com
*********************************************************************/

function randomstr(length){
	var str = '';
	for(var i = 0; i < length; i++){
		var rand = Math.floor(Math.random() * 62);
		if(rand >= 0 && rand <= 25){
			rand += 0x41;
		}else if(rand <= 51){
			rand -= 26;
			rand += 0x61;
		}else{
			rand -= 52;
			rand += 0x30;
		}
		str += String.fromCharCode(rand);
	}

	return str;
}

function makeToast(data){
	var toast = $('

');
	toast.html(data.message);

	toast.appendTo($('body'));
	toast.animate({
		top : '-=40px',
		opacity : 1
	}, 300);

	setTimeout(function(){
		toast.fadeOut(500, function(){
			toast.remove();
			if(data.url_forward){
				if(data.url_forward == 'refresh'){
					location.reload();
				}else if(data.url_forward == 'back'){
					toast.remove();
				}else{
					location.href = data.url_forward;
				}
			}
		});
	}, 1500);
}

$(function(){
	$('.menu > li > .submenu').each(function(){
		var submenu = $(this);
		var menu = submenu.parent();
		submenu.css({
			top: 0,
			left: menu.outerWidth(),
		});
	});

	$('.menu > li').mouseenter(function(){
		var submenu = $(this).children('.submenu');
		if(submenu.is(':visible') && submenu.css('opacity') >= 1.0)
			return;
		var offset_left = $(this).outerWidth();
		submenu.css({'left' : offset_left - 10, 'opacity' : 0.0});
		submenu.show();
		submenu.data('isShowing', true);
		submenu.animate({'left' : offset_left, 'opacity' : 1.0}, 300, 'swing', function(){
			submenu.data('isShowing', false);
		});
	});

	$('.menu > li').mouseleave(function(){
		var submenu = $(this).find('.submenu');
		setTimeout(function(){
			var li = submenu.parent();
			if(li.is(':hover') || submenu.data('isShowing'))
				return;
			submenu.fadeOut(300);
		}, 300);
	});

	$('form.toast').submit(function(){
		var form = $(this);
		var data = form.serialize();
		var url = form.attr('action');
		if(url == '###'){
			url = location.href;
		}
		url += (url.indexOf('?') >= 0 ? '&' : '?') + 'ajaxform=1';
		$.post(url, data, function(response){
			eval('var response = ' + response + ';');
			makeToast(response);
		});
		return false;
	});
});
<commit_msg>菜单碰撞到视口边界时调整显示位置<commit_after>
/********************************************************************
 Copyright (c) 2013-2015 - Kazuichi Takashiro

 This file is part of Orchard Hut.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 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
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 takashiro@qq.com
*********************************************************************/

function randomstr(length){
	var str = '';
	for(var i = 0; i < length; i++){
		var rand = Math.floor(Math.random() * 62);
		if(rand >= 0 && rand <= 25){
			rand += 0x41;
		}else if(rand <= 51){
			rand -= 26;
			rand += 0x61;
		}else{
			rand -= 52;
			rand += 0x30;
		}
		str += String.fromCharCode(rand);
	}

	return str;
}

function makeToast(data){
	var toast = $('

');
	toast.html(data.message);

	toast.appendTo($('body'));
	toast.animate({
		top : '-=40px',
		opacity : 1
	}, 300);

	setTimeout(function(){
		toast.fadeOut(500, function(){
			toast.remove();
			if(data.url_forward){
				if(data.url_forward == 'refresh'){
					location.reload();
				}else if(data.url_forward == 'back'){
					toast.remove();
				}else{
					location.href = data.url_forward;
				}
			}
		});
	}, 1500);
}

$(function(){
	$('.menu > li > .submenu').each(function(){
		var submenu = $(this);
		var menu = submenu.parent();
		submenu.css({
			top: 0,
			left: menu.outerWidth(),
		});
	});

	$('.menu > li').mouseenter(function(){
		var submenu = $(this).children('.submenu');
		if(submenu.length <= 0 || (submenu.is(':visible') && submenu.css('opacity') >= 1.0))
			return;

		var offset_left = $(this).outerWidth();
		submenu.css({top: 0, left: offset_left - 10, opacity: 0});
		submenu.show();

		var submenu_rect = submenu.offset();
		submenu_rect.bottom = submenu_rect.top + submenu.outerHeight();
		submenu_rect.right = submenu_rect.left + submenu.outerWidth();

		var viewport = {
			top: $(window).scrollTop(),
			left: $(window).scrollLeft()
		};
		viewport.bottom = viewport.top + $(window).height();
		viewport.right = viewport.left + $(window).width();
		if(viewport.bottom < submenu_rect.bottom){
			submenu.css({top: $(this).outerHeight() - submenu.outerHeight()});
		}

		submenu.show();
		submenu.data('isShowing', true);
		submenu.animate({'left' : offset_left, 'opacity' : 1.0}, 300, 'swing', function(){
			submenu.data('isShowing', false);
		});
	});

	$('.menu > li').mouseleave(function(){
		var submenu = $(this).find('.submenu');
		if(submenu.length <= 0)
			return;

		setTimeout(function(){
			var li = submenu.parent();
			if(li.is(':hover') || submenu.data('isShowing'))
				return;
			submenu.fadeOut(300, function(){
				$(this).hide();
			});
		}, 300);
	});

	$('form.toast').submit(function(){
		var form = $(this);
		var data = form.serialize();
		var url = form.attr('action');
		if(url == '###'){
			url = location.href;
		}
		url += (url.indexOf('?') >= 0 ? '&' : '?') + 'ajaxform=1';
		$.post(url, data, function(response){
			eval('var response = ' + response + ';');
			makeToast(response);
		});
		return false;
	});
});
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, Carlos Brito Lage
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * The name of the author may not be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

if (module) {
	module.exports = Cachelicious;
}

var http = require('http');
var fs = require('fs');
var path = require('path');
var LRU = require("lru-cache");
var util = require("util");
var events = require("events");
var stream = require("stream");

function CacheStreamConsumer(cacheStream, response, startOffset, endOffset) {
	events.EventEmitter.call(this);

	this.paused = false;

	this.cacheStream = cacheStream;
	this.readOffset  = undefined === startOffset ? 0 : startOffset;
	this.maxOffset   = undefined === endOffset ||  endOffset > this.cacheStream.size ? this.cacheStream.size : endOffset;

	this.response = response;

	var self = this;
	this.response.on('drain', function () {
		// Resume the read stream when the write stream gets hungry
		self.resume();
	});
}
util.inherits(CacheStreamConsumer, events.EventEmitter);

CacheStreamConsumer.prototype.asyncStart = function (timeout)
{
	var self = this;
	if (undefined === timeout) {
		timeout = 6;
	}

	//console.log(timeout);
	setTimeout(function () {
		self.emit('start');
		self.tick();
	}, timeout);
	//the timeout value should probably be calculated based on file size and number of global pending requests
};

CacheStreamConsumer.prototype.tick = function ()
{
	if (this.paused) {
		return;
	}

	if (this.readOffset < this.cacheStream.writeOffset) {
		var data = this.cacheStream.buffer.slice(this.readOffset, this.cacheStream.writeOffset);
		this.readOffset = this.cacheStream.writeOffset;

		if (this.readOffset === this.maxOffset) {
			this.end(data);
			return;
		}

		if (false === this.response.write(data)) {
			//console.log(requestId + ": Pausing stream...")
			this.pause();
			return;
		}

		//this.emit('data', data);

		if (this.paused) {
			return;
		}
	}

	//we drained the buffer, wait on more data
	var self = this;
	this.cacheStream.once('data', function () {
		self.tick();
	});
};

CacheStreamConsumer.prototype.end = function (data)
{
	this.response.end(data);
	this.emit('end');
};

CacheStreamConsumer.prototype.pause = function ()
{
	this.paused = true;
	this.emit('pause');
};

CacheStreamConsumer.prototype.resume = function ()
{
	this.paused = false;
	this.emit('resume');
	//if the response asked to be resumed, lets prioritize it in this tick
	this.tick();
};

function CacheStream(size) {
	stream.Stream.call(this);
	this.buffer = new Buffer(size);
	this.size = size;
	this.writeOffset = 0;
	this.consumerCount = 0;
	this.writable = true;
	this.setMaxListeners(0);
}

util.inherits(CacheStream, stream.Stream);

CacheStream.prototype.write = function (data)
{
	if (!this.writable) {
		//console.log("rejecting write because we ended already")
		return;
	}

	var writtenBytes;
	if (Buffer.isBuffer(data)) {
		//console.log("writing buffer data " + data.length + " bytes to offset: " + this.writeOffset);
		data.copy(this.buffer, this.writeOffset);
		writtenBytes = data.length;
	} else {
		//console.log("writing " + Buffer.byteLength(data) + " bytes to offset: " + this.writeOffset);
		writtenBytes = this.buffer.write(data, this.writeOffset);
	}
	this.writeOffset+= writtenBytes;

	this.emit('data', data);
	//console.log("wrote " + writtenBytes + " bytes into buffer");
	//console.log("new offset" + this.writeOffset);
};

CacheStream.prototype.end = function ()
{
	//console.log("ended!");
	this.writable = false;
	this.emit('end');
};

function defaultPathFinder (request)
{
	var filepath = '.';
	if ('/' === request.url) {
		filepath += '/index.html';
	} else {
		filepath += request.url;
	}
	return filepath;
}

function defaultContentTypeFinder (filepath)
{
	var extname = path.extname(filepath).toLowerCase();
	switch (extname) {
		case '.js':
			return 'text/javascript';
		case '.css':
			return 'text/css';
		case '.jpeg':
		case '.jpg':
			return 'image/jpeg';
	}
	return 'text/html';
}

function Cachelicious (pathFinder, contentTypeFinder, port, maxCacheSize)
{
	events.EventEmitter.call(this);
	this.setMaxListeners(0);
	this.init(pathFinder, contentTypeFinder, port, maxCacheSize)
}

util.inherits(Cachelicious, events.EventEmitter);

Cachelicious.prototype.init = function (pathFinder, contentTypeFinder, port, maxCacheSize)
{
	var self = this;

	if (typeof pathFinder === 'undefined') {
		pathFinder = defaultPathFinder;
	}

	if (typeof contentTypeFinder === 'undefined') {
		contentTypeFinder = defaultContentTypeFinder;
	}

	if (typeof port === 'undefined') {
		port = 9876;
	}

	if (typeof maxCacheSize === 'undefined') {
		maxCacheSize = 20971520; //20mb
	}

	if (maxCacheSize !== false) {
		this.cache = LRU(maxCacheSize, function (cacheStream) {
			return cacheStream.size;
		});
	} else {
		this.cache = false;
	}

	this.port = port;
	this.pathFinder = pathFinder;
	this.contentTypeFinder = contentTypeFinder;
	this.pendingRequests = 0;

	this.server = http.createServer(function (request, response) {
		self.dispatch(request, response);
	});
};

Cachelicious.prototype.start = function ()
{
	this.server.listen(this.port);
	console.log('Server running at http://127.0.0.1:' + this.port);
};

Cachelicious.prototype.stop = function ()
{
	this.server.close();
	console.log('Server shut down');
};

Cachelicious.prototype.dispatch = function (request, response)
{
	var filepath = this.pathFinder(request), contentType;

	if (null === filepath) {
		this.serveError(request.method, response, 404);
		return;
	}

	contentType = this.contentTypeFinder(filepath);

	this.streamPath(filepath, contentType, request.method, response);
};

Cachelicious.prototype.calculateNextConsumerTimeout = function ()
{
	//var result = Math.min(Math.round(this.pendingRequests/10), 10);
	//console.log(result);
	//return result;
	return Math.min(Math.round(this.pendingRequests/10), 10);
};

Cachelicious.prototype.fileCheck = function (filepath, successCb, errorCb)
{
	//console.log('running stat on:' + filepath)
	var self = this;
	fs.stat(filepath, function (error, stat) {
		if (null !== error) {
			if (errorCb) {
				errorCb(404);
			}
			return false;
		}

		if (undefined === stat) {
			if (errorCb) {
				errorCb(500);
			}
			return false;
		}

		if (!stat.isFile()) {
			if (errorCb) {
				errorCb(401);
			}
			return false;
		}
		successCb(stat);
		return true;
	});
};

Cachelicious.prototype.streamPath = function (filepath, contentType, method, response)
{
	if (false === this.cache) {
		this.asyncServeUncachedStream(filepath, contentType, method, response);
		return;
	}

	var
		cachedStream = this.getCached(filepath),
		self = this;

	if (undefined !== cachedStream) {
		self.asyncServeCachedStream(cachedStream, contentType, method, response);
		return;
	}

	this.once('fileCheckSuccess-' + filepath, function (cachedStream) {
		self.asyncServeCachedStream(cachedStream, contentType, method, response);
	});

	this.once('fileCheckError-' + filepath, function (error) {
		self.serveError(method, response, error);
	});

	this.fileCheck(filepath,
		function (stat)
		{
			var newStream = new CacheStream(stat.size);
			self.setCached(filepath, newStream);
			fs.createReadStream(filepath).pipe(newStream);

			//console.log('emitting: fileCheckSuccess-' + filepath);
			self.emit('fileCheckSuccess-' + filepath, newStream);
			self.removeAllListeners('fileCheckError-' + filepath);
		},
		function (error)
		{
			//console.log('emitting: fileCheckError-' + filepath);
			self.emit('fileCheckError-' + filepath, error);
			self.removeAllListeners('fileCheckSuccess-' + filepath);
		}
	);
};

Cachelicious.prototype.asyncServeUncachedStream = function (filepath, contentType, method, response)
{
	var self = this;
	this.fileCheck(filepath,
		function (stat) {
			response.writeHead(200, {
				'Content-Type':   contentType,
				'Content-Length': stat.size
			});

			if ('HEAD' !== method) {
				fs.createReadStream(filepath).pipe(response);
			} else {
				response.end();
			}
		},
		function (error) {
			self.serveError(method, response, error);
		}
	);
};

Cachelicious.prototype.asyncServeCachedStream = function (cachedStream, contentType, method, response)
{
	var self = this;
	process.nextTick(function () {
		self.serveCachedStream(cachedStream, contentType, method, response);
	});
};

Cachelicious.prototype.serveCachedStream = function (cachedStream, contentType, method, response)
{
	response.writeHead(200, {
		'Content-Type':   contentType,
		'Content-Length': cachedStream.size
	});

	if ('HEAD' !== method) {
		++this.pendingRequests;

		var self = this;
		(new CacheStreamConsumer(cachedStream, response))
			.on('end', function () { --self.pendingRequests; })
			.asyncStart(this.calculateNextConsumerTimeout());
	} else {
		response.end();
	}
};

Cachelicious.prototype.serveError = function (method, response, code)
{
	console.log('error: ' + code);
	response.writeHead(code, {'Content-Type': 'text/html'});
	if ('HEAD' !== method) {
		response.end(""+code, 'utf-8');
	} else {
		response.end();
	}
};

Cachelicious.prototype.getCached = function (filepath)
{
	return this.cache.get(filepath);
};

Cachelicious.prototype.setCached = function (filepath, cacheStream)
{
	this.cache.set(filepath, cacheStream);
	//console.log('Current cache size: ' + Math.round(this.cache.length/(1024*1024)) + 'MB');
};

<commit_msg>Ranged HTTP requests now supported. I think.<commit_after>/*
Copyright (c) 2012, Carlos Brito Lage
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * The name of the author may not be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

if (module) {
	module.exports = Cachelicious;
}

var http = require('http');
var fs = require('fs');
var path = require('path');
var LRU = require("lru-cache");
var util = require("util");
var events = require("events");
var stream = require("stream");

function CacheStreamConsumer(cacheStream, response, startOffset, endOffset) {
	events.EventEmitter.call(this);

	this.paused = false;

	this.cacheStream = cacheStream;
	this.readOffset  = undefined === startOffset ? 0 : startOffset;
	this.maxOffset   = undefined === endOffset ||  endOffset >= this.cacheStream.size ? this.cacheStream.size-1: endOffset;

	this.response = response;

	var self = this;
	this.response.on('drain', function () {
		// Resume the read stream when the write stream gets hungry
		self.resume();
	});
}
util.inherits(CacheStreamConsumer, events.EventEmitter);

CacheStreamConsumer.prototype.asyncStart = function (timeout)
{
	var self = this;
	if (undefined === timeout) {
		timeout = 6;
	}

	//console.log(timeout);
	setTimeout(function () {
		self.emit('start');
		self.tick();
	}, timeout);
	//the timeout value should probably be calculated based on file size and number of global pending requests
};

CacheStreamConsumer.prototype.tick = function ()
{
	if (this.paused) {
		return;
	}

	var	outputMaxOffset = Math.min(this.maxOffset, this.cacheStream.writeOffset);

	if (this.readOffset < outputMaxOffset) {
		var data = this.cacheStream.buffer.slice(this.readOffset, outputMaxOffset+1);

		this.readOffset = outputMaxOffset;

		if (this.readOffset === this.maxOffset) {
			this.end(data);
			return;
		}

		if (false === this.response.write(data)) {
			//console.log(requestId + ": Pausing stream...")
			this.pause();
			return;
		}

		//this.emit('data', data);

		if (this.paused) {
			return;
		}
	}

	//we drained the buffer, wait on more data
	var self = this;
	this.cacheStream.once('data', function () {
		self.tick();
	});
};

CacheStreamConsumer.prototype.end = function (data)
{
	this.response.end(data);
	this.emit('end');
};

CacheStreamConsumer.prototype.pause = function ()
{
	this.paused = true;
	this.emit('pause');
};

CacheStreamConsumer.prototype.resume = function ()
{
	this.paused = false;
	this.emit('resume');
	//if the response asked to be resumed, lets prioritize it in this tick
	this.tick();
};

function CacheStream(size) {
	stream.Stream.call(this);
	this.buffer = new Buffer(size);
	this.size = size;
	this.writeOffset = 0;
	this.consumerCount = 0;
	this.writable = true;
	this.setMaxListeners(0);
}

util.inherits(CacheStream, stream.Stream);

CacheStream.prototype.write = function (data)
{
	if (!this.writable) {
		//console.log("rejecting write because we ended already")
		return;
	}

	var writtenBytes;
	if (Buffer.isBuffer(data)) {
		//console.log("writing buffer data " + data.length + " bytes to offset: " + this.writeOffset);
		data.copy(this.buffer, this.writeOffset);
		writtenBytes = data.length;
	} else {
		//console.log("writing " + Buffer.byteLength(data) + " bytes to offset: " + this.writeOffset);
		writtenBytes = this.buffer.write(data, this.writeOffset);
	}
	this.writeOffset+= writtenBytes;

	this.emit('data', data);
	//console.log("wrote " + writtenBytes + " bytes into buffer");
	//console.log("new offset" + this.writeOffset);
};

CacheStream.prototype.end = function ()
{
	//console.log("ended!");
	this.writable = false;
	this.emit('end');
};

function defaultPathFinder (request)
{
	var filepath = '.';
	if ('/' === request.url) {
		filepath += '/index.html';
	} else {
		filepath += request.url;
	}
	return filepath;
}

function defaultContentTypeFinder (filepath)
{
	var extname = path.extname(filepath).toLowerCase();
	switch (extname) {
		case '.js':
			return 'text/javascript';
		case '.css':
			return 'text/css';
		case '.jpeg':
		case '.jpg':
			return 'image/jpeg';
	}
	return 'text/html';
}

function Cachelicious (pathFinder, contentTypeFinder, port, maxCacheSize)
{
	events.EventEmitter.call(this);
	this.setMaxListeners(0);
	this.init(pathFinder, contentTypeFinder, port, maxCacheSize)
}

util.inherits(Cachelicious, events.EventEmitter);

Cachelicious.prototype.init = function (pathFinder, contentTypeFinder, port, maxCacheSize)
{
	var self = this;

	if (typeof pathFinder === 'undefined') {
		pathFinder = defaultPathFinder;
	}

	if (typeof contentTypeFinder === 'undefined') {
		contentTypeFinder = defaultContentTypeFinder;
	}

	if (typeof port === 'undefined') {
		port = 9876;
	}

	if (typeof maxCacheSize === 'undefined') {
		maxCacheSize = 20971520; //20mb
	}

	if (maxCacheSize !== false) {
		this.cache = LRU(maxCacheSize, function (cacheStream) {
			return cacheStream.size;
		});
	} else {
		this.cache = false;
	}

	this.port = port;
	this.pathFinder = pathFinder;
	this.contentTypeFinder = contentTypeFinder;
	this.pendingRequests = 0;

	this.server = http.createServer(function (request, response) {
		self.dispatch(request, response);
	});
};

Cachelicious.prototype.start = function ()
{
	this.server.listen(this.port);
	console.log('Server running at http://127.0.0.1:' + this.port);
};

Cachelicious.prototype.stop = function ()
{
	this.server.close();
	console.log('Server shut down');
};

Cachelicious.prototype.dispatch = function (request, response)
{
	var filepath = this.pathFinder(request), contentType;

	if (null === filepath) {
		this.serveError(request, response, 404);
		return;
	}

	contentType = this.contentTypeFinder(filepath);

	this.streamPath(filepath, contentType, request, response);
};

Cachelicious.prototype.calculateNextConsumerTimeout = function ()
{
	//var result = Math.min(Math.round(this.pendingRequests/10), 10);
	//console.log(result);
	//return result;
	return Math.min(Math.round(this.pendingRequests/10), 10);
};

Cachelicious.prototype.fileCheck = function (filepath, successCb, errorCb)
{
	//console.log('running stat on:' + filepath)
	var self = this;
	fs.stat(filepath, function (error, stat) {
		if (null !== error) {
			if (errorCb) {
				errorCb(404);
			}
			return false;
		}

		if (undefined === stat) {
			if (errorCb) {
				errorCb(500);
			}
			return false;
		}

		if (!stat.isFile()) {
			if (errorCb) {
				errorCb(401);
			}
			return false;
		}
		successCb(stat);
		return true;
	});
};

Cachelicious.prototype.streamPath = function (filepath, contentType, request, response)
{
	if (false === this.cache) {
		this.asyncServeUncachedStream(filepath, contentType, request, response);
		return;
	}

	var
		cachedStream = this.getCached(filepath),
		self = this;

	if (undefined !== cachedStream) {
		self.asyncServeCachedStream(cachedStream, contentType, request, response);
		return;
	}

	this.once('fileCheckSuccess-' + filepath, function (cachedStream) {
		self.asyncServeCachedStream(cachedStream, contentType, request, response);
	});

	this.once('fileCheckError-' + filepath, function (error) {
		self.serveError(request, response, error);
	});

	this.fileCheck(filepath,
		function (stat)
		{
			var newStream = new CacheStream(stat.size);
			self.setCached(filepath, newStream);
			fs.createReadStream(filepath).pipe(newStream);

			//console.log('emitting: fileCheckSuccess-' + filepath);
			self.emit('fileCheckSuccess-' + filepath, newStream);
			self.removeAllListeners('fileCheckError-' + filepath);
		},
		function (error)
		{
			//console.log('emitting: fileCheckError-' + filepath);
			self.emit('fileCheckError-' + filepath, error);
			self.removeAllListeners('fileCheckSuccess-' + filepath);
		}
	);
};

Cachelicious.prototype.asyncServeUncachedStream = function (filepath, contentType, request, response)
{
	var self = this;
	this.fileCheck(filepath,
		function (stat) {
			response.writeHead(200, {
				'Content-Type':   contentType,
				'Content-Length': stat.size
			});

			if ('HEAD' !== request.method) {
				fs.createReadStream(filepath).pipe(response);
			} else {
				response.end();
			}
		},
		function (error) {
			self.serveError(request, response, error);
		}
	);
};

Cachelicious.prototype.asyncServeCachedStream = function (cachedStream, contentType, request, response)
{
	var self = this;
	process.nextTick(function () {
		self.serveCachedStream(cachedStream, contentType, request, response);
	});
};

//range parsing inspired by https://github.com/meloncholy/vid-streamer/blob/master/index.js
function isNumber(n)
{
  return !isNaN(parseFloat(n)) && isFinite(n);
}

Cachelicious.prototype.serveCachedStream = function (cachedStream, contentType, request, response)
{
	var startOffset = 0, endOffset = cachedStream.size - 1;

	if ('string' === typeof request.headers.range) {
		var parsedRange = request.headers.range.match(/bytes=(.+)-(.+)?/);
		if (null === parsedRange) {
			this.serveError(request, response, 416);
			return;
		}

		if (isNumber(parsedRange[1]) && parsedRange[1] >= 0 && parsedRange[1] < cachedStream.size) {
			startOffset = parsedRange[1];
		} else {
			this.serveError(request, response, 416);
			return;
		}

		if (isNumber(parsedRange[2]) && parsedRange[2] > startOffset && parsedRange[2] < cachedStream.size) {
			endOffset = parsedRange[2];
		} else {
			this.serveError(request, response, 416);
			return;
		}

		response.writeHead(206, {
			'Content-Type':   contentType,
			'Status':         '206 Partial Content',
			'Accept-Ranges':  'bytes',
			'Content-Range':  'bytes ' + startOffset + "-" + endOffset + "/" + cachedStream.size,
			'Content-Length': endOffset - startOffset + 1
		});
	} else {
		response.writeHead(200, {
			'Content-Type':   contentType,
			'Content-Length': cachedStream.size
		});
	}

	if ('HEAD' !== request.method) {
		++this.pendingRequests;

		var self = this;
		(new CacheStreamConsumer(cachedStream, response, startOffset, endOffset))
			.on('end', function () { --self.pendingRequests; })
			.asyncStart(this.calculateNextConsumerTimeout());
	} else {
		response.end();
	}
};

Cachelicious.prototype.serveError = function (request, response, code)
{
	console.log('error: ' + code);
	response.writeHead(code, {'Content-Type': 'text/html'});
	if ('HEAD' !== request.method) {
		response.end(""+code, 'utf-8');
	} else {
		response.end();
	}
};

Cachelicious.prototype.getCached = function (filepath)
{
	return this.cache.get(filepath);
};

Cachelicious.prototype.setCached = function (filepath, cacheStream)
{
	this.cache.set(filepath, cacheStream);
	//console.log('Current cache size: ' + Math.round(this.cache.length/(1024*1024)) + 'MB');
};

<|endoftext|>


<commit_before>#!/usr/bin/env node

var http = require('http');
var httpSync = require('http-sync');
var clc = require('cli-color');
var clc_color = require('./clc-color');

var id_color = clc.xterm(232).bgWhiteBright;
var def_source_color = clc.whiteBright.bgXterm(232);

function getUserHome() {
	return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
}

var requestNotification = function(id) {
	var config = require(getUserHome() + '/.nodeifier.json');

	config.path = "/" + id;
	config.method = "GET";

	var req = httpSync.request(config);

	var data = req.end();

	var data_json = JSON.parse(data.body);

	var source_color = def_source_color;
	if(data_json.colorfg)
		source_color = clc_color.color_from_text(data_json.colorfg, data_json.colorbg);

	// pad with leading zeroes
	var pos_string = String(id);

	// if the string is wider than our terminal we need to shorten it
	var source_text_length = 5 + pos_string.length + data_json.source.length;
	var text_length = data_json.text.length;
	if(source_text_length + text_length > process.stdout.columns)
		data_json.text = data_json.text.substr(0, process.stdout.columns - source_text_length - 3) + '...';

	console.log(id_color(' ' + pos_string + ' ') + source_color(' ' + data_json.source + ' ') + ' ' + data_json.text);
};

if(process.argv[2]) {
	requestNotification(process.argv[2]);
} else { // get 15 previous notifications
	var config = require(getUserHome() + '/.nodeifier.json');

	config.path = "/getstate";
	config.method = "GET";

	var req = http.request(config, function(res) {
		res.on('data', function(data) {
			var data_json = JSON.parse(data);

			var NUM_NOTIFICATIONS = 15;
			var i;
			var id = data_json.n_pos - NUM_NOTIFICATIONS;
			if (id < 0)
				id += data_json.N_SIZE;

			for (i = id; i < id + NUM_NOTIFICATIONS && i < data_json.N_SIZE; i++) {
				requestNotification(i);
			}

			// if we overflowed N_SIZE, take the rest from index 0 and up
			if (id + NUM_NOTIFICATIONS >= data_json.N_SIZE) {
				for (i = 0; i < NUM_NOTIFICATIONS - (data_json.N_SIZE - id); i++) {
					requestNotification(i);
				}
			}
		});
	});

	req.end();
}
<commit_msg>client side too<commit_after>#!/usr/bin/env node

var http = require('http');
var httpSync = require('http-sync');
var clc = require('cli-color');
var clc_color = require('./clc-color');

var id_color = clc.xterm(232).bgWhiteBright;
var def_source_color = clc.whiteBright.bgXterm(232);

function getUserHome() {
	return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
}

var requestNotification = function(id) {
	var config = require(getUserHome() + '/.nodeifier.json');

	config.path = "/" + id;
	config.method = "GET";

	var req = httpSync.request(config);

	var data = req.end();

	if(data.statusCode == 200) {
		var data_json = JSON.parse(data.body);

		var source_color = def_source_color;
		if(data_json.colorfg)
			source_color = clc_color.color_from_text(data_json.colorfg, data_json.colorbg);

		// pad with leading zeroes
		var pos_string = String(id);

		// if the string is wider than our terminal we need to shorten it
		var source_text_length = 5 + pos_string.length + data_json.source.length;
		var text_length = data_json.text.length;
		if(source_text_length + text_length > process.stdout.columns)
			data_json.text = data_json.text.substr(0, process.stdout.columns - source_text_length - 3) + '...';

		console.log(id_color(' ' + pos_string + ' ') + source_color(' ' + data_json.source + ' ') + ' ' + data_json.text);
	} else {
		// do nothing
	}
};

if(process.argv[2]) {
	requestNotification(process.argv[2]);
} else { // get 15 previous notifications
	var config = require(getUserHome() + '/.nodeifier.json');

	config.path = "/getstate";
	config.method = "GET";

	var req = http.request(config, function(res) {
		res.on('data', function(data) {
			var data_json = JSON.parse(data);

			var NUM_NOTIFICATIONS = 15;
			var i;
			var id = data_json.n_pos - NUM_NOTIFICATIONS;
			if (id < 0)
				id += data_json.N_SIZE;

			for (i = id; i < id + NUM_NOTIFICATIONS && i < data_json.N_SIZE; i++) {
				requestNotification(i);
			}

			// if we overflowed N_SIZE, take the rest from index 0 and up
			if (id + NUM_NOTIFICATIONS >= data_json.N_SIZE) {
				for (i = 0; i < NUM_NOTIFICATIONS - (data_json.N_SIZE - id); i++) {
					requestNotification(i);
				}
			}
		});
	});

	req.end();
}
<|endoftext|>


<commit_before>/**
 *  class CoffeeEngine
 *
 *  Engine for the CoffeeScript compiler. You will need `coffee-script` Node
 *  module installed in order to use [[Mincer]] with `*.coffee` and
 *  `*.litcoffee` files:
 *
 *      npm install coffee-script
 *
 *
 *  ##### SUBCLASS OF
 *
 *  [[Template]]
 **/

'use strict';

// stdlib
var extname = require("path").extname;

// 3rd-party
var _ = require('lodash');
var coffee; // initialized later

// internal
var Template  = require('../template');
var prop      = require('../common').prop;

////////////////////////////////////////////////////////////////////////////////

// Class constructor
var CoffeeEngine = module.exports = function CoffeeEngine() {
  Template.apply(this, arguments);
  coffee = coffee || Template.libs["coffee"] || require("coffee");
};

require('util').inherits(CoffeeEngine, Template);

// Internal (private) options storage
var options = {bare: true};

/**
 *  CoffeeEngine.configure(opts) -> Void
 *  - opts (Object):
 *
 *  Allows to set CoffeeScript compilation options.
 *  Default: `{bare: true}`.
 *
 *  ##### Example
 *
 *      CoffeeScript.configure({bare: true});
 **/
CoffeeEngine.configure = function (opts) {
  options = _.clone(opts);
};

// Render data
CoffeeEngine.prototype.evaluate = function (/*context, locals*/) {
  return coffee.compile(this.data, _.extend({}, options, {
    literate: '.litcoffee' === extname(this.file)
  }));
};

// Expose default MimeType of an engine
prop(CoffeeEngine, 'defaultMimeType', 'application/javascript');
<commit_msg>Fixed require of coffee-script module<commit_after>/**
 *  class CoffeeEngine
 *
 *  Engine for the CoffeeScript compiler. You will need `coffee-script` Node
 *  module installed in order to use [[Mincer]] with `*.coffee` and
 *  `*.litcoffee` files:
 *
 *      npm install coffee-script
 *
 *
 *  ##### SUBCLASS OF
 *
 *  [[Template]]
 **/

'use strict';

// stdlib
var extname = require("path").extname;

// 3rd-party
var _ = require('lodash');
var coffee; // initialized later

// internal
var Template  = require('../template');
var prop      = require('../common').prop;

////////////////////////////////////////////////////////////////////////////////

// Class constructor
var CoffeeEngine = module.exports = function CoffeeEngine() {
  Template.apply(this, arguments);
  coffee = coffee || Template.libs["coffee"] || require("coffee-script");
};

require('util').inherits(CoffeeEngine, Template);

// Internal (private) options storage
var options = {bare: true};

/**
 *  CoffeeEngine.configure(opts) -> Void
 *  - opts (Object):
 *
 *  Allows to set CoffeeScript compilation options.
 *  Default: `{bare: true}`.
 *
 *  ##### Example
 *
 *      CoffeeScript.configure({bare: true});
 **/
CoffeeEngine.configure = function (opts) {
  options = _.clone(opts);
};

// Render data
CoffeeEngine.prototype.evaluate = function (/*context, locals*/) {
  return coffee.compile(this.data, _.extend({}, options, {
    literate: '.litcoffee' === extname(this.file)
  }));
};

// Expose default MimeType of an engine
prop(CoffeeEngine, 'defaultMimeType', 'application/javascript');
<|endoftext|>


<commit_before><commit_msg>Skip GTL until we have an implementation<commit_after><|endoftext|>


<commit_before>'use strict';

function create_audio(id, properties){
    for(var property in properties){
        audio[id] = properties[property];
    }
}

function play_audio(id){
    //if(settings['audio-volume'] <= 0){
    //    return;
    //}

    document.getElementById(id).currentTime = 0;
    document.getElementById(id).play();
}

var audio = {};
<commit_msg>started switching to namespaced function names<commit_after>'use strict';

function audio_create(id, properties){
    for(var property in properties){
        audio[id] = properties[property];
    }
}

function audio_play(id){
    //if(settings['audio-volume'] <= 0){
    //    return;
    //}

    document.getElementById(id).currentTime = 0;
    document.getElementById(id).play();
}

var audio = {};
<|endoftext|>