diff --git a/.jshintrc b/.jshintrc index ad9dfcc..c9d3bea 100644 --- a/.jshintrc +++ b/.jshintrc @@ -10,7 +10,6 @@ "latedef": true, "newcap": true, "noarg": true, - "quotmark": "single", "regexp": true, "undef": true, "unused": true, diff --git a/app/audio/alert.mp3 b/app/audio/alert.mp3 new file mode 100644 index 0000000..b72eda8 Binary files /dev/null and b/app/audio/alert.mp3 differ diff --git a/app/audio/alert.ogg b/app/audio/alert.ogg new file mode 100644 index 0000000..1e26281 Binary files /dev/null and b/app/audio/alert.ogg differ diff --git a/app/audio/alert.wav b/app/audio/alert.wav new file mode 100644 index 0000000..d608f03 Binary files /dev/null and b/app/audio/alert.wav differ diff --git a/app/images/angular.png b/app/images/angular.png deleted file mode 100644 index 59f36fa..0000000 Binary files a/app/images/angular.png and /dev/null differ diff --git a/app/images/browsersync.png b/app/images/browsersync.png deleted file mode 100644 index 201c641..0000000 Binary files a/app/images/browsersync.png and /dev/null differ diff --git a/app/images/gulp.png b/app/images/gulp.png deleted file mode 100644 index 5da1891..0000000 Binary files a/app/images/gulp.png and /dev/null differ diff --git a/app/images/jasmine.png b/app/images/jasmine.png deleted file mode 100644 index 5be8ec8..0000000 Binary files a/app/images/jasmine.png and /dev/null differ diff --git a/app/images/karma.png b/app/images/karma.png deleted file mode 100644 index 48b9601..0000000 Binary files a/app/images/karma.png and /dev/null differ diff --git a/app/images/less.png b/app/images/less.png deleted file mode 100644 index a6bbde7..0000000 Binary files a/app/images/less.png and /dev/null differ diff --git a/app/images/protractor.png b/app/images/protractor.png deleted file mode 100644 index 98e0162..0000000 Binary files a/app/images/protractor.png and /dev/null differ diff --git a/app/images/yeoman.png b/app/images/yeoman.png deleted file mode 100644 index 92497ad..0000000 Binary files a/app/images/yeoman.png and /dev/null differ diff --git a/app/img/apple-touch-icon-precomposed.png b/app/img/apple-touch-icon-precomposed.png new file mode 100644 index 0000000..46c0221 Binary files /dev/null and b/app/img/apple-touch-icon-precomposed.png differ diff --git a/app/img/cb-loading-640x920.png b/app/img/cb-loading-640x920.png new file mode 100644 index 0000000..4cbf64e Binary files /dev/null and b/app/img/cb-loading-640x920.png differ diff --git a/app/img/cb-loading-phone.png b/app/img/cb-loading-phone.png new file mode 100644 index 0000000..8864eb0 Binary files /dev/null and b/app/img/cb-loading-phone.png differ diff --git a/app/img/cb-loading.png b/app/img/cb-loading.png new file mode 100644 index 0000000..25b8466 Binary files /dev/null and b/app/img/cb-loading.png differ diff --git a/app/img/cb-logo-small-white.png b/app/img/cb-logo-small-white.png new file mode 100644 index 0000000..6a813df Binary files /dev/null and b/app/img/cb-logo-small-white.png differ diff --git a/app/img/cb-logo-small.png b/app/img/cb-logo-small.png new file mode 100644 index 0000000..1a81eb4 Binary files /dev/null and b/app/img/cb-logo-small.png differ diff --git a/app/img/chat-white.png b/app/img/chat-white.png new file mode 100644 index 0000000..7d2a503 Binary files /dev/null and b/app/img/chat-white.png differ diff --git a/app/img/chat.png b/app/img/chat.png new file mode 100644 index 0000000..b67abd3 Binary files /dev/null and b/app/img/chat.png differ diff --git a/app/img/favicon.ico b/app/img/favicon.ico new file mode 100644 index 0000000..95dcf91 Binary files /dev/null and b/app/img/favicon.ico differ diff --git a/app/img/gradient.png b/app/img/gradient.png new file mode 100644 index 0000000..889c47b Binary files /dev/null and b/app/img/gradient.png differ diff --git a/app/img/icons/desktop.ico b/app/img/icons/desktop.ico new file mode 100644 index 0000000..c0b2025 Binary files /dev/null and b/app/img/icons/desktop.ico differ diff --git a/app/img/icons/phone.ico b/app/img/icons/phone.ico new file mode 100644 index 0000000..45c8435 Binary files /dev/null and b/app/img/icons/phone.ico differ diff --git a/app/img/suite.png b/app/img/suite.png new file mode 100644 index 0000000..fbfe194 Binary files /dev/null and b/app/img/suite.png differ diff --git a/app/index.html b/app/index.html index 7389ce4..7dacd94 100644 --- a/app/index.html +++ b/app/index.html @@ -1,64 +1,186 @@ - + frontend - - - + + + + + + + + + + + + - - + + - + - - - - -
- - - + + +
+
+
+
+ + +
+
+ + +
+
+ Welcome, {{ active_user.first_name }} +
+ - - - - - - - - - - - +
+

Alerts

+ +
    +
  • No current alerts

  • +
+
+
+ +
- - - - - - - + +
+ +
+
+ +
+
+

Area Map

+
+ +
+
+
+ +
+ + + +
+ +
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + diff --git a/app/partials/main.html b/app/partials/main.html index 52198d4..5b74965 100644 --- a/app/partials/main.html +++ b/app/partials/main.html @@ -1,39 +1,6 @@ -
- - - -
-

'Allo, 'Allo!

-

- I'm Yeoman
- Always a pleasure scaffolding your apps. -

-

Splendid!

-
- -
-
- {{awesomeThing.title}} -
-

{{awesomeThing.title}}

-

{{awesomeThing.description}}

-

{{awesomeThing.url}}

-
-
-
- -
- - - +
+ + +
+
diff --git a/app/scripts/components/channel/channel-directive.js b/app/scripts/components/channel/channel-directive.js new file mode 100644 index 0000000..4676a08 --- /dev/null +++ b/app/scripts/components/channel/channel-directive.js @@ -0,0 +1,12 @@ +'use strict'; + +angular.module('chatBlendApp', []) + .directive('channel', function() { + return { + restrict: 'AEC', + scope: { + // bindings from directive attributes + }, + templateUrl: 'partials/scripts/components/channel/channel.html' + }; + }); \ No newline at end of file diff --git a/app/scripts/components/channel/channel.html b/app/scripts/components/channel/channel.html new file mode 100644 index 0000000..41b786c --- /dev/null +++ b/app/scripts/components/channel/channel.html @@ -0,0 +1,107 @@ +
+
+

+ {{ name }} + {{ (typeof phone_number !== 'undefined' && typeof phone_number.phone_number !== 'undefined' ? '— ' + phone_number.phone_number : '') }} +
+
+ {{ (typeof phone_number !== 'undefined' ? '
' : '') }} +
+

+ +
+ + + +
+
+
+ +
    +
+
+
+ +

No active conversations

+
+
+ + + + +
\ No newline at end of file diff --git a/app/scripts/components/conversation/conversation-directive.js b/app/scripts/components/conversation/conversation-directive.js new file mode 100644 index 0000000..ceda732 --- /dev/null +++ b/app/scripts/components/conversation/conversation-directive.js @@ -0,0 +1,12 @@ +'use strict'; + +angular.module('chatBlendApp', []) + .directive('conversation', function() { + return { + restrict: 'AEC', + scope: { + // bindings from directive attributes + }, + templateUrl: 'partials/scripts/components/conversation/conversation.html' + }; + }); \ No newline at end of file diff --git a/app/scripts/components/conversation/conversation.html b/app/scripts/components/conversation/conversation.html new file mode 100644 index 0000000..c809766 --- /dev/null +++ b/app/scripts/components/conversation/conversation.html @@ -0,0 +1,67 @@ +
+

{{ (visitor.metas && visitor.metas.name) || visitor.ip || visitor.phone_number }}

+
{{ visitor.ip }}
+
+ +
+
+
    + +
+ +
+
\ No newline at end of file diff --git a/app/scripts/components/message/message-directive.js b/app/scripts/components/message/message-directive.js new file mode 100644 index 0000000..81496ed --- /dev/null +++ b/app/scripts/components/message/message-directive.js @@ -0,0 +1,12 @@ +'use strict'; + +angular.module('chatBlendApp', []) + .directive('message', function() { + return { + restrict: 'AEC', + scope: { + // bindings from directive attributes + }, + templateUrl: 'partials/scripts/components/message/message.html' + }; + }); \ No newline at end of file diff --git a/app/scripts/components/message/message.html b/app/scripts/components/message/message.html new file mode 100644 index 0000000..ae726dd --- /dev/null +++ b/app/scripts/components/message/message.html @@ -0,0 +1,4 @@ +
  • +
    {{ created_at }}
    +

    {{ message }}

    +
  • \ No newline at end of file diff --git a/app/scripts/components/quickMessage/quickMessage-directive.js b/app/scripts/components/quickMessage/quickMessage-directive.js new file mode 100644 index 0000000..335a7ba --- /dev/null +++ b/app/scripts/components/quickMessage/quickMessage-directive.js @@ -0,0 +1,12 @@ +'use strict'; + +angular.module('chatBlendApp', []) + .directive('quickMessage', function() { + return { + restrict: 'AEC', + scope: { + // bindings from directive attributes + }, + templateUrl: 'partials/scripts/components/quickMessage/quickMessage.html' + }; + }); \ No newline at end of file diff --git a/app/scripts/components/quickMessage/quickMessage.html b/app/scripts/components/quickMessage/quickMessage.html new file mode 100644 index 0000000..7141a29 --- /dev/null +++ b/app/scripts/components/quickMessage/quickMessage.html @@ -0,0 +1,4 @@ +
  • +

    {{ label }}

    +

    {{ message }}

    +
  • \ No newline at end of file diff --git a/app/scripts/components/visitor/visitor-directive.js b/app/scripts/components/visitor/visitor-directive.js new file mode 100644 index 0000000..4162da1 --- /dev/null +++ b/app/scripts/components/visitor/visitor-directive.js @@ -0,0 +1,12 @@ +'use strict'; + +angular.module('chatBlendApp', []) + .directive('visitor', function() { + return { + restrict: 'AEC', + scope: { + // bindings from directive attributes + }, + templateUrl: 'partials/scripts/components/visitor/visitor.html' + }; + }); \ No newline at end of file diff --git a/app/scripts/components/visitor/visitor.html b/app/scripts/components/visitor/visitor.html new file mode 100644 index 0000000..849d571 --- /dev/null +++ b/app/scripts/components/visitor/visitor.html @@ -0,0 +1,6 @@ +
  • + + {{ status }} + {{ (visitor.metas && visitor.metas.name) || visitor.ip || visitor.phone_number }} + +
  • \ No newline at end of file diff --git a/app/scripts/pushstream.js b/app/scripts/pushstream.js new file mode 100644 index 0000000..b19efad --- /dev/null +++ b/app/scripts/pushstream.js @@ -0,0 +1,1072 @@ +/*jshint evil: true, plusplus: false, regexp: false */ +/** + * Copyright (C) 2010-2013 Wandenberg Peixoto , Rogério Carvalho Schneider + * + * This file is part of Nginx Push Stream Module. + * + * Nginx Push Stream Module 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. + * + * Nginx Push Stream Module 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 Nginx Push Stream Module. If not, see . + * + * + * pushstream.js + * + * Created: Nov 01, 2011 + * Authors: Wandenberg Peixoto , Rogério Carvalho Schneider + */ + var window, document; +(function (window, document, undefined) { + "use strict"; + + /* prevent duplicate declaration */ + if (window.PushStream) { return; } + + var Utils = {}; + + var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + + var valueToTwoDigits = function (value) { + return ((value < 10) ? '0' : '') + value; + }; + + Utils.dateToUTCString = function (date) { + var time = valueToTwoDigits(date.getUTCHours()) + ':' + valueToTwoDigits(date.getUTCMinutes()) + ':' + valueToTwoDigits(date.getUTCSeconds()); + return days[date.getUTCDay()] + ', ' + valueToTwoDigits(date.getUTCDate()) + ' ' + months[date.getUTCMonth()] + ' ' + date.getUTCFullYear() + ' ' + time + ' GMT'; + }; + + var extend = function () { + var object = arguments[0] || {}; + for (var i = 0; i < arguments.length; i++) { + var settings = arguments[i]; + for (var attr in settings) { + if (!settings.hasOwnProperty || settings.hasOwnProperty(attr)) { + object[attr] = settings[attr]; + } + } + } + return object; + }; + + var validChars = /^[\],:{}\s]*$/, + validEscape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + validTokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + validBraces = /(?:^|:|,)(?:\s*\[)+/g; + + var trim = function(value) { + return value.replace(/^\s*/, "").replace(/\s*$/, ""); + }; + + Utils.parseJSON = function(data) { + if (!data || !isString(data)) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = trim(data); + + // Attempt to parse using the native JSON parser first + if (window.JSON && window.JSON.parse) { + try { + return window.JSON.parse( data ); + } catch(e) { + throw "Invalid JSON: " + data; + } + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if (validChars.test(data.replace(validEscape, "@").replace( validTokens, "]").replace( validBraces, "")) ) { + return (new Function("return " + data))(); + } + + throw "Invalid JSON: " + data; + }; + + var getControlParams = function(pushstream) { + var data = {}; + data[pushstream.tagArgument] = ""; + data[pushstream.timeArgument] = ""; + data[pushstream.eventIdArgument] = ""; + if (pushstream.messagesControlByArgument) { + data[pushstream.tagArgument] = Number(pushstream._etag); + if (pushstream._lastModified) { + data[pushstream.timeArgument] = pushstream._lastModified; + } else if (pushstream._lastEventId) { + data[pushstream.eventIdArgument] = pushstream._lastEventId; + } + } + return data; + }; + + var getTime = function() { + return (new Date()).getTime(); + }; + + var currentTimestampParam = function() { + return { "_" : getTime() }; + }; + + var objectToUrlParams = function(settings) { + var params = settings; + if (typeof(settings) === 'object') { + params = ''; + for (var attr in settings) { + if (!settings.hasOwnProperty || settings.hasOwnProperty(attr)) { + params += '&' + attr + '=' + window.escape(settings[attr]); + } + } + params = params.substring(1); + } + + return params || ''; + }; + + var addParamsToUrl = function(url, params) { + return url + ((url.indexOf('?') < 0) ? '?' : '&') + objectToUrlParams(params); + }; + + var isArray = Array.isArray || function(obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + + var isString = function(obj) { + return Object.prototype.toString.call(obj) === '[object String]'; + }; + + var isDate = function(obj) { + return Object.prototype.toString.call(obj) === '[object Date]'; + }; + + var Log4js = { + logger: null, + debug : function() { if (PushStream.LOG_LEVEL === 'debug') { Log4js._log.apply(Log4js._log, arguments); }}, + info : function() { if ((PushStream.LOG_LEVEL === 'info') || (PushStream.LOG_LEVEL === 'debug')) { Log4js._log.apply(Log4js._log, arguments); }}, + error : function() { Log4js._log.apply(Log4js._log, arguments); }, + _log : function() { + if (!Log4js.logger) { + var console = window.console; + if (console && console.log) { + if (console.log.apply) { + Log4js.logger = console.log; + } else if ((typeof console.log === "object") && Function.prototype.bind) { + Log4js.logger = Function.prototype.bind.call(console.log, console); + } else if ((typeof console.log === "object") && Function.prototype.call) { + Log4js.logger = function() { + Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments)); + }; + } + } + } + + if (Log4js.logger) { + Log4js.logger.apply(window.console, arguments); + } + + var logElement = document.getElementById(PushStream.LOG_OUTPUT_ELEMENT_ID); + if (logElement) { + var str = ''; + for (var i = 0; i < arguments.length; i++) { + str += arguments[i] + " "; + } + logElement.innerHTML += str + '\n'; + + var lines = logElement.innerHTML.split('\n'); + if (lines.length > 100) { + logElement.innerHTML = lines.slice(-100).join('\n'); + } + } + } + }; + + var Ajax = { + _getXHRObject : function() { + var xhr = false; + try { xhr = new window.XMLHttpRequest(); } + catch (e1) { + try { xhr = new window.XDomainRequest(); } + catch (e2) { + try { xhr = new window.ActiveXObject("Msxml2.XMLHTTP"); } + catch (e3) { + try { xhr = new window.ActiveXObject("Microsoft.XMLHTTP"); } + catch (e4) { + xhr = false; + } + } + } + } + return xhr; + }, + + _send : function(settings, post) { + settings = settings || {}; + settings.timeout = settings.timeout || 30000; + var xhr = Ajax._getXHRObject(); + if (!xhr||!settings.url) { return; } + + Ajax.clear(settings); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + Ajax.clear(settings); + if (settings.afterReceive) { settings.afterReceive(xhr); } + if(xhr.status === 200) { + if (settings.success) { settings.success(xhr.responseText); } + } else { + if (settings.error) { settings.error(xhr.status); } + } + } + }; + + if (settings.beforeOpen) { settings.beforeOpen(xhr); } + + var params = {}; + var body = null; + var method = "GET"; + if (post) { + body = objectToUrlParams(settings.data); + method = "POST"; + } else { + params = settings.data || {}; + } + + xhr.open(method, addParamsToUrl(settings.url, extend({}, params, currentTimestampParam())), true); + + if (settings.beforeSend) { settings.beforeSend(xhr); } + + var onerror = function() { + try { xhr.abort(); } catch (e) { /* ignore error on closing */ } + Ajax.clear(settings); + settings.error(304); + }; + + if (post) { + xhr.setRequestHeader("Accept", "application/json"); + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + } else { + settings.timeoutId = window.setTimeout(onerror, settings.timeout + 2000); + } + + xhr.send(body); + return xhr; + }, + + _clearScript : function(script) { + // Handling memory leak in IE, removing and dereference the script + if (script) { + script.onerror = script.onload = script.onreadystatechange = null; + if (script.parentNode) { script.parentNode.removeChild(script); } + } + }, + + _clearTimeout : function(settings) { + settings.timeoutId = clearTimer(settings.timeoutId); + }, + + clear : function(settings) { + Ajax._clearTimeout(settings); + Ajax._clearScript(document.getElementById(settings.scriptId)); + }, + + jsonp : function(settings) { + settings.timeout = settings.timeout || 30000; + Ajax.clear(settings); + + var head = document.head || document.getElementsByTagName("head")[0]; + var script = document.createElement("script"); + var startTime = getTime(); + + var onerror = function() { + Ajax.clear(settings); + var callbackFunctionName = settings.data.callback; + if (callbackFunctionName) { window[callbackFunctionName] = function() { window[callbackFunctionName] = null; }; } + var endTime = getTime(); + settings.error(((endTime - startTime) > settings.timeout/2) ? 304 : 0); + }; + + var onload = function() { + Ajax.clear(settings); + settings.load(); + }; + + script.onerror = onerror; + script.onload = script.onreadystatechange = function() { + if (!script.readyState || /loaded|complete/.test(script.readyState)) { + onload(); + } + }; + + if (settings.beforeOpen) { settings.beforeOpen({}); } + if (settings.beforeSend) { settings.beforeSend({}); } + + settings.timeoutId = window.setTimeout(onerror, settings.timeout + 2000); + settings.scriptId = settings.scriptId || getTime(); + + var callbackFunctionName = settings.data.callback; + if (callbackFunctionName) { window[callbackFunctionName] = function() { window[callbackFunctionName] = null; }; } + settings.data.callback = settings.scriptId + "_onmessage_" + getTime(); + window[settings.data.callback] = settings.success; + + script.setAttribute("src", addParamsToUrl(settings.url, extend({}, settings.data, currentTimestampParam()))); + script.setAttribute("async", "async"); + script.setAttribute("id", settings.scriptId); + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + head.insertBefore(script, head.firstChild); + return settings; + }, + + load : function(settings) { + return Ajax._send(settings, false); + }, + + post : function(settings) { + return Ajax._send(settings, true); + } + }; + + var escapeText = function(text) { + return (text) ? window.escape(text) : ''; + }; + + var unescapeText = function(text) { + return (text) ? window.unescape(text) : ''; + }; + + Utils.parseMessage = function(messageText, keys) { + var msg = messageText; + if (isString(messageText)) { + msg = Utils.parseJSON(messageText); + } + + var message = { + id : msg[keys.jsonIdKey], + channel: msg[keys.jsonChannelKey], + text : isString(msg[keys.jsonTextKey]) ? unescapeText(msg[keys.jsonTextKey]) : msg[keys.jsonTextKey], + tag : msg[keys.jsonTagKey], + time : msg[keys.jsonTimeKey], + eventid: msg[keys.jsonEventIdKey] || "" + }; + + return message; + }; + + var getBacktrack = function(options) { + return (options.backtrack) ? ".b" + Number(options.backtrack) : ""; + }; + + var getChannelsPath = function(channels, withBacktrack) { + var path = ''; + for (var channelName in channels) { + if (!channels.hasOwnProperty || channels.hasOwnProperty(channelName)) { + path += "/" + channelName + (withBacktrack ? getBacktrack(channels[channelName]) : ""); + } + } + return path; + }; + + var getSubscriberUrl = function(pushstream, prefix, extraParams, withBacktrack) { + var websocket = pushstream.wrapper.type === WebSocketWrapper.TYPE; + var useSSL = pushstream.useSSL; + var url = (websocket) ? ((useSSL) ? "wss://" : "ws://") : ((useSSL) ? "https://" : "http://"); + url += pushstream.host; + url += ((!useSSL && pushstream.port === 80) || (useSSL && pushstream.port === 443)) ? "" : (":" + pushstream.port); + url += prefix; + + var channels = getChannelsPath(pushstream.channels, withBacktrack); + if (pushstream.channelsByArgument) { + var channelParam = {}; + channelParam[pushstream.channelsArgument] = channels.substring(1); + extraParams = extend({}, extraParams, channelParam); + } else { + url += channels; + } + return addParamsToUrl(url, extraParams); + }; + + var getPublisherUrl = function(pushstream) { + var channel = ""; + var url = (pushstream.useSSL) ? "https://" : "http://"; + url += pushstream.host; + url += ((pushstream.port !== 80) && (pushstream.port !== 443)) ? (":" + pushstream.port) : ""; + url += pushstream.urlPrefixPublisher; + for (var channelName in pushstream.channels) { + if (!pushstream.channels.hasOwnProperty || pushstream.channels.hasOwnProperty(channelName)) { + channel = channelName; + break; + } + } + url += "?id=" + channel; + return url; + }; + + Utils.extractXssDomain = function(domain) { + // if domain is an ip address return it, else return ate least the last two parts of it + if (domain.match(/^(\d{1,3}\.){3}\d{1,3}$/)) { + return domain; + } + + var domainParts = domain.split('.'); + // if the domain ends with 3 chars or 2 chars preceded by more than 4 chars, + // we can keep only 2 parts, else we have to keep at least 3 (or all domain name) + var keepNumber = Math.max(domainParts.length - 1, (domain.match(/(\w{4,}\.\w{2}|\.\w{3,})$/) ? 2 : 3)); + + return domainParts.slice(-1 * keepNumber).join('.'); + }; + + var linker = function(method, instance) { + return function() { + return method.apply(instance, arguments); + }; + }; + + var clearTimer = function(timer) { + if (timer) { + window.clearTimeout(timer); + } + return null; + }; + + /* common callbacks */ + var onmessageCallback = function(event) { + Log4js.info("[" + this.type + "] message received", arguments); + var message = Utils.parseMessage(event.data, this.pushstream); + if (message.tag) { this.pushstream._etag = message.tag; } + if (message.time) { this.pushstream._lastModified = message.time; } + if (message.eventid) { this.pushstream._lastEventId = message.eventid; } + this.pushstream._onmessage(message.text, message.id, message.channel, message.eventid, true); + }; + + var onopenCallback = function() { + this.pushstream._onopen(); + Log4js.info("[" + this.type + "] connection opened"); + }; + + var onerrorCallback = function(event) { + Log4js.info("[" + this.type + "] error (disconnected by server):", event); + if ((this.pushstream.readyState === PushStream.OPEN) && + (this.type === EventSourceWrapper.TYPE) && + (event.type === 'error') && + (this.connection.readyState === window.EventSource.CONNECTING)) { + // EventSource already has a reconnection function using the last-event-id header + return; + } + this._closeCurrentConnection(); + this.pushstream._onerror({type: ((event && ((event.type === "load") || (event.type === "close"))) || (this.pushstream.readyState === PushStream.CONNECTING)) ? "load" : "timeout"}); + }; + + /* wrappers */ + + var WebSocketWrapper = function(pushstream) { + if (!window.WebSocket && !window.MozWebSocket) { throw "WebSocket not supported"; } + this.type = WebSocketWrapper.TYPE; + this.pushstream = pushstream; + this.connection = null; + }; + + WebSocketWrapper.TYPE = "WebSocket"; + + WebSocketWrapper.prototype = { + connect: function() { + this._closeCurrentConnection(); + var params = extend({}, this.pushstream.extraParams(), currentTimestampParam(), getControlParams(this.pushstream)); + var url = getSubscriberUrl(this.pushstream, this.pushstream.urlPrefixWebsocket, params, !this.pushstream._useControlArguments()); + this.connection = (window.WebSocket) ? new window.WebSocket(url) : new window.MozWebSocket(url); + this.connection.onerror = linker(onerrorCallback, this); + this.connection.onclose = linker(onerrorCallback, this); + this.connection.onopen = linker(onopenCallback, this); + this.connection.onmessage = linker(onmessageCallback, this); + Log4js.info("[WebSocket] connecting to:", url); + }, + + disconnect: function() { + if (this.connection) { + Log4js.debug("[WebSocket] closing connection to:", this.connection.URL); + this.connection.onclose = null; + this._closeCurrentConnection(); + this.pushstream._onclose(); + } + }, + + _closeCurrentConnection: function() { + if (this.connection) { + try { this.connection.close(); } catch (e) { /* ignore error on closing */ } + this.connection = null; + } + }, + + sendMessage: function(message) { + if (this.connection) { this.connection.send(message); } + } + }; + + var EventSourceWrapper = function(pushstream) { + if (!window.EventSource) { throw "EventSource not supported"; } + this.type = EventSourceWrapper.TYPE; + this.pushstream = pushstream; + this.connection = null; + }; + + EventSourceWrapper.TYPE = "EventSource"; + + EventSourceWrapper.prototype = { + connect: function() { + this._closeCurrentConnection(); + var params = extend({}, this.pushstream.extraParams(), currentTimestampParam(), getControlParams(this.pushstream)); + var url = getSubscriberUrl(this.pushstream, this.pushstream.urlPrefixEventsource, params, !this.pushstream._useControlArguments()); + this.connection = new window.EventSource(url); + this.connection.onerror = linker(onerrorCallback, this); + this.connection.onopen = linker(onopenCallback, this); + this.connection.onmessage = linker(onmessageCallback, this); + Log4js.info("[EventSource] connecting to:", url); + }, + + disconnect: function() { + if (this.connection) { + Log4js.debug("[EventSource] closing connection to:", this.connection.URL); + this.connection.onclose = null; + this._closeCurrentConnection(); + this.pushstream._onclose(); + } + }, + + _closeCurrentConnection: function() { + if (this.connection) { + try { this.connection.close(); } catch (e) { /* ignore error on closing */ } + this.connection = null; + } + } + }; + + var StreamWrapper = function(pushstream) { + this.type = StreamWrapper.TYPE; + this.pushstream = pushstream; + this.connection = null; + this.url = null; + this.frameloadtimer = null; + this.pingtimer = null; + this.iframeId = "PushStreamManager_" + pushstream.id; + }; + + StreamWrapper.TYPE = "Stream"; + + StreamWrapper.prototype = { + connect: function() { + this._closeCurrentConnection(); + var domain = Utils.extractXssDomain(this.pushstream.host); + try { + document.domain = domain; + } catch(e) { + Log4js.error("[Stream] (warning) problem setting document.domain = " + domain + " (OBS: IE8 does not support set IP numbers as domain)"); + } + var params = extend({}, this.pushstream.extraParams(), currentTimestampParam(), {"streamid": this.pushstream.id}, getControlParams(this.pushstream)); + this.url = getSubscriberUrl(this.pushstream, this.pushstream.urlPrefixStream, params, !this.pushstream._useControlArguments()); + Log4js.debug("[Stream] connecting to:", this.url); + this.loadFrame(this.url); + }, + + disconnect: function() { + if (this.connection) { + Log4js.debug("[Stream] closing connection to:", this.url); + this._closeCurrentConnection(); + this.pushstream._onclose(); + } + }, + + _clearIframe: function() { + var oldIframe = document.getElementById(this.iframeId); + if (oldIframe) { + oldIframe.onload = null; + oldIframe.src = "about:blank"; + if (oldIframe.parentNode) { oldIframe.parentNode.removeChild(oldIframe); } + } + }, + + _closeCurrentConnection: function() { + this._clearIframe(); + if (this.connection) { + this.pingtimer = clearTimer(this.pingtimer); + this.frameloadtimer = clearTimer(this.frameloadtimer); + this.connection = null; + this.transferDoc = null; + if (typeof window.CollectGarbage === 'function') { window.CollectGarbage(); } + } + }, + + loadFrame: function(url) { + this._clearIframe(); + try { + var transferDoc = new window.ActiveXObject("htmlfile"); + transferDoc.open(); + transferDoc.write(""); + transferDoc.parentWindow.PushStream = PushStream; + transferDoc.close(); + var ifrDiv = transferDoc.createElement("div"); + transferDoc.appendChild(ifrDiv); + ifrDiv.innerHTML = ""; + this.connection = ifrDiv.getElementsByTagName("IFRAME")[0]; + this.connection.onload = linker(onerrorCallback, this); + this.transferDoc = transferDoc; + } catch (e) { + var ifr = document.createElement("IFRAME"); + ifr.style.width = "1px"; + ifr.style.height = "1px"; + ifr.style.border = "none"; + ifr.style.position = "absolute"; + ifr.style.top = "-10px"; + ifr.style.marginTop = "-10px"; + ifr.style.zIndex = "-20"; + ifr.PushStream = PushStream; + document.body.appendChild(ifr); + ifr.setAttribute("src", url); + ifr.onload = linker(onerrorCallback, this); + this.connection = ifr; + } + this.connection.setAttribute("id", this.iframeId); + this.frameloadtimer = window.setTimeout(linker(onerrorCallback, this), this.pushstream.timeout); + }, + + register: function(iframeWindow) { + this.frameloadtimer = clearTimer(this.frameloadtimer); + iframeWindow.p = linker(this.process, this); + this.connection.onload = linker(this._onframeloaded, this); + this.pushstream._onopen(); + this.setPingTimer(); + Log4js.info("[Stream] frame registered"); + }, + + process: function(id, channel, text, eventid, time, tag) { + this.pingtimer = clearTimer(this.pingtimer); + Log4js.info("[Stream] message received", arguments); + if (id !== -1) { + if (tag) { this.pushstream._etag = tag; } + if (time) { this.pushstream._lastModified = time; } + if (eventid) { this.pushstream._lastEventId = eventid; } + } + this.pushstream._onmessage(unescapeText(text), id, channel, eventid || "", true); + this.setPingTimer(); + }, + + _onframeloaded: function() { + Log4js.info("[Stream] frame loaded (disconnected by server)"); + this.connection.onload = null; + this.disconnect(); + }, + + setPingTimer: function() { + if (this.pingtimer) { clearTimer(this.pingtimer); } + this.pingtimer = window.setTimeout(linker(onerrorCallback, this), this.pushstream.pingtimeout); + } + }; + + var LongPollingWrapper = function(pushstream) { + this.type = LongPollingWrapper.TYPE; + this.pushstream = pushstream; + this.connection = null; + this.opentimer = null; + this.messagesQueue = []; + this._linkedInternalListen = linker(this._internalListen, this); + this.xhrSettings = { + timeout: this.pushstream.timeout, + data: {}, + url: null, + success: linker(this.onmessage, this), + error: linker(this.onerror, this), + load: linker(this.onload, this), + beforeSend: linker(this.beforeSend, this), + afterReceive: linker(this.afterReceive, this) + }; + }; + + LongPollingWrapper.TYPE = "LongPolling"; + + LongPollingWrapper.prototype = { + connect: function() { + this.messagesQueue = []; + this._closeCurrentConnection(); + this.urlWithBacktrack = getSubscriberUrl(this.pushstream, this.pushstream.urlPrefixLongpolling, {}, true); + this.urlWithoutBacktrack = getSubscriberUrl(this.pushstream, this.pushstream.urlPrefixLongpolling, {}, false); + this.xhrSettings.url = this.urlWithBacktrack; + var domain = Utils.extractXssDomain(this.pushstream.host); + var currentDomain = Utils.extractXssDomain(window.location.hostname); + var port = this.pushstream.port; + var currentPort = window.location.port ? Number(window.location.port) : (this.pushstream.useSSL ? 443 : 80); + this.useJSONP = (domain !== currentDomain) || (port !== currentPort) || this.pushstream.useJSONP; + this.xhrSettings.scriptId = "PushStreamManager_" + this.pushstream.id; + if (this.useJSONP) { + this.pushstream.messagesControlByArgument = true; + } + this._internalListen(); + this.opentimer = window.setTimeout(linker(onopenCallback, this), 100); + Log4js.info("[LongPolling] connecting to:", this.xhrSettings.url); + }, + + _listen: function() { + if (this._internalListenTimeout) { clearTimer(this._internalListenTimeout); } + this._internalListenTimeout = window.setTimeout(this._linkedInternalListen, 100); + }, + + _internalListen: function() { + if (this.pushstream._keepConnected) { + this.xhrSettings.url = this.pushstream._useControlArguments() ? this.urlWithoutBacktrack : this.urlWithBacktrack; + this.xhrSettings.data = extend({}, this.pushstream.extraParams(), this.xhrSettings.data, getControlParams(this.pushstream)); + if (this.useJSONP) { + this.connection = Ajax.jsonp(this.xhrSettings); + } else if (!this.connection) { + this.connection = Ajax.load(this.xhrSettings); + } + } + }, + + disconnect: function() { + if (this.connection) { + Log4js.debug("[LongPolling] closing connection to:", this.xhrSettings.url); + this._closeCurrentConnection(); + this.pushstream._onclose(); + } + }, + + _closeCurrentConnection: function() { + this.opentimer = clearTimer(this.opentimer); + if (this.connection) { + try { this.connection.abort(); } catch (e) { + try { Ajax.clear(this.connection); } catch (e) { /* ignore error on closing */ } + } + this.connection = null; + this.xhrSettings.url = null; + } + }, + + beforeSend: function(xhr) { + if (!this.pushstream.messagesControlByArgument) { + xhr.setRequestHeader("If-None-Match", this.pushstream._etag); + xhr.setRequestHeader("If-Modified-Since", this.pushstream._lastModified); + } + }, + + afterReceive: function(xhr) { + if (!this.pushstream.messagesControlByArgument) { + this.pushstream._etag = xhr.getResponseHeader('Etag'); + this.pushstream._lastModified = xhr.getResponseHeader('Last-Modified'); + } + this.connection = null; + }, + + onerror: function(status) { + if (this.pushstream._keepConnected) { /* abort(), called by disconnect(), call this callback, but should be ignored */ + if (status === 304) { + this._listen(); + } else { + Log4js.info("[LongPolling] error (disconnected by server):", status); + this._closeCurrentConnection(); + this.pushstream._onerror({type: ((status === 403) || (this.pushstream.readyState === PushStream.CONNECTING)) ? "load" : "timeout"}); + } + } + }, + + onload: function() { + this._listen(); + }, + + onmessage: function(responseText) { + if (this._internalListenTimeout) { clearTimer(this._internalListenTimeout); } + Log4js.info("[LongPolling] message received", responseText); + var lastMessage = null; + var messages = isArray(responseText) ? responseText : responseText.replace(/\}\{/g, "}\r\n{").split("\r\n"); + for (var i = 0; i < messages.length; i++) { + if (messages[i]) { + lastMessage = Utils.parseMessage(messages[i], this.pushstream); + this.messagesQueue.push(lastMessage); + if (this.pushstream.messagesControlByArgument && lastMessage.time) { + this.pushstream._etag = lastMessage.tag; + this.pushstream._lastModified = lastMessage.time; + } + } + } + + this._listen(); + + while (this.messagesQueue.length > 0) { + var message = this.messagesQueue.shift(); + this.pushstream._onmessage(message.text, message.id, message.channel, message.eventid, (this.messagesQueue.length === 0)); + } + } + }; + + /* mains class */ + + var PushStreamManager = []; + + var PushStream = function(settings) { + settings = settings || {}; + + this.id = PushStreamManager.push(this) - 1; + + this.useSSL = settings.useSSL || false; + this.host = settings.host || window.location.hostname; + this.port = Number(settings.port || (this.useSSL ? 443 : 80)); + + this.timeout = settings.timeout || 30000; + this.pingtimeout = settings.pingtimeout || 30000; + this.reconnectOnTimeoutInterval = settings.reconnectOnTimeoutInterval || 3000; + this.reconnectOnChannelUnavailableInterval = settings.reconnectOnChannelUnavailableInterval || 60000; + + this.lastEventId = settings.lastEventId || null; + this.messagesPublishedAfter = settings.messagesPublishedAfter; + this.messagesControlByArgument = settings.messagesControlByArgument || false; + this.tagArgument = settings.tagArgument || 'tag'; + this.timeArgument = settings.timeArgument || 'time'; + this.eventIdArgument = settings.eventIdArgument || 'eventid'; + this.useJSONP = settings.useJSONP || false; + + this._reconnecttimer = null; + this._etag = 0; + this._lastModified = null; + this._lastEventId = null; + + this.urlPrefixPublisher = settings.urlPrefixPublisher || '/pub'; + this.urlPrefixStream = settings.urlPrefixStream || '/sub'; + this.urlPrefixEventsource = settings.urlPrefixEventsource || '/ev'; + this.urlPrefixLongpolling = settings.urlPrefixLongpolling || '/lp'; + this.urlPrefixWebsocket = settings.urlPrefixWebsocket || '/ws'; + + this.jsonIdKey = settings.jsonIdKey || 'id'; + this.jsonChannelKey = settings.jsonChannelKey || 'channel'; + this.jsonTextKey = settings.jsonTextKey || 'text'; + this.jsonTagKey = settings.jsonTagKey || 'tag'; + this.jsonTimeKey = settings.jsonTimeKey || 'time'; + this.jsonEventIdKey = settings.jsonEventIdKey || 'eventid'; + + this.modes = (settings.modes || 'eventsource|websocket|stream|longpolling').split('|'); + this.wrappers = []; + this.wrapper = null; + + this.onchanneldeleted = settings.onchanneldeleted || null; + this.onmessage = settings.onmessage || null; + this.onerror = settings.onerror || null; + this.onstatuschange = settings.onstatuschange || null; + this.extraParams = settings.extraParams || function() { return {}; }; + + this.channels = {}; + this.channelsCount = 0; + this.channelsByArgument = settings.channelsByArgument || false; + this.channelsArgument = settings.channelsArgument || 'channels'; + + + for (var i = 0; i < this.modes.length; i++) { + try { + var wrapper = null; + switch (this.modes[i]) { + case "websocket" : wrapper = new WebSocketWrapper(this); break; + case "eventsource": wrapper = new EventSourceWrapper(this); break; + case "longpolling": wrapper = new LongPollingWrapper(this); break; + case "stream" : wrapper = new StreamWrapper(this); break; + } + this.wrappers[this.wrappers.length] = wrapper; + } catch(e) { Log4js.info(e); } + } + + this.readyState = 0; + }; + + /* constants */ + PushStream.LOG_LEVEL = 'error'; /* debug, info, error */ + PushStream.LOG_OUTPUT_ELEMENT_ID = 'Log4jsLogOutput'; + + /* status codes */ + PushStream.CLOSED = 0; + PushStream.CONNECTING = 1; + PushStream.OPEN = 2; + + /* main code */ + PushStream.prototype = { + addChannel: function(channel, options) { + if (escapeText(channel) !== channel) { + throw "Invalid channel name! Channel has to be a set of [a-zA-Z0-9]"; + } + Log4js.debug("entering addChannel"); + if (typeof(this.channels[channel]) !== "undefined") { throw "Cannot add channel " + channel + ": already subscribed"; } + options = options || {}; + Log4js.info("adding channel", channel, options); + this.channels[channel] = options; + this.channelsCount++; + if (this.readyState !== PushStream.CLOSED) { this.connect(); } + Log4js.debug("leaving addChannel"); + }, + + removeChannel: function(channel) { + if (this.channels[channel]) { + Log4js.info("removing channel", channel); + delete this.channels[channel]; + this.channelsCount--; + } + }, + + removeAllChannels: function() { + Log4js.info("removing all channels"); + this.channels = {}; + this.channelsCount = 0; + }, + + _setState: function(state) { + if (this.readyState !== state) { + Log4js.info("status changed", state); + this.readyState = state; + if (this.onstatuschange) { + this.onstatuschange(this.readyState); + } + } + }, + + connect: function() { + Log4js.debug("entering connect"); + if (!this.host) { throw "PushStream host not specified"; } + if (isNaN(this.port)) { throw "PushStream port not specified"; } + if (!this.channelsCount) { throw "No channels specified"; } + if (this.wrappers.length === 0) { throw "No available support for this browser"; } + + this._keepConnected = true; + this._lastUsedMode = 0; + this._connect(); + + Log4js.debug("leaving connect"); + }, + + disconnect: function() { + Log4js.debug("entering disconnect"); + this._keepConnected = false; + this._disconnect(); + this._setState(PushStream.CLOSED); + Log4js.info("disconnected"); + Log4js.debug("leaving disconnect"); + }, + + _useControlArguments :function() { + return this.messagesControlByArgument && ((this._lastModified !== null) || (this._lastEventId !== null)); + }, + + _connect: function() { + if (this._lastEventId === null) { + this._lastEventId = this.lastEventId; + } + if (this._lastModified === null) { + var date = this.messagesPublishedAfter; + if (!isDate(date)) { + var messagesPublishedAfter = Number(this.messagesPublishedAfter); + if (messagesPublishedAfter > 0) { + date = new Date(); + date.setTime(date.getTime() - (messagesPublishedAfter * 1000)); + } else if (messagesPublishedAfter < 0) { + date = new Date(0); + } + } + + if (isDate(date)) { + this._lastModified = Utils.dateToUTCString(date); + } + } + + this._disconnect(); + this._setState(PushStream.CONNECTING); + this.wrapper = this.wrappers[this._lastUsedMode++ % this.wrappers.length]; + + try { + this.wrapper.connect(); + } catch (e) { + //each wrapper has a cleanup routine at disconnect method + if (this.wrapper) { + this.wrapper.disconnect(); + } + } + }, + + _disconnect: function() { + this._reconnecttimer = clearTimer(this._reconnecttimer); + if (this.wrapper) { + this.wrapper.disconnect(); + } + }, + + _onopen: function() { + this._reconnecttimer = clearTimer(this._reconnecttimer); + this._setState(PushStream.OPEN); + if (this._lastUsedMode > 0) { + this._lastUsedMode--; //use same mode on next connection + } + }, + + _onclose: function() { + this._reconnecttimer = clearTimer(this._reconnecttimer); + this._setState(PushStream.CLOSED); + this._reconnect(this.reconnectOnTimeoutInterval); + }, + + _onmessage: function(text, id, channel, eventid, isLastMessageFromBatch) { + Log4js.debug("message", text, id, channel, eventid, isLastMessageFromBatch); + if (id === -2) { + if (this.onchanneldeleted) { this.onchanneldeleted(channel); } + } else if (id > 0) { + if (this.onmessage) { this.onmessage(text, id, channel, eventid, isLastMessageFromBatch); } + } + }, + + _onerror: function(error) { + this._setState(PushStream.CLOSED); + this._reconnect((error.type === "timeout") ? this.reconnectOnTimeoutInterval : this.reconnectOnChannelUnavailableInterval); + if (this.onerror) { this.onerror(error); } + }, + + _reconnect: function(timeout) { + if (this._keepConnected && !this._reconnecttimer && (this.readyState !== PushStream.CONNECTING)) { + Log4js.info("trying to reconnect in", timeout); + this._reconnecttimer = window.setTimeout(linker(this._connect, this), timeout); + } + }, + + sendMessage: function(message, successCallback, errorCallback) { + message = escapeText(message); + if (this.wrapper.type === WebSocketWrapper.TYPE) { + this.wrapper.sendMessage(message); + if (successCallback) { successCallback(); } + } else { + Ajax.post({url: getPublisherUrl(this), data: message, success: successCallback, error: errorCallback}); + } + } + }; + + PushStream.sendMessage = function(url, message, successCallback, errorCallback) { + Ajax.post({url: url, data: escapeText(message), success: successCallback, error: errorCallback}); + }; + + // to make server header template more clear, it calls register and + // by a url parameter we find the stream wrapper instance + PushStream.register = function(iframe) { + var matcher = iframe.window.location.href.match(/streamid=([0-9]*)&?/); + if (matcher[1] && PushStreamManager[matcher[1]]) { + PushStreamManager[matcher[1]].wrapper.register(iframe); + } + }; + + PushStream.unload = function() { + for (var i = 0; i < PushStreamManager.length; i++) { + try { PushStreamManager[i].disconnect(); } catch(e){} + } + }; + + /* make class public */ + window.PushStream = PushStream; + window.PushStreamManager = PushStreamManager; + + if (window.attachEvent) { window.attachEvent("onunload", PushStream.unload); } + if (window.addEventListener) { window.addEventListener.call(window, "unload", PushStream.unload, false); } + +})(window, document); \ No newline at end of file diff --git a/app/styles/base.less b/app/styles/base.less new file mode 100644 index 0000000..f67dc66 --- /dev/null +++ b/app/styles/base.less @@ -0,0 +1,260 @@ +// Reset +* { + margin: 0; + padding: 0; + +} +html, body { + overflow-x:hidden; + font-family: 'Droid Sans', sans-serif; + font-weight: normal; + background-color:#ddd; +} +html.ios body, html.ios { + + font-family: -apple-system-font; + +} +html.ios { + background-color:#307f63; +} + + +// Colors + +@color-p1: #333; +@color-p2: #666; + +@color-s1: #EE5A10; //dashsocial +@color-s2: #2FA1D7; //thehound +@color-s3: #007722; //chatblend + +@color-s1-l: #FF712B; //dashsocial -light +@color-s2-l: #51C7FF; //thehound -light +@color-s3-l: #53cb99; //chatblend -light + + +//Grid System + +@col-width-bp1: 120px; //col width for breakpoint 1 +@col-width-bp2: 100px; //col width for breakpoint 2 +@col-width-bp3: 80px; //col width for breakpoint 3 +@col-width-bp4: 100%; //col width for small glass + + +@grid-width-bp2: 1299px; +@grid-width-bp3: 1109px; +@grid-width-bp4: 909px; + + +@col-margin: 10px; + +// Display Classes + +h1 { + color:@color-s1; + font-size:24px; +} +h2 { + color:@color-p1; + font-size:22px; +} +.font-normal-large { + color:@color-p1; + font-weight: normal; + font-size:24px; +} +.font-banner-large { + color:@color-p1; + font-weight: normal; + font-size:60px; + line-height:1.05em; +} + +p { + color:@color-p2; + font-size:20px; + letter-spacing: .01em; + padding:5px; +} + +a,a:visited,a:hover { + color:@color-s2; + font-weight:normal; + font-size:20px; +} + + + +i.icon { + display:inline-block; +} +i.icon + * { + display:inline-block; +} +.ie7 i.icon { display:none;} + +.fa { + font-family:inherit !important; +} +.fa:before { + font-family:'FontAwesome'; + padding-right:10px; +} +.css-checkbox { + display: none; +} + +.left-color-orange { + border-left: 2px solid #f8b870; + padding-left:8px; + margin-right:-10px; +} +.left-color-grey { + border-left: 2px solid #999; + padding-left:8px; + margin-right:-10px; +} + + +// Responsive Grid System - 4 Breakpoints +.main-container { + width: 1100px; + margin:auto; +} +.row { + position:relative; + clear:both; + margin:auto; + @row-width:@col-width-bp1*10 + @col-margin*11; + width:100%; + + .col { + width:@col-width-bp1; margin-left:@col-margin; float: left; + + &:first-child { + margin-left:0; + } + } + .col.two { width:@col-width-bp1*2 + @col-margin; } + .col.three { width:@col-width-bp1*3 + @col-margin*2; } + .col.four { width:@col-width-bp1*4 + @col-margin*3; } + .col.five { width:@col-width-bp1*5 + @col-margin*4; } + .col.six { width:@col-width-bp1*6 + @col-margin*5; } + .col.seven { width:@col-width-bp1*7 + @col-margin*6; } + .col.eight { width:@col-width-bp1*8 + @col-margin*7; } + .col.nine { width:@col-width-bp1*9 + @col-margin*8; } + .col.ten { width:@col-width-bp1*10 + @col-margin*9;} +} +// allow for nested rows +.row .row { + margin-left:0; + margin-right:0; + padding:0; +} + + +@media screen and (min-width:@grid-width-bp3) and (max-width: @grid-width-bp2) { + + .main-container { + //width: 890px; + //margin:auto; + } + h1 { + font-size:22px; + } + h2 { + font-size:20px; + } + .font-normal-large { + font-size:22px; + } + .font-banner-large { + font-size:52px; + } + .row { + @row-width:@col-width-bp2*10 + @col-margin*11 ; + //width:@row-width; + .col { width:@col-width-bp2; } + .col.two { width:@col-width-bp2*2 + @col-margin; } + .col.three { width:@col-width-bp2*3 + @col-margin*2; } + .col.four { width:@col-width-bp2*4 + @col-margin*3; } + .col.five { width:@col-width-bp2*5 + @col-margin*4; } + .col.six { width:@col-width-bp2*6 + @col-margin*5; } + .col.seven { width:@col-width-bp2*7 + @col-margin*6; } + .col.eight { width:@col-width-bp2*8 + @col-margin*7; } + .col.nine { width:@col-width-bp2*9 + @col-margin*8; } + .col.ten { width:@col-width-bp2*10 + @col-margin*9;} + } +} + +@media screen and (min-width:@grid-width-bp4) and (max-width: @grid-width-bp3) { + + .main-container { + //width: 557px; + //margin:auto; + } + h1 { + font-size:20px; + } + h2 { + font-size:18px; + } + .font-normal-large { + font-size:18px; + } + .font-banner-large { + font-size:40px; + } + + .row { + @row-width:@col-width-bp3*10 + @col-margin*11; + //width:@row-width; + .col { width:@col-width-bp3; } + .col.two { width:@col-width-bp3*2 + @col-margin; } + .col.three { width:@col-width-bp3*3 + @col-margin*2; } + .col.four { width:@col-width-bp3*4 + @col-margin*3; } + .col.five { width:@col-width-bp3*5 + @col-margin*4; } + .col.six { width:@col-width-bp3*6 + @col-margin*5; } + .col.seven { width:@col-width-bp3*7 + @col-margin*6; } + .col.eight { width:@col-width-bp3*8 + @col-margin*7; } + .col.nine { width:@col-width-bp3*9 + @col-margin*8; } + .col.ten { width:@col-width-bp3*10 + @col-margin*9;} + } +} + +@media screen and (max-width: @grid-width-bp4) { + + .main-container { + width: 100%; + } + h1 { + font-size:18px; + } + h2 { + font-size:16px; + } + .font-normal-large { + font-size:16px; + } + .font-banner-large { + font-size:21px; + } + + .row { + width:100%; + padding:0 10px; + box-sizing:border-box; + .col { margin-left:0px;} + .col { width:@col-width-bp4; float:none; } + .col.two { width:@col-width-bp4; } + .col.three { width:@col-width-bp4; } + .col.four { width:@col-width-bp4; } + .col.five { width:@col-width-bp4; } + .col.six { width:@col-width-bp4; } + .col.seven { width:@col-width-bp4; } + .col.eight { width:@col-width-bp4; } + .col.nine { width:@col-width-bp4; } + .col.ten { width:@col-width-bp4; } + } +} \ No newline at end of file diff --git a/app/styles/client.less b/app/styles/client.less new file mode 100644 index 0000000..1b19162 --- /dev/null +++ b/app/styles/client.less @@ -0,0 +1,384 @@ +* { + margin:0; + padding:0; + font-family:arial; +} + + +.cb-container { + width:280px; + padding-top:10px; + border:none; + border-bottom:none; + position:relative; + margin:auto; + display:block; + .mobile { + display:none; + } + .mobile.show { + display:block; + background-color: orange; + color: white; + text-align: center; + min-height: 44px; + line-height: 44px; + position: relative; + top: -5px; + + a{ + color:white; + font-size:14px; + font-weight:bold; + text-decoration:none; + position: absolute; + top: 0; + left: 0; + height: 44px; + width: 100%; + display:block; + } + } + .header { + position:relative; + width:180px; + display:block; + box-shadow:0 0 10px rgba(0,0,0,.25); + border-radius:5px 5px 0 0; + + .fa-comments-o { + position:absolute; + left:15px; + top:10px; + display:block; + z-index:5; + &:before { + font-size:30px; + color:#d07f4a; + } + } + + h2,h3 { + background-color:#eee; + display:block; + text-align:center; + width:150px; + padding-left:30px; + position:relative; + z-index:4; + } + h2 { + color:#222; + padding-top:5px; + line-height:25px; + font-size:16px; + border-radius:5px 5px 0 0; + height:27px; + margin-top:-1px; + } + h3 { + color:#444; + line-height:15px; + padding-bottom:5px; + font-size:12px; + font-weight:normal; + border-bottom:1px solid #ddd; + height:15px; + } + } + .below-tab { + box-shadow:0 0 10px rgba(0,0,0,.25); + border-radius:0 5px 0 0; + overflow:hidden; + } + .body { + background-color:#fff; + height:195px; + display:block; + position:relative; + overflow-y:scroll; + overflow-x:hidden; + padding-top:5px; + + ul li { + transition:.5s; + opacity:1; + position:relative; + right:0px; + } + ul.loading-msg li:last-child { + opacity:0; + right:-30px; + } + .cb-msg { + border-radius:15px; + padding:7px; + position:relative; + min-width:5%; + list-style:none; + margin:10px; + clear:both; + font-weight:normal; + max-width:85%; + p { + font-size:14px; + word-wrap:break-word; + } + + .cb-timestamp { + font-style:italic; + font-size:9px; + color:#666; + position:absolute; + top:-13px; + z-index:4; + white-space:nowrap; + .date { + display:none; + } + .time { + opacity:0; + transition: .5s; + } + .time.show { + opacity:1; + } + } + + &.to { + background-color:#D7EBFF; + float:right; + + .cb-timestamp { + right:0; + } + } + + &.from { + + background-color:#FFEFE8; + float:left; + + } + } + } + .offline-contact .body { + height:243px; + border-radius:5px; + border:1px solid orange; + padding:5px; + margin:5px; + font-size:14px; + + dl { + font-size:14px; + margin:5px; + color:#333; + + input[type='text'],textarea{ + height:22px; + width:80%; + } + } + } + + //Pending Delete + .cb-form { + position: fixed; + display: block; + width: 280px; + } + //end + .footer { + background-color:#eee; + height:50px; + display:block; + position:relative; + overflow:hidden; + padding-top:5px; + + textarea { + height:35px; + border:2px solid #ccc; + border-radius:5px; + width:180px; + margin-left:10px; + position:relative; + font-size:15px; + } + .submit { + display:block; + position:absolute; + border:2px solid #d07f4a; + border-radius:5px; + background-color: #f0d6c6; + color:#666; + text-align:center; + line-height:35px; + width:60px; + margin-right:10px; + font-weight:bold; + cursor:pointer; + left:202px; + top:5px; + } + } +} +//Mobile Interface + +body.mobile_ignore { + +.cb-container { + padding-top:0; + height:75px; + width:75px; + overflow:hidden !important; + border-radius:25px; + transition:.5s; + left:95px; + box-shadow:0px 10px 15px rgba(0,0,0,.25); + .header i.fa-comments-o { + height:75px; + width:75px; + background-color:#ddd; + position:absolute; + top:0; + left:0; + font-size:44px; + padding-left:20px; + + &:before { + top: 10px; + position: relative; + } + + } + h2,h3 { + display:none; + } + } + .below-tab { + opacity:0; + } + #setting-livechat:checked + .cb-container{ + height:100%; + width:100%; + overflow:hidden; + border-radius:0; + padding-top:10px; + left:0; + .header i.fa-comments-o { + + position:absolute; + left:15px; + top:0px; + display:block; + background-color:transparent; + padding-left:0px; + + &:before { + top: 0px; + position: relative; + } + + + + + } + h2,h3 { + display:block; + } + + .below-tab { + opacity:1; + } + } + + &.twox { + .cb-container{ + padding-top:0; + height:300px; + width:300px; + overflow:hidden !important; + border-radius:50px; + transition:.5s; + left:60px; + box-shadow:0px 10px 15px rgba(0,0,0,.25); + + .header i.fa-comments-o { + height:300px; + width:300px; + background-color:#ddd; + position:absolute; + top:0; + left:0; + padding-left:20px; + + &:before { + top: 10px; + position: relative; + + font-size:144px; + transition:.5s; + } + + } + h2,h3 { + display:none; + } + } + #setting-livechat:checked + .cb-container{ + height:100%; + width:100%; + overflow:hidden; + border-radius:0; + padding-top:10px; + left:0; + .header i.fa-comments-o { + position:absolute; + left:15px; + top:0px; + display:block; + background-color:transparent; + padding-left:0px; + &:before { + font-size:90px; + } + } + + h2,h3 { + width:600px; + padding-left:30px; + position:relative; + z-index:4; + } + h2 { + color:#222; + padding-top:20px; + line-height:100px; + font-size:64px; + border-radius:5px 5px 0 0; + height:104px; + margin-top:-1px; + } + h3 { + color:#444; + line-height:60px; + padding-bottom:20px; + font-size:48px; + font-weight:normal; + border-bottom:1px solid #ddd; + height:60px; + } + + .below-tab { + opacity:1; + } + } + + + + } +} + + diff --git a/app/styles/client_side.css b/app/styles/client_side.css new file mode 100644 index 0000000..63c46b7 --- /dev/null +++ b/app/styles/client_side.css @@ -0,0 +1,40 @@ +#chatblend_client { + position:fixed; + display:block; + bottom:0; + right:10px; + width:298px; + height:60px; + transition:.5s; + z-index:10000000; +} +#chatblend_client.mobile { + height:60px; + +} + +#chatblend_client.mobile.twox_ignore { + height:420px; + width:596px; + +} +#chatblend_client.mobile #chatblend_click_ignore { + display:none; + } +#chatblend_client.view { + height:310px; +} + +#chatblend_client iframe { + height:100%; + border:0; +} + +#chatblend_client #chatblend_click { + width: 100%; + position: absolute; + top: 0; + left: 0; + height: 61px; + display: block; +} \ No newline at end of file diff --git a/app/styles/main.less b/app/styles/main.less deleted file mode 100644 index 11916b5..0000000 --- a/app/styles/main.less +++ /dev/null @@ -1,116 +0,0 @@ -.browsehappy { - margin: 0.2em 0; - background: #ccc; - color: #000; - padding: 0.2em 0; -} - -body { - margin: 0; -} - -a { - text-decoration: none; -} - -.container { - width: 1170px; - margin-right: auto; - margin-left: auto; - padding-left: 15px; - padding-right: 15px; -} - -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - background-color: #222; - - &>a { - float: left; - color: lightgrey; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; - height: 50px; - } - - ul { - float: left; - padding: 0; - margin: 0; - - li { - float: left; - position: relative; - display: block; - - a { - color: white; - position: relative; - display: block; - padding: 15px; - line-height: 20px; - } - &.active a { - background-color: black; - } - } - } -} - -.jumbotron { - padding: 60px; - margin-bottom: 30px; - background-color: gainsboro; - border-radius: 6px; - text-align: center; -} - -.btn { - display: inline-block; - text-align: center; - vertical-align: middle; - cursor: pointer; - border: 1px solid transparent; - color: white; - background-color: #5cb85c; - border-color: #4cae4c; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -.col { - float: left; - width: 33.33%; - position: relative; - padding-left: 15px; - padding-right: 15px; - box-sizing: border-box; - - .thumbnail { - height: 200px; - border: 1px solid lightgrey; - border-radius: 4px; - margin-bottom: 20px; - - .caption { - padding: 9px; - } - - img.pull-right { - width: 50px; - } - } -} - -.pull-right { - float: right; -} - -hr { - clear: both; -} diff --git a/app/styles/styles.less b/app/styles/styles.less new file mode 100644 index 0000000..c20b802 --- /dev/null +++ b/app/styles/styles.less @@ -0,0 +1,2869 @@ +// Variables +@link-1 : #2fa1d7; + +@highlight-color-1 : #d07f4a; + +@status-new : #E8BB4C; +@status-waiting : #FF6E52; +@status-engaged : #666; +@status-helped : #307f63; + +@color-s3-l: #459579; //chatblend -light +@color-s3: #307f63; //chatblend + +@color-s1: #ee5a10; // dark orange + +@grid-width-bp0: 1300px; +@grid-width-bp1: 930px; +@grid-width-bp2: 500px; + +html { + height:100%; +} + +body { + background-color:#eee; + position:relative; + min-height:100%; +} + +label { + cursor:pointer; +} + +/* Global Styles */ +.display-none { + display:none !important; +} +.fade-out { + transition:.5s !important; + opacity:0 !important; +} +.fade-in { + transition:.5s !important; + opacity:1 !important; +} + + +//turns a checkbox into a radio slider +input[type="checkbox"].switch{ + display:inline-block; + width:70px; + text-align: center; + cursor:pointer; + position: relative; + top: 0px; + left: 10px; + margin-top:15px; + + &:before { + content:''; + display:block; + position:absolute; + width:70px; + height:40px; + border-radius:18px; + right:0px; + top:-10px; + background-color:@color-s3-l; + transition:.25s; + + } + &:after { + content:''; + display:block; + position:absolute; + height:30px; + width:30px; + border-radius:15px; + border:1px solid @color-s3; + background-color:#fff; + right:33px; + transition:.25s; + top:-6px; + background: rgb(255,255,255); /* Old browsers */ + background: -moz-radial-gradient(center, ellipse cover, rgba(255,255,255,1) 33%, rgba(243,243,243,1) 97%); /* FF3.6+ */ + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(33%,rgba(255,255,255,1)), color-stop(97%,rgba(243,243,243,1))); /* Chrome,Safari4+ */ + background: -webkit-radial-gradient(center, ellipse cover, rgba(255,255,255,1) 33%,rgba(243,243,243,1) 97%); /* Chrome10+,Safari5.1+ */ + background: -o-radial-gradient(center, ellipse cover, rgba(255,255,255,1) 33%,rgba(243,243,243,1) 97%); /* Opera 12+ */ + background: -ms-radial-gradient(center, ellipse cover, rgba(255,255,255,1) 33%,rgba(243,243,243,1) 97%); /* IE10+ */ + background: radial-gradient(ellipse at center, rgba(255,255,255,1) 33%,rgba(243,243,243,1) 97%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f3f3f3',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ + + } + &:checked:before { + background-color:#eee; + } + &:checked:after { + right:5px; + border-color:#bbb; + } + +} + + +.cb-header { + width:100%; + position:fixed; + height:70px; + background-color:white; + border-bottom:1px solid @highlight-color-1; + z-index:101; + @media screen and (max-width: @grid-width-bp2) { + height:50px; + position:relative; + } + + + + .cb-suite-box { + padding-left:50px; + padding-right:420px; + } + .cb-search { + position:absolute; + top:0; + right:0; + width:220px; + width:25%; + height:100%; + border-left:1px solid #ddd; + + + //Temp: supress search on small glass + @media screen and (max-width: @grid-width-bp2) { + height:44px; + width:100%; + position:absolute; + right:0; + top:0; + border-left:none; + background-color:none; + + .search-con { + display:none; + } + + } + .search-con { + z-index: 10; + //background-color:white; + position: relative; + display: block; + height: 100%; + width: 100%; + + } + label.search_text { + font-size:12px; + color: @link-1; + padding-top:2px; + width:57%; + text-align: center; + display:block; + position:relative; + margin-bottom:10px; + left:8%; + @media screen and (max-width: @grid-width-bp2) { + position: absolute; + top: 31px; + right: 11px; + width: 44px; + left:auto; + } + } + .search-input { + width:57%; + border:3px solid #999; + border-radius:5px; + text-align: center; + color:#aaa; + font-style: italic; + left:8%; + position: relative; + height:20px; + margin-top:27px; + transition:.5s; + &:focus { + color:#333; + font-style:normal; + border-color:@highlight-color-1; + } + } + @media screen and (max-width: @grid-width-bp2) { + + #setting-searchshow:checked + .search-con .fa-search:before { + color:@color-s1; + transition:.5s; + } + .search-con .search-input-container { + width: 100%; + background-color: #93C4B3; + right: -100%; + position: absolute; + display: block; + top: 53px; + left: auto; + transition:.5s; + height:46px; + opacity:0; + .search-input { + position: relative; + left: 10%; + margin-top: 7px; + width: 80%; + height: 26px; + transition:.5s; + + } + } + #setting-searchshow:checked + .search-con .search-input-container { + right:0%; + opacity:1; + transition:.5s; + } + } + i.fa-search { + float:right; + position:relative; + top:28px; + margin-right:5%; + @media screen and (max-width: @grid-width-bp2) { + left:-12px; + top:9px; + margin-right:0; + } + } + i.fa-search:before { + transition:.5s; + } + + .search-results{ + opacity:0; + z-index: -1; + position: absolute; + width:215px; + border:3px solid @highlight-color-1; + border-radius:5px; + box-shadow:0 5px 10px -2px rgba(0,0,0,.5); + background-color:white; + left:-1px; + top:0px; + transition:.5s; + max-height:0px; + overflow:hidden; + + @media screen and (max-width: @grid-width-bp2) { + + z-index: 1; + max-height: 500px; + width: 82%; + left: 16%; + right:auto; + + } + + .results-close { + position: absolute; + top:5px; + right:5px; + width:20px; + height:20px; + cursor:pointer; + } + + &.show { + top:70px; + opacity:1; + z-index: 1; + max-height:800px; + + @media screen and (max-width: @grid-width-bp2) { + top: 99px; + } + } + + h3{ + display:block; + color:#333; + text-align: center; + border-bottom:1px solid #eee; + font-weight: normal; + font-size:16px; + line-height:34px; + + span { + font-weight:bold; + } + } + p { + padding:10px; + font-size:14px; + } + li { + position:relative; + height:44px; + border-bottom:1px solid #ddd; + } + + span.visitor { + display:block; + position:absolute; + top:0px; + min-height:44px; + width:100%; + a { + padding:5px; + font-size:14px; + position:absolute; + top:0; + left:0 !important; + height:34px; + left:100%; + width:100%; + z-index:10; + + background: -moz-linear-gradient(top, rgba(247,247,247,0.65) 0%, rgba(232,232,232,0.39) 44%, rgba(0,0,0,0.07) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(247,247,247,0.65)), color-stop(44%,rgba(232,232,232,0.39)), color-stop(100%,rgba(0,0,0,0.07))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(247,247,247,0.65) 0%,rgba(232,232,232,0.39) 44%,rgba(0,0,0,0.07) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(247,247,247,0.65) 0%,rgba(232,232,232,0.39) 44%,rgba(0,0,0,0.07) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(247,247,247,0.65) 0%,rgba(232,232,232,0.39) 44%,rgba(0,0,0,0.07) 100%); /* IE10+ */ + background: linear-gradient(to bottom, rgba(247,247,247,0.65) 0%,rgba(232,232,232,0.39) 44%,rgba(0,0,0,0.07) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a6f7f7f7', endColorstr='#12000000',GradientType=0 ); /* IE6-9 */ + + + } + } + span.date { + display:block; + font-size:10px; + position:absolute; + bottom:7px; + width:100%; + padding-left:5px; + box-sizing:border-box; + z-index:9; + + + } + span.no-results { + line-height:34px; + padding:5px; + font-size:14px; + } + } + } + + .cb-user { + position:absolute; + top:0; + right:221px; + right:26%; + width:200px; + height:100%; + border-left:1px solid #ddd; + //Temp: quick fix for visibility on small glass + @media screen and (max-width: @grid-width-bp2) { + right:0; + border-left:none; + } + + .user-name { + font-size:12px; + color: @link-1; + padding-top:8px; + width:100%; + display:block; + position:relative; + padding-bottom:5px; + text-align: center; + background-color:white; + z-index: 2; + + @media screen and (max-width: @grid-width-bp2){ + display:none; + } + } + .user-settings { + width:100%; + margin:auto; + display:block; + position:relative; + z-index: 2; + top:-1px; + //background-color:white; + height:43px; + .icon-button:first-child { + margin-left:20px; + } + + @media screen and (max-width: @grid-width-bp2){ + margin-top:0px; + width:110px; + height:50px; + margin-left:0; + right: -30px; + top:0px; + z-index:11; + .icon-button:first-child { + margin-left:0; + } + .icon-button { + height:100%; + a { + margin-top:5px; + } + } + } + } + .settings-alerts { + opacity:0; + z-index: 1; + position: absolute; + width:196px; + border:3px solid #ddd; + border-radius:5px; + box-shadow:0 5px 10px -2px rgba(0,0,0,.5); + background-color:white; + left:-1px; + top:-60px; + transition:.5s; + .sms-count-alert { + display:none; + } + + @media screen and (max-width: @grid-width-bp2){ + top:-200px; + } + + h3{ + display:block; + color:#333; + text-align: center; + border-bottom:1px solid #eee; + padding:10px; + font-weight: normal; + } + p { + padding:10px; + font-size:14px; + } + ul { + list-style:none; + &.sms-count-alert { + border-bottom:1px solid orange; + p { + padding:6px; + } + } + } + + } + .settings-alerts.show { + opacity:1; + top:68px; + } + } + .cb-logo { + display:block; + position:relative; + width:200px; + top:10px; + z-index:101; + margin:auto; + //Swap to short Logo after space runs out + + img { + max-height:50px; + max-width:75%; + display: block; + margin: auto; + } + + @media screen and (max-width:625px) { + img {display:none;} + background-image: url('/static/img/cb-logo-small.png'); + height: 46px; + width: 100%; + background-size: 50px; + background-repeat: no-repeat; + background-position: center; + min-width: 75px; + left:23%; + } + @media screen and (max-width: @grid-width-bp2) { + top:3px; + } + } +} +//make ios7 app like +.iosheader { + display:none; +} + + + .ios { + + .cb-header .cb-logo { + background-repeat:no-repeat; + img { + display:none; + } + @media screen and (max-width: @grid-width-bp2) { + background-image: url('/static/img/cb-logo-small-white.png'); + } + @media screen and (min-width: @grid-width-bp2){ + background-image: url('/static/img/chat-white.png'); + height: 60px; + background-size: 200px; + background-position: -8px; + + } + } + .cb-user { + border:none; + .user-name { + background-color:@color-s3; + color:white; + } + } + .cb-search{ + border:none; + .search-con { + background-color:@color-s3; + } + label.search_text{ + color:white !important; + } + } + .cb-header .user-settings i,.cb-header .user-settings a { + color:white; + border:none; + } + .cb-header { + background-color: @color-s3; + // position:fixed; + + .icon-button { + border:none; + } + .fa-search { + color:white; + } + } + .cb-app { + + + @media screen and (max-width: @grid-width-bp2) { + // padding-top:50px; + } + @media screen and (min-width: @grid-width-bp2){ + // padding-top:70px; + } + } + } + .ios.ios-sa { + + .iosheader{ + display:block; + height:22px; + width:100%; + // position:fixed; + background-color:@color-s3; + z-index:1000000; + } + .cb-app .app-menu { + top:70px; + @media screen and (min-width: @grid-width-bp2){ + top:90px; + } + } + .cb-app { + // padding-top:70px; + @media screen and (min-width: @grid-width-bp2){ + // padding-top:90px; + } + } + .cb-header { + //margin-top:22px; + } + + } + +.cb-setting { + display:none; +} + +/* Navigation */ + + + + + +.cb-side-nav .fa { + float:left; + position:relative; + top:-3px; + margin-right:10px; +} + +.cb-nav { + position:relative; + transition:.5s; + + .cb-side-nav { + display:block; + width:200px; + background-color:#333333; + color:#FFFFFF; + font-size:12px; + position:absolute; + top:-200px; + height:100%; + transition:.5s; + z-index:100; + + } +} + +.cb-nav ul li { + font-size:14px; + font-weight:bold; + padding:10px 0; +} +.cb-side-nav ul li:hover { + background-color:#555; +} + +.s9-suite { + //background:url(/static/img/suite.png) no-repeat center center #307F63; + width:50px; + height:70px; + display:block; + z-index:102; + position:absolute; + left:0; + top:0; + background-color:@color-s3; + .cb-s-logo { + transition: .5s; + border: 4px solid white; + border-radius: 2px; + + padding: 0px; + width: 25px; + height: 25px; + margin: auto; + margin-top: 18px; + @media screen and (max-width: @grid-width-bp2) { + margin-top:8px; + } + + + .cb-s { + height:5px; + width:5px; + background-color:white; + margin:5px 0 0 5px; + float:left; + } + } + + @media screen and (max-width: @grid-width-bp2){ + height:50px; + } + @media screen and (min-width: @grid-width-bp0){ + width:200px; + } +} + + + + +/* Application version 2 */ + + + +#cb-nav-setting:checked + .cb-app { + left:150px; + @media screen and (min-width: @grid-width-bp0){ + left:0; + } +} + +#cb-nav-setting:checked + .cb-app .app-menu { + left:0px; +} +#cb-nav-setting:checked + .cb-app .app-chats { + + -webkit-transform: rotateY(33deg); + -webkit-transform-origin: left; + @media screen and (min-width: @grid-width-bp0){ + -webkit-transform: none; + } +} +#cb-nav-setting:checked + .cb-app .app-chats .app-gradient { + opacity:.3; + z-index: 10000; + @media screen and (min-width: @grid-width-bp0){ + display:none; + } +} +.cb-app { + position: relative; + display:block; + width:100%; + min-height:100%; + padding-top:70px; + left:0; + transition:.5s; + box-sizing:border-box; + + @media screen and (max-width: @grid-width-bp2) { + padding-top:0px; + } + .channel-msg { + opacity:0; + transition:.5s; + display:block; + margin:auto; + text-align:center; + margin-top:100px; + position:absolute; + width: 83%; + margin-left: 17%; + p{ + color:#999; + font-size:14px; + } + z-index:1; + } + + .app-menu { + width:44px; + height:100%; + display:block; + background-color:#459579; + position:fixed; + top:70px; + left:-150px; + width:200px; + z-index: 10; + -webkit-transition-timing-function: linear; + transition:.5s; + border-top:2px solid @highlight-color-1; + + @media screen and (max-width: @grid-width-bp2) { + left:-250px; + top:50px; + } + + @media screen and (min-width: @grid-width-bp0) { + left:0px; + } + + ul { + margin-left:0; + list-style:none; + + li { + color:white; + font-size:20px; + line-height:44px; + height:44px; + border-bottom:1px solid #6fb59d; + display:block; + position:relative;text-shadow: 1px 1px #666; + + a { + color:white; + text-decoration: none; + display:block; + height:100%; + width:100%; + line-height:44px; + top:0; + left:0; + position:absolute; + text-indent: 10px; + + &:hover div:before { + color:#d07f4a; + } + + div { + position:absolute; + width:44px; + height:44px; + top:0px; + right:0px; + &:before { + color:white; + top:10px; + right:5px; + position:absolute; + } + } + } + } + } + } + .app-gradient { + transition:.5s; + z-index: 1; + content:''; + position: absolute; + top:-4px; + left:0; + height:100%; + width:120%; + img { + width:100%; height:100%; + } + //background: -webkit-gradient(linear, 0 0, 100% 0, from(rgba(0,0,0,0)), to(rgba(0,0,0,0.65))); + //background: -webkit-linear-gradient(left, rgba(0,0,0,0) 0%, rgba(0,0,0,0.65) 100%); + //background: -moz-linear-gradient(left, rgba(0,0,0,0) 0%, rgba(0,0,0,0.65) 100%); + //background: -o-linear-gradient(left, rgba(0,0,0,0) 0%, rgba(0,0,0,0.65) 100%); + //background: linear-gradient(left, rgba(0,0,0,0) 0%, rgba(0,0,0,0.65) 100%); /* FF3.6+ */ /* Chrome,Safari4+ */ /* Chrome10+,Safari5.1+ */ /* Opera 11.10+ */ /* IE10+ */ /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00000000', endColorstr='#a6000000',GradientType=1 ); /* IE6-9 */ + opacity:0; + + } + .app-loading { + transition:0s; + z-index: 10000; + content:''; + position: absolute; + top:0%; + left:0; + height:100%; + min-height:1000px; + width:100%; + background:rgba(0,0,0,.20); + opacity:1; + -webkit-transform: translate3d(0, 0, 0); + + &.hide { + + -webkit-transform: translate3d(0, 0, 0); + transition:.25s ease-in-out; + opacity:0; + } + &.none { + display:none; + } + + + i { + color:white; + font-size:80px; + top:-33px; + width:80px; + height:80px; + display:block; + margin:auto; + position:relative; + } + + + .cb-logo { + margin:auto; + width:320px; + margin-top:25%; + position:relative; + display:block; + @media screen and (max-width: @grid-width-bp2) { + text-align: center; + } + + + img { + width:236px; + height:83px; + display:inline-block; + position:relative; + @media screen and (max-width: @grid-width-bp2) { + width:175px; + height:auto; + } + } + div { + display:inline-block; + position:relative;top: -27px; + left: -6px; + p { + padding:0; + margin:0; + line-height:83px; + font-size:34px; + color:white; + position:relative; + @media screen and (max-width: @grid-width-bp2) { + font-size:25px; + top:5px; + } + } + } + } + + } + .app-chats { + -webkit-transform: translate3d(0, 0, 0); + -webkit-transform: rotateY(0deg); + z-index: 9; + width:auto; + display:block; + margin-left:50px; + left:0; + -webkit-transition-timing-function: linear; + transition:.5s; + position: relative; + //min-width:930px; + min-height:100%; + + @media screen and (max-width: @grid-width-bp2) { + margin-left:0px; + } + @media screen and (min-width: @grid-width-bp0) { + margin-left:200px; + } + + .main { + position: relative; + z-index: 10; + .chats-channels { + background-color: rgb(250, 250, 250); + position:relative; + } + } + + .status { + position: relative; + font-size: 0; + display: block; + width: 30px; + height: 39px; + overflow: hidden; + margin-top: -3px; + float: left; + @media screen and (max-width: @grid-width-bp2) { + width: 100%; + height: 30px; + margin-top: -30px; + } + + &.status:before { + display:inline-block; + font-size:22px; + position:relative; + font-family: 'FontAwesome'; + //height:20px; + //width:20px; + text-shadow: 0px 2px 2px rgba(0,0,0,.15); + top:3px; + @media screen and (max-width: @grid-width-bp2) { + font-size: 20px; + top: 8px; + + + } + } + &.status.desktop:first-child { + left:10px; + } + &.phone:before { + content: "\f095"; + } + &.desktop:before { + content: "\f075"; + } + &.helped:before { + color:@status-helped; + } + &.waiting:before { + color:@status-waiting; + } + &.engaged:before { + color:@status-engaged; + } + &.new:before { + color:@status-new; + } + } + .chats-camp { + border-top:2px solid @highlight-color-1; + position:relative; + display:block; + clear:both; + overflow:hidden; + z-index: 12; + padding-bottom: 50px; + box-sizing: border-box; + height:100%; + transition:.5s linear; + max-height:1500px; + box-shadow: 0px 7px 20px rgba(0,0,0,.5); + margin-top:20px; + + &:first-child { + margin-top:0; + } + + &.collapse { + max-height: 94px; + } + + .camp-header { + font-size:26px; + font-weight: normal; + border-bottom:1px solid #ccc; + display:block; + line-height:44px; + background-color:#eee; + z-index:5; + position:relative; + //box-shadow:0 0 50px 0 rgba(0,0,0,.2); + width:100%; + height:88px; + + @media screen and (max-width: @grid-width-bp2){ + height:46px; + } + h2.multichannel { + cursor:pointer; + @media screen and (max-width: @grid-width-bp2){ + width: 48%; + font-size: 13px; + line-height: 16px; + padding-top: 8px; + } + } + h2 { + overflow:hidden; + max-height:34px; + .numberOfChats { + position: absolute; + top: 1px; + right: 0; + background-color: #eee; + height: 44px; + .number { + float: right; + height: 22px; + min-width: 18px; + background-color: white; + border-radius: 15px; + border: 1px solid #ddd; + top: 10px; + position: relative; + margin-right: 7px; + font-size: 14px; + line-height: 22px; + padding-left: 5px; + padding-right:5px; + text-align:center; + } + } + } + .camp-setting { + position:absolute; + right:0px; + top:43px; + z-index:98; + border-top:1px solid @color-s3-l; + background-color:#ddd; + margin-left: 180px; + width:80%; + width: ~"calc(100% - 181px)"; + border-left:#666; + @media screen and (min-width: @grid-width-bp2) and (max-width: 965px){ + width:80%; + } + @media screen and (max-width: @grid-width-bp2){ + top:-44px; + z-index: 4; + width:100%; + } + + //disable exmail/export for now + #nav-export, #nav-email { + display:none; + } + // 3 Bar Menu drop down + .menu { + position:absolute; + top:0; + right:0; + min-height:44px; + width:44px; + max-height:44px; + overflow:hidden; + display:block; + z-index:100; + transition:.5s; + i { + width:44px; + height:44px; + position:absolute; + right:0; + top:0; + display:block; + text-align:center; + padding-top:5px; + background-color: #eee; + } + i:before { + position:absolute; + right:2px; + top:10px; + } + ul { + list-style-type:none; + display:block; + position:relative; + top:44px; + background-color:white; + border-left:1px solid #ccc; + li { + position:relative; + display:block; + border-bottom: 1px solid #ccc; + border-right: 1px solid #ccc; + &:hover { + background-color:#efefef; + } + } + } + &:hover ul { + } + &:hover { + min-height:200px; + width:100%; + } + } + + .modal { + z-index:100; + position:absolute; + border:1px solid #bbb; + border-top:0px; + background-color:white; + width:100%; + -webkit-transform:rotateX(90deg); /* Chrome, Safari, Opera */ + transform:rotateX(90deg); /* Standard syntax */ + -webkit-transform-origin:0% 0%; + transform-origin:0% 0%; + transition: .25s ease-in-out; + //opacity:0; + left:-1px; + top:45px; + box-shadow:0 10px 15px rgba(0,0,0,0); + + @media screen and (max-width: @grid-width-bp2){ + width:240%; + left:52%; + } + + .buttons { + display:block; + padding:5px; + text-align: center; + button { + padding: 13px; + margin: 0 5px; + font-size: 16px; + width: 40%; + display: inline-block; + margin-bottom: 8px + } + } + + li { + list-style: none; + } + + p { + letter-spacing: .01em; + padding: 5px; + line-height: 17px; + font-size: 15px; + text-align: center; + } + + h2 { + padding-left: 20px; + position: relative; + text-align:center; + z-index: 9; + color: #ee5a10; + font-weight: bold; + font-size: 16px; + line-height: 21px; + padding-right: 35px; + display: block; + margin-top: 6px; + border-bottom: 1px solid #eee; + padding-bottom: 5px; + } + + .closebutton { + position:absolute; + right:0px; + top:5px; + display:block; + cursor:pointer; + z-index:10; + } + input[type='text'] { + width:80%; + margin:auto; + display:block; + border-radius:5px; + height:25px; + font-size:23px; + position:relative; + border:1px solid orange; + margin-bottom:15px; + } + + } + .modal.show { + -webkit-transform:rotateX(0deg); /* Chrome, Safari, Opera */ + transform:rotateX(0deg); /* Standard syntax */ + box-shadow:0 5px 10px rgba(0,0,0,.25); + //opacity:1; + } + + .icon-button { + width:32%; + z-index:99; + position:relative; + border-right:1px solid #ccc; + + i:before { + color:#666; + } + + } + .icon-button:last-child { + border-right:none; + } + + .icon-button.selected { + box-shadow: 0 0 5px rgba(0,0,0,.5); + background-color:#ccc; + } + + } + + + h2 { + font-weight: normal; + padding-left:10px; + } + + i.heading-icon { + float:right; + position:relative; + top:10px; + margin-left:10px; + } + + } + } + .chats-list-back { + position:absolute; + left:0; + top:0; + display:block; + width:20%; + max-width:180px; + border-right:1px solid #ddd; + margin-right:-1px; + z-index:99; + } + .chats-list { + height:100%; + position:relative; + display:block; + width:20%; + background-color:#fff; + float:left; + //overflow:hidden; + margin-left:0; + max-width:180px; + border-right:1px solid #ddd; + margin-right:-1px; + white-space: nowrap; + text-overflow:ellipsis; + top: -46px; + z-index: 100; + border-top: 1px solid #53cb99; + min-height:400px; + padding-bottom:44px; + margin-bottom:-46px; + + &:before { + content:''; + display:block; + position:absolute; + top:0; + left:0; + width:100%; + max-width:180px; + background-color:white; + border-right:1px solid #ddd; + margin-right:-1px; + height:10000px; + + } + .chat-list-check { + float:right; + margin-right:10px; + margin-top:-113px; + height:20px; + width:20px; + //position:relative; + z-index:1; + } + .chat-list-check:checked:after { + display:block; + position:absolute; + content:''; + top:0; + left:0; + z-index:1; + width:100%; + height:100%; + background-color:rgba(0,0,0,.1); + } + ul { + margin-left:0; + position:relative; + z-index:2; + } + li { + line-height:44px; + padding-left:10px; + list-style:none; + font-weight: normal; + position:relative; + height:44px; + overflow:hidden; + z-index:2; + + &.empty { + display:none; + } + + label { + position:absolute; + left:0; + top:0; + height:100%; + width:100%; + z-index:3; + text-overflow:ellipsis; + } + + &.user, &.user a { + border-bottom:1px solid #ddd; + font-size:14px; + text-decoration: none !important; + @media screen and (min-width: @grid-width-bp2) and (max-width: 820px){ + font-size:11px; + } + + } + } + + h1 { + display:block; + background-color:#666; + color:white; + padding-left:10px; + line-height:44px; + font-size:22px; + font-weight:normal; + border-bottom: 1px solid #aaa; + height:44px; + } + + @media screen and (max-width: @grid-width-bp2) { + + border-top: none; + top:0px; + width:16%; + background-color:white; + background: rgb(255,255,255); /* Old browsers */ + background: rgb(232,232,232); /* Old browsers */ + background: -moz-linear-gradient(left, rgba(232,232,232,1) 0%, rgba(255,255,255,1) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(232,232,232,1)), color-stop(100%,rgba(255,255,255,1))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(left, rgba(232,232,232,1) 0%,rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(left, rgba(232,232,232,1) 0%,rgba(255,255,255,1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(left, rgba(232,232,232,1) 0%,rgba(255,255,255,1) 100%); /* IE10+ */ + background: linear-gradient(to right, rgba(232,232,232,1) 0%,rgba(255,255,255,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e8e8e8', endColorstr='#ffffff',GradientType=1 ); /* IE6-9 */ + + li { + line-height:21px; + padding-top:28px; + padding-left:0px; + list-style:none; + font-weight: normal; + position:relative; + height:16px; + overflow:hidden; + z-index:2; + + label { + position:absolute; + left:0; + top:0; + height:100%; + width:100%; + z-index:3; + text-overflow:ellipsis; + } + + &.user, &.user a { + border-bottom:1px solid #ddd; + font-size:8px; + text-decoration: none !important; + text-align: center; + + } + &.user { + margin-left:-1px; + } + } + + h1 { + display:block; + background-color:#666; + color:white; + padding-left:10px; + line-height:44px; + font-size:10px; + font-weight:normal; + border-bottom: 1px solid #aaa; + height:44px; + } + } + } + .chats-conv { + display:block; + float:left; + width:80%; + z-index:2; + height:90%; + overflow:auto; + + display: inline-flex; + flex-flow: row wrap; + @media screen and (max-width: @grid-width-bp2) { + width:84%; + } + + .conv-con { + display:block; + border:0px solid #ccc; + width:30%; + margin:0 1% 25px 1%; + height:300px; + position:relative; + left:10px; + background-color:#fff; + padding-bottom:50px; + float:left; + transition:.5s; + -webkit-transform: translate3d(0, 0, 0); + top:-600px; + margin-bottom:-1000px; + border-radius:0 0 5px 5px; + overflow:hidden; + opacity:0; + z-index:1; + order:999999; + @media screen and (min-width:@grid-width-bp2) and (max-width: @grid-width-bp1) { + width:45%; + } + + @media screen and (max-width: @grid-width-bp2) { + width: 100%; + margin-left:0; + margin-right:0; + left:1px; + } + + .location { + position: absolute; + top: 28px; + left: 8px; + font-size: 12px; + color: #fff; + display:block; + &.hide { + display:none; + } + } + + .cb-actions { + width:100%; + height:22px; + position:absolute; + top:-23px; + z-index:5; + ul li { + float:left; + font-size:14px; + } + .email, .export { + display:none; + } + a { + right: 0; + position: absolute; + font-size: 12px; + top: 27px; + text-align: center; + width: 59px; + color: white; + text-decoration: none; + height:40px; + } + i { + color:white; + position:relative; + left:5px; + font-size:15px; + margin-top:3px; + } + } + + &.checked { + opacity:1; + top:0; + margin-bottom:25px; + z-index: 2; + + //Commenting out as it's causing issues on ipad. + //@media screen and (min-width: @grid-width-bp1) { + // -webkit-animation: chat-load .5s ease-in-out; + // -webkit-animation-fill-mode: forwards; + //} + + + } + + &.dragging { + z-index: 10001; + transition:0; + -webkit-animation: none; + //-webkit-transform: scale(.75); + -webkit-transform-origin:top; + animation: none; + //transform: scale(.75); + transform-origin:top; + opacity:.5; + } + + h3 { + cursor:pointer; + height:40px; + padding-left:5px; + padding-top:5px; + font-size:20px; + line-height:22px; + color:white; + font-weight:normal; + text-shadow: 1px 1px #777; + max-width: 76%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .cb-user-name { + margin-bottom:0px; + z-index:4; + + h3 { + + } + &:before { + position:absolute; + left:0; + top:0; + height:45px; + width:10px; + content:''; + display:none; + } + //possibly deprecated + &.helped:before { + background-color:@status-helped; + } + &.waiting:before { + background-color:@status-waiting; + } + &.engaged:before { + background-color:@status-engaged; + } + &.new:before { + background-color:@status-new; + } + &.helped { + background-color:@status-helped; + } + &.waiting { + background-color:@status-waiting; + } + &.engaged { + background-color:@status-engaged; + } + &.new { + background-color:@status-new; + } + + .cb-user-input { + position:absolute; + top: 4px; + left: -4px; + height: 24px; + width:70%; + } + + input { + position:relative; + + left:0; + bottom:auto; + border:0; + height:30px; + font-size:16px; + //font-weight:bold; + margin-left:10px; + margin-bottom:30px; + top:8px; + } + } + + .cb-edit-user { + top:-3px; + right:-4px; + position:absolute; + font-size:20px !important; + } + + .cb-location { + font-size:14px; + color:#eee; + position:absolute; + top:36px; + padding-left:10px; + white-space: nowrap; + text-overflow:ellipsis; + max-width:94%; + overflow:hidden; + + i { + float: left; + position: relative; + top: -3px; + text-shadow:1px 1px #666; + font-size:23px; + margin-right:-5px; + cursor: pointer; + color:#fff; + } + } + + @-webkit-keyframes chat-load{ + 0%{ + -webkit-transform:scale(.8); + opacity:.2; + } + 30%{ + -webkit-transform:scale(.8); + + } + 100%{ + -webkit-transform:scale(1); + opacity:1; + } + } + } + } + } + + + +} + + + + + + + +/* Maps Modal Styles */ + +.app-maps { + opacity:0; + z-index:-1; + border:3px solid @highlight-color-1; + border-radius:5px; + background-color:white; + position:absolute; + margin-left:50%; + left:-160px; + top:100px; + .maps-close { + position: absolute; + top:5px; + right:5px; + width:20px; + height:20px; + cursor:pointer; + } + + .maps-header { + h3 { + text-align: center; + display:block; + font-weight:normal; + font-size:15px; + background-color:#ddd; + line-height:34px; + height:34px; + border-bottom:1px solid @highlight-color-1; + } + input { + width:80%; + margin-left:5%; + display:block; + height:30px; + border:3px solid #ddd; + border-radius:5px; + margin-bottom:5px; + } + i { + float:right; + margin-top:-35px; + } + } + .maps-google { + display:block; + height:300px; + width:320px; + } + &.show { + opacity:1; + z-index: 100; + } +} + + + + + + + + + + + + + + + + + .controls { + margin-top: 16px; + border: 1px solid transparent; + border-radius: 2px 0 0 2px; + box-sizing: border-box; + -moz-box-sizing: border-box; + height: 32px; + outline: none; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + } + + #pac-input { + background-color: #fff; + padding: 0 11px 0 13px; + width: 400px; + font-family: Roboto; + font-size: 15px; + font-weight: 300; + text-overflow: ellipsis; + } + + #pac-input:focus { + border-color: #4d90fe; + margin-left: -1px; + padding-left: 14px; /* Regular padding-left + 1. */ + width: 401px; + } + + .pac-container { + font-family: Roboto; + } + + #type-selector { + color: #fff; + background-color: #4d90fe; + padding: 5px 11px 0px 11px; + } + + #type-selector label { + font-family: Roboto; + font-size: 13px; + font-weight: 300; + } + + +//Chat Interface +.cb-chat-area { + height: 255px; + overflow-y: scroll; + display:block; + + + .cb-chat-messages { + z-index:3; + position:relative; + + li[id*='view-entire-conversation-'] { + border-radius: 0 0 15px 15px; + margin-top: -6px; + width: 100%; + text-align: center; + background-color:white; + border:2px solid #D7EBFF; + border-top:none; + padding:0; + p { + position:relative; + padding:0; + min-height:44px; + } + a { + font-size:14px; + text-align: center; + position: absolute; + width: 100%; + height: 100%; + display: block; + line-height:44px; + } + } + } + .cb-msg { + border-radius:15px; + padding:7px; + position:relative; + min-width:5%; + list-style:none; + margin:10px; + clear:both; + font-weight:normal; + max-width:85%; + top:5px; + p { + font-size:14px; + word-wrap: break-word; + } + + .cb-timestamp { + font-style:italic; + font-size:9px; + color:#CCCCCC; + position:absolute; + top:-13px; + z-index:4; + white-space:nowrap; + + } + + &.to { + background-color:#D7EBFF; + float:right; + + .cb-timestamp { + right:0; + } + } + + &.from { + + background-color:#FFEFE8; + float:left; + + } + .cb-edit-label { + position: absolute; + top: 10px; + right: 10px; + display:block; + } + } + + .cb-split { + font-size:10px; + color:#ccc; + text-align:center; + display:block; + position:relative; + width:100%; + background-color:#fff; + float:left; + margin-bottom:10px; + border-bottom:1px solid #ddd; + + } + .cb-chat-footer { + width:100%; + position:absolute; + height:50px; + bottom:0px; + border-top:1px solid #ddd; + z-index:4; + display:block; + + .cb-chatbox { + display:block; + float:left; + width:63%; + position:relative; + height:40px; + background-color:#D7EBFF; + border:0; + padding:5px 1%; + font-family: 'Droid Sans', sans-serif; + font-size:13px; + @media screen and (max-width: @grid-width-bp2) { + width:56%; + } + } + + .cb-chatbox-submit { + display:block; + float:left; + height:37px; + color:white; + font-weight:normal; + font-size:18px; + text-align:center; + padding-top:13px; + background-color:#0099FF; + width:25%; + cursor:pointer; + border-radius:0 0 3px 0; + } + .cb-chatbox-quick{ + display:block; + float:left; + height:35px; + color:white; + font-weight:normal; + text-align:center; + padding-top:15px; + background-color:#06C; + width:10%; + cursor:pointer; + border-radius:0 0 0 3px; + position: relative; + z-index: 8; + @media screen and (max-width: @grid-width-bp2) { + width:16%; + } + + &:hover { + + background-color:#0099FF ; + ul { + } + } + + ul { + position: absolute; + bottom:50px; + width:750%; + display:none; + background-color:#333; + background-color:rgba(50,50,50,.8); + border-radius:0px 3px 0 0; + z-index:10000; + @media screen and (max-width: @grid-width-bp2) { + width:618%; + } + + &.show { + display:block !important; + } + + li { + list-style-type:none; + margin-top:0; + border-bottom:1px solid white; + border-color:rgba(255,255,255,.75); + position:relative; + display:block; + + .close { + display:block; + text-align: center; + position: relative; + font-weight: normal; + font-size: 14px; + padding: 2px; + color: #eee; + background-color: rgba(0,0,0,.9); + @media screen and (max-width: @grid-width-bp2) { + height:40px; + line-height:40px; + } + } + .qr-label { + position: relative; + top:2px; + overflow:hidden; + white-space: nowrap; + } + .qr-text { + + } + + h3 { + font-size:16px !important; + padding-top:2px !important; + height:25px !important; + padding-top:0 !important; + text-align: left; + } + p { + text-align:left; + font-size:14px; + font-weight:normal; + color:white; + display:none; + line-height:17px; + } + &:hover p { + display:block; + } + &:hover div.qr-label { + display:none; + } + } + } + + &:before { + font-size:21px; + display:block; + position: relative; + left: 4px; + + } + + } + } + +} + + + + + +/* Cb User Settings */ +#cb-user-settings:checked + .cb-user-settings-menu { + opacity:1; +} + +#cb-user-settings-2:checked + .cb-user-settings-menu { + opacity:1; +} +#cb-user-settings-3:checked + .cb-user-settings-menu { + opacity:1; +} +.cb-user-settings-menu { + list-style:none; + position:absolute; + display:block; + top:30px; + right:0px; + background-color:#efefef; + border: 1px solid #072; + border-radius:15px 0 15px 15px; + z-index:5; + opacity:.0; + transition: opacity .25s ease-out; + + li { + padding:5px; + font-size:14px; + } +} + + +/* Channel Footer */ +.channel-footer { + display:block; + position:absolute; + background-color:#aaa; + width:100%; + height:50px; + bottom:0px; + color:white; + z-index:200; + .visitor { + display:none !important; //supress until we work it out + cursor:pointer; + display:inline-block; + min-width:181px; + background-color:#999; + @media screen and (max-width: @grid-width-bp2) { + min-width:160px; + } + + + i { + float:left; + color:#eee; + line-height:50px; + padding-left:10px; + height:50px; + + } + .information{ + z-index: 5; + .number { + display:inline-block; + line-height:50px; + } + + p { + display:inline-block; + position:relative; + color:white; + font-size:15px; + line-height:50px; + padding:0 5px 0 0px; + } + &:hover .menu { + bottom:94px; + opacity:1; + bottom:50px; + } + .menu { + + z-index: 4; + position:absolute; + transition:.5s; + bottom:-40px; + opacity:0; + + ul { + list-style-type:none; + display:block; + position:relative; + background-color:white; + border-left:1px solid #ccc; + min-width:180px; + li { + color:@link-1; + font-size:14px; + line-height:44px; + font-weight:normal; + position:relative; + display:block; + border-top: 1px solid #ccc; + border-right: 1px solid #ccc; + padding-left:10px; + padding-right:10px; + &:hover { + background-color:#efefef; + } + input[type=checkbox]{ + float:right; + margin-right:10px; + margin-top:15px; + } + a { + font-size:14px; + text-decoration: none; + } + } + } + } + &:hover .menu { + + } + } + } + .active-switch { + display:inline-block; + float:right; + max-width:200px; + position:relative; + margin-right:25px; + + label { + display:inline-block; + position: absolute; + left: -50px; + top: 0; + line-height:50px; + + } + + input[type=checkbox] + label:before { + display:block; + transition:.25s; + } + input[type=checkbox]:checked + label:before { + content:'Offline'; + } + input[type=checkbox] + label:before { + display:block; + content:'Online'; + } + + } +} + + +/* effects */ + +.icon-button { + float:left; + margin-right:5px; + border-right:1px solid #ddd; + padding-right:5px; + a { font-weight: normal; + text-decoration: none; + font-size:13px; + display:block; + height:44px; + min-width: 44px; + text-align:center; + i { + float:none; + &:before { + padding-right:0; + position: relative; + top:3px; + } + &:hover:before { + color: @highlight-color-1; + } + } + } + &:last-child { + padding-right:0; + margin-right:0; + border-right:none; + } + .fa-label { + font-size:12px; + line-height:13px; + margin-top:4px; + + font-family: -apple-system-font,'Droid Sans', sans-serif; + } +} + +.fa { + color:#999; + font-size:25px; + display:block; + opacity:.8; +} + +.tooltip { + border-radius:15px; + padding:10px; + background-color:#C1FFC1; + border:1px solid #00A452; + +} + +.main .content { + a { + text-decoration: none; + font-size:16px; + } + + + .notes { + width:80%; + left:10%; + position:relative; + height:100px; + margin-top:15px; + + } + .notes + input { + display:block; + width:30%; + margin-left:35% !important; + position:relative; + float:none !important; + margin-bottom:15px; + } + table { + padding:5px; + + &.list { + width:100%; + display:table; + + td { + width:auto; + } + } + &.archive tr:nth-child(even) td { + background-color:#efefef; + } + &.archive { + padding:0; + td { + padding:2px; + } + } + th.archive { + width:auto; + position: relative; + background-color: #fff; + border-bottom: 2px solid #bbb; + background-color: #ddd; + min-height: 44px; + height:44px; + } + td.actions { + text-align: center; + font-size:14px; + padding:2px; + min-width:138px !important; + button { + font-size:14px; + background-color:#ddd; + @media screen and (max-width: @grid-width-bp2) { + margin-left:5px; + font-size:12px; + } + } + a{ + padding: 5px; + border-radius: 3px; + border: 1px solid #bbb; + cursor: pointer; + background-color:#ddd; + color:black; + font-weight:normal; + font-size:14px; + margin:5px 15px; + @media screen and (max-width: @grid-width-bp2) { + margin:0px; + font-size:12px; + } + } + } + .load-more { + width: 75%; + margin-left:auto !important; + margin: auto; + display: block; + position: relative; + float: none !important; + margin-top: 10px; + margin-bottom: 10px; + background-color:@color-s3-l; + color:white; + } + } + h1 { + padding-top:15px; + padding-bottom:10px; + + margin-left:3%; + display:inline-block; + font-size:20px; + @media screen and (max-width: @grid-width-bp2) { + margin:2%; + max-width:95%; + padding-top:5px; + } + } + h1 a { + color:@color-s1; + font-size:20px; + } + + h2 { + padding-top:15px; + padding-bottom:10px; + margin-left:3%; + display:inline-block; + font-size:18px; + color:#666; + @media screen and (max-width: @grid-width-bp2) { + margin:2%; + max-width:95%; + padding-top:5px; + } + } + h2 a { + color:#666; + font-size:18px; + } + .notice { + display: block; + margin: 0; + padding: 10px; + color: white; + line-height:1.3em; + font-weight:normal; + position:relative; + + background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 26%, rgba(0,0,0,0.18) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0)), color-stop(26%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0.18))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 26%,rgba(0,0,0,0.18) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 26%,rgba(0,0,0,0.18) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 26%,rgba(0,0,0,0.18) 100%); /* IE10+ */ + background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 26%,rgba(0,0,0,0.18) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00000000', endColorstr='#2e000000',GradientType=0 ); /* IE6-9 */ + + + &.red { + background-color:#FF6E78; + } + &.yellow { + background-color:#FFDE71; + color:#666; + } + &.green { + background-color:@color-s3-l; + } + } + .chart { + display:block; + height:250px; + position:relative; + padding-top:70px; + border-bottom:2px solid #ccc; + margin-bottom:15px; + li.header { + display:block; + width:100%; + text-align: center; + height:30px; + position:absolute; + top:0; + + } + li { + display:inline-block; + height:100%; + width:40px; + margin-right:15px; + margin-left:15px; + position:relative; + label { + position:absolute; + bottom:-40px; + width:50px; + text-align: center; + font-size:15px; + line-height:17px; + width:100%; + font-size:12px; + } + } + .bar { + width:100%; + background-color:#666; + min-height:10px; + position:absolute; + bottom:0; + } + } + .timepicker { + width: 75px !important; + min-width: 75px !important; + & + .timepicker-list { + display:inline-block; + margin-left:10px; + } + } + .row { + margin:5px 10px; + @media screen and (max-width: @grid-width-bp2) { + margin:0; + } + + .half { + width:49%; + display:inline-block; + vertical-align: top; + @media screen and (max-width: @grid-width-bp2) { + width:100%; + } + + } + } + form { + background-color:white; + border:2px solid orange; + margin:25px; + margin-top:5px; + display:block; + position:relative; + padding:0px; + line-height:25px; + border-radius:0 0 10px 0; + @media screen and (max-width: @grid-width-bp2) { + margin:2%; + table { + border-spacing: 0; + td { + border-bottom:1px solid #ccc; + vertical-align: top; + } + } + } + p { + font-size:14px; + line-height:17px; + @media screen and (max-width: @grid-width-bp2) { + line-height:16px; + } + } + td { + position:relative; + height:50px; + padding-right:15px; + vertical-align:top; + &:first-child { + padding-top:5px; + } + } + label { + font-size:17px; + padding:2px; + display:inline-block; + margin-top:5px; + + @media screen and (max-width: @grid-width-bp2) { + //display:none; + } + } + input[type="text"],input[type="password"] { + height:25px; + font-size:16px; + line-height:25px; + color:#333; + border:1px solid #999; + padding:5px; + border-radius:5px; + min-width:300px; + box-shadow:inset 0 0 15px rgba(0,0,0,.05); + max-width:100%; + margin-top:5px; + + @media screen and (min-width: @grid-width-bp2) and (max-width: @grid-width-bp1) { + width:80%; + min-width:200px; + } + @media screen and (max-width: @grid-width-bp2) { + min-width:150px; + width:95%; + } + } + textarea { + min-height:100px; + width:100%; + border-radius:5px; + border:1px solid #999; + box-shadow:inset 0 0 15px rgba(0,0,0,.05); + } + @media screen and (max-width: @grid-width-bp2) { + input[type="checkbox"] { + -ms-transform: scale(2); /* IE */ + -moz-transform: scale(2); /* FF */ + -webkit-transform: scale(2); /* Safari and Chrome */ + -o-transform: scale(2); /* Opera */ + padding: 10px; + display: block; + margin-left: 10px; + margin-top:20px; + } + } + input[type="submit"],input[type="button"], button { + height:50px; + font-size:16px; + text-shadow:1px 1px #333; + line-height:25px; + border:1px solid #999; + padding:5px; + border-radius:5px; + position:relative; + display:inline-block; + min-width:150px; + cursor:pointer; + background: #ffc578; /* Old browsers */ + background: -moz-linear-gradient(top, #ffc578 0%, #fb9d23 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffc578), color-stop(100%,#fb9d23)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #ffc578 0%,#fb9d23 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #ffc578 0%,#fb9d23 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #ffc578 0%,#fb9d23 100%); /* IE10+ */ + background: linear-gradient(to bottom, #ffc578 0%,#fb9d23 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffc578', endColorstr='#fb9d23',GradientType=0 ); /* IE6-9 */ + color:white; + margin-top:15px; + margin-bottom:15px; + @media screen and (max-width: @grid-width-bp2) { + height:44px; + min-width:44%; + margin-top:15px; + margin-bottom:5px; + } + } + } + .list { + overflow:hidden; + margin-left:3%; + max-width:93%; + position:relative; + display:block; + background-color:white; + border:2px solid #999; + border-radius:0 0 10px 0px; + margin-top:5px; + .info { + padding-left:36%; + min-height:15px; + } + .label { + display:block; + position:absolute; + width:33%; + border-right:1px solid #ddd; + font-size:14px; + font-weight:bold; + left:0; + top:0; + height:80%; + padding-top:2%; + padding-left:2%; + padding-bottom:2%; + } + @media screen and (max-width: @grid-width-bp2) { + margin-left:2%; + max-width:95%; + } + + .actions { + float:none; + button { + float:none; + } + } + + + li { + position:relative; + display:block; + border-top:1px solid #bbb; + padding:10px; + + } + li:first-child { + border-top:none; + } + input[type="submit"],input[type="button"],button { + padding:5px; + margin-left:10px; + border-radius:3px; + border:1px solid #bbb; + cursor:pointer; + float:right; + } + + .cb-msg { + position:relative; + padding:5px 30px; + + .cb-timestamp { + font-size:14px; + color:#bbb; + } + .source { + display:block; + background-color:#D7EBFF; + + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + position:absolute; + left:0; + top:0; + height:100%; + width:25px; + text-align: right; + + p { + writing-mode: tb-rl; + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + font-size:14px; + text-align: right; + position:relative; + top:5px; + } + + &.from { + left:auto; + right:0; + background-color:#FFEFE8; + writing-mode: tb-lr; + } + + } + } + + } + &> .actions { + display:block; + margin-right:3%; + position:relative; + height:44px; + + @media screen and (max-width: @grid-width-bp2) { + margin-right:2%; + } + input[type="submit"],input[type="button"], button { + float:right; + height:44px; + font-size:16px; + text-shadow:1px 1px #333; + line-height:25px; + border:1px solid #999; + padding:5px; + border-radius:5px; + position:relative; + display:inline-block; + min-width:150px; + cursor:pointer; + background: #ffc578; /* Old browsers */ + background: -moz-linear-gradient(top, #ffc578 0%, #fb9d23 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffc578), color-stop(100%,#fb9d23)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #ffc578 0%,#fb9d23 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #ffc578 0%,#fb9d23 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #ffc578 0%,#fb9d23 100%); /* IE10+ */ + background: linear-gradient(to bottom, #ffc578 0%,#fb9d23 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffc578', endColorstr='#fb9d23',GradientType=0 ); /* IE6-9 */ + color:white; + margin-bottom:15px; + @media screen and (max-width: @grid-width-bp2) { + height:44px; + } + } + } + form .menu, .list .menu { + display:block; + position:relative; + background-color:white; + width:100%; + border-bottom:2px solid #bbb; + background-color:#ddd; + min-height:44px; + ul { + float:right; + list-style: none; + li { + display:inline-block; + border-left:2px solid #eee; + padding:5px 10px; + line-height:34px; + max-width:150px; + a { + font-size:14px; + } + } + } + } + .squares { + + li { + list-style:none; + width:150px; + height:100px; + border-radius:10px; + border:2px solid orange; + float:left; + margin-left:25px; + margin-top:10px; + position:relative; + display:block; + background: #fff; /* Old browsers */ + + background: -moz-linear-gradient(top, #ffffff 0%, #f2f2f2 50%, #e2e2e2 51%, #fefefe 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(50%,#f2f2f2), color-stop(51%,#e2e2e2), color-stop(100%,#fefefe)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #ffffff 0%,#f2f2f2 50%,#e2e2e2 51%,#fefefe 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #ffffff 0%,#f2f2f2 50%,#e2e2e2 51%,#fefefe 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #ffffff 0%,#f2f2f2 50%,#e2e2e2 51%,#fefefe 100%); /* IE10+ */ + background: linear-gradient(to bottom, #ffffff 0%,#f2f2f2 50%,#e2e2e2 51%,#fefefe 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#fefefe',GradientType=0 ); /* IE6-9 */ + + + @media screen and (max-width: @grid-width-bp2) { + width:44%; + margin-top:10px; + margin-left:10px + } + + a { + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + display:block; + text-decoration: none; + text-align: center; + } + i { + + margin-top:5px; + } + i:before { + font-size:40px; + } + a:hover i:before{ + color:orange; + } + span { + position:relative; + margin-top:15px; + display:block; + } + } + } + + +} + +// Utility Styles +.show-on-small { + display:none !important; +} +@media screen and (max-width: @grid-width-bp2) { + .hide-on-small { + display:none; + } + .show-on-small { + display:block !important; + } +} \ No newline at end of file diff --git a/app/styles/vendor.less b/app/styles/vendor.less deleted file mode 100644 index 0593697..0000000 --- a/app/styles/vendor.less +++ /dev/null @@ -1 +0,0 @@ -// Nothing yet diff --git a/gulp/build.js b/gulp/build.js index c90d13e..42aae2b 100644 --- a/gulp/build.js +++ b/gulp/build.js @@ -28,7 +28,7 @@ gulp.task('scripts', function () { }); gulp.task('partials', function () { - return gulp.src('app/partials/**/*.html') + return gulp.src('app/{partials,scripts/components}/**/*.html') .pipe($.minifyHtml({ empty: true, spare: true, diff --git a/gulp/server.js b/gulp/server.js index 433c03a..57688c3 100644 --- a/gulp/server.js +++ b/gulp/server.js @@ -45,7 +45,7 @@ gulp.task('serve', ['watch'], function () { 'app/styles/**/*.css', '.tmp/styles/**/*.css', 'app/scripts/**/*.js', - 'app/partials/**/*.html', + 'app/{partials,scripts/components}/**/*.html', 'app/images/**/*' ]); });