diff --git a/README.md b/README.md index 0ce36e6..ea5306f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ column. * nodejs * npm -* Static web server ##Install @@ -24,17 +23,20 @@ $ cp config/database.coffee.sample database.coffee ``` * Edit settings in application.coffee and database.coffee as necessary -* Setup your web server to serve the public directory ##Usage -Go to URL setup in your static web server! +``` +$ coffee dbmonitor.coffee +``` + +Access the application in your browser using the port you have configured. ##License The MIT License -Copyright (c) 2012 Andrew Tomaka +Copyright (c) 2013 Andrew Tomaka Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/dbmonitor.coffee b/dbmonitor.coffee index 1517663..902e3a1 100644 --- a/dbmonitor.coffee +++ b/dbmonitor.coffee @@ -2,10 +2,9 @@ database = require './config/database.coffee' application = require './config/application.coffee' moment = require 'moment' -io = require('socket.io').listen(application.port) +fs = require 'fs' sockets = [] -io.set('log level', 1); db = require('mysql-native').createTCPClient(database.host, database.port) db.auth database.database, database.username, database.password @@ -24,6 +23,26 @@ updateClient = (job) -> for client in sockets client.emit 'update', job +http = require('http').createServer((req, res) -> + if req.url == '/' + res.writeHead 200, {'Content-Type': 'text/html'} + res.end fs.readFileSync('public/index.html') + else if req.url == '/css/style.css' + res.writeHead 200, {'Content-Type': 'text/css'} + res.end fs.readFileSync('public/css/style.css') + else if req.url == '/js/jquery.mustache.js' + res.writeHead 200, {'Content-Type': 'text/javascript'} + res.end fs.readFileSync('public/js/jquery.mustache.js') + else if req.url == '/templates/views.html' + res.writeHead 200, {'Content-Type': 'text/html'} + res.end fs.readFileSync('public/templates/views.html') + else + res.writeHead 404, {"Content-Type": "text/plain"} + res.end "404 Not Found\n" +).listen application.port + +io = require('socket.io').listen(http) +io.set('log level', 1); io.sockets.on 'connection', (socket) -> sockets.push socket diff --git a/public/index.html b/public/index.html index 6c93305..7efa263 100644 --- a/public/index.html +++ b/public/index.html @@ -10,13 +10,12 @@ - + ` + domTemplateType: 'text/html', + + // Specifies the `dataType` attribute used when external templates are loaded. + externalTemplateDataType: 'text' + }; + + function getMustache() { + // Lazily retrieve Mustache from the window global if it hasn't been defined by + // the User. + if (instance === null) { + instance = window.Mustache; + if (instance === void 0) { + $.error("Failed to locate Mustache instance, are you sure it has been loaded?"); + } + } + return instance; + } + + /** + * Returns true if the supplied templateName has been added. + */ + function has(templateName) { + return templateMap[templateName] !== void 0; + } + + /** + * Registers a template so that it can be used by $.Mustache. + * + * @param templateName A name which uniquely identifies this template. + * @param templateHtml The HTML which makes us the template; this will be rendered by Mustache when render() + * is invoked. + * @throws If options.allowOverwrite is false and the templateName has already been registered. + */ + function add(templateName, templateHtml) { + if (!options.allowOverwrite && has(templateName)) { + $.error('TemplateName: ' + templateName + ' is already mapped.'); + return; + } + templateMap[templateName] = $.trim(templateHtml); + } + + /** + * Adds one or more tempaltes from the DOM using either the supplied templateElementIds or by retrieving all script + * tags of the 'domTemplateType'. Templates added in this fashion will be registered with their elementId value. + * + * @param [...templateElementIds] List of element id's present on the DOM which contain templates to be added; + * if none are supplied all script tags that are of the same type as the + * `options.domTemplateType` configuration value will be added. + */ + function addFromDom() { + var templateElementIds; + + // If no args are supplied, all script blocks will be read from the document. + if (arguments.length === 0) { + templateElementIds = $('script[type="' + options.domTemplateType + '"]').map(function () { + return this.id; + }); + } + else { + templateElementIds = $.makeArray(arguments); + } + + $.each(templateElementIds, function() { + var templateElement = document.getElementById(this); + + if (templateElement === null) { + $.error('No such elementId: #' + this); + } + else { + add(this, $(templateElement).html()); + } + }); + } + + /** + * Removes a template, the contents of the removed Template will be returned. + * + * @param templateName The name of the previously registered Mustache template that you wish to remove. + * @returns String which represents the raw content of the template. + */ + function remove(templateName) { + var result = templateMap[templateName]; + delete templateMap[templateName]; + return result; + } + + /** + * Removes all templates and tells Mustache to flush its cache. + */ + function clear() { + templateMap = {}; + getMustache().clearCache(); + } + + /** + * Renders a previously added Mustache template using the supplied templateData object. Note if the supplied + * templateName doesn't exist an empty String will be returned. + */ + function render(templateName, templateData) { + if (!has(templateName)) { + if (options.warnOnMissingTemplates) { + $.error('No template registered for: ' + templateName); + } + return ''; + } + return getMustache().to_html(templateMap[templateName], templateData, templateMap); + } + + /** + * Loads the external Mustache templates located at the supplied URL and registers them for later use. This method + * returns a jQuery Promise and also support an `onComplete` callback. + * + * @param url URL of the external Mustache template file to load. + * @param onComplete Optional callback function which will be invoked when the templates from the supplied URL + * have been loaded and are ready for use. + * @returns jQuery deferred promise which will complete when the templates have been loaded and are + * ready for use. + */ + function load(url, onComplete) { + return $.ajax({ + url: url, + dataType: options.externalTemplateDataType + }).done(function (templates) { + $(templates).filter('script').each(function (i, el) { + add(el.id, $(el).html()); + }); + + if ($.isFunction(onComplete)) { + onComplete(); + } + }); + } + + /** + * Returns an Array of templateNames which have been registered and can be retrieved via + * $.Mustache.render() or $(element).mustache(). + */ + function templates() { + return $.map(templateMap, function (value, key) { + return key; + }); + } + + // Expose the public methods on jQuery.Mustache + $.Mustache = { + options: options, + load: load, + add: add, + addFromDom: addFromDom, + remove: remove, + clear: clear, + render: render, + templates: templates, + instance: instance + }; + + /** + * Renders one or more viewModels into the current jQuery element. + * + * @param templateName The name of the Mustache template you wish to render, Note that the + * template must have been previously loaded and / or added. + * @param templateData One or more JavaScript objects which will be used to render the Mustache + * template. + * @param options.method jQuery method to use when rendering, defaults to 'append'. + */ + $.fn.mustache = function (templateName, templateData, options) { + var settings = $.extend({ + method: 'append' + }, options); + + var renderTemplate = function (obj, viewModel) { + $(obj)[settings.method](render(templateName, viewModel)); + }; + + return this.each(function () { + var element = this; + + // Render a collection of viewModels. + if ($.isArray(templateData)) { + $.each(templateData, function () { + renderTemplate(element, this); + }); + } + + // Render a single viewModel. + else { + renderTemplate(element, templateData); + } + }); + }; + +}(jQuery, window)); \ No newline at end of file