Blux Logo
Loading BLUX...
"; analytics += ''; return analytics; }; Page.prototype.getMetaTags = function() { var app = this.app, thisPage = this, tags = ''; if (this.description) { tags += '
\n'; } if (thisPage.internal.substr(0, 9) === '/pages/0/') { if (app.site.settings.integrations) { if (app.site.settings.integrations.googleWebmasterVerifySite) { if (app.site.settings.integrations.googleWebmasterVerifySite.metaTag) { tags += '
\n'; } } if (app.site.settings.integrations.bingWebmasterVerifySite) { if (app.site.settings.integrations.bingWebmasterVerifySite.metaTag) { tags += '
\n'; } } if (app.site.settings.integrations.pinterestVerifySite) { if (app.site.settings.integrations.pinterestVerifySite.metaTag) { tags += '
\n'; } } if (app.site.settings.integrations.facebookVerifySite) { if (app.site.settings.integrations.facebookVerifySite.metaTag) { tags += '
\n'; } } } } tags += '
\n'; if (app.site.i18n) { Object.keys(app.site.i18n).forEach(function(i18nID) { var trans = app.site.i18n[i18nID], domain = (trans.domain || '').trim(), folder = (trans.language_code || i18nID).urlSafe(); if (trans && domain && folder) { tags += '
\n'; } }); } return tags; }; Page.prototype.getOpenGraphTags = function() { function addMetaTag(property, content) { if (!content) { content = ''; } return '
'; } var meta = ''; meta += addMetaTag('og:title', this.title); meta += addMetaTag('og:description', this.description); meta += addMetaTag('og:site_name', this.app.site.name); meta += addMetaTag('og:url', this.href); if (this.primaryMedia) { meta += addMetaTag('twitter:card', 'summary_large_image'); meta += addMetaTag('og:image', this.primaryMedia); } return meta; }; App.prototype.siteMap = function(config, cache) { // if you update this functions logic you need to update it Recommendations.js var app = this; if (!config) { config = {}; } if (cache) { var cacheKey = 'd'; if (config.blocks) { cacheKey += 'b'; } if (config.public) { cacheKey += 'p'; } if (app.siteMapCached) { if (app.siteMapCached[cacheKey]) { return app.siteMapCached[cacheKey]; } } } var siteMap = [], content = app.site.content; app.pageURLS = {}; app.urlMap = {}; Object.keys(content).forEach(function(section) { if (content[section].length && section !== '__templates') { content[section].forEach(function(page, p) { if (page && typeof page === 'object' && Object.keys(page).length > 1) { var url = app.getPageURL(section, app.site.content[section][p], p, false, true), internal = app.getPageURL(section, app.site.content[section][p], p, true, false), l = p > 0 ? 1 : 0, title = content[section][p].title + '', mapObject = { title: DOM().new('span').html(title).text(), url: url, section: section, l: l }; if (!config.public) { mapObject.p = p; mapObject.internal = internal; mapObject.disable = page.disable || false; mapObject.hidden = page.hidden || false; if (p === 0) { l = 0; if (section === 'pages') { mapObject.title += ' (Home Page)'; } else { mapObject.title += ' (Index)'; } } } if ((config.public && !page.disable) || !config.public) { siteMap.push(mapObject); } if (config.blocks) { if (app.site.content[section][p].items) { app.site.content[section][p].items.forEach(function(block, b) { var subMapObject = { title: DOM().new('span').html(content[section][p].items[b].title || '').text() + '', url: url + '#' + b, l: 2 }; if (!config.public) { subMapObject.internal = internal + '/' + b; } siteMap.push(subMapObject); }); } } } else { delete content[section][p]; } }); } }); if (cache) { if (!app.siteMapCached) { app.siteMapCached = {}; } app.siteMapCached[cacheKey] = siteMap; setTimeout(function() { delete app.siteMapCached[cacheKey]; if (Object.keys(app.siteMapCached).length < 1) { delete app.siteMapCached; } }, 1000); } return siteMap; }; App.prototype.getPageURL = function(section, page, p, internal, fixDuplicateURLS) { var app = this, url = ''; if (page && typeof page === 'object' && Object.keys(page).length > 1) { if (!app.pageURLS) { app.pageURLS = {}; } if (p === 0 && !internal) { url = (section !== 'pages') ? '/' + section : '/'; } else { if (section !== 'pages' || internal) { url = '/' + section; } if (internal) { url += '/' + p; } if (p > 0 || internal) { if (page.url) { url += '/' + page.url.replace(/\//g, ''); } else if (page.title) { url += '/' + page.title.toString().urlSafe(); } else { url += '/' + p; } } if (!internal) { if (app.pageURLS[url] && fixDuplicateURLS) { var baseURL = url + ''; var ticker = 2; var checkURL = baseURL + '-' + ticker; while (app.pageURLS[checkURL]) { ticker++; checkURL = baseURL + '-' + ticker; } url = checkURL + ''; var update = { url: url }; if(p && app.site.content[section] && typeof(app.site.content[section][p]) === 'object' && Object.keys(app.site.content[section][p]).length > 1){ app.siteUpdate(['content', section, p], update); } } app.pageURLS[url] = true; } } if (!internal) { app.urlMap[section + p] = url; } } else { console.error('tried to generate a url for a bad page'); console.log('page', page); } return url; }; App.prototype.getPageURLSingle = function(section, p) { var app = this; if (app.urlMap) { if (app.urlMap[section + p]) { return app.urlMap[section + p]; } } return ''; }; App.prototype.pathToURL = function(path) { var app = this, url = ''; if (Array.isArray(path)) { if (path[0] === 'content' && path.length > 1) { var page = app.site.content[path[1]][path[2]]; if (page) { url = '/content' + app.getPageURL(path[1], page, path[2], true); if (path.length > 4) { for (var i = 4; i < path.length; i++) { if (i % 2 === 0) { url += '/' + path[i]; } } } } } else if(path[0] === 'feeds'){ url = '/feeds/'+(path[1] || ''); if(path[3]){ url += '/' + path[3]; } } } return url; }; App.prototype.pathToInfo = function(path) { var app = this, page; if (app.site.content[path[1]]) { page = app.site.content[path[1]][path[2]]; if (page && typeof page === 'object') { var title = page.title || '(no title set)'; var pageTitle = title + ''; var url = '/content' + app.getPageURL(path[1], page, path[2], true); if (path.length > 4) { for (var i = 4; i < path.length; i++) { if (i % 2 === 0) { url += '/' + path[i]; title += '/' + path[i]; } } } return { pageTitle: pageTitle, pathTitle: title, url: url }; } else { return false; } } }; App.prototype.siteURL = function(noDomains) { var app = this, scheme = 'http://', url = scheme + app.site.id + '.blux.com'; if (app.site.settings && app.site.settings.hosting && app.site.settings.hosting.ssl) { scheme = 'https://'; } if (window.location.hostname === 'localhost') { url = 'http://' + app.site.id + '.localhost:8071'; } else { if (app.site.domain && !noDomains) { url = scheme + app.site.domain; } } return url; }; App.prototype.stagingURL = function() { return window.location.hostname === 'localhost' ? 'http://' + this.site.id + '-staging.localhost:8071' : 'https://' + this.site.id + '-staging.blux.com'; }; App.prototype.tagHints = function() { var app = this, hintList = [], k; Object.keys(app.site.content).forEach(function(sec) { if (Array.isArray(app.site.content[sec])) { app.site.content[sec].forEach(function(page) { if (page.tags) { for (k in page.tags) { if (hintList.indexOf(page.tags[k]) < 0 && page.tags[k]) { hintList.push(page.tags[k]); } } } }); } }); Object.keys(app.site.feeds).forEach(function(feed) { if (Array.isArray(app.site.feeds[feed].items)) { app.site.feeds[feed].items.forEach(function(feedItem) { if (feedItem.tags) { for (k in feedItem.tags) { if (hintList.indexOf(feedItem.tags[k]) < 0 && feedItem.tags[k]) { hintList.push(feedItem.tags[k]); } } } }); } }); return hintList; }; App.prototype.collabHints = function() { var app = this, hintList = [], k; app.sites.forEach(function(site) { if (Array.isArray(site.collaborators)) { site.collaborators.forEach(function(email) { if (hintList.indexOf(email) < 0 && email) { hintList.push(email); } }); } }); return hintList; }; App.prototype.mediaFiles = function() { var app = this, list = []; Object.keys(app.site.media).forEach(function(mediaID) { var media = app.site.media[mediaID]; if (media.type === 'application/pdf') { var mapObject = { title: media.name || 'No Title Set', url: ca_config.media_cdn + '/' + app.site.id + '/' + mediaID + '.pdf', section: 'files', l: 0 }; list.push(mapObject); } }); return list; }; String.prototype.urlSafe = function() { return this.toString().toLowerCase().replace(/[^a-z0-9\-]/gi, '-').replace(/\-\-/g, '-').replace(/\-\-/g, '-').replace(/\-$/, ''); }; String.prototype.idSafe = function() { return this.toString().replace(/[^a-z0-9\-]/gi, '-').replace(/\-\-/g, '-'); }; String.prototype.xmlSafe = function() { return this.toString().replace(/\"/, '"'); }; String.prototype.singular = function() { var ret = this.toString(); var endletter = ret.substr(-1); if (endletter === 's' || endletter === 'S') { ret = ret.substring(ret.length - 1, -1); } return ret; }; String.prototype.toClassName = function() { var ret = this.toString().replace('/:/g', ''); return this; }; String.prototype.capitalizeFirstLetter = function() { return this.charAt(0).toUpperCase() + this.slice(1); }; String.prototype.htmlSafe = function() { return this.replace(/&/g, '&') .replace(/“/g, '“') .replace(/”/g, '”') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }; String.prototype.cleanWord = function() { return this .replace(/[\u2018\u2019\u201A]/g, "\'") //.replace(/"\b/g, "\u201c") // opening double //.replace(/\b"/g, "\u201d") // closing double .replace(/[\u201E]/g, "\"") .replace(/\u2026/g, "...") .replace(/[\u2013]/g, "-") .replace(/\u02C6/g, "^") .replace(/\u2039/g, "<") .replace(/\u203A/g, ">") .replace(/[\u02DC\u00A0]/g, " "); }; String.prototype.clean = function(){ var tmpel = document.createElement('span'); tmpel.innerHTML = this.toString(); return tmpel.textContent; }; String.prototype.cssMeasurement = function() { if (this) { if (!this.indexOf('em') && !this.indexOf('px') && !this.indexOf('pt') && !this.indexOf('%')) { return this + 'px'; } } else { return 0; } return this; }; function arrayMove(ar, old_index, new_index) { while (old_index < 0) { old_index += ar.length; } while (new_index < 0) { new_index += ar.length; } if (new_index >= ar.length) { var k = new_index - ar.length; while ((k--) + 1) { ar.push(undefined); } } ar.splice(new_index, 0, ar.splice(old_index, 1)[0]); return ar; // for testing purposes } var StyleEditorFor = { text: function(app, object, path, target) { var key = path[path.length - 1]; var selector = '.' + path[path.length - 2] + key; var dom = DOM().new('div'); //LABEL StyleEditorHelpers.label(app, dom, object, path, target, { label: 'Style Label' }); // FONT + WEIGHTetc StyleEditorHelpers.font(app, dom, object[selector], path.concat(selector), target, { label: 'Font', value: object[selector] }); // FONT SIZE StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Font Size', value: object[selector]['font-size'], property: 'font-size' }); // TEXT COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Text Color', value: object[selector].color, fullWidth: true, property: 'color' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Background Color', value: object[selector]['background-color'], fullWidth: true, property: 'background-color' }); EditorHelpers.options(app, dom, object[selector], path.concat(selector), target, { label: 'Text Transform', value: object[selector]['text-transform'] || '', property: 'text-transform', fullWidth: true, options: ['none', 'capitalize', 'uppercase', 'lowercase'].map(function(item) { return { text: item.capitalizeFirstLetter(), value: item }; }), }); // MARGIN StyleEditorHelpers.paddingMargin(app, dom, object[selector], path.concat(selector), target, { label: 'Margin', value: object[selector].margin, property: 'margin' }); // PADDING StyleEditorHelpers.paddingMargin(app, dom, object[selector], path.concat(selector), target, { label: 'Padding', value: object[selector].padding, property: 'padding' }); StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Line Height', min: '-100', max: '200', units: ['px', '%'], value: object[selector]['line-height'], clear: true, property: 'line-height' }); StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Letter Spacing', min: '-10', max: '20', units: ['px', '%'], value: object[selector]['letter-spacing'], clear: true, property: 'letter-spacing' }); // FONT SIZE MOBILE StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Tablet Font Size (1024px)', value: object[selector]['__media_tablet_font-size'] || '', clear: true, property: '__media_tablet_font-size' }); // FONT SIZE MOBILE StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Mobile Font Size (700px)', value: object[selector]['__media_mobile_font-size'] || '', clear: true, property: '__media_mobile_font-size' }); StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Tablet Line Height', min: '-100', max: '200', units: ['px', '%'], clear: true, value: object[selector]['__media_tablet_line-height'] || '', property: '__media_tablet_line-height' }); StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Mobile Line Height', min: '-100', max: '200', units: ['px', '%'], clear: true, value: object[selector]['__media_mobile_line-height'] || '', property: '__media_mobile_line-height' }); StyleEditorHelpers.boxShadow(app, dom, object[selector], path.concat(selector), target, { label: 'Text Shadow', value: object[selector]['text-shadow'], radius: true, property: 'text-shadow' }); StyleEditorHelpers.delete(app, dom, object, path, target, { searchObject: app.site, searchPath: [], searchKeys: ['class', '_class'], searchValue: 'text' + key }); return dom; }, blocks: function(app, object, path, target) { var key = path[path.length - 1]; var selector = '.' + path[path.length - 2] + key, selectorHover = '.' + path[path.length - 2] + key + ':hover', selectorContainer = '.' + path[path.length - 2] + key + 'container'; var dom = DOM().new('div'); //LABEL StyleEditorHelpers.label(app, dom, object, path, target, { label: 'Style Label' }); // TEXT COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Text Color', value: object[selector].color, fullWidth: true, property: 'color' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Background Color', value: object[selector]['background-color'], fullWidth: true, gradient: 'background', gradient_value: object[selector]['background'], property: 'background-color' }); if(!object[selectorHover]){ object[selectorHover] = {}; } StyleEditorHelpers.color(app, dom, object[selectorHover], path.concat(selectorHover), target, { label: 'Background Hover Color', value: object[selectorHover]['background-color'], fullWidth: true, gradient: 'background', gradient_value: object[selectorHover]['background'], property: 'background-color' }); var blockWidthOps = [{ text: '1280px (Default)', value: '1280px' }, { text: '920px', value: '920px' }, { text: '600px', value: '600px' }, { text: '1920px', value: '1920px' }, { text: 'Full Width', value: 'none' }]; EditorHelpers.options(app, dom, object[selectorContainer], path.concat(selectorContainer), target, { label: 'Block Content Max Width', value: object[selectorContainer] && object[selectorContainer]['max-width'] || '', property: 'max-width', fullWidth: true, allowCustom: true, options: blockWidthOps }); EditorHelpers.options(app, dom, object[selector], path.concat(selector), target, { label: 'Block Max Width', value: object[selector]['max-width'] || '', property: 'max-width', fullWidth: true, allowCustom: true, onchange: function(val) { if(val && val != 'none'){ app.siteUpdate(path.concat(selector), {margin: '0 auto'}) } else { app.siteUpdate(path.concat(selector), {margin: ''}) } }, options: blockWidthOps.map(function(item, i) { if (i === 0) { return { text: '1280px', value: '1280px' }; } else if (i === 4) { return { text: 'Full Width (Default)', value: 'none' }; } else { return item; } }) }); // HORIZONTAL-ALIGN StyleEditorHelpers.textAlign(app, dom, object[selector], path.concat(selector), target, { label: 'Text Alignment', value: object[selector]['text-align'], property: 'text-align', justify: true }); var selectorPadding = selector + 'container'; // PADDING StyleEditorHelpers.paddingMargin(app, dom, object[selectorPadding], path.concat(selectorPadding), target, { label: 'Padding', value: object[selectorPadding].padding, property: 'padding' }); // PADDING MOBILE StyleEditorHelpers.paddingMargin(app, dom, object[selectorPadding], path.concat(selectorPadding), target, { label: 'Mobile Padding', value: object[selectorPadding].__media_mobile_padding || object[selector].padding, property: '__media_mobile_padding', clear: true }); // BORDER StyleEditorHelpers.border(app, dom, object[selector], path.concat(selector), target, { label: 'Border', value: object[selector].border, radius: true, property: 'border' }); // SHADOW StyleEditorHelpers.boxShadow(app, dom, object[selector], path.concat(selector), target, { label: 'Box Shadow', value: object[selector]['box-shadow'], radius: true, property: 'box-shadow' }); /* old needs fixing if (key > 0) { DOM().new('div').class('caa_rightPanelSection').append(DOM().new('button').class('caa_button-default').text('Delete Style').on('click', function(e) { app.deleteStyle(type, key); app.render('/' + app.parts[0] + '/' + type, false, true); })).appendTo(dom); }*/ StyleEditorHelpers.delete(app, dom, object, path, target, { searchObject: app.site, searchPath: [], searchKeys: ['class', '_class'], searchValue: 'blocks' + key }); return dom; }, buttons: function(app, object, path, target) { var key = path[path.length - 1]; var baseSelector = '.' + path[path.length - 2] + key, selector = baseSelector + '', selectorHover = baseSelector + ':hover', selectorActive = baseSelector + ':active'; var dom = DOM().new('div'); //LABEL StyleEditorHelpers.label(app, dom, object, path, target, { label: 'Style Label' }); // FONT + WEIGHTetc StyleEditorHelpers.font(app, dom, object[selector], path.concat(selector), target, { label: 'Font', value: object[selector] || 'inherit' }); // FONT SIZE StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Font Size', value: object[selector]['font-size'], property: 'font-size' }); EditorHelpers.options(app, dom, object[selector], path.concat(selector), target, { label: 'Text Transform', value: object[selector]['text-transform'] || '', property: 'text-transform', fullWidth: true, options: ['none', 'capitalize', 'uppercase', 'lowercase'].map(function(item) { return { text: item.capitalizeFirstLetter(), value: item }; }), }); EditorHelpers.options(app, dom, object[selector], path.concat(selector), target, { label: 'Font Weight', value: object[selector]['font-weight'] || '', property: 'font-weight', fullWidth: true, options: ['', 'normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900', 'initial', 'inherit'] }); StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Letter Spacing', min: '-10', max: '20', units: ['px', '%'], value: object[selector]['letter-spacing'], clear: true, property: 'letter-spacing' }); StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Line Height', min: '-100', max: '200', units: ['px', '%'], value: object[selector]['line-height'], clear: true, property: 'line-height' }); // TEXT COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Text Color', value: object[selector].color, fullWidth: true, property: 'color' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Background Color', value: object[selector]['background-color'], fullWidth: true, property: 'background-color' }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // BORDER StyleEditorHelpers.border(app, dom, object[selector], path.concat(selector), target, { label: 'Border', value: object[selector].border, radius: true, property: 'border' }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // PADDING StyleEditorHelpers.paddingMargin(app, dom, object[selector], path.concat(selector), target, { label: 'Padding', value: object[selector].padding, property: 'padding' }); // MARGIN StyleEditorHelpers.paddingMargin(app, dom, object[selector], path.concat(selector), target, { label: 'Margin', value: object[selector].margin, property: 'margin' }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // HOVER TEXT COLOR StyleEditorHelpers.color(app, dom, object[selectorHover], path.concat(selectorHover), target, { label: 'Hover Text Color', value: object[selectorHover].color, fullWidth: true, property: 'color' }); // HOVER BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selectorHover], path.concat(selectorHover), target, { label: 'Hover Background', value: object[selector]['background-color'], fullWidth: true, property: 'background-color' }); // HOVER BORDER StyleEditorHelpers.color(app, dom, object[selectorHover], path.concat(selectorHover), target, { label: 'Hover Border', value: object[selectorHover]['border-color'], fullWidth: true, property: 'border-color' }); var hoverOptions = [{ text: 'None', value: 'none' }, { text: 'Diagonal Fill', value: 'ef-h-fill-diagonal' }, { text: 'Middle Expand', value: 'ef-h-fill-middle-expand' }], clickOptions = [{ text: 'None', value: 'none' }, { text: 'Ripple', value: 'ef-a-ripple' }]; app.getCustomElements().forEach(function(item) { if (item.customType) { if (item.customType === 'hover-effect') { hoverOptions.push({ text: 'Custom Element: ' + item.text, value: 'custom-' + item.value }); } } }); EditorHelpers.options(app, dom, object, path, target, { label: 'Hover Effect', value: object.__hover, property: '__hover', fullWidth: true, options: hoverOptions }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // ACTIVE TEXT COLOR StyleEditorHelpers.color(app, dom, object[selectorActive], path.concat(selectorActive), target, { label: 'Active/Click Text Color', value: object[selectorActive].color, fullWidth: true, property: 'color' }); // ACTIVE BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selectorActive), target, { label: 'Active/Click Background', value: object[selectorActive]['background-color'], fullWidth: true, property: 'background-color' }); // ACTIVE BORDER StyleEditorHelpers.color(app, dom, object[selectorActive], path.concat(selectorActive), target, { label: 'Active/Click Border', value: object[selectorActive]['border-color'], fullWidth: true, property: 'border-color' }); EditorHelpers.options(app, dom, object[selector], path.concat(selector), target, { label: 'Off/Hover/Active State Transitions', value: object[selector]['transition'] || '', property: 'transition', fullWidth: true, options: [{ text: 'None/Use Effects', value: '' }, { text: 'Fast Linear', value: 'all 0.15s linear' }, { text: 'Fast Ease In', value: 'all 0.15s ease-in' }, { text: 'Fast Ease Out', value: 'all 0.15s ease-out' }, { text: 'Fast Ease', value: 'all 0.15s ease-in-out' }, { text: 'Medium Linear', value: 'all 0.25s linear' }, { text: 'Medium Ease In', value: 'all 0.25s ease-in' }, { text: 'Medium Ease Out', value: 'all 0.25s ease-out' }, { text: 'Medium Ease', value: 'all 0.25s ease-in-out' }, { text: 'Slow Linear', value: 'all 0.5s linear' }, { text: 'Slow Ease In', value: 'all 0.5s ease-in' }, { text: 'Slow Ease Out', value: 'all 0.5s ease-out' }, { text: 'Slow Ease', value: 'all 0.5s ease-in-out' }] }); EditorHelpers.options(app, dom, object, path, target, { label: 'Click/Tap Effect', value: object.__click, property: '__click', fullWidth: true, options: clickOptions }); StyleEditorHelpers.delete(app, dom, object, path, target, { searchObject: app.site, searchPath: [], searchKeys: ['class', '_class'], searchValue: 'buttons' + key }); DOM().new('div').class('caa_rightPanelSection').append( DOM().new('button').class('caa_button-default').text('Duplicate Button').on('click', function(e){ var oldNum = key; var newNum = app.site.styles.buttons.length; var newButton = JSON.parse(JSON.stringify(object).replace(new RegExp('.buttons' + oldNum, 'g'), '.buttons'+newNum)); app.siteAdd(['styles', 'buttons'], newButton); app.render('/' + app.parts[0] + '/buttons', false, true); }) ).appendTo(dom); return dom; }, links: function(app, object, path, target) { var dom = DOM().new('div'), selectors = { base: '.links', hover: '.links:hover', active: '.links:active' }; EditorHelpers.options(app, dom, object[selectors.base], path.concat(selectors.base), target, { label: 'Text Decoration/Underline', value: object[selectors.base]['text-decoration'] || 'underline', property: 'text-decoration', fullWidth: true, options: ['none', 'underline', 'overline', 'line-through', 'blink', 'underline overline'].map(function(item) { return { text: item.capitalizeFirstLetter(), value: item }; }), }); EditorHelpers.options(app, dom, object[selectors.base], path.concat(selectors.base), target, { label: 'Text Transform', value: object[selectors.base]['text-transform'] || '', property: 'text-transform', fullWidth: true, options: ['none', 'capitalize', 'uppercase', 'lowercase'].map(function(item) { return { text: item.capitalizeFirstLetter(), value: item }; }), }); EditorHelpers.options(app, dom, object[selectors.base], path.concat(selectors.base), target, { label: 'Font Weight', value: object[selectors.base]['font-weight'] || '', property: 'font-weight', fullWidth: true, options: ['', 'normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900', 'initial', 'inherit'] }); // TEXT COLOR StyleEditorHelpers.color(app, dom, app.site.styles.colors, ['styles', 'colors'], target, { label: 'Link Color', value: app.site.styles.colors.links, fullWidth: true, property: 'links' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selectors.base], path.concat(selectors.base), target, { label: 'Background Color', value: object[selectors.base]['background-color'], fullWidth: true, property: 'background-color' }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // BORDER StyleEditorHelpers.border(app, dom, object[selectors.base], path.concat(selectors.base), target, { label: 'Border', value: object[selectors.base].border, radius: true, property: 'border' }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // HOVER TEXT COLOR StyleEditorHelpers.color(app, dom, object[selectors.hover], path.concat(selectors.hover), target, { label: 'Hover Text Color', value: object[selectors.hover].color, fullWidth: true, property: 'color' }); // HOVER BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selectors.hover], path.concat(selectors.hover), target, { label: 'Hover Background', value: object[selectors.hover]['background-color'], fullWidth: true, property: 'background-color' }); // HOVER BORDER StyleEditorHelpers.color(app, dom, object[selectors.hover], path.concat(selectors.hover), target, { label: 'Hover Border', value: object[selectors.hover]['border-color'], fullWidth: true, property: 'border-color' }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // ACTIVE TEXT COLOR StyleEditorHelpers.color(app, dom, object[selectors.active], path.concat(selectors.active), target, { label: 'Active/Click Text Color', value: object[selectors.active].color, fullWidth: true, property: 'color' }); // ACTIVE BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selectors.active], path.concat(selectors.active), target, { label: 'Active/Click Background', value: object[selectors.active]['background-color'], fullWidth: true, property: 'background-color' }); // ACTIVE BORDER StyleEditorHelpers.color(app, dom, object[selectors.active], path.concat(selectors.active), target, { label: 'Active/Click Border', value: object[selectors.active]['border-color'], fullWidth: true, property: 'border-color' }); return dom; }, forms: function(app, object, path, target) { var dom = DOM().new('div'), key = path[path.length - 1], selectors = { input: '.' + path[path.length - 2] + key, label: 'label.' + path[path.length - 2] + key, sublabel: '.' + path[path.length - 2] + key+'-sublabel', invalid: '.' + path[path.length - 2] + key + '-error', invalidInput: '.' + path[path.length - 2] + key + '-input-error', divider: '.' + path[path.length - 2] + key+'-divider', form: '.' + path[path.length - 2] + key + '-form', }, tabs = UI.tabs({ settings: { title: 'Settings', selected: true }, inputs: { title: 'Inputs' }, labels: { title: 'Labels' }, invalid: { title: 'Invalid Input' } }, dom, app.rightPanel.tabs); var setLatest = {}; ['invalid', 'label', 'form', 'sublabel', 'divider'].forEach(function(item){ if (!object[selectors[item]]) { setLatest[selectors[item]] = {}; object[selectors[item]] = {}; } }); if (!object[selectors.label]['background-color'] && object[selectors.input]['background-color']) { object[selectors.label]['background-color'] = 'transparent'; if (!setLatest[selectors.label]) { setLatest[selectors.label] = {}; } setLatest[selectors.label]['background-color'] = 'transparent'; } if (Object.keys(setLatest).length) { app.siteUpdate(path, setLatest); } //LABEL StyleEditorHelpers.label(app, tabs.settings.dom, object, path, target, { label: 'Style Label' }); //Form Text Alignment StyleEditorHelpers.textAlign(app, tabs.settings.dom, object[selectors.form], path.concat(selectors.form), target, { label: 'Form Text Alignment', value: object[selectors.form]['text-align'], property: 'text-align' }); //INPUT // FONT + WEIGHTetc StyleEditorHelpers.font(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Font', value: object[selectors.input] || 'inherit', inherit: 1 }); // FONT SIZE StyleEditorHelpers.size(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Font Size', value: object[selectors.input]['font-size'], property: 'font-size' }); // TEXT COLOR StyleEditorHelpers.color(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Text Color', value: object[selectors.input].color, fullWidth: true, property: 'color' }); //Form Text Alignment StyleEditorHelpers.textAlign(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Text Alignment', value: object[selectors.input]['text-align'], property: 'text-align' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Background Color', value: object[selectors.input]['background-color'], fullWidth: true, property: 'background-color' }); // BORDER StyleEditorHelpers.border(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Border', value: object[selectors.input].border, radius: true, clear: true, property: 'border' }); // PADDING StyleEditorHelpers.paddingMargin(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Padding', value: object[selectors.input].padding, property: 'padding' }); // MARGIN StyleEditorHelpers.paddingMargin(app, tabs.inputs.dom, object[selectors.input], path.concat(selectors.input), target, { label: 'Input Margin', value: object[selectors.input].margin, property: 'margin' }); /// LABELS //Form Text Alignment StyleEditorHelpers.textAlign(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Text Alignment', value: object[selectors.label]['text-align'], property: 'text-align' }); // FONT + WEIGHTetc StyleEditorHelpers.font(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Font', value: object[selectors.label] || 'inherit', inherit: 1 }); // FONT SIZE StyleEditorHelpers.size(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Font Size', value: object[selectors.label]['font-size'], property: 'font-size' }); // TEXT COLOR StyleEditorHelpers.color(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Text Color', value: object[selectors.label].color, fullWidth: true, property: 'color' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Background Color', value: object[selectors.label]['background-color'], fullWidth: true, property: 'background-color' }); // BORDER StyleEditorHelpers.border(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Border', value: object[selectors.label].border, radius: true, clear: true, property: 'border', onchange: function(val) { var update = {}; if (!object[selectors.label].border) { update['border-color'] = 'transparent'; } else { update['border-color'] = ''; } app.siteUpdate(path.concat(selectors.label), update); } }); // PADDING StyleEditorHelpers.paddingMargin(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Padding', value: object[selectors.label].padding, property: 'padding' }); // MARGIN StyleEditorHelpers.paddingMargin(app, tabs.labels.dom, object[selectors.label], path.concat(selectors.label), target, { label: 'Label Margin', value: object[selectors.label].margin, property: 'margin' }); // SUB-LABEL FONT SIZE StyleEditorHelpers.size(app, tabs.labels.dom, object[selectors.sublabel], path.concat(selectors.sublabel), target, { label: 'Sub-Label Font Size', value: object[selectors.sublabel]['font-size'], property: 'font-size' }); // SUB-LABEL TEXT COLOR StyleEditorHelpers.color(app, tabs.labels.dom, object[selectors.sublabel], path.concat(selectors.sublabel), target, { label: 'Sub-Label Text Color', value: object[selectors.sublabel].color, fullWidth: true, property: 'color' }); // DIVIDER BORDER StyleEditorHelpers.border(app, tabs.labels.dom, object[selectors.divider], path.concat(selectors.divider), target, { label: 'Spacer/Divider Line', value: object[selectors.divider]['border-bottom'], sides: false, property: 'border-bottom' }); //INVALID SEC // PADDING StyleEditorHelpers.paddingMargin(app, tabs.invalid.dom, object[selectors.invalid], path.concat(selectors.invalid), target, { label: 'Invalid Input Error Padding', value: object[selectors.invalid].padding || '', property: 'padding' }); // MARGIN StyleEditorHelpers.paddingMargin(app, tabs.invalid.dom, object[selectors.invalid], path.concat(selectors.invalid), target, { label: 'Invalid Input Error Margin', value: object[selectors.invalid].margin, property: 'margin' }); // FONT SIZE StyleEditorHelpers.size(app, tabs.invalid.dom, object[selectors.invalid], path.concat(selectors.invalid), target, { label: 'Invalid Input Error Font Size', value: object[selectors.invalid]['font-size'] || '', property: 'font-size' }); // TEXT COLOR StyleEditorHelpers.color(app, tabs.invalid.dom, object[selectors.invalid], path.concat(selectors.invalid), target, { label: 'Invalid Input Error Text Color', value: object[selectors.invalid].color, fullWidth: true, property: 'color' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, tabs.invalid.dom, object[selectors.invalid], path.concat(selectors.invalid), target, { label: 'Invalid Input Error Background Color', value: object[selectors.invalid]['background-color'], fullWidth: true, property: 'background-color' }); if (!object[selectors.invalidInput]) { object[selectors.invalidInput] = {}; } // INPUT ERROR BORDER StyleEditorHelpers.border(app, tabs.invalid.dom, object[selectors.invalidInput], path.concat(selectors.invalidInput), target, { label: 'Invalid Input Border', value: object[selectors.invalidInput].border, radius: true, property: 'border' }); EditorHelpers.options(app, tabs.settings.dom, object, path, target, { label: 'Required Field Indicator', value: object._requiredIndicator, property: '_requiredIndicator', fullWidth: true, options: [{ text: '* After Label', value: '*al' }, { text: '* Before Label', value: '*bl' }, { text: '* After Input', value: '*ai' }, { text: '* Before Input', value: '*bi' }, { text: 'No Indicator', value: ' ' }] }); // TEXT COLOR StyleEditorHelpers.color(app, tabs.settings.dom, object, path, target, { label: 'Required Indicator Color', value: object[selectors.input].color || 'red', fullWidth: true, property: '_requiredIndicatorColor' }); //delete StyleEditorHelpers.delete(app, tabs.settings.dom, object, path, target, { searchObject: app.site, searchPath: [], searchKeys: ['class', '_class'], searchValue: 'forms' + key }); return dom; }, tabs: function(app, object, path, target) { var dom = DOM().new('div'), key = path[path.length - 1], selector = '.' + path[path.length - 2] + key, selectorO = selector + 'on', selectorH = selector + ':hover', selectorT = selector + 'tabs', selectorB = selector + ':before', selectorC = selector + 'content', selectorNotFirstTab = selector + ':not(:first-child)', updateStylesForTabs = function() { var contentCSS = {}, borderSize = (object[selector].border || '').split(' ')[0] || '', borderColor = (object[selector].border || '').split(' ')[2] || '', radius = (object[selector]['border-radius'] || '').split(' ')[0] || ''; if (borderSize) { contentCSS['margin-top'] = '-' + borderSize; } else { contentCSS['margin-top'] = ''; } // udpate content styles contentCSS.border = object[selector].border || ''; if (object[selectorT]['text-align'] === 'right') { // only radius on top left not top right contentCSS['border-radius'] = radius + ' 0 ' + radius + ' ' + radius; } else if (object[selectorT]['text-align'] === 'center') { contentCSS['border-radius'] = radius + ' ' + radius + ' ' + radius + ' ' + radius; } else { // only radius on right contentCSS['border-radius'] = '0 ' + radius + ' ' + radius + ' ' + radius; } app.siteUpdate(path.concat(selector + 'content'), contentCSS); if(borderSize){ // update the borders to show the tabs with borders var updateBords = { content: '""', position: 'absolute', left:0, right:0, bottom:0, height: borderSize, 'background-color': borderColor }; app.siteUpdate(path.concat(selectorB), updateBords); } else { app.siteDelete(path.concat(selectorB)); } // update tabs styles var updateObj = { 'border-radius': radius + ' ' + radius + ' 0 0' }; if(object[selector]['border-bottom-width'] != '0'){ updateObj['border-bottom-width'] = '0'; } if (object[selectorT]['text-align'] === 'right') { if (object[selector]['margin-right']) { updateObj['margin-left'] = (object[selector]['margin-right'] || '') + ''; updateObj['margin-right'] = ''; } } else { if (object[selector]['margin-left']) { updateObj['margin-right'] = (object[selector]['margin-left'] || '') + ''; updateObj['margin-left'] = ''; } } app.siteUpdate(path.concat(selector), updateObj); // not first tab border with spacing or no spacing var updateNotFirstTab = { 'border-left': object[selector]['margin-left'] || object[selector]['margin-right'] || updateObj['margin-left'] || updateObj['margin-right'] ? '' : '0' }; if (object[selectorNotFirstTab]['border-left'] != updateNotFirstTab['border-left']) { app.siteUpdate(path.concat(selectorNotFirstTab), updateNotFirstTab); } //shadow for borders removed, do not use this anymore if(object[selector + ':first-child']){ app.siteDelete(path.concat(selector + ':first-child')); } if (object[selectorH].padding) { // delete padding from hover if it is set for some reason app.siteDelete(path.concat(selectorH, 'padding')); } }; //LABEL StyleEditorHelpers.label(app, dom, object, path, target, { label: 'Style Label' }); if (!object[selectorT]) { object[selectorT] = {}; } if (!object[selectorB]) { object[selectorB] = {}; } //TABS POSITION StyleEditorHelpers.textAlign(app, dom, object[selectorT], path.concat(selectorT), target, { label: 'Tabs Position', value: object[selectorT]['text-align'], property: 'text-align', onchange: updateStylesForTabs }); // FONT SIZE StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Tab Font Size', value: object[selector]['font-size'], property: 'font-size' }); // TEXT COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Tab Text Color', value: object[selector].color, fullWidth: true, property: 'color' }); // ON TEXT COLOR StyleEditorHelpers.color(app, dom, object[selectorO], path.concat(selectorO), target, { label: 'Active Tab Text Color', value: object[selectorO].color, fullWidth: true, property: 'color' }); if (!object[selectorH]) { object[selectorH] = {}; } // HOVER TEXT COLOR StyleEditorHelpers.color(app, dom, object[selectorH], path.concat(selectorH), target, { label: 'Hover Tab Text Color', value: object[selectorH].color, fullWidth: true, property: 'color' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selector], path.concat(selector), target, { label: 'Tab Color', value: object[selector]['background-color'], fullWidth: true, property: 'background-color' }); // HOVER BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selectorH], path.concat(selectorH), target, { label: 'Hover Tab Color', value: object[selectorH]['background-color'], fullWidth: true, property: 'background-color' }); // ON BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object[selectorO], path.concat(selectorO), target, { label: 'Active Tab Color', value: object[selectorO]['background-color'], fullWidth: true, property: 'background-color', onchange: function(color) { var contentCSS = {}; contentCSS['background-color'] = object[selectorO]['background-color'] || ''; app.siteUpdate(path.concat(selector + 'content'), contentCSS); var onCSS = {}; onCSS['border-bottom-color'] = color; app.siteUpdate(path.concat(selectorO), onCSS); } }); EditorHelpers.divider(dom).css({ 'margin-top': '14px' }); // PADDING StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Tab Padding', value: object[selector].padding, property: 'padding', onchange: updateStylesForTabs }); // PADDING StyleEditorHelpers.size(app, dom, object[selector], path.concat(selector), target, { label: 'Tab Spacing', value: object[selector]['margin-right'], property: 'margin-right', onchange: updateStylesForTabs }); // BORDER StyleEditorHelpers.border(app, dom, object[selector], path.concat(selector), target, { label: 'Border', value: object[selector].border, radius: true, property: 'border', onchange: updateStylesForTabs }); StyleEditorHelpers.delete(app, dom, object, path, target, { searchObject: app.site, searchPath: [], searchKeys: ['class', '_class'], searchValue: 'tabs' + key }); return dom; }, tables: function(app, object, path, target) { var key = path[path.length - 1]; var selector = '.' + path[path.length - 2] + key, selectorHeader = selector + ' th', selectorColumn = selector + ' td:first-child', selectorCell = selector + ' td'; var dom = DOM().new('div'); //LABEL StyleEditorHelpers.label(app, dom, object, path, target, { label: 'Style Label' }); StyleEditorHelpers.delete(app, dom, object, path, target, { searchObject: object.content, searchPath: ['content'], searchKeys: ['class', '_class'] }); EditorHelpers.textClass(app, dom, object, path, target, { label: 'Header Text Style', noswitch: true, value: object._class_header || 'text0', property: '_class_header', previewKey: 'title' }); StyleEditorHelpers.textAlign(app, dom, object[selectorHeader], path.concat(selectorHeader), target, { label: 'Header Text Alignment', value: object[selectorHeader]['text-align'], property: 'text-align' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object.selectorHeader, path.concat(selectorHeader), target, { label: 'Header Background Color', value: object[selectorHeader]['background-color'], fullWidth: true, property: 'background-color' }); EditorHelpers.textClass(app, dom, object, path, target, { label: 'First Column Text Style', noswitch: true, value: object._class_column || 'text1', property: '_class_column', previewKey: 'body' }); StyleEditorHelpers.textAlign(app, dom, object[selectorColumn], path.concat(selectorColumn), target, { label: 'First Column Text Alignment', value: object[selectorColumn]['text-align'], property: 'text-align' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object.selectorColumn, path.concat(selectorColumn), target, { label: 'First Column Background Color', value: object[selectorColumn]['background-color'], fullWidth: true, property: 'background-color' }); EditorHelpers.textClass(app, dom, object, path, target, { label: 'Cell Text Style', noswitch: true, value: object._class_cell || 'text1', property: '_class_cell', previewKey: 'body' }); StyleEditorHelpers.textAlign(app, dom, object[selectorCell], path.concat(selectorCell), target, { label: 'Cell Text Alignment', value: object[selectorCell]['text-align'], property: 'text-align' }); // BACKGROUND COLOR StyleEditorHelpers.color(app, dom, object.selectorCell, path.concat(selectorCell), target, { label: 'Cell Background Color', value: object[selectorCell]['background-color'], fullWidth: true, property: 'background-color' }); StyleEditorHelpers.delete(app, dom, object, path, target, { searchObject: app.site, searchPath: [], searchKeys: ['class', '_class'], searchValue: 'tables' + key }); return dom; }, icons: function(app, object, path, target) { var key = path[path.length - 1]; var selector = '.' + path[path.length - 2] + key; var dom = DOM().new('div'); var set = 1; if (app.site.styles.icons) { if (app.site.styles.icons.set) { set = app.site.styles.icons.set; } } DOM().new('button').class('caa_button-default pickIconSet').text('Icon Set ' + set).appendTo(DOM().new('div').class('caa_rightPanelSection').appendTo(dom)).on('click', function(e) { var modal = UI.openModal(DOM(e.target)); app.pickIconSet(DOM().new('div').class('caa_padding').appendTo(modal), function(set) { var upd = { icons: JSON.parse(JSON.stringify(object || {})) }; upd.icons.set = set; app.siteUpdate(['styles'], upd); DOM().byClass('pickIconSet').text('Icon Set ' + set); UI.closeModal(); app.setCurrentIconSet(); }); }); var size = '32px'; if (object.size) { size = object.size; } StyleEditorHelpers.size(app, dom, object, path, target, { label: 'Default Size', value: size, property: 'size', clear: true, min: 10, max: 200 }, false); var asize = size; if (object.sizeArrows) { asize = object.sizeArrows; } StyleEditorHelpers.size(app, dom, object, path, target, { label: 'Arrow Size', value: asize, property: 'sizeArrows', clear: true, min: 10, max: 200 }, false); DOM().new('div').class('caa_rightPanelSection').text('To provide your own custom icons that are compatible, please type or paste in the SVG paths and the viewBox. Do not include the
tag').appendTo(dom); var customIconSection = DOM().new('div').appendTo(dom); var buttonHolder = DOM().new('div').class('caa_rightPanelSection').appendTo(customIconSection); DOM().new('button').class('caa_button-default').text('Add Custom Icon').appendTo(buttonHolder).on('click', function(e) { var newIcon = { id: 'icon1', viewBox: '0 0 32 32', svg: '
' }; var update = { icons: [] }; if (app.site.icons) { if (app.site.icons.length) { update.icons = app.site.icons.slice(0); } } update.icons.push(newIcon); app.siteUpdate([], update); showFields(); app.setCurrentIconSet(); }); var iconsHolder = DOM().new('div').appendTo(customIconSection); var showFields = function() { iconsHolder.html(''); if (app.site.icons) { if (app.site.icons.length) { app.site.icons.forEach(function(icon, i) { var iconHolder = DOM().new('div').appendTo(iconsHolder).css({ 'border-bottom': '1px solid #d4d4d4' }); EditorHelpers.text(app, iconHolder, icon, ['icons', i], {}, { label: 'id', value: icon.id || '', property: 'id', onchange: function(e) { app.setCurrentIconSet(); } }); EditorHelpers.text(app, iconHolder, icon, ['icons', i], {}, { label: 'viewBox', value: icon.viewBox || '', property: 'viewBox', onchange: function() { app.setCurrentIconSet(); } }); DOM().new('div').class('caa_rightPanelSection').append( Inputs.textarea({ label: 'SVG Markup', value: icon.svg || '' })).appendTo(iconHolder).on('change', function(e) { var setVal = DOM(e.target).val(); var update = { svg: setVal }; app.siteUpdate(['icons', i], update); app.setCurrentIconSet(); }); }); } } }; showFields(); return dom; }, mediaLoading: function(app, object, path, target) { var widget = object.mediaLoading || {}, usePath = path.concat('mediaLoading'); var dom = DOM().new('div'); StyleEditorHelpers.color(app, dom, widget, usePath, target, { label: 'Fill/Background Color', value: widget['background-color'] || 'rgba(102,102,102,0.2)', fullWidth: true, property: 'background-color' }); // BORDER StyleEditorHelpers.border(app, dom, widget, usePath, target, { label: 'Border', value: widget.border, radius: true, property: 'border' }); return dom; }, }; App.prototype.genStyleSheet = function(forWhat, specialFlag) { var app = this, sheet = '', sheet2 = '', // more important lst in css list sheetQ = '', sheetQueries = {}, docwdiff = 0; if (!document.getElementsByClassName('caa_previewFrame').length && document.innerWidth < 1200) { var stagew = app.stage.setWidth || app.stage.elements[0].offsetWidth; docwdiff = window.innerWidth - stagew; } var addMediaQuery = function(w, selector, css) { if (typeof w === 'number' && docwdiff) { w = (w + docwdiff); } if (!sheetQueries[w]) { sheetQueries[w] = {}; } if (!sheetQueries[w][selector]) { sheetQueries[w][selector] = ''; } if (selector.indexOf('.grid') > -1 && css.indexOf('width:') > -1 && checkForWhat.indexOf('cagridFlexHeight') > -1 && css.indexOf('width:auto') < 0) { var spl = css.split(';'), len = spl.length, s = 0, newCSS = css; for (; s < len; s++) { if (spl[s].substr(0, 6) === 'width:') { newCSS += ';' + spl[s].replace('width', 'min-width'); newCSS += ';' + spl[s].replace('width', 'max-width'); } } newCSS = newCSS.replace(/\;\;/gi, ';'); if (!sheetQueries[w]['.cagridFlexHeight > ' + selector]) { sheetQueries[w]['.cagridFlexHeight > ' + selector] = ''; } sheetQueries[w]['.cagridFlexHeight > ' + selector] += newCSS; } sheetQueries[w][selector] += css; }; var ignoreProperties = ['font-ident', 'label'], genCSS = function(what, specialFlag) { var cssString = ''; if (what) { for (var selector in what) { if (what.hasOwnProperty(selector)) { if (selector.substr(0, 1) !== '_' && typeof what[selector] === 'object') { var selectorContent = ''; for (var property in what[selector]) { if (property && what[selector].hasOwnProperty(property)) { if ((what[selector][property] || what[selector][property] == '0') && (typeof what[selector][property] === 'string' || typeof what[selector][property] === 'number') && what[selector][property] !== 'px' && what[selector][property] !== ' px') { if (property[0] === '@') { var mp = property.split('@'); if (mp[1] && mp[2]) { addMediaQuery(mp[1], selector, mp[2] + ': ' + what[selector][property] + '; '); } } else if (property[0] === '_') { if (property.substr(0, 7) === '__media') { var mp = property.replace('__media_', '').split('_'); if (mp[0]) { var sw = mp[0] === 'tablet' ? 1024 : 700; //700 mobile //mp[0] === 'mobile'; // switch here. for now we only have 700 for mobile addMediaQuery(sw, selector, property.replace('__media_' + mp[0] + '_', '') + ': ' + what[selector][property] + '; '); } } } else { if (ignoreProperties.indexOf(property) < 0) { selectorContent += property + ': ' + what[selector][property] + ';\n'; if (specialFlag) { if (property == 'color' || property == 'background-color') { app.buildColorList(what[selector][property]); } } } } } } } if (selectorContent) { cssString += selector + ' {\n' + selectorContent + '}\n'; } } } } } return cssString; }; if (!specialFlag) { specialFlag = false; } var checkForWhat = (forWhat) ? forWhat : []; if (!specialFlag) { var baseFont = ''; if (app.site.styles.text[1]['.text1']['font-family']) { baseFont += 'font-family:' + app.site.styles.text[1]['.text1']['font-family'] + '; '; } if (app.site.styles.text[1]['.text1']['font-style']) { baseFont += 'font-style:' + app.site.styles.text[1]['.text1']['font-style'] + '; '; } if (app.site.styles.text[1]['.text1']['font-weight']) { baseFont += 'font-weight:' + app.site.styles.text[1]['.text1']['font-weight'] + '; '; } sheet += 'body{-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale; width: 100%; overflow-x: hidden; } '; sheet += 'img, video, .img{ max-width:100%; width:auto; border:0; vertical-align:middle; } '; sheet += '.page0{ position:relative; padding:0; margin:0; color: ' + app.site.styles.colors.text + '; background:' + app.site.styles.colors.background + '; ' + baseFont + 'display: flex; min-height: 100vh; height:100%; flex-direction: column; max-width:100%; } '; sheet += '#page-content{ flex: 1 0 auto; -ms-flex: 1 0 auto; } '; // you can't overflow-x hidden page-content because it makes there be vertical scroll bars in page-content in the app which sucks bad. sheet += 'nav, footer{ flex: none; } footer{ z-index: 1 } '; //sheet += '.page0 h1, .page0 h2, .page0 h3, .page0 h4, .page0 h5, .page0 h6{margin:0} '; sheet += 'a{ color: ' + app.site.styles.colors.links + '; } '; sheet += '.ib{display:inline-block} .ibb{display:inline-block;box-sizing:border-box} .middle{vertical-align:middle} .top{vertical-align:top} .bottom{vertical-align:bottom} .center{text-align:center} '; sheet += '.abs-fill{ position: absolute; top:0; right:0; bottom:0; left:0; } '; sheet += '.blockcontainer{ position:relative; } '; sheet += '.block-content{ padding-top:1px; margin-top:-1px; } '; // hack that fixes overflow from making a block zero padding and text styles having margin if (checkForWhat.indexOf('icon') > -1) { var s = '32px'; if (app.site.styles.icons) { if (app.site.styles.icons.size) { s = app.site.styles.icons.size; } } sheet += '.icon, .icon svg{ fill:' + app.site.styles.colors.icons + '; width:' + s + '; height:' + s + '; } .icon svg{ pointer-events:none;display:block;} .icon{ position: relative; padding: 0; border: none; background: none; } .icon:focus{ outline: none; } '; } if (checkForWhat.indexOf('icon-arrows') > -1) { var as = '32px'; if (app.site.styles.icons) { if (app.site.styles.icons.size) { as = app.site.styles.icons.size; } if (app.site.styles.icons.sizeArrows) { as = app.site.styles.icons.sizeArrows; } } sheet += '.icon-arrows, .icon-arrows svg{ width:' + as + '; height:' + as + '; } '; addMediaQuery(648, '.icon-arrows, .icon-arrows svg', 'width:32px; height:32px;'); } if (checkForWhat.indexOf('links') > -1) { sheet += genCSS(app.site.styles.globals.links, specialFlag); } if (checkForWhat.indexOf('sup') > -1) { sheet += 'sup{ vertical-align: baseline; position: relative; top: -0.4em; } '; } if (checkForWhat.indexOf('cagrid') > -1 || checkForWhat.indexOf('caslider') > -1) { sheet += '.cagrid{ position:relative; } .cagrid .cagriditem{position:relative; display:inline-block;box-sizing:border-box;} '; } if (checkForWhat.indexOf('cagridnostack')) { sheet += '.cagridnostack{ white-space:nowrap; } .cagridnostack .cagriditem{white-space:normal;} '; } if (checkForWhat.indexOf('cagridFlexHeight') > -1) { sheet += '.cagridFlexHeight{ display:flex; flex-wrap: wrap; } .cagridFlexHeight .cagriditem{ flex: 1 0 auto; } .cagridFlexHeight .cagriditem > div{ height: 100%; box-sizing: border-box } '; } if (checkForWhat.indexOf('caslider') > -1) { sheet += '.caslider{ white-space:nowrap; max-width:100%; overflow:hidden; } .caslider .cagriditem{white-space:normal} '; } if (checkForWhat.indexOf('valignmiddle') > -1) { sheet += '.valignmiddle:before{content:"";height:100%;display:inline-block;width:0;vertical-align:middle;position:relative;} .valignmiddle{white-space:nowrap} .valignmiddleitem{white-space:normal;vertical-align:middle;display:inline-block;max-width:100%} '; } if (checkForWhat.indexOf('valignbottom') > -1) { sheet += '.valignbottom:before{content:"";height:100%;display:inline-block;width:0;vertical-align:bottom} .valignbottom{white-space:nowrap} .valignbottomitem{white-space:normal;vertical-align:bottom;display:inline-block;max-width:100%} '; } if (checkForWhat.indexOf('fixlongtext') > -1) { //sheet += '.fixlongtext{ -ms-word-break: break-all; word-break: break-all; overflow-wrap: break-word; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } '; sheet += '.fixlongtext{ overflow-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } '; // above produced breaking word issues in ie11 assholes } if (checkForWhat.indexOf('gmap') > -1) { sheet += '.gmap img{max-width: inherit;} .gmap{max-width:100%} '; } if (checkForWhat.indexOf('overlay') > -1) { sheet += '.overlay{ opacity:0; transition:opacity 0.4s ease-out; -webkit-transition:opacity 0.4s ease-out } .overlay:hover{ opacity:1; } '; sheet += '.overlay-container{ margin: 0; border: 0 }.overlay-container iframe{ margin: 0; border: 0 } '; } if (checkForWhat.indexOf('overlay-tr') > -1) { sheet += '.overlay-tr{ position: absolute; right: 40px; top: 10px; cursor: pointer; pointer-events: fill; font-size:13px; } '; addMediaQuery(700, '.overlay-tr', 'top:10px; right:20px;'); } if (checkForWhat.indexOf('click') > -1) { sheet += '.click{ cursor:pointer } '; } if (checkForWhat.indexOf('base-button') > -1) { sheet += '.base-button{ outline: none; border: 0; -webkit-appearance: none; -moz-appearance: none; appearance: none; background-color:transparent; cursor:pointer; font:inherit; } '; } if (checkForWhat.indexOf('transition150') > -1) { sheet += '.transition150{ transition:all 0.15s ease-in-out; -webkit-transition:all 0.15s ease-in-out; -webkit-transform: translateZ(0); transform: translateZ(0); } '; } if (checkForWhat.indexOf('ef-h-grow-s') > -1) { sheet += '.ef-h-grow-s:hover{ -webkit-transform: scale(1.1); transform: scale(1.1); } '; } if (checkForWhat.indexOf('ef-a-grow-s') > -1) { sheet += '.ef-a-grow-s:active{ -webkit-transform: scale(1); transform: scale(1); } '; } var kf; sheet += '.block-effects { opacity:0; -webkit-transform: translateZ(0); transform: translateZ(0); -webkit-animation-duration: 1s;animation-duration: 1s;-webkit-animation-fill-mode: both;animation-fill-mode: both;-webkit-animation-timing-function: cubic-bezier(.2, .55, .88, .95);animation-timing-function: cubic-bezier(.2, .55, .88, .95); } '; sheet += '.block-effects-applied { opacity:1; } '; if (checkForWhat.indexOf('block-effects.fast') > -1) { sheet += '.block-effects.fast{-webkit-animation-duration: .75s; animation-duration: .75s; } '; } if (checkForWhat.indexOf('block-effects.slow') > -1) { sheet += '.block-effects.slow{-webkit-animation-duration: 1.25s; animation-duration: 1.25s; } '; } if (checkForWhat.indexOf('block-effects.slight') > -1) { sheet += '.block-effects.slight{-webkit-animation-delay: .25s; animation-delay: .25s;} '; } if (checkForWhat.indexOf('block-effects.delay05') > -1) { sheet += '.block-effects.delay05{-webkit-animation-delay: 0.5s; animation-delay: 0.5s;} '; } if (checkForWhat.indexOf('block-effects.delay1') > -1) { sheet += '.block-effects.delay1{-webkit-animation-delay: 1s; animation-delay: 1s;} '; } if (checkForWhat.indexOf('block-effects.fadeIn') > -1) { sheet += '.block-effects.fadeIn{ -webkit-animation-name: fadeIn; animation-name: fadeIn; } '; kf = '@keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.fadeInDown') > -1) { sheet += '.block-effects.fadeInDown { -webkit-animation-name: fadeInDown; animation-name: fadeInDown; } '; kf = '@keyframes fadeInDown { 0% { opacity: 0; -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); } 100% { opacity: 1; -webkit-transform: none; transform: none; } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.fadeInDownShort') > -1) { sheet += '.block-effects.fadeInDownShort { -webkit-animation-name: fadeInDownShort; animation-name: fadeInDownShort; } '; kf = '@keyframes fadeInDownShort { 0% { opacity: 0; -webkit-transform: translate3d(0, -25px, 0); transform: translate3d(0, -25px, 0); } 100% { opacity: 1; -webkit-transform: none; transform: none; } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.fadeInUp') > -1) { sheet += '.block-effects.fadeInUp { -webkit-animation-name: fadeInUp; animation-name: fadeInUp; } '; kf = '@keyframes fadeInUp { 0% { opacity: 0; -webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0); } 100% { opacity: 1; -webkit-transform: none; transform: none; } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.fadeInUpShort') > -1) { sheet += '.block-effects.fadeInUpShort { -webkit-animation-name: fadeInUpShort; animation-name: fadeInUpShort; } '; kf = '@keyframes fadeInUpShort { 0% { opacity: 0; -webkit-transform: translate3d(0, 25px, 0); transform: translate3d(0, 25px, 0); } 100% { opacity: 1; -webkit-transform: none; transform: none; } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideInDown') > -1) { sheet += '.block-effects.slideInDown { -webkit-animation-name: slideInDown; animation-name: slideInDown; } '; kf = '@keyframes slideInDown { 0% { -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideInDownShort') > -1) { sheet += '.block-effects.slideInDownShort { -webkit-animation-name: slideInDownShort; animation-name: slideInDownShort; } '; kf = '@keyframes slideInDownShort { 0% { -webkit-transform: translate3d(0, -25px, 0); transform: translate3d(0, -25px, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideInUp') > -1) { sheet += '.block-effects.slideInUp { -webkit-animation-name: slideInUp; animation-name: slideInUp; } '; kf = '@keyframes slideInUp { 0% { -webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideInUpShort') > -1) { sheet += '.block-effects.slideInUpShort { -webkit-animation-name: slideInUpShort; animation-name: slideInUpShort; } '; kf = '@keyframes slideInUpShort { 0% { -webkit-transform: translate3d(0, 25px, 0); transform: translate3d(0, 25px, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideFromLeftShort') > -1) { sheet += '.block-effects.slideFromLeftShort { -webkit-animation-name: slideFromLeftShort; animation-name: slideFromLeftShort; } '; kf = '@keyframes slideFromLeftShort { 0% { -webkit-transform: translate3d(-25px, 0, 0); transform: translate3d(-25px, 0, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideFromLeft') > -1) { sheet += '.block-effects.slideFromLeft { -webkit-animation-name: slideFromLeft; animation-name: slideFromLeft; } '; kf = '@keyframes slideFromLeft { 0% { -webkit-transform: translate3d(-100px, 0, 0); transform: translate3d(-100px, 0, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideFromRightShort') > -1) { sheet += '.block-effects.slideFromRightShort { -webkit-animation-name: slideFromRightShort; animation-name: slideFromRightShort; } '; kf = '@keyframes slideFromRightShort { 0% { -webkit-transform: translate3d(25px, 0, 0); transform: translate3d(25px, 0, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.slideFromRight') > -1) { sheet += '.block-effects.slideFromRight { -webkit-animation-name: slideFromRight; animation-name: slideFromRight; } '; kf = '@keyframes slideFromRight { 0% { -webkit-transform: translate3d(100px, 0, 0); transform: translate3d(100px, 0, 0); visibility: visible; } 100% { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.growFadeInUp') > -1) { sheet += '.block-effects.growFadeInUp { -webkit-animation-name: growFadeInUp; animation-name: growFadeInUp; } '; kf = '@keyframes growFadeInUp { 0% { opacity: 0; -webkit-transform: translate3d(0, 100%, 0) scale(0.5); transform: translate3d(0, 100%, 0) scale(0.5); } 100% { opacity: 1; -webkit-transform: none; transform: none; } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('block-effects.growFadeInUpShort') > -1) { sheet += '.block-effects.growFadeInUpShort { -webkit-animation-name: growFadeInUpShort; animation-name: growFadeInUpShort; } '; kf = '@keyframes growFadeInUpShort { 0% { opacity: 0; -webkit-transform: translate3d(0, 25px, 0) scale(0.9); transform: translate3d(0, 25px, 0) scale(0.9); } 100% { opacity: 1; -webkit-transform: none; transform: none; } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('loadingIcon') > -1) { sheet += '.loadingIcon{ display:inline-block; font-size:0; -webkit-animation: loader-icon-animate 1s infinite linear; animation:loader-icon-animate 1s infinite linear; pointer-events:none; } '; kf = '@keyframes loader-icon-animate { 0% { -webkit-transform:rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform:rotate(359deg); transform: rotate(359deg); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('mediaLoading') > -1) { var mediaLoading = { 'background-color': 'rgba(102,102,102,0.2)', }, cssStr = ''; if (app.site.styles.widgets && app.site.styles.widgets.mediaLoading) { for (var k in app.site.styles.widgets.mediaLoading) { if (mediaLoading[k] || k.indexOf('border') > -1) { mediaLoading[k] = app.site.styles.widgets.mediaLoading[k]; } } } mediaLoading['width'] = '10%'; mediaLoading['height'] = '10%'; mediaLoading['left'] = '45%'; mediaLoading['top'] = '45%'; for (var k in mediaLoading) { cssStr += k + ':' + mediaLoading[k] + ';'; } sheet += '.mediaLoading{ position: absolute; margin: 0 auto; font-size:0; -webkit-animation: mediaLoading 1s infinite linear; animation:mediaLoading 1s infinite linear; pointer-events:none; ' + cssStr + '} '; kf = '@keyframes mediaLoading { 0% { -webkit-transform:scale(1); transform: scale(1); } 80% { -webkit-transform:scale(1.1); transform: scale(1.1); } 100% { -webkit-transform:scale(1); transform: scale(1); } } '; sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } if (checkForWhat.indexOf('taln-l') > -1) { sheet += '.taln-l{text-align:left} '; } if (checkForWhat.indexOf('taln-c') > -1) { sheet += '.taln-c{text-align:center} '; } if (checkForWhat.indexOf('taln-r') > -1) { sheet += '.taln-r{text-align:right} '; } if (checkForWhat.indexOf('taln-l-m') > -1) { addMediaQuery(600, '.taln-l-m', 'text-align:left'); } if (checkForWhat.indexOf('taln-c-m') > -1) { addMediaQuery(600, '.taln-c-m', 'text-align:center'); } if (checkForWhat.indexOf('taln-r-m') > -1) { addMediaQuery(600, '.taln-r-m', 'text-align:right'); } if (checkForWhat.indexOf('inline-left') > -1) { sheet += '.inline-left{ float: left; margin: 0 20px 20px 0; max-width: 50% } '; addMediaQuery(600, '.inline-left', 'float:none; margin: 0; max-width: 100%;'); } if (checkForWhat.indexOf('inline-right') > -1) { sheet += '.inline-right{ float: right; margin: 0 0 20px 20px; max-width: 50% } '; addMediaQuery(600, '.inline-right', 'float:none; margin: 0; max-width: 100%;'); } if (checkForWhat.indexOf('site-search') > -1) { sheet += '.site-search-input:hover{ outline:0; } '; sheet += '.site-search-input{ font-size: 20px; padding: 10px 0; margin:0; border:0; outline:0; border-radius: 0; border-bottom: 1px solid #666; display: block; width: calc(100% - 60px); white-space:normal; background:none; line-height:1; font-family:inherit; -webkit-appearance: none; -moz-appearance: none;} '; } if (checkForWhat.indexOf('block-background-fixed') > -1) { sheet += '.block-background-fixed > .load-media-holder{ position: fixed; height:100%; height: 100vh;} '; } if (checkForWhat.indexOf('form-tbl') > -1) { sheet += '.form-tbl-table{ display: table; } '; sheet += '.form-tbl-row{ display: table-row; } '; sheet += '.form-tbl-cell{ display: table-cell; } '; if (checkForWhat.indexOf('form-tbl-m') > -1) { addMediaQuery(600, '.form-tbl-m-table', 'display: block'); addMediaQuery(600, '.form-tbl-m-row', 'display: block'); addMediaQuery(600, '.form-tbl-m-cell', 'display: block'); } } checkForWhat.forEach(function(row) { if (row === 'grid-stack') { addMediaQuery(600, '.' + row, 'width:auto;display:block'); } else if (row.substring(0, 5) === 'grid-') { var spl = row.substring(5).split('-'), numcols = spl[0] * 1, w = Math.floor((100 / numcols) * 10) / 10 || 100, usew = w + '', ogw = w * 1, minw = 0, splratio = 0, spacing = 0; if (!numcols) { numcols = 1; } if (spl[1]) { for (var gk = 1; gk < spl.length; gk++) { if (spl[gk][0] === 'r') { splratio = spl[gk].substr(1); } else if (spl[gk][0] === 's') { spacing = spl[gk].substr(1); } else if (spl[gk][0] !== 's' && spl[gk][0] !== 'r') { minw = spl[gk] * 1; } } } if (splratio) { // you are assuming split ratio is from full width of container as split ratio is for block content or a two column grid if (spacing) { sheet += '.' + row + '{width:' + (100 * (splratio / 100)) + '%;width:calc(' + (100 * (splratio / 100)) + '% - '+(spacing*0.5)+'px);} '; } else { sheet += '.' + row + '{width:' + (100 * (splratio / 100)) + '%;} '; } if (spacing) { sheet += '.griditem-l-s' + spacing + '{ margin-right:'+(spacing*0.5)+'px; } '; sheet += '.griditem-r-s' + spacing + '{ margin-left:'+(spacing*0.5)+'px; } '; addMediaQuery((minw * 2) || 700, '.griditem-l-s' + spacing, 'margin-right:0'); if (row.indexOf('-ns') < 0) { addMediaQuery((minw * 2) || 700, '.griditem-r-s' + spacing, 'margin-left:0;margin-top:'+spacing+'px;'); } } if (row.indexOf('-ns') < 0) { addMediaQuery((minw * 2) || 700, '.' + row, 'width:100%;display:block;'); } } else if (spl[0] == 'any') {} else if (minw) { var mqw = minw * 1, i = 1, db, p, spacingMargin = ''; //console.log('spacing', spacing, 'numcols', numcols) if (spacing && numcols > 1) { usew = 'calc( ' + w + '% - (' + ((spacing * (numcols - 1)) / numcols) + 'px))'; var breaksat = (mqw * (numcols + 1) - 1); addMediaQuery('+' + breaksat, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n)', 'margin-right:0'); //console.log('breaksat', breaksat, 'max', usew_max); spacingMargin = ';margin:0 ' + spacing + 'px ' + spacing + 'px 0'; sheet += '.' + row + '{' + spacingMargin.substr(1) + '} '; } else { usew = w + '%'; } sheet += '.' + row + '{width:' + usew + spacingMargin + '} '; if (checkForWhat.indexOf('cagridFlexHeight') > -1) { sheet += '.cagridFlexHeight .' + row + '{min-width:' + usew + spacingMargin + '; max-width:' + usew + spacingMargin + ';} '; } while (i < numcols) { if (mqw * i === 100) { db = 'display:block'; } else { db = ''; } p = Math.floor((100 / i) * 10) / 10 || 100; var usew = (mqw * (i + 1) - 1); var usew_max = (mqw * (i + 2) - 1); var cur_num_cols = numcols - (numcols - i); if (cur_num_cols === 1) { usew = '0'; } //console.log('i', i, 'usew', usew, 'usewmax', usew_max, 'spacingmargin', spacingMargin, 'cur num cols', cur_num_cols, 'spacing fix', ((spacing * (cur_num_cols - 1)) / cur_num_cols)) if(!db && spacingMargin) { p = 'calc( ' + p + '% - (' + ((spacing * (cur_num_cols - 1)) / cur_num_cols) + 'px))'; } else { p = p + '%'; } if (db && spacingMargin) { db += 'margin-right: '+spacing+';margin-bottom:' + spacing + 'px;'; } addMediaQuery(usew + ',' + usew_max, '.' + row, 'width:' + p + ';' + db); if (spacingMargin) { var ri = numcols - i; for (var rii = 0; rii < ri; rii++) { addMediaQuery(usew + ',' + usew_max, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + (cur_num_cols) + 'n+0)', 'margin-right:0;'); //console.log('usew', usew + ',' + usew_max, 'num cols', cur_num_cols); addMediaQuery(usew + ',' + usew_max, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-last-child(-n+'+cur_num_cols+')', 'margin-bottom:0;'); //addMediaQuery(usew + ',' + usew_max, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + (numcols - rii) + 'n+1):nth-last-child(-n+' + (numcols - rii) + '),div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + (numcols - rii) + 'n+1):nth-last-child(-n+' + (numcols - rii) + ') ~ .' + row, 'margin-bottom:0'); } } i++; } } else { var widths = { 1200: 33.33, 900: 50, 600: 100 }; var spacingMargin = '', firstBreak = 600; if (spacing) { usew = 'calc( ' + w + '% - (' + ((spacing * (numcols - 1)) / numcols) + 'px))'; sheet += 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n){margin-right:0} '; //addMediaQuery('>100', 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n+1):nth-last-child(-n+' + numcols + '),div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n+1):nth-last-child(-n+' + numcols + ') ~ .' + row, 'margin-bottom: 0'); spacingMargin = ';margin:0 ' + spacing + 'px ' + spacing + 'px 0'; widths[1200] = 'calc( ' + widths[1200] + '% - (' + ((spacing * (3 - 1)) / 3) + 'px))'; widths[900] = 'calc( ' + widths[900] + '% - (' + ((spacing * (3 - 1)) / 3) + 'px))'; } else { usew = w + '%'; widths[1200] = widths[1200] + '%'; widths[900] = widths[900] + '%'; } sheet += '.' + row + '{width:' + usew + spacingMargin + '} '; if (checkForWhat.indexOf('cagridFlexHeight') > -1) { sheet += '.cagridFlexHeight > .' + row + '{min-width:' + usew + spacingMargin + '; max-width:' + usew + spacingMargin + ';} '; } if (ogw < 33) { firstBreak = 1200; // anything greater than 3 cols gets this addMediaQuery(1200, '.' + row, 'width:' + widths[1200] + spacingMargin); if (spacingMargin) { addMediaQuery(1200, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n)', 'margin-right:' + spacing + 'px;'); addMediaQuery(1200, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n)', 'margin-right:0;'); addMediaQuery('901,1200', 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n+1):nth-last-child(-n+3),div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n+1):nth-last-child(-n+3) ~ div[data-spacing="' + spacing + '"] .' + row, 'margin-bottom:0;'); } } if (ogw < 50) { firstBreak = 900; // anything greater than 2 cols gets this addMediaQuery(900, '.' + row, 'width:' + widths[900] + spacingMargin); if (spacingMargin) { addMediaQuery(900, 'div[data-spacing="' + spacing + '"] .' + row, 'margin-bottom:' + spacing + 'px;'); addMediaQuery(900, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n)', 'margin-right:' + spacing + 'px;'); addMediaQuery(900, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n)', 'margin-right:' + spacing + 'px;'); addMediaQuery(900, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n+1):nth-last-child(-n+3),div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n+1):nth-last-child(-n+3) ~ div[data-spacing="' + spacing + '"] .' + row, 'margin-bottom:0;'); addMediaQuery(900, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(2n)', 'margin-right:0'); } } if(spacing){ // two col spacing addMediaQuery('>'+firstBreak, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n+1):nth-last-child(-n+' + numcols + '),div[data-spacing="' + spacing + '"] .' + row + ':nth-child(' + numcols + 'n+1):nth-last-child(-n+' + numcols + ') ~ .' + row, 'margin-bottom: 0'); } if(row.indexOf('-ns') < 0){ var mb = spacingMargin ? ';margin-bottom:' + spacing + 'px;' : ''; if(widths[600] > 50){ mb += ';margin-right:0;'; } addMediaQuery(600, '.' + row, 'width:' + widths[600] + '%;display:block' + mb); if(spacing){ // weird quirks needed to fix the margin addMediaQuery(600, 'div[data-spacing="' + spacing + '"] .' + row, 'margin:0 0 '+spacing+'px 0;'); addMediaQuery(600, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n+1):nth-last-child(-n+3)', 'margin:0 0 '+spacing+'px 0;'); addMediaQuery(600, 'div[data-spacing="' + spacing + '"] .' + row + ':nth-child(3n)', 'margin:0 0 '+spacing+'px 0;'); addMediaQuery(600, 'div[data-spacing="' + spacing + '"] .' + row + ':last-child', 'margin:0;'); } } } } else if (row.substring(0, 3) === 'sp-') { var prts = row.split('-'); sheet += '.' + row + '{position:absolute !important} '; if (prts[1] === 'stack') { addMediaQuery(prts[2], '.' + row, 'position:static !important'); } else if (prts[1] == 'hide') { addMediaQuery(prts[2], '.' + row, 'display:none'); } } else if (row.substring(0, 7) === 'margin-') { var resMargin = { left: '', leftMobile: '', right: '', rightMobile: '' }; row.split('-').forEach(function(part, p) { if (p > 0) { if (part.match('l')) { resMargin.left = 'margin-left: ' + part.replace('l', '') + '%; '; resMargin.leftMobile = 'margin-left: 0; '; } else if (part.match('r')) { resMargin.right = 'margin-right: ' + part.replace('r', '') + '%; '; resMargin.rightMobile = 'margin-right: 0; '; } } }); sheet2 += '.' + row + '{' + resMargin.left + ' ' + resMargin.right + '} '; addMediaQuery(800, '.' + row, resMargin.leftMobile + ' ' + resMargin.rightMobile); } else if (row.substring(0, 9) === 'kenburns-') { var spl = row.split('-'); var kb_config = { speed: (spl[1] * 1) || 100, scale: 1 + '.' + ((spl[2] * 1) || 4), repeat: row.indexOf('-norepeat') < 0 }; if(kb_config.repeat) { sheet += '.' + row + '{ -webkit-animation:' + row + '-animate ' + (kb_config.speed * 2) + 's infinite ease-in-out; -webkit-animation-fill-mode: forwards; animation:' + row + '-animate ' + (kb_config.speed * 2) + 's infinite ease-in-out; animation-fill-mode: forwards; -webkit-transform-origin: 50% 50%; transform-origin: 50% 50%; } '; kf = '@keyframes ' + row + '-animate { 0% { -webkit-transform: scale(1) rotate(0deg); transform: scale(1) rotate(0deg); } 50% { -webkit-transform: scale(' + kb_config.scale + ') rotate(0.1deg); transform: scale(' + kb_config.scale + ') rotate(0.1deg); } 100% { -webkit-transform: scale(1) rotate(0.1deg); transform: scale(1) rotate(0deg); } } '; } else { sheet += '.' + row + '{ -webkit-animation:' + row + '-animate ' + (kb_config.speed) + 's 1 ease-in-out; -webkit-animation-fill-mode: forwards; animation:' + row + '-animate ' + (kb_config.speed) + 's 1 ease-in-out; animation-fill-mode: forwards; -webkit-transform-origin: 50% 50%; transform-origin: 50% 50%; } '; kf = '@keyframes ' + row + '-animate { 0% { -webkit-transform: scale(1) rotate(0deg); transform: scale(1) rotate(0deg); } 100% { -webkit-transform: scale(' + kb_config.scale + ') rotate(0.1deg); transform: scale(' + kb_config.scale + ') rotate(0.1deg); } } '; } sheet += kf + ' ' + kf.replace('@keyframes', '@-webkit-keyframes'); } else if (row.substring(0, 3) === 'pd_' || row.substring(0, 3) === 'mg_') { var spl = row.split('_'), mw = '', pd_string = spl[1] || ''; if (spl.length > 2) { mw = spl[1] * 1; pd_string = spl[2]; } if (mw) { addMediaQuery(mw, '.' + row, bluxClassToCSS(spl[0], pd_string)); } else { sheet += '.' + row + '{' + bluxClassToCSS(spl[0], pd_string) + '} '; } } else if (row.substring(0, 12) === 'block-ratio-') { var spl = row.split('-'); var minHeight = spl[3] ? 'min-height:'+spl[3]+';' : ''; var maxHeight = spl[4] ? 'max-height:'+spl[4]+';' : ''; if(minHeight || maxHeight) { sheet += '.'+row+'{ '+minHeight+maxHeight+' }'; } sheet += '.'+row+':before{ content: ""; display:block; padding-bottom: '+spl[2].replace('_', '.')+'%; box-sizing:border-box;'+minHeight+maxHeight+' }'; sheet += '.'+row+' > .block-holder, .'+row+' > .block-holder > .blockcontainer, .'+row+' > .blockcontainer{ position: absolute; left:0; top:0; bottom:0; right:0 }'; } }); } if (forWhat) { if (forWhat.length) { forWhat.forEach(function(row) { var classString = alpha(row); var classNumber = num(row); if (app.site.styles[classString]) { if (app.site.styles[classString][classNumber]) { sheet += genCSS(app.site.styles[classString][classNumber], specialFlag); } else { sheet += genCSS(app.site.styles[classString], specialFlag); } } if (classString === 'navigation') { if (app.site.navigation[classNumber]) { if (app.site.navigation[classNumber].styles) { sheet += genCSS(app.site.navigation[classNumber].styles, specialFlag); } if (app.site.navigation[classNumber].customElement) { if (app.site.media[app.site.navigation[classNumber].customElement]) { if (app.site.media[app.site.navigation[classNumber].customElement].css) { sheet += app.site.media[app.site.navigation[classNumber].customElement].css; } } } } } else if (classString === 'footer') { if (app.site.footer[classNumber]) { if (app.site.footer[classNumber].styles) { sheet += genCSS(app.site.footer[classNumber].styles, specialFlag); } if (app.site.footer[classNumber].customElement) { if (app.site.media[app.site.footer[classNumber].customElement]) { if (app.site.media[app.site.footer[classNumber].customElement].css) { sheet += app.site.media[app.site.footer[classNumber].customElement].css; } } } } } }); } } else { for (var classString in app.site.styles) { if (classString !== 'globals') { if (app.site.styles[classString].length) { for (var classNumber in app.site.styles[classString]) { sheet += genCSS(app.site.styles[classString][classNumber], specialFlag); } } else { sheet += genCSS(app.site.styles[classString], specialFlag); } } } if (app.site.navigation) { app.site.navigation.forEach(function(nav, navIndex) { if (app.site.navigation[navIndex].styles) { sheet += genCSS(app.site.navigation[navIndex].styles, specialFlag); } }); } else if (app.site.footer) { app.site.footer.forEach(function(nav, navIndex) { if (app.site.footer[navIndex].styles) { sheet += genCSS(app.site.footer[navIndex].styles, specialFlag); } }); } } var w, selector, ar = Object.keys(sheetQueries).sort(function(a, b) { return num(b) - num(a); }); //console.log('ar', ar) ar.forEach(function(w) { if(typeof w === 'number'){ sheetQ += '\n@media all and (max-width: ' + w + 'px){ '; } else if(w.substr(0,1) === '+'){ sheetQ += '\n@media all and (min-width: ' + w.substr(1) + 'px){ '; } else { var spl = w.split(','); if(spl.length < 2){ if(w.substr(0,1) === '>'){ sheetQ += '\n@media all and (min-width: ' + num(w) + 'px){ '; } else { sheetQ += '\n@media all and (max-width: ' + num(w) + 'px){ '; } } else { sheetQ += '\n@media all and (min-width: ' + spl[0] + 'px) and (max-width: ' + spl[1] + 'px){ '; } } for (selector in sheetQueries[w]) { sheetQ += '\n\t' + selector + '{' + sheetQueries[w][selector] + '} '; } sheetQ += '\n} '; }); //console.log(sheetQ); return sheet + sheet2 + sheetQ; }; App.prototype.lookForAllColorsCached = function(color) { var app = this; if(!app.siteObjectColorList){ app.siteObjectColorList = []; app.siteObjectExec(app.site, [], function(type, path, value, parentObject) { if (!value) { value = ''; } if (value && path[path.length - 1] == 'color' || path[path.length - 1] == 'background-color') { app.siteObjectColorList.push(value); } }); } for(var i=0; i
window.innerWidth) { layer.css({ right: '', left: (window.innerWidth - pos.width) + 'px' }); } if (pos.top + pos.height > window.innerHeight) { layer.css({ bottom: '', top: (window.innerHeight - pos.height) + 'px' }); } }, openLayer: function(pos) { if (currentLayer) { UI.removeLayers(); } ['top', 'right', 'bottom', 'left'].forEach(function(side) { if (pos[side] !== 'undefined') { pos[side] += 'px'; } }); var layer = DOM().newOrFind('div', 'caa_layer').class('caa_layer').css({ position: 'fixed' }).css(pos) .html('').appendTo(DOM(document.body)) .on('click', function(e) { if (currentLayer) { currentLayer.noDestroy = true; setTimeout(function() { currentLayer.noDestroy = false; }, 10); } if (currentModal) { // this is necessary to ensure that modal isn't closed when a layer is over a modal currentModal.noDestroy = true; setTimeout(function() { currentModal.noDestroy = false; }, 10); } }); setTimeout(function() { window.currentLayer = layer; UI.fixLayerPosition(layer, pos); }, 10); return layer; }, removeLayers: function() { if(typeof currentLayer.onDestroy === 'function'){ currentLayer.onDestroy(); delete currentLayer.onDestroy; } if (!currentLayer.noDestroy) { window.removeEventListener('touchmove', UI.colorPickerEvents); window.removeEventListener('touchend', UI.colorPickerEvents); window.removeEventListener('mousemove', UI.colorPickerEvents); window.removeEventListener('mouseup', UI.colorPickerEvents); rm('caa_layer'); window.currentLayer = false; } else { if (!currentLayer) { window.currentLayer = false; } } }, closeModal: function() { if (!currentModal.noDestroy) { if (window.currentModal) { var modalRef = DOM().id('caa_modal'); currentModal.animate(currentModal.destroyTo, function(e) { DOM(e.target).remove(); modalRef.remove(); }); } else { DOM().id('caa_modal').remove(); } currentModal = false; } }, openModal: function(from, config) { if(typeof config !== 'object'){ config = {}; } var w = window.innerWidth, h = window.innerHeight; var scaleX = 0, scaleY = 0, transX = 0, transY = 0; if (from) { var pos = from.pos(); scaleX = pos.width / w; scaleY = pos.height / h; transX = (pos.left * 2) + 'px'; transY = (pos.top * 2) + 'px'; } var startPosition = { left: 0, top: 0, width: '100%', height: '100%', transform: 'scale(' + scaleX + ', ' + scaleY + ') translate(' + transX + ', ' + transY + ')' }; var layer = DOM().new('div').id('caa_modal') .class('caa_modal_layer') .css(startPosition) .animate({ transform: 'scale(1, 1) translate(0px, 0px)', opacity: 1 }) .appendTo(DOM(document.body)); if(config['background-color']){ layer.css({ 'background-color': config['background-color'] }); } var content = DOM().new('div') .class('caa_modal') .appendTo(layer) .on('click', function(e) { if (currentModal) { currentModal.noDestroy = true; setTimeout(function() { currentModal.noDestroy = false; }, 10); } }); var doCSS = {}, doCSS_set; ['width', 'min-width', 'max-width', 'height'].forEach(function(prop){ doCSS[prop] = config[prop]; doCSS_set = true; }); if(doCSS_set){ content.css(doCSS); } if(config.dismissable !== false){ DOM().new('button').class('caa_button-delete').appendTo(content).css({ position: 'absolute', right: 0, top: 0, 'z-index': 2 }).on('click', function(e) { UI.closeModal(); }); } layer.destroyTo = startPosition; var cancelModal = function(e) { if (e.type === 'click') { //slow for button animation setTimeout(function() { UI.closeModal(from); }, 10); } else if (e.which == 27) { UI.closeModal(from); } window.removeEventListener('keyup', cancelModal); }; if(config.dismissable !== false){ window.addEventListener('keyup', cancelModal); } setTimeout(function() { window.currentModal = layer; if(config.dismissable === false){ currentModal.noDestroy = true; } }, 10); content.scrollFunc = function(){ content.byClass('camediaload').loadMedia({ viewport: 1, loadEffect: 'none' }); } content.on('scroll', function(){ clearTimeout(content.scrollFuncTimer); content.scrollFuncTimer = setTimeout(content.scrollFunc, 100); }); return content; }, colorPickerEvents: function(e) { e.preventDefault(); var pos = canvasObject.pos(); var mx = e.pageX - pos.pageX, my = e.pageY - pos.pageY, area = 0, h, s, l, a; if (e.type === 'mousedown' || e.type === 'touchstart') { if (mx >= 235) { area = 2; } else if (mx < 235 && my >= 235 && my <= 290) { area = 3; } else if (my < 235) { area = 1; } else { area = 0; } if (area) { window.addEventListener('touchmove', UI.colorPickerEvents); window.addEventListener('touchend', UI.colorPickerEvents); window.addEventListener('mousemove', UI.colorPickerEvents); window.addEventListener('mouseup', UI.colorPickerEvents); if(currentLayer){ currentLayer.noDestroy = true; } canvasObject.eventArea = area; } } else if (e.type === 'mouseup' || e.type === 'touchend') { canvasObject.eventArea = 0; window.removeEventListener('touchmove', UI.colorPickerEvents); window.removeEventListener('touchend', UI.colorPickerEvents); window.removeEventListener('mousemove', UI.colorPickerEvents); window.removeEventListener('mouseup', UI.colorPickerEvents); setTimeout(function() { if(currentLayer){ currentLayer.noDestroy = false; } }, 10); } if (canvasObject.eventArea) { if (canvasObject.h < 0) { canvasObject.h = 0; } if (canvasObject.eventArea === 2) { if (my < 10) { my = 10; } if (my > 370) { my = 370; } var hy = ((my - 10) / 360); canvasObject.h = Math.round(360 * hy); canvasObject.setHue(); canvasObject.setAlpha(); canvasObject.setColor(false); } else if (canvasObject.eventArea === 3) { if (mx < 10) { mx = 10; } if (mx > 230) { mx = 230; } var hx = ((mx - 10) / 220); canvasObject.a = Math.round(((100 * hx) / 100) * 100) / 100; canvasObject.setAlpha(); canvasObject.setColor(false); } else if (canvasObject.eventArea === 1) { if (mx < 10) { mx = 10; } if (mx > 230) { mx = 230; } if (my < 10) { my = 10; } if (my > 230) { my = 230; } l = ((my - 10) / 220); s = ((mx - 10) / 220); canvasObject.l = 100 - Math.round(100 * l); canvasObject.s = Math.round(100 * s); canvasObject.setSL(); canvasObject.setAlpha(); canvasObject.setColor(false); } } }, colorPicker: function(color, cb) { var container = DOM().new('div').css({ position: 'relative' }); window.canvasObject = DOM().new('canvas').id('colorPicker').attr({ width: 300, height: 380 }).on('mousedown touchstart', UI.colorPickerEvents).appendTo(container); var canvas = canvasObject.elements[0]; canvasObject.context = canvas.getContext('2d'); canvasObject.setColorPicker = function(color) { if (color) { var hsla = color2color(color, "hsla").replace(/[^\d,.]+/g, '').split(','); canvasObject.h = hsla[0] || 0; canvasObject.s = hsla[1] || 100; canvasObject.l = hsla[2] || 50; canvasObject.a = hsla[3] || 0; } else { canvasObject.h = -1; canvasObject.s = 100; canvasObject.l = 50; canvasObject.a = 1; } }; canvasObject.setColorPicker(color); canvasObject.hueMarker = DOM().new('div').css({ position: 'absolute', left: 236 + 'px', 'border': '8px solid transparent', 'border-left': '12px solid #666', 'pointer-events': 'none' }).appendTo(container); canvasObject.slMarker = DOM().new('div').css({ position: 'absolute', 'border': '2px solid #666', 'width': '10px', 'height': '10px', 'margin': '-7px 0 0 -7px', 'box-shadow': '0 0 0 1px #fff', 'border-radius': '50%', 'pointer-events': 'none' }).appendTo(container); canvasObject.aMarker = DOM().new('div').css({ position: 'absolute', top: 236 + 'px', 'border': '8px solid transparent', 'border-top': '12px solid #666', 'pointer-events': 'none' }).appendTo(container); canvasObject.htmlContainer = DOM().new('div').css({ position: 'absolute', top: '290px', left: '10px', }).appendTo(container).html(''); canvasObject.input = Inputs.text({}).appendTo(container).css({ position: 'absolute', left: '10px', top: '330px', width: '210px' }).byTag('input').on('input,change', function(e) { canvasObject.setColorPicker(canvasObject.input.val()); canvasObject.setHue(); canvasObject.setSL(); canvasObject.setAlpha(); canvasObject.setColor(true); }).css({margin:0}); var h = 0, y = 10; for (y = 10; y < (canvas.height - 10); y++) { h = y - 10; canvasObject.context.fillStyle = 'hsl(' + h + ', 100%, 50%)'; canvasObject.context.fillRect(240, y, 50, 1); } canvasObject.setHue = function() { var h = canvasObject.h, s = 0, l = 0, x, y, gradient, cache; for (y = 10; y < 230; y++) { l = 100 - ((y / 220) * 100); gradient = canvasObject.context.createLinearGradient(0, 0, 220, 0); gradient.addColorStop(0, 'hsl(' + h + ', 0%, ' + l + '%)'); gradient.addColorStop(1, 'hsl(' + h + ', 100%, ' + l + '%)'); canvasObject.context.fillStyle = gradient; canvasObject.context.fillRect(10, y, 220, 1); } canvasObject.hueMarker.css({ top: (canvasObject.h + 10 - 8) + 'px', }); }; canvasObject.setSL = function() { canvasObject.slMarker.css({ left: (10 + ((canvasObject.s / 100) * 220)) + 'px', top: (10 + (((100 - canvasObject.l) / 100) * 220)) + 'px' }); }; canvasObject.setAlpha = function() { var x = 0, y = 0, i = 0; for (x = 0; x < 22; x++) { for (y = 0; y < 5; y++) { if (i % 2) { canvasObject.context.fillStyle = '#cccccc'; } else { canvasObject.context.fillStyle = '#ffffff'; } canvasObject.context.fillRect(10 + (10 * x), 240 + (10 * y), 10, 10); i++; } } var gradient = canvasObject.context.createLinearGradient(0, 0, 220, 50); gradient.addColorStop(0, 'hsla(' + canvasObject.h + ', ' + canvasObject.s + '%, ' + canvasObject.l + '%, 0)'); gradient.addColorStop(1, 'hsla(' + canvasObject.h + ', ' + canvasObject.s + '%, ' + canvasObject.l + '%, 1)'); canvasObject.context.fillStyle = gradient; canvasObject.context.fillRect(10, 240, 220, 50); canvasObject.aMarker.css({ left: ((220 * canvasObject.a) + 10 - 8) + 'px', }); }; canvasObject.setColor = function(fromInput) { var hsla = 'hsla(' + canvasObject.h + ',' + canvasObject.s + '%,' + canvasObject.l + '%,' + canvasObject.a + ')'; var rgba = color2color(hsla); var hex = color2color(hsla, 'hex'); var html = '
rgba: ' + rgba + '
'; html += '
hsla: ' + hsla + '
'; html += '
hex: ' + hex + '
'; canvasObject.htmlContainer.html(html); var color = rgba; if (canvasObject.a * 1 === 1) { color = hex; } if (canvasObject.h < 0) { color = ''; } if (cb) { cb(color); if (!fromInput) { canvasObject.input.val(color); } } }; canvasObject.setHue(); canvasObject.setSL(); canvasObject.setAlpha(); canvasObject.setColor(false); return container; }, killFocusContent: function() { DOM().byClass('focusContent').remove(); }, focusContent: function(element, stage) { UI.killFocusContent(); var pos1 = element.pos(); var pos2 = stage.pos(); var css = { position: 'absolute', 'background-color': 'rgba(0,0,0,0.5)', top: 0, left: 0, width: '100%', height: 0 }; if (pos1.offsetTop > 0) { css.height = pos1.height + 'px'; DOM().new('div').class('focusContent').css(css).appendTo(stage); } css.top = pos1.top + pos1.height + 'px'; css.height = (pos2.height - (pos1.top + pos1.height)) + 'px'; DOM().new('div').class('focusContent').css(css).appendTo(stage); }, cover: function() { DOM().newOrFind('div', 'caa_cover').class('caa_cover').css({ opacity: 0 }).appendTo(DOM(document.body)).animate({ opacity: 1 }); }, removeCover: function() { var caa_cover = byID('caa_cover'); if (caa_cover) { DOM(caa_cover).animate({ opacity: 0 }, function(e) { DOM(caa_cover).remove(); }); } }, dropZone: function(action){ return DOM().new('div').class('abs-fill caa_clickSecTarget caa_dropZone').on('dragenter', function(e){ DOM(e.target).parent().parent().byClass('caa_dropZone').attr({'data-enabled': '2'}); window.dropZone = true; }).on('dragleave', function(e){ DOM(e.target).parent().parent().byClass('caa_dropZone').attr({'data-enabled': '1'}); delete window.dropZone; }).on('drop', function(e){ e.preventDefault(); DOM(e.target).parent().parent().byClass('caa_dropZone').attr({'data-enabled': '0'}); if(action){ action(e); } }); }, tabs: function(tabs, tabsInto, tabContentInto){ Object.keys(tabs).forEach(function(key) { var tab = tabs[key], addClassTab = tab.selected ? ' caa_rightPanelTabSelected' : ''; tab.tab = DOM().new('div').class('ibb caa_rightPanelTab' + addClassTab) .append(DOM().new('span').css({ display: 'block', 'padding-top': '4px' }).text(tab.title)).appendTo(tabContentInto).attr({ 'data-tab': key }).on('click', function(e) { if (tab.selected) { return false; } else { for (var t in tabs) { if (t === key) { tabs[t].tab.addClass('caa_rightPanelTabSelected'); tabs[t].dom.css({ display: '' }); tabs[t].selected = true; } else { tabs[t].tab.removeClass('caa_rightPanelTabSelected'); tabs[t].dom.css({ display: 'none' }); tabs[t].selected = false; } } } }); if(tab.icon){ UI.Icon(tab.icon, 'tabs').insertFirst(tab.tab); } tab.dom = DOM().new('div').class('caa_tabContent').appendTo(tabsInto).css({ display: 'none' }); if (tab.selected) { tab.dom.css({ display: '' }); } }) return tabs; } }; function filterDesignItems(obj) { if (!obj) { return false; } else { if (obj.removed) { return false; } return true; } } var repeatThrottle = function(func, t) { var throttle = this; this.timer = false; this.func = func; this.t = t; this.run = function ThrottleRun(e) { clearTimeout(throttle.timer); throttle.timer = setTimeout(function ThrottleRunner() { throttle.func(e); }, throttle.t); }; }; var uploadFile = function(app, file, fileName) { var self = this; var formData = new FormData(); formData.append('site_id', app.site.id); formData.append('user_id', app.user.id); formData.append('token', app.user.token); if(!fileName && file.name){ fileName = file.name; } formData.append(fileName, file, fileName); this.completed = function(e) {}; this.progress = function(e) {}; this.on = function(event, func) { this[event] = func; }; this.send = function() { self.xhr.send(formData); }; this.xhr = new XMLHttpRequest(); this.xhr.open('POST', '/__upload', true); this.xhr.onload = function(e) { var response = this.responseText || ''; self.completed(e, response); }; this.xhr.upload.onprogress = function(e) { if (e.lengthComputable) { var percent = Math.round((e.loaded / e.total) * 100); self.progress(e, percent); } }; return this; }; var uploadURL = function(app, url, options) { if (!options) { options = {}; } var self = this; var formData = new FormData(); formData.append('site_id', app.site.id); formData.append('user_id', app.user.id); formData.append('token', app.user.token); formData.append('file_url', url); if (typeof options === 'object') { for (var k in options) { formData.append(k, options[k]); } } this.completed = function(e) {}; this.progress = function(e) {}; this.on = function(event, func) { this[event] = func; }; this.send = function() { self.xhr.send(formData); }; this.xhr = new XMLHttpRequest(); this.xhr.open('POST', '/__upload', true); this.xhr.onload = function(e) { var response = this.responseText || ''; self.completed(e, response); }; this.xhr.upload.onprogress = function(e) { if (e.lengthComputable) { var percent = Math.round((e.loaded / e.total) * 100); self.progress(e, percent); } }; return this; }; var parseCustomCSS = function(input) { var output = { string: '', object: {} }; if (typeof input === 'object') { Object.keys(input).sort().forEach(function(k) { if (k[0] !== '_') { if (input[k]) { if (output.string) { output.string += ';'; } output.string += k + ':' + input[k]; output.object[k] = input[k]; } } }); if (output.string) { output.string = 'style="' + output.string + '"'; } } return output; }; function objectFind(object, path, matchKeys, value, perform, findOnlyOne, foundOne) { if (typeof matchKeys !== 'object') { matchKeys = [matchKeys]; } if (typeof path !== 'object') { path = []; } var objKey, matchKey; if (typeof object === 'object') { for (objKey in object) { var go = false; for (matchKey in matchKeys) { if (typeof matchKeys[matchKey] !== 'object') { if (objKey === matchKeys[matchKey]) { go = true; } } else { if (objKey.indexOf(matchKeys[matchKey]) > -1) { go = true; } } } if (typeof object[objKey] === 'object' && !go) { if(!findOnlyOne || findOnlyOne && !foundOne){ objectFind(object[objKey], path.concat(objKey), matchKeys, value, perform, findOnlyOne, foundOne); } } else { if (go) { if (typeof object[objKey] === 'object') { for (var k in object[objKey]) { if (object[objKey][k] == value || (typeof object[objKey][k] === 'string' && object[objKey][k].indexOf(value) > -1)) { perform(path, object, objKey); foundOne = true; } } } else { if (object[objKey] == value || (typeof object[objKey] === 'string' && object[objKey].indexOf(value) > -1)) { perform(path, object, objKey); foundOne = true; } } } } } } } function getPaddingMargin(value, noDefault) { if (!value || typeof value != 'string') { value = noDefault ? '' : '0'; } var nums = { top: '', right: '', bottom: '', left: '' }; var numspl = value.split(' '); if (numspl.length > 3) { nums.top = numspl[0]; nums.right = numspl[1]; nums.bottom = numspl[2]; nums.left = numspl[3]; } else if (numspl.length > 2) { nums.top = numspl[0]; nums.right = numspl[1]; nums.bottom = numspl[1]; nums.left = numspl[2]; } else if (numspl.length > 1) { nums.top = numspl[0]; nums.right = numspl[1]; nums.bottom = numspl[0]; nums.left = numspl[1]; } else { nums.top = numspl[0]; nums.right = numspl[0]; nums.bottom = numspl[0]; nums.left = numspl[0]; } return nums; } var monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; function giveDate(d, how) { var dateString = ''; dateString = monthNames[d.getMonth()] + ' ' + d.getDate() + ', ' + d.getFullYear(); return dateString; } function optionTextMap(item) { var type = typeof item; if (type === 'string') { return { text: item.capitalizeFirstLetter(), value: item }; } else { return item; } } function optionTextMapPX(item) { if (typeof item == 'object') { return item; } else { return { text: item + 'px', value: item + '' }; } } function toggleLoadEffectTimer() { window.recentlySetLoadEffect = true; setTimeout(function() { window.recentlySetLoadEffect = false; }, 100); } function fixButtonText(button, text) { text = text || ''; if (text.match(/\
/) || text.match(/\
/) || text.match(/\
/) || text.match(/\
/g, '>') .replace(/\<\;br\>\;/g, '
') .replace(/\<\;br\/\>\;/g, '
') .replace(/\<\;br\ \/\>\;/g, '
') .replace(/\<\;strong\>\;/g, '
') .replace(/\<\;\/strong\>\;/g, '
') .replace(/\<\;b\>\;/g, '
') .replace(/\<\;\/b\>\;/g, '
') .replace(/\<\;sup\>\;/g, '
') .replace(/\<\;\/sup\>\;/g, '
'); button.html(buttonText); } } function renderButtonMedia(app, targetButton, button) { if(button.media){ targetButton.text(''); var media = DOM().new('span').css({width: button.mediaWidth || '40px'}).class('ibb middle').appendTo(targetButton); if(button.text){ if(button.mediaPosition === 'right'){ media.css({'margin-left': (button.mediaGap || 10) + 'px'}) } else if(button.mediaPosition === 'left' || !button.mediaPosition){ media.css({'margin-right': (button.mediaGap || 10) + 'px'}) } var text = DOM().new('span').class('ibb middle').text(button.text).appendTo(targetButton); fixButtonText(text, button.text); } app.Media(button.media).appendTo(media); } else { fixButtonText(targetButton, button.text); } return targetButton; } function supFace(styles, s) { var face; try { var style = styles[s]; var fontFamily = style['.text' + s]['font-family'].replace(/\'/g, '') || 'Helvetica', fontWeight = style['.text' + s]['font-weight'] || '', fontStyle = (style['.text' + s]['font-style'] == 'itallic') ? 'Itallic' : '', fontSize = style['.text' + s]['font-size'] || '', fontColor = style['.text' + s].color || ''; if (style['.text' + s]['font-ident']) { var ident = style['.text' + s]['font-ident'].split(':'); if (ident[0] === 'T' && ident[1]) { fontFamily = ident[1]; } } face = fontFamily + ' ' + fontWeight + ' ' + fontStyle + ' ' + fontColor + fontSize; } catch (e) { face = 'Helvetica'; } return face; } function colorIsLight(color) { return colorLuma(color2color(color, 'hex')) > 200; } function colorLuma(c){ var c = c.substring(1); // strip # var rgb = parseInt(c, 16); // convert rrggbb to decimal var r = (rgb >> 16) & 0xff; // extract red var g = (rgb >> 8) & 0xff; // extract green var b = (rgb >> 0) & 0xff; // extract blue var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709 return luma; } function urlHinting(e, into, text, fastList){ var l = 0, ot = text.parent().elements[0].offsetTop * 1, th = text.parent().elements[0].offsetHeight * 1; if (e.type === 'input') { var search = text.val() || ''; fastList.byClass('caa_clickSecTarget').elements.forEach(function(element) { var el = DOM(element); if (!search || el.text().match(search)) { el.css({ display: '' }); l++; } else { el.css({ display: 'none' }); } }); fastList.sizer(l); } else if (e.type === 'focus') { fastList.css({ position: 'absolute', left: 0, right: 0, top: ot + th + 'px', 'box-shadow': '0px 1px 4px #999', 'z-index': 2, 'max-height': 0, 'overflow-x': 'hidden', 'overflow-y': 'auto', 'background-color': '#fff' }).appendTo(into); text.hintsLength = 0; fastList.sizer = function(l) { if (l > 6) { l = 6; } var flh = l * 64; fastList.animate({ 'max-height': flh + 'px' }); setTimeout(function(){ var pos = fastList.pos(); if((pos.top + flh) > window.innerHeight){ fastList.css({ top: (0-th-flh) + 'px', height: flh + 'px' }); } else { fastList.css({top: ot + th + 'px', height: ''}); } }, 250); }; fastList.sizer(fastList.hintsLength); } else if (e.type === 'blur') { fastList.animate({ 'max-height': 0 }); } } function humanPath(path, object){ var str = '', currentObject = object; path.forEach(function(part, p){ var friendly = ''; if(str){ str += ' / '; } if(currentObject){ if(currentObject[part] && typeof currentObject[part] === 'object'){ currentObject = currentObject[part]; if(typeof currentObject.title === 'string'){ friendly = currentObject.title; } else if(typeof currentObject.name === 'string'){ friendly = currentObject.name; } else if(typeof currentObject.label === 'string'){ friendly = currentObject.name; } else if(typeof currentObject._label === 'string'){ friendly = currentObject.name; } else if(typeof currentObject.subtitle === 'string'){ friendly = currentObject.name; } else if(typeof currentObject.body === 'string'){ friendly = currentObject.name; } } else { currentObject = false; } } str += friendly ? (friendly.substr(0, 20)) : ((part || '') + '').capitalizeFirstLetter(); }); return str; } function secondsToMinutes(sec){ var div = sec > 0 ? sec/60 : 0, str = '', parts; if(!div){ return '0 sec'; } parts = (div + '').split('.'); if(parts[0]){ str += parts[0] + 'm' } if(parts[1]){ parts[1] = Math.round(60 * ('0.'+parts[1])); if(str){ str += ' '; } str += parts[1] + 'sec' } return str; } App.prototype.checkWarnings = function() { var app = this, link, icon, checkBillingTrial = function() { if (app.billingInfo) { if (app.billingInfo[app.site.id]) { if (app.billingInfo[app.site.id].owner == app.user.id) { if (!app.billingInfo[app.site.id].subscription || app.billingInfo[app.site.id].subscription === 'trial') { return true; } } } } return false; }, checkBillingTransfer = function() { if (app.billingInfo) { if (app.billingInfo[app.site.id]) { if (app.billingInfo[app.site.id].transfer == app.user.email) { return true; } } } return false; }, checkBillingIssues = function() { return false; }; app.warningHolder = DOM().newOrFind('div', 'caa_warningHolder').css({ 'max-height': 0, overflow: 'hidden' }).html(''); setTimeout(function(){ var header = DOM().byClass('caa_header'); header.exists() ? app.warningHolder.insertAfter(header) : app.warningHolder.insertFirst(app.stage); }, 10); if (app.notification === 'email_confirmed') { link = DOM().new('a').attr({ href: '#' }).text('Dismiss').on('click', function(e) { delete app.notification; app.checkWarnings(); }); icon = UI.Icon('email', 'tabs').css({ 'padding-right': '10px', 'margin-top': '-4px' }); icon.byTag('use').attr({ fill: '#2C7CAE' }); DOM().new('div').class('caa_content caa_acc_warning').css({ 'background-color': '#F1F8FB', }) .append(icon) .append(DOM().new('span').class('ib middle').text(app.user.email + ' confirmed! ').css({ 'padding-right': '10px', 'white-space': 'normal' }).append(link)) .appendTo(app.warningHolder.animate({ 'max-height': '100px' })); return true; } else if (!app.user.email_confirmed) { link = DOM().new('a').attr({ href: '#' }).text('Resend').on('click', function(e) { e.preventDefault(); if (!link.disabled) { link.text('Sending Email...').disabled = true; app.Request({ do: 'request', origin: window.location.protocol + '//' + window.location.host, request: 'confirmEmail' }, function(data) { if (data.email_sent) { link.text('Email Sent!'); } else { link.disabled = false; link.text('Something broke...'); setTimeout(function() { link.text('Resend'); }, 5000); } }); } }); icon = UI.Icon('email', 'tabs').css({ 'padding-right': '10px', 'margin-top': '-4px' }); icon.byTag('use').attr({ fill: '#ec2643' }); DOM().new('div').class('caa_content caa_acc_warning').css({ 'background-color': '#fff9a1', }) .append(icon) .append(DOM().new('span').class('ib middle').text('Please check email to confirm ' + app.user.email + '. ').css({ 'padding-right': '10px', 'white-space': 'normal' }).append(link)) .appendTo(app.warningHolder.animate({ 'max-height': '100px' })); return true; } else if (checkBillingTrial()) { link = DOM().new('a').attr({ href: '#' }).text('Upgrade Now').on('click', function(e) { e.preventDefault(); app.render('/billing/' + app.site.id, false, false); }); icon = UI.Icon('rocket', 'tabs').css({ 'padding-right': '10px' }); icon.byTag('use').attr({ fill: '#2C7CAE' }); DOM().new('div').class('caa_content caa_acc_warning').css({ 'background-color': '#F1F8FB', }) .append(icon) .append(DOM().new('span').class('ib middle').text(app.site.name + ' is using a trial plan. ').css({ 'padding-right': '10px', 'white-space': 'normal' }).append(link)) .appendTo(app.warningHolder.animate({ 'max-height': '100px' })); return true; } else if (checkBillingTransfer()) { link = DOM().new('a').attr({ href: '#' }).text('Accept Transfer').on('click', function(e) { e.preventDefault(); DOM(e.target).text('Accepting...'); app.Request({ do: 'request', request: 'acceptTransfer', siteID: app.site.id }, function(data) { if (!data.success) { DOM(e.target).text('Error! Try later'); } else { window.pendingBillingMessage = DOM().new('div').css({ 'background-color': 'green', color: '#fff' }).class('caa_content caa_padding').text('You are now the owner of ' + app.site.name); delete app.siteBilling; app.render('/billing', false, false); } }); }); icon = UI.Icon('gift', 'tabs').css({ 'padding-right': '10px' }); icon.byTag('use').attr({ fill: '#2C7CAE' }); DOM().new('div').class('caa_content caa_acc_warning').css({ 'background-color': '#E0F9E1', }) .append(icon) .append(DOM().new('span').class('ib middle').text(app.site.name + ' is being offered as a transfer of ownership to you. ').css({ 'padding-right': '10px', 'white-space': 'normal' }).append(link)) .appendTo(app.warningHolder.animate({ 'max-height': '100px' })); return true; } else if (checkBillingIssues()) { link = DOM().new('a').attr({ href: '#' }).text('Update Now').on('click', function(e) { e.preventDefault(); app.render('/billing', false, false); }); icon = UI.Icon('warning', 'tabs').css({ 'padding-right': '10px' }); icon.byTag('use').attr({ fill: '#F13445' }); DOM().new('div').class('caa_content caa_acc_warning').css({ 'background-color': '#FFFA9C', }) .append(icon) .append(DOM().new('span').class('ib middle').text('Please update your payment methods to ensure there is no interruption of service. ').css({ 'padding-right': '10px', 'white-space': 'normal' }).append(link)) .appendTo(app.warningHolder.animate({ 'max-height': '100px' })); return true; } app.setHubBilling(); return false; }; App.prototype.addContent = function() { var app = this; app.stage.html(''); // mark content as the highlighted nav section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.subscribe('content', function onchangeContentMenu() { app.contentMenu(false); }); var content = DOM().new('div').class('caa_content').appendTo(app.stage), searchTimer, addType = 'section'; if (app.parts.length > 3) { addType = 'block'; } else if (app.parts.length > 2) { addType = 'page'; } if (app.parts[1] === 'footer' || app.parts[1] === 'navigation') { addType = app.parts[1]; } if (addType === 'page' || addType === 'block') { content.html('').append(UI.Spinner('24').css({ 'margin': '20px' })); app.getTemplates(function(templates) { content.html(''); var appHeading = DOM().new('div') .class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text(addType === 'page' ? 'Add Page' : 'Add Block')) .insertFirst(app.stage), section = app.parts[1] || 'pages', nextItemIndex = 0, topSection = DOM().new('div').class('caa_content').css({ padding: '10px 10px 0 10px' }).appendTo(content), buttonsHolder = DOM().new('div').class('caa_content').css({ padding: '0 10px' }).appendTo(content), searchHolder = DOM().new('div').class('caa_content').css({ padding: '0 10px' }).appendTo(content), grid = DOM().new('div').class('caa_grid').css({ 'max-width': '1280px' }).appendTo(content), noMansLand = DOM().new('div'), boxes = [], filterTags = [], curSection = '', searchFilter = function(e) { var Search = e.target.value || ''; clearTimeout(searchTimer); searchTimer = setTimeout(function() { var searchAr = Search.split(/\\s */), searchRegex = ''; for (var s in searchAr) { if (searchAr[s]) { if (searchRegex) { searchRegex += '|'; } searchRegex += searchAr[s]; } } var Regex = new RegExp(searchRegex, 'i'); boxes.forEach(function(element, e) { var el = DOM(element), tagMatch = false, hasTags = el.attr('data-tags'), st = 0, hasSec = el.attr('data-section'), go = true; if (curSection !== '__page' && hasSec === '__page'){ go = false; } if (curSection && hasTags.indexOf(curSection + ',') < 1) { go = false; } if (Search && !Regex.test(el.text())) { go = false; console.log('no go serach') } if (addType === 'page' && !curSection && hasSec === 'blux') { go = false; console.log('no go type blux') } if (!go) { el.appendTo(noMansLand); } else { el.appendSort(grid); } }); resize(); }, 200); }, clickSecLink = function(e) { buttonsHolder.byClass('caa_button-default').css({ 'background-color': '', 'border-color': '' }).removeClass('caa_button-default-white-text'); curSection = DOM(e.target).css({ 'background-color': '#1D355D', 'border-color': '#1D355D', }).addClass('caa_button-default-white-text').attr('data-sec'); searchFilter({ target: byID('caa-screen-search') }); }; Inputs.search({ label: 'Find '+(addType === 'page' ? 'Page' : 'Block') }).addClass('ib middle').css({ display: addType === 'page' ? '' : 'none', // serach only on pages addding width: '140px', 'margin-right': '10px' }).appendTo(searchHolder).byTag('input').id('caa-screen-search').on('input,blur', searchFilter); var pages = [], buttons = [], hasButton = {}; if (addType === 'page') { buttons.push({ title: 'Copy Page From This Site', sec: '' }, { title: 'Start With Block Template', sec: 'blux' }) var blankObject = { 'title': 'New ' + section.singular() + ' title', 'body': '', 'items': [] }; Object.keys(app.site.content).forEach(function(sec) { if (Array.isArray(app.site.content[sec])) { app.site.content[sec].forEach(function(page, p) { var add = { title: page.title, description: page.description, section: sec, media: app.site.content[sec][p].media || getFirstMedia(app.site.content[sec][p], '', app.site.media), tags: page.tags || [], type: 'Site ' + sec.capitalizeFirstLetter(), object: JSON.parse(JSON.stringify(page)) }; add.object.url = (page.url || (page.title || 'new page').urlSafe()) + '-copy'; pages.push(add); }); } }); templates.pages.forEach(function(page) { pages.push(page); }); } else { buttons.push({ title: 'All Blocks', sec: '' }) var blankObject = { 'title': '', 'body': '' }; templates.pages.forEach(function(page, i) { if ((page.section === 'blocks' || page.section === 'blux') && i > 0 && page.items && page.items.length) { var tPage = JSON.parse(JSON.stringify(page)); tPage.object = JSON.parse(JSON.stringify(page.items[1] ? page.items[1] : page.items[0])); pages.push(tPage); if (page.tags) { page.tags.filter(function(tag) { return tag; }).forEach(function(tag) { if (!hasButton[tag]) { hasButton[tag] = true; buttons.push({ title: tag.capitalizeFirstLetter(), sec: tag }) } }) } } }); Object.keys(app.site.content).forEach(function(section){ app.site.content[section].forEach(function(page){ if(page.items && page.items.length){ var tPage = JSON.parse(JSON.stringify(page)); tPage.__page = true; tPage.section = '__page'; tPage.tags = ['__page']; tPage.object = JSON.parse(JSON.stringify(page.items)); pages.push(tPage); } }); }) buttons.push({ title: 'Copy All Blocks From a Page', sec: '__page' }) } buttons.forEach(function(button, i) { var cls = i === 0 ? ' caa_button-default-white-text' : ''; DOM().new('button').class('caa_button-default' + cls).css({ 'margin': '0 10px 10px 0', 'background-color': i === 0 ? '#1D355D' : '', 'border-color': i === 0 ? '#1D355D' : '', }).text(button.title).attr({ 'data-sec': button.sec }).appendTo(buttonsHolder).on('click', clickSecLink); }) DOM().new('div').class('blux_labelR').text('Start From Scratch').appendTo(topSection); DOM().new('div').class('caa_griditem_border caa_griditemhover caa_click caa_valignmiddle') .css({ height: '60px', border: '1px solid #cfcfcf', 'background-color': '#f1f8fb', 'text-align': 'center' }) .append(DOM().new('div').class('caa_valignmiddleitem').text('Add Blank ' + addType.capitalizeFirstLetter())) .on('click', function(e) { nextItemIndex = app.site.content[section].length || 0; if (addType === 'page') { app.siteAdd(['content', section], blankObject); setTimeout(function() { app.render('/content/' + section + '/' + nextItemIndex + '/new-' + section.singular() + '-title', false, false); }, 10); } else if (addType === 'block' && app.parts[2]) { app.siteAdd(['content', section, app.parts[2], 'items'], blankObject); setTimeout(function() { app.render(app.pathToURL(['content', section, app.parts[2]]), false, false); }, 10); } }).appendTo(topSection); DOM().new('div').class('blux_labelR').text('Choose A Starting Point').css({ 'margin-top': '20px' }).appendTo(topSection); pages.forEach(function(page, p) { if (page.blux) { page.section = 'blux'; } var box = DOM().new('div').class('caa_griditem').css({ 'border': '1px solid #d4d4d4' }).attr({ 'data-tags': page.tags ? ',' + page.tags.concat(page.section).join(',') + ',' : page.section, 'data-section': page.section || '', 'data-sort-value': pages.length - p }); if (page.media) { if (page.media.src) { page.media.src = page.media.src.replace('http://', '//'); } box.append(app.Media(page.media)); } box.append(DOM().new('div').text(page.title || '').css({ 'font-size': '18px', padding: '20px 10px' })); /*box.append(DOM().new('div').text(page.description || '').css({ padding: '0 10px 10px 10px', 'font-size': '14px' })); box.append(DOM().new('div').text(page.type || '').css({ padding: '0 10px 10px 10px', color: '#999', 'font-size': '12px' })); */ box.append( DOM().new('div').css({ 'border-top': '1px solid #cfcfcf' }) .append( DOM().new('a').class('ibb middle caa_resizePanelButton').css({ width: '50%', 'border-right': '1px solid #cfcfcf', padding: '16px 0' }).text('Preview').on('click', function(e) { var src = DOM(e.target), layer = UI.openModal(src); console.log('obj', page); app.tmp.tmpPreview = addType === 'page' ? page.object : { title: 'Preview', items: page.items }; app.preview('/__key/tmpPreview', layer); }) ) .append( DOM().new('a').class('ibb middle caa_resizePanelButton').css({ width: '50%', padding: '16px 0' }).text('Select').on('click', function(e) { DOM(e.target).attr({ disabled: true }); nextItemIndex = app.site.content[section].length || 0; if (addType === 'page') { app.siteAdd(['content', section], JSON.parse(JSON.stringify(page.object))); setTimeout(function() { app.render('/content/' + section + '/' + nextItemIndex + '/new-' + section.singular() + '-title', false, false); }, 10); } else if (addType === 'block' && app.parts[2]) { if(page.section === '__page'){ if(Array.isArray(page.object)){ var pageBlocks = app.getFromPath(['content', section, app.parts[2], 'items']); page.object.forEach(function(addBlock){ pageBlocks.push(JSON.parse(JSON.stringify(addBlock))) }); app.siteUpdate(['content', section, app.parts[2], 'items'], pageBlocks, true) } setTimeout(function() { app.render(app.pathToURL(['content', section, app.parts[2]]), false, false); }, 10); } else { var widgetID = page.object && page.object.widget && page.object.widget.media ? page.object.widget.media : ''; console.log('widgetID', widgetID); console.log('objet', page.object); console.log('templates', templates); if (widgetID && templates.media[widgetID]) { if (!app.site.media[widgetID]) { app.siteUpdate(['media', widgetID], templates.media[widgetID]); } } app.siteAdd(['content', section, app.parts[2], 'items'], JSON.parse(JSON.stringify(page.object))); setTimeout(function() { app.render(app.pathToURL(['content', section, app.parts[2]]), false, false); }, 10); } } }) ) ); box.appendSort(grid); boxes.push(box); }); searchFilter({ target: byID('caa-screen-search') }) var resize = function(e) { grid.masonry({ childrenSelector: '.caa_griditem', spacing: 10, edges: true, columns: 3 }); }; app.onResize(resize); setTimeout(function() { resize(); DOM().byClass('camediaload').loadMedia(); }, 100); }); } else if (addType === 'navigation' || addType === 'footer') { content.html('').append(UI.Spinner('24').css({ 'margin': '20px' })); app.getTemplates(function(templates) { content.addClass('caa_padding').html(''); var appHeading = DOM().new('div') .class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text('Add ' + (addType.capitalizeFirstLetter()))) .insertFirst(app.stage); DOM().new('div').class('blux_labelR').text('Start From Scratch').appendTo(content); DOM().new('div').class('caa_griditem_border caa_griditemhover caa_click caa_valignmiddle') .css({ height: '40px', border: '1px solid #cfcfcf', 'background-color': '#f1f8fb', 'text-align': 'center' }) .append(DOM().new('div').class('caa_valignmiddleitem').text('Add Blank ' + addType.capitalizeFirstLetter())) .on('click', function(e) { var nextItemIndex = app.site[addType].length; app.siteAdd([addType], { 'items': [], 'styles': {} }); app.render('/' + addType + '/' + nextItemIndex, false, false); }).appendTo(content); DOM().new('div').class('blux_labelR').text('Choose A Template').css({ 'margin-top': '20px' }).appendTo(content); // risky app.site[addType + '2'] = app.site[addType]; app.site[addType] = [{}]; var restoreNavFoot = function() { if (app.site[addType + '2']) { app.site[addType] = app.site[addType + '2']; delete app.site[addType + '2']; } }; templates[addType].forEach(function(item, f) { app.site[addType].push(item.object); var into = DOM().new('div').class('caa_griditem_border caa_griditemhover caa_click').css({ 'margin-bottom': '40px', position: 'relative' }) .append(DOM().new('div').css({ position: 'absolute', left: 0, top: 0, right: 0, bottom: 0, 'pointer-events': 'fill' }).on('click', function(e) { e.stopPropagation(); var nextItemIndex = app.site[addType].length; var repl = new RegExp('.footer' + (f + 1), 'g'), newNode = JSON.parse(JSON.stringify(item.object).replace(repl, '.footer' + app.site.footer.length)); newNode._label = addType.capitalizeFirstLetter() + ' ' + app.site.footer.length; app.siteAdd([addType], newNode); app.render('/' + addType + '/' + nextItemIndex, false, false); })) .appendTo(content); if (addType === 'footer') { var pageDom, frame = app.preview('/__foot', into, { footIndex: f + 1, navIndex: 'disabled', onRenderPreview: function(doc) { doc.find('#page-content').remove(); console.log('foot', doc.byTag('footer')) frame.css({ height: doc.byTag('footer').elements[0].offsetHeight + 'px' }) setTimeout(restoreNavFoot, 100); // fast automatic restore }, customFooterObject: item.object }); } else if (addType === 'navigation') { var frame = app.preview('/__nav', into, { navIndex: f + 1, footIndex: 'disabled', noContent: true, customNavigationObject: item.object }); } }) setTimeout(restoreNavFoot, 1000); // fast automatic restore }); } else if (addType === 'section') { ['blog', 'events', 'jobs', 'news', 'products', 'services', 'projects', 'portfolio', 'people'].forEach(function(section) { var go = true; if (Array.isArray(app.site.content[section])) { if (app.site.content[section].length) { go = false; } } if (go) { DOM().new('div').class('caa_row caa_clickSecTarget') .append(UI.Icon('plus', 'menu3')) .append(DOM().new('div').class('ib middle').css({ 'margin-left': '10px' }).text(section)) .on('click', function(e) { var update = {}; update[section] = [{ 'title': section.singular().capitalizeFirstLetter() + ' Index', 'body': '', 'description': '', 'items': [{ 'title': 'New Block Title', 'body': 'section body', 'styles': {}, 'sources': [ section ], 'sourceConfig': { 'layout': 'tbb' }, 'type': 'masonry' }] }]; app.siteUpdate(['content'], update); app.render('/content/' + section, false, false); }) .appendTo(content); } }); } return this; }; App.prototype.billing = function() { var app = this, subSections = ['Sites', 'Payment Methods', 'Billing History'], billingSite = {}; DOM().id('caa_mainNavItemBar').css({ opacity: 0 }); app.stage.html('').append(DOM().new('div').class('caa_content caa_padding').text('Loading billing information...')); app.listeners.billingInfo = function(data) { if (data.error) { app.stage.text(data.error); } else { app.stripe_publish = data.stripe_publish; if (data.cards) { app.user.cards = data.cards; } if (data.config) { app.billingConfig = data.config; } if (data.billing) { app.billingInfo = data.billing; app.sites.forEach(function(site) { if (site.owner === app.user.id) { if (data.billing[site.id]) { site.billing = data.billing[site.id]; if (site.billing.history) { site.billing.history.reverse(); } site.subscriptionName = ''; if (site.billing.subscription) { if (app.billingConfig.subscriptions[site.billing.subscription]) { site.subscriptionName = app.billingConfig.subscriptions[site.billing.subscription].name; } } } if (site.id === app.parts[1]) { billingSite = site; } } }); } initBillingScreen(data); } }; app.send({ do: 'billingInfo' }); var initBillingScreen = function(billingInfo) { app.stage.html(''); if (window.pendingBillingMessage) { window.pendingBillingMessage.appendTo(app.stage); delete window.pendingBillingMessage; } var moreText = '', appHeading = DOM().new('div') .class('caa_content caa_header'); if (billingSite.id) { appHeading.append(UI.Icon('left', 'head').on('click', function(e) { app.render('/billing', false, false); }).css({ 'margin-right': '10px' })); appHeading.append(DOM().new('img').class('middle').attr({ src: billingSite.favicon || '' }).css({ 'width': '30px', height: '30px', 'padding': '0 10px 0 0' })); moreText = ' for ' + billingSite.name; } appHeading .append(DOM().new('div').class('caa_heading ib middle').text('Billing' + moreText)) .appendTo(app.stage); if (billingSite.id) { app.billingSite(billingSite); } else { var box = DOM().new('div').class('caa_content'); subSections.forEach(function(subSection, s) { var sec = subSection.toString().toLowerCase().replace(' ', '-'); var title = DOM().new('div').id('settings' + sec).class('caa_sectionBar').append(DOM().new('span').text(subSection)).css({ position: 'relative' }).appendTo(box).on('click', function(e) { if (title.expanded) { title.byTag('p').animate({ 'max-height': 0, padding: 0 }); title.byTag('use').animate({ fill: '' }); title.byTag('use').attr({ 'xlink:href': '#icon-plus' }); title.expanded = false; } else { title.byTag('p').animate({ 'max-height': '100px', padding: '10px 0' }); title.byTag('use').animate({ fill: '#26A4DD' }); title.byTag('use').attr({ 'xlink:href': '#icon-minus' }); title.expanded = true; } }); title.expanded = false; DOM().new('p').css({ padding: 0, margin: 0, 'max-height': 0, overflow: 'hidden', 'text-transform': 'none' }).appendTo(title); UI.Icon('plus', 'help').appendTo(title).css({ position: 'absolute', 'right': '16px', top: '4px' }); var secHolder = DOM().new('div').class('caa_padding').css({ padding: '16px 16px 32px 16px', position: 'relative' }).appendTo(box); switch (sec) { case 'sites': app.billingSites(title, secHolder); break; case 'payment-methods': app.billingPaymentMethods(title, secHolder); break; case 'billing-history': app.billingHistory(title, secHolder); break; } }); box.appendTo(app.stage); } }; }; App.prototype.billingSites = function(title, secHolder) { title.byTag('p').html('This is the list of sites that you own and are responsible for payment on. Other sites that you are a collaborator on will appear in the sites list in the main menu. You may transfer a site to another user at any time to take over billing responsibility.'); var app = this, updateSites = function() { var account = userAccountBalance(app.user, app.billingInfo); secHolder.html(''); var siteHolder = DOM().new('div').css({ 'white-space': 'nowrap', 'max-width': '100%', 'overflow-y': 'auto' }).appendTo(secHolder); if (app.sites) { var numSites = 0; app.sites.filter(function(site){ return site.owner === app.user.id }).forEach(function(site) { numSites++; app.billingInfo[site.id].name = site.name; var subscription = 'Free Trial', balanceDue = '', discounts = ''; if (!site.billing.card) { site.billing.card = '__nocard'; } if (!account.balances[site.billing.card]) { account.balances[site.billing.card] = {}; if (!account.balances[site.billing.card][site.id]) { account.balances[site.billing.card][site.id] = 0; } } if (account.balances[site.billing.card][site.id] > 0) { balanceDue = 'Payment Due: ' + displayNumber(account.balances[site.billing.card][site.id] / 100, 'USD'); } else if (account.balances[site.billing.card][site.id] < 0) { balanceDue = 'No Payment Due, credit of ' + displayNumber(account.balances[site.billing.card][site.id] / 100, 'USD'); } else { balanceDue = 'No Payment Due'; } if (site.billing.subscription_discount) { if (app.billingConfig.discounts[site.billing.subscription_discount]) { if (discounts) { discounts += ', '; } discounts += app.billingConfig.discounts[site.billing.subscription_discount].name; } } if (discounts) { discounts = 'Discounts: ' + discounts; } DOM().new('div').class('ib top caa_box caa_box_hover caa_click').css({ width: '180px', // height: '140px', padding: '10px', 'margin': '0 10px 0 0' }) .append( DOM().new('div').css({ overflow: 'hidden' }) .append(DOM().new('img').class('middle').attr({ src: site.favicon || '' }).css({ 'width': '30px', height: '30px', 'padding': '0 10px 0 0' })) .append(DOM().new('span').class('ib middle').css({ 'white-space': 'normal' }).text(site.name)) ) .append( DOM().new('div').css({ 'white-space': 'normal' }).css({ 'padding-top': '10px' }) .append(DOM().new('div').text(site.subscriptionName || 'No Subscription')) .append(DOM().new('div').css({ 'font-size': '12px', 'margin-top': '8px' }).append(app.user.cards[site.billing.card] ? showCardDOM(app.user.cards[site.billing.card]) : DOM().new('span').text('No Payment Method'))) .append(DOM().new('div').text(balanceDue)) .append(DOM().new('div').text(discounts)) ) .on('click', function(e) { app.render('/billing/' + site.id, false, false); }) .appendTo(siteHolder); }); app.sites.filter(function(site){ return site.owner !== app.user.id }).forEach(function(site) { numSites++; DOM().new('div').class('ib top caa_box caa_box_hover caa_click').css({ width: '180px', // height: '140px', padding: '10px', opacity: 0.75, 'margin': '0 10px 0 0' }) .append( DOM().new('div').css({ overflow: 'hidden' }) .append(DOM().new('img').class('middle').attr({ src: site.favicon || '' }).css({ 'width': '30px', height: '30px', 'padding': '0 10px 0 0' })) .append(DOM().new('span').class('ib middle').css({ 'white-space': 'normal' }).html( '
' + (site.name || '') + '
' + '
Only the owner of this site can manage billing information.' + '
Current Owner:
' + (app.billingInfo[site.id].ownerName || '') + ' ' + (app.billingInfo[site.id].ownerEmail || '') )) ) .appendTo(siteHolder); }); title.byTag('span').text(numSites + ' Sites'); } }; app.listeners.getSites = function() { updateSites(); app.listeners.getSites2(); // executes it on payment history }; if (app.sites.length) { updateSites(); } }; App.prototype.billingPaymentMethods = function(title, secHolder) { var app = this; title.byTag('p').html('Add one or multiple credit cards to pay your invoices. You may assign your sites to be paid with whichever card you prefer. You will only be billed once per month per card and only on cards associated with paid site subscriptions.'); var renderPaymentMethods = function() { secHolder.html(''); var account = userAccountBalance(app.user, app.billingInfo); var cards = {}; if (app.user.cards) { for (var k in app.user.cards) { if (k) { cards[k] = app.user.cards[k]; } } } if (account.paymentsDue.__nocard) { if (account.paymentsDue.__nocard > 0) { DOM().new('div') .css({ 'padding': '8px', 'background-color': 'orange' }) .text('You have a balance of ' + displayNumber(account.paymentsDue.__nocard / 100, 'USD') + ' due for sites that are not assigned to an active card. Please ensure all sites with a subscription have an active card assigned and all balances are paid in order to avoid any disruption of service to your sites.') .appendTo(secHolder); } } Object.keys(cards).forEach(function(cardID) { var cardDOM = showCardDOM(cards[cardID]), balance = (account.balances[cardID]) ? account.paymentsDue[cardID] || 0 : 0, message = ''; if (balance > 0) { message = 'A payment of ' + displayNumber(balance / 100, 'USD') + ' is due.'; } else if (balance < 0) { message = 'There is a ' + displayNumber(Math.abs(balance) / 100, 'USD') + ' credit for this account. No payment is due at this time.'; } else { message = 'No payment is due at this time.'; } var editCard = DOM().new('div').css({ 'max-height': 0, overflow: 'hidden' }); var row = DOM().new('div').class('caa_row caa_row_hover').appendTo(secHolder).css({ 'margin-bottom': '10px' }) .append( DOM().new('div').class('ib middle') .append(cardDOM) .append(DOM().new('i').text(message)) .append(editCard) ) .on('click', function(e) { editCard.html(''); if (editCard.expanded) { editCard.expanded = false; editCard.animate({ 'max-height': '0' }); } else { editCard.expanded = true; if (account.balances[cardID]) { for (var siteID in account.balances[cardID]) { if (siteID !== 'amount') { DOM().new('div').text(displayNumber(account.balances[cardID][siteID] / 100, 'USD') + ' ' + (app.billingInfo[siteID].name || siteID)).appendTo(editCard); } } } editCard.animate({ 'max-height': '500px' }); } }); if (balance > 0) { row.append(DOM().new('button').id('pay-card-' + cardID).class('caa_button-default').css({ float: 'right' }).text('Pay ' + displayNumber(balance / 100, 'USD')).on('click', function(e) { e.stopPropagation(); DOM(e.target).attr({ disabled: true }).text('Attemping Payment...'); app.send({ do: 'billingInfo', makePayment: cardID, amount: balance }); })); } }); var addPaymentMethod = DOM().new('form') .append( DOM().new('input').id('caa-add-payment-method-submit').class('caa_button-default').css({ 'padding-left': '4px' }).attr({ type: 'submit', value: 'Add Credit Card' }) ).on('submit', function(e) { e.preventDefault(); if (addPaymentMethod.expanded) { for (var k in addPaymentMethod.inputs) { if (addPaymentMethod.inputs[k].validate) { addPaymentMethod.inputs[k].validate(); } } // proceed DOM().id('caa-add-payment-method-submit').attr({ disabled: true }).val('Adding Card...'); Stripe.card.createToken(addPaymentMethod.elements[0], addNewCard); } else { addPaymentMethod.expanded = true; if (app.stripe_publish) { loadScript('https://js.stripe.com/v2/', function(e) { addPaymentMethod.inputs = {}; var years = [], accepted = ['visa', 'mastercard', 'americanexpress', 'jcb', 'discover', 'dinersclub']; accepted.forEach(function(cardBrand) { DOM().new('img').class('ib middle').css({ margin: '0 10px 10px 0' }).attr({ src: '//cdn.blux.com/images/cards/' + cardBrand + '.svg' }).css({ width: '50px' }).appendTo(addPaymentMethod); }); for (var i = 0; i < 20; i++) { years.push(new Date().getFullYear() + i); } [ [{ label: 'Name on Card', input: { type: 'text', size: 26, 'data-stripe': 'name' }, validate: function() { var input = addPaymentMethod.find('input[data-stripe="name"]'); var color = 'green', valid = (input.val() || '').length > 2; if (!valid) { color = 'red'; } input.css({ 'border-color': color }); } }], [{ label: 'Card Number', input: { type: 'text', size: 26, 'data-stripe': 'number' }, validate: function() { var input = addPaymentMethod.find('input[data-stripe="number"]'); var color = 'green', valid = Stripe.validateCardNumber(input.val(), '01'); if (!valid) { color = 'red'; } input.css({ 'border-color': color }); var type = Stripe.cardType(input.val()); if (type && type !== 'Unknown') { DOM().newOrFind('img', 'card-brand-image').class('ib middle').attr({ src: '//cdn.blux.com/images/cards/' + type.toLowerCase().replace(/\ /g, '') + '.svg' }).css({ width: '50px', 'margin-left': '10px' }).appendIf('insertAfter', input); } else { DOM().id('card-brand-image').remove(); } } }], [{ label: 'Month', options: [{ text: 'Jan - 01', value: '01' }, { text: 'Feb - 02', value: '02' }, { text: 'Mar - 03', value: '03' }, { text: 'Apr - 04', value: '04' }, { text: 'May - 05', value: '05' }, { text: 'Jun - 06', value: '06' }, { text: 'Jul - 07', value: '07' }, { text: 'Aug - 08', value: '08' }, { text: 'Sep - 09', value: '09' }, { text: 'Oct - 10', value: '10' }, { text: 'Nov - 11', value: '11' }, { text: 'Dec - 12', value: '12' }], input: { 'data-stripe': 'exp_month' } }, { label: 'Year', options: years, input: { 'data-stripe': 'exp_year' } }, { label: 'CVC Code', input: { type: 'text', size: 8.5, 'data-stripe': 'cvc' }, validate: function() { var input = addPaymentMethod.find('input[data-stripe="cvc"]'); var color = 'green', valid = Stripe.validateCVC(input.val()); if (!valid) { color = 'red'; } input.css({ 'border-color': color }); } }] ].forEach(function(inputs) { var dom = DOM().new('div').css({ 'margin-bottom': '10px' }).appendTo(addPaymentMethod); inputs.forEach(function(row) { var input, inputTarget; row.input.label = row.label; if (row.options) { row.input.options = row.options; input = Inputs.options(row.input); inputTarget = input.byTag('select'); } else { input = Inputs.text(row.input).css({ margin: '18px 0 -3px 0' }); inputTarget = input.byTag('input'); } dom.append( DOM().new('div').class('ib middle caa_panelInputLabel').css({ padding: '0 10px 10px 0', width: (row.input.size * 10) + 'px' }).append(input) ); inputTarget.on('input change', function(e) { if (row.validate) { row.validate(); } }); if (row.input['data-stripe']) { inputTarget.attr({ 'data-stripe': row.input['data-stripe'] }); } addPaymentMethod.inputs[row.input['data-stripe']] = row; }); }); DOM().id('caa-add-payment-method-submit').appendTo(addPaymentMethod); DOM().id('caa-add-payment-messages').css({ 'margin-top': '20px', 'font-style': 'italic' }).html('We do not store your credit card information. We send this information directly to
stripe.com
to safely and securely store your payment information for future automatic payments'); Stripe.setPublishableKey(app.stripe_publish); }); } else { addPaymentMethod.html('We are unable to accept new cards right now. Please try again in a few minutes'); } } return false; }).appendTo(secHolder); DOM().new('div').id('caa-add-payment-messages').appendTo(secHolder); }; app.listeners.updatePaymentMethods = function(data) { if (data.error) { app.stage.text(data.error); } else { if (data.cards) { app.user.cards = data.cards; } renderPaymentMethods(); } }; renderPaymentMethods(); app.listeners.makePayment = function(data) { if (data.error) { DOM().new('div').css({ 'color': 'DarkRed' }).class('caa_padding').text(data.error).insertAfter(subscriptionTitle || DOM().id('settingspayment-methods')); DOM().id('pay-card-' + cardID).text('Failed'); } else { app.render(app.AppURL, false, true); setTimeout(function() { DOM().new('div').css({ 'background-color': 'green', color: '#fff' }).class('caa_padding').text('Payment successful! Thank you!').insertAfter(subscriptionTitle || DOM().id('settingspayment-methods')); }, 1000); } }; var addNewCard = function(status, response) { DOM().id('caa-add-payment-method-submit').attr({ disabled: true }); if (response.error) { // Show the errors on the form DOM().id('caa-add-payment-method-submit').attr({ disabled: false }).val('Add Card'); DOM().id('caa-add-payment-messages').css({ color: 'red' }).text('Error: ' + response.error.message); } else { // response contains id and card, which contains additional card details var token = response.id; DOM().id('caa-add-payment-messages').css({ color: '' }).text(''); app.send({ do: 'billingInfo', updatePaymentMethods: { add: token } }); } }; }; App.prototype.billingHistory = function(title, secHolder) { title.byTag('p').html('View upcoming, current and past invoices and payments. For a more detailed look you can select a site at the top to view the history for a single site.'); var app = this, siteNames = {}, updateSites = function() { app.sites.forEach(function(site) { siteNames[site.id] = site.name || 'No Name Set'; }); secHolder.html(''); var siteHolder = DOM().new('div').appendTo(secHolder); var account = userAccountBalance(app.user, app.billingInfo); if (!account.payments.length) { DOM().new('i').text('Billing history will be available as soon as you upgrade your site to a paid plan.').appendTo(siteHolder); } else { var table = DOM().new('table').class('caa_tbl').appendTo(siteHolder) .append( DOM().new('thead') .append( DOM().new('tr') .append(DOM().new('th').text('Date')) .append(DOM().new('th').text('Transaction Name').css({ width: '100%' })) .append(DOM().new('th').text('Amount')) ) ); account.payments.forEach(function(transaction) { var transactionDetail = DOM().new('td').class('caa_row-border'); var row = DOM().new('tr').css({ 'line-height': '200%' }).class('caa_row_hover caa_click').on('click', function(e) { if (transactionDetail.expanded) { transactionDetail.expanded = false; domItems.css({ display: 'none' }); } else { transactionDetail.expanded = true; domItems.css({ display: '' }); } }) .append(DOM().new('td').css({ 'white-space': 'nowrap' }).class('caa_row-border').text(displayDate(parseAnyDate(transaction.date)))) .append(transactionDetail) .append(DOM().new('td').css({ 'white-space': 'nowrap' }).class('caa_row-border').text(displayNumber(transaction.credit / 100, 'USD', true))) .insertFirst(table), domItems = DOM().new('div').css({ display: 'none' }), form = DOM().new('form').on('click', function(e) { e.stopPropagation(); }).on('submit', function(e) { e.preventDefault(); form.byClass('inlinemessages').remove(); if (!form.toggled) { form.toggled = true; Inputs.text({ type: 'text', label: 'Company', value: app.user.company || app.user.name || '' }).insertFirst(form); Inputs.text({ type: 'email', label: 'Email Address', value: app.user.email || '' }).insertFirst(form); form.byTag('button').text('Send Email') } else { form.attr({ disabled: true }).byTag('button').text('Email This'); var email = DOM(form.byTag('input').elements[0]).val() || '', company = DOM(form.byTag('input').elements[1]).val() || '', emailGood = (email.match(/\@/) && email.match(/\./) && email.length > 5); if (emailGood) { app.Request({ do: 'request', request: 'emailTransaction', type: transaction.type, title: transaction.invoice ? transaction.invoice.title || '' : transaction.credit.title || '', items: transaction.invoice ? transaction.invoice.items || [] : [], date: displayDate(transaction.date), cardInfo: app.user.cards[transaction.card] ? app.user.cards[transaction.card].last4 || '' : '', company: company, amount: transaction.credit ? displayNumber(transaction.credit / 100, 'USD', true) : displayNumber(transaction.debit / 100, 'USD', true), email: email }, function(data) { form.attr({ disabled: false }); DOM().new('div').class('inlinemessages').css({ color: 'green' }).addClass('caa_padding').text('An email was sent with a copy of this transaction').appendTo(form); }); } else { form.attr({ disabled: false }); DOM().new('div').class('inlinemessages').css({ color: 'red' }).addClass('caa_padding').text('That is not a vaild address').appendTo(form); } } }).append(DOM().new('button').class('caa_button-default').text('Email This')); if (transaction.type === 'invoice') { var color = '', upcomingText = '', upcoming = (mathDate(parseAnyDate(getFirstOfMonth(transaction.date))) > mathDate(parseAnyDate(getFirstOfMonth(new Date())))); if (upcoming) { color = '#999'; upcomingText = '(Upcoming) '; } if (transaction.invoice.items) { transaction.invoice.items.forEach(function(item) { DOM().new('div').text(item.name + ' @ ' + displayNumber(item.amount / 100, 'USD')).appendTo(domItems); }); } transactionDetail.css({ color: color }) .append(DOM().new('div').text(upcomingText + transaction.invoice.title)); } else if (transaction.type === 'payment') { var cardInfo = app.user.cards[transaction.card] ? showCardLine(app.user.cards[transaction.card]) : 'Card Info Not Retained/Previous Owner'; transactionDetail .append(DOM().new('div').text(siteNames[transaction.site] + ' via ' + cardInfo)); } domItems.append(form); transactionDetail.append(domItems); }); } }; app.listeners.getSites2 = updateSites; if (app.sites.length) { updateSites(); } }; App.prototype.billingSite = function(site) { var app = this; app.billingInfo[site.id].name = site.name; var content = DOM().new('div').class('caa_content').appendTo(app.stage); var subscription = DOM().new('div').appendTo(content).css({ 'margin': '20px 0' }), subscriptionTitle = DOM().new('div').id('subscriptionTitle').class('caa_sectionBar').text('Plan Selection').appendTo(subscription), hostingDescription = DOM().new('div').id('subscriptionTitle').class('caa_padding').text('Blux uses Amazon Web Services for unlimited scale, enterprise ready, high-availability, and high-performance website hosting.').appendTo(subscription), subscriptionHolder = DOM().new('div').class('caa_padding').appendTo(subscription), discountForm = DOM().new('div').class('caa_padding').append(DOM().new('form') .append( Inputs.text({ type: 'text', value: '', label: 'Enter Promo Code', }).addClass('ibb middle') ) .append(DOM().new('input').class('caa_button-default').attr({ type: 'submit' }).val('Apply')) .on('submit', function(e) { e.preventDefault(); discountForm.byTag('input').attr({disabled: true}); discountForm.byClass('blux-error').remove(); app.Request({ do: 'request', request: 'discountCode', siteID: site.id, siteName: site.name, code: discountForm.byTag('input').val() }, function(data) { if(data.success){ discountForm.html('Promo Code Accepted: '+data.description); subscriptionHolder.html(''); } else { discountForm.byTag('input').attr({disabled: false}); DOM().new('div').class('blux-error').css({color: 'red'}).text('That code was not accepted').appendTo(discountForm); } console.log('got back', data); }); })).appendTo(subscription), account = DOM().new('div').appendTo(content).css({ 'margin': '20px 0' }), cardsTitle = DOM().new('div').class('caa_sectionBar').text('Payment Method').appendTo(account), cardsHolder = DOM().new('div').class('caa_padding').appendTo(account), transfer = DOM().new('div').appendTo(content).css({ 'margin': '20px 0' }), transferTitle = DOM().new('div').class('caa_sectionBar').text('Site Transfer').appendTo(transfer), transferHolder = DOM().new('div').class('caa_padding').appendTo(transfer), history = DOM().new('div').appendTo(content).css({ }), historyTitle = DOM().new('div').class('caa_sectionBar').text('Billing History').appendTo(history), historyHolder = DOM().new('div').appendTo(history), deleteSite = DOM().new('div').appendTo(content).css({ }), deleteSiteTitle = DOM().new('div').class('caa_sectionBar').text('Delete Site').appendTo(history), deleteSiteHolder = DOM().new('div').class('caa_padding').appendTo(history), renderSubscriptions = function() { subscriptionHolder.html(''); if (site.billing.subscription === 'tryout' || site.billing.subscription === 'hookup') { DOM().new('div').css({'font-weight': 'bold', 'font-size': '18', padding: '10px', 'background-color': '#EBCC8A', 'margin-bottom': '20px'}).text('This site is currently on a special subscription that will expire on ' + displayDate(site.billing.subscription_expires)).appendTo(subscriptionHolder); } app.billingConfig.subscriptions.base.sub1 = 'A great choice for starter sites'; app.billingConfig.subscriptions.base.sub2 = '$5 per month'; app.billingConfig.subscriptions.base.sub3 = '$1 per gigabyte of bandwidth'; app.billingConfig.subscriptions.base.sub4 = '$1 per gigabyte of storage'; app.billingConfig.subscriptions.base.sub5 = '
Online Support
'; app.billingConfig.subscriptions['199'].sub1 = 'A pro solution for agencies and clients'; app.billingConfig.subscriptions['199'].sub2 = '$199 per month'; app.billingConfig.subscriptions['199'].sub3 = 'Unlimited bandwidth included'; app.billingConfig.subscriptions['199'].sub4 = 'Unlimited storage included'; app.billingConfig.subscriptions['199'].sub5 = 'Phone, email & developer support'; Object.keys(app.billingConfig.subscriptions).sort(function(a, b) { return app.billingConfig.subscriptions[a].amount - app.billingConfig.subscriptions[b].amount; }).forEach(function(subscriptionID) { var checked = ((site.billing.subscription_next || site.billing.subscription || 'trial') === subscriptionID), checkedNext = ((site.billing.subscription_next) === subscriptionID); if (app.billingConfig.subscriptions[subscriptionID].amount > 0) { var selOrUp = checked ? 'Selected' : 'Upgrade', bclass = 'caa_button-default'; if (app.billingConfig.subscriptions[site.billing.subscription].amount && selOrUp === 'Upgrade') { bclass = 'caa_button-big caa_button-blue'; } if (app.billingConfig.subscriptions[site.billing.subscription_next || site.billing.subscription].amount > app.billingConfig.subscriptions[subscriptionID].amount) { bclass = 'caa_button-default'; selOrUp = 'Downgrade'; } var planTitle = DOM().new('div').css({ 'font-size': '24px' }).append(DOM().new('span').class('ib middle').text(app.billingConfig.subscriptions[subscriptionID].name)); var row = DOM().new('div').class('ibb middle caa_box').css({ width: '300px', 'max-width': 'calc(100% - 12px)', //height:'200px', margin: '0 10px 10px 0', 'text-align': 'center', padding: '20px 10px' }) .append(planTitle) .append(DOM().new('div').css({ 'font-size': '12px', 'padding': '16px 0' }).text(app.billingConfig.subscriptions[subscriptionID].sub1)) .append(DOM().new('div').css({ 'font-size': '14px', 'padding': '16px 0', 'border-bottom': '1px solid #EEEEEE' }).text(app.billingConfig.subscriptions[subscriptionID].sub3)) .append(DOM().new('div').css({ 'font-size': '14px', 'padding': '16px 0', 'border-bottom': '1px solid #EEEEEE' }).text(app.billingConfig.subscriptions[subscriptionID].sub4)) .append(DOM().new('div').css({ 'font-size': '14px', 'padding': '16px 0' }).html(app.billingConfig.subscriptions[subscriptionID].sub5)) .append(DOM().new('div').css({ 'font-size': '18px', 'margin': '16px 0' }).text(app.billingConfig.subscriptions[subscriptionID].sub2)) .append(DOM().new('button').class(bclass).text(selOrUp).on('click', function(e) { if (!site.billing.subscription_next && site.billing.subscription === subscriptionID) { return false; } if (site.billing.subscription && site.billing.subscription_started) { changePlan(e, subscriptionID); } else { DOM(e.target).text('Loading...'); setTimeout(function() { DOM(e.target).text(selOrUp); }, 2000); startPlan(e, subscriptionID); } })) .appendTo(subscriptionHolder); if (checked) { UI.Icon('check').css({ 'margin-right': '10px' }).insertFirst(planTitle); row.byTag('p').css({ 'margin-left': '10px' }); } else { row.byTag('p').css({ 'margin-left': '42px' }); } if (checkedNext) { DOM().new('div').css({ 'background-color': 'orange', 'margin-top': '10px', padding: '10px' }).text('You will be changed to this plan starting on ' + displayDate(parseAnyDate(site.billing.subscription_next_date))).appendTo(row); } } }); if(app.billingInfo[site.id].currentPromoCode) { discountForm.html(''); } }, renderHistory = function() { historyHolder.html(''); var go = false; if (site.billing.history) { if (site.billing.history.length) { go = true; site.billing.history.forEach(function(history) { DOM().new('div').class('caa_row').text(displayDate(history.date) + ': ' + history.description).appendTo(historyHolder); }); } } if (!go) { DOM().new('i').class('caa_padding').css({ display: 'block', 'font-size': '14px' }).text('No billing history to date.').appendTo(historyHolder); } }, stripeCheckout = function(subscriptionID) { loadScript('https://checkout.stripe.com/checkout.js', function(e) { e.preventDefault(); var handler = StripeCheckout.configure({ key: app.stripe_publish, image: 'https://app.blux.com/favicon-194x194.png', locale: 'auto', currency: 'USD', panelLabel: 'Subscribe', zipCode: true, email: app.user.email, // bitcoin: true, // we cannot accept bitcoin because it doesn't allow for subscriptions for now token: function(token) { app.send({ do: 'billingInfo', startSubscription: true, siteID: site.id, siteName: site.name, subscription: subscriptionID, addToken: true, token: token }); } }); handler.open({ name: 'Blux', description: app.billingConfig.subscriptions[subscriptionID].name + ' Plan', amount: app.billingConfig.subscriptions[subscriptionID].amount }); }); }, renderCards = function() { if (!site.billing.subscription || site.billing.subscription === 'trial') { cardsTitle.css({ display: 'none' }); cardsHolder.css({ display: 'none' }); } else { cardsHolder.html(''); Object.keys(app.user.cards).forEach(function(cardID) { var checked = (site.billing.card === cardID); var row = DOM().new('div').class('caa_row caa_row_hover caa_click').append(DOM().new('span').class('ib middle').text(showCardLine(app.user.cards[cardID]))).appendTo(cardsHolder).on('click', function(e) { app.send({ do: 'billingInfo', updateSiteBilling: true, siteID: site.id, card: cardID }); }); if (checked) { UI.Icon('check-fill').insertFirst(row).byTag('use').attr({ fill: '#307BAA' }); row.byTag('span').css({ 'margin-left': '10px', color: '#307BAA' }); } else { row.byTag('span').css({ 'margin-left': '42px' }); } }); } }, renderTransfer = function() { transferHolder.html(''); if (site.billing.transfer) { DOM().new('div').append(DOM().new('span').text('Current transfer offer to: ' + site.billing.transfer + ' ')).appendTo(transferHolder).append(DOM().new('a').text('Cancel').class('caa_click').on('click', function(e) { DOM(e.target).text('Canceling...'); app.Request({ do: 'request', request: 'transferSite', siteID: site.id, siteName: site.name, cancel: true }, function(data) { app.listeners.transferSite(data); }); })); } var transferForm = DOM().new('form').css({ 'margin-top': '20px' }).on('submit', function(e) { e.preventDefault(); var email = input.val() || ''; if (email.match(/\@/) && email.match(/\./) && email.length > 5) { input.css({ 'border-color': '' }); app.Request({ do: 'request', request: 'transferSite', transferSite: email, siteID: site.id, siteName: site.name }, function(data) { app.listeners.transferSite(data); }); } else { input.css({ 'border-color': 'red' }); } UI.Spinner().insertAfter(transferForm.byClass('caa_button-default').attr({ disabled: true })).css({ 'margin-left': '10px' }); setTimeout(function() { transferForm.byClass('caa_button-default').css({ disabled: false }); }, 500); }).appendTo(transferHolder); var input = Inputs.text({ type: 'email', value: site.billing.transfer || '', label: 'New Owner Email', }).appendTo(DOM().new('div').class('ib middle').css({ width: '200px', 'margin-right': '10px' }).appendTo(transferForm)).byTag('input').id('caa-site-transfer-to'); DOM().new('input').attr({ type: 'submit' }).class('caa_button-default').val('Send').appendTo(transferForm); }, renderDelete = function() { deleteSiteHolder.html(''); DOM().new('button').class('caa_button-default').text('Delete This Site Forever').on('click', function(e) { deleteSiteHolder.html(''); DOM().new('div').text('Are you sure? We are going to delete every single bit of data we have for this site forever. You might consider going to the settings screen to download your site before you continue here. Just in case you maybe needed some part of your site later').appendTo(deleteSiteHolder); var left = 5, timer = setInterval(function() { left -= 1; if (left <= 0) { clearInterval(timer); DOM().new('button').class('caa_button-default').text('I have read the warning. I want this site deleted').on('click', function(e) { DOM(e.target).attr({ disabled: true }).text('Deleting forever...'); app.Request({ do: 'request', request: 'deleteSite', siteID: site.id }, function(data) { console.log('delete site confirmation incoming'); if (data.error) { console.error('errors'); renderDelete(); } else { if (app.site.id === site.id) { var useSite = app.sites[0]; if (useSite.id === app.site.id){ if(app.sites[1]){ useSite = app.sites[1]; } else { useSite = false; } } if(useSite){ app.siteListToggler(); app.switchSite(useSite); app.send({ do: 'getSites' }); } else { alert('You can\'t delete your only site. If you really want this site deleted, make a new site, then delete this one.'); } } else { app.send({ do: 'getSites' }); app.render('/billing', false, false); } } }); }).appendTo(deleteSiteHolder); DOM().id('deleteTimerText').remove(); } else { DOM().newOrFind('div', 'deleteTimerText').appendTo(deleteSiteHolder).text('You will be able to delete this site in ' + left + ' seconds'); } }, 1000); }).appendTo(deleteSiteHolder); }, startPlan = function(e, subscriptionID) { if (app.stripe_publish) { var cards = Object.keys(app.user.cards); if (cards.length > 0) { var modal = UI.openModal(DOM(e.target)).css({ 'max-width': '400px', 'height': 'auto' }), holder = DOM().new('div').class('caa_padding').appendTo(modal); DOM().new('div').text('Select which card to use').appendTo(holder); cards.forEach(function(cardID) { var card = app.user.cards[cardID], cardDOM = showCardDOM(card); var row = DOM().new('div').class('caa_row caa_row_hover caa_click').append(cardDOM).appendTo(modal).on('click', function(e) { app.send({ do: 'billingInfo', startSubscription: true, siteID: site.id, siteName: site.name, subscription: subscriptionID, addToken: false, token: card }); UI.closeModal(e.target); }); }); DOM().new('div').class('caa_padding').append(DOM().new('button').class('caa_button-default').text('Add New Card').on('click', function(e) { stripeCheckout(subscriptionID); UI.closeModal(e.target); })).appendTo(modal); } else { stripeCheckout(subscriptionID); } } else { alert('We messed up somehow, email support@blux.com'); } }, changePlan = function(e, subscriptionID) { var modal = UI.openModal(DOM(e.target)).css({ 'max-width': '400px', 'height': 'auto' }), modalContent = DOM().new('div').class('caa_padding').appendTo(modal), endOfMonth = new Date(parseAnyDate(getFirstOfMonth(new Date(), 1))), text; endOfMonth.setDate(endOfMonth.getDate() - 1); text = subscriptionID === 'trial' ? site.name + ' will remain in the ' + app.billingConfig.subscriptions[site.billing.subscription].name + ' plan through ' + displayDate(endOfMonth) + ' and will no longer automatically renew.' : site.name + ' will remain in the ' + app.billingConfig.subscriptions[site.billing.subscription].name + ' plan through ' + displayDate(endOfMonth) + '. ' + site.name + ' will change to the ' + app.billingConfig.subscriptions[subscriptionID].name + ' plan on ' + displayDate(parseAnyDate(getFirstOfMonth(new Date(), 1))) + '.'; DOM().new('div').css({ 'margin-bottom': '60px' }).text(text).appendTo(modalContent); var holder = DOM().new('div').css({ overflow: 'hidden' }).appendTo(modalContent); DOM().new('button').class('caa_button-default').text('Nevermind').on('click', function(e) { UI.closeModal(e.target); }).appendTo(holder); DOM().new('button').class('caa_button-default caa_button-blue').text('Continue').on('click', function(e) { DOM(e.target).attr({ disabled: true }); app.send({ do: 'billingInfo', updateSiteBilling: true, siteID: site.id, subscription: subscriptionID }); UI.closeModal(e.target); }).appendTo(holder).css({ float: 'right' }); }; if (site.billing.subscription && site.billing.subscription !== 'trial' && site.billing.subscription_next !== 'trial') { var cancelSite = DOM().new('div').appendTo(content).css({ 'margin': '20px 0' }).insertAfter(transferHolder), cancelTitle = DOM().new('div').class('caa_sectionBar').text('Cancel Site').appendTo(cancelSite), cancelHolder = DOM().new('div').class('caa_padding').appendTo(cancelSite) .append( DOM().new('a').class('caa_click caa_link').text('Cancel Now').on('click', function(e) { changePlan(e, 'trial'); }) ); } renderSubscriptions(); renderCards(); renderTransfer(); renderHistory(); renderDelete(); app.listeners.updateSiteBilling = function(data) { if (data.siteID == site.id) { if (data.card && site.billing) { site.billing.card = data.card; } } if (data.billingInfo && data.siteID) { app.billingInfo[data.siteID] = data.siteBilling; } if (site.id === data.siteID) { site.billing = data.siteBilling; if (site.billing.history) { site.billing.history.reverse(); } } renderSubscriptions(); renderCards(); renderTransfer(); renderHistory(); }; app.listeners.startSubscription = function(data) { if (data.error) { DOM().new('div').css({ 'background-color': 'red', color: '#fff' }).class('caa_padding').text(data.error).insertAfter(subscriptionTitle); } else { app.billingInfo[data.siteID].billingOK = true; // allows publishing and other billign related things DOM().new('div').css({ 'background-color': 'green', color: '#fff' }).class('caa_padding').text('Great! Your subscription was started.').insertAfter(subscriptionTitle); if (data.siteID == site.id) { if (data.subscription) { site.billing.subscription = data.subscription; } } renderSubscriptions(); } }; app.listeners.transferSite = function(data) { if (data.error) { DOM().new('div').css({ 'background-color': 'red', color: '#fff' }).class('caa_padding').text(data.error).insertAfter(transferTitle); } else { DOM().new('div').css({ 'background-color': 'green', color: '#fff' }).class('caa_padding').text('Great! Your site transfer was offered to ' + data.transferSite).insertAfter(transferTitle); if (data.siteID == site.id) { if (data.transferSite) { site.billing.transfer = data.transferSite; } } } renderTransfer(); }; app.listeners.cancelTransfer = function(data) { if (data.error) { DOM().new('div').css({ 'background-color': 'red', color: '#fff' }).class('caa_padding').text(data.error).insertAfter(transferTitle); } else { DOM().new('div').css({ 'background-color': 'green', color: '#fff' }).class('caa_padding').text('The site transfer was canceled').insertAfter(transferTitle); if (data.siteID == site.id) { site.billing.transfer = ''; } } renderTransfer(); }; return this; }; function showCardLine(card) { if (!card || typeof card !== 'object') { return ''; } var cardLine = '', mo; if (card.name) { cardLine += card.name + ' '; } if (card.brand) { if (card.exp_month < 10) { mo = '0' + card.exp_month; } else { mo = card.exp_month + ''; } cardLine += card.brand + ' ******' + card.last4 + ' Exp ' + mo + '/' + card.exp_year; } return cardLine; } function showCardDOM(card) { var cardLine = '', mo = ''; if (card.name) { cardLine += card.name + ' '; } if (card.brand) { if (card.exp_month < 10) { mo = '0' + card.exp_month; } else { mo = card.exp_month + ''; } cardLine += ' ******' + card.last4 + ' Exp ' + mo + '/' + card.exp_year; } return DOM().new('div').css({ 'white-space': 'nowrap' }) .append(DOM().new('img').class('middle').attr({ src: '//cdn.blux.com/images/cards/' + (card.brand || 'visa').toLowerCase().replace(/\ /g, '') + '.svg' }).css({ width: '40px' })) .append(DOM().new('span').class('ib middle').css({ 'padding-left': '10px', 'white-space': 'normal', width: 'calc(100% - 50px)' }).text(cardLine)); } App.prototype.changes = function(into, type) { var app = this; var chHolder = DOM().new('div').appendTo(into).append(UI.Spinner('24').addClass('caa_padding')).append(DOM().new('span').class('ib middle').text('Loading the long list of changes...').css({ 'padding-left': '10px' })); var changeTypeMap = { 'update': 'Updated', 'set': 'Updated', 'delete': 'deleted', 'add': 'added', 'system': 'Blux Auto Fixer' }, request = { do: 'request', request: 'changes' }, chFirst = false, lastYMD = '', loadChanges = function(data) { setTimeout(function() { if (!chFirst) { chFirst = true; chHolder.html('').removeClass('caa_padding'); } else { DOM().byClass('load_more').remove(); } if (data.changes) { if (data.changes) { var changes = Object.keys(data.changes).sort().reverse().filter(function(ch, i) { if (i > 15) { return false; } return true; }); changes.forEach(function(ymd) { var ymdparts = ymd.split(/\-/); var d = new Date(ymdparts[0], (ymdparts[1] - 1), ymdparts[2], 0, 0, 0); DOM().new('div').class('caa_sectionBar').text(giveDate(d)).appendTo(chHolder); var secContent = DOM().new('div').appendTo(chHolder); lastYMD = ymd + ''; if (data.changes[ymd]) { data.changes[ymd].reverse().forEach(function(change, c) { var row; if (change.type === 'publish') { row = DOM().new('div').class('caa_row').text(displayDateLocal(change.date, 'time').split(' ').slice(1).join(' ') + ' ' + change.name + ' published ' + change.value).appendTo(secContent) if(change.revision){ row.addClass('caa_click').on('click', function(e) { e.preventDefault(); var modal = UI.openModal(DOM(e.target)); app.restore(change).appendTo(modal); }).appendTo(secContent); } } else if (change.type === 'restore') { row = DOM().new('div').class('caa_row').text(change.name + ' restored revision #' + change.value).appendTo(secContent); } else { var linkPath = Array.isArray(change.path) ? humanPath(change.path, app.site) : '/'; row = DOM().new('div').class('caa_row caa_click').html('#' + change.revision + ' ' + displayDateLocal(change.date, 'time').split(' ').slice(1).join(' ') + ' ' + change.name + ' ' + changeTypeMap[change.type] + ' ' + linkPath + ' ') .on('click', function(e) { e.preventDefault(); var modal = UI.openModal(DOM(e.target)); app.restore(change).appendTo(modal); }).appendTo(secContent); } }); } }); /* not working well, has not been touched since splitting the changes into multiple files var buttonHolder = DOM().new('div').class('caa_padding load_more') .append(DOM().new('button').class('caa_button-default').text('Load More').on('click', function(e) { request.from = parseAnyDate(lastYMD); request.from.setDate(request.from.getDate() - 10); request.to = parseAnyDate(lastYMD); request.to.setDate(request.to.getDate() - 2); buttonHolder.html('').append(UI.Spinner('24')); app.Request(request, loadChanges); })) .append(DOM().new('button').class('caa_button-default').css({ 'margin-left': '10px' }).text('Load All').on('click', function(e) { request.all = true; buttonHolder.html('').append(UI.Spinner('24')); app.Request(request, loadChanges); })) .appendTo(chHolder); */ } } else { DOM().new('div').text('There are no changes to display').appendTo(chHolder); } }, 30); }; if (type === 'd') { request.from = app.parts[1]; request.to = app.parts[1]; } app.Request(request, loadChanges); }; App.prototype.content = function() { var app = this, p, doNew = false, doNewBefore = false, doScreenSizes = false; // mark content as the highlighted nav section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.subscribe('content', function onchangeContentMenu() { app.contentMenu(false); }); if (!hasSiteAccess(app.user.access, app.parts.join('/'))) { app.stage.html('you do not have access to this section'); return false; } var url = '', pageChannel = 'content'; if (app.parts.length > 1) { url += '/' + app.parts[1]; pageChannel += '/' + app.parts[1]; } if (app.parts.length > 2) { url += '/' + app.parts[2]; pageChannel += '/' + app.parts[2]; } if (app.parts.length > 3) { url += '/' + app.parts[3]; } if (app.parts.length > 4) { url += '#' + app.parts[4]; } if (app.parts.length > 5) { url += '/' + app.parts[5]; } var goSection = app.site.content[app.parts[1]]; if (goSection) { goSection = app.site.content[app.parts[1]].length; } if (!goSection) { // add section and re-render if not found for certain types if (app.parts[1] === '__templates') { if (!Array.isArray(app.site.content[app.parts[1]])) { var update = {}; update[app.parts[1]] = [{ 'title': 'Default Template', 'body': '', 'description': '', 'items': [{ 'title': app.parts[1].capitalizeFirstLetter() + ' Section Title', 'body': 'section body' }] }]; app.siteUpdate(['content'], update); app.render('/content/' + app.parts[1], false, false); return true; } } } for (p in app.parts) { if (app.parts[p] === '__new') { doNew = true; } } for (p in app.partsBefore) { if (app.partsBefore[p] === '__new') { doNewBefore = true; } } if (doNew) { app.addContent(); } else if (app.parts.length > 2) { var page; app.subscribe(pageChannel, function onchangePage() { if (goSection) { if (app.parts[0] === 'preview') { var renderURL = app.parts.slice(1).join('/') || ''; app.preview('/' + renderURL); if(app.renderForEmail){ app.previewForEmail(); } } else { if (!app.isEditing) { app.stage.html(''); page = new Page(app, app.site, url, true).edit(); app.currentPage = page; if(!page.usePage.items || !page.usePage.items.length) { DOM().new('div').class('caa_content caa_padding').id('blux-empty-state-help').appendTo(app.stage); } else { app.stage.append(page.dom); } var check = [], checkString = app.parts[0] + '/' + app.parts[1] + '/' + app.parts[2] + '/items/' + app.parts[4]; check.push({ l: app.parts[5], s: checkString }); if (app.parts.length > 5) { for (p = 5; p < app.parts.length; p++) { checkString += '/items/' + app.parts[p]; check.push({ l: app.parts[(p + 1)], s: checkString }); } } setTimeout(function() { page.onload(); page.dom.byTag('a').caPrefixURL(app, '/content'); if (window.caExecRefs) { check.forEach(function(checker) { if (caExecRefs[checker.s + '.slider']) { caExecRefs[checker.s + '.slider'].touchDisabled = true; var tmpConfig = caExecRefs[checker.s + '.slider'].config.transition + '', goTo = Math.floor(checker.l / caExecRefs[checker.s + '.slider'].config.columns); if (goTo || goTo === 0) { caExecRefs[checker.s + '.slider'].config.transition = 'Instant'; caExecRefs[checker.s + '.slider'].transitionTo(goTo); caExecRefs[checker.s + '.slider'].config.transition = tmpConfig; setTimeout(function() { if (caExecRefs[checker.s + '.slider'].slides[goTo]) { caExecRefs[checker.s + '.slider'].slides[goTo].css({ 'pointer-events': '', opacity: 1 }); } caExecRefs[checker.s + '.slider'].on('click', function(e) { clearInterval(caExecRefs[checker.s + '.slider'].autoplay) }) }, 10); } } else if (caExecRefs[checker.s + '.tabs']) { caExecRefs[checker.s + '.tabs'].tab(checker.l * 1); } }); } }, 10); if (setStyles) { setStyles(); } } } } }); if (app.parts[0] !== 'preview') { var setStyles = function() { if(app.currentPage && app.currentPage.classArray){ var stylesheet = app.genStyleSheet(app.currentPage.classArray) + '\n' + app.currentPage.customCSS; app.removeSheets().applySheet(stylesheet); } }; app.subscribe('styles', setStyles); var genstyles = new repeatThrottle(function() { setStyles(); }, 200); app.onResize(genstyles.run); if (page && page.onresize) { app.onResize(page.onresize); } if (page && page.onscroll) { app.onScroll(page.onscroll); } } DOM().id('blux-empty-state-help').exists(function(holder){ var emptyStateResize = function(e){ if (window.innerWidth < 1201) { holder.html('') .append( DOM().new('div').css({position: 'absolute', top: '73%', left: '30px'}) .append(UI.Icon('left')) .append(DOM().new('span').class('ibb middle').css({'white-space':'normal'}).text('Open the left panel to edit the page and add blocks')) ) } else { holder.html('') .append( DOM().new('div').css({'margin-top': '154px', 'white-space': 'nowrap'}) .append(UI.Icon('left')) .append(DOM().new('span').class('ibb middle').css({'white-space':'normal'}).text('Press here to edit the page')) ) .append( DOM().new('div').css({'margin-top': '16px', 'white-space': 'nowrap'}) .append(UI.Icon('left')) .append(DOM().new('span').class('ibb middle').css({'white-space':'normal'}).html('Pages are made of blocks. Blocks let you structure the layout of your page and add content.
Add your first block here.
')) ) } }; app.onResize(emptyStateResize); emptyStateResize(); }) doScreenSizes = 'enable'; } else { app.destroyPanels(); if (app.changed[0] || doNewBefore || app.partsBefore.length > 2) { var searchTimer; app.subscribe('content', function onchangeContentList() { app.stage.html(''); app.pageURLS = {}; DOM().new('div') .class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text('Content')) .appendTo(app.stage); var addersHolder = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage).append( DOM().new('button').class('caa_button-default').text('Add Page').on('click', function(e){ app.render('/content/pages/__new', false, false); }) ), header = DOM().new('div').class('caa_content caa_control_header').css({'border-bottom': 'none', 'border-top': '1px solid #d4d4d4'}).appendTo(app.stage), content = DOM().new('div').class('caa_content').appendTo(app.stage), sec, p, pages = [], allTags = [], filterTags = [], curSection = '', tagList = DOM().new('div').class('caa_click').css({ position: 'absolute', top: '22px', right: '4px' }).append(UI.Icon('tags')).appendTo(header).on('click', function(e) { if (tagList.expanded) { tagList.expanded = false; tagHolder.animate({ 'max-height': 0, padding: 0 }); } else { tagHolder.html(''); tagList.expanded = true; if (allTags.length) { allTags.forEach(function(tag) { DOM().new('label').css({ padding: '8px' }) .append(DOM().new('input').class('ib middle').attr({ type: 'checkbox', checked: (filterTags.indexOf(tag) > -1) }).on('change', function(e) { var i = filterTags.indexOf(tag); if (i < 0) { filterTags.push(tag); } else { filterTags.splice(i, 1); } searchFilter({ target: byID('caa-screen-search') }); })) .append(DOM().new('span').class('ib middle').text(tag)) .appendTo(tagHolder); }); // } else { DOM().new('i').text('You are not using any tags').appendTo(tagHolder); } tagHolder.animate({ 'max-height': '20px', padding: '16px 0', 'text-align': 'right' }); } }), tagHolder = DOM().new('div').css({ 'max-height': 0, 'overflow': 'hidden' }), gridItems, searchFilter = function(e) { var Search = e.target.value || ''; clearTimeout(searchTimer); searchTimer = setTimeout(function() { var searchAr = Search.split(/\\s */), searchRegex = ''; for (var s in searchAr) { if (searchAr[s]) { if (searchRegex) { searchRegex += '|'; } searchRegex += searchAr[s]; } } var Regex = new RegExp(searchRegex, 'i'); boxes.forEach(function(element, e) { var el = DOM(element), tagMatch = false, hasTags = el.attr('data-tags') || '', st = 0, hasSec = el.attr('data-section'), hasStatus = '_status' + el.attr('data-status'), adder = el.attr('data-adder'), showAdder = false; if (filterTags.length) { for (st in filterTags) { if (hasTags.indexOf(filterTags[st] + ',') > -1) { tagMatch = true; } } } if(adder){ if(curSection === hasSec || curSection === hasStatus || (!curSection && hasSec === 'pages')){ showAdder = true; } } if ((Search && !Regex.test(el.text())) || (!tagMatch && filterTags.length) || (curSection && curSection !== hasSec && curSection !== hasStatus) || (adder && !showAdder)) { el.appendTo(noMansLand); } else { el.appendSort(grid); } }); resize(); }, 200); }, addTagsToList = function(tag) { if (allTags.indexOf(tag) < 0) { allTags.push(tag); } }; var searchBox = Inputs.search({ label: 'Find Content' }).addClass('ib middle').css({ margin: 0, width: '200px' }).appendTo(header); searchBox.byTag('input').id('caa-screen-search').on('input change', searchFilter); var filterOps = Inputs.select([{text: 'All', value: ''}], '').addClass('ibb middle').css({'max-width': '100px', 'margin-left': '10px'}).appendTo(header).on('change', function(e){ curSection = filterOps.val(); if (curSection === '_all') { curSection = ''; } app.stage.byClass('caa_pageAdder').appendTo(noMansLand); searchFilter({ target: byID('caa-screen-search') }); }); tagHolder.appendTo(header); var secnum = 0; Object.keys(app.site.content).forEach(function(sec){ if (Array.isArray(app.site.content[sec]) && sec !== '__templates') { if(sec !== 'pages'){ DOM().new('button').class('caa_button-default').css({'margin-left': '10px'}).text('Add '+sec.capitalizeFirstLetter()).appendTo(addersHolder).on('click', function(e){ app.render('/content/'+sec+'/__new', false, false); }) } if (app.site.content[sec].length) { DOM().new('option').text((sec || '').capitalizeFirstLetter()).val(sec).appendTo(filterOps); } } for (p in app.site.content[sec]) { if (app.site.content[sec][p].tags) { app.site.content[sec][p].tags.forEach(addTagsToList); } pages.push({ section: sec, internal_status: app.site.content[sec][p].internal_status || 0, secnum: secnum, p: p, object: app.site.content[sec][p], title: app.site.content[sec][p].title || 'title not set', description: app.site.content[sec][p].description || 'description not set', date: isoDate(app.site.content[sec][p].date), url: app.getPageURL(sec, app.site.content[sec][p], p, false) || '/', media: app.site.content[sec][p].media || getFirstMedia(app.site.content[sec][p], '', app.site.media), tags: app.site.content[sec][p].tags, comments: [] }); } secnum++; }); [{ text: 'In Progress', value: '0' }, { text: 'In Review', value: '1' }, { text: 'Approved', value: '2' }].forEach(function(internal_status){ DOM().new('option').text(internal_status.text).val('_status' + internal_status.value).appendTo(filterOps); }); var grid = DOM().new('div').appendTo(content), noMansLand = DOM().new('div'), secAdders = {}, boxes = []; pages.slice(0, 100).forEach(function(page, p) { var thumb = DOM().new('div').css({ width: '80px', 'padding-top': '56%' }).class('caa_valignmiddleitem'); app.Media(page.media, thumb); thumb.css({ 'background-size': 'cover', 'background-position': 'center center' }) var box = DOM().new('div').id('content-' + page.section + '-' + page.p).class('caa_griditemhover caa_click').css({ display: 'block', margin: '10px', 'border': '1px solid #d4d4d4' }).attr({ 'data-tags': page.tags ? ',' + page.tags.join(',') + ',' : '', 'data-section': page.section, 'data-status': page.internal_status || '', 'data-sort-value': page.secnum + '-' + page.p }) .append( DOM().new('div').class('ibb middle caa_valignmiddle').css({ width: '80px', overflow: 'hidden' }).append(thumb) ) .append( DOM().new('div').class('ibb middle page-title content-text-holder').css({ position: 'relative', width: 'calc(100% - 80px)', padding: '0 10px' }).append(DOM().new('span').class('ibb middle ellipsis').css({ width: '100%', 'padding-right': '20px' }).text(page.title)) .append(DOM().new('span').class('ibb middle ellipsis').css({ width: '100%', color: '#999', 'font-size': '12px', 'padding-right': '20px', 'margin-top': '-4px' }).text(page.url)) ); box.on('click', function(e) { app.render('/content/' + page.section + '/' + page.p + '/' + page.title.urlSafe(), false, false); if (!app.user.prefs.preview) { // open editor panel when they click on a page but only if they are not toggled to preview mode setTimeout(function() { app.EditorPanel('page', page.object, ['content', page.section, page.p], DOM().id('page')); }, 100); } }).appendSort(grid); boxes.push(box); }); var resize = function(e) { DOM().byClass('camediaload').loadMedia().mediaNOFX(); }; app.onResize(resize); setTimeout(resize, 100); app.getAndUpdateFeedback(); }); app.stage.find('.caa_secLinks[data-sec="' + (app.parts[1] || '_all') + '"]').exists(function(link) { link.trigger('click'); }); } else if (app.changed[1] || typeof app.changed[1] === 'undefined') { app.stage.find('.caa_secLinks[data-sec="' + (app.parts[1] || '_all') + '"]').exists(function(link) { link.trigger('click'); }); } } if (app.parts.length > 4) { var focusTargetId = 'page-block-' + app.parts[4]; if (app.parts.length > 5) { for (p = 5; p < app.parts.length; p++) { focusTargetId += '-item-' + app.parts[p]; } } var targetDOM = byID(focusTargetId); if (targetDOM) { setTimeout(function(){ app.stage.scrollTo(DOM(targetDOM).pos().offsetTop - 20); }, 50); } } else { app.stage.scrollTo(0); } if (app.parts.length < 2) { app.destroyPanels(); } app.screenSizes(doScreenSizes); }; App.prototype.custom = function() { var app = this; // mark content as the highlighted nav section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.contentMenu(false); app.subNavContainer.byClass('caa_subNavBackText').text('Custom Elements'); app.stage.html(''); var content = DOM().new('div').class('caa_content caa_cols-2h').appendTo(app.stage); var appHeader = DOM().new('div') .class('caa_content caa_header'), backLink = '/content', moreText = ''; if (app.parts[1]) { if (!hasSiteAccess(app.user.access, 'media/' + app.parts[1])) { app.stage.html('You do not have access to this section'); return false; } if (app.site.media[app.parts[1]]) { moreText = ': ' + app.site.media[app.parts[1]].name; var mediaID = app.parts[1], media = app.site.media[mediaID], textbox = DOM().new('div').class('caa_cols-2b caa_padding').appendTo(content), rightside = DOM().new('div').class('caa_cols-2s caa_padding').css({ 'max-width': '300px' }).appendTo(content), fields = DOM().new('div').appendTo(rightside), preview = DOM().new('div').css({ 'margin-top': '20px', width: '100%', 'min-height': '400px', position: 'relative' }).appendTo(rightside); //app.subNavContainer.byClass('caa_subNavBackText').text(media.name || 'No Name'); var checked = { html: !!media.content, css: !!media.css, javascript: !!media.javascript, javascript_prerender: !!media.javascript_prerender, customData: !!media.customData }; DOM().new('label').class('caa_panelInputLabel').css({ margin: '10px 0' }).appendTo(textbox) .append(DOM().new('input').class('ibb middle blux_checkbox').attr({ type: 'checkbox', checked: checked.html }).on('change', function(e) { markup.css({ display: e.target.checked ? 'block' : 'none' }) })) .append(DOM().new('span').class('ibb middle').css({ 'margin-left': '10px' }).text('HTML')); var markup = DOM().new('div').css({ 'height': '240px', width: 'calc(100% - 16px)', display: checked.html ? 'block' : 'none' }).text(media.content || '').appendTo(textbox).aceEditor('html', true).on('save', function(e) { button.trigger('click'); }); DOM().new('label').class('caa_panelInputLabel').css({ margin: '10px 0' }).appendTo(textbox) .append(DOM().new('input').class('ibb middle blux_checkbox').attr({ type: 'checkbox', checked: checked.css }).on('change', function(e) { css.css({ display: e.target.checked ? 'block' : 'none' }) })) .append(DOM().new('span').class('ibb middle').css({ 'margin-left': '10px' }).text('CSS')); var css = DOM().new('div').css({ 'height': '240px', width: 'calc(100% - 16px)', display: checked.css ? 'block' : 'none' }).text(media.css || '').appendTo(textbox).aceEditor('css', true).on('save', function(e) { button.trigger('click'); }); DOM().new('label').class('caa_panelInputLabel').css({ margin: '10px 0' }).appendTo(textbox) .append(DOM().new('input').class('ibb middle blux_checkbox').attr({ type: 'checkbox', checked: checked.javascript }).on('change', function(e) { javascript.css({ display: e.target.checked ? 'block' : 'none' }) })) .append(DOM().new('span').class('ibb middle').css({ 'margin-left': '10px' }).text('JavaScript: Execute On Page Load')); var javascript = DOM().new('div').css({ 'height': '400px', width: 'calc(100% - 16px)', display: checked.javascript ? 'block' : 'none' }).text(media.javascript || '').appendTo(textbox).aceEditor('javascript', true).on('save', function(e) { button.trigger('click'); }); /*DOM().new('label').class('caa_panelInputLabel').css({ margin: '10px 0' }).appendTo(textbox) .append(DOM().new('input').class('ibb middle blux_checkbox').attr({ type: 'checkbox', checked: checked.javascript_prerender }).on('change', function(e) { javascript_prerender.css({ display: e.target.checked ? 'block' : 'none' }) })) .append(DOM().new('span').class('ibb middle').css({ 'margin-left': '10px' }).text('JavaScript: Execute Immediate (before page load/publish)')); var javascript_prerender = DOM().new('div').css({ 'height': '400px', width: 'calc(100% - 16px)', display: checked.javascript_prerender ? 'block' : 'none' }).text(media.javascript_prerender || '').appendTo(textbox).aceEditor('javascript', true).on('save', function(e) { button.trigger('click'); });*/ DOM().new('label').class('caa_panelInputLabel').css({ margin: '10px 0' }).appendTo(textbox) .append(DOM().new('input').class('ibb middle blux_checkbox').attr({ type: 'checkbox', checked: checked.customData }).on('change', function(e) { customData.css({ display: e.target.checked ? 'block' : 'none' }) })) .append(DOM().new('span').class('ibb middle').css({ 'margin-left': '10px' }).text('Custom Data / JSON')); var customData = DOM().new('div').css({ 'height': '400px', width: 'calc(100% - 16px)', display: checked.customData ? 'block' : 'none' }).text(media.customData || '').appendTo(textbox).aceEditor('json', true).on('save', function(e) { button.trigger('click'); }); var button = DOM().new('button').class('caa_button-default').css({ 'margin-top': '20px' }).text('Save Markup').appendTo(textbox).on('click', function(e) { app.siteUpdate(['media', mediaID], { content: markup.editor.getSession().getValue(), css: css.editor.getSession().getValue(), javascript: javascript.editor.getSession().getValue(), //javascript_prerender: javascript_prerender.editor.getSession().getValue(), customData: customData.editor.getSession().getValue() }); }); var usage = DOM().new('div').css({ 'margin-top': '20px' }).appendTo(textbox); var matches = false; objectFind(app.site, [], ['media', 'customElement', 'widget'], mediaID, function(path, object, key) { if (!matches) { usage.html('This custom element is used by: '); } console.log('path', path) var pathInfo = app.pathToInfo(path); if (path[0] !== 'content') { pathInfo = { pageTitle: path.join('-'), url: '/' + path.join('/') }; } else { console.log('proceed', path) } DOM().new('a').text(pathInfo.pageTitle).attr({ href: pathInfo.url || '#' }).on('click', function(e) { e.preventDefault(); app.render(pathInfo.url, false); UI.closeModal(); }).appendTo(usage); DOM().new('span').text(' ').appendTo(usage); matches = true; }); var notes = DOM().new('div').css({ 'margin-top': '20px' }).appendTo(textbox); DOM().http({ url: '/docs/custom_elements.txt', callback: function(notesContent) { notes.html(notesContent.replace('{{customFuncName}}', (mediaID || '').replace(/\-/g, '_'))); } }); UI.deleteButton('Delete Custom Element', 'button', function(e) { app.siteDelete(['media', app.parts[1]]); app.render('/custom', false, false); }).appendTo(DOM().new('div').css({ 'margin-top': '100px' }).appendTo(textbox)); app.subscribe('media/' + mediaID, function() { setTimeout(function() { app.renderCustomObjectInputs(['media', mediaID], media.content + media.css + media.javascript + media.javascript_prerender, media, fields, false); preview.html(''); var iframe = app.preview('/__custom', preview, {}, { __config: 'previewMedia', media: mediaID, display: 'contain' }); }, 100); }); } else { DOM().new('div').class('caa_padding').text('Not found.').appendTo(content); moreText = ': Not Found'; } appHeader.append(UI.Icon('left', 'head').on('click', function(e) { app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Custom Elements' + moreText)) .insertFirst(app.stage); } else { if (!hasSiteAccess(app.user.access, 'media', true)) { app.stage.html('You do not have access to this section'); return false; } appHeader.append(UI.Icon('left', 'head').on('click', function(e) { app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Custom Elements' + moreText)) .insertFirst(app.stage); content.addClass('caa_padding'); var mediaContainer = DOM().new('div').class('caa_grid').appendTo(content); app.subscribe('media', function onchangeMedia() { mediaContainer.html(''); Object.keys(app.site.media).sort(function(a, b) { return b - a; }).forEach(function(mediaID) { if (app.site.media[mediaID].type === 'custom') { var name = app.site.media[mediaID].name || 'No Name Set'; var row = DOM().new('div').class('caa_row caa_row_hover caa_click').on('click', function(e) { app.render('/custom/' + mediaID, false, false); }).appendTo(mediaContainer); var m = DOM().new('div').class('ib middle').css({ width: '130px', 'background-image': checkered_background_gif }).appendTo(row); app.Media({ media: mediaID, display: 'contain', browse: true }).appendTo(m).css({ /*'width':'520px', 'transform': 'scale(0.25)', 'transform-origin': '0 0', '-webkit-transform-origin': '0 0',*/ overflow: 'hidden', 'pointer-events': 'none' }); var textbox = DOM().new('div').class('ib middle').css({ 'margin-left': '10px', 'max-width': '300px' }).appendTo(row); var info = { name: name }; for (var k in info) { DOM().new('div').text(info[k]).appendTo(textbox); } } }); mediaContainer.caGrid(200, 10); }); } }; App.prototype.renderCustomObjectInputs = function(path, content, media, into, browseClick) { var app = this; into.html(''); var row = DOM().new('div').css({ 'padding-bottom': '10px' }).appendTo(into); var templateMode = path[0] === 'media'; // template mode to set defaults/change name if (templateMode) { Inputs.text({ label: 'Name', value: media.name }).appendTo(row).byTag('input').on('change', function(e) { var val = DOM(e.target).val() || ''; app.siteUpdate(path, { name: val }); }); Inputs.textarea({ label: 'Description', value: media.description || '', onchange: function(val) { app.siteUpdate(path, { description: val }); } }).appendTo(row); Inputs.options({ label: 'Custom Type', value: media.customType || '', options: [{ text: 'Default', value: '' }, { text: 'Button/Block Effect', value: 'hover-effect' }, { text: 'Page Widget', value: 'page' }], onchange: function(val) { app.siteUpdate(path, { customType: val }); } }).css({ 'margin-top': '10px' }).appendTo(row); Inputs.textarea({ label: 'External js/css dependencies', value: media.dependencies || '', explain: 'Enter the url to each javascript or css file each on their own line that are necessary for this custom element. Blux will include these files asyncronously and execute your javascript when all files are ready', onchange: function(val) { app.siteUpdate(path, { dependencies: val }); } }).appendTo(row); DOM().new('label').class('caa_panelInputLabel').css({ 'margin-top': '10px' }).text('Include Data In Config').appendTo(row); var dataOptions = { sitemap: 'Site Map', sitemap_sections: 'Site Map w/ 1st Level Blocks', sitemap_blocks: 'Site Map w/ All Blocks', navigation_page: 'Page Specific Navigation', navigations: 'All Site Navigations' }; if (Array.isArray(app.site.navigation)) { app.site.navigation.forEach(function(nav, n) { dataOptions['navigation' + n] = 'Nav: ' + (nav.label || 'Navigation ' + (n + 1)); }); } dataOptions.footer_page = 'Page Specific Footer'; dataOptions.footers = 'All Site Footers'; if (Array.isArray(app.site.footer)) { app.site.footer.forEach(function(footer, f) { dataOptions['footer_' + f] = 'Footer: ' + (footer.label || 'Footer ' + (f + 1)); }); } dataOptions.auto = 'Auto Feeds'; Object.keys(app.site.content).forEach(function(section) { dataOptions['auto_' + section] = 'Feed: ' + section.capitalizeFirstLetter() + ' Auto Feed'; }); if (app.site.feeds) { dataOptions.feeds = 'Feeds'; Object.keys(app.site.feeds).forEach(function(feedID) { dataOptions['feed_' + feedID] = 'Feed: ' + app.site.feeds[feedID].name; }) } Object.keys(dataOptions).forEach(function(key) { if (key === 'feeds') { DOM().new('div').class('caa_panelInputLabel').css({ margin: '10px 0' }).text(dataOptions[key]) .appendTo(row); } else { Inputs.checkbox({ label: dataOptions[key], value: Array.isArray(media.data) ? media.data.indexOf(key) > -1 : false, onchange: function(val) { var setData = Array.isArray(media.data) ? media.data : []; if (val) { setData.push(key); } else { var inThere = setData.indexOf(key); if (inThere > -1) { setData.splice(inThere, 1); } } app.siteUpdate(path, { data: setData }, true); } }).css({ 'margin': '10px 0 0 ' + (dataOptions[key].match(': ') ? '10px' : 0) }).appendTo(row); } }); } var matches = content.match(/\{\{([^{}]+)}}/g) || [], didKey = {}, fieldSettings = media.fields || {}; if (matches.length) { matches.forEach(function(match) { if (!didKey[match]) { if (!fieldSettings[match]) { fieldSettings[match] = {}; } var row = DOM().new('div').css({ 'margin-top': '10px' }).appendTo(into); if (match.substr(2, 6) === 'color:') { Inputs.color({ label: templateMode ? 'Default Color' : 'Color', value: fieldSettings[match].value || '', getColors: function() { return app.currentColorList(); }, onchange: function(color) { fieldSettings[match].value = color || ''; } }).appendTo(row); } else if (match.substr(2, 10) === 'textStyle:') { var classOptions = []; app.site.styles.text.forEach(function(textStyle, s) { if (filterDesignItems(textStyle)) { var value = 'text' + s, label = textStyle._label; if (!label) { if (s === 0) { label = 'Title'; } else if (s === 1) { label = 'Body'; } else if (s === 2) { label = 'Sub-Title'; } else if (s === 3) { label = 'Sub-Body'; } else { label = 'new text style ' + s; } } classOptions.push({text: label, value: value}); } }); Inputs.options({ label: templateMode ? 'Default Text Style' : 'Text Style', options: classOptions, value: fieldSettings[match].value || '', onchange: function(val) { fieldSettings[match].value = val || ''; } }).appendTo(row); } else if (match.substr(2, 8) === 'options:') { var options = ((match.split(':')[2] || '').slice(0,-2) || '').split('.'); Inputs.options({ label: templateMode ? 'Default Option' : 'Option', options: options, value: fieldSettings[match].value || '', onchange: function(val) { fieldSettings[match].value = val || ''; } }).appendTo(row); } else { Inputs.text({ label: templateMode ? 'Default Value' : 'Value', value: fieldSettings[match].value || '', onchange: function(val) { fieldSettings[match].value = val || ''; } }).appendTo(row); } DOM().new('label').class('caa_panelInputLabel').text(match.substr(2,match.length-4).replace(/\:/g, ' ')).appendTo(row); didKey[match] = true; } }); DOM().new('button').class('caa_button-default').css({ 'margin-top': '10px' }).text('Save Settings').appendTo(into).on('click', function(e) { if (browseClick) { browseClick(e, { media: media.media || path[path.length - 1], fields: fieldSettings }) } else { console.log('path', path, fieldSettings); app.siteUpdate(path, { fields: fieldSettings }, true); } app.renderCustomObjectInputs(path, content, media, into, browseClick); }); } }; App.prototype.design = function() { var app = this; if (!hasSiteAccess(app.user.access, 'styles', true)) { app.stage.html('You do not have access to this section'); return false; } var subSections = [{ title: 'Default Colors', section: 'defaults', icon: 'wand' }, { title: 'Typography', section: 'text', icon: 'edit' }, { title: 'Links & Buttons', section: 'buttons', icon: 'attachment' }, { title: 'Blocks', section: 'blocks', icon: 'stack' }, { title: 'Icons', section: 'icons', icon: 'balloon' }, { title: 'Forms', section: 'forms', icon: 'adjustments' }, { title: 'Tabs', section: 'tabs', icon: 'pictures' }, { title: 'Tables', section: 'tables', icon: 'grid' }, { title: 'Widgets', section: 'widgets', icon: 'genius' }], subSection = subSections[0]; subSections.forEach(function(checkSubSection) { var sec = checkSubSection.section; if (hasSiteAccess(app.user.access, 'styles/' + sec)) { if (app.changed[0]) { DOM().new('a').id('nav-item-for-'+sec).class('caa_subNavItem') .append(DOM().new('div').class('ib middle caa_navItemText').text(checkSubSection.title)) .attr({ href: '/' + app.parts[0] + '/' + sec }).appendTo(app.subNavContainer).on('click', function(e) { e.preventDefault(); app.render('/' + app.parts[0] + '/' + sec, false, false); app.destroyPanels(); }); } if((app.parts[1] || 'defaults') === sec){ DOM().byClass('caa_navItemText').class('caa_navItemText'); DOM().id('nav-item-for-' + sec).byClass('caa_navItemText').addClass('caa_navItemTextOn'); subSection = checkSubSection; } } }); app.stage.html(''); var appHeading = DOM().new('div') .class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text(subSection.title)) .appendTo(app.stage); var content = DOM().new('div').appendTo(app.stage); app.subscribe('styles', function() { var scrollTop = app.stage.elements[0].scrollTop || 0; content.html(''); var thisContent = DOM().new('div').class('page0'); var includedStyles = [], specialStyles = []; var sec = subSection.section; if (!hasSiteAccess(app.user.access, 'styles/' + sec)) { return false; } /* var title = DOM().new('div').id('caa-section' + sec).class('caa_section-target') .css({margin: '10px', padding: '10px 0'}) .append(UI.Icon(subSection.icon).css({'margin-right': '10px'})) .append(DOM().new('span').class('ibb middle').text(subSection.title)) .appendTo(thisContent); if (i > 0) { title.css({ 'border-top': '1px solid #d4d4d4', 'margin-top': '200px' }); } */ var thisSection = DOM().new('div').class('container').appendTo(DOM().new('section').appendTo(thisContent)); switch (subSection.title) { case 'Default Colors': thisSection.class('caa_padding'); var colorBox = DOM().new('div'); DOM().new('div') .append(colorBox) .append( DOM().new('div').class('caa_button-default').css({ 'text-align': 'center', 'white-space': 'nowrap' }).append(DOM().new('span').class('ibb middle').text('View Combos').css({ 'padding-left': '6px', 'font-size': '12px' })).on('click', function(e) { var modal = UI.openModal(DOM(e.target)), modalContent = DOM().new('div').class('caa_padding').appendTo(modal); app.pickColorSet(modalContent, function(set) { Object.keys(set).forEach(function(color) { onChangeColor(color, set[color]); }); UI.closeModal(); }); }) ).appendTo(thisSection); var colors = [{ 'text': 'Text', 'key': 'text' }, { 'text': 'Background', 'key': 'background' }, { 'text': 'Links', 'key': 'links' }, { 'text': 'Icons', 'key': 'icons' }].forEach(function(item) { DOM().new('div').css({ 'margin': '0 0 40px 0' }).append( Inputs.color({ position: true, label: item.text, showvalue: true, getColors: function() { return app.currentColorList(); }, value: app.site.styles.colors[item.key], onchange: function(color) { onChangeColor(item.key, color); } })).appendTo(colorBox); }), onChangeColor = function(key, color) { var setCSS = {}; setCSS[key] = color; if (key === 'text') { content.find('.page0').css({ color: color }); } else if (key === 'background') { content.find('.page0').css({ background: color }); } else if (key === 'links') { } app.siteUpdate(['styles', 'colors'], setCSS); }; break; case 'Typography': thisSection.parent().addClass('blocks0'); var sortedValues = app.getSortedPreference('design/text'); app.site.styles.text.forEach(function(style, s) { if (filterDesignItems(style)) { var tag = 'div', text = supFace(app.site.styles.text, s); if (s === 0) { tag = 'h2'; } else if (s == 2) { tag = 'h3'; } var target = DOM().new(tag).id('style-target-for-' + sec + '-' + s).class('text' + s).text(text), dragHandle = DOM().new('span').class('ib middle').append(UI.Icon('drag', 'drag').attr({ 'data-dragable': '1' })).addClass('caa_subNavItem_hover').css({ position: 'absolute', right: '2px', 'margin-top': '-7px', top: '50%' }); if(style['.text'+s]){ if(style['.text'+s].color){ if(colorIsLight(style['.text'+s].color)){ target.css({'background-image': checkered_background_gif}); } } } var textbox = DOM().new('div').class('caa_clickSecTarget dragula-sortable') .css({position: 'relative'}) .attr({ 'dragula-id': sec + s, 'data-sort-value': app.getSortedPreferenceValue(sortedValues, sec + s) }) .append(DOM().new('div').id('style-label-for-' + sec + '-' + s).class('caa_subSectionTitle').text(app.site.styles.text[s]._label).css({ 'margin': '10px' })) .append(target) .append(dragHandle) .on('click', function(e) { app.StyleEditorPanel('text', style, ['styles', 'text', s], target); }).appendSort(thisSection); includedStyles.push('text' + s); } }); dragula([thisSection.elements[0]], { moves: function(el, source, handle) { return handle.getAttribute('data-dragable') === '1'; } }).on('dragend', function(e) { var sortedArray = []; thisSection.byClass('dragula-sortable').elements.forEach(function(element) { if (element.getAttribute('dragula-id')) { sortedArray.push(element.getAttribute('dragula-id')); } }); app.setSortedPreference('design/text', sortedArray); }); DOM().new('button').class('caa_button-default').text('Add Text Style').on('click', function(e) { var next = app.site.styles.text.length * 1; app.addStyle('text'); //app.render('/' + app.parts[0] + '/' + sec, false, true); setTimeout(function() { app.StyleEditorPanel('text', app.site.styles.text[next], ['styles', 'text', next], DOM().id('style-target-for-' + sec + '-' + next)); }, 100); }).appendTo(DOM().new('div').css({ 'margin': '20px 10px 10px 10px' }).appendTo(thisSection)); app.prepareSiteFonts(); break; case 'Blocks': app.site.styles.blocks.forEach(function(style, s) { if (filterDesignItems(style)) { var title = supFace(app.site.styles.text, 0), body = supFace(app.site.styles.text, 1), subtitle = supFace(app.site.styles.text, 2), subbody = supFace(app.site.styles.text, 3); var target = DOM().new('section').class('blocks' + s); var container = DOM().new('div').class('blocks' + s + 'container').appendTo(target) .append(DOM().new('h2').class('text0').text('Title '+title).appendTo(thisSection)) .append(DOM().new('h3').class('text2').text('Sub-Title '+subtitle).appendTo(thisSection)) .append(DOM().new('p').class('text1').text('Body '+body).appendTo(thisSection)) .append(DOM().new('div').class('text3').text('Sub-Body '+subbody).appendTo(thisSection)); DOM().new('div').class('caa_clickSecTarget') .append(DOM().new('div').id('style-label-for-' + sec + '-' + s).class('caa_subSectionTitle').text(app.site.styles.blocks[s]._label).css({ 'margin': '10px' })) .append(target) .on('click', function(e) { app.StyleEditorPanel('blocks', style, ['styles', 'blocks', s], target); }).appendTo(thisSection); includedStyles.push('blocks' + s); } }); DOM().new('button').class('caa_button-default').text('Add Block Style').css({ 'margin': '10px' }).on('click', function(e) { app.addStyle('blocks'); app.render('/' + app.parts[0] + '/' + sec, false, true); }).appendTo(DOM().new('div').css({ 'margin-top': '20px' }).appendTo(thisSection)); break; case 'Icons': includedStyles.push('icon'); if (!app.site.styles.icons) { app.site.styles.icons = {}; } thisSection.css({ padding: '10px' }).addClass('caa_clickSecTarget').on('click', function(e) { app.StyleEditorPanel('icons', app.site.styles.icons, ['styles', 'icons'], {}); }); var set = 1; if (app.site.styles.icons) { if (app.site.styles.icons.set) { set = app.site.styles.icons.set * 1; } } app.showSet(set, thisSection); break; case 'Links & Buttons': thisSection.addClass('text1').css({ padding: 0 }); var cont = DOM().new('div').class('caa_clickSecTarget').css({ 'padding': '10px', 'margin-top': '10px' }).appendTo(thisSection).on('click', function(e) { app.StyleEditorPanel('links', app.site.styles.globals.links, ['styles', 'globals', 'links'], target); }); var target = DOM().new('a').id('style-label-for-links').attr({ href: '#' }).class('links').text('Page Links').appendTo(cont).on('click', function(e) { e.preventDefault(); }); includedStyles.push('links'); app.site.styles.buttons.forEach(function(style, s) { if (filterDesignItems(style)) { var cont = DOM().new('div').class('caa_clickSecTarget').css({ 'padding': '10px' }).appendTo(thisSection).on('click', function(e) { app.StyleEditorPanel('buttons', style, ['styles', 'buttons', s], target); }); var target = DOM().new('a').id('style-label-for-' + sec + '-' + s).attr({ href: '#' }).class('ib buttons' + s + '').text(style._label).appendTo(cont).on('click', function(e) { e.preventDefault(); }); if(style['.buttons'+s] && style['.buttons'+s].color && colorIsLight(style['.buttons'+s].color)){ cont.css({'background-image': checkered_background_gif}); } includedStyles.push('buttons' + s); specialStyles.push({ className: 'buttons' + s, target: target }); } }); DOM().new('button').class('caa_button-default').text('Add Button Style').on('click', function(e) { app.addStyle('buttons'); app.render('/' + app.parts[0] + '/' + sec, false, true); }).appendTo(DOM().new('div').css({ 'margin': '10px' }).appendTo(thisSection)); break; case 'Forms': thisSection.addClass('text1').css({padding: 0}); app.site.styles.forms.forEach(function(style, s) { if (filterDesignItems(style)) { var target = DOM().new('section').class('blocks0'), container = DOM().new('div').class('blocks0container').appendTo(target); app.Media({ 'id': 'forms' + s, 'class': 'forms' + s, 'type': 'form', 'send_to': '', 'confirmation': 'text', 'confirmation_text': 'Thank you for your submission.', 'confirmation_url': '', 'submit_text': 'Submit', 'display_fields': 'rows', 'fields': [{ 'type': 'text', 'label': 'Text Input', 'sublabel': 'Sub-Label for Text Input', 'placeholder': 'Enter Text', 'required': true }, { 'type': 'Phone', 'label': 'Enter Phone', 'placeholder': 'Enter Phone Number', 'required': true }, { 'type': 'Select Menu', 'label': 'Select Menu', 'placeholder': 'Field Placeholder Text', 'options': [ '', 'Select Option 1', 'Select Option 2' ] }, { 'type': 'Spacer', 'label': 'Section Spacer', 'sublabel': 'Section spacer sub-label', 'divider': 'middle' }, { 'type': 'Checkbox', 'label': 'Checkbox', 'placeholder': 'Field Placeholder Text', 'options': [ 'Checkbox 1', 'Checkbox 2' ] }, { 'type': 'Radio', 'label': 'Radio', 'placeholder': 'Field Placeholder Text', 'options': [ 'Radio 1', 'Radio 2' ] }, { 'type': 'Text Area', 'label': 'Text Area', 'sublabel': 'Sub-Label for Text Area', 'placeholder': 'Enter message' }], 'ident': '', styleObject: style }).appendTo(container); target.byTag('form').id('forms' + s); DOM().new('div').class('caa_clickSecTarget') .css({padding: '10px'}) .append(DOM().new('div').id('style-label-for-' + sec + '-' + s).class('caa_subSectionTitle').text(app.site.styles.forms[s]._label).css({ 'margin': '10px' })) .append(target) .on('click', function(e) { app.StyleEditorPanel('forms', style, ['styles', 'forms', s], target); }).appendTo(thisSection); includedStyles.push('forms' + s); } }); DOM().new('button').class('caa_button-default').text('Add Form Style').on('click', function(e) { app.addStyle('forms'); app.render('/' + app.parts[0] + '/' + sec, false, true); }).appendTo(DOM().new('div').class().css({ 'margin': '20px 10px 10px 10px' }).appendTo(thisSection)); //prevent form from submitting setTimeout(function() { thisSection.byTag('form').elements.forEach(function(form) { DOM(form).form({}).preventSubmission = true; }); }, 10); break; case 'Tabs': thisSection.css({ padding: '0' }).addClass('text1'); app.site.styles.tabs.forEach(function(style, s) { if (filterDesignItems(style)) { var cont = DOM().new('div').class('ib middle caa_clickSecTarget').css({ padding: '10px', 'margin-top': '10px' }).appendTo(thisSection).on('click', function(e) { app.StyleEditorPanel('tabs', style, ['styles', 'tabs', s], target); }); var tabs = DOM().new('div').class('tabs'+s+'tabs').appendTo(cont); var target = DOM().new('div').id('style-label-for-' + sec + '-' + s).class('ib bottom tabs' + s + ' tabs' + s + 'on').text(style._label).appendTo(tabs); var target2 = DOM().new('div').class('ib bottom tabs' + s).text(style._label).appendTo(tabs); var target3 = DOM().new('div').class('ib bottom tabs' + s).text(style._label).appendTo(tabs); var target4 = DOM().new('div').class('tabs' + s + 'content').css({ 'min-height': '100px', padding: '10px', }).appendTo(cont).text('Default body text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac finibus nisl. Phasellus lacus eros, cursus vel rutrum vel, posuere eu ligula. Integer vestibulum tellus nec lorem pretium, at tristique eros congue. Aenean et vehicula purus. Nunc accumsan felis vitae est consequat faucibus. Nullam quis nibh at augue malesuada consequat quis nec leo. Donec ac pellentesque erat.'); target.elements.push(target2.elements[0], target3.elements[0]); includedStyles.push('tabs' + s); } }); DOM().new('button').class('caa_button-default').text('Add Tab Style').on('click', function(e) { app.addStyle('tabs'); app.render('/' + app.parts[0] + '/' + sec, false, true); }).appendTo(DOM().new('div').css({ 'margin': '20px 10px 10px 10px' }).appendTo(thisSection)); break; case 'Tables': thisSection.css({ padding: 0 }).addClass('text1'); var defaults = [{ '_label': 'Tables (Default)', '.tables0': { 'border-collapse': 'collapse', }, '.tables0 td': { 'padding': '10px' }, '.tables0 td:first-child': { }, '.tables0 th': { 'text-align': 'left', 'padding': '10px' } }]; if (!Array.isArray(app.site.styles.tables)) { app.site.styles.tables = defaults; app.siteUpdate(['styles', 'tables'], defaults); } app.site.styles.tables.forEach(function(style, s) { if (filterDesignItems(style)) { app.objectDefaults(style, defaults[0]); var cont = DOM().new('div').class('ib middle caa_clickSecTarget').css({ 'margin-top': '10px', padding: '10px' }).appendTo(thisSection).on('click', function(e) { app.StyleEditorPanel('tables', style, ['styles', 'tables', s], target); }), classes = { header: style._class_header || 'text0', column: style._class_column || 'text1', cell: style._class_cell || 'text1' }, tableMarkup = ['
', '
Header 1
Header 2
Header 3
', '
', '
Row 1 cell 1
Row 1 cell 2
Row 1 cell 3
', '
Row 2 cell 1
Row 2 cell 2
Row 2 cell 3
', '
Row 3 cell 1
Row 3 cell 2
Row 3 cell 3
', '
' ].join(''), target = DOM().new('div').id('style-label-for-' + sec + '-' + s).html(tableMarkup).appendTo(cont); includedStyles.push('tables' + s); } }); DOM().new('button').class('caa_button-default').text('Add Table Style').on('click', function(e) { app.addStyle('tables'); app.render('/' + app.parts[0] + '/' + sec, false, true); }).appendTo(DOM().new('div').css({ 'margin': '20px 10px 10px 10px' }).appendTo(thisSection)); break; case 'Widgets': thisSection.css({ padding: '10px' }).addClass('text1'); ['overlay-text', 'overlay-background', 'overlay-icons'].forEach(function(key, ki) { Inputs.color({ label: key.replace(/\-/g, ' ').capitalizeFirstLetter(), showvalue: true, getColors: function() { return app.currentColorList(); }, value: app.site.styles.colors[key], onchange: function(color) { var setCSS = {}; setCSS[key] = color; app.siteUpdate(['styles', 'colors'], setCSS); } }).appendTo(DOM().new('div').class('ibb top').css({ 'margin-left': ki ? '10px' : 0 }).appendTo(thisSection)); }); var searchOverlayElements = [{ text: 'None', value: '' }]; app.getCustomElements().forEach(function(item) { searchOverlayElements.push(item); }); Inputs.options({ label: 'Search Overlay Custom Element', value: app.site.settings['search-overlay-custom'] || '', inline: true, options: searchOverlayElements, onchange: function(val) { var setCSS = {}; setCSS['search-overlay-custom'] = val || ''; app.siteUpdate(['settings'], setCSS); } }).appendTo(DOM().new('div').class('ibb top').css({ width: '240px', 'margin-left': '10px' }).appendTo(thisSection)); includedStyles.push('mediaLoading'); var target = DOM().new('span').class('ibb mediaLoading'); DOM().new('div').class('caa_clickSecTarget') .append(DOM().new('div').class('caa_subSectionTitle').text('Media Loading Animation').css({ 'margin': '10px' })) .append(DOM().new('div').css({position: 'relative'}).class('ibb top').css({height: '120px', width: '200px'}).append(target)) .on('click', function(e) { app.StyleEditorPanel('mediaLoading', app.site.styles.widgets || {}, ['styles', 'widgets'], target); }).appendTo(thisSection); break; } var page = new Page(app, app.site, '/__custom', true); content.append(page.dom.css({ display: 'none' })); specialStyles.forEach(function(specialStyle) { app.checkAddStylesFor(specialStyle.className, specialStyle.target); }); page.onload(); var genStyles = function() { var stylesheet = app.genStyleSheet(includedStyles) + app.currentExecutionPage.customCSS; app.removeSheets().applySheet(stylesheet); }; app.onResize(genStyles); genStyles(); thisContent.appendTo(content); app.stage.elements[0].scrollTop = scrollTop; }); /* var checkHighlight = function(secID, goTo){ console.log('checking', secID); var secdom = byID('caa-section' + secID); if (secdom) { DOM().byClass('caa_navItemText').class('caa_navItemText'); DOM().id('nav-item-for-' + secID).byClass('caa_navItemText').addClass('caa_navItemTextOn'); if(goTo){ app.stage.scrollTo(DOM(secdom).pos().offsetTop - 20); } } }, pointsOfInterest = DOM().byClass('caa_section-target'); checkHighlight(app.parts[1] || 'defaults', app.parts[1]); app.onScroll(function(e, scrollTop){ console.log('app scroll'); var found = false, i = 0; while(!found && i < pointsOfInterest.elements.length){ if(pointsOfInterest.elements[i].offsetTop > scrollTop - 100){ found = true; checkHighlight(pointsOfInterest.elements[i].id.replace('caa-section',''), false); } i++; } }); */ }; App.prototype.getAndUpdateFeedback = function() { var app = this; app.Request({ do: 'request', request: 'feedback', cache: 60000 }, function(data) { if (data.feedback && data.feedback.length) { if (!data.pages) { data.pageRef = {}; data.pages = []; var sec, p; for (sec in app.site.content) { for (p in app.site.content[sec]) { data.pages.push({ section: sec, p: p, comments: [] }); } } data.pages.forEach(function(page, pi) { data.pageRef[page.section + '/' + page.p] = pi; }); data.feedback.filter(function(row) { return row.status !== 'Resolved' && row.status !== 'Rejected' }).forEach(function(row) { if (row.area.indexOf('navigation') === 0 || row.area.indexOf('footer') === 0) { data.pages.forEach(function(page) { page.comments.push(row); }) } else { data.pages[data.pageRef[row.page]].comments.push(row); } }) } data.pages.forEach(function(page, pi) { //content screen DOM().id('content-' + page.section + '-' + page.p).exists(function(target) { target.byClass('num-feedback').remove(); if (page.comments.length) { target .byClass('content-text-holder') .append( DOM().new('span').class('num-feedback').css({ position: 'absolute', top: '6px', right: '4px' }) .append(UI.Icon('chat', 'blue')) .append( DOM().new('span').css({ color: '#3FB1E3', position: 'absolute', display: 'block', 'text-align': 'center', 'font-size': '12px', left: '3px', top: '6px', width: '20px' }).text(page.comments.length) ) .on('click', function(e) { setTimeout(function() { // opens workflow tab app.rightPanel.find('div.caa_rightPanelTab[data-tab="workflow"]').trigger('click'); }, 300) }) ); } }); // page editor worfklow tab if(app.rightPanel){ DOM().id('page-editor-for-' + page.section + '-' + page.p).exists(function(target) { var tab = app.rightPanel.find('div.caa_rightPanelTab[data-tab="workflow"]').byClass('caa_icon-tabs').css({ position: 'relative' }); tab.byClass('num-feedback').remove(); if (page.comments.length) { tab.append( DOM().new('div').class('num-feedback').css({ position: 'absolute', left: '-2.5px', top: '3px', right: 0, 'text-align': 'center', 'font-size': '8px' }).text(page.comments.length) ); } }); } //left panel content menu DOM().find('.caa_subNavItem[data-page-target="' + page.section + '-' + page.p + '"]').exists(function(target) { target.byClass('num-feedback').remove(); if(page.comments.length){ target .append( DOM().new('span').class('num-feedback').css({ position: 'absolute', top: '10px', right: '4px' }) .append(UI.Icon('chat', 'blue', 24)) .append( DOM().new('span').css({ color: '#3FB1E3', position: 'absolute', display: 'block', 'text-align': 'center', 'font-size': '10px', left: '0', top: '4px', width: '20px' }).text(page.comments.length) ) .on('click', function(e) { setTimeout(function() { // opens workflow tab app.rightPanel.find('div.caa_rightPanelTab[data-tab="workflow"]').trigger('click'); }, 300) }) ); } }); }); } }); }; App.prototype.feeds = function() { var app = this; // mark content as the highlighted nav section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.contentMenu(false); app.stage.html(''); var appHeader = DOM().new('div').class('caa_content caa_header'), backLink = '/content', moreText = '', setSortValue = function(sort, post, itemDom) { if (sort === '-date') { itemDom.attr({ 'data-sort-value': !post.date ? 0 : ((new Date().getTime() * 2) - new Date(post.date).getTime()) || 0 }); } else if (self.sort === 'title') { itemDom.attr({ 'data-sort-value': post.title }); } else if (sort === 'date') { itemDom.attr({ 'data-sort-value': !post.date ? 0 : new Date(post.date).getTime() || 0 }); } }; var content = DOM().new('div').class('caa_content').appendTo(app.stage); if (app.parts[1]) { if (!hasSiteAccess(app.user.access, 'feeds/' + app.parts[1])) { app.stage.html('You do not have access to this section'); return false; } var feedID = app.parts[1]; var item = app.site.feeds[feedID]; if (item) { moreText = ': ' + item.name; var in_levels = app.parts.length - 2; if (in_levels) { var levelPathRef = item; for(var i = 0; i<(in_levels+1); i++) { levelPathRef = (levelPathRef.items ? levelPathRef.items[app.parts[2+i]] : '') || '' if (levelPathRef) { moreText += ': ' + levelPathRef.title; } } } app.subscribe('feeds/' + feedID, function onchangeFeeds() { if (item.source === 'manual') { //TIMEOUT HELPS ENSURE CLICK TRIGGERED BEFORE RE-RENDER setTimeout(function() { var feedItemEdit = false, getPath = app.parts.slice(0, 2); if (app.parts.length > 1) { app.parts.forEach(function(part, p) { if (p > 1) { getPath.push('items', part); } }) if (getPath.length > 2) { feedItemEdit = app.getFromPath(getPath); } } var renderFeedItem = function(feedItem, r, itemPath, level, into, totalLen) { var feedItemRow = DOM().new('div').class('caa_row caa_row_hover').css({ 'padding': '10px', overflow: 'hidden', opacity: feedItem.disabled ? 0.5 : '' }).insertFirst(into); if (item.sort) { setSortValue(item.sort, feedItem, feedItemRow); feedItemRow.appendSort(into) } var feedItemHolder = DOM().new('div').class('caa_click').appendTo(feedItemRow); var mr = '0'; if (feedItem.media) { if (typeof feedItem.media === 'object') { if (totalLen > 20 && feedItem.media.media) { DOM().new('img').attr({ src: mediaSource(app.site, feedItem.media, 100) }).css({ float: 'right', 'max-width': '25%' }).appendTo(feedItemHolder); } else { DOM().new('div').css({ float: 'right', 'max-width': '25%' }).append(app.Media(feedItem.media)).appendTo(feedItemHolder); } } else { DOM().new('div').css({ float: 'right', 'max-width': '25%' }).html(feedItem.media).appendTo(feedItemHolder); } mr = 'calc(25% + 10px)'; } if (feedItem.title) { DOM().new('div').css({ 'font-weight': 'bold', margin: '10px ' + mr + ' 10px 0', }).html(feedItem.title).appendTo(feedItemHolder); } if (feedItem.body) { DOM().new('div').css({ 'margin-right': mr }).html(feedItem.body).css({ overflow: 'hidden', 'max-height': '200px' }).appendTo(feedItemHolder); } if (!(feedItemHolder.html() || '').trim()) { DOM().new('div').css({ 'margin-right': mr }).text('No title/body').css({ overflow: 'hidden', 'max-height': '200px', color: '#ccc' }).appendTo(feedItemHolder); } var subItems = DOM().new('div').appendTo(feedItemHolder); if (feedItem.date) { DOM().new('span').text(displayDate(parseAnyDate(feedItem.date))).css({ 'text-decoration': 'italic' }).appendTo(subItems); DOM().new('span').text(' ').appendTo(subItems); } if (feedItem.url || feedItem.link_url) { DOM().new('a').attr({ href: (feedItem.url || feedItem.link_url), target: '_blank' }).text((feedItem.url || feedItem.link_url)).appendTo(subItems); DOM().new('span').text(' ').appendTo(subItems); } if (feedItem.tags) { DOM().new('div').html('
Tags:
' + feedItem.tags.join(', ')).appendTo(feedItemHolder); } feedItemHolder.on('click', function(e) { var clickPath = itemPath.filter(function(key) { return key !== 'items' }).join('/') app.render('/' + clickPath, false, false); app.EditorPanel('FeedEditorItem', app.getFromPath(itemPath), itemPath, feedItemHolder); }); if (level < item.levels) { var feedItemSubs = DOM().new('div').appendTo(feedItemRow), feedItemSubsOps = DOM().new('div') .append(DOM().new('span').class('ibb middle')) .append(DOM().new('span').class('ibb middle').css({ 'min-width': '120px', 'margin-left': '10px' }).text((feedItem.items || []).length + ' Sub-Items')) .appendTo(feedItemSubs); var feedItemSubHolder = DOM().new('div').appendTo(feedItemSubs); if (feedItem.items) { feedItem.items.forEach(function(subFeedItem, sr) { renderFeedItem(subFeedItem, sr, itemPath.concat('items', sr), level + 1, feedItemSubHolder, totalLen); }); } DOM().new('button').class('caa_button-default').css({ 'margin-left': '10px' }).text('Add Sub-Item').on('click', function(e) { var update = { items: feedItem.items ? feedItem.items.slice(0) : [] }; update.items.push(newItem); app.siteUpdate(itemPath, update); }).appendTo(feedItemSubsOps); } }; if (feedItemEdit) { if (!app.isEditing) { content.html(''); moreText = ': ' + item.name + ' Post #' + (app.parts[2] + 1); //backLink = '/feeds/' + feedID; backLink = '/' + app.parts.slice(0,-1).join('/') var feedItemContent = DOM().new('div').class('caa_padding').appendTo(content); var clickBoxOpenPanel = function(e) { app.EditorPanel('FeedEditorItem', feedItemEdit, getPath, feedItemContent); }; if (feedItemEdit.description && !feedItemEdit.body) { feedItemEdit.body = feedItemEdit.description + ''; delete feedItemEdit.description; } DOM().new('label').class('caa_panelInputLabel').text('Title').appendTo(feedItemContent); console.log('styles', app.site.styles); var colorConfig = { title_light: colorIsLight(app.site.styles.text[0]['.text0'].color || app.site.styles.colors.text), title_size: num(app.site.styles.text[0]['.text0']['font-size']), body_light: colorIsLight(app.site.styles.text[1]['.text1'].color || app.site.styles.colors.text), body_size: num(app.site.styles.text[1]['.text1']['font-size']), block_light: colorIsLight(app.site.styles.blocks[0]['.blocks0']['background-color'] || app.site.styles.colors.background) }; var title = DOM().new('div').class('text0').css({ 'min-height': '30px', color: colorConfig.title_light && colorConfig.block_light ? '#000' : (!colorConfig.title_light && !colorConfig.block_light) ? '#fff' : '', 'font-size': colorConfig.title_size > 50 ? '50px' : '', 'line-height': 'normal', 'letter-spacing': 'normal' }).html(feedItemEdit.title || '').appendTo(feedItemContent).on('click', clickBoxOpenPanel); DOM().new('label').class('caa_panelInputLabel').text('Body').appendTo(feedItemContent); var body = DOM().new('div').class('text1').css({ 'min-height': '100px', color: colorConfig.body_light && colorConfig.block_light ? '#000' : (!colorConfig.body_light && !colorConfig.block_light) ? '#fff' : '', 'font-size': colorConfig.body_size > 30 ? '30px' : '', 'line-height': 'normal', 'letter-spacing': 'normal' }).html(feedItemEdit.body || '').appendTo(feedItemContent).on('click', clickBoxOpenPanel); var page = new Page(app, app.site, '/__custom', true, {}, feedItemEdit); feedItemContent.append(page.dom.css({ display: 'none' })); page.addClass('text0', 'text1', 'inline-left', 'inline-right'); page.onload(); var stylesheet = app.genStyleSheet(page.classArray); app.removeSheets().applySheet(stylesheet); app.Editable("text", title, feedItemEdit, getPath, 'title'); app.Editable("text", body, feedItemEdit, getPath, 'body'); app.displayContentMedia(feedItemContent, true); feedItemContent.byClass('camediaload').loadMedia(); } var level = getPath.filter(function(key){ return key === 'items'}).length if (level < (item.levels*1+1)) { var newItem = { title: 'New Item Title' }; var feedAdder = DOM().newOrFind('div', 'feedAdder').html('').append( DOM().new('button').class('caa_button-default').text('Add Sub-Item').on('click', function(e) { var update = { items: feedItemEdit.items ? feedItemEdit.items.slice(0) : [] }; update.items.push(newItem); app.siteUpdate(getPath, update); }) ).appendTo(feedItemContent); } var feedRows = DOM().newOrFind('div', 'feedRows').html('').appendTo(feedItemContent); if (feedItemEdit.items) { feedItemEdit.items.forEach(function(subFeedItem, sr) { renderFeedItem(subFeedItem, sr, getPath.concat('items', sr), level + 1, feedRows, 10); }); } feedRows.byClass('camediaload').loadMedia({ viewPort: 2 }); } else { var newItem = { title: 'New Item Title' }; var feedAdder = DOM().newOrFind('div', 'feedAdder').class('caa_padding').html('').append( DOM().new('button').class('caa_button-default').text('Add Item').on('click', function(e) { if (typeof item.items === 'object') { app.siteAdd(['feeds', feedID, 'items'], newItem); } else { app.siteUpdate(['feeds', feedID], { items: [newItem] }); } }) ).appendTo(content); var feedRows = DOM().newOrFind('div', 'feedRows').html('').appendTo(content); if (item.items) { item.items.forEach(function(feedItem, r) { renderFeedItem(feedItem, r, ['feeds', feedID, 'items', r], 0, feedRows, item.items.length); }); } feedRows.byClass('camediaload').loadMedia({ viewPort: 2 }); } }, 10); } else { content.html(''); var sourceInfo = contentSources[item.source]; var notes = 'Feed ' + item.name + ' Source: ' + (item.source || 'No Source Set') + ' Account: ' + (item.account || 'No Account Set'); DOM().new('div').class('caa_padding').html(notes + ' ').appendTo(content) .append(DOM().new('a').attr({ href: '#' }).text('Reload Uncached').on('click', function(e) { e.preventDefault(); item.cachebust = true; renderFeedItems(); delete item.cachebust; })); var feedContent = DOM().new('div').appendTo(content), renderFeedItems = function() { item.id = feedID; app.getFeedItems(item, function(feed) { feedContent.html(''); var okay = false; if (feed) { if (feed.items) { okay = true; feed.items.forEach(function(feedItem) { var feedItemHolder = DOM().new('div').css({ 'padding': '10px', 'border-bottom': '1px solid #ccc', overflow: 'hidden' }).appendTo(feedContent).on('click', function(e) { var modal = UI.openModal(feedItemHolder); DOM().new('a').attr({ href: '#' }).css({ position: 'absolute', top: '10px', left: '10px', background: '#fff', padding: '4px' }).text('show data').on('click', function(e) { e.preventDefault(); if (pre.showing) { pre.css({ display: 'none' }).showing = false; DOM(e.target).text('show data'); } else { pre.css({ display: '' }).showing = true; DOM(e.target).text('hide data'); } }).appendTo(modal); var pre = DOM().new('pre').css({ padding: '20px', 'white-space': 'pre-wrap', display: 'none' }).text(JSON.stringify(feedItem, undefined, 2)).appendTo(modal); if (item.template) { app.tmp.tmpPreview = app.getFromPath(['content'].concat(item.template.split('/').slice(0, 2))); } else { app.tmp.tmpPreview = { items: [{ title: '{{title}}', body: '{{body}}', media: feedItem.media ? feedItem.media : false }] }; } if (app.tmp.tmpPreview) { app.preview('/__key/tmpPreview', modal, {}, feedItem); } }); if (item.sort) { setSortValue(item.sort, feedItem, feedItemHolder); feedItemHolder.appendSort(feedContent) } var mr = ''; if (feedItem.media) { if (typeof feedItem.media === 'object') { DOM().new('div').css({ float: 'right', 'max-width': '25%' }).append(app.Media(feedItem.media)).appendTo(feedItemHolder); } else { DOM().new('div').css({ float: 'right', 'max-width': '25%' }).html(feedItem.media).appendTo(feedItemHolder); } mr = 'calc(25% + 10px)'; } if (feedItem.title) { DOM().new('h2').css({ 'margin-right': mr }).html(feedItem.title).appendTo(feedItemHolder); } if (feedItem.body) { DOM().new('div').css({ 'margin-right': mr }).html(feedItem.body).css({ overflow: 'hidden', 'max-height': '200px' }).appendTo(feedItemHolder); } var subItems = DOM().new('div').appendTo(feedItemHolder); if (feedItem.date) { DOM().new('span').text(displayDate(feedItem.date)).css({ 'text-decoration': 'italic' }).appendTo(subItems); DOM().new('span').text(' ').appendTo(subItems); } if (feedItem.url || feedItem.link_url) { DOM().new('a').attr({ href: (feedItem.url || feedItem.link_url), target: '_blank' }).text((feedItem.url || feedItem.link_url)).appendTo(subItems); DOM().new('span').text(' ').appendTo(subItems); } }); } DOM().byClass('camediaload').loadMedia(); } if (!okay && item.source) { feedContent.append(DOM().new('div').class('caa_padding').text('we could not load the content')); } }); }; renderFeedItems(); } }); } else { DOM().new('div').class('caa_padding').text('Not found.').appendTo(content); moreText = ': Not Found'; } backLink = '/feeds'; appHeader.append(UI.Icon('left', 'head').on('click', function(e) { app.destroyPanels(); app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Feeds' + moreText)) .insertFirst(app.stage); } else { if (!hasSiteAccess(app.user.access, 'feeds', true)) { app.stage.html('You do not have access to this section'); return false; } appHeader.append(UI.Icon('left', 'head').on('click', function(e) { app.destroyPanels(); app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Feeds' + moreText)) .insertFirst(app.stage); var feedContainer = DOM().new('div').class('caa_grid').appendTo(content); app.subscribe('feeds', function onchangeFeeds() { feedContainer.html(''); Object.keys(app.site.feeds).sort(function(a, b) { return b - a; }).forEach(function(feedID) { if (hasSiteAccess(app.user.access, 'feeds/' + feedID)) { var item = app.site.feeds[feedID]; var itemDOM = DOM().new('div').class('caa_row caa_clickSecTarget').text(item.name).appendTo(feedContainer).on('click', function(e) { app.render('/feeds/' + feedID, false, false); }); } }); }); } }; App.prototype.getFeedItems = function(item, callback) { var app = this; if (item.source === 'manual') { callback(item); return this; } var sourceGet = 'get'; if (item.source === 'site') { sourceGet = 'getFromSite'; } else if (!item.source) { return this; } var getURL = '/__get/' + item.source + '/name:' + encodeURIComponent(item.account || ''), moreURL = ''; if (item.opengraph) { moreURL += '/opengraph:true'; } if (item.tag) { moreURL += '/tag:' + (item.tag || ''); } if (item.opengraph) { moreURL += '/opengraph:true'; } if (item.imagecache) { moreURL += '/imagecache:true'; } if (item.body_markup) { moreURL += '/body_markup:true'; } if (item.publish) { moreURL += '/publish:' + item.publish; } if (item.cachebust) { moreURL += '/cachebust:true'; } if (item.cache_duration) { moreURL += '/cache_duration:' + item.cache_duration; } if (item.source === 'json') { getURL = '/__get/' + item.source + '/site:' + app.site.id + '/feed:' + item.id + moreURL; } app[sourceGet](getURL + moreURL, { json: true, tag: item.tag || false }, function(data) { if (data.items) { var i = 0, len = data.items.length; for (; i < len; i++) { if (data.items[i].title) { data.items[i].title = cleanMarkup(data.items[i].title); } if (data.items[i].body) { data.items[i].body = cleanMarkup(data.items[i].body); } } } callback(data); }); return this; }; App.prototype.footer = function() { var app = this; var footIndex = app.parts[1] || 0; if (!hasSiteAccess(app.user.access, 'footer/' + footIndex)) { app.stage.html('You do not have access to this section'); return false; } // mark content as the highlighted footer section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.subscribe('footer', function onchangeContentMenu() { app.contentMenu(false); }); app.stage.html(''); var appHeader = DOM().new('div') .class('caa_content caa_header') .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/content', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Footer: ' + (app.site.footer[footIndex].label || 'footer ' + footIndex))) .insertFirst(app.stage); var content = DOM().new('div').class('caa_content').appendTo(app.stage); var theseClasses = ['page0', 'text1', 'footer' + footIndex]; DOM().new('div').class('caa_sectionBar').text('Desktop Preview').appendTo(content); var footHolder = DOM().new('div').appendTo(content).css({ 'margin-bottom': '20px' }); DOM().new('div').class('caa_sectionBar').text('Mobile Preview').appendTo(content); var footHolderM = DOM().new('div').appendTo(content).css({ 'margin-bottom': '20px' }); app.subscribe('footer', function onchangeFooter() { footHolder.html(''); app.preview('/__foot', footHolder).css({ height: '400px', width: '1280px' }); footHolderM.html(''); app.preview('/__foot', footHolderM).css({ height: '400px', width: '420px' }); }); }; Page.prototype.renderFooter = function(app, footIndex, into, useFooter) { var thisPage = this; if (!footIndex) { footIndex = 0; } var siteFooter = useFooter || app.site.footer[footIndex]; if(!useFooter) { if (!app.site.footer[footIndex].customElement) { delete app.site.footer[footIndex].customElementConfig; } if (!app.site.footer[footIndex].config) { app.site.footer[footIndex].config = {}; } var footerStylesSrc = { '.footer0': { 'background-color': '' }, '.footer0h': { 'position': 'relative', 'max-width': '1280px', 'margin': '0 auto' }, '.footer0ul': { 'margin': '0 auto', 'padding': 0, 'max-width': '1280px' }, '.footer0ul:before': { 'content': '\'\'', 'min-height': 0, 'font-size': 0, 'display': 'inline-block', '@700@display': 'none', 'vertical-align': 'middle' }, '.footer0ulli': { 'display': 'inline-block', 'vertical-align': 'middle', 'list-style-type': 'none' }, '.footer0ullia': { 'display': 'block', 'text-decoration': 'none', 'padding': '10px' }, '.footer0ullia:active': { '': '' }, }; var footerStyles = {}; var hadToFix = false; if(siteFooter.styles) { for(var k in siteFooter.styles) { var key = (k.replace(/\d+/i, '') * 1) + ''; if( key != footIndex && !isNaN(key)){ siteFooter.styles = JSON.parse(JSON.stringify(siteFooter.styles).replace(new RegExp('.footer' + key, 'g'), '.footer' + footIndex)) hadToFix = true; } } } for (var k in footerStylesSrc) { footerStyles[k.replace(/\.footer0/ig, '.footer' + footIndex)] = footerStylesSrc[k]; } if(!app.site.footer[footIndex].styles){ app.site.footer[footIndex].styles = {}; } var setNewDefaults = app.objectDefaults(app.site.footer[footIndex].styles, footerStyles); if(app.parts[0] === 'footer'){ if(hadToFix || setNewDefaults) { app.siteUpdate(['footer', 'styles'], siteFooter.styles); } } } var footID = 'footer' + footIndex, foot = DOM().new('footer').id(footID).class('footer' + footIndex).appendTo(into), footHolder = DOM().new('div').id(footID + 'h').class('footer' + footIndex + 'h').appendTo(foot), listHolder, ul, useColumns = false; if (siteFooter.useBlockAbove) { var blockPath = siteFooter.useBlockAbove.split('/'), block = app.getFromPath(blockPath); if (block) { thisPage.renderBlock(block, blockPath, 0, 'foot-block-0', foot, foot, false); } footHolder.appendTo(foot); // throws this under } if (siteFooter.items) { siteFooter.items.forEach(function(footItem) { if (footItem.items) { if (footItem.items.length) { useColumns = true; } } }); } if (siteFooter.backgroundMedia) { app.Media(siteFooter.backgroundMedia, foot); } this.addClass('page0', 'text1'); if (!siteFooter.customElementConfig) { this.addClass('footer' + footIndex); } if (siteFooter.items && Object.keys(siteFooter.items).length) { var footContainerType = (siteFooter.items.length <= 1) ? 'ul' : 'div', rowForItem = {}, rowHas = {}, curRow = 0; listHolder = DOM().new(footContainerType).class('footer' + footIndex + 'ul').css({display: 'inline-block', width: '100%'}).appendTo(footHolder); siteFooter.items.forEach(function(footItem, f, ar) { if (ar.length > 1) { if (footItem.newRow) { curRow++; } rowForItem[f] = curRow * 1; rowHas[curRow] = rowHas[curRow] ? (rowHas[curRow] + 1) : 1; } }); siteFooter.items.forEach(function(footItem, f) { var li; if (siteFooter.items.length) { if (rowHas[rowForItem[f]] > 1) { var gridClass = !siteFooter.inlineGrid ? ' grid-' + rowHas[rowForItem[f]] : ' grid-stack'; if (siteFooter.inlineGrid && siteFooter.inlineGridNoStack) { gridClass = ''; } var ulAlignment = siteFooter.config.itemAlignment || 'middle'; ul = DOM().new('ul').class('footer' + footIndex + 'ul-sub ibb ' + ulAlignment + gridClass).css({padding: 0}).appendTo(listHolder); if (gridClass) { thisPage.addClass(gridClass); } } else { ul = DOM().new('ul').class('footer' + footIndex + 'ul-sub').css({padding: 0}).appendTo(listHolder); } if (footItem.itemAlignment) { ul.addClass('taln-' + footItem.itemAlignment[0]); thisPage.addClass('taln-' + footItem.itemAlignment[0]); } if (footItem.itemMobileAlignment) { ul.addClass('taln-' + footItem.itemMobileAlignment[0] + '-m'); thisPage.addClass('taln-' + footItem.itemMobileAlignment[0] + '-m'); } li = DOM().new('li').class('footer' + footIndex + 'ulli').css({ 'list-style-type': 'none' }).appendTo(ul); } else { li = DOM().new('li').css({ 'list-style-type': 'none' }).class('footer' + footIndex + 'ul').appendTo(listHolder); } var aClass = 'footer' + footIndex + 'ullia', atype = footItem.link ? 'a' : 'div', a; if (footItem._title) { if (footItem._title.class) { aClass += ' ' + footItem._title.class; thisPage.addClass(footItem._title.class); } } if (footItem.title && !footItem.media) { a = DOM().new(atype).class(aClass).appendTo(li).html(!footItem.hideTitle ? footItem.title : ''); } else if (footItem.media) { a = DOM().new(atype).class(aClass).appendTo(li); if (footItem.title && !footItem.hideTitle) { DOM().new('span').class('ibb middle').html(footItem.title).appendTo(a); } var insertFunc = 'insertFirst', mediaDisp = ''; if (footItem.media.position === 'top' || footItem.media.position === 'right') { insertFunc = 'appendTo'; } if (footItem.media.position === 'top' || footItem.media.position === 'bottom') { mediaDisp = 'block'; } app.Media(footItem.media, false).css({ display: mediaDisp })[insertFunc](a); } else { li.remove(); } if(a) { if(footItem.style){ a.css(footItem.style); } if (footItem.link) { a.attr({ href: footItem.link, target: footItem.target || '' }); } if (footItem.target === 'overlay' || footItem.target === 'search') { var footItemID = genUID('nav-item'); a.id(footItemID).attr({ href: '' }); thisPage.configureContentLink(footItem, a, footItemID); } } if (footItem.items) { footItem.items.forEach(function(subitem, si) { var li = DOM().new('li').class('footer' + footIndex + 'ulli').appendTo(ul); if (footItem.subItemStacking === 'inline') { li.addClass('ib middle'); } else { li.css({display: 'block'}); } var aClass = 'footer' + footIndex + 'ullia'; if (subitem._title) { if (subitem._title.class) { aClass += ' ' + subitem._title.class; thisPage.addClass(subitem._title.class); } } var atype = subitem.link ? 'a' : 'div', a; if (subitem.title && !subitem.media) { a = DOM().new(atype).class(aClass).appendTo(li).html(!subitem.hideTitle ? subitem.title : ''); } else if (subitem.media) { a = DOM().new(atype).class(aClass).appendTo(li); if (subitem.title && !subitem.hideTitle) { DOM().new('span').class('ibb middle').html(subitem.title).appendTo(a); } var insertFunc = 'insertFirst', mediaDisp = ''; if (subitem.media.position === 'top' || subitem.media.position === 'right') { insertFunc = 'appendTo'; } if (subitem.media.position === 'top' || subitem.media.position === 'bottom') { mediaDisp = 'block'; } app.Media(subitem.media, false).css({ display: mediaDisp })[insertFunc](a); } else { li.remove(); } if(a) { if(subitem.style){ a.css(subitem.style); } if(subitem.link){ a.attr({ href: subitem.link, target: subitem.target || '' }); } if (footItem.target === 'overlay' || footItem.target === 'search') { var footItemID = genUID('nav-item'); a.id(footItemID).attr({ href: '' }); thisPage.configureContentLink(footItem, a, footItemID); } } }); } }); } if (siteFooter.customElement) { var customFooter = app.Media({ media: siteFooter.customElement }); if (siteFooter.customElementConfig === 'replace') { foot.html(foot.html() + customFooter.html()); } else { foot.html(foot.html() + customFooter.html()); } } if (siteFooter.useBlockBelow) { var blockPath = siteFooter.useBlockBelow.split('/'), block = app.getFromPath(blockPath); if (block) { thisPage.renderBlock(block, blockPath, 0, 'foot-block-1', foot, foot, false); } } }; App.prototype.generateAnalytics = function(into, config) { var app = this, pieLegendTemplate = '<% for (var i=0; i
\">
<%=segments[i].label%>
<%}%>', data = { line: { holder: DOM().new('div').css({ height: '400px', margin: '10px 20px' }), datablocks: { newusers: { title: 'New Visitors', total: 0, data: [] }, users: { title: 'Visitors', total: 0, selected: true, data: [] }, pageviews: { title: 'Pageviews', total: 0, data: [] }, submissions: { title: 'Submissions', total: 0, data: [] }, bandwidth: { title: 'Gigabytes', total: 0, data: [] } }, labels: [], datasets: [{ label: 'Visitors', fillColor: '#00B375', strokeColor: '#00B375', pointColor: '#00B375', pointStrokeColor: '#fff', pointHighlightFill: '#fff', pointHighlightStroke: '#00B375', data: [] }] }, browsers: { holder: DOM().new('div').class('caa_grid caa_cols-3'), options: { showScale: true, legendTemplate: pieLegendTemplate }, data: [{ value: 0, color: '#00B375', highlight: '', label: 'Chrome' }, { value: 0, color: '#FF9326', highlight: '', label: 'Firefox' }, { value: 0, color: '#cc66ff', highlight: '', label: 'Safari' }, { value: 0, color: '#3cf', highlight: '', label: 'Edge' }, { value: 0, color: '#00A3D9', highlight: '', label: 'Internet Explorer' }, { value: 0, color: 'Red', highlight: '', label: 'Other' }] }, oses: { holder: DOM().new('div').class('caa_grid caa_cols-3'), options: { showScale: true, legendTemplate: pieLegendTemplate }, data: [{ value: 0, color: '#00A3D9', highlight: '', label: 'Windows' }, { value: 0, color: '#666', highlight: '', label: 'iOS' }, { value: 0, color: '#999', highlight: '', label: 'Macintosh' }, { value: 0, color: '#00B375', highlight: '', label: 'Android' }, { value: 0, color: 'Yellow', highlight: '', label: 'Chrome OS' }, { value: 0, color: 'Red', highlight: '', label: 'Linux/Other' }] }, screens: { holder: DOM().new('div').class('caa_grid caa_cols-3'), options: { showScale: true, legendTemplate: pieLegendTemplate }, data: [{ value: 0, color: '#99c2ff', highlight: '', label: 'Mobile (<= 600px)' }, { value: 0, color: '#66a3ff', highlight: '', label: 'Tablet (<= 1200px)' }, { value: 0, color: '#3385ff', highlight: '', label: 'Laptop/Desktop (<= 1920px)' }, { value: 0, color: '#06f', highlight: '', label: 'Large Display (> 1920px)' }] } }; into.html(''); UI.Spinner('24').addClass('caa_padding findSpinner').appendTo(into); app.getFeed(function() { console.log('sitefeed',app.siteFeed) app.Request({ do: 'request', request: 'analytics', start_date: config.start_date || false, end_date: config.end_date || false }, function(analyticsData) { into.byClass('findSpinner').remove(); var analyticsSections = { line: DOM().new('div').appendTo(into).append(data.line.holder), technologiesHolder: DOM().new('div').append(DOM().new('div').class('caa_sectionBar').text('Technologies')).appendTo(into), topContentHolder: DOM().new('div').append(DOM().new('div').class('caa_sectionBar').text('Top Content')).appendTo(into) }; analyticsSections.technologies = DOM().new('div').class('caa_padding').appendTo(analyticsSections.technologiesHolder).append(data.browsers.holder).append(data.oses.holder).append(data.screens.holder); analyticsSections.topContent = DOM().new('div').class('caa_padding').appendTo(analyticsSections.topContentHolder); analyticsSections.lineLegend = DOM().new('div').class('caa_padding').appendTo(analyticsSections.line); if (analyticsData.results) { analyticsData.results.forEach(function(result) { if (!result.rows) { result.rows = []; } if (result.title === 'Traffic') { var useData = result.rows; if(result.rows.length > 30) { useData = []; var addRow; result.rows.forEach(function(row){ var d = parseAnyDate(row[0]); if(!addRow || d.getDay() === 0){ addRow = [row[0], 0, 0, 0, 0]; useData.push(addRow); } for(var a = 1; a< row.length; a++){ addRow[a] += row[a] * 1; } }) } useData.forEach(function(row) { var d = parseAnyDate(row[0]), ymd = d.toISOString().substr(0, 10), numSubs = 0, numBW = 0; if (app.siteFeed[ymd]) { numSubs = app.siteFeed[ymd].submissions || 0; numBW = app.siteFeed[ymd].bandwidth || 0; if (numBW) { numBW = numBW / 1073741824; // Gigabytes } } data.line.datablocks.bandwidth.data.push(Math.round(numBW * 10) / 10); data.line.datablocks.bandwidth.total += numBW; data.line.datablocks.submissions.data.push(numSubs); data.line.datablocks.submissions.total += numSubs; data.line.datablocks.pageviews.data.push(row['3'] || 0); data.line.datablocks.pageviews.total += row['3'] * 1; data.line.datablocks.users.data.push(row['2'] || 0); data.line.datablocks.users.total += row['2'] * 1; data.line.datablocks.newusers.data.push(row['1'] || 0); data.line.datablocks.newusers.total += row['1'] * 1; data.line.datasets[0].data.push(row['2'] || 0); data.line.labels.push(displayDate(d)); }); } else if (result.title === 'Top Content') { var renderTopContent = function() { analyticsSections.topContent.html(''); result.rows.forEach(function(row, r) { if (r < renderTopContentMax) { DOM().new('div').class('caa_row') .append(DOM().new('span').class('ib middle ellipsis').css({ width: 'calc(100% - 50px)' }).text(row[0])) .append(DOM().new('span').class('ib middle').text(row[1])) .appendTo(analyticsSections.topContent); } }); }, renderTopContentMax = 5; renderTopContent(); if (result.rows.length > renderTopContentMax) { DOM().new('button').class('caa_button-default').css({ 'margin-top': '20px' }).text('Show ' + (result.rows.length - renderTopContentMax) + ' More Item(s)').appendTo(analyticsSections.topContent).on('click', function(e) { renderTopContentMax = result.rows.length; renderTopContent(); }); } } else if (result.title === 'Technologies') { result.rows.forEach(function(row) { if (row[0].match(/Chrome/)) { data.browsers.data[0].value += row[3] * 1; } else if (row[0].match(/Firefox/) || row[0].match(/Mozilla/)) { data.browsers.data[1].value += row[3] * 1; } else if (row[0].match(/Safari/)) { data.browsers.data[2].value += row[3] * 1; } else if (row[0].match(/Edge/)) { data.browsers.data[3].value += row[3] * 1; } else if (row[0].match(/Internet Explorer/)) { data.browsers.data[4].value += row[3] * 1; } else { data.browsers.data[5].value += row[3] * 1; } if (row[1].match(/Windows/)) { data.oses.data[0].value += row[3] * 1; } else if (row[1].match(/iOS/)) { data.oses.data[1].value += row[3] * 1; } else if (row[1].match(/Macintosh/)) { data.oses.data[2].value += row[3] * 1; } else if (row[1].match(/Android/)) { data.oses.data[3].value += row[3] * 1; } else if (row[1].match(/Chrome/)) { data.oses.data[4].value += row[3] * 1; } else { data.oses.data[5].value += row[3] * 1; } var w = row[2].split('x')[0] * 1; if (w <= 600) { data.screens.data[0].value += row[3] * 1; } else if (w <= 1200) { data.screens.data[1].value += row[3] * 1; } else if (w <= 1920) { data.screens.data[2].value += row[3] * 1; } else { data.screens.data[3].value += row[3] * 1; } }); } }); } // round to 1 dec bandwith data.line.datablocks.bandwidth.total = Math.round(data.line.datablocks.bandwidth.total * 10) / 10; Object.keys(data.line.datablocks).forEach(function(key) { var line = data.line.datablocks[key], addClass = ''; if (line.selected) { addClass = ' caa_rightPanelTabSelected'; } var lineSec = DOM().new('div').class('caa_cols-5 caa_click caa_clickSecTarget' + addClass) .append( DOM().new('div').class('caa_padding') .append(DOM().new('div').text(line.total)) .append(DOM().new('div').text(line.title)) ) .appendTo(analyticsSections.lineLegend) .on('click', function(e) { analyticsSections.lineLegend.byClass('caa_rightPanelTabSelected').removeClass('caa_rightPanelTabSelected'); lineSec.addClass('caa_rightPanelTabSelected'); data.line.datasets[0].label = line.title; data.line.datasets[0].data = data.line.datablocks[key].data; DOM().id('lineChart').remove(); DOM().new('canvas').id('lineChart').appendTo(data.line.holder); new Chart(document.getElementById('lineChart').getContext('2d')).Line(data.line, {}); }); }); loadScript('https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js', function(e) { console.log('load script go'); Chart.defaults.global.maintainAspectRatio = false; Chart.defaults.global.responsive = true; Chart.defaults.Line.tooltipTemplate = '<%= label %> <%= datasetLabel %>: <%= value %>'; DOM().new('canvas').id('lineChart').appendTo(data.line.holder); new Chart(document.getElementById('lineChart').getContext('2d')).Line(data.line, { scaleSteps: 20 }); DOM().new('canvas').id('browsersChart').appendTo(data.browsers.holder); var donutChart = new Chart(document.getElementById('browsersChart').getContext('2d')).Doughnut(data.browsers.data, data.browsers.options); DOM().new('div').class('ib middle').html(donutChart.generateLegend()).appendTo(data.browsers.holder); DOM().new('canvas').id('osesChart').appendTo(data.oses.holder); var osesChart = new Chart(document.getElementById('osesChart').getContext('2d')).Doughnut(data.oses.data, data.oses.options); DOM().new('div').class('ib middle').html(osesChart.generateLegend()).appendTo(data.oses.holder); DOM().new('canvas').id('screensChart').appendTo(data.screens.holder); var screensHolder = new Chart(document.getElementById('screensChart').getContext('2d')).Doughnut(data.screens.data, data.screens.options); DOM().new('div').class('ib middle').html(screensHolder.generateLegend()).appendTo(data.screens.holder); }); }); }); }; App.prototype.hub = function() { var app = this, subSections = [{ title: 'Analytics', icon: '', link: '/analytics' }, { title: 'Form Submissions', icon: '', link: '/submissions' }, { title: 'Recommendations', icon: '', link: '/recommendations' }, { title: 'SEO', icon: '', link: '/seo' }, { title: 'Changes', icon: '', link: '/changes' }, /*, { title: 'Quality Assurance', icon: '', link: '/quality' }, { title: 'Internationalization', icon: '', link: '/internationalization' },*/ { title: 'Usage', icon: '', link: '/usage' }, { title: 'Billing', icon: '', link: '/billing' }, { title: 'Profile', icon: '', link: '/profile' }, { title: 'Support', icon: '', link: '/support' } ]; app.stage.html(''); app.subNavContainer.html(''); app.listeners.checkSite = function() { app.checkWarnings(); }; app.checkWarnings(); subSections.forEach(function(subSection) { if (hasSiteAccess(app.user.access, 'hub' + subSection.link)) { DOM().new('a').class('caa_subNavItem') .append(DOM().new('div').class('ib middle caa_navItemText').text(subSection.title)) .attr({ href: subSection.link }).appendTo(app.subNavContainer).on('click', function(e) { e.preventDefault(); app.render(subSection.link, false, false); }); } }); var content = DOM().new('div').class('caa_content'), appHeading = DOM().new('div').class('caa_header'), type = ''; if (app.parts[1]) { var chk = app.parts[1].split('-'); if (chk[0].length === 4) { type = 'd'; } } if (app.parts[0] === 'support') { if (!hasSiteAccess(app.user.access, 'hub/support')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Support')) .appendTo(content); app.listeners.checkSite = function() { app.checkWarnings(); app.support(content, type); }; app.support(content, type); } else if (app.parts[0] === 'publish') { if (!hasSiteAccess(app.user.access, 'publish')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Publish')) .appendTo(content); app.publish(content, type); } else if (app.parts[0] === 'changes') { if (!hasSiteAccess(app.user.access, 'hub/changes')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Changes')) .appendTo(content); app.changes(content, type); } else if (app.parts[0] === 'quality') { if (!hasSiteAccess(app.user.access, 'hub/quality')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Quality Assurance')) .appendTo(content); app.quality(content, type); } else if (app.parts[0] === 'seo') { if (!hasSiteAccess(app.user.access, 'hub/seo')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('SEO')) .appendTo(content); app.seo(content, type); } else if (app.parts[0] === 'usage') { if (!hasSiteAccess(app.user.access, 'hub/usage')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Usage')) .appendTo(content); app.usage(content, type); } else if (app.parts[0] === 'quality') { if (!hasSiteAccess(app.user.access, 'hub/quality')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Quality')) .appendTo(content); app.quality(content, type); } else if (app.parts[0] === 'recommendations') { if (!hasSiteAccess(app.user.access, 'hub/recommendations')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Recommendations')) .appendTo(content); var recHolder = DOM().new('div').appendTo(content).append(UI.Spinner('24').addClass('caa_padding')).append(DOM().new('span').class('ib middle').text('Scanning site for issues...').css({ 'padding-left': '10px' })), renderRecs = function() { var sup = new Recommendations(app, { showAll: true }, function(recs) { sup.length; // makes eslint happy for the new Reconds variables recHolder.html(''); if (recs) { recs.forEach(function(rec) { var boxColor = 'rgb(136, 200, 136)', icon = UI.Icon('check', ''); if (!rec.ok) { boxColor = 'rgb(255, 68, 68)'; icon = UI.Icon('caution', ''); } icon.byTag('svg').css({ fill: boxColor }); var textHolder = DOM().new('div').class('ellipsis').css({ 'margin-left': '40px' }), row = DOM().new('div').class('caa_row caa_click caa_row_hover ellipsis').css({ overflow: 'hidden', cursor: 'pointer' }) .append( DOM().new('div').css({ float: 'left', 'padding-top': '4px' }).append(icon) ) .append( textHolder .append(DOM().new('div').text(rec.title || '').css({ 'font-size': '18px', 'padding-top': '4px' })) .append(DOM().new('div').text(rec.link || '').css({ 'font-size': '11px', 'padding-top': '2px' })) .append(DOM().new('div').text(rec.description || '').css({ 'font-size': '13px', 'padding-top': '2px', 'white-space': 'normal' })) ) .on('click', function(e) { if (!rec.link) { rec.link = ''; } app.render(rec.link, false, false); setTimeout(function() { app.editorLink(rec); }, 100); }) .appendTo(recHolder); if (rec.dismissible) { textHolder.css({ 'margin-right': '90px' }); if (rec.ok) { if (rec.dismissed) { DOM().new('div').css({ 'float': 'right' }).append(DOM().new('button').class('caa_button-default').text('Restore')).insertFirst(row).on('click', function(e) { e.stopPropagation(); var update = { dismissed: (app.site.dismissed || []) }; var index = update.dismissed.indexOf(rec.dismissible); if (index > -1) { rec.dismissible.splice(index, 1); } app.site.settings.dismissed = update.dismissed; app.siteUpdate(['settings'], update); renderRecs(); }); } } else { DOM().new('div').css({ 'float': 'right' }).append(UI.Icon('x')).insertFirst(row).on('click', function(e) { e.stopPropagation(); var update = { dismissed: (app.site.dismissed || []) }; update.dismissed.push(rec.dismissible); app.site.settings.dismissed = update.dismissed; app.siteUpdate(['settings'], update); renderRecs(); }); } } }); } }); }; renderRecs(); } else if (app.parts[0] === 'submissions') { if (!hasSiteAccess(app.user.access, 'hub/submissions')) { app.stage.html('You do not have access to this section.'); return false; } app.manageSubmissions(content, appHeading, type); } else if (app.parts[0] === 'analytics') { if (!hasSiteAccess(app.user.access, 'hub/analytics')) { app.stage.html('You do not have access to this section.'); return false; } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Analytics')) .appendTo(content); var subHolder = DOM().new('div').appendTo(content); var week_start = new Date(), week_end = new Date(), last30_start = new Date(), last30_end = new Date(), year_start = new Date(), year_end = new Date(), custom_start = new Date(); week_start.setDate(week_start.getDate() - 7); week_end.setDate(week_end.getDate() - 1); last30_start.setDate(last30_start.getDate() - 30); last30_end.setDate(last30_end.getDate() - 1); year_start.setDate(1); year_start.setMonth(0); custom_start.setDate(custom_start.getDate() - 30); var tabsHolder = DOM().new('div').css({ 'background-color': '#d4d4d4', padding: '4px 20px 0 20px' }).appendTo(subHolder), tabs = { thisweek: { title: 'Last 7 Days', start_date: week_start, end_date: week_end, selected: true }, last30: { title: 'Last 30 Days', start_date: last30_start, end_date: last30_end }, lastyear: { title: 'This Year', start_date: year_start, end_date: year_end }, custom: { title: 'Custom', start_date: last30_start, end_date: last30_end } }; Object.keys(tabs).forEach(function(key) { var tab = tabs[key], addClassTab = tab.selected ? ' caa_rightPanelTabSelected' : ''; tab.tab = DOM().new('div').class('ibb caa_rightPanelTab' + addClassTab) .append(DOM().new('span').css({ display: 'block', 'padding-top': '4px' }).text(tab.title)).appendTo(tabsHolder).on('click', function(e) { if (tab.selected) { return false; } else { var addInput = function() { app.generateAnalytics(analyticsContent, { start_date: tabs[key].start_date.toISOString().substr(0, 10), end_date: tabs[key].end_date.toISOString().substr(0, 10) }); if (key === 'custom') { DOM().new('form').class('caa_padding analytics-custom-input') .on('submit', function(e) { e.preventDefault(); tabs[key].start_date = parseAnyDate(DOM(DOM(e.target).byTag('input').elements[0]).val()); tabs[key].end_date = parseAnyDate(DOM(DOM(e.target).byTag('input').elements[1]).val()); app.generateAnalytics(analyticsContent, { start_date: tabs[key].start_date, end_date: tabs[key].end_date }); addInput(); }) .append( DOM().new('div').class('ibb bottom').css({ 'margin-right': '10px' }).append(Inputs.date({ label: 'From', value: isoDate(tabs[key].start_date) })) ) .append( DOM().new('div').class('ibb bottom').css({ 'margin-right': '10px' }).append(Inputs.date({ label: 'To', value: isoDate(tabs[key].end_date) })) ) .append( DOM().new('div').class('ibb bottom').append(DOM().new('input').attr({ type: 'submit' }).class('caa_button-default').val('Update')) ) .insertFirst(analyticsContent); } else { DOM().byClass('analytics-custom-input').remove(); } } addInput(); for (var t in tabs) { if (t === key) { tabs[t].tab.addClass('caa_rightPanelTabSelected'); tabs[t].selected = true; } else { tabs[t].tab.removeClass('caa_rightPanelTabSelected'); tabs[t].selected = false; } } } }); }); var analyticsContent = DOM().new('div').appendTo(subHolder); app.generateAnalytics(analyticsContent, { start_date: tabs.thisweek.start_date.toISOString().substr(0, 10), end_date: tabs.thisweek.end_date.toISOString().substr(0, 10) }); } else { if (!hasSiteAccess(app.user.access, 'hub')) { app.stage.html('You do not have access to this section.'); app.checkWarnings(); return false; } appHeading .append(DOM().new('div').class('caa_heading ib middle').text('Hub')) .appendTo(content); var hubContent = DOM().new('div').appendTo(content), statsHolder, topHolder = DOM().new('div').css({ margin: '0', padding: '16px 16px 0 16px', 'overflow-x': 'auto' }).appendTo(hubContent); var publishArrow = UI.Icon('left', 'panelsec').css({ transform: 'rotate(-90deg) translateX(2px)', 'margin-left': '10px' }), publishContent = DOM().new('div'); DOM().new('div') .append(UI.Icon('publish')) .append(DOM().new('span').class('ibb middle').text('Site Publishing').css({ 'margin-left': '10px' })) .css({ 'padding-bottom': '10px' }).appendTo(publishContent); app.publish(publishContent, ''); //app.render('/publish', false, false); DOM().new('div').css({ padding: '0 0 16px 0', 'border-bottom': '1px solid #d4d4d4' }) .append(publishContent) .appendTo(topHolder); statsHolder = DOM().new('div').css({ 'padding-top': '16px', 'padding-bottom': '8px', 'border-bottom': '1px solid #d4d4d4' }).appendTo(topHolder) DOM().new('div') .append(UI.Icon('barchart')) .append(DOM().new('span').class('ibb middle').text('Weekly Activity').css({ 'margin-left': '10px' })) .css({ 'padding-bottom': '10px' }).appendTo(statsHolder); [1, 2, 3, 4, 5].forEach(function(n) { DOM().new('div').class('ibb middle caa_click').id('hub-top-box-' + n).css({ 'min-width': '120px', 'padding': '0 16px 0', 'line-height': '150%' }).appendTo(statsHolder).on('click', function() { app.render('/analytics', false, false); }); }); var lineChart = { labels: [], datasets: [{ fill: false, label: 'Visitors', fillColor: 'transparent', strokeColor: '#00B375', pointColor: '#00B375', pointStrokeColor: '#fff', pointHighlightFill: '#fff', pointHighlightStroke: '#00B375', data: [] }] }; var totalSubmissions = 0, monthBandwidth = 0, storage = 0; app.getFeed(function() { var sumnums = {}, curYearMonth = new Date().toISOString().substr(0, 7); Object.keys(app.siteFeed).sort().reverse().forEach(function(ymd, i) { if (ymd !== 'id' && typeof app.siteFeed[ymd] === 'object') { var ymdparts = ymd.split(/\-/), d = new Date(ymdparts[0], (ymdparts[1] - 1), ymdparts[2], 0, 0, 0), k; if (lineChart.datasets[0].data.length < 7) { for (k in app.siteFeed[ymd]) { if (!sumnums[k]) { sumnums[k] = 0; } sumnums[k] += app.siteFeed[ymd][k] || 0; } lineChart.labels.push(displayDate(d)); lineChart.datasets[0].data.push(app.siteFeed[ymd].visitors || 0); } if (ymd.substr(0, 7) === curYearMonth) { monthBandwidth += app.siteFeed[ymd].bandwidth || 0; } totalSubmissions += app.siteFeed[ymd].submissions || 0; if (!storage) { storage = app.siteFeed[ymd].storage || 0; } } }); lineChart.labels.reverse(); lineChart.datasets[0].data.reverse(); var box1 = DOM().id('hub-top-box-1').css({ 'padding-right': '10px' }); DOM().id('hub-top-box-2').html((sumnums.visitors || 0) + ' visitor' + (sumnums.visitors === 1 ? '' : 's')); DOM().id('hub-top-box-3').text((sumnums.new_visitors || 0) + ' new visitor' + (sumnums.new_visitors === 1 ? '' : 's')); DOM().id('hub-top-box-4').text((sumnums.pageviews || 0) + ' pageview' + (sumnums.pageviews === 1 ? '' : 's')); DOM().id('hub-top-box-5').text(secondsToMinutes(sumnums.avg_time_on_site) + ' avg time'); loadScript('https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js', function(e) { Chart.defaults.global.maintainAspectRatio = true; Chart.defaults.global.responsive = true; Chart.defaults.global.showScale = false; Chart.defaults.global.scaleShowLabels = false; Chart.defaults.Line.tooltipTemplate = '<%= label %> <%= datasetLabel %>: <%= value %>'; DOM().new('canvas').id('lineChart').attr({ height: 80 }).css({ 'margin-bottom': '-4px' }).appendTo(DOM().new('div').class('ibb').css({ 'width': '100%' }).appendTo(box1)); if (!Array.isArray(lineChart.datasets[0].data)) { lineChart.datasets[0].data = []; } if (lineChart.datasets[0].data.length < 5) { while (lineChart.datasets[0].data.length < 5) { lineChart.datasets[0].data.unshift(0); } } new Chart(document.getElementById('lineChart').getContext('2d')).Line(lineChart, { fill: false, tooltipCaretSize: 0, scaleShowGridLines: false }); }); // updates numbers setTimeout(function() { usageHolder.byClass('target-text').text('Usage This Month ' + (monthBandwidth ? formatBytes(monthBandwidth) : 'N/A') + ' bandwidth + ' + (storage ? formatBytes(storage) : 'N/A') + ' storage'); }, 10); }); var planHolder = DOM().new('div').id('hub-plan').css({ 'padding': '16px 0', 'border-bottom': '1px solid #d4d4d4' }) .class('caa_click') .append(UI.Icon('cart')) .append(DOM().new('span').class('box middle target-text').css({ 'margin-left': '10px' }).text('Fetching plan...')) .on('click', function(e) { app.render('/billing/' + app.site.id, false, false); }) .appendTo(topHolder); setTimeout(function() { app.setHubBilling(); }, 100); var usageHolder = DOM().new('div').css({ 'padding': '16px 0', 'border-bottom': '1px solid #d4d4d4' }) .class('caa_click') .append(UI.Icon('piechart')) .append(DOM().new('span').class('box middle target-text').css({ 'margin-left': '10px' }).text('Fetching usage...')) .appendTo(topHolder) .on('click', function(e) { app.render('/usage', false, false); }) var subsHolder = DOM().new('div').css({ 'padding': '16px 0', 'border-bottom': '1px solid #d4d4d4' }) .class('caa_click') .append(UI.Icon('email')) .append(DOM().new('span').class('box middle target-text').css({ 'margin-left': '10px' }).text('Fetching submissions...')) .appendTo(topHolder) .on('click', function(e) { app.render('/submissions', false, false); }) var recsHolder = DOM().new('div').css({ 'padding': '16px 0', 'border-bottom': '1px solid #d4d4d4' }) .class('caa_click') .append(UI.Icon('caution')) .append(DOM().new('span').class('box middle target-text').css({ 'margin-left': '10px' }).text('Fetching recommendations...')) .appendTo(topHolder) .on('click', function(e) { app.render('/recommendations', false, false); }) new Recommendations(app, { showAll: true }, function(recs) { var numRecs = 0; if (recs) { recs.forEach(function(rec) { if (!rec.ok) { numRecs++; } }); recsHolder.byClass('target-text').text(numRecs + ' Recommendation' + (numRecs === 1 ? '' : 's')) } }); app.Request({ do: 'request', request: 'submissions' }, function(data) { var totalSubmissions = 0; if (data && data.submissions && data.submissions.length) { for (var i = 0; i < data.submissions.length; i++) { if (!data.submissions[i].read) { totalSubmissions++; } } } subsHolder.byClass('target-text').text(totalSubmissions + ' Unread Submission' + (totalSubmissions === 1 ? '' : 's')); }); } content.appendTo(app.stage); }; App.prototype.setHubBilling = function() { var app = this; if (app.billingInfo && app.billingInfo[app.site.id]) { DOM().id('hub-plan').exists(function(hubPlan) { var subOptions = { 'trial': 'Trial Plan', 'base': 'Starter Plan - $5/month + Bandwidth + Storage', '199': 'Premium Plan - $199/month Unlimited Bandwidth & Storage + Premium Support' }; var target = hubPlan.byClass('target-text').text(subOptions[app.billingInfo[app.site.id].subscription || 'trial']); if (app.billingInfo[app.site.id].subscription != '199' && app.site.owner === app.user.id) { target.append(DOM().new('span').text(' ')).append(DOM().new('a').attr({ href: '#' }).text('Upgrade').on('click', function(e) { app.render('/billing/' + app.site.id, false, false); })) } }) } } // TRANSLATE // https://translate.googleapis.com/translate_a/single?client=gtx&sl=" + sourceLang + "&tl=" + targetLang + "&dt=t&q=" + encodeURI(sourceText) App.prototype.i18n = function() { var app = this; // mark content as the highlighted nav section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.contentMenu(false); app.stage.html(''); var appHeader = DOM().new('div').class('caa_content caa_header'), backLink = '/content', moreText = ''; var content = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage); if (app.parts[1]) { if (!hasSiteAccess(app.user.access, 'i18n/' + app.parts[1])) { app.stage.html('You do not have access to this section'); return false; } var editablePaths = [], pathLoopFunc = function(l, path, item, parent) { var title = item.title || item.label || item._label || item.name || 'No Title Set'; editablePaths.push({ title: title, path: path, item: item, parent: parent, l: l }); if (item.items && item.items.length) { item.items.forEach(function(item, i) { pathLoopFunc(l + 1, path.concat('items', i), item, path); }) } }; editablePaths.push({ title: 'Navigation', path: ['navigation'], item: false, parent: false, l: 0 }); app.site.navigation.forEach(function(item, i) { pathLoopFunc(1, ['navigation', i], item, ['navigation']); }); editablePaths.push({ title: 'Footer', path: ['footer'], item: false, parent: false, l: 0 }); app.site.footer.forEach(function(item, i) { pathLoopFunc(1, ['footer', i], item, ['footer']); }); Object.keys(app.site.content).forEach(function(sec) { editablePaths.push({ title: sec.capitalizeFirstLetter(), path: ['content', sec], item: false, parent: false, l: 0 }); app.site.content[sec].forEach(function(page, p) { pathLoopFunc(1, ['content', sec, p], page, ['content', sec]); }); }); editablePaths.push({ title: 'Media', path: ['media'], item: false, parent: false, l: 0 }); Object.keys(app.site.media).forEach(function(mediaID, i) { pathLoopFunc(1, ['media', mediaID], app.site.media[mediaID], ['media']); }); editablePaths.push({ title: 'Feeds', path: ['feeds'], item: false, parent: false, l: 0 }); Object.keys(app.site.feeds).forEach(function(feedID, i) { pathLoopFunc(1, ['feeds', feedID], app.site.feeds[feedID], ['feeds']); }); var i18nID = app.parts[1]; var item = app.site.i18n[i18nID]; if (item) { moreText = ': ' + item.name; var curPath = app.parts.slice(2), depth = 1, curDepth = curPath.length; app.subscribe('i18n/' + i18nID, function onchangeFeeds() { content.html(''); var folder = (item.language_code || i18nID).urlSafe(), domain = item.domain; DOM().new('div').css({ padding: '10px 0' }) .append(DOM().new('a').text('Staging Link').attr({ href: app.stagingURL().replace('-staging.', '-' + folder + '-staging.'), target: '_blank' })) .append(DOM().new('span').text(' ')) .append(DOM().new('a').text('Live Link').attr({ href: 'http://' + domain, target: '_blank' })) .appendTo(content); if (curPath.length) { var backPathDOM = DOM().new('div').appendTo(content); DOM().new('a').text('All').attr({ href: '#' }).on('click', function(e) { e.preventDefault(); app.render('/' + app.parts[0] + '/' + app.parts[1]); }).appendTo(backPathDOM); curPath.forEach(function(item, i) { DOM().new('span').text(' / ').appendTo(backPathDOM); DOM().new('a').text(item).attr({ href: '#' }).on('click', function(e) { e.preventDefault(); app.destroyPanels(); app.render('/' + app.parts[0] + '/' + app.parts[1] + '/' + curPath.slice(0, i).join('/')); }).appendTo(backPathDOM); }) } editablePaths.filter(function(item) { return (!curPath.length || item.path.join('/').indexOf(curPath.join('/')) === 0) && item.l <= curDepth + depth; }).forEach(function(item) { if (!app.site.i18n[i18nID].paths) { app.site.i18n[i18nID].paths = {}; } var usePath = item.path.join('/'), hasTranslation = false, translation = app.site.i18n[i18nID].paths[usePath] || {}; var objectRow = DOM().new('div').class('caa_griditem caa_griditemhover caa_click').css({ 'white-space': 'nowrap' }) .append(DOM().new('div').css({color: '#666'}).text(item.title || 'No Title Set')) .append(DOM().new('div').text(item.path.join('/')).css({ 'font-size': '12px', color: '#999' })) .css({ 'padding': '10px 10px 10px ' + (10 + (item.l * 10)) + 'px' }).appendTo(content).on('click', function(e) { app.render('/' + app.parts[0] + '/' + app.parts[1] + '/' + item.path.join('/'), false, false); app.EditorPanel('i18nEditorItem', translation, ['i18n', app.parts[1], 'paths', usePath], app.getFromPath(item.path) || {}); }) if (translation) { Object.keys(translation).forEach(function(key) { DOM().new('div').text((key || '').capitalizeFirstLetter()).appendTo(objectRow); DOM().new('div').css({ 'margin-left':'20px', }).text(item[key]).appendTo(objectRow); DOM().new('div').css({'margin-left':'20px', 'font-style': 'italic'}).text(translation[key]).appendTo(objectRow); }) } }) }); } else { DOM().new('div').class('caa_padding').text('Not found.').appendTo(content); moreText = ': Not Found'; } backLink = '/i18n'; appHeader.append(UI.Icon('left', 'head').on('click', function(e) { app.destroyPanels(); app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Translation' + moreText)) .insertFirst(app.stage); } else { if (!hasSiteAccess(app.user.access, 'i18n', true)) { app.stage.html('You do not have access to this section'); return false; } appHeader.append(UI.Icon('left', 'head').on('click', function(e) { app.destroyPanels(); app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Localization' + moreText)) .insertFirst(app.stage); var contentContainer = DOM().new('div').class('caa_grid').appendTo(content); app.subscribe('i18n', function onchangeFeeds() { contentContainer.html(''); Object.keys(app.site.i18n || {}).sort(function(a, b) { return b - a; }).forEach(function(i18nID) { if (hasSiteAccess(app.user.access, 'i18n/' + i18nID)) { var item = app.site.i18n[i18nID]; var itemDOM = DOM().new('div').class('caa_row caa_clickSecTarget').text(item.name).appendTo(contentContainer).on('click', function(e) { app.render('/i18n/' + i18nID, false, false); }); } }); }); } }; var i18nEditor = function(app, object, path, element) { var dom = DOM().new('div'), i18nID = path[1]; EditorHelpers.text(app, dom, object, path, element, { label: 'Translation Name', value: object.name || '', property: 'name' }); EditorHelpers.options(app, dom, object, path, element, { label: 'Select Domain', value: object.domain, options: [''].concat(app.site.cnames.split(/ /gi)), property: 'domain' }); EditorHelpers.text(app, dom, object, path, element, { label: 'HTML Language Code/Tag Value', value: object.language_code || '', property: 'language_code' }); var matches = false; var usage = DOM().new('div').class('caa_rightPanelSection').appendTo(dom); usage.html('').append(UI.deleteButton('Delete Translation', 'button', function(e) { app.render('/i18n', false, false); if(i18nID){ app.siteDelete(['i18n', i18nID]); setTimeout(function(){ app.render('/i18n', false, true); }, 10) } }).appendTo(DOM().new('div').class('caa_rightPanelSection').appendTo(dom))); return dom; }; var i18nEditorItem = function(app, object, path, sourceObject) { // in htis case we're replacing "element" with sourceObject. var dom = DOM().new('div'), element = DOM().new('div'), i18nID = path[1]; console.log('i18n obj', object, 'source', sourceObject); if(sourceObject.title && (!sourceObject._title || (sourceObject._title && sourceObject._title.class !== 'disable'))){ EditorHelpers.textarea(app, dom, object, path, element, { label: 'Title', value: object.title || '', property: 'title' }); DOM().new('div').class('caa_rightPanelSection').css({'font-style': 'italic', 'padding-top': 0}).text(sourceObject.title || '').appendTo(dom); } if(sourceObject.subtitle && (!sourceObject._subtitle || (sourceObject._subtitle && sourceObject._subtitle.class !== 'disable'))){ EditorHelpers.textarea(app, dom, object, path, element, { label: 'Sub-Title', value: object.subtitle || '', property: 'subtitle' }); DOM().new('div').class('caa_rightPanelSection').css({'font-style': 'italic', 'padding-top': 0}).text(sourceObject.subtitle || '').appendTo(dom); } if(sourceObject.body && (!sourceObject._body || (sourceObject._body && sourceObject._body.class !== 'disable'))){ EditorHelpers.textarea(app, dom, object, path, element, { label: 'Body', value: object.body || '', property: 'body' }); DOM().new('div').class('caa_rightPanelSection').css({'font-style': 'italic', 'padding-top': 0}).text(sourceObject.body || '').appendTo(dom); } if(sourceObject.subbody && (!sourceObject._subbody || (sourceObject._subbody && sourceObject._subbody.class !== 'disable'))){ EditorHelpers.textarea(app, dom, object, path, element, { label: 'Sub-Body', value: object.subbody || '', property: 'subbody' }); DOM().new('div').class('caa_rightPanelSection').css({'font-style': 'italic', 'padding-top': 0}).text(sourceObject.subbody || '').appendTo(dom); } return dom; }; App.prototype.import = function() { var app = this; if (!hasSiteAccess(app.user.access, 'content')) { app.stage.html('You do not have access to this section'); return false; } DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.stage.html(''); var appHeader = DOM().new('div') .class('caa_content caa_header') .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/content', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Import Content')) .insertFirst(app.stage); var content = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage), formContent = DOM().new('div'); var changeSource = function(source) { if (source === 'ContentActivator JSON') { form.css({ 'max-width': '600px' }) formContent.html('') .append(DOM().new('textarea').class('ibb').css({ width: '100%', height: '100px' }).attr({ placeholder: 'Paste JSON or a URL here' })) .append(DOM().new('input').class('caa_button-default').attr({ type: 'submit', value: 'Begin' })) } else if (source === 'Photoshop PSD File') { form.css({ 'max-width': 'none' }) formContent.html('Getting supporting code for this...'); app.importPSD(formContent); } } var form = DOM().new('form').css({ 'max-width': '600px' }).on('submit', function(e) { form.attr({ disabled: true }); e.preventDefault(); var value = form.byTag('textarea').val(), type = form.byTag('select').val(), button = form.byTag('input').text('Processing...'), json = {}; if (value.substr(0, 4) !== 'http') { try { json = JSON.parse(value); } catch (e) { console.error(e); DOM().new('div').css({ color: 'red' }).appendTo(form).text('We could not sure that data'); } } if (json && type === 'ContentActivator JSON') { app.importContentActivator(json, content); } else { form.attr({ disabled: false }); button.text('Begin'); } }) .append(Inputs.options({ label: 'Select Source', options: [{ text: 'Select Source', value: '' }, 'Photoshop PSD File', 'ContentActivator JSON'], onchange: changeSource })) .append(formContent) .appendTo(content); }; App.prototype.importContentActivator = function(data, into) { var app = this; into.html(''); var expandSec = function(title) { var el = DOM().new('div'); el.displayedRow = DOM().new('div').appendTo(el); el.button = DOM().new('div').css({ float: 'left' }).append(UI.Icon('plus', '', 20)).on('click', function(e) { el.displayedRow.byClass('caa_icon').remove(); el.content.byTag('button').remove(); if (el.showing) { UI.Icon('plus', '', 20).appendTo(el.button); el.showing = false; el.content.css({ display: 'none' }); } else { UI.Icon('minus', '', 20).appendTo(el.button); el.showing = true; el.content.css({ display: '' }); DOM().new('button').class('caa_button-default').text('Uncheck All').insertFirst(el.content).on('click', function(e) { el.content.byTag('input').attr({ checked: false }); changeButton(); }); DOM().new('button').class('caa_button-default').text('Check All').insertFirst(el.content).on('click', function(e) { el.content.byTag('input').attr({ checked: true }); changeButton(); }).css({ 'margin-right': '10px' }); } }).appendTo(el.displayedRow); el.title = DOM().new('div').css({ 'margin-left': '40px', height: '40px' }).text(title || '').appendTo(el.displayedRow) el.content = DOM().new('div').css({ display: 'none' }).appendTo(el); return el; }; if (data.content) { var sections = Object.keys(app.site.content).map(function(section) { return { text: 'Site Section: ' + section.capitalizeFirstLetter(), value: 'section:' + section } }); Object.keys(app.site.feeds).forEach(function(feedID) { if (app.site.feeds[feedID].source === 'manual') { sections.push({ text: 'Feed: ' + app.site.feeds[feedID].name, value: 'feed:' + feedID }) } }) var button = DOM().new('button').class('caa_button-default').text('Import 0 Selected Pages').on('click', function(e) { var added = 0; var intoOp = into.byTag('select').val(), intoWhat = '', intoIdent = ''; if (intoOp.substr(0, 8) === 'section:') { intoWhat = 'section'; intoIdent = intoOp.split(':')[1]; } else if (intoOp.substr(0, 5) === 'feed:') { intoWhat = 'feed'; intoIdent = intoOp.split(':')[1]; if (!app.site.feeds[intoIdent].items) { app.siteUpdate(['feeds'], intoIdent, [], true); } } if (intoWhat && intoIdent) { into.byTag('input').elements.forEach(function(el) { if (el.checked) { var addPage = JSON.parse(JSON.stringify(data.content[el.getAttribute('data-section')][el.getAttribute('data-index')])); if (addPage) { for (var k in addPage) { if (k.substr(0, 4) === 'ref_') { delete addPage[k]; } } if (intoWhat === 'section') { app.siteAdd(['content', intoIdent], addPage); } else if (intoWhat === 'feed') { var feedBody = ''; if (addPage.items) { addPage.items.forEach(function(item) { if (item.body) { if (feedBody) { feedBody += '
'; } feedBody += item.body; } }) delete addPage.items; addPage.body = feedBody; } app.siteAdd(['feeds', intoIdent, 'items'], addPage); } added++; } } }) into.html('Imported ' + added + ' pages'); } else { console.error('invalid import target selected'); } }); var changeButton = function() { var tot = 0, chk = 0; into.byTag('input').elements.forEach(function(el) { tot++; if (el.checked) { chk++; } }) button.text('Import ' + chk + ' of ' + tot + ' Pages'); } DOM().new('div').append(Inputs.options({ label: 'Import Into', options: sections }).class('ibb middle').css({ 'max-width': '200px', 'margin-right': '20px' })).append(button).appendTo(into).css({ 'margin-bottom': '20px' }); Object.keys(data.content).forEach(function(section) { var sec = expandSec(section).appendTo(into); if (data.content[section]) { data.content[section].forEach(function(page, i) { DOM().new('div').css({ 'white-space': 'nowrap' }) .append(DOM().new('input').attr({ type: 'checkbox', 'data-section': section, 'data-index': i }).on('change', changeButton)) .append(DOM().new('span').text(page.title || 'No Page Title')) .appendTo(sec.content); }) } }) } }; App.prototype.importPSD = function(formContent) { var app = this; var keys = ['artboard', 'blendClippingElements', 'blendInteriorElements', 'fillOpacity', 'gradientFill', 'layerId', 'layerNameSource', 'legacyTypetool', 'locked', 'metadata', 'name', 'nestedSectionDivider', 'objectEffects', 'sectionDivider', 'solidColor', 'typeTool', 'vectorMask', 'vectorOrigination', 'vectorStroke', 'vectorStrokeContent']; var fontWeightMap = { thin: 100, hairline: 100, extralight: 200, ultralight: 200, light: 300, normal: 400, medium: 500, semibold: 600, demibold: 600, bold: 700, extrabold: 800, ultrabold: 800, black: 900, heavy: 900 }, fontNameNormal = function(str) { return (str || '').toLowerCase().replace(/[^a-z0-9]/gi, ''); }; var assessLayer = function(root, layer, parent, path, names, ci, elements, layers) { try { var text = layer.get('typeTool'), layerjson = layer.export(), gcss, textContent = '', css = {}; if (text && (text.textValue || text.textValue == '0')) { gcss = text.toCSS(); if (gcss) { gcss.split('\n').forEach(function(cssline) { var prts = cssline.split(':'); if (prts[0] && prts[1]) { css[prts[0]] = prts[1].trim().replace(/\,\ /g, ',').replace(/\;/g, ''); } }) delete css['text-align']; css['font-size'] = (css['font-size'] || '').replace('pt', 'px'); elements.push({ type: 'style', css: css }) } textContent = text.textValue; elements.push({ type: 'text', text: textContent }) } var layerRefIndex = layers.push({ i: ci, depth: path.length, path: path, layer: layer, layerjson: layerjson, name: layer.name || '', text: textContent, longName: names.filter(function(val) { return val; }).join(', ') + ' (' + ci + ')', coords: layer.coords, visible: layerjson.visible, type: layerjson.type, items: [] }) - 1; parent.items.push(layers[layerRefIndex]); if (layer.hasChildren()) { layer.children().forEach(function(child, i) { assessLayer(root, child, layers[layerRefIndex], path.concat('children', i), names.concat(layer.name || ''), i, elements, layers) }) } } catch (e) { console.log('failed on layer', layer, path) console.error(e); } } app.get('/fontList.json', { cache: true }, function(fontJSON) { var fontList = JSON.parse(fontJSON); loadScript('https://cdn.blux.com/scripts/psd.min.js', function() { formContent.html('') DOM().new('div').css({ position: 'relative', height: '200px', 'margin-top': '20px' }).append(DOM().new('div').addClass('caa_pickMedia').text('DRAG HERE TO IMPORT PSD')).append(UI.dropZone(function(e) { formContent.html('Processing PSD file...'); var PSD = require('psd'); PSD.fromEvent(e).then(function(psd) { var elements = [], layers = []; var root = psd.tree(); assessLayer(root, root, {items:[]}, [], [], 0, elements, layers); formContent.html(''); var showHideSecs = function(e, what) { formContent.byClass('caa_button-default').css({ 'background-color': '', color: '', 'border-color': '' }) previewContainer.css({ display: 'none', 'background-color': '#666', color: '#fff', 'border-color': '#666' }); textStyles.css({ display: 'none' }); textElements.css({ display: 'none' }); what.css({ display: 'block' }); DOM(e.target).css({ 'background-color': '#666', color: '#fff !important', 'border-color': '#666' }); }; DOM().new('div') .css({ 'margin-top': '20px' }) .append(DOM().new('button').class('caa_button-default').css({ 'margin-right': '10px' }).text('Preview/Import Blocks').on('click', function(e) { showHideSecs(e, previewContainer); })) .append(DOM().new('button').class('caa_button-default').css({ 'margin-right': '10px' }).text('Import Text Styles').on('click', function(e) { showHideSecs(e, textStyles); })) .append(DOM().new('button').class('caa_button-default').css({ 'margin-right': '10px' }).text('Text Content').on('click', function(e) { showHideSecs(e, textElements); })) .appendTo(formContent); var preview = DOM().new('div').css({ position: 'relative', 'margin-right': '300px', 'min-width': '300px' }), layersContainer = DOM().new('div').css({ position: 'absolute', top: '23px', right: 0, width: '300px', height: 'calc(100% - 23px)', 'overflow-y': 'auto', 'overflow-x': 'auto' }), previewContainer = DOM().new('div').appendTo(formContent).css({ position: 'relative', 'margin-top': '20px' }) .append(DOM().new('div').class('caa_sectionBar').text('Preview')) .append(preview) .append(layersContainer), textStyles = DOM().new('div').appendTo(formContent).css({ display: 'none', 'margin-top': '20px' }) .append(DOM().new('div').class('caa_sectionBar').text('Text Styles')), hasTextStyles = {}, textElements = DOM().new('div').appendTo(formContent).css({ display: 'none', 'margin-top': '20px' }) .append(DOM().new('div').class('caa_sectionBar').text('Text')); DOM(psd.image.toPng()).attr({ height: '' }).appendTo(preview); var img = preview.byTag('img').elements[0], getRelativeSize = function(coords, imgsize) { return { top: ((coords.top / imgsize.h) * 100) + '%', left: ((coords.left / imgsize.w) * 100) + '%', width: (((coords.right - coords.left) / imgsize.w) * 100) + '%', height: (((coords.bottom - coords.top) / imgsize.h) * 100) + '%' }; }; layers.forEach(function(layer, i) { var layerdom, css, imgsize, mousey = function(e) { if (e.type === 'mouseover') { paneldom.css({'font-weight': 'bold', 'background-color': '#eaeaea'}) layerdom.css({ opacity: 1 }) } else { paneldom.css({'font-weight': '', 'background-color': ''}) layerdom.css({ opacity: 0 }) } }, mousec = function(e) { var modal = UI.openModal(DOM(e.target)); var pretext = DOM().new('div').class('caa_padding').text('Loading layer and image preview...').appendTo(modal); setTimeout(function() { var modalContent = DOM().new('div').class('caa_padding').appendTo(modal); pretext.remove(); var image = layer.layer.get('image'); console.log('layer', layer); app.pageBlockList({}, function(newPath){}).appendTo(modalContent); DOM().new('div').class('caa_sectionBar').text('Preview Block').appendTo(modalContent); var blockPreview = DOM().new('div').class('blocks0').appendTo(modalContent); var figureOutBlock = function(layer) { if(layer.text){ DOM().new('div').text(layer.text).appendTo(blockPreview) } if(layer.items){ layer.items.forEach(figureOutBlock); } }; figureOutBlock(layer); keys.forEach(function(key) { try { var val = layer.layer.get(key); if (val) { console.log('key', key, val); console.log('key json', key, val.export()); } } catch (e) { console.log('failed on key', key); } }) if (image) { DOM().new('div').class('caa_sectionBar').text('Layer Image Import').appendTo(modalContent); var imagedom; try { imagedom = image.toPng(); } catch (e) { // fails to get it at groups. console.log('image fail', image, 'name', layer.name); console.error(e); } if (imagedom) { var element = { type: 'image', name: layer.longName, image: imagedom }; var optionsDOM = DOM().new('div'); var row = DOM().new('div').class('caa_row caa_row_hover') .append(DOM().new('div').text(element.name || '')) .append(DOM(element.image).css({ 'background-image': checkered_background_gif, }).attr({ height: '' })) .append(optionsDOM) .appendTo(modal); var match = false; Object.keys(app.site.media).forEach(function(mediaID) { if (app.site.media[mediaID].name == element.name) { match = true; } }); if (match) { DOM().new('div').text('Matches existing media item').appendTo(optionsDOM); } else { if (element.image.src && element.image.src.indexOf('png') > -1) { DOM().new('button').text('Add To Media').class('caa_button-default').appendTo(optionsDOM).on('click', function(e) { optionsDOM.html('').css({ position: 'relative', height: '20px' }); var statusBox = DOM().new('div').class('ellipsis').css({ padding: '6px' }).appendTo(optionsDOM).text('uploading...'); var bytes = atob(element.image.src.split(',')[1]) var arr = new Uint8Array(bytes.length); for (var i = 0; i < bytes.length; i++) { arr[i] = bytes.charCodeAt(i); } var blob = new Blob([arr], { type: 'image/png' }); var upload = new uploadFile(app, blob, element.name); upload.on('completed', function(e, response) { var data = {}; try { data = JSON.parse(response); } catch (err) { data = {}; } if (data.id) { app.siteUpdate(['media', data.id], data.media); statusBox.animate({ opacity: 0 }, function() { statusBox.remove(); }); } else { console.error(response); } }); upload.on('progress', function(e, percent) { var moreText = ''; if (percent >= 100) { moreText = ' processing...'; } statusBox.animate({ background: 'linear-gradient(to right, #27a4dd 0%, #27a4dd ' + percent + '%, rgba(0,0,0,0) 100%)' }).text('uploading ' + percent + '%' + moreText); }); upload.send(); }); } } } } }) }; setTimeout(function() { if (!imgsize) { imgsize = { w: img.naturalWidth, h: img.naturalHeight } } css = getRelativeSize(layer.coords, imgsize); css.position = 'absolute'; css.border = '1px solid yellow'; css.opacity = 0; css['z-index'] = layer.depth; layerdom = DOM().new('div').css(css).insertFirst(preview).on('mouseover mouseout', mousey).on('click', mousec); }, 10) var paneldom = DOM().new('div').css({ 'padding-left': (layer.depth * 10) + 'px' }).text(layer.type + ': ' + layer.name).appendTo(layersContainer).class('caa_row caa_row_hover').on('mouseover mouseout', mousey).on('click', mousec); }) elements.forEach(function(element) { if (element.type === 'style') { var fontstr = (element.css['font-family'].split(',')[0] || '') + ' ' + (element.css['font-size'] || '') + ' ' + (element.css['color'] || '').replace(/\ \ /g).trim(); if (fontstr && element.css && !hasTextStyles[fontstr]) { hasTextStyles[fontstr] = true; if (typeof element.css['font-family'] === 'string') { var fontFamily = element.css['font-family'].split(',')[0].split('-'), fontName = fontNameNormal(fontFamily[0] || ''), font, fontWeight = fontWeightMap[(fontFamily[1] || 'normal').idSafe().toLowerCase()] || 400, row = DOM().new('div'), optionsDOM = DOM().new('div').css({ margin: '10px -10px -16px -10px', padding: '10px', 'background-color': 'white' }); if (fontName) { for (var f = 0; f < fontList.length; f++) { if (fontNameNormal(fontList[f].f) == fontName) { font = fontList[f]; break; } } if (!font) { fontName = fontName.split(/[0-9]/)[0]; // split at first number for (var f = 0; f < fontList.length; f++) { if (fontNameNormal(fontList[f].f) == fontName) { font = fontList[f]; break; } } } if (font) { if (typeof fontWeight != 'number' || fontWeight < 100 || fontWeight > 900) { fontWeight = 400; } var family = font.f, fid = font.i || '', fallback = fallback = (font.fb) ? ', \'' + font.fb + '\'' : '', variant = 'n' + (fontWeight / 100), fontStyle = 'normal'; if (font.p === 'T') { family = font.i; } font.v = font.v || ['']; if (font.v.indexOf(variant) < 0) { variant = font.v[0]; } if (variant.indexOf('i') > -1) { fontStyle = 'italic'; } var fontIdent = font.p + ':' + font.f + ':' + variant + ':' + fid; app.loadFont(fontIdent); element.css['font-family'] = family; element.css['font-weight'] = fontWeight; if (fontStyle != 'normal') { element.css['font-style'] = fontStyle; } var exists = '', selectStyle = [{ text: 'Create New Style', value: '' }]; app.site.styles.text.forEach(function(style, s) { if (filterDesignItems(style)) { selectStyle.push({ text: style._label || 'Text Style ' + s, value: 'text' + s }); if (style['.text' + s]['font-ident'] == fontIdent) { exists = s; } } }); if (exists !== '') { DOM().new('div').text('Matches: ' + app.site.styles.text[exists]._label || 'Text Style ' + exists).appendTo(optionsDOM); element.textStyle = 'text' + exists; } else { var addTextForm = DOM().new('form').on('submit', function(e) { e.preventDefault(); addTextForm.remove(); var textStyle = addTextForm.byTag('select').val(), setFont = { 'font-ident': fontIdent, 'font-family': '\'' + family + '\'' + fallback, 'font-size': element.css['font-size'] || '', 'font-weight': fontWeight, color: element.css.color || '', 'font-style': fontStyle } if (textStyle) { textStyle = textStyle.replace('text', ''); } if (textStyle !== '' && app.site.styles.text[textStyle] && app.site.styles.text[textStyle]['.text' + textStyle]) { app.siteUpdate(['styles', 'text', textStyle, '.text' + textStyle], setFont); } else { var next = app.site.styles.text.length * 1; app.addStyle('text'); app.siteUpdate(['styles', 'text', next, '.text' + next], setFont); element.textStyle = 'text' + next; } }) .append(Inputs.options({ label: 'Select Text Style To Update', options: selectStyle }).class('ibb bottom').css({ 'max-width': '200px' })) .append(DOM().new('input').attr({ type: 'submit' }).val('Set Text Style').css({ 'margin-left': '10px' }).class('ibb bottom caa_button-default')) .appendTo(optionsDOM); } row.class('caa_row caa_row_hover') .append(DOM().new('div').text(fontstr || '').css(element.css)) .append(optionsDOM) .appendTo(textStyles); if (element) { if (element.css.color) { if (colorIsLight(element.css.color)) { row.css({ 'background-image': checkered_background_gif }); } } } } } } } } else if (element.type === 'text') { DOM().new('div').class('caa_row caa_row_hover').css({ 'margin': '10px 0' }).text(element.text).appendTo(textElements); } }) }); }).css({ 'pointer-events': 'fill', })).appendTo(formContent); }); }); } App.prototype.importContent = function(item, into) { var app = this; var notesText = 'Feed ' + item.name + ' Source: ' + item.source + ' Account: ' + item.account, notes = DOM().new('div').class('caa_padding').html(notesText).appendTo(into), feedWhat = DOM().new('div').appendTo(into).class('caa_padding'), feedContent = DOM().new('div'), sayWhat = DOM().new('div').text('Loading feed...').appendTo(feedWhat), medias = []; app.getFeedItems(item, function(feed) { var ok = false; if (feed) { sayWhat.html('').append(DOM().new('div').css({ 'font-weight': 'bold' }).text('The following posts will be imported into this site as a manually managed feed:')); if (feed.items) { ok = true; DOM().new('button').class('caa_button-default').text('Import This Content').on('click', function(e) { var newFeed = {}; var newFeedID = uuid(); feed.items.forEach(function(feedItem, i) { if (feedItem.body && !feedItem.description) { feedItem.description = feedItem.body; delete feedItem.body; } }); newFeed[newFeedID] = { name: 'Imported: ' + item.name, source: 'manual', items: feed.items };; app.siteUpdate(['feeds'], newFeed); setTimeout(function() { app.render('/feeds/' + newFeedID, false, false); }); UI.closeModal(); app.destroyPanels(); }).appendTo(sayWhat); feed.items.forEach(function(feedItem, i) { var feedItemHolder = DOM().new('div'), feedItemWhat = DOM().new('div').css({ 'margin': '10px 0' }).appendTo(feedWhat), thisMedias = [], thisMediasMedia = ''; if (feedItem.media) { if (feedItem.media.src) { thisMedias.push({ src: feedItem.media.src }); thisMediasMedia = feedItem.media.src; } } if (feedItem.title) { var title = DOM().new('h2').html(feedItem.title).appendTo(feedItemHolder); DOM().new('div').text(title.text()).appendTo(feedItemWhat); } if (feedItem.body) { DOM().new('div').html(feedItem.body).appendTo(feedItemHolder); } feedItemHolder.byTag('media').exists(function(images) { images.elements.forEach(function(img) { var src = img.getAttribute('data-src'); if (src && src !== thisMediasMedia) { thisMedias.push({ src: src }); } }); }); if (thisMedias.length) { medias = medias.concat(thisMedias); var thisMediasDOM = DOM().new('div').css({ 'padding-left': '20px' }).appendTo(feedItemWhat); thisMedias.forEach(function(media) { app.Media(media).css({ 'max-width': '60px', 'max-height': '60px', margin: '10px' }).appendTo(DOM().new('a').attr({ href: media.src, target: '_blank' }).appendTo(thisMediasDOM)); }); } }); } } if (!ok) { feedWhat.text('we could not load the content'); } }); }; App.prototype.importMedia = function(feedID, into) { var app = this; var feed = app.site.feeds[feedID], notesText = 'Feed ' + feed.name, notes = DOM().new('div').class('caa_padding').html(notesText).appendTo(into), feedWhat = DOM().new('div').appendTo(into).class('caa_padding'), feedContent = DOM().new('div'), sayWhat = DOM().new('div').text('Loading feed...').appendTo(feedWhat), medias = [], mediaURLmap = {}, mediaFetchMap = {}, handleMedia = function(media, into, callback) { if (media.src) { if (!mediaFetchMap[media.src]) { mediaFetchMap[media.src] = true; var statusForImage = DOM().new('div').attr({ 'data-src': media.src }).text('Getting ... ' + media.src).appendTo(into); var upload = new uploadURL(app, media.src, {}); upload.on('completed', function(e, response) { var data = {}; try { data = JSON.parse(response); } catch (err) { data = {}; } if (data.id) { app.siteUpdate(['media', data.id], data.media); mediaURLmap[media.src] = data.id; statusForImage.text('Done ... ' + media.src).css({ color: 'green' }); (feed.items || []).forEach(function(feedItem, i) { var feedItemHolder = DOM().new('div'); if (feedItem.media) { if (feedItem.media.src) { if (feedItem.media.src == media.src) { var update = { media: { media: data.id } }; app.siteUpdate(['feeds', feedID, 'items', i], update); } } } ['title', 'description', 'body'].forEach(function(key) { if ((feedItem[key] || '').match(/media/)) { var check = DOM().new('div').html(feedItem[key]); check.byTag('media').exists(function(images) { images.elements.forEach(function(img) { var src = img.getAttribute('data-src'); if (src) { if (src == media.src) { DOM(img).attr({ 'data-media': data.id, 'data-src': '' }); var update = {}; update[key] = check.html(); app.siteUpdate(['feeds', feedID, 'items', i], update); } } }); }); } }); }); } else { console.error(response); statusForImage.text('Error ... ' + media.src).css({ color: 'red' }); } callback(); }); upload.send(); } else { callback(); } } else { callback(); } }; sayWhat.html('').append(DOM().new('div').css({ 'font-weight': 'bold' }).text('The following media elements will be downloaded and then uploaded into your site\'s media bucket:')); DOM().new('button').class('caa_button-default').text('Import Media').on('click', function(e) { feedWhat.html(''); var state = DOM().new('div').text('Starting...').appendTo(feedWhat), into = DOM().new('div').appendTo(feedWhat), out = 0, done = 0, completed = function(){ done++; if(done >= out){ state.html('Completed!'); } else { state.html('Imported '+done+' of '+out); } }; medias.forEach(function(media, m) { out++; setTimeout(function() { handleMedia(media, into, completed); }, (m * 1000)); }); }).appendTo(sayWhat); (feed.items || []).forEach(function(feedItem, i) { var feedItemHolder = DOM().new('div'), feedItemWhat = DOM().new('div').css({ 'margin': '10px 0' }).appendTo(feedWhat), thisMedias = [], thisMediasMedia = ''; if (feedItem.media) { if (feedItem.media.src) { thisMedias.push({ src: feedItem.media.src }); thisMediasMedia = feedItem.media.src; } } if (feedItem.title) { DOM().new('div').html(feedItem.title).appendTo(feedItemHolder); } if (feedItem.body) { DOM().new('div').html(feedItem.body).appendTo(feedItemHolder); } feedItemHolder.byTag('media').exists(function(images) { images.elements.forEach(function(img) { var src = img.getAttribute('data-src'); if (src && src !== thisMediasMedia) { thisMedias.push({ src: src }); } }); }); if (thisMedias.length) { DOM().new('div').text(feedItem.title).appendTo(feedItemWhat); medias = medias.concat(thisMedias); var thisMediasDOM = DOM().new('div').css({ 'padding-left': '20px' }).appendTo(feedItemWhat); thisMedias.forEach(function(media) { app.Media(media).css({ 'max-width': '60px', 'max-height': '60px', margin: '10px' }).appendTo(DOM().new('a').attr({ href: media.src, target: '_blank' }).appendTo(thisMediasDOM)); }); } }); }; App.prototype.integrations_googleWebmasterVerifySite = function(into) { var app = this; var configKey = 'googleWebmasterVerifySite', config = app.site.settings.integrations[configKey] || {}, disp = 'your verification code'; if (config.metaTag) { disp = config.metaTag + ''; } Inputs.text({ label: 'Google Webmaster Tools Site Verification Meta Tag', value: config.metaTag || '', explain: 'Type in or paste the Google Webmaster Tools verification meta tag provided by Google. Publish your whole site or just your home page before having Google check for the tag' }).appendTo(into).byTag('input').on('change', function(e) { var val = DOM(e.target).val(), value = ''; var parts = val.split(/content\=\"/); if (parts[0] && parts[1]) { value = parts[1].split('"')[0]; } else { value = parts[0] || ''; } value = value.replace(/[^a-z0-9\-\_]/gi, ''); var update = { metaTag: value }; DOM(e.target).val(value); metaTag.text('
'); app.siteUpdate(['settings', 'integrations', configKey], update, true); }); var metaTag = DOM().new('div').css({ 'font-size': '10px', color: '#666' }).text('
').appendTo(into); return this; }; App.prototype.integrations_bingWebmasterVerifySite = function(into) { var app = this; var configKey = 'bingWebmasterVerifySite', config = app.site.settings.integrations[configKey] || {}, disp = 'your verification code'; if (config.metaTag) { disp = config.metaTag + ''; } Inputs.text({ label: 'Bing Webmaster Tools Site Verification Meta Tag', value: config.metaTag || '', explain: 'Type in or paste the Bing Webmaster Tools verification meta tag provided by Bing. Publish your whole site or just your home page before having Bing check for the tag' }).appendTo(into).byTag('input').on('change', function(e) { var val = DOM(e.target).val(), value = ''; var parts = val.split(/content\=\"/); if (parts[0] && parts[1]) { value = parts[1].split('"')[0]; } else { value = parts[0] || ''; } value = value.replace(/[^a-z0-9\-\_]/gi, ''); var update = { metaTag: value }; DOM(e.target).val(value); metaTag.text('
'); app.siteUpdate(['settings', 'integrations', configKey], update, true); }); var metaTag = DOM().new('div').css({ 'font-size': '10px', color: '#666' }).text('
').appendTo(into); return this; }; App.prototype.integrations_pinterestVerifySite = function(into) { var app = this; var configKey = 'pinterestVerifySite', config = app.site.settings.integrations[configKey] || {}, disp = 'your verification code'; if (config.metaTag) { disp = config.metaTag + ''; } Inputs.text({ label: 'Pinterest Site Verification Meta Tag', value: config.metaTag || '', explain: 'Type in or paste the verification meta tag provided by Pinterest. Publish your whole site or just your home page before having pinterest check for the tag' }).appendTo(into).byTag('input').on('change', function(e) { var val = DOM(e.target).val(), value = ''; var parts = val.split(/content\=\"/); if (parts[0] && parts[1]) { value = parts[1].split('"')[0]; } else { value = parts[0] || ''; } value = value.replace(/[^a-z0-9]/gi, ''); var update = { metaTag: value }; DOM(e.target).val(value); metaTag.text('
'); app.siteUpdate(['settings', 'integrations', configKey], update, true); }); var metaTag = DOM().new('div').css({ 'font-size': '10px', color: '#666' }).text('
').appendTo(into); return this; }; App.prototype.integrations_facebookVerifySite = function(into) { var app = this; var configKey = 'facebookVerifySite', config = app.site.settings.integrations[configKey] || {}, disp = 'your verification code'; if (config.metaTag) { disp = config.metaTag + ''; } Inputs.text({ label: 'Facebook Insights Verification Meta Tag', value: config.metaTag || '', explain: 'Type in or paste the verification meta tag provided by Facebook. Publish your whole site or just your home page before having Facebook check for the tag' }).appendTo(into).byTag('input').on('change', function(e) { var val = DOM(e.target).val(), value = ''; var parts = val.split(/content\=\"/); if (parts[0] && parts[1]) { value = parts[1].split('"')[0]; } else { value = parts[0] || ''; } value = value.replace(/[^a-z0-9]/gi, ''); var update = { metaTag: value }; DOM(e.target).val(value); metaTag.text('
'); app.siteUpdate(['settings', 'integrations', configKey], update, true); }); var metaTag = DOM().new('div').css({ 'font-size': '10px', color: '#666' }).text('
').appendTo(into); return this; }; App.prototype.integrations_optimizelySnippet = function(into) { var app = this; var configKey = 'optimizelySnippet', config = app.site.settings.integrations[configKey] || {}, disp = 'your optimizely script url'; if (config.metaTag) { disp = config.metaTag + ''; } /*** NOT WORKING YET, CONSIDER PER-PAGE IMPLEMENTATION ***/ Inputs.text({ label: 'Facebook Insights Verification Meta Tag', value: config.metaTag || '', explain: 'Type in or paste the script tag provided by Optimizely. Publish your whole site or just your home page before having Facebook check for the tag' }).appendTo(into).byTag('input').on('change', function(e) { var val = DOM(e.target).val(), value = ''; var parts = val.split(/content\=\"/); if (parts[0] && parts[1]) { value = parts[1].split('"')[0]; } else { value = parts[0] || ''; } value = value.replace(/[^a-z0-9]/gi, ''); var update = { metaTag: value }; DOM(e.target).val(value); metaTag.text('
'); app.siteUpdate(['settings', 'integrations', configKey], update, true); }); var metaTag = DOM().new('div').css({ 'font-size': '10px', color: '#666' }).text('
').appendTo(into); return this; }; App.prototype.integrations_twitterRemarketing = function(into) { var app = this; var configKey = 'twitterRemarketing', config = app.site.settings.integrations[configKey] || {}; var executeThis = function() { into.html(''); if (Object.keys(config).length < 1) { config[uuid()] = {}; } Object.keys(config).forEach(function(key, i, ar) { var itemConfig = config[key]; if (typeof itemConfig !== 'object') { config[key] = {}; itemConfig = config[key]; } var holder = DOM().new('div').css({ position: 'relative' }).appendTo(into); Inputs.text({ label: 'Campaign Name', value: itemConfig.name || '' }).appendTo(holder).byTag('input').on('change', function(e) { itemConfig.name = DOM(e.target).val() || ''; app.siteUpdate(['settings', 'integrations', configKey], config, true); }); Inputs.textarea({ label: 'Twitter Remarketing Script/Code', value: itemConfig.script || '', explain: 'Paste the code provided by twitter into the box above' }).appendTo(holder).byTag('textarea').on('change', function(e) { itemConfig.script = DOM(e.target).val() || ''; app.siteUpdate(['settings', 'integrations', configKey], config, true); }); if(ar.length > 1) { DOM().new('button').class('caa_button-delete').css({ position: 'absolute', right: 0, top: '-30px' }).on('click', function(e) { app.siteDelete(['settings', 'integrations', configKey, key]); app.integrations_twitterRemarketing(into); }).appendTo(holder); } Inputs.checkbox({ label: 'Apply To Every Page', value: itemConfig.allPages, onchange: function(chkd) { itemConfig.allPages = chkd; app.siteUpdate(['settings', 'integrations', configKey], config, true); } }).appendTo(holder); DOM().new('div').css({ 'padding-bottom': '50px' }).appendTo(holder); //spacer }); DOM().new('button').class('caa_button-default').appendTo(into).text('Add Another').on('click', function(e) { config[uuid()] = { name: 'New Campaign ' + (Object.keys(config).length + 1) }; app.siteUpdate(['settings', 'integrations', configKey], config, true); executeThis(); }); }; executeThis(); return this; }; App.prototype.integrations_pageScripts = function(into) { var app = this; var configKey = 'pageScripts', config = app.site.settings.integrations[configKey] || {}; var executeThis = function() { into.html(''); if (Object.keys(config).length < 1) { config[uuid()] = {}; } Object.keys(config).forEach(function(key, i, ar) { var itemConfig = config[key]; if (typeof itemConfig !== 'object') { config[key] = {}; itemConfig = config[key]; } var holder = DOM().new('div').css({ position: 'relative' }).appendTo(into); Inputs.text({ label: 'Integration/Script Name', value: itemConfig.name || '', explain: 'Enter the name of the integration script to make available to one or all of your pages. The name is used to identify the script being added to the page in the page settings.' }).appendTo(holder).byTag('input').on('change', function(e) { itemConfig.name = DOM(e.target).val() || ''; app.siteUpdate(['settings', 'integrations', configKey], config, true); }); Inputs.textarea({ label: 'Integration Script / Paste Code', value: itemConfig.script || '', explain: 'Enter or paste the code provided to make available to your pages. If you enable the "apply to every page" option this script will automatically be included in every page. If it is not included in every page it can be optionally included in individual pages within the integrations section of the page itself' }).appendTo(holder).byTag('textarea').on('change', function(e) { itemConfig.script = DOM(e.target).val() || ''; app.siteUpdate(['settings', 'integrations', configKey], config, true); }); if(ar.length > 1) { DOM().new('button').class('caa_button-delete').css({ position: 'absolute', right: 0, top: '-30px' }).on('click', function(e) { app.siteDelete(['settings', 'integrations', configKey, key]); app.integrations_twitterRemarketing(into); }).appendTo(holder); } Inputs.checkbox({ label: 'Apply To Every Page', value: itemConfig.allPages, onchange: function(chkd) { itemConfig.allPages = chkd; app.siteUpdate(['settings', 'integrations', configKey], config, true); } }).appendTo(DOM().new('span').class('ib middle').appendTo(holder)); Inputs.checkbox({ label: 'Insert Into Tag', value: itemConfig.headTag, onchange: function(chkd) { itemConfig.headTag = chkd; app.siteUpdate(['settings', 'integrations', configKey], config, true); } }).appendTo(DOM().new('span').class('ib middle').appendTo(holder)); DOM().new('div').css({ 'padding-bottom': '20px' }).appendTo(holder); //spacer }); DOM().new('button').class('caa_button-default').appendTo(into).text('Add Another').on('click', function(e) { config[uuid()] = { name: 'New Campaign ' + (Object.keys(config).length + 1) }; app.siteUpdate(['settings', 'integrations', configKey], config, true); executeThis(); }); }; executeThis(); return this; }; App.prototype.logout = function(){ var app = this; app.stage.html(''); var content = DOM().new('div').class('caa_padding').appendTo(app.stage); DOM().new('button').class('caa_button-default').css({'margin-right': '10px'}).text('Logout This Session').appendTo(content).on('click', function(e){ localStorage.removeItem('_ca:User'); localStorage.removeItem('_ca:site'); window.location.href = '/?logout=true'; }); DOM().new('button').class('caa_button-default').text('Logout All Sessions').appendTo(content).on('click', function(e){ app.Request({ do: 'request', request: 'destroyAllSessions' }, function(data) { localStorage.removeItem('_ca:User'); localStorage.removeItem('_ca:site'); window.location.href = '/?logout=true'; }); }); } App.prototype.mediaMain = function(mediaIn, path, into, browseClick, source, pickEvent) { var app = this, browseMode = false, prefs = app.urlPrefs(), massDeleteTypes = ['image/png', 'image/gif', 'image/jpg', 'image/jpeg', 'image/svg+xml', 'icon/svg+xml', 'video/mp4', 'application/pdf'], appHeader = DOM().new('div').class('caa_content caa_header'); if (into) { browseMode = true; } else { into = app.stage; app.stage.html(''); // mark content as the highlighted nav section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.contentMenu(false); } var media, mediaContainer; if (!source) { source = ''; } if (app.parts[1] && !prefs.type && !prefs.tag && !prefs.sort && !browseMode) { if (!browseMode) { appHeader .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/media', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Media: ' + app.parts[1] || '')) .insertFirst(into); } var box = DOM().new('div').class('caa_content caa_padding').appendTo(into); var mediaID = app.parts[1]; media = app.site.media[mediaID]; if (media) { Inputs.text({ label: 'Media Title', value: media.name || '' }).appendTo(box) .addClass('ib top').css({ width: '200px', 'margin-right': '10px' }) .byTag('input').on('change', function(e) { var update = { name: DOM(e.target).val() }; app.siteUpdate(['media', mediaID], update); }); EditorHelpers.tags(app, box, media, ['media', mediaID], {}, { label: 'Tags', value: media.tags || [], property: 'tags' }).removeClass('caa_rightPanelSection').addClass('ib top').css({ width: '200px' }); mediaContainer = DOM().new('div').css({ 'background-image': checkered_background_gif }); app.subscribe('media/' + mediaID, function onchangeMedia() { mediaContainer.html(''); var actualMedia = app.Media({ media: mediaID, display: 'normal' }).appendTo(mediaContainer); box.byClass('camediaload').loadMedia(); }); setTimeout(function() { box.byClass('camediaload').loadMedia(); }, 10); mediaContainer.appendTo(box); var info = DOM().new('div').appendTo(box); var urlList = [], ext = media.type ? anyTypeToExtension(media.type) : 'svg'; if (ext === 'jpg' || ext === 'png' || ext === 'gif') { urlList.push({ title: 'Original Media URL', url: ca_config.media_cdn + '/' + (media.siteID || app.site.id) + '/' + mediaID + '.' + ext }); urlList.push({ title: 'Optimized Media URL', url: ca_config.optimize_cdn + '/' + (media.siteID || app.site.id) + '/w:800/' + mediaID + '.' + ext }); } else if (ext === 'pdf') { urlList.push({ title: 'PDF URL', url: ca_config.media_cdn + '/' + (media.siteID || app.site.id) + '/' + mediaID + '.' + ext }); urlList.push({ title: 'Preview Thumbnail', url: ca_config.optimize_cdn + '/' + (media.siteID || app.site.id) + '/w:800/from:pdf/' + mediaID + '.png' }); } else if (ext === 'mp4') { var vid = box.byTag('video').elements[0]; if (vid) { vid.addEventListener('loadedmetadata', function(e) { if (vid.videoWidth && vid.videoHeight) { if(!media || !media.size || !media.size.w){ var update = { size: { w: vid.videoWidth, h: vid.videoHeight } }; app.siteUpdate(['media', mediaID], update); } } }, false); } urlList.push({ title: 'Video URL', url: ca_config.media_cdn + '/' + (media.siteID || app.site.id) + '/' + mediaID + '.' + ext }); } urlList.forEach(function(urlItem) { if (urlItem.url) { DOM().new('div').css({ 'padding-top': '10px' }) .append( DOM().new('div').text(urlItem.title) .append( DOM().new('button').class('caa_button-default').css({ padding: '2px', margin: '0 2px' }).text('Copy URL').on('click', function(e) { // Select the email link anchor text var successful = false; try { var range = document.createRange(); range.selectNode(e.target.parentNode.parentNode.querySelector('a')); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); successful = document.execCommand('copy'); window.getSelection().removeAllRanges(); } catch (err) { // } if (successful) { DOM(e.target).text('Copied'); setTimeout(function() { DOM(e.target).text('Copy URL'); }, 1000); } }) ) ) .append( DOM().new('a').attr({ href: urlItem.url, target: '_blank' }).text(urlItem.url) ).appendTo(info); } }); Inputs.textarea({ label: 'Media Description/Body', value: media.description || '' }).appendTo(box).byTag('textarea').on('change', function(e) { app.siteUpdate(['media', mediaID], { description: DOM(e.target).val() || '' }); }); Inputs.date({ label: 'Media Date', value: media.date }).appendTo(box).css({ 'max-width': '200px' }).byTag('input').on('change', function(e) { var update = {}; update.date = isoDate(parseAnyDate(DOM(e.target).val())); app.siteUpdate(['media', mediaID], update); }) Inputs.checkbox({ label: 'Featured', value: media.featured || false, onchange: function(val) { app.siteUpdate(['media', mediaID], { featured: val }); } }).appendTo(box).css({ 'margin-top': '10px', 'max-width': '200px' }); if (ext === 'svg') { Inputs.checkbox({ label: 'Inline SVG', value: media.inline || false, onchange: function(val) { app.siteUpdate(['media', mediaID], { inline: val }); } }).appendTo(box).css({ 'margin-top': '10px', 'max-width': '200px' }); DOM().new('button').class('caa_button-default').text('Auto Clean/Fix Generated SVG').on('click', function(e) { var update = {}; if (media.content && media.content.substr(0, 4).toLowerCase() != '
').appendTo(bottom); objectFind(app.site, [], ['media', 'backgroundMedia', 'title', 'body'], mediaID, function(path, object, key) { var str = humanPath(path, object), link = app.pathToURL(path), node = DOM().new(link ? 'a' : 'span').text(str).appendTo(usage); if (link) { node.attr({ href: link }).on('click', function(e) { e.preventDefault(); app.render(link, false); UI.closeModal(); }); } DOM().new('br').appendTo(usage); matches = true; }); if (!matches && !media.siteID) { usage.html(''); var deleteButton = UI.deleteButton('Delete Media', 'button', function(e) { deleteButton.text('Deleting...').attr({disabled: true}); app.Request({ do: 'request', request: 'deleteMedia', mediaID: app.parts[1] }, function(data) { if (data.success) { app.siteDelete(['media', app.parts[1]]); app.render('/media', false, false); } else { deleteButton.text('Error! Could not delete!').attr({disabled: false}); } }); }).appendTo(bottom); } else if (!matches && media.siteID && media.siteID !== app.site.id) { usage.html(''); var deleteButton = UI.deleteButton('Delete Media', 'button', function(e) { app.siteDelete(['media', app.parts[1]]); app.render('/media', false, false); }).appendTo(bottom); } var tmpHolder = DOM().new('div').css({ position: 'absolute', left: '-10000px', width: '10px', height: '10px' }).appendTo(app.stage); app.screenResize.push(function() { DOM().byClass('camediaload').loadMedia({ loadEffect: 'none' }); }); } } else { media = mediaIn; if (browseMode) { app.pasteListeners = []; } var previewAndUpload = function(e) { var accepted = ['gif', 'png', 'jpg', 'svg', 'mp4', 'mp3', 'pdf', 'woff', 'woff2', 'kmz'], uploadByURL = ''; if (!e.dataTransfer) { e.dataTransfer = {}; } if (!e.target) { e.target = {}; } var files = e.target.files || e.dataTransfer.files || []; if (e.type === 'paste') { if (DOM().id('media-upload-input').exists()) { if (!e.clipboardData) { return; } var image = e.clipboardData.items; if (image) { for (var i = 0; i < image.length; i++) { if ((image[i].type || '').indexOf('image') !== -1) { var blob = image[i].getAsFile(); files.push(blob); } else { var asText = e.clipboardData.getData('text/plain'); console.log('paste event: not an image', image[i], 'trying as text', asText); if (asText) { for (var a = 0; a < accepted.length; a++) { if (asText.substr(0 - accepted[a].length) === accepted[a]) { uploadByURL = asText; } } } } } } } else { return false; } } if (uploadByURL) { var box = DOM().new('div').css({ 'margin-top': '10px' }).text('Uploading url ' + uploadByURL + ' ...'); box.appendTo(previewContainer.css({ display: '' })); var upload = new uploadURL(app, uploadByURL, { noresize: 1 }); upload.on('completed', function(e, response) { var data = {}; try { data = JSON.parse(response); } catch (err) { data = {}; } if (data.id) { box.animate({ opacity: 0 }, function() { box.remove(); }); app.siteUpdate(['media', data.id], data.media); if (browseMode) { if (browseClick) { browseClick(e, { media: data.id }); } } } else { console.error(response); } }); upload.send(); } else if (files.length) { [].slice.call(files).forEach(function(file) { var ext = anyTypeToExtension(file.type); var type = extensionToContentType(ext); console.log('type', ext, type, file.type) if (accepted.indexOf(ext) < 0) { console.error(new Error('file not accepted: ' + ext)); return; } var windowURL = window.URL || window.webKitURL, url; if (windowURL && windowURL.createObjectURL) { if (ext === 'svg') { var reader = new FileReader(); reader.onload = function(e) { var svgContent = reader.result || ''; svgContent = svgContent.replace(/\<\?xml(.+?)\?\>/gi, '').trim(); var update = {}; var mediaID = uuid(); if (mediaID) { update[mediaID] = { name: file.name || 'No Name Set', type: 'image/svg+xml', content: svgContent }; app.siteUpdate(['media'], update); } if (browseMode) { if (browseClick) { browseClick(e, { media: mediaID }); } } }; reader.readAsText(file); } else { url = windowURL.createObjectURL(file); var typeTag = type.split('/')[0], previewTag; var box = DOM().new('div').css({ 'margin-top': '10px' }); var mediaBox = DOM().new('div').class('ib middle imgfit').css({ width: '90px', 'margin-right': '10px', overflow: 'hidden', height: '80px' }).appendTo(box); var rightBox = DOM().new('div').class('ibb middle').css({ width: 'calc(100% - 100px)' }).appendTo(box); var filenameBox = DOM().new('div').class('ellipsis').css({ padding: '6px' }).appendTo(rightBox).text((file.name || '')); var statusBox = DOM().new('div').class('ellipsis').css({ padding: '6px' }).appendTo(rightBox).text('uploading...'); if (typeTag === 'image') { previewTag = DOM().new('img').class('imgfit').css({ height: '100%', width: 'auto', 'max-width': 'none' }).attr({ src: url }).appendTo(mediaBox); } else if (typeTag === 'video') { previewTag = DOM().new('video').class('imgfit').attr({ src: url, controls: true }).appendTo(mediaBox); } else { previewTag = DOM().new('div').class('ib middle').css({ width: '90px', height: '80px', 'background-color': '#ccc' }).appendTo(mediaBox); } var upload = new uploadFile(app, file); upload.on('completed', function(e, response) { var data = {}; try { data = JSON.parse(response); } catch (err) { data = {}; } if (data.id) { app.siteUpdate(['media', data.id], data.media); box.animate({ opacity: 0 }, function() { box.remove(); }); if (browseMode) { if (browseClick) { browseClick(e, { media: data.id }); } } } else { console.error(response); } }); upload.on('progress', function(e, percent) { var moreText = ''; if (percent >= 100) { moreText = ' processing...'; } statusBox.animate({ background: 'linear-gradient(to right, #27a4dd 0%, #27a4dd ' + percent + '%, rgba(0,0,0,0) 100%)' }).text('uploading ' + percent + '%' + moreText); }); upload.send(); if (url) { previewTag.on('load', function(e) { windowURL.revokeObjectURL(url); }); } box.appendTo(previewContainer.css({ display: '' })); return; } } }); } }; var backLink = '/content', mediaFilterText = '', mediaContent = DOM().new('div').class('caa_content'), topArea = DOM().new('div').appendTo(mediaContent), uploadContainer = DOM().new('div').appendTo(topArea), previewContainer = DOM().new('div').class('caa_padding').css({ display: 'none', 'margin-top': '10px' }).appendTo(topArea), searchTimer, sectionList, dragArea = DOM().new('label').css({ display: 'block', position: 'relative', overflow: 'hidden', 'min-height': '40px', margin: '10px' }) .append(DOM().new('div').class('caa_pickMedia').text('DRAG, PASTE OR PRESS HERE TO UPLOAD')) .append(UI.dropZone(previewAndUpload)) .appendTo(topArea), header = DOM().new('div').class('caa_content caa_control_header').appendTo(topArea), mediaFilter = { search: '', tags: [], type: '' }, input = DOM().new('input').id('media-upload-input').attr({ type: 'file', multiple: true }).insertFirst(dragArea).css({ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', margin: 0, opacity: 0.01, cursor: 'pointer' }).on('change', previewAndUpload), loadMediaFunc, filterMedia = function() { var gridItems = DOM().byClass('caa_row'), Search = (mediaFilter.search || '').trim(); app.lastSearchMedia = Search; clearTimeout(searchTimer); searchTimer = setTimeout(function() { var searchAr = Search.split(/\\s */), searchRegex = ''; for (var s in searchAr) { if (searchAr[s]) { if (searchRegex) { searchRegex += '|'; } searchRegex += searchAr[s]; } } var Regex = new RegExp(searchRegex, 'i'); gridItems.elements.forEach(function(element, e) { var el = DOM(element), hasType = el.attr('data-type'), hasTags = el.attr('data-tags') || ''; if ((Search && !Regex.test(el.text())) || (mediaFilter.type && hasType !== mediaFilter.type) || (mediaFilter.tag !== '__notag' && mediaFilter.tag && hasTags.indexOf(mediaFilter.tag) < 0) || (mediaFilter.tag === '__notag' && hasTags)) { el.css({ display: 'none' }); } else { el.css({ display: '', }); } el.byTag('input').trigger('change') }); loadMediaFunc(); }, 200); }, checkList = [], checkListDom = DOM().new('div'), showCheckListOptions = function() { checkListDom.html(''); if (checkList.length) { DOM().new('form').on('submit', function(e) { e.preventDefault(); var tag = (DOM(e.target).byTag('input').val() || '').trim().toLowerCase().urlSafe(); if (tag) { checkList.forEach(function(checkMediaID) { var checkMedia = app.site.media[checkMediaID]; if (checkMedia) { var update = { tags: [] }; if ((checkMedia.tags || '').indexOf('tag') < 0) { update.tags = (checkMedia.tags || []).concat(tag); } else { update.tags = [tag]; } app.siteUpdate(['media', checkMediaID], update); } }) checkList = []; renderMediaList(); app.contentMenu(false); showCheckListOptions(); } }) .append(Inputs.text({ label: 'Add Tag To Selected' }) .append(DOM().new('button').class('caa_button-add').css({ position: 'absolute', right: '-6px', top: '-4px', transform: 'scale(0.65)' }).attr({ type: 'submit', }))) .appendTo(DOM().new('div').class('ibb middle').css({ width: '240px' }).appendTo(checkListDom)); UI.deleteButton('Delete Selected Media', 'button', function(e) { checkList.forEach(function(checkMediaID) { var mediaUsed = false; objectFind(app.site, [], ['media', 'backgroundMedia', 'title', 'body'], checkMediaID, function(path, object, key) { mediaUsed = true; }, true, false); if (massDeleteTypes.indexOf(app.site.media[checkMediaID].type) < 0) { mediaUsed = true; } if (!mediaUsed) { if (app.site.media[checkMediaID] && app.site.media[checkMediaID].siteID && app.site.media[checkMediaID].siteID !== app.site.id) { app.siteDelete(['media', checkMediaID]); } else { app.Request({ do: 'request', request: 'deleteMedia', mediaID: checkMediaID }, function(data) { if (data.success) { app.siteDelete(['media', checkMediaID]); } else { deleteButton.text('Error! Could not delete!').attr({disabled: false}); } }); } } }); setTimeout(function() { app.render('/media', false, false); }, 10) }).removeClass('middle').addClass('bottom').css({ 'margin-left': '20px' }).appendTo(checkListDom); } }; if (!browseMode) { if (prefs.type || prefs.tag) { backLink = '/media'; mediaFilterText = ': ' + (prefs.type || prefs.tag); } appHeader .append(UI.Icon('left', 'head').on('click', function(e) { app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Media' + mediaFilterText)) .insertFirst(mediaContent); } Inputs.search({ label: 'Find Media', value: app.lastSearchMedia || '' }).addClass('ib middle').css({ width: '200px' }).appendTo(header).byTag('input').on('input,blur', function(e) { mediaFilter.search = DOM(e.target).val() || ''; filterMedia(); }); var opsHolder = DOM().new('div').class('ib middle').css({ width: '140px' }).appendTo(header).css({ 'margin-left': '10px' }); sectionList = DOM().new('div').class('ib middle').css({ width: 'calc(100% - 354px)', padding: '10px 0', 'margin-top': '20px', 'white-space': 'nowrap', 'text-align': 'right', 'min-width': '200px', 'max-width': '100%' }).appendTo(header); checkListDom.appendTo(header); app.pasteListeners.push(previewAndUpload); if (pickEvent && pickEvent.type === 'drop') { previewAndUpload(pickEvent); } mediaContainer = DOM().new('div').appendTo(mediaContent); mediaContent.appendTo(into); var sortFunc = function(e) { var gosort = DOM(e.target).attr('data-sort'); if (prefs.sort === gosort || (!prefs.sort && gosort === 'recent')) { prefs.sort = gosort + '-rev'; } else { prefs.sort = gosort; } if (browseMode) { renderMediaList(); } else { app.render('/media' + app.urlPrefs(prefs), false, false); } }, sortRecent = DOM().new('a').class('ib caa_click caa_secLinks').css({ color: '', 'text-decoration': 'underline' }).text(prefs.sort === 'recent-rev' ? 'Oldest' : 'Recent').attr({ 'data-sort': 'recent' }).appendTo(sectionList).on('click', sortFunc), sortAZ = DOM().new('a').class('ib caa_click caa_secLinks').css({ 'padding-left': '10px', color: '', 'text-decoration': 'underline' }).text(prefs.sort === 'a-z-rev' ? 'Z-A' : 'A-Z').attr({ 'data-sort': 'a-z' }).appendTo(sectionList).on('click', sortFunc); if (!browseMode) { DOM().new('input').class('blux_checkbox').css({ 'margin-left': '10px' }).attr({ type: 'checkbox' }).appendTo(sectionList).on('change', function(e) { var checked = e.target.checked; mediaContainer.byTag('input').attr({ checked: checked }).trigger('change'); }); } var mediaRefs = {}; var renderMediaList = function() { mediaContainer.html('').remove(); mediaContainer = DOM().new('div'); sortRecent.text(prefs.sort === 'recent-rev' ? 'Oldest' : 'Recent'); sortAZ.text(prefs.sort === 'a-z-rev' ? 'Z-A' : 'A-Z'); var useAr = [], mediaTypes = []; if (prefs.sort === 'a-z' || prefs.sort === 'a-z-rev') { sortRecent.css({ 'font-weight': '' }); sortAZ.css({ 'font-weight': 'bold' }); useAr = Object.keys(app.site.media).reverse().sort(function(a, b) { return ((app.site.media[a] || {}).name || '').localeCompare((app.site.media[b] || {}).name || ''); }); } else { sortRecent.css({ 'font-weight': 'bold' }); sortAZ.css({ 'font-weight': '' }); useAr = Object.keys(app.site.media).reverse(); } if ((prefs.sort || '').indexOf('-rev') > -1) { useAr = useAr.reverse(); } if (source === 'Custom Elements') { topArea.remove(); } useAr.forEach(function(mediaID, i, ar) { var go = false, item = app.site.media[mediaID] || {}; if (source === 'Custom Elements') { if (app.site.media[mediaID].type === 'custom') { go = true; } } else { go = true; } if (prefs.type) { go = false; if (app.site.media[mediaID].type == prefs.type) { go = true; } } if (prefs.tag) { go = false; if ((app.site.media[mediaID].tags || '').indexOf(prefs.tag) > -1) { go = true; } if (prefs.tag === '__notag') { if (!app.site.media[mediaID].tags || !app.site.media[mediaID].tags.length) { go = true; } } if (prefs.tag === '__nouse') { var mediaUsed = false; objectFind(app.site, [], ['media', 'backgroundMedia', 'title', 'body'], mediaID, function(path, object, key) { mediaUsed = true; }, true, false); if (massDeleteTypes.indexOf(app.site.media[mediaID].type) < 0) { mediaUsed = true; } go = !mediaUsed } } if (go) { var editorLink = '/media'; if (app.site.media[mediaID].type === 'custom') { editorLink = '/custom'; } var info = { name: item.name || 'No Name Set', type: item.type || '', tags: Array.isArray(item.tags) ? item.tags : '' }; if (info.type) { if (mediaTypes.indexOf(info.type) < 0) { mediaTypes.push(info.type); } } if (Array.isArray(info.tags)) { info.tags.forEach(function(tag) { if (mediaTypes.indexOf('#' + tag) < 0) { mediaTypes.push('#' + tag); } }) } if (item.size) { info.size = 'Size: ' + item.size.w + 'x' + item.size.h; } if (info.type === 'image/svg+xml') { if (item.content && item.content.indexOf('data:image/') > 0) { info.oversized = 'SVG includes raster image warning. Prefer using JPG or PNG over SVG for this image.'; } } if (item.siteID) { if (item.siteID !== app.site.id) { var refSite = ''; for (var k in app.sites) { if (app.sites[k].id === item.siteID) { refSite = app.sites[k].name || ''; } } if (refSite) { info.external = 'External Reference: ' + refSite; } else { info.external = 'External Reference'; } } } var row = DOM().new('div').class('caa_row caa_row_hover caa_click').attr({ 'data-type': info.type, 'data-tags': info.tags ? info.tags.join(',') : '' }).css({ 'white-space': 'nowrap' }).on('click', function(e) { if (!app.mediaBrowseClickPrevention) { if (browseMode) { if (browseClick) { browseClick(e, { media: mediaID }); } } else { app.render(editorLink + '/' + mediaID, false, false); } } }).appendTo(mediaContainer); if (!browseMode) { var rowClickPrevention = function(e) { app.mediaBrowseClickPrevention = true; setTimeout(function() { delete app.mediaBrowseClickPrevention; }, 100) }; DOM().new('label').class('ibb').css({ position: 'absolute', right: '0', top: '0', width: '100px', height: '100%', padding: '14px', 'text-align': 'right' }).append(DOM().new('input').attr({ type: 'checkbox' }).class('blux_checkbox').on('change', function(e) { rowClickPrevention(); var inthere = checkList.indexOf(mediaID); if (e.target.checked && row.css('display') !== 'none') { if (inthere < 0) { checkList.push(mediaID); } } else { if (inthere >= 0) { checkList.splice(inthere, 1); } } showCheckListOptions(); })).appendTo(row) .on('mousemedia click', rowClickPrevention) } var m = DOM().new('div').class('ib middle').css({ width: '130px', height: '74px', 'background-image': checkered_background_gif }).appendTo(row); if ((item.type || '').indexOf('/font') > -1) { var ext = anyTypeToExtension(item.type); var fontURL = ca_config.media_cdn + '/' + (item.siteID || app.site.id) + '/' + mediaID + '.' + ext DOM().new('style').text('\ @font-face {\ font-family: \'custom-font-' + mediaID + '\';\ src: url(\'' + fontURL + '\') format(\'woff\');\ }\ ').appendTo(m); m.css({ 'background-image': '' }) .append(DOM().new('div').text('Aa Bb Cc Dd')) .append(DOM().new('span').css({ 'font-family': 'custom-font-' + mediaID }).text('Aa Bb Cc Dd')); } else { mediaRefs[mediaID] = m; /*app.Media({ media: mediaID, display: 'contain', browse: browseMode }).appendTo(m).css({ 'pointer-events': 'none', overflow: 'hidden' });*/ } var textbox = DOM().new('div').class('ib middle').css({ 'margin-left': '10px', 'max-width': '300px' }).appendTo(row); for (var k in info) { DOM().new('div').text(info[k]).appendTo(textbox); } } }); if (browseMode) { opsHolder.html('').append( Inputs.options({ label: 'Type', options: ['All'].concat(mediaTypes.sort()).concat({ text: 'Not Tagged', value: '#__notag' }, { text: 'Not Used', value: '#__nouse' }), onchange: function(val) { if (val !== 'All') { if (val[0] === '#') { mediaFilter.tag = val.substr(1); mediaFilter.type = ''; } else { mediaFilter.type = val; mediaFilter.tag = ''; } } else { mediaFilter.type = ''; mediaFilter.tag = ''; } filterMedia(); } }) ); } mediaContainer.appendTo(mediaContent); if (app.lastSearchMedia) { mediaFilter.search = app.lastSearchMedia; filterMedia(); } var allmedia = DOM().byClass('camediaload'); var inViewPort = function(element) { var rect = element.getBoundingClientRect(), chk_h = window.innerHeight; if (rect.top < chk_h && (rect.top + rect.height) > 0) { return true; } return false; }; loadMediaFunc = function() { for (var mediaID in mediaRefs) { if (!mediaRefs[mediaID].loaded && inViewPort(mediaRefs[mediaID].elements[0])) { mediaRefs[mediaID].loaded = true; app.Media({ media: mediaID, display: 'contain', browse: browseMode }).appendTo(mediaRefs[mediaID]).css({ 'pointer-events': 'none', overflow: 'hidden' }).loadMedia(); } else { console.log('not loading'); } } }; setTimeout(loadMediaFunc, 10) app.onScroll(loadMediaFunc); if (into.parent().elements[0].className.indexOf('modal') > -1) { var scrollTimer; into.parent().on('scroll', function(e) { clearTimeout(scrollTimer) scrollTimer = setTimeout(loadMediaFunc, 50); }) } }; window.requestAnimationFrame(function() { app.subscribe('media', renderMediaList); }) } }; App.prototype.navigation = function() { var app = this; var navIndex = app.parts[1] * 1 || 0; if (!hasSiteAccess(app.user.access, 'navigation/' + navIndex)) { app.stage.html('You do not have access to this section'); return false; } // mark content as the highlighted nav section DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.subscribe('navigation', function onchangeContentMenu() { app.contentMenu(false); }); app.stage.html(''); var appHeader = DOM().new('div') .class('caa_content caa_header') .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/content', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Navigation: ' + (app.site.navigation[navIndex].label || 'navigation ' + navIndex))) .insertFirst(app.stage); var content = DOM().new('div').class('caa_content').appendTo(app.stage); DOM().new('div').class('caa_sectionBar').text('Desktop Preview').appendTo(content); var navHolder = DOM().new('div').appendTo(content).css({ 'margin-bottom': '20px' }); DOM().new('div').class('caa_sectionBar').text('Mobile Preview').appendTo(content); var navHolderM = DOM().new('div').appendTo(content).css({ 'margin-bottom': '20px' }); app.subscribe('navigation', function onchangeNavigation() { navHolder.html(''); app.preview('/__nav', navHolder).css({ height: '300px', width: '1280px' }); navHolderM.html(''); var mb_frame = app.preview('/__nav', navHolderM).css({ height: '600px', width: '420px' }); }); }; Page.prototype.renderNavigation = function(app, navIndex, into, useNav) { var thisPage = this; if (!navIndex) { navIndex = 0; } var siteNav = useNav || app.site.navigation[navIndex]; if (!siteNav) { return this; } if (!siteNav.customElement) { delete siteNav.customElementConfig; } if (!siteNav.config) { siteNav.config = {}; } if(!siteNav.styles){ siteNav.styles = {}; } if (!useNav) { var navigationStylesSrc = { ".navigation0": { "box-sizing": "border-box", "top": 0, "width": "100%", "max-width": "", "margin": "", "z-index": 10 }, ".navigation0h": { "max-width": "1280px", "margin": "0 auto", }, ".navigation0h:before": { "content": "''", "display": "inline-block", "vertical-align": "middle", "min-height": "60px" }, ".navigation0ul": { "margin": "0 auto", "padding": 0, "overflow": "hidden", "text-align": "justify" }, ".navigation0ul:before": { "content": "''", "display": "inline-block", "vertical-align": "middle", "min-height": "60px" }, ".navigation0ulli": { "display": "inline-block", "vertical-align": "middle", "list-style-type": "none" }, ".navigation0ullia": { "display": "block", "text-decoration": "none", "padding": "10px" }, ".navigation0ullia:hover": {}, ".navigation0ullia-on": {}, ".navigation0ul-m": { "margin": "0 auto", "overflow": "hidden", "padding": 0 }, ".navigation0ulli-m": { "display": "block", "list-style-type": "none", "max-width": "1280px", "margin": "0 auto" }, ".navigation0ullia-m": { "display": "block", "text-decoration": "none", "padding": "10px" }, ".navigation0ullia:active": { "": "" }, ".navigation0ullia-m-on": {}, ".navigation0-menuiconholder": { "cursor": "pointer", "pointer-events": "fill" }, ".navigation0-menuicon": { "position": "relative", "display": "inline-block", "width": "30px", "height": "20px", "cursor": "pointer" }, ".navigation0-menuicon>span": { "position": "absolute", "transition": "all 0.25s ease-in-out", "transform-origin": "0 0", "-webkit-transition": "all 0.25s ease-in-out", "-webkit-transform-origin": "0 0", "left": "0", "width": "100%", "height": "2px", "border-radius": "2px", "background-color": "#000" }, '.navigation0-menuicon span[data-line="1"]': { "top": "10%" }, '.navigation0-menuicon span[data-line="2"]': { "top": "50%; top: calc(50% - 1px)" }, '.navigation0-menuicon span[data-line="3"]': { "top": "90%; top: calc(90% - 2px)" }, '#navigation0-menuicon:checked ~ span[data-line="1"]': { "transform": "translate(3px,-3px) rotate(45deg)", "-webkit-transform": "translate(3px,-3px) rotate(45deg)" }, '#navigation0-menuicon:checked ~ span[data-line="2"]': { "left": "50%", "width": "0%" }, '#navigation0-menuicon:checked ~ span[data-line="3"]': { "transform": "translate(2px,4px) rotate(-45deg)", "-webkit-transform": "translate(2px,4px) rotate(-45deg)" } }; var navigationStyles = {}; var hadToFix = false; if (siteNav.styles) { var siteNavStyleString = JSON.stringify(siteNav.styles); var siteNavStyleStringOld = siteNavStyleString + ''; for (var k in siteNav.styles) { var key = (k.replace(/\d+/i, '') * 1) + ''; if (key != navIndex && !isNaN(key)) { var repl = new RegExp('navigation' + key, 'g'); siteNavStyleString = siteNavStyleString.replace(repl, 'navigation' + navIndex); hadToFix = true; } } if (hadToFix) { siteNav.styles = JSON.parse(siteNavStyleString) } } for (var k in navigationStylesSrc) { navigationStyles[k.replace(/navigation0/ig, 'navigation' + navIndex)] = navigationStylesSrc[k]; } navigationStyles[k.replace(/navigation0:before/ig, 'navigation' + navIndex + 'h:before')] = navigationStylesSrc[k]; // fixes an old bug with nav if (siteNav.styles['.navigation0:before']) { siteNav.styles['.navigation0:before'] = ''; app.siteUpdate(['navigation', navIndex, 'styles'], siteNav.styles); } if (siteNav.styles['.navigation0']) { if (siteNav.styles['.navigation0']['max-width']) { delete siteNav.styles['.navigation0']['max-width']; delete siteNav.styles['.navigation0'].margin; app.siteUpdate(['navigation', navIndex, 'styles'], siteNav.styles); } } if (siteNav.styles['.navigation' + navIndex + 'ulli-m'] && siteNav.styles['.navigation' + navIndex + 'h'] && siteNav.styles['.navigation' + navIndex + 'ulli-m']['max-width'] != siteNav.styles['.navigation' + navIndex + 'h']['max-width']) { app.siteUpdate(['navigation', navIndex, 'styles', '.navigation' + navIndex + 'ulli-m'], { 'max-width': siteNav.styles['.navigation' + navIndex + 'h']['max-width'] }); } if (!siteNav.styles) { siteNav.styles = {}; } var setNewDefaults = app.objectDefaults(siteNav.styles, navigationStyles); if (hadToFix || setNewDefaults) { app.siteUpdate(['navigation', 'styles'], siteNav.styles, true); console.log('exec replace fix', hadToFix, setNewDefaults, siteNavStyleStringOld, siteNavStyleString); } } this.addClass('page0', 'text1'); if (!siteNav.customElementConfig) { this.addClass('navigation' + navIndex); } var navID = 'navigation' + navIndex, nav = DOM().new('nav').id(navID).class('navigation' + navIndex).attr({ 'data-nav-index': navIndex, 'data-nav-height': siteNav.styles['.navigation' + navIndex + 'h:before']['min-height'] }).appendTo(into), navInside = DOM().new('div').class('navigation' + navIndex + 'h nav-holder').css({ position: 'relative' }).appendTo(nav), hasSubNav = false; if (siteNav.useBlockAbove) { var blockPath = siteNav.useBlockAbove.split('/'), block = app.getFromPath(blockPath); if (block) { thisPage.renderBlock(block, blockPath, 0, 'nav-block-0', nav, nav, false); } navInside.appendTo(nav); // throws this under } if (siteNav.useBlockBelow) { var blockPath = siteNav.useBlockBelow.split('/'), block = app.getFromPath(blockPath); if (block) { thisPage.renderBlock(block, blockPath, 0, 'nav-block-1', nav, nav, false); } } if (siteNav.backgroundMedia) { app.Media(siteNav.backgroundMedia, nav); } app.site.styles.buttons.forEach(function(style, s) { thisPage.addClass('buttons' + s); }); if (siteNav.loadEffect && siteNav.loadEffect !== 'disable') { thisPage.loadEffect = true; thisPage.addClass('block-effects'); thisPage.addClass('block-effects.' + siteNav.loadEffect); nav.addClass('block-effects'); if (siteNav.loadEffectSpeed && siteNav.loadEffectSpeed != 'normal') { nav.addClass(siteNav.loadEffectSpeed); thisPage.addClass('block-effects.' + siteNav.loadEffectSpeed); } if (siteNav.loadEffectDelay && siteNav.loadEffectDelay != 'none') { nav.addClass(siteNav.loadEffectDelay); thisPage.addClass('block-effects.' + siteNav.loadEffectDelay); } nav.attr({ 'data-reveal-effect': siteNav.loadEffect }); } if (siteNav.config.menuPosition) { // matches everything but blank nav.css({ position: 'absolute', left: 0, right: 0 }); if (siteNav.config.menuPosition.indexOf('bottom') > -1) { nav.css({ position: 'fixed', top: 'auto', bottom: 0 }); } } if (!siteNav.logo) { siteNav.logo = { text: {} }; } var logoLink = siteNav.logo.link || '/', logoValign = siteNav.config.logoAlignment || 'middle', logoBox = DOM().new(logoLink ? 'a' : 'div').class('ib ' + logoValign + ' navigation' + navIndex + 'logobox').appendTo(navInside); if (logoLink) { logoBox.attr({ href: logoLink }); } if (siteNav.logo.media) { app.Media(siteNav.logo.media, false).appendTo(logoBox); if (siteNav.logo.media.padding) { logoBox.css({ padding: siteNav.logo.media.padding }); } } if (siteNav.logo.text) { if (siteNav.logo.text.title) { var textPosition = siteNav.logo.text.position || ''; if (textPosition && textPosition != 'hidden') { var ib = ''; if (textPosition !== 'above' && textPosition !== 'under') { ib = 'ib '; } var logotext = DOM().new('div').class(ib + 'middle navigation' + navIndex + 'logotext').text(siteNav.logo.text.title); if (siteNav.logo.text._class) { logotext.addClass(siteNav.logo.text._class); thisPage.addClass(siteNav.logo.text._class); } if (siteNav.logo.text.padding) { logotext.css({ padding: siteNav.logo.text.padding }); } if (textPosition === 'left' || textPosition == 'above') { logotext.insertFirst(logoBox); } else { logotext.appendTo(logoBox); } } } } if (!siteNav.config.subNavIcon) { siteNav.config.subNavIcon = '▼'; } if (!siteNav.config.subNavIconOpen) { siteNav.config.subNavIconOpen = '▲'; } var ulAlignment = siteNav.config.itemAlignment || 'middle'; var ul = DOM().new('ul').class('ib ' + ulAlignment + ' navigation' + navIndex + 'ul').appendTo(navInside); if (siteNav.config.logoPlacement === 'above' || siteNav.config.logoPlacement === 'below') { var alignLogo = '', logoHolder = DOM().new('div').class('navigation' + navIndex + 'logoholder'); logoBox.appendTo(logoHolder); if (siteNav.config.logoPosition === 'right' || siteNav.config.logoPosition === 'center') { alignLogo = siteNav.config.logoPosition; } if (alignLogo) { logoHolder.css({ 'text-align': alignLogo }); } if (siteNav.config.logoPlacement === 'above') { navInside.appendFirst(logoHolder.addClass('ib').css({ 'width': '100%' })); // ib on logo holder helps that ::before vertical alignment of logo } else { logoHolder.appendTo(navInside); } } else { // logo is inline so we have to align it if (siteNav.config.logoPosition === 'right') { logoBox.appendTo(navInside); if (siteNav.styles['.navigation' + navIndex]['text-align'] == 'left') { logoBox.css({ position: 'absolute', top: 0, bottom: 0, right: 0 }).append(DOM().new('span').class('ib ' + logoValign).css({ height: '100%', width: 0 })); } } else if (siteNav.config.logoPosition === 'left') { if (siteNav.styles['.navigation' + navIndex]['text-align'] == 'right') { logoBox.css({ position: 'absolute', top: 0, bottom: 0, left: 0 }).append(DOM().new('span').class('ib ' + logoValign).css({ height: '100%', width: 0 })); } } } var fs = siteNav.config.type || ''; if (siteNav.config.forceMobile) { ul.css({ display: 'none' }); } if (siteNav.items) { var anyHasSubItems = false; siteNav.items.forEach(function(navItem) { if (navItem.items && navItem.items.length) { anyHasSubItems = true; } }); siteNav.items.forEach(function(navItem) { var aClass = 'navigation' + navIndex + 'ullia', useButtonClass = false; if (navItem._title) { if (navItem._title.class) { aClass += ' base-button ' + navItem._title.class; useButtonClass = navItem._title.class + ''; thisPage.addClass(navItem._title.class); thisPage.addClass('base-button'); } } var li = DOM().new('li').class('navigation' + navIndex + 'ulli').appendTo(ul); var a = DOM().new(navItem.link ? 'a' : 'div').class(aClass).appendTo(li); if(!navItem.hideTitle){ a.text(navItem.title || ''); } if (navItem.link) { a.attr({ href: navItem.link, target: navItem.target === '_blank' ? '_blank' : '' }); } if (navItem.target === 'overlay' || navItem.target === 'search') { var navItemID = genUID('nav-item'); a.id(navItemID).attr({ href: '' }); thisPage.configureContentLink(navItem, a, navItemID); } if (useButtonClass) { app.checkAddStylesFor(useButtonClass, a); } if (navItem.media) { var insertFunc = 'insertFirst', mediaDisp = ''; if (navItem.media.position === 'top' || navItem.media.position === 'right') { insertFunc = 'appendTo'; } if (navItem.media.position === 'top' || navItem.media.position === 'bottom') { mediaDisp = 'block'; } app.Media(navItem.media, false).css({ display: mediaDisp })[insertFunc](a); } if (navItem.body) { var bodyClass = ''; if (navItem._body) { if (navItem._body.class) { bodyClass = navItem._body.class; } } if (bodyClass) { thisPage.addClass(bodyClass); a.append(DOM().new('span').css({ display: 'block' }).class(bodyClass).text(navItem.body)); } } if(navItem.style){ li.css(navItem.style); } if (Array.isArray(navItem.items) && navItem.items.length) { hasSubNav = true; var subTextWrapped = DOM().new('span').class('ib middle').text(a.text() || ''); // wraps the link text into a middle aligned span for arrow to be middle too a.text('').append(subTextWrapped); DOM().new('span').class('ib middle navigation' + navIndex + '-subIcon').css({ 'margin-left': '10px' }).html(siteNav.config.subNavIcon).appendTo(a); var subUL = DOM().new('ul').class('navigation' + navIndex + '-subHolder').css({ margin: 0, padding: 0 }).appendTo(li).css({ display: 'none' }); navItem.items.forEach(function(subNavItem) { if (!subNavItem) { return false; } var aClass = 'navigation' + navIndex + 'ullia', useButtonClass = false; if (subNavItem._title) { if (subNavItem._title.class) { aClass += ' base-button ' + subNavItem._title.class; useButtonClass = subNavItem._title.class + ''; thisPage.addClass(subNavItem._title.class); thisPage.addClass('base-button'); } } var li = DOM().new('li').class('navigation' + navIndex + 'ulli').css({ 'text-align': siteNav.config.subNavTextAlignment || '' }).appendTo(subUL); var a = DOM().new(subNavItem.link ? 'a' : 'div').class(aClass).appendTo(li); if(!subNavItem.hideTitle){ a.text(subNavItem.title || ''); } if (subNavItem.link) { a.attr({ href: subNavItem.link, target: subNavItem.target === '_blank' ? '_blank' : '' }); } if (subNavItem.target === 'overlay' || subNavItem.target === 'search') { var navItemID = genUID('nav-item'); a.id(navItemID).attr({ href: '' }); thisPage.configureContentLink(subNavItem, a, navItemID); } if (useButtonClass) { app.checkAddStylesFor(useButtonClass, a); } if (subNavItem.media) { var insertFunc = 'insertFirst', mediaDisp = ''; if (subNavItem.media.position === 'top' || subNavItem.media.position === 'right') { insertFunc = 'appendTo'; } if (subNavItem.media.position === 'top' || subNavItem.media.position === 'bottom') { mediaDisp = 'block'; } app.Media(subNavItem.media, false).css({ display: mediaDisp })[insertFunc](a); } if (subNavItem.body) { var bodyClass = ''; if (subNavItem._body) { if (subNavItem._body.class) { bodyClass = subNavItem._body.class; } } if (bodyClass) { thisPage.addClass(bodyClass); a.append(DOM().new('span').css({ display: 'block' }).class(bodyClass).text(subNavItem.body)); } } if(subNavItem.style){ li.css(subNavItem.style); } }); } else { if (anyHasSubItems && !navItem.media) { // we wrap the item in a span if any of the items have sub nav so that they line up properly var subTextWrapped = DOM().new('span').class('ib middle').text(a.text() || ''); // wraps the link text into a middle aligned span for arrow to be middle too a.text('').append(subTextWrapped); } } }); } var padding = getPaddingMargin(siteNav.styles['.navigation' + navIndex].padding); var menucss = { display: 'none', position: 'absolute', top: '10px' }, menutextcss = { 'margin-right': '15px' }, appendTextFunc = 'insertFirst'; if (siteNav.config.menuLeft) { menucss.left = num(padding.left) ? 0 : '10px'; menutextcss['margin-left'] = '15px'; delete menutextcss['margin-right']; appendTextFunc = 'appendTo'; } else { //menucss.right = padding.right; menucss.right = num(padding.right) ? 0 : '10px'; // we moved the location of the menu icon so it would stay when scrolling and the nav is static, updated to do at least 10px if there is no padding } var MenuIconLabel = DOM().new('label').attr({ for: 'navigation' + navIndex + '-menuicon' }).class('ib navigation' + navIndex + '-menuiconholder').html('
'); var MenuIcon = DOM().new('div').id(navID + '-menu').css(menucss).append(MenuIconLabel).appendTo(navInside); if (siteNav.menuIconText || siteNav.menuIconCloseText) { DOM().new('span').class('ib middle navigation' + navIndex + '-menuicontext').css(menutextcss).text(siteNav.menuIconText || '')[appendTextFunc](MenuIconLabel); } var config = { id: navID, navIndex: navIndex, pad: (num(padding.top) + num(padding.bottom)), type: siteNav.config.type || '', height: num(siteNav.styles['.navigation' + navIndex + 'h:before']['min-height']) || 60, forceMobile: siteNav.config.forceMobile || false, openMenuIconColor: siteNav.config.openMenuIconColor || '', closedMenuIconColor: siteNav.styles['.navigation' + navIndex + '-menuicon>span']['background-color'], textColorMobile: siteNav.styles['.navigation' + navIndex + 'ullia-m'].color || '', textColor: siteNav.styles['.navigation' + navIndex + 'ullia'].color || '', menuIconText: siteNav.menuIconText || '', menuIconCloseText: siteNav.menuIconCloseText || '', logoStacked: (siteNav.config.logoPlacement === 'above' || siteNav.config.logoPlacement === 'below') }; if (siteNav.config.menuPosition) { nav.attr({ 'data-type': siteNav.config.menuPosition }); if (siteNav.config.menuPosition.indexOf('sticky') > -1) { if (siteNav.config.menuPosition.indexOf('bottom') > -1) { config.bottom = true; } config.fixed = siteNav.config.menuPosition; if (siteNav.config.scrolledBackgroundColor) { config.scrolledBackgroundColor = siteNav.config.scrolledBackgroundColor; } if (siteNav.config.scrolledPadding) { config.scrolledPadding = siteNav.config.scrolledPadding; } } else { config.fixed = false; } } if (siteNav.customElement) { var customNav = app.Media({ media: siteNav.customElement, config: config }); if (siteNav.customElementConfig === 'replace') { nav.html(customNav.html()); } else { nav.html(nav.html() + customNav.html()); } } if (siteNav.items && siteNav.items.length && !siteNav.customElementConfig) { thisPage.onloadFunctions.push({ config: config, exec: function(config) { if (!window.caExecRefs) { window.caExecRefs = {}; } caExecRefs['menu-' + config.navID + '.menu'] = DOM().id(config.id).responsiveMenu(config); if (config.forceMobile) { caExecRefs['menu-' + config.navID + '.menu'].goMobile(); } } }); if (hasSubNav) { var subNavConfig = { id: navID + 'sub', navID: navID, navIndex: navIndex, menuPosition: siteNav.config.menuPosition || '', subNavDisplay: siteNav.config.subNavDisplay, subNavIcon: siteNav.config.subNavIcon, subNavIconOpen: siteNav.config.subNavIconOpen }; thisPage.onloadFunctions.push({ config: subNavConfig, exec: function(config) { caExecRefs['menu-' + config.navID + '.submenu'] = DOM().id(config.navID).responsiveSubMenu(config); } }); } app.onResize(function(e) { if (!e) { // stage resize if (window.caExecRefs) { for (var k in caExecRefs) { if (k.match(/\.menu/)) { caExecRefs[k].checkYoSelf(); } } } } }); } }; Page.prototype.renderNavigation2 = function(app, navIndex, into) { var thisPage = this; if (!navIndex) { navIndex = 0; } var siteNav = app.site.navigation[navIndex]; if (!siteNav) { return this; } if (!siteNav.customElement) { delete siteNav.customElementConfig; } if (!siteNav.config) { siteNav.config = {}; } if (!siteNav.styles) { siteNav.styles = {}; } // only for reset/testing //siteNav.styles = {}; var navigationStylesSrc = { ".navigation0": { position: "relative", "box-sizing": "border-box", "width": "100%", "z-index": 10 }, ".navigation0h": { 'max-width': '1280px', margin: '0 auto', }, ".navigation0 ul": { "list-style": "none", "margin": 0, "padding-left": 0 }, ".navigation0ulli": { "max-width": "100%", "display": "inline-block", "white-space": "normal", "vertical-align": "middle", "list-style-type": "none" }, ".navigation0ullia": { "display": "block", "text-decoration": "none", "padding": "10px", }, ".navigation0ulli-m": { "display": "block", "white-space": "normal", "list-style-type": "none" }, ".navigation0ullia-m": { "display": "block", "text-decoration": "none", "padding": "10px", }, ".navigation0ullia-m-on": { }, ".navigation0ullia:hover": {}, ".navigation0ullia-on": {}, ".navigation0ul-m": { position: 'fixed', overflow: 'hidden', padding: 0, 'z-index': 10, top: 0, margin: 0, bottom: 0, left: 0, display: '', 'overflow-y': 'auto', width: '100%' }, ".navigation0ullia:active": { "": "" }, ".navigation0-menu": { "@800@display": "inline-block", display: "none", position: 'absolute', 'z-index': 11, top: "50%", "margin-top": "-10px" }, ".navigation0-menuiconholder": { "cursor": "pointer", "pointer-events": "fill" }, ".navigation0-menuicon": { "position": "relative", "display": "inline-block", "width": "30px", "height": "20px", "cursor": "pointer" }, ".navigation0-menuicon>span": { "position": "absolute", "transition": "all 0.25s ease-in-out", "transform-origin": "0 0", "-webkit-transition": "all 0.25s ease-in-out", "-webkit-transform-origin": "0 0", "left": "0", "width": "100%", "height": "2px", "border-radius": "2px", "background-color": "#000" }, '.navigation0-menuicon span[data-line="1"]': { "top": "10%" }, '.navigation0-menuicon span[data-line="2"]': { "top": "50%; top: calc(50% - 1px)" }, '.navigation0-menuicon span[data-line="3"]': { "top": "90%; top: calc(90% - 2px)" }, '#navigation0-menuicon:checked ~ .navigation0-menu span[data-line="1"]': { "transform": "translate(3px,-3px) rotate(45deg)", "-webkit-transform": "translate(3px,-3px) rotate(45deg)" }, '#navigation0-menuicon:checked ~ .navigation0-menu span[data-line="2"]': { "left": "50%", "width": "0%" }, '#navigation0-menuicon:checked ~ .navigation0-menu span[data-line="3"]': { "transform": "translate(2px,4px) rotate(-45deg)", "-webkit-transform": "translate(2px,4px) rotate(-45deg)" }, ".navigation0row": { "display": "flex", 'white-space': 'nowrap', '@800@white-space': 'normal' }, ".navigation0section": { flex: 1, "align-self": "center", "justify-content": "center", "max-width": "100%", "vertical-align": siteNav.config.itemAlignment || "middle" }, ".navigation0center": { flex: "1 1 auto", "align-self": "center", "text-align": "center", "@800@text-align": "left" }, '.navigation0left': { "margin-right": "auto", "text-align": "left" }, '.navigation0right': { "margin-left": "auto", "text-align": "right", '@800@text-align': 'left' }, '.navigation0h-d': { 'z-index': 10, position: "relative", 'box-sizing': 'border-box', '@800@display': 'none', "@800@position": '', "@800@width": '100%', "@800@left": 0, "@800@top": 0, "@800@bottom": 0, "@800@overflow": 'auto' }, '.navigation0h-m': { transition: "opacity 0.25s ease-in-out", position: "relative", 'display': 'none', "@800@display": "block" }, '.navigation0m-items': { 'text-align': 'left' }, '#navigation0-menuicon:checked ~ .navigation0h-d': { 'display': 'block', }, '#navigation0-menuicon:checked ~ .navigation0h-m': { opacity: 0 }, '#navigation0-menuicon:checked ~ .navigation0h-d .navigation0row': { display: "block" }, '#navigation0-menuicon:checked ~ .navigation0h-d .navigation0section': { flex: 'none', display: 'block' }, '#navigation0-menuicon:checked ~ .navigation0h-d .navigation0ulli': { display: 'block' }, '#navigation0-menuicon:checked ~ .navigation0h-d': { display: "block", 'min-height': '100vh' }, '#navigation0-menuicon:checked ~ .navigation0-menuicon>span': { } }; var navigationStyles = {}; for (var k in navigationStylesSrc) { navigationStyles[k.replace(/navigation0/ig, 'navigation' + navIndex)] = navigationStylesSrc[k]; } app.objectDefaults(siteNav.styles, navigationStyles); siteNav.styles['.navigation'+navIndex+'h-d']['@800@transform'] = 'translate3d(0,-100%,0)'; // these reset the styles in case transform or opacity is not used siteNav.styles['.navigation'+navIndex+'h-d']['@800@transform-origin'] = ''; // these reset the styles in case transform or opacity is not used siteNav.styles['.navigation'+navIndex+'h-d']['@800@opacity'] = ''; siteNav.styles['.navigation'+navIndex+'h-d']['@800@transition'] = 'transform 0.25s ease-in-out, opacity 0.25s ease-in-out'; siteNav.styles['#navigation'+navIndex+'-menuicon:checked ~ .navigation'+navIndex+'h-d']['@800@transform'] = ''; if(siteNav.config.type === 'zoom'){ siteNav.styles['.navigation'+navIndex+'h-d']['@800@transform'] = 'scale(0)'; siteNav.styles['.navigation'+navIndex+'h-d']['@800@transform-origin'] = '50% 50%'; siteNav.styles['#navigation'+navIndex+'-menuicon:checked ~ .navigation'+navIndex+'h-d']['@800@transform'] = 'scale(1)'; } else if(siteNav.config.type === 'fade'){ siteNav.styles['.navigation'+navIndex+'h-d']['@800@transform'] = 'translate3d(0,0,0)'; siteNav.styles['.navigation'+navIndex+'h-d']['@800@opacity'] = '0'; siteNav.styles['#navigation'+navIndex+'-menuicon:checked ~ .navigation'+navIndex+'h-d']['@800@opacity'] = '1'; } else if(siteNav.config.type === 'slide-side'){ var xf = siteNav.config.menuButtonPosition === 'left' ? '-100%' : '100%' siteNav.styles['.navigation'+navIndex+'h-d']['@800@transform'] = 'translate3d('+xf+',0,0)'; siteNav.styles['#navigation'+navIndex+'-menuicon:checked ~ .navigation'+navIndex+'h-d']['@800@transform'] = 'translate3d(0,0,0)'; } else { siteNav.styles['#navigation'+navIndex+'-menuicon:checked ~ .navigation'+navIndex+'h-d']['@800@transform'] = 'translate3d(0, 0%, 0)'; } var mobileWidth = num(siteNav.config.mobileWidth) || 800; for (var k in siteNav.styles) { for (var prop in siteNav.styles[k]) { if (prop.indexOf('@') === 0) { var newprop = '@' + mobileWidth + '@' + (prop.split('@')[2] || '') if (newprop != prop) { siteNav.styles[k][newprop] = siteNav.styles[k][prop]; delete siteNav.styles[k][prop]; } } } } this.addClass('page0', 'text1'); if (!siteNav.customElementConfig) { this.addClass('navigation' + navIndex); } var navID = 'navigation' + navIndex, nav = DOM().new('nav').id(navID).class('navigation' + navIndex).attr({ 'data-nav-index': navIndex }).appendTo(into), desktopNav = DOM().new('div').class('navigation' + navIndex + 'h navigation' + navIndex + 'h-d nav-holder').appendTo(nav), mobileNav = DOM().new('div').class('navigation' + navIndex + 'h navigation' + navIndex + 'h-m nav-holder').appendTo(nav), mobileNavItems = DOM().new('ul').class('navigation' + navIndex + 'm-items').appendTo(mobileNav), hasSubNav = false; if(siteNav.config.minHeight){ nav.css({'min-height': siteNav.config.minHeight}) } if (siteNav.backgroundMedia) { app.Media(siteNav.backgroundMedia, nav); } app.site.styles.buttons.forEach(function(style, s) { thisPage.addClass('buttons' + s); }); if (siteNav.useBlockAbove) { var blockPath = siteNav.useBlockAbove.split('/'), block = app.getFromPath(blockPath); if (block) { thisPage.renderBlock(block, blockPath, 0, 'nav-block-0', nav, nav, false); nav.find('#nav-block-0').insertFirst(nav); } } if (siteNav.useBlockBelow) { var blockPath = siteNav.useBlockBelow.split('/'), block = app.getFromPath(blockPath); if (block) { thisPage.renderBlock(block, blockPath, 0, 'nav-block-1', nav, nav, false); } } if (siteNav.loadEffect && siteNav.loadEffect !== 'disable') { thisPage.loadEffect = true; thisPage.addClass('block-effects'); thisPage.addClass('block-effects.' + siteNav.loadEffect); nav.addClass('block-effects'); if (siteNav.loadEffectSpeed && siteNav.loadEffectSpeed != 'normal') { nav.addClass(siteNav.loadEffectSpeed); thisPage.addClass('block-effects.' + siteNav.loadEffectSpeed); } if (siteNav.loadEffectDelay && siteNav.loadEffectDelay != 'none') { nav.addClass(siteNav.loadEffectDelay); thisPage.addClass('block-effects.' + siteNav.loadEffectDelay); } nav.attr({ 'data-reveal-effect': siteNav.loadEffect }); } if (siteNav.config.menuPosition) { // matches everything but blank nav.css({ position: 'absolute', left: 0, top: 0, right: 0 }); if (siteNav.config.menuPosition.indexOf('bottom') > -1) { nav.css({ position: siteNav.config.stickyScrollOffset > 1 ? 'absolute' : 'fixed', top: 'auto', bottom: 0 }); } } if (!siteNav.config.subNavIcon) { siteNav.config.subNavIcon = '▼'; } if (!siteNav.config.subNavIconOpen) { siteNav.config.subNavIconOpen = '▲'; } if (siteNav.items) { var inPosition = {}; siteNav.items.sort(function(a, b) { return (a.navPosition || 5) - (b.navPosition || 5); }).forEach(function(navItem) { inPosition[navItem.navPosition || 5] = true; }); var navGrid = {}, navRow = {}; for (var b = 1; b < 10; b++) { if (inPosition[b]|| true) { // tmp fix to get all rows in for centering var row = b < 4 ? 1 : 2; if (b > 6) { row = 3; } if (!navRow[row]) { navRow[row] = DOM().new('div').class('navigation' + navIndex + 'row').appendTo(desktopNav); } var side = 'center'; if (b === 1 || b === 4 || b === 7) { side = 'left' } if (b === 3 || b === 6 || b === 9) { side = 'right' } navGrid[b] = DOM().new('ul').class('ibb navigation' + navIndex + 'section navigation' + navIndex + side).appendTo(navRow[row]); } } siteNav.items.forEach(function(navItem) { if (!navItem.title) { navItem.title = navItem.text || ''; } // switched from .text to .title to be consistent var aClass = 'navigation' + navIndex + 'ullia', useButtonClass = false; if (navItem._title) { if (navItem._title.class) { aClass += ' base-button ' + navItem._title.class; useButtonClass = navItem._title.class + ''; thisPage.addClass(navItem._title.class); thisPage.addClass('base-button'); } } var li = DOM().new('li').class('navigation' + navIndex + 'ulli').appendTo(navGrid[(navItem.navPosition || 5)]); var a = DOM().new(navItem.link ? 'a' : 'div').class(aClass).appendTo(li); if (!navItem.hideTitle) { a.text(navItem.title || ''); } if (navItem.link) { a.attr({ href: navItem.link, target: navItem.target === '_blank' ? '_blank' : '' }); } if (navItem.target === 'overlay' || navItem.target === 'search') { var navItemID = genUID('nav-item'); a.id(navItemID).attr({ href: '' }); thisPage.configureContentLink(navItem, a, navItemID); } if (useButtonClass) { app.checkAddStylesFor(useButtonClass, a); } if (navItem.media) { var insertFunc = 'insertFirst', mediaDisp = ''; if (navItem.media.position === 'top' || navItem.media.position === 'right') { insertFunc = 'appendTo'; } if (navItem.media.position === 'top' || navItem.media.position === 'bottom') { mediaDisp = 'block'; } app.Media(navItem.media, false).css({ display: mediaDisp })[insertFunc](a); } if (navItem.body) { var bodyClass = ''; if (navItem._body) { if (navItem._body.class) { bodyClass = navItem._body.class; } } if (bodyClass) { thisPage.addClass(bodyClass); a.append(DOM().new('span').css({ display: 'block' }).class(bodyClass).text(navItem.body)); } } if(navItem.style){ a.css({padding: navItem.style.padding}); li.css(navItem.style).css({padding: ''}); } if (navItem.showOnMobile) { li.clone(true).appendTo(mobileNavItems); } if (Array.isArray(navItem.items)) { if (navItem.items.length) { hasSubNav = true; var subTextWrapped = DOM().new('span').class('ib middle').text(a.text() || ''); // wraps the link text into a middle aligned span for arrow to be middle too a.text('').append(subTextWrapped); DOM().new('span').class('ib middle navigation' + navIndex + '-subIcon').css({ 'margin-left': '10px' }).html(siteNav.config.subNavIcon).appendTo(a); var subUL = DOM().new('ul').class('navigation' + navIndex + '-subHolder').css({ margin: 0, padding: 0 }).appendTo(li).css({ display: 'none' }); navItem.items.forEach(function(subNavItem) { if (!subNavItem) { return false; } var aClass = 'navigation' + navIndex + 'ullia', useButtonClass = false; if (subNavItem._title) { if (subNavItem._title.class) { aClass += ' base-button ' + subNavItem._title.class; useButtonClass = subNavItem._title.class + ''; thisPage.addClass(subNavItem._title.class); thisPage.addClass('base-button'); } } var li = DOM().new('li').class('navigation' + navIndex + 'ulli').appendTo(subUL); var a = DOM().new(subNavItem.link ? 'a' : 'div').class(aClass).appendTo(li); if (!subNavItem.hideTitle) { a.text(subNavItem.title || ''); } if (subNavItem.link) { a.attr({ href: subNavItem.link, target: subNavItem.target === '_blank' ? '_blank' : '' }); } if (subNavItem.target === 'overlay' || subNavItem.target === 'search') { var navItemID = genUID('nav-item'); a.id(navItemID).attr({ href: '' }); thisPage.configureContentLink(subNavItem, a, navItemID); } if (useButtonClass) { app.checkAddStylesFor(useButtonClass, a); } if (subNavItem.media) { var insertFunc = 'insertFirst', mediaDisp = ''; if (subNavItem.media.position === 'top' || subNavItem.media.position === 'right') { insertFunc = 'appendTo'; } if (subNavItem.media.position === 'top' || subNavItem.media.position === 'bottom') { mediaDisp = 'block'; } app.Media(subNavItem.media, false).css({ display: mediaDisp })[insertFunc](a); } if (subNavItem.body) { var bodyClass = ''; if (subNavItem._body) { if (subNavItem._body.class) { bodyClass = subNavItem._body.class; } } if (bodyClass) { thisPage.addClass(bodyClass); a.append(DOM().new('span').css({ display: 'block' }).class(bodyClass).text(subNavItem.body)); } } if(subNavItem.style){ a.css({padding: subNavItem.style.padding}); li.css(subNavItem.style).css({padding: ''}); } }); } } }); } for(var r=1; r<4;r++){ if(!navRow[r].byTag('li').exists()){ navRow[r].remove(); } } var padding = getPaddingMargin(siteNav.styles['.navigation' + navIndex].padding), paddingAlt = getPaddingMargin(siteNav.styles['.navigation' + navIndex + 'ullia-m'].padding), navPad = num(padding.top) + num(padding.bottom); var menucss = {}, menutextcss = { 'margin-right': '15px' }, appendTextFunc = 'insertFirst'; if (siteNav.config.menuButtonPosition === 'left') { menucss.left = (num(padding.left) || num(paddingAlt.left) || 0) + 'px'; menutextcss['margin-left'] = '15px'; delete menutextcss['margin-right']; appendTextFunc = 'appendTo'; } else { menucss.right = (num(padding.right) || num(paddingAlt.right) || 0) + 'px'; if(!num(menucss.right)){ menucss.right = '10px'; } } var MenuIconLabel = DOM().new('label').attr({ for: 'navigation' + navIndex + '-menuicon' }).class('ib navigation' + navIndex + '-menuiconholder').html('
'); var MenuIcon = DOM().new('div').id(navID + '-menu').class('navigation' + navIndex + '-menu').css(menucss).append(MenuIconLabel); if (siteNav.menuIconText || siteNav.menuIconCloseText) { DOM().new('span').class('ib middle navigation' + navIndex + '-menuicontext').css(menutextcss).text(siteNav.menuIconText || '')[appendTextFunc](MenuIconLabel); } MenuIcon.css({ display: '', position: '' }).insertFirst(nav); MenuIconLabel.byTag('input').insertFirst(nav); if (siteNav.config.menuButtonPosition === 'left') { //throw menu icon into dom for calc it's size var ref = MenuIcon.clone(true).css({ display: 'inline-block', position: 'absolute' }).appendTo(DOM().id('caa_body')); var pos = MenuIcon.pos(); mobileNavItems.css({ 'padding-left': 30 + pos.width + 'px' }); siteNav.styles['.navigation'+navIndex+'h-d']['@800@padding-top'] = (pos.height || 50) + 'px'; ref.remove(); } var config = { id: navID, navIndex: navIndex, menuside: siteNav.config.menuButtonPosition || 'right', type: siteNav.config.type || '', mobileWidth: mobileWidth, maxWidth: num(siteNav.styles['.navigation' + navIndex + 'h']['max-width']) || 1280, menuIconOffset: num(siteNav.styles['.navigation' + navIndex + 'h']['max-width']) || 1280, openMenuIconColor: siteNav.config.openMenuIconColor || '', menuIconText: siteNav.menuIconText || '', menuIconCloseText: siteNav.menuIconCloseText || '' }; if(siteNav.config.stickyScrollOffset){ config.stickyScrollOffset = num(siteNav.config.stickyScrollOffset); } if (siteNav.config.menuPosition) { nav.attr({ 'data-type': siteNav.config.menuPosition }); if (siteNav.config.menuPosition.indexOf('sticky') > -1) { if (siteNav.config.menuPosition.indexOf('bottom') > -1) { config.bottom = true; } config.fixed = siteNav.config.menuPosition; if (siteNav.config.scrolledBackgroundColor) { config.scrolledBackgroundColor = siteNav.config.scrolledBackgroundColor; } if (siteNav.config.scrolledPadding) { config.scrolledPadding = siteNav.config.scrolledPadding; } } else { config.fixed = false; } } if (siteNav.customElement) { var customNav = app.Media({ media: siteNav.customElement, config: config }); if (siteNav.customElementConfig === 'replace') { nav.html(customNav.html()); } else { nav.html(nav.html() + customNav.html()); } } if (!siteNav.customElementConfig) { thisPage.onloadFunctions.push({ config: config, exec: function(config) { if (!window.caExecRefs) { window.caExecRefs = {}; } caExecRefs['menu-' + config.id + '.menu'] = DOM().id(config.id).responsiveMenu2(config); } }); if (hasSubNav) { var subNavConfig = { id: navID + 'sub', navID: navID, navIndex: navIndex, subNavDisplay: siteNav.config.subNavDisplay, subNavIcon: siteNav.config.subNavIcon, subNavIconOpen: siteNav.config.subNavIconOpen }; thisPage.onloadFunctions.push({ config: { ref: 'menu-' + config.id + '.menu' }, exec: function(config) { caExecRefs[config.ref].responsiveSubMenu2(); } }); } } }; App.prototype.newSite = function() { var app = this; app.stage.html(''); var appHeading = DOM().new('div') .class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text('Create New Site')) .appendTo(app.stage), NewSiteConfig = { name: app.user.email.split('@')[0] + '\'s Site', fromSite: false }, siteList = [{ id: '_default', name: 'Blank/Default Site' }]; DOM().new('div').class('caa_sectionBar').text('Site Information').appendTo(app.stage); var siteSec = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage); Inputs.text({ label: 'Site Name', value: NewSiteConfig.name }).appendTo(siteSec).byTag('input').on('change', function(e) { NewSiteConfig.name = DOM(e.target).val(); }); DOM().new('div').class('caa_sectionBar').text('Create Site From').appendTo(app.stage); siteSec = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage); var siteListSortedHolder = DOM().new('div').class('caa_grid').css({ margin: '-4px' }).appendTo(siteSec), renderSitesList = function() { siteListSortedHolder.html(''); siteList.concat(app.sites || []).forEach(function(site, i) { if (site.id && site.name !== undefined) { var addClass = ''; if (!NewSiteConfig.fromSite && i === 0 || site.id === NewSiteConfig.fromSite) { addClass = ' caa_clickSecFill'; } var row = DOM().new('div').class('caa_griditem caa_click caa_clickSecTarget' + addClass) .css({ padding: '4px', position: 'relative' }).append( DOM().new('img').class('middle').attr({ src: site.favicon || '' }).css({ 'width': '30px', height: '30px', 'padding-right': '10px' }) ).append( DOM().new('div').class('ib middle caa_navItemText ellipsis').css({ 'max-width': '210px' }).text(site.name) ).appendTo(siteListSortedHolder).on('click', function(e) { siteListSortedHolder.byClass('caa_griditem').removeClass('caa_clickSecFill'); row.addClass('caa_clickSecFill'); NewSiteConfig.fromSite = site.id; showSiteCustomization(site); }); } }); resize(); }, showSiteCustomization = function(site) { /* if (site.id && site.id !== '_default') { customizeSiteHeader.css({ display: '' }); customizeSiteHeaderSec.css({ display: '' }).html(''); Inputs.checkbox({ value: NewSiteConfig.referenceMedia, label: 'Reference Media Instead of Duplicate', onchange: function(checked) { if (checked) { } else { } showPageTitleSection(); } }).css({ 'margin-top': '20px' }).appendTo(left); } else { */ customizeSiteHeader.css({ display: 'none' }); customizeSiteHeaderSec.css({ display: 'none' }).html(''); //} }; var customizeSiteHeader = DOM().new('div').class('caa_sectionBar').text('What To Keep').appendTo(app.stage).css({ display: 'none' }), customizeSiteHeaderSec = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage).css({ display: 'none' }); var resize = function(e) { siteListSortedHolder.css({ 'margin-top': '10px' }).masonry({ childrenSelector: '.caa_griditem', spacing: 6, edges: false, columns: 5 }); }; app.onResize(resize); app.listeners.getSites = function() { renderSitesList(); }; renderSitesList(); siteSec = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage); DOM().new('button').class('caa_button-default').css({ 'margin-top': '10px' }).appendTo(siteSec).text('Create New Site').on('click', function(e) { app.send({ do: 'createNewSite', config: NewSiteConfig }); }); DOM().new('button').class('caa_button-default').css({ 'margin': '10px 0 0 10px' }).appendTo(siteSec).text('Cancel').on('click', function(e) { app.siteListContainer.expanded = true; app.siteListToggler(); app.render('/hub', false, false); }); app.listeners.newSite = function(data){ app.switchSite(data); app.siteListContainer.expanded = true; app.siteListToggler(); app.render('/content/pages/0/home-page-title', false, true); }; }; App.prototype.profile = function() { var app = this; app.stage.html(''); var appHeading = DOM().new('div') .class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text('Profile')) .appendTo(app.stage); DOM().new('div').class('caa_sectionBar').text('Profile').appendTo(app.stage); var imageURL = ''; if (app.user.image) { imageURL = 'url(' + app.user.image + ')'; } var content = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage), messages = DOM().new('div').appendTo(content), profileObject = DOM().new('div').class('caa_profile caa_profileLarge').css({ 'background-image': imageURL || ca_config.def_profile }), uploadImage = DOM().new('input').attr({ type: 'file', accept: 'image/*' }).css({ opacity: 0.0001, position: 'absolute', left: 0, top: 0, right: 0, bottom: 0, width: '200px', height: '200px' }).on('change', function(e) { if (e.target) { if (e.target.files) { var file = e.target.files[0], reader = new FileReader(), box = DOM().new('canvas').id('preview-canvas-profile').css({ position: 'absolute', left: 0, opacity: 0.00001, 'pointer-events': 'none' }).appendTo(profileObject), canvas = byID('preview-canvas-profile'), ctx = canvas.getContext('2d'), scale, typeFirst = (file.type || '').split('/')[0] || ''; reader.onload = function(readerEvent) { var img = new Image(), imageContent; img.onload = function() { scale = img.width > img.height ? 128 / img.width : 128 / img.height; console.log('image w', img.width, 'img h', img.height, 'scale', scale); canvas.width = img.width * scale; canvas.height = img.height * scale; ctx.drawImage(img, 0, 0, canvas.width, canvas.height); imageContent = canvas.toDataURL('png'); DOM().id('update-user-image').val(imageContent); profileObject.css({ 'background-image': 'url(\'' + imageContent + '\')' }); }; img.src = readerEvent.target.result; }; reader.readAsDataURL(file); } } }), profilePicture = DOM().new('div').append( DOM().new('div').class('ib middle caa_clickSecTarget') .css({ position: 'relative', overflow: 'hidden' }) .append( uploadImage ) .append( profileObject )); app.listeners.profile = function(data) { messages.text(data.success || data.error || ''); if(data.user){ for(var k in data.user){ app.user[k] = data.user[k]; } app.setUser(); } if (data.image) { profileObject.css({ 'background-image': 'url(\'' + data.image + '\')' }); } }; var pwb = Inputs.text({ label: 'New Password', type: 'password' }), pwi = pwb.byTag('input'), unb = Inputs.text({ label: 'Name', value: app.user.name || '' }), unc = Inputs.text({ label: 'Company', value: app.user.company || '' }), uni = unb.byTag('input'), unci = unc.byTag('input'); DOM().new('div').css({ padding: '10px 0' }).text(app.user.email).appendTo(content); DOM().new('form').on('submit', function(e) { e.preventDefault(); var message = { do: 'profile', profile: { pw: pwi.val() || '', name: uni.val() || '', company: unci.val() || '', image: DOM().id('update-user-image').val() || '', } }; app.send(message); }).css({'max-width': '300px'}) .append(profilePicture) .append(DOM().new('input').id('update-user-image').attr({ type: 'hidden' })) .append(pwb.css({ 'margin-top': '20px' })) .append(unb.css({ 'margin-top': '20px' })) .append(unc.css({ 'margin-top': '20px' })) .append(DOM().new('input').class('caa_button-default').attr({ type: 'submit', value: 'Update Profile' }).css({ 'margin-top': '20px' })).appendTo(content); /* DOM().new('div').class('caa_sectionBar').text('API TOKENS').css({ 'margin-top': '20px' }).appendTo(app.stage); var tokens = DOM().new('div').class('caa_content caa_padding').appendTo(app.stage); app.listeners.apiTokens = function(data) { tokens.html(''); if (data.error) { tokens.text(data.error); } else { DOM().new('div').css({'margin-bototm':'10px'}).text('id: '+data.id).appendTo(tokens); Object.keys(data.tokens).forEach(function(token) { var row = DOM().new('div').class('caa_row caa_row_hover').appendTo(tokens).css({ 'margin-bottom': '10px' }) .append(DOM().new('span').class('ib middle').text(token)) .append( UI.deleteButton('Delete', 'button', function(e) { app.send({ do: 'apiTokens', deleteToken: token }); }).css({ position: 'absolute', top: '4px', right: 0 }) ); }); DOM().new('button').class('caa_button-default').text('Generate New Token').on('click', function(e) { DOM(e.target).attr({disabled:true}); app.send({ do: 'apiTokens', newToken: 'hello' }); }).appendTo(tokens); } }; app.send({ do: 'apiTokens' }); */ }; App.prototype.publish = function(into, type) { var app = this; clearInterval(app.publishButtons); delete app.publishButtons; var buttons = DOM().new('div').class('ibb middle').appendTo(into), links = DOM().new('div').class('ibb middle').appendTo(into); var but_publish = DOM().new('button').text('Publish To Staging').class('caa_publish_options caa_button-default').css({ width: '220px' }).on('click', function(e) { app.publishSite(undefined, function(e) { }); into.byTag('button').attr({ disabled: true }); }).css({ margin: '0 16px 16px 0' }).appendTo(buttons); var but_golive = DOM().new('button') .text('Publish Staging to Live').class('caa_publish_options caa_button-default').css({ width: '220px' }).on('click', function(e) { app.goLive(app.publishProgress); into.byTag('button').attr({ disabled: true }); }).css({ margin: '0 16px 16px 0' }).appendTo(buttons); var but_pubgolive = DOM().new('button').text('Publish To Staging & Live').class('caa_publish_options caa_button-default').css({ width: '220px' }).on('click', function(e) { app.publishSite(undefined, function() { app.goLive(app.publishProgress); }); into.byTag('button').attr({ disabled: true }); }).css({ margin: '0 16px 16px 0' }).appendTo(buttons); DOM().new('a').class('ibb middle').css({ margin: '0 16px 16px 0' }).attr({ href: app.stagingURL(), target: '_blank' }) .append(DOM().new('span').class('ib middle').text('View Staging Site')) .append(UI.Icon('popout', 'menu2').css({ 'margin-left': '4px' })) .appendTo(links); DOM().new('a').class('ibb middle').css({ margin: '0 16px 16px 0' }).attr({ href: app.siteURL(), target: '_blank' }) .append(DOM().new('span').class('ib middle').text('View Live Site')) .append(UI.Icon('popout', 'menu2').css({ 'margin-left': '4px' })) .appendTo(links); DOM().new('a').class('ibb middle').css({ margin: '0 16px 16px 0' }).attr({ href: 'https://www.blux.com/support/publishing', target: '_blank' }) .append(DOM().new('span').class('ib middle').text('About Publishing')) .append(UI.Icon('rocket', 'menu2').css({ 'margin-left': '4px' })) .appendTo(links); DOM().new('a').class('ibb middle').css({ margin: '0 16px 16px 0' }).attr({ href: '#' }) .on('click', function(e) { app.notifyReviewersModal(e); }) .append(DOM().new('span').class('ib middle').text('Notify Reviewers')) .append(UI.Icon('email', 'menu2').css({ 'margin-left': '4px' })) .appendTo(links); DOM().new('div').id('stagingStatusText').appendTo(into); app.publishButtons = function() { if (document.contains(but_publish.elements[0])) { if (app.publishQueueStatus && !app.publishQueueStatus.complete) { DOM().byClass('caa_publish_options').attr({ disabled: true }); } else { DOM().byClass('caa_publish_options').attr({ disabled: false }); } } else { clearInterval(app.publishButtons); delete app.publishButtons; } }; setInterval(app.publishButtons, 100); }; App.prototype.publishSite = function(urlList, publishCallback) { var app = this; loadScript('https://cdn.blux.com/scripts/uglifyjs-2.7.3.js', function() { loadScript('https://cdn.blux.com/scripts/clean-css-3.4.19.js', function() { app.checkBilling(function(billingOK) { if (billingOK) { app.publishSiteReal(urlList, publishCallback); } else { app.showPublishProgress('init') var publishStatus = DOM().new('div').class('caa_padding').appendTo(app.publishProgress).css({ 'background-color': '#e7e7e7', 'padding-bottom': '60px', height: '100%', 'max-height': '200px', 'overflow-y': 'auto' }); DOM().new('div').text('This site may not be published until it has a valid Blux subscription.').css({ 'margin-bottom': '20px' }).appendTo(publishStatus); if (app.site.owner === app.user.id) { DOM().new('button').class('caa_button-default').text('Manage Billing').on('click', function(e) { app.render('/billing/' + app.site.id, false, false); }).appendTo(publishStatus); } else { DOM().new('div').text('Contact the site owner to update this site\'s billing preferences so you may publish this site').appendTo(publishStatus); } app.showPublishProgress('dismissable'); return this; } }) }); }); }; App.prototype.showPublishProgress = function(state) { var app = this; app.publishProgress = DOM().newOrFind('div', 'publishProgress').class('caa_content').css({ position: 'fixed', bottom: '-1px', left: 0, right: 0, margin: '0 auto', 'z-index': 102, background: '#fff', 'border': '1px solid #d4d4d4' }).appendTo(app.domBody); app.publishProgress.state = state; if (state === 'init') { app.publishProgress.html(''); } else if (state === 'dismissable') { app.publishProgress.deleteButton = DOM().new('button').class('caa_button-delete').appendTo(app.publishProgress).css({ position: 'absolute', right: 0, top: 0, 'z-index': 102 }).on('click', function(e) { app.publishProgress.remove(); delete app.publishProgress; delete app.publishQueueStatus; }); } }; App.prototype.publishSiteReal = function(urlList, publishCallback) { var app = this, partial = false, doFeeds = []; if (app.publishQueueStatus && !app.publishQueueStatus.complete) { return false; } if (!Array.isArray(urlList)) { urlList = []; } if (urlList.length > 0) { partial = true; } app.publishQueue = []; app.publishQueueStatus = { pathList: [], hashList: {}, pathsToHandle: [], didLast: false, percent: 0, lastGuess: partial ? 0 : 6, handled: 0, total: 0 }; app.showPublishProgress('init'); var target = app.publishProgress; var publishPercentBox = DOM().new('div').css({ position: 'absolute', bottom: 0, left: 0, right: 0, height: '51px' }).appendTo(target).html(''); var publishPercentFill = DOM().new('div').css({ height: '51px', 'background-color': '#27a4dd', width: '0%' }).appendTo(publishPercentBox); var publishStatus = DOM().new('div').class('caa_padding caa_publish_status').appendTo(target).css({ 'background-color': '#e7e7e7', 'padding-bottom': '60px', height: '100%', 'max-height': '200px', 'overflow-y': 'auto' }); var startingText = DOM().new('div').css({ 'padding-bottom': '10px' }).text('Publishing...').appendTo(publishStatus), passwords = [], hasPasswords = false, sitemapURLs = '', sitemap = '', siteURL = app.siteURL(), rssFeeds = {}, rssUpdated = {}, modifiedXML = new Date().toUTCString(), modified = new Date().toISOString(), search = { name: (app.site.content.pages[0].title || app.site.name), url: siteURL, content: [] }; var processPage = function(item) { var pageRef = item.data ? item.data : app.site.content[item.section][item.p]; window.genUIDTicker = 0; // ensures that genuid is fresh on gen to make content the same for hashing var page = new Page(app, app.site, item.internal, false, {}, item.data || false), html, source = ((item.internal || '') + '').split('/').slice(0, 3).join('/'), pageContentHTML, description = item.data ? pageRef.meta || pageRef.description : pageRef.description || '', date = new Date(isoDate(pageRef.date)).toUTCString(), media = pageRef.media || getFirstMedia(pageRef, '', app.site.media), mediaURL = mediaSource(app.site, media); item.path = item.url; // just an alias we use if (!pageRef.date || !(pageRef.date || '').trim() || !date || date.match(/01 Jan 1970/)) { if (app.publishMeta.publish_hash[item.path] && app.publishMeta.publish_hash[item.path].lastChanged) { date = new Date(app.publishMeta.publish_hash[item.path].lastChanged).toUTCString(); } else { date = new Date().toUTCString(); } } if (item.publishFeed) { source += '/' + item.publishFeed } page.url = item.url; page.href = siteURL + item.url; //imporatnt for published items if (page.publishSources && partial) { doFeeds = doFeeds.concat(page.publishSources); app.publishQueueStatus.lastGuess += page.publishSources.length; } if (item.data) { // we do this so that the replacement in the markup doesn't touch the scripts var allHTML = page.dom.html(); pageContentHTML = ''; //priority to body if (item.data.description && !item.data.body) { item.data.body = item.data.description; } if (!item.data.description && item.data.body) { item.data.description = item.data.body; } var processHTML = function(html){ Object.keys(item.data).forEach(function(key) { if (typeof item.data[key] === 'string') { var value = (item.data[key] + '') || ''; if (key === 'date') { value = displayDate(parseAnyDate(value)); } html = html.replace(new RegExp('{{' + key + '}}', 'gi'), value); } else { if (key === 'media') { var newMedia = DOM().new('div').append(app.Media(item.data[key])); html = html.replace(new RegExp('{{' + key + '}}', 'gi'), newMedia.html()); } } }); return html; } allHTML.split('-item-X').forEach(function(html, i) { if (i % 2 === 0) { pageContentHTML += processHTML(html); } else { var html2 = html.split('-end-X') pageContentHTML += html2[0] || ''; pageContentHTML += processHTML(html2[1] || ''); } }) pageContentHTML = app.displayContentMedia(pageContentHTML, false); page.dom.html(pageContentHTML); } html = page.html(true, true); item.murmurHash = murmur(html); item.not_updated = false; if (app.publishMeta.publish_hash[item.path]) { if (app.publishMeta.publish_hash[item.path].lastHash == item.murmurHash) { item.not_updated = true; } } if (typeof rssFeeds[item.section] !== 'string') { rssFeeds[item.section] = ''; app.publishQueueStatus.lastGuess++; } if (item.p > 0 && !item.disable) { if (!item.not_updated) { rssUpdated[item.section] = true; } rssFeeds[item.section] += '
\n'; rssFeeds[item.section] += '
' + item.title.htmlSafe() + '
\n'; rssFeeds[item.section] += '
' + siteURL + item.url + '\n'; rssFeeds[item.section] += '
' + siteURL + item.url + '
\n'; if (mediaURL && description) { rssFeeds[item.section] += '
' + description.htmlSafe() + '
' + ']]>
\n'; } else if (mediaURL && !description) { rssFeeds[item.section] += '
]]>
\n'; } else if (description) { rssFeeds[item.section] += '
' + description.htmlSafe() + '
\n'; } rssFeeds[item.section] += '
' + date + '
\n'; rssFeeds[item.section] += '
\n'; } if (!item.disable) { if (!item.hidden) { var pageMediaSitemapItems = ''; if (page.mediaArray && page.mediaArray.length) { page.mediaArray.forEach(function(mediaID) { var mediaURL = mediaSource(app.site, mediaID, 'full'); if (mediaURL) { pageMediaSitemapItems += '
\n
' + mediaURL.htmlSafe() + '
\n
' + (app.site.media[mediaID].name || '').htmlSafe() + '
\n
\n'; } }) } var lastModified = modified; if (app.publishMeta.publish_hash[item.path] && app.publishMeta.publish_hash[item.path].lastChanged) { lastModified = new Date(app.publishMeta.publish_hash[item.path].lastChanged).toISOString(); } sitemapURLs += '
\n
' + siteURL + item.url + '
\n
' + lastModified + '
\n' + pageMediaSitemapItems + '
\n'; var feedSearchContent = ''; var ignoreKeys = ['media', 'url']; var addToSearchContent = function(item) { Object.keys(item).forEach(function(key){ if(item[key] && ignoreKeys.indexOf(key) < 0) { if(key === 'items') { if(item.items && item.items.length){ item.items.forEach(addToSearchContent); } } else { if(key === 'tags' && item[key] && typeof item[key] === 'object') { feedSearchContent += item[key].join(' '); } else { feedSearchContent += DOM().new('div').html(item[key] || '').text() + ' '; } } } }); } Object.keys(app.site.feeds || {}).forEach(function(feedID){ var item = app.site.feeds[feedID]; if (item && item.source === 'manual') { if ((doFeeds.indexOf(feedID) > -1 || (page.publishSources && page.publishSources.indexOf(feedID) > -1)) && item.items && item.items.length) { //console.log('add feed to search', feedID); item.items.forEach(addToSearchContent); } } }) //console.log('publish page with search content', page.url, feedSearchContent) search.content.push({ title: DOM().new('div').html(item.title).text() || '', description: DOM().new('div').html(description || '').text() || '', url: siteURL + item.url, tags: Array.isArray(pageRef.tags) ? pageRef.tags : [], content: DOM().new('div').html(page.dom.content.html().replace(/\ 0) ? item.url : item.url + '*'; passwords.push({ url: passwordURL, passwords: pageRef.passwords }); } } } else { html = '__delete'; } app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: item.url, type: 'text/html', content: html }); setTimeout(processQueueExec, 100); app.publishQueueExec(); }; var processQueue = []; var processQueueExec = function() { if (processQueue.length) { processPage(processQueue.shift()); } else { readyForLast(); } }; app.publishMeta = { publish_hash: {} }; app.publishSiteMap(function(siteMap) { siteMap.forEach(function(item, i) { if ((!partial || urlList.indexOf(item.url) > -1) && !item.disable) { processQueue.push(item); } }); app.publishQueueStatus.preGuess = siteMap.length - 1; processQueueExec(); runPublishQueue(); }, { publishMeta: true }); var readyForLast = function() { app.publishQueueStatus.preGuess = 0; if (!partial) { sitemap += '\n'; sitemap += '
\n'; sitemap += sitemapURLs; sitemap += '
'; app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: '/sitemap.xml', type: 'text/xml', content: sitemap }); app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: '/search.json', type: 'application/json', content: JSON.stringify(search) }); for (var section in rssFeeds) { if (section !== 'pages' && section !== '__templates') { var lastModifiedXML = modifiedXML, xmlPath = '/' + section + '.xml'; if (!rssUpdated[section] && app.publishMeta.publish_hash[xmlPath] && app.publishMeta.publish_hash[xmlPath].lastChanged) { lastModifiedXML = new Date(app.publishMeta.publish_hash[xmlPath].lastChanged).toUTCString(); } var rssxml = '\n'; rssxml += '
\n'; rssxml += '
\n'; rssxml += '
' + (app.site.content[section][0].title || app.site.name) + '
\n'; rssxml += '
' + siteURL + '/' + section + '\n'; rssxml += '
' + app.site.content[section][0].description + '
\n'; rssxml += '
en-us
\n'; rssxml += '
' + lastModifiedXML + '
\n'; rssxml += '
' + lastModifiedXML + '
\n'; rssxml += '
Blux
\n'; rssxml += '
\n'; rssxml += rssFeeds[section] + '\n'; rssxml += '
\n'; rssxml += '
\n'; app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: xmlPath, type: 'text/xml', not_updated: !rssUpdated[section], content: rssxml }); } } } if (!partial || doFeeds.length) { var feedID; for (feedID in app.site.feeds) { var item = app.site.feeds[feedID]; if (item) { if (item.source === 'manual') { if ((!doFeeds.length || doFeeds.indexOf(feedID) > -1) && item.items && item.items.length) { var feedJSON = JSON.parse(JSON.stringify(item.items)), processJSONmedia = function(item) { if (item.media && item.media.media && app.site.media[item.media.media]) { item.media.type = app.site.media[item.media.media].type; item.media.src = mediaSource(app.site, item.media); } }; feedJSON.forEach(processJSONmedia); app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: '/' + feedID + '.json', type: 'application/json', content: JSON.stringify(feedJSON) }); } } } } if (!partial) { // feeds index and all feeds into json if (app.site.feeds) { var publishFeeds = JSON.parse(JSON.stringify(app.site.feeds)); if (publishFeeds) { for (feedID in publishFeeds) { if (publishFeeds[feedID]) { delete publishFeeds[feedID].items; } } app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: '/feeds.json', type: 'application/json', content: JSON.stringify(publishFeeds) }); } } } } if (!partial) { // robots.txt var robots = 'User-agent: *\n'; robots += 'Sitemap: ' + siteURL + '/sitemap.xml\n'; robots += 'Disallow:\n'; if (app.site.settings.hosting) { if (app.site.settings.hosting.hideFromSearch) { robots = 'User-agent: *\nDisallow: /\n'; } } app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: '/robots.live.txt', type: 'text/plain', content: robots }); app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: '/robots.txt', type: 'text/plain', content: 'User-agent: *\nDisallow: /' }); // site hosting config var config = {}; if (app.site.settings.redirects) { if (app.site.settings.redirects.length) { config.redirects = app.site.settings.redirects; } } if (hasPasswords) { config.passwords = passwords; } if (app.site.domain) { config.domain = app.site.domain; } if (app.site.settings.hosting) { if (app.site.settings.hosting.redirectToPrimary) { config.redirectToPrimary = true; } } if (app.site.i18n) { Object.keys(app.site.i18n).forEach(function(i18nID) { var trans = app.site.i18n[i18nID], domain = (trans.domain || '').trim(), folder = (trans.language_code || i18nID).urlSafe(); if (trans && domain && folder) { if (!config.i18n) { config.i18n = {}; } config.i18n[i18nID] = { domain: domain, folder: folder, code: trans.language_code }; } }); } app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: 10000, path: '__config.json', type: 'application/json', content: JSON.stringify(config) }); } app.publishQueueStatus.lastGuess = 0; app.publishQueueStatus.didLast = true; app.publishQueueExec(); } var runPublishQueue = function() { app.publishStatusFunc = function(message) { app.publishQueueStatus.handled++; var index = app.publishQueueStatus.pathsToHandle.indexOf(message.path); if (index > -1) { app.publishQueueStatus.pathsToHandle.splice(index, 1); } app.publishQueueStatus.percent = (app.publishQueueStatus.handled / (app.publishQueueStatus.lastGuess + app.publishQueueStatus.preGuess + app.publishQueueStatus.total)) || 0; publishPercentFill.animate({ width: Math.round(app.publishQueueStatus.percent * 100) + '%' }, 100); if (message.path) { var msg = DOM().new('div').css({ 'padding-bottom': '10px' }).text(message.path || '').appendTo(publishStatus); if (message.not_updated) { msg.css({ color: '#999' }).text('Not Updated: ' + message.path); } else if (!message.success) { if (message.reason !== 'delete') { msg.css({ color: 'red' }).text('Failed ' + message.path + ' (' + message.reason + ')'); } } } if (!app.publishQueueStatus.complete && app.publishQueueStatus.didLast && app.publishQueueStatus.percent >= 1) { app.publishQueueStatus.complete = true; startingText.text(''); DOM().new('div').css({ 'padding-bottom': '10px' }).text('Publish completed').appendTo(publishStatus); publishPercentFill.animate({ height: 0 }); publishPercentBox.animate({ height: 0 }, function(e) { publishPercentBox.remove(); }); if (!partial) { DOM().new('div').css({ 'padding-bottom': '10px' }).append(DOM().new('a').attr({ href: app.stagingURL(), target: '_blank' }).text('View Staging Site')).appendTo(publishStatus); app.Request({ do: 'request', request: 'publishSiteCleanup', updateFeed: true, revision: app.site.revision, pathList: app.publishQueueStatus.pathList, hashList: app.publishQueueStatus.hashList, //siteObject: app.site }, function(data) { //console.log('data', data, 'cleanup complete'); }); } if (typeof publishCallback === 'function') { setTimeout(function() { publishCallback(); }, 200); } app.showPublishProgress('dismissable'); } publishStatus.elements[0].scrollTop = publishStatus.elements[0].scrollHeight; app.publishQueueExec(); }; app.publishQueueExec(); }; }; App.prototype.publishSiteMap = function(callback, config) { if (!config) { config = {}; } var app = this, urlList = app.siteMap(config), out = 0, done = 0, feedMap = function() { if (app.site.feeds) { Object.keys(app.site.feeds).forEach(function(feedID) { var feed = app.site.feeds[feedID]; if (feed) { if (feed.publish) { out++; app.getFeedItems(feed, function(feedData) { if (Array.isArray(feedData.items)) { feedData.items.forEach(function(feedItem, f) { if (!feedItem.disable_publish) { var url = app.figureOutFeedItemURL(feed, feedItem); feedItem.url = url; if (url) { urlList.push({ title: feedItem.title || '', url: url, section: '__templates', publishFeed: feedID + '/' + f, internal: '/' + feed.template, data: feedItem }); } } }); } setTimeout(completed, 10); }); } } }); } setTimeout(completed, 10); }, completed = function() { done++; if (out > 0 && done === out) { app.publisheSiteMapCached = urlList; callback(urlList); } }; out++; feedMap(); if (config.publishMeta) { out++; app.Request({ do: 'request', request: 'publishMeta' }, function(data) { app.publishMeta = data; setTimeout(completed, 10); }); } }; App.prototype.figureOutFeedItemURL = function(feed, feedItem) { var app = this, prefix = '/' + feed.publish + '/', url = ''; if (prefix === '/pages/') { prefix = '/'; } url = prefix; if (feedItem.url) { url += (feedItem.url.split('/').pop() || '').urlSafe(); } if (url === prefix) { url += (feedItem.title || '').urlSafe(); } if (app.pageURLS[url]) { // note this is wher eyou fix the bug to do -3 or -4 on urls url += '-2'; } if (!url) { console.error('could not figure out url for feed', feed, 'item', feedItem); } return url; }; App.prototype.publishQueueAdd = function(item, isTranslation) { var app = this; if (!item.murmurHash) { item.murmurHash = murmur(item.content); } if (item.path && item.content) { app.publishQueueStatus.hashList[item.path] = item.murmurHash; if (app.publishMeta.publish_hash[item.path]) { if (app.publishMeta.publish_hash[item.path].lastHash == item.murmurHash || item.not_updated) { item.not_updated = true; } } } app.publishQueue.push(item); app.publishQueueStatus.total++; if (app.publishQueueStatus.preGuess > 0) { app.publishQueueStatus.preGuess--; } app.publishQueueStatus.pathList.push(item.path); app.publishQueueStatus.pathsToHandle.push(item.path); app.publishQueueStatus.didProceed = true; if (!isTranslation && item.path !== '__config.json' && app.site.i18n) { Object.keys(app.site.i18n).forEach(function(i18nID) { var trans = app.site.i18n[i18nID], folder = (trans.language_code || i18nID).urlSafe(), translatedHTML = (item.content || '') + ''; if (item.type === 'text/html') { translatedHTML = translatedHTML.replace('', ''); if (trans.paths) { Object.keys(trans.paths).forEach(function(transPath) { for (var transKey in trans.paths[transPath]) { var originalText = app.getFromPath(transPath.split('/'))[transKey]; if (originalText && trans.paths[transPath][transKey]) { if (translatedHTML.indexOf('>' + originalText + '<') > -1) { translatedHTML = translatedHTML.replace('>' + originalText + '<', '>' + trans.paths[transPath][transKey] + '<'); } } } }); } } app.publishQueueAdd({ do: 'request', request: 'publishFile', timeout: item.timeout, path: '/_' + folder + item.path, type: item.type, content: translatedHTML }, true); }) } }; App.prototype.publishQueueExec = function() { var app = this; if (app.publishQueue) { if (app.publishQueue.length) { var item = app.publishQueue.shift(); if (item.not_updated) { setTimeout(function() { app.publishStatusFunc(item); }, 10); } else { app.Request(item, function(data) { app.publishStatusFunc(data); }); } } } }; App.prototype.goLive = function(paths) { var app = this; app.showPublishProgress('init'); var into = DOM().new('div').class('caa_padding').text('Going live...').appendTo(app.publishProgress); app.Request({ do: 'request', paths: paths || undefined, request: 'goLive' }, function(data) { into.css({ color: data.color || '' }).html(data.response); if (data.color == 'green') { if (paths && paths.length) { DOM().new('span').text(' ').appendTo(into); DOM().new('a').attr({ href: app.siteURL() + (paths[0] || '').replace('.html', ''), target: '_blank' }).text('View Page').appendTo(into); } else { DOM().new('span').text(' ').appendTo(into); DOM().new('a').attr({ href: app.siteURL(), target: '_blank' }).text('View Live Site').appendTo(into); } DOM().new('span').css({ color: 'black', 'font-size': '12px' }).html('
*It may take a few minutes for your published site to load in your browser. If the site does not appear to be updated press Ctrl+R (Windows) or Command+R (Mac) to verify.').appendTo(into); } app.showPublishProgress('dismissable'); }); }; function minifyCSS(css) { if (!css) { return css; } return new CleanCSS().minify(css).styles; } function minifyJS(code) { //if(devmode){ return code; } if (!code) { return ''; } try { var ugly = UglifyJS.parse(code, { filename: '?', toplevel: ugly }); UglifyJS.merge({ warnings: false }, { sequences: true, dead_code: true, conditionals: true, booleans: true, unused: true, if_return: true, join_vars: true, drop_console: true }); /* tmp makes it way faster to minify ugly.figure_out_scope(); var sq = UglifyJS.Compressor({ warnings: false }); ugly = ugly.transform(sq); ugly.figure_out_scope(); ugly.compute_char_frequency(); ugly.mangle_names({}); */ var stream = UglifyJS.OutputStream(); ugly.print(stream); code = stream.toString(); } catch (error) { console.error('failed to minify js', error); } return code; } function minifyMarkup(html) { if (!html) { return ''; } var shadowDom = DOM().new('div').html(html); shadowDom.byTag('style').elements.forEach(function(tag) { var css = (tag.textContent || '').trim(); if (css && css.length > 100) { try { tag.textContent = minifyCSS(css || ''); } catch (error) { console.error('failed to minify css', error); } } }); shadowDom.byTag('script').elements.forEach(function(tag) { var code = (tag.textContent || '').trim(); if (code.length > 400) { code = minifyJS(code); if (code) { tag.textContent = code; } else { console.error('could not process uglify js on code'); } } }); html = shadowDom.html(); shadowDom = null; return html; } App.prototype.quality = function(into, type) { var app = this, siteURL = app.siteURL(); var content = DOM().new('div').addClass('caa_padding').appendTo(into).append(UI.Spinner('24').css({ 'padding-right': '20px' })) .append(DOM().new('span').class('ib middle').text('Getting history of approval...')), siteMap; app.publishSiteMap(function(getSiteMap) { siteMap = getSiteMap; app.Request({ do: 'request', request: 'publishMeta' }, function(data) { if (data.publish_hash) { content.html(''); siteMap.forEach(function(page, i) { var media = page.data && page.data.media ? page.data.media : getFirstMedia(app.getFromPath(['content'].concat(page.internal.substr(1).split('/').slice(0,2)))), hashRef = data.publish_hash[page.url]; var thumb = DOM().new('div').css({ width: '80px', 'padding-top': '56%' }).class('caa_valignmiddleitem'); app.Media(media, thumb); thumb.css({ 'background-size': 'cover', 'background-position': 'center center' }) var lastString = ''; if(hashRef){ lastString = 'Last changed '+displayDateLocal(new Date(hashRef.lastChanged).toString(), 'time'); } DOM().new('div') .class('caa_griditem caa_griditemhover caa_click') .css({margin: '0 0 10px 0', border: '1px solid #d4d4d4'}) .append( DOM().new('div').class('ibb middle caa_valignmiddle').css({ width: '80px', overflow: 'hidden' }).append(thumb) ) .append( DOM().new('div').class('ibb middle page-title').css({ width: 'calc(100% - 80px)', padding: '2px 10px 2px 10px' }) .append(DOM().new('span').class('ibb middle ellipsis').css({ width: '100%', overflow: 'hidden' }).text(page.title) .append(DOM().new('div').css({'font-size':'-1', color: '#666'}).text(lastString)) .append(DOM().new('div').css({'font-size':'-1', color: '#999'}).text(page.url || '')) ) ) .appendTo(content); }); DOM().byClass('camediaload').loadMedia().mediaNOFX(); } }); }); }; /* two issues: 1 need to fix app.siteSet() cause that doesn't work for some reason and two. provide a better way to show the change list. spend time on it */ App.prototype.restore = function(change) { var app = this; var revision = change.revision; var box = DOM().new('div').class('caa_padding'); // designed to be used in a modal box.text('Getting site as of change #' + revision + '...'); var request = { do: 'request', request: 'getRevision', changeID: change.changeID, type: change.type, previousRevision: change.previousRevision, revision: revision }; var showRevision = function(data) { box.html(''); console.log('change', data); DOM().new('div').text('Revision #' + revision + ' ' + displayDate(change.date, 'time')).appendTo(box); if (change.type !== 'publish') { if(data.changeObject){ var linkPath = Array.isArray(data.changeObject.path) ? humanPath(data.changeObject.path, app.site) : '/' var thisChange = DOM().new('div').css({'background-color': '#ccc', padding: '10px','margin-top':'20px'}).append(DOM().new('div').text('Change made to: '+linkPath).css({padding: '4px 0'})).appendTo(box); if(typeof data.changeObject.value === 'object'){ app.siteTree('view', function(dom, path, obj) { var str = humanPath(path, data.site); }, data.changeObject.value).appendTo(thisChange); } if(data.changeObject.reason){ DOM().new('div').text('Auto Fix Reason: '+data.changeObject.reason).appendTo(thisChange); } if(data.changeObject.changed){ DOM().new('pre').text(JSON.stringify(data.changeObject.changed, undefined, 2)).appendTo(thisChange); } if(data.previousSite){ var previousValue = DOM().new('div').css({'background-color': '#ccc', padding: '10px','margin-top':'20px'}).append(DOM().new('div').text('Previous Value: '+linkPath).css({padding: '4px 0'})).appendTo(box); if(typeof data.previousSite === 'object'){ var previousValueObject = JSON.parse(JSON.stringify(app.getFromPath(data.changeObject.path, data.previousSite))); for(var k in previousValueObject) { if(typeof data.changeObject.value[k] == 'undefined'){ delete previousValueObject[k]; } } app.siteTree('view', function(dom, path, obj) { var str = humanPath(path, previousValueObject); }, previousValueObject).appendTo(previousValue); DOM().new('button').class('caa_button-default').text('Restore This').on('click', function(e){ DOM(e.target).attr({disabled: true}).text('Restored!'); app.siteUpdate(data.changeObject.path, previousValueObject); }).appendTo(previousValue); } } } DOM().new('div').text('Optionally, select which part of your site you wish to restore from this revision.').css({'margin-top': '100px'}).appendTo(box); } else { DOM().new('div').text('Select which part of your site you wish to restore from this published revision.').appendTo(box); } var restoreButtonHolder = DOM().new('div').css({margin: '10px 0'}).appendTo(box); app.siteTree('view', function(dom, path, obj) { var str = humanPath(path, data.site); restoreButtonHolder.html('').append( DOM().new('button').class('caa_button-default').text('Restore: '+str).on('click', function(e){ DOM(e.target).attr({disabled: true}); app.siteSet(path, obj); restoreButtonHolder.css({'color': '#00cc00', 'font-weight':'bold'}).html(str+' was restored!'); }) ); }, data.site).appendTo(box); }; app.Request(request, showRevision); return box; }; App.prototype.richEditor = function(e, element, into, selectedText) { if (!into) { into = this.stage; } var app = this, pos = { x: e.touches ? e.touches[0].pageX : e.pageX, y: e.touches ? e.touches[0].pageY : e.pageY, }, offsetLeft = (app.leftPanel.expanded || window.innerWidth >= 1200) ? 300 : 0, offsetWidth = into.elements[0].offsetWidth, scrollTop = into.elements[0].scrollTop, left = pos.x - offsetLeft - 150, top = ((pos.y - 70) + scrollTop); if (left < 10) { left = 10; } if (top < 10) { top = 10; } app.showingRichEditor = true; var container = DOM().newOrFind('div', 'caa_rich-editor').css({ display: '', opacity: 0, position: 'absolute', 'z-index': 99, left: left + 'px', top: top + 'px', 'white-space': 'nowrap', transform: 'scale(0)' }).html('').appendTo(into) .animate({ opacity: 1, transform: 'scale(1)' }).on('mousedown', function(e) { app.richEditorClick(); }), buttons = [{ command: 'font', icon: 'title', text: 'Block Heading' }, { command: 'inlinefont', icon: 'font', text: 'Inline Text Style' }, { command: 'foreColor', icon: 'color', text: 'Text Color' }, { command: 'CreateLink', icon: 'link', text: 'Create Link' }, { command: 'bold', icon: 'bold', text: 'Bold' }, { command: 'italic', icon: 'italic', text: 'Italic' }, { command: 'underline', icon: 'underline', text: 'Underline' }, { command: 'superscript', icon: 'superscript', text: 'Superscript' }, { command: 'insertunorderedlist', icon: 'unordered-list', text: 'Unordered List' }, { command: 'insertorderedlist', icon: 'ordered-list', text: 'Ordered List' }, { command: 'removeFormat', icon: 'remove-formatting', text: 'Remove Formatting' }]; if (selectedText.newline) { buttons = [{ command: 'insertunorderedlist', icon: 'unordered-list', text: 'Unordered List' }, { command: 'insertorderedlist', icon: 'ordered-list', text: 'Ordered List' }, { command: 'media', icon: 'media', text: 'Media' }]; } else if (!selectedText.text) { buttons = []; } if (left + (buttons.length * 44) > offsetWidth) { container.css({ left: '', right: 0 }); } buttons.forEach(function(button) { DOM().new('button').class('caa_button-default').attr({ title: button.text }).append(UI.Icon(button.icon, 'editor')).appendTo(container).on('click', function(e) { if (button.command === 'CreateLink') { app.richEditorLink(container); } else if (button.command === 'font' || button.command === 'inlinefont') { app.richEditorTextStyle(button.command, container, element); } else if (button.command === 'foreColor') { app.richEditorTextColor(button.command, container, element); } else if (button.command === 'media') { document.execCommand('inserthtml', null, '
'); app.displayContentMedia(element, true); } else { document.execCommand(button.command, null, null); element.elements[0].focus(); } }); }); }; App.prototype.richEditorLink = function(container) { var app = this, url = '', remLink = '', selection = saveSelection(), chkdblank = '', target, className = 'links', sel = window.getSelection(); if (sel) { if (sel.anchorNode) { var targetNode = sel.anchorNode.nodeName === 'A' ? sel.anchorNode : sel.anchorNode.parentElement, ContainingElement = DOM(targetNode); if (targetNode.nodeName !== 'A') { // target nothing so we do not inherit from the container ContainingElement = DOM().new('span'); } url = ContainingElement.attr('href'); if (url === 'undefined' || !url) { url = ''; } target = ContainingElement.attr('target'); className = ContainingElement.attr('class') || 'links'; remLink = true; } } if (target === '_blank') { chkdblank = 'selected'; } var pos = container.pos(); var layer = UI.openLayer({ left: pos.left, top: pos.top, width: 300, 'max-height': '400px', 'overflow': 'visible' }); var box = DOM().new('div').class('caa_rightPanelSection').appendTo(layer).css({ 'min-width': '300px' }); // VERTICAL-ALIGN EditorHelpers.link(app, box, {}, false, {}, { label: 'Links To', value: url || '', target: target, property: 'link', siteMap: false, onchange: function(chURL, chTARGET) { url = chURL; target = chTARGET; } }); box.byClass('caa_rightPanelSection').removeClass('caa_rightPanelSection'); var buttonClassOptions = [{ text: 'Default Page Links', value: 'links' }], k; for (k in app.site.styles.buttons) { if (filterDesignItems(app.site.styles.buttons[k])) { buttonClassOptions.push({ text: app.site.styles.buttons[k]._label, value: 'buttons' + k }); } } Inputs.options({ label: 'Link/Button Style', value: className, options: buttonClassOptions, onchange: function(val) { className = val; } }).appendTo(box); var buttonHolder = DOM().new('div').css({ 'margin-top': '20px', overflow: 'hidden' }).append( DOM().new('button').class('caa_button-default').css({ float: 'right' }).text('Set Link').on('click', function(e) { restoreSelection(selection); document.execCommand('CreateLink', null, url); ContainingElement = DOM(sel.anchorNode.parentElement); ContainingElement.attr({ 'target': target }).class(className); UI.removeLayers(); }) ).appendTo(box); if (remLink) { DOM().new('button').class('caa_button-default').text('Remove Link').on('click', function(e) { restoreSelection(selection); document.execCommand('unlink', null); UI.removeLayers(); }).appendTo(buttonHolder); } }; App.prototype.richEditorTextStyle = function(type, container, element) { var app = this, selection = saveSelection(), className = '', sel = window.getSelection(); if (sel) { if (sel.anchorNode) { var targetNode = sel.anchorNode.nodeName === 'H3' ? sel.anchorNode : sel.anchorNode.parentElement, ContainingElement = DOM(targetNode); if (targetNode.nodeName !== 'H3') { // target nothing so we do not inherit from the container ContainingElement = DOM().new('H3'); } className = ContainingElement.attr('class') || ''; } } var pos = container.pos(), layer = UI.openLayer({ left: pos.left, top: pos.top, width: 300, 'max-height': '400px', 'overflow-y': 'auto' }), box = DOM().new('div').class('caa_rightPanelSection').appendTo(layer); DOM().new('div').text('None / Remove Style').addClass('caa_clickSecTarget').appendTo(box).on('click', function(e) { restoreSelection(selection); document.execCommand('formatBlock', null, 'p'); // only h3 is allowed it should make it text ContainingElement = DOM(sel.anchorNode.parentElement); ContainingElement.class('').css({ margin: 0, padding: 0, display: 'inline' }); UI.removeLayers(); }); Object.keys(app.site.styles.text).forEach(function(k) { if (filterDesignItems(app.site.styles.text[k])) { DOM().new('div').text(app.site.styles.text[k]._label || 'text' + k).addClass('caa_clickSecTarget text' + k).appendTo(box).on('click', function(e) { if (type === 'inlinefont') { restoreSelection(selection); document.execCommand('inserthtml', null, '
' + (sel.toString() || '').trim() + '
'); } else { restoreSelection(selection); document.execCommand('formatBlock', null, 'h3'); ContainingElement = DOM(sel.anchorNode.parentElement); ContainingElement.addClass('text' + k); } UI.removeLayers(); }); } }); }; App.prototype.richEditorTextColor = function(type, container, element) { var app = this, selection = saveSelection(), className = '', sel = window.getSelection(), color = '', targetNode, ContainingElement = element; if (sel) { if (sel.anchorNode) { targetNode = sel.anchorNode.nodeName === 'H3' ? sel.anchorNode : sel.anchorNode.parentElement; ContainingElement = DOM(targetNode); } } console.log('containing element', element); var pos = container.pos(), layer = UI.openLayer({ left: pos.left, top: pos.top, width: 300, 'max-height': '400px', 'overflow-y': 'auto' }); var colorOps = app.currentColorList(); var colorBox = DOM().new('div').class('ib top').appendTo(layer).css({ 'max-width': '105px', 'max-height': '400px', 'overflow-y': 'auto', 'white-space': 'normal' }); var colorPicker = DOM().new('div').class('ib top').css({ 'white-space': 'normal' }).appendTo(layer); colorOps.forEach(function(color, c) { color = (color || '').toLowerCase().trim(); var item = DOM().new('div').class('ib middle caa_colorBox').attr({ title: color }).css({ 'background': color, 'margin': '10px 0 0 10px' }).appendTo(colorBox).on('click', function(e) { restoreSelection(selection); if (color) { document.execCommand('foreColor', null, color); var markup = ContainingElement.html(); var newMarkup = DOM().new('div').html(markup); newMarkup.byTag('font').exists(function(fontNode) { DOM().new('span').html(fontNode.html()).css({ color: color }).insertAfter(fontNode); fontNode.remove(); ContainingElement.html(newMarkup.html()); }); } else { document.execCommand('inserthtml', null, (sel.toString() || '')); } }); if (!color) { item.css({ position: 'relative', overflow: 'hidden' }).append(DOM().new('span').css({ position: 'absolute', left: '-10px', right: '-10px', height: '2px', top: '49%', 'background-color': '#aaa', 'transform-origin': '50% 50%', 'transform': 'rotate(45deg)' })); } }); }; // http://stackoverflow.com/a/4713197 function getSelectedText() { var ret = { text: '', newline: false }; var sel = window.getSelection(), range = sel.getRangeAt(0); ret.text = (sel.toString() || '').trim(); if (range.collapsed) { var len = (range.startContainer.textContent || '').length, str = '', restoreIndex = range.startOffset * 1, hasRange = true; if (range.startOffset > 0) { range.setStart(sel.anchorNode, range.startOffset - 1); } if (range.endOffset < len) { try { range.setEnd(sel.anchorNode, range.endOffset + 1); } catch (e) {} } sel.removeAllRanges(); sel.addRange(range); str = window.getSelection().toString(); if (!len || (!str.trim() && (str.substr(0, 1) === '\n' || str.substr(-1) === '\n'))) { ret.newline = true; } range.setStart(sel.anchorNode, restoreIndex); range.setEnd(sel.anchorNode, restoreIndex); sel.removeAllRanges(); sel.addRange(range); } return ret; } /* http://stackoverflow.com/questions/5605401/insert-link-in-contenteditable-element */ function saveSelection() { var sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { var ranges = []; for (var i = 0, len = sel.rangeCount; i < len; ++i) { ranges.push(sel.getRangeAt(i)); } return ranges; } return null; } function restoreSelection(savedSel) { if (savedSel) { var sel = window.getSelection(); sel.removeAllRanges(); for (var i = 0, len = savedSel.length; i < len; ++i) { sel.addRange(savedSel[i]); } } } App.prototype.screenSizes = function(size) { var app = this; if (!app.screenSize && app.screenSize !== 0) { app.screenSize = 0; } if (!size && size !== 0) { size = false; } if (size == 'enable') { var show = app.parts[0]; var editPreviewButton; var changeScreenSizeButton; var editingText = 'Editor', editingIcon = 'edit', preview = show === 'preview'; if (!preview) { editingText = 'Preview'; editingIcon = 'eye'; } if (app.screenSizeShowing) { editPreviewButton = app.domBody.byClass('caa_resizePanelButtonEdit').animate({ width: preview ? '50%' : '100%' }); changeScreenSizeButton = app.domBody.byClass('caa_resizePanelButtonIcon').animate({ width: preview ? '50%' : '0' }); } else { rm('caa_resizePanel'); app.subNavContainer.css({ bottom: '52px' }); var resizePanel = DOM().new('div').id('caa_resizePanel').class('caa_resizePanel'), sizes = ['fitscreen', 'mobile', 'tablet', 'notebook', 'desktop', 'email']; var screenSizeIconHolder = DOM().new('div').appendTo(resizePanel).css({ overflow: 'hidden', 'white-space': 'nowrap' }) editPreviewButton = DOM().new('span').class('ibb middle caa_resizePanelButton caa_resizePanelButtonEdit') .css({ padding: '10px 0', width: preview ? '50%' : '100%' }) .on('click', function(e) { var renderURL, renderParts = app.parts.slice(0); if (app.parts[0] === 'content') { app.user.prefs.preview = true; renderParts[0] = 'preview'; } else { delete app.user.prefs.preview; renderParts[0] = 'content'; } app.setUser(); app.render('/' + renderParts.join('/'), false, false); if (renderParts[0] === 'content' && app.screenSize !== 0) { app.setScreenSize(0); changeScreenSizeButton.html('').append(UI.Icon('fitscreen', 'menu')); } }).appendTo(screenSizeIconHolder); changeScreenSizeButton = DOM().new('span').class('ibb middle caa_resizePanelButton caa_resizePanelButtonIcon') .css({ padding: '10px 0', width: preview ? '50%' : 0, overflow: 'hidden', 'border-left': '1px solid #cfcfcf' }) .append(UI.Icon('fitscreen', 'menu')) .on('click', function(e) { var layer = UI.openLayer({ left: 170, bottom: 0 }).css({ width: '110px' }); sizes.forEach(function(icon, s) { var fillColor = (app.screenSize === s) ? '#357EAA' : ''; var icondom = UI.Icon(icon, 'menu').css({ padding: '4px 0', }).on('click', function(e) { app.screenSizes(s); layer.byTag('svg').css({ 'fill': '' }); DOM(e.target).byTag('svg').css({ 'fill': '#357EAA' }); changeScreenSizeButton.html('').append(UI.Icon(icon, 'menu')); }); icondom.byTag('svg').css({ fill: fillColor }); DOM().new('div').css({ 'text-align': 'center', }).append(icondom).appendTo(layer); }); }).appendTo(screenSizeIconHolder); resizePanel.appendTo(app.leftPanel); } editPreviewButton.html('') .append(UI.Icon(editingIcon, 'resizePanel')) .append(DOM().new('span').class('ib middle').css({ 'margin-left': '8px' }).text(editingText)) app.screenSizeShowing = app.parts[0]; app.onResize(function(e) { if (e) { app.setScreenSize(app.screenSize); } }); } else { if (size || size === 0) { if (app.screenSize !== size) { app.screenSize = size; app.setScreenSize(size); } } else { delete app.screenSizeShowing; app.screenSize = 0; app.stage.css({ 'margin-top': 0, width: 'auto', height: '', 'transform': '', '-webkit-transform': '' }); rm('caa_resizePanel'); DOM(document.body).css({ overflow: '' }); app.subNavContainer.css({ bottom: 0 }); } } }; App.prototype.setScreenSize = function(size) { var app = this, w = 0, h = 0, l = 300, r = app.rightPanel ? 300 : 0, reRender = app.renderForEmail; delete app.renderForEmail; if (size === 5) { app.renderForEmail = true; } else if (size === 4) { w = 1920; h = 1080; } else if (size === 3) { w = 1280; h = 720; } else if (size === 2) { w = 768; h = 1024; } else if (size === 1) { w = 375; h = 667; } if(reRender && !app.renderForEmail || app.renderForEmail){ app.publishChanges(['content'].concat(app.parts.slice(1)), {}); } if (w && h) { var zoom = 1, ozoom = 1, width = window.innerWidth - l - r - 40; var ow = (w * 1); var oh = (h * 1); if (w > width) { zoom = (width / w); ozoom = (w / width); w = (w * ozoom); h = (h * ozoom); } app.stage.css({ 'margin-top': 0, '-moz-transform-origin': '0 0', '-webkit-transform-origin': '0 0', '-ms-transform-origin': '0 0' }); app.stage.animate({ width: ow + 'px', height: oh + 'px', 'transform': 'scale(' + zoom + ')', '-webkit-transform': 'scale(' + zoom + ')', }, function(e) { app.stage.find('div[style*="height: 100vh"], section[style*="height: 100vh;"]').addClass('caa_dynamic_height'); app.stage.byClass('caa_dynamic_height').css({ height: app.stage.elements[0].offsetHeight + 'px' }); app.Resize(false); app.stage.css({ //transform: '' // this fixes glitches but breaks actual screen zoom size }); }); if(oh < window.innerHeight){ app.stage.animate({'margin-top': ((window.innerHeight - oh) * 0.5) + 'px'}) } app.stage.setWidth = w; DOM(document.body).css({ overflow: 'hidden' }); } else { app.stage.css({ 'margin-top': 0, width: '', height: '', 'transform': '', '-webkit-transform': '' }); DOM(document.body).css({ overflow: '' }); app.stage.byClass('caa_dynamic_height').css({ height: '100vh' }); delete app.stage.setWidth; } app.execListeners('styles'); }; App.prototype.seo = function(into, type) { var app = this, siteURL = app.siteURL(); var content = DOM().new('div').addClass('caa_padding').appendTo(into).append(UI.Spinner('24').css({ 'padding-right': '20px' })) .append(DOM().new('span').class('ib middle').text('Getting full site map...')); app.publishSiteMap(function(siteMap) { content.removeClass('caa_padding').html(''); var tabsHolder = DOM().new('div').css({ 'background-color': '#d4d4d4', padding: '4px 20px 0 20px' }).appendTo(content), tabs = { pages: { title: 'Pages' }, migration: { title: 'Site URL Migration' } }, screens = { pages: function(into) { into.html(''); DOM().new('div').text('Each row displays the page title, meta description, url and the most used keywords on the page').appendTo(into); siteMap.forEach(function(page){ var data = page.data ? page.data : app.getFromPath(['content', page.section, page.p]); var row = DOM().new('div').class('caa_row caa_click caa_row_hover'); if(page.title){ row.append(DOM().new('div').text(page.title || '')); } else { row.append(DOM().new('div').css({color: 'red'}).text('Page title not set')); } if(data.meta || data.description){ row.append(DOM().new('div').text(data.meta || '')); } else { row.append(DOM().new('div').css({color: 'red'}).text('Meta description is not set')); } row.append(DOM().new('div').css({color:'#999'}).text(page.url || '')) var words = wordDensity(data); DOM().new('div').text(words).appendTo(row); row.appendTo(into).on('click', function(e){ if(page.publishFeed) { var feedPath = ('/feeds/'+page.publishFeed.split('/')[0]+'/items/'+page.publishFeed.split('/')[1]).substr(1).split('/'); console.log('feedpath', feedPath); app.render('/feeds/'+page.publishFeed, false, false); app.EditorPanel('FeedEditorItem', data, feedPath, DOM().new('div')); } else if(page.section && typeof page.p !== 'undefined') { app.render('/content'+page.internal, false, false); app.EditorPanel('page', data, ['content', page.section, page.p], DOM().id('page')); } }); }) }, migration: function(into) { into.html(''); var cachedURL = app.getLocalCacheItem(['seo','sitemap-url']) || ''; var form = DOM().new('form') .append(Inputs.text({ value: cachedURL, label: 'XML Sitemap URL' }).addClass('ibb middle').css({width: 'calc(100% - 50px)'})) .append(DOM().new('input').attr({type: 'submit'}).class('caa_button-default').val('GO')) .appendTo(into) .on('submit', function(e){ e.preventDefault(); form.attr({disabled: true}); results.html('').append(UI.Spinner(24)); var url = form.byTag('input').val() || ''; if(url && url.indexOf('.xml') && url.indexOf('http') === 0){ app.setLocalCache(['seo', 'sitemap-url'], url); app.get('/__get/sitemap/url:' + encodeURIComponent(url), { json: true }, function(data) { results.html(''); var stats = { good: 0, notgood: 0 } DOM().new('div').text('Non-Matching URL\'s').css({'font-weight': 'bold'}).appendTo(results); var notgood = DOM().new('div').appendTo(results); DOM().new('div').text('Matching URL\'s').css({'font-weight': 'bold','margin-top': '20px'}).appendTo(results); var good = DOM().new('div').appendTo(results); if(data.urls){ data.urls.forEach(function(url){ var oldURLpath = DOM().new('a').attr({href: url}).elements[0].pathname; if(oldURLpath.substr(-1) === '/') { oldURLpath = oldURLpath.substr(0, oldURLpath.length - 1); } if (oldURLpath) { var handled = ''; siteMap.forEach(function(page){ var urlPath = DOM().new('a').attr({href: page.url}).elements[0].pathname if(urlPath == oldURLpath){ handled = 'Matches page: '+urlPath } }); if (app.site.settings) { if (app.site.settings.redirects) { app.site.settings.redirects.forEach(function(item, i) { var go = false; if (item.from.indexOf('*') > -1) { var re = new RegExp(item.from.replace(/\*/, '\\S'), 'gi'); if (re.test(oldURLpath)) { go = true; } } else if (oldURLpath.substr(1).toLowerCase() == item.from.toLowerCase() || ((oldURLpath.substr(1) || '').split('?', 1)[0] || '').toLowerCase() == item.from.toLowerCase()) { go = true; } if (go) { handled = 'Redirects to: ' + item.to; } }); } } if(handled){ stats.good ++; DOM().new('div').text(url).css({'margin-top':'10px'}).appendTo(good); DOM().new('div').css({color: 'green'}).text(handled).appendTo(good); } else { stats.notgood ++; DOM().new('div').html('
'+url+'
').appendTo(notgood); } } }); if(!stats.notgood) { DOM().new('div').text('These URL\'s do not match any from your new site and if they are important should redirected to the correct URL').insertFirst(notgood); } } }); } else { results.html('Please enter a valid XML Sitemap URL'); } }); var results = DOM().new('div').css({padding: '20px 0'}).appendTo(into); if(cachedURL){ form.trigger('submit'); } } }; Object.keys(tabs).forEach(function(key) { var tab = tabs[key], addClassTab = tab.selected ? ' caa_rightPanelTabSelected' : ''; tab.content = DOM().new('div').class('caa_padding').css({display:'none'}).appendTo(content); tab.tab = DOM().new('div').class('ibb caa_rightPanelTab' + addClassTab) .append(DOM().new('span').css({ display: 'block', 'padding-top': '4px' }).text(tab.title)).appendTo(tabsHolder).on('click', function(e) { if (tab.selected) { return false; } else { for (var t in tabs) { if (t === key) { tabs[t].content.css({display: ''}); tabs[t].tab.addClass('caa_rightPanelTabSelected'); tabs[t].selected = true; screens[key](tab.content) } else { tabs[t].tab.removeClass('caa_rightPanelTabSelected'); tabs[t].selected = false; if(tabs[t].content){ tabs[t].content.css({display: 'none'}); } } } } }); }); tabs['pages'].tab.trigger('click'); }); var wordDensityLoopObject = function(obj, config){ for(var k in obj){ var type = typeof obj[k]; if(config.allowKeys.indexOf(k) > -1){ if(type === 'string' || type === 'number'){ config.str += obj[k] + ' '; } } else { if(type === 'object'){ if(config.depth <= config.maxDepth){ wordDensityLoopObject(obj[k], config); } } } } } var wordDensity = function(obj) { var config = { str: '', depth: 0, maxDepth: 100, allowKeys: ['title', 'body', 'subtitle', 'subbody','category', 'author', 'tag', 'tags', 'role', 'meta'], }; var stopWords = ['a','about','above','across','after','afterwards','again','against','all','almost','alone','along','already','also','although','always','am','among','amongst','amoungst','amount','an','and','another','any','anyhow','anyone','anything','anyway','anywhere','are','around','as','at','back','be','became','because','become','becomes','becoming','been','before','beforehand','behind','being','below','beside','besides','between','beyond','bill','both','bottom','but','by','call','can','cannot','cant','co','computer','con','could','couldnt','cry','de','describe','detail','do','done','down','due','during','each','eg','eight','either','eleven','else','elsewhere','empty','enough','etc','even','ever','every','everyone','everything','everywhere','except','few','fifteen','fify','fill','find','fire','first','five','for','former','formerly','forty','found','four','from','front','full','further','get','give','go','had','has','hasnt','have','he','hence','her','here','hereafter','hereby','herein','hereupon','hers','herse"','him','himse"','his','how','however','hundred','i','ie','if','in','inc','indeed','interest','into','is','it','its','itse"','keep','last','latter','latterly','least','less','ltd','made','many','may','me','meanwhile','might','mill','mine','more','moreover','most','mostly','move','much','must','my','myse"','name','namely','neither','never','nevertheless','next','nine','no','nobody','none','noone','nor','not','nothing','now','nowhere','of','off','often','on','once','one','only','onto','or','other','others','otherwise','our','ours','ourselves','out','over','own','part','per','perhaps','please','put','rather','re','same','see','seem','seemed','seeming','seems','serious','several','she','should','show','side','since','sincere','six','sixty','so','some','somehow','someone','something','sometime','sometimes','somewhere','still','such','system','take','ten','than','that','the','their','them','themselves','then','thence','there','thereafter','thereby','therefore','therein','thereupon','these','they','thick','thin','third','this','those','though','three','through','throughout','thru','thus','to','together','too','top','toward','towards','twelve','twenty','two','un','under','until','up','upon','us','very','via','was','we','well','were','what','whatever','when','whence','whenever','where','whereafter','whereas','whereby','wherein','whereupon','wherever','whether','which','while','whither','who','whoever','whole','whom','whose','why','will','with','within','without','would','yet','you','your','yours','yourself','yourselves']; wordDensityLoopObject(obj, config); var str = DOM().new('div').text(config.str || '').text().toLowerCase().replace(/[^a-z\-\ ]/g, ''); var wordAr = {}; str.split(' ').filter(function(word){ word = word.trim(); if(!word || word.length < 2){ return false; } if(stopWords.indexOf(word) > -1){ return false; } else { return word }; }).forEach(function(word){ if(!wordAr[word]){ wordAr[word] = 0; } wordAr[word]++; }); var ret = ''; Object.keys(wordAr).filter(function(word){ return wordAr[word] > 1 }).sort(function(a, b){ return wordAr[b] - wordAr[a]; }).forEach(function(word){ ret += word + ' (' + wordAr[word] + '), '; }) ret = ret.substr(0, ret.length -2); return ret; }; }; App.prototype.settings = function() { var app = this; app.stage.html(''); if (!hasSiteAccess(app.user.access, 'settings', true)) { app.stage.html('You do not have access to this section'); return false; } var appHeading = DOM().new('div') .class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text('Settings')) .appendTo(app.stage); var subSections = ['General', 'Domain', 'Social Accounts', 'Collaborators', 'Reviewers', 'Integrations', 'Widgets', 'Redirects', 'Private Pages', 'Download Site', 'API']; if (app.bluxapp) { subSections.push('Blux App'); } if (app.changed[0]) { subSections.forEach(function(subSection) { var sec = subSection.toString().toLowerCase().replace(' ', '-'); if (hasSiteAccess(app.user.access, 'settings/' + sec)) { DOM().new('a').id('nav-item-for-' + sec).class('caa_subNavItem') .append(DOM().new('div').class('ib middle caa_navItemText').text(subSection)) .attr({ href: '/' + app.parts[0] + '/' + sec }).appendTo(app.subNavContainer).on('click', function(e) { e.preventDefault(); app.render('/' + app.parts[0] + '/' + sec, false, false); }); } }); } var secTitle = 'General'; var box = DOM().new('div').class('caa_content').css({ //'padding-bottom': 'calc(100vh - 40px)' }); box.appendTo(app.stage); subSections.forEach(function(subSection, s) { var sec = subSection.toString().toLowerCase().replace(' ', '-'); if (app.parts[1] && app.parts[1] === sec || !app.parts[1] && sec === 'general') { DOM().byClass('caa_navItemText').class('caa_navItemText'); DOM().id('nav-item-for-' + sec).byClass('caa_navItemText').addClass('caa_navItemTextOn'); secTitle = subSection; if (hasSiteAccess(app.user.access, 'settings/' + sec)) { var secHolder = DOM().new('div').class('caa_padding').css({ padding: '16px 16px 32px 16px', position: 'relative' }).appendTo(box); var title = DOM().new('p').css({ padding: 0, margin: '0 0 10px 0' }).appendTo(secHolder); if (sec === 'general') { app.settingsSite(title, secHolder); } else if (sec === 'domain') { if (!app.site.domain || (app.site.domain && app.site.cnames && (app.site.cnames == 'www.' + app.site.domain || 'www.' + app.site.cnames == app.site.domain))) { app.settingsDomainsBasic(title, secHolder); } else { app.settingsDomainsAdvanced(title, secHolder); } } else if (sec === 'social-accounts') { app.settingsSocial(title, secHolder); } else if (sec === 'integrations') { app.settingsIntegrations(title, secHolder); } else if (sec === 'widgets') { app.settingsWidgets(title, secHolder); } else if (sec === 'collaborators') { app.settingsCollaborators(title, secHolder); } else if (sec === 'reviewers') { app.settingsReviewers(title, secHolder); } else if (sec === 'redirects') { app.settingsRedirects(title, secHolder); } else if (sec === 'private-pages') { app.settingsPrivatePages(title, secHolder); } else if (sec === 'backups') { app.settingsBackups(title, secHolder); } else if (sec === 'download-site') { app.settingsDownload(title, secHolder); } else if (sec === 'api') { app.settingsAPI(title, secHolder); } else if (sec === 'blux-app') { app.settingsBluxApp(title, secHolder); } } } }); appHeading.html('') .append(DOM().new('div').class('caa_heading ib middle').text(secTitle)) /* var checkHighlight = function(secID, goTo) { var secdom = byID('settings' + secID); if (secdom) { DOM().byClass('caa_navItemText').class('caa_navItemText'); DOM().id('nav-item-for-' + secID).byClass('caa_navItemText').addClass('caa_navItemTextOn'); if (goTo) { app.stage.scrollTo(DOM(secdom).pos().offsetTop - 20); } } }, pointsOfInterest = DOM().byClass('caa_sectionBar'); checkHighlight(app.parts[1], true); app.onScroll(function(e, scrollTop) { var found = false, i = 0; while (!found && i < pointsOfInterest.elements.length) { if (pointsOfInterest.elements[i].offsetTop > scrollTop - 100) { found = true; checkHighlight(pointsOfInterest.elements[i].id.replace('settings', ''), false); } i++; } }); */ }; App.prototype.settingsSite = function(title, into) { var app = this; var left = DOM().new('div').appendTo(into), right = DOM().new('div').css({ 'margin-top': '20px' }).appendTo(into); Inputs.text({ label: 'Site Name', value: app.site.name }).css({ 'max-width': '300px' }).appendTo(left).byTag('input').on('change', function(e) { var update = { name: DOM(e.target).val() }; app.siteUpdate([], update); }).attr({ 'data-find': 'sitename' }); Inputs.text({ label: 'Default Contact Email', value: app.site.email || '', type: 'email' }).css({ 'max-width': '300px', 'margin-top': '40px' }).appendTo(left).byTag('input').on('change', function(e) { var update = { email: DOM(e.target).val() }; app.siteUpdate([], update); }); var useCustomPageTitles = app.site.settings.pageTitles ? true : false; Inputs.checkbox({ value: useCustomPageTitles, label: 'Custom Page Titles', onchange: function(checked) { if (checked) { app.site.settings.pageTitles = { before: '', after: '' }; var update = { pageTitles: app.site.settings.pageTitles }; app.siteUpdate(['settings'], update); } else { app.site.settings.pageTitles = false; var update = { pageTitles: false }; app.siteUpdate(['settings'], update); } showPageTitleSection(); } }).css({ 'margin-top': '20px' }).appendTo(left); var pageTitlesSection = DOM().new('div').appendTo(left), showPageTitleSection = function() { pageTitlesSection.html(''); if (app.site.settings.pageTitles) { Inputs.text({ label: 'Before Page Title', value: app.site.settings.pageTitles.before || '', type: 'text' }).appendTo(pageTitlesSection).byTag('input').on('change', function(e) { var update = { before: DOM(e.target).val() || '' }; app.siteUpdate(['settings', 'pageTitles'], update); }).css({ 'margin-top': '20px' }); Inputs.text({ label: 'After Page Title', value: app.site.settings.pageTitles.after || '', type: 'text' }).appendTo(pageTitlesSection).byTag('input').on('change', function(e) { var update = { after: DOM(e.target).val() || '' }; app.siteUpdate(['settings', 'pageTitles'], update); }).css({ 'margin-top': '20px' }); } }; showPageTitleSection(); var src = ''; if (app.site.settings.favicon) { if (app.site.settings.favicon.media) { src = app.getFavIconFromMedia(app.site.settings.favicon.media); } } var favicon = DOM().new('img').css({ position: 'relative', 'z-index': 2, 'pointer-events': 'none' }), favicontest = DOM().new('img').css({ position: 'absolute', left: '-1000px', top: '-1000px', width: '20px', height: '20px' }).appendTo(app.stage); if (src) { favicon.elements[0].src = src; favicontest.attr({ src: src }); } setTimeout(function() { // listen after a bit so you can reload any uploads favicon.tries = 0; favicontest.on('error', function(e) { if (favicon.tries > 6) { return false; } setTimeout(function() { favicon.tries++; var gsrc = favicontest.attr('src'), newsrc = ''; if (gsrc) { gsrc = gsrc.split('?')[0]; favicon.attr({ src: gsrc }); } }, 1000); }).on('load', function(e) { favicon.css({ opacity: 1 }).attr({ src: favicontest.attr('src') }); mediaBox.byClass('caa_spinner').remove(); }); }, 300); var mediaBox = DOM().new('div').css({ position: 'relative', 'margin-top': '20px', width: '64px', height: '64px' }).append(favicon).append(DOM().new('div').class('caa_clickSecTarget').css({ 'background-image': checkered_background_gif, position: 'absolute', 'pointer-events': 'fill', top: 0, left: 0, width: '100%', height: '100%' })) .on('click', function(e) { app.MediaPicker(app.site.settings.favicon, ['settings', 'favicon'], UI.openModal(mediaBox), function(e, mediaSource) { if (mediaSource.media) { if (app.site.media[mediaSource.media]) { favicon.css({ opacity: 1 }).animate({ opacity: 0 }); UI.Spinner('64').css({ position: 'absolute', left: 0, top: 0, width: '64px', height: '64px', 'z-index': '3' }).appendTo(mediaBox); var mediaID = mediaSource.media + '', getPath = app.getFavIconFromMedia(mediaID), settingsFavicon = { favicon: { media: mediaID } }; setTimeout(function() { favicontest.elements[0].src = getPath; }, 10); app.siteUpdate(['settings'], settingsFavicon); } } UI.closeModal(); }, 'raster', e); }) .appendTo(left); DOM().new('label').class('caa_panelInputLabel').text('Favicon').appendTo(left); var url = app.siteURL(); var urls = [{ url: '/sitemap.xml', title: 'Sitemap' }]; for (var sec in app.site.content) { if (sec !== 'pages' && sec !== '__templates') { if (app.site.content[sec].length) { urls.push({ url: '/' + sec + '.xml', title: sec + ' RSS Feed' }); } } } urls.push({ url: '/robots.txt', title: 'robots.txt' }); urls.forEach(function(item, i) { var css = {}; if (i > 0) { css['margin-top'] = '20px'; } DOM().new('div').css(css) .append( DOM().new('a').attr({ href: url + item.url, target: '_blank' }).text(item.url) ) .append( DOM().new('label').class('caa_panelInputLabel').text(item.title) ) .appendTo(right); }); var hosting = app.site.settings.hosting || {}; if (typeof hosting !== 'object') { hosting = {}; } Inputs.checkbox({ value: hosting.hideFromSearch || false, label: 'Prevent entire site from being indexed by search engines', onchange: function(checked) { hosting.hideFromSearch = checked; app.siteUpdate(['settings'], { hosting: hosting }, true); } }).css({ 'margin-top': '20px' }).appendTo(right); }; App.prototype.settingsSocial = function(title, into) { var app = this; title.html('Add all of the social accounts relevant to this website that you will will want to link to or provide sharing links for.'); var inputContainer = DOM().new('div').appendTo(into), networkContainer = DOM().new('div').appendTo(into); app.subscribe('settings/social', function onchangeSocial() { inputContainer.html(''); var ops = [{ text: 'Select a Social Network', value: 's' }], hasNetworks = {}, select, inputHolder = DOM().new('span').css({ 'padding-top': '4px' }).appendTo(inputContainer); if (app.site.settings) { if (app.site.settings.social) { app.site.settings.social.forEach(function(item, i) { hasNetworks[item.network] = true; }); } } for (var networkKey in socialNetworks) { if (!hasNetworks[networkKey]) { ops.push({ text: socialNetworks[networkKey].name, value: networkKey }); } } select = Inputs.select(ops, 's').on('change', function(e) { inputHolder.html(''); var val = select.val(); if (socialNetworks[val]) { var spl = socialNetworks[val].url.split('{{name}}'); var textLeft = spl[0] || ''; var textRight = spl[1] || ''; DOM().new('form').append( DOM().new('span').text(textLeft) ).append( Inputs.text({ label: 'Enter ' + socialNetworks[val].name + ' Name' }).css({ width: '300px' }) ).append( DOM().new('input').class('caa_button-default').css({ 'padding-left': '4px' }).attr({ type: 'submit', value: 'Add Social Network' }) ).on('submit', function(e) { e.preventDefault(); var socialAdd = { network: val, account: inputHolder.find('input').val() }; if (!app.site.settings.social) { app.siteUpdate(['settings'], { social: [socialAdd] }); app.execListeners('settings'); } else { app.siteAdd(['settings', 'social'], socialAdd); } }).appendTo(inputHolder); } }).appendTo(inputContainer); networkContainer.html(''); if (app.site.settings) { if (app.site.settings.social) { app.site.settings.social.forEach(function(item, i) { DOM().new('div').class('caa_row caa_row_edge caa_row_hover').appendTo(networkContainer) .append(DOM().new('span').class('ib middle').css({ 'min-width': '180px' }).text(socialNetworks[item.network].surl + (item.account || '')).css({ 'margin-right': '10px' })) .append( DOM().new('button').class('caa_button-delete').on('click', function(e) { app.siteDelete(['settings', 'social', i]); app.execListeners('settings/social'); }).css({ position: 'absolute', right: '-10px', top: '6px' }) ); }); } } }); }; App.prototype.settingsIntegrations = function(title, into) { var app = this; title.html('Add any 3rd party integrations, modules or utilities that you wish to include in your site.'); var ops = [{ text: 'Select an Integration to Add', value: 'default' }], availOps = [{ text: 'Google Search Console/Webmaster Tools Verification', value: 'googleWebmasterVerifySite' }, { text: 'Bing Webmaster Tools', value: 'bingWebmasterVerifySite' }, { text: 'Pinterest Site Verification', value: 'pinterestVerifySite' }, { text: 'Facebook Insights', value: 'facebookVerifySite' }, { text: 'Twitter Remarketing', value: 'twitterRemarketing', multi: true }, { text: 'Page Integration/Custom Scripts', value: 'pageScripts', multi: true }], integrations = app.site.settings.integrations || {}; availOps.forEach(function(op) { if (integrations[op.value] === undefined) { ops.push(op); } }); var integrationHolder = DOM().new('div').appendTo(into); var renderIntegrations = function() { integrationHolder.html(''); if (ops.length > 1) { var select = Inputs.select(ops, 'default').addClass('ib middle').on('change', function(e) { var value = select.val(), updatePath = ['settings'], update = {}; if (value !== 'default' && value) { update[value] = {}; if (typeof app.site.settings.integrations !== 'object') { update = { integrations: update }; } else { updatePath.push('integrations'); } app.siteUpdate(updatePath, update); integrations[value] = {}; renderIntegrations(); } }).appendTo(integrationHolder); } Inputs.text({ label: 'Google Analytics', value: app.site.settings.googleAnalytics || '', type: 'text', explain: 'You may enter one or more google analytics ID\'s separated by spaces or commas. Do not paste the entire script here. Only use the ID provided by google that looks like UA-XXXXXXXX' }) .appendTo(integrationHolder).css({ 'margin-top': '60px' }).byTag('input').on('change', function(e) { var update = { googleAnalytics: DOM(e.target).val() }; app.siteUpdate(['settings'], update); }); Inputs.checkbox({ label: 'Make Google/Typekit Fonts Blocking', explain: 'By default (unchecked) Blux will load fonts asynchronously. This makes the web page render as fast as possible and then displays text with the custom fonts when they are downloaded/ready. The default setting is a better experience for site visitors on slow devices or internet connections. Enabling this setting will prevent the page from loading until the fonts are ready which sacrifices speed for beauty and prevents the flash of unstyled text (FOUT). Enabling this setting will also reduce your google pagespeed score.', value: app.site.settings && app.site.settings.fonts && app.site.settings.fonts.blocking, onchange: function(chkd) { var update = {}, updatePath = ['settings']; if (app.site.settings.fonts) { updatePath.push('fonts'); update.blocking = chkd; } else { update = { fonts: { blocking: chkd } }; } app.siteUpdate(updatePath, update, true); } }) .appendTo(integrationHolder).css({ 'margin-top': '20px' }); availOps.forEach(function(op) { if (integrations[op.value] !== undefined) { if (app['integrations_' + op.value]) { var holder = DOM().new('div').css({ 'margin-top': '0px', border: 0, position: 'relative' }).class('caa_row caa_row_edge').appendTo(integrationHolder); if (!op.multi || Object.keys(app.site.settings.integrations[op.value]).length < 2) { // we only show this delete if the item has only 1 sub item or isn't a multi item integration DOM().new('button').class('caa_button-delete').css({ position: 'absolute', right: 0, top: 0 }).on('click', function(e) { app.siteDelete(['settings', 'integrations', op.value]); setTimeout(function() { delete integrations[op.value]; renderIntegrations(); }, 10) }).appendTo(holder); } var into = DOM().new('div').appendTo(holder); app['integrations_' + op.value](into); } } }); }; renderIntegrations(); }; App.prototype.settingsWidgets = function(title, into) { var app = this; title.html('Enable customizable widgets to all or individual pages of your site.'); var widgetHolder = DOM().new('div').appendTo(into); var renderWidgets = function() { widgetHolder.html(''); app.getTemplates(function(templates) { var ops = [{ text: 'Select a Widget to Add', value: 'default' }].concat(Object.keys(templates.media).filter(function(mediaID) { return templates.media[mediaID] && templates.media[mediaID].type === 'custom' }).map(function(mediaID) { return { text: 'Blux: ' + (templates.media[mediaID].name || 'No Title Set'), value: mediaID }; })).concat(Object.keys(app.site.media).filter(function(mediaID) { return app.site.media[mediaID] && app.site.media[mediaID].type === 'custom' }).map(function(mediaID) { return { text: app.site.media[mediaID].name || 'No Title Set', value: mediaID }; })); var select = Inputs.select(ops, 'default').addClass('ib middle').on('change', function(e) { var value = select.val(), updatePath = ['settings'], update = {}; if (value !== 'default' && value) { var update = {}; if (!app.site.media[value]) { app.siteUpdate(['media', value], templates.media[value]); } update[uuid()] = { media: value }; app.siteUpdate(['settings', 'widgets'], update); renderWidgets(); } }).insertFirst(widgetHolder); }); if (app.site.settings.widgets) { Object.keys(app.site.settings.widgets).forEach(function(widgetID) { var widget = app.site.settings.widgets[widgetID]; if (widget.media && app.site.media[widget.media]) { var mediaRef = app.site.media[widget.media] || 'No Title Set'; var row = DOM().new('div').class('caa_row caa_row_edge caa_row_hover caa_click').appendTo(widgetHolder) .append(DOM().new('span').class('ib middle').text(mediaRef.name || 'No Title Set')) .append(DOM().new('span').class('ibb middle').append( Inputs.checkbox({ label: 'Apply To Every Page', value: widget.allPages, onchange: function(chkd) { app.siteUpdate(['settings', 'widgets', widgetID], { allPages: chkd }, true); } }) )) .append(DOM().new('button').class('ibb middle caa_button-default').text('Configure').on('click', function(e) { app.MediaPicker(widget, ['settings', 'widgets', widgetID], UI.openModal(row), function(e, mediaSource) { if (mediaSource) { app.siteUpdate(['settings', 'widgets', widgetID], mediaSource, true); } UI.closeModal(); renderWidgets(); }, 'widget', e); })) } }) } }; renderWidgets(); }; App.prototype.settingsCollaborators = function(title, into) { var app = this; title.html('Invite collaborators to help manage your site. Provide full administrative or limited access to your site.'); var inputContainer = DOM().new('div').appendTo(into), collabContainer = DOM().new('div').appendTo(into), hasCollabs = {}, collabBox = DOM().new('div').class('ib middle').css({ position: 'relative', }), collabInput = Inputs.text({ type: 'email', label: 'Email Address', autocomplete: 'off' }).css({ 'width': '200px', 'margin-right': '10px' }).appendTo(collabBox).byTag('input').id('caa-add-collaborator-email').attr({ autocomplete: 'off' }).on('focus input blur', function(e) { if (e.type === 'input') { var search = collabInput.val() || '', l = 0; collabInput.hints.byClass('caa_row').elements.forEach(function(element) { var el = DOM(element); if (!search || el.text().match(search)) { el.css({ display: '' }); l++; } else { el.css({ display: 'none' }); } }); collabInput.sizer(l); } else if (e.type === 'focus') { collabInput.hints = DOM().newOrFind('div', 'tag-input-hints').css({ position: 'absolute', left: 0, right: 0, top: collabBox.elements[0].offsetHeight + 'px', 'box-shadow': '0px 1px 4px #999', 'z-index': 2, 'max-height': 0, 'overflow-x': 'hidden', 'overflow-y': 'auto', 'background-color': '#fff' }).html('').appendTo(collabBox); collabInput.hintsLength = 0; app.collabHints().forEach(function(tag) { DOM().new('div').class('caa_row caa_row_hover caa_click').css({ padding: '6px' }).text(tag).appendTo(collabInput.hints).on('click', function(e) { collabInput.val(tag).trigger('change'); }); collabInput.hintsLength++; }); collabInput.sizer = function(l) { if (l > 10) { l = 10; } collabInput.hints.animate({ 'max-height': (l * 34) + 'px' }); }; collabInput.sizer(collabInput.hintsLength); } else if (e.type === 'blur') { collabInput.hints.animate({ 'max-height': 0 }, function(e) { DOM(e.target).remove(); }); } }); DOM().new('form').append( collabBox ).append( DOM().new('input').class('caa_button-default').css({ 'margin-left': '4px' }).attr({ type: 'submit', value: 'Add Collaborator' }) ).on('submit', function(e) { e.preventDefault(); var email = (DOM().id('caa-add-collaborator-email').val() || '').toLowerCase().replace(/ /g, '').trim(), collabAdd = { email: email, admin: true, }; if (validEmail(email) && !hasCollabs[email]) { if (!app.site.settings.collaborators) { app.siteUpdate(['settings'], { collaborators: [collabAdd] }); app.execListeners('settings'); } else { app.siteAdd(['settings', 'collaborators'], collabAdd); } } else { DOM().id('caa-add-collaborator-email').val(''); } }).appendTo(inputContainer); var addInput = function(name, path, paths, indent, into) { var pathjoin = path.join('/'), checked = paths.indexOf(pathjoin) > -1; var input = Inputs.checkbox({ value: checked, label: name, onchange: function(val) { var disp = val ? 'none' : '', pjl = pathjoin.length; into.byTag('input').elements.forEach(function(element) { if (element.name.substr(0, pjl) === pathjoin && element.name !== pathjoin) { element.parentNode.style.display = disp; element.checked = false; } }); } }).css({ padding: '5px 0 5px ' + (indent * 16) + 'px' }).appendTo(into).byTag('input').attr({ name: pathjoin }); if (checked) { setTimeout(function() { input.trigger('change'); }, 10); } }; app.subscribe('settings/collaborators', function onchangeCollabs() { collabContainer.html(''); if (app.site.settings) { if (app.site.settings.collaborators) { hasCollabs = {}; var requestImagesByEmail = []; app.site.settings.collaborators.forEach(function(item, i) { hasCollabs[item.email] = true; requestImagesByEmail.push(item.email); var row = DOM().new('div').class('caa_row caa_row_edge caa_row_hover caa_click').appendTo(collabContainer) .append(DOM().new('span').class('ib middle caa_profile').attr({ 'collab-email': item.email }).css({ 'margin-right': '8px', 'background-image': ca_config.def_profile })) .append(DOM().new('span').class('ib middle').text(item.email)) .on('click', function(e) { var modal = UI.openModal(row), modalContent = DOM().new('div').class('caa_padding').appendTo(modal), name = DOM().new('div').text(item.email).appendTo(modalContent), save = DOM().new('button').class('caa_button-default').text('Save Settings').css({ 'margin': '10px 0' }).appendTo(modalContent).on('click', function(e) { var paths = []; boxes.byTag('input').elements.forEach(function(element) { if (element.checked) { paths.push(element.name); } }); app.siteUpdate(['settings', 'collaborators', i], { paths: paths, admin: DOM().id('collab-' + i + '-admin').byTag('input').elements[0].checked }); UI.closeModal(); }), explain = DOM().new('div').css({ padding: '10px 0' }).text( ['Select the sections or sub-sections that this user will be able to view and change. Selecting a section automatically includes all sub-sections. Administrators get full access to the site.'] .join(' ') ).appendTo(modalContent), admin = Inputs.checkbox({ value: item.admin, label: 'Administrator', onchange: function(val) { if (val) { boxes.byTag('div').css({ display: 'none' }); } else { boxes.byTag('div').css({ display: '' }); } } }).id('collab-' + i + '-admin').appendTo(modalContent), boxes = DOM().new('div').appendTo(modalContent), delButton = UI.deleteButton('Remove Collaborator', 'button', function(e) { app.siteDelete(['settings', 'collaborators', i]); app.execListeners('settings/collaborators'); UI.closeModal(); }).appendTo(modalContent).css({ 'margin-top': '100px' }); app.checkBilling(function(billingOK) { console.log('billing ok', billingOK); if (billingOK !== '199') { DOM().new('div').css({ padding: '20px 0' }).html('Upgrade to a
premium subscription
to be able to choose which areas of the app and site that a collaborator may access.') .appendTo(boxes).byTag('a').attr({ href: '/billing/' + app.site.id }).on('click', function(e) { e.preventDefault(); app.render('/billing/' + app.site.id, false, false); UI.closeModal(); }) } else { if (!Array.isArray(item.paths)) { item.paths = []; } addInput('Hub', ['hub'], item.paths, 0, boxes); addInput('Analytics', ['hub/analytics'], item.paths, 1, boxes); addInput('Submissions', ['hub/submissions'], item.paths, 1, boxes); addInput('Recommendations', ['hub/recommendations'], item.paths, 1, boxes); addInput('Changes', ['hub/changes'], item.paths, 1, boxes); addInput('Quality Assurance', ['hub/quality'], item.paths, 1, boxes); addInput('SEO', ['hub/seo'], item.paths, 1, boxes); addInput('Localization', ['i18n'], item.paths, 1, boxes); addInput('Usages', ['hub/usage'], item.paths, 1, boxes); addInput('Storage', ['hub/storage'], item.paths, 1, boxes); addInput('Publish Site', ['publish'], item.paths, 0, boxes); addInput('Publish Content', ['publish/content'], item.paths, 0, boxes); addInput('All Content', ['content'], item.paths, 0, boxes); Object.keys(app.site.content).forEach(function(sec) { if (app.site.content[sec].length) { addInput(sec.capitalizeFirstLetter(), ['content', sec], item.paths, 1, boxes); app.site.content[sec].forEach(function(page, p) { addInput(page.title || 'no title', ['content', sec, p], item.paths, 2, boxes); }); } }); addInput('Navigation', ['navigation'], item.paths, 0, boxes); if (app.site.navigation) { if (app.site.navigation.length) { app.site.navigation.forEach(function(nav, navIndex) { addInput(nav._label || 'navigation ' + navIndex, ['navigation', navIndex], item.paths, 1, boxes); }); } } addInput('Footer', ['footer'], item.paths, 0, boxes); if (app.site.footer) { if (app.site.footer.length) { app.site.footer.forEach(function(nav, navIndex) { addInput(nav._label || 'footer ' + navIndex, ['footer', navIndex], item.paths, 1, boxes); }); } } addInput('Feeds', ['feeds'], item.paths, 0, boxes); if (app.site.feeds) { Object.keys(app.site.feeds).forEach(function(feedID) { addInput(app.site.feeds[feedID].name, ['feeds', feedID], item.paths, 1, boxes); }); } addInput('Media/Custom Elements', ['media'], item.paths, 0, boxes); if (app.site.media) { Object.keys(app.site.media).forEach(function(mediaID) { if (app.site.media[mediaID].type === 'custom') { addInput(app.site.media[mediaID].name, ['media', mediaID], item.paths, 1, boxes); } }); } addInput('Files', ['files'], item.paths, 0, boxes); addInput('Design', ['styles'], item.paths, 0, boxes); addInput('Default Colors', ['styles/defaults'], item.paths, 1, boxes); addInput('Typography', ['styles/text'], item.paths, 1, boxes); addInput('Links & Buttons', ['styles/buttons'], item.paths, 1, boxes); addInput('Block Defaults', ['styles/blocks'], item.paths, 1, boxes); addInput('Iconography', ['styles/icons'], item.paths, 1, boxes); addInput('Form Elements', ['styles/forms'], item.paths, 1, boxes); addInput('Links & Buttons', ['styles/buttons'], item.paths, 1, boxes); addInput('Tabs', ['styles/tabs'], item.paths, 1, boxes); addInput('Settings', ['settings'], item.paths, 0, boxes); addInput('Social Accounts', ['settings/social'], item.paths, 1, boxes); addInput('Collaborators', ['settings/collaborators'], item.paths, 1, boxes); addInput('Redirects', ['settings/redirects'], item.paths, 1, boxes); addInput('Integrations', ['settings/integrations'], item.paths, 1, boxes); addInput('Widgets', ['settings/widgets'], item.paths, 1, boxes); admin.byTag('input').trigger('change'); } }) }); }); app.Request({ do: 'request', request: 'getProfileImages', emails: requestImagesByEmail }, function(data) { if (data.imagesFor) { Object.keys(data.imagesFor).forEach(function(email) { collabContainer.find('span[collab-email="' + email + '"]').css({ 'background-image': 'url(' + data.imagesFor[email] + ')' }); }); } }); } } }); }; App.prototype.settingsReviewers = function(title, into) { var app = this; title.html('Invite reviewers to provide feedback on your staging site. All reviewer feedback can be accessed within those specific pages in the Content section of the Blux app.'); var inputContainer = DOM().new('div').appendTo(into), collabContainer = DOM().new('div').appendTo(into), hasCollabs = {}, collabBox = DOM().new('div').class('ib middle').css({ position: 'relative', }), collabInput = Inputs.text({ type: 'email', label: 'Email Address', autocomplete: 'off' }).css({ 'width': '200px', 'margin-right': '10px' }).appendTo(collabBox).byTag('input').id('caa-add-reviewer-email').attr({ autocomplete: 'off' }).on('focus input blur', function(e) { app.tagHintsEvent(e, collabInput, collabBox, function(e) { }, 'collabHints'); }); DOM().new('form').append( collabBox ).append( DOM().new('input').class('caa_button-default').css({ 'margin-left': '4px' }).attr({ type: 'submit', value: 'Add Reviewer' }) ).on('submit', function(e) { e.preventDefault(); var email = (DOM().id('caa-add-reviewer-email').val() || '').toLowerCase().replace(/ /g, '').trim(), collabAdd = { id: uuid(), email: email }; if (validEmail(email) && !hasCollabs[email]) { if (!app.site.settings.reviewers) { app.siteUpdate(['settings'], { reviewers: [collabAdd] }); app.execListeners('settings'); } else { app.siteAdd(['settings', 'reviewers'], collabAdd); } } else { DOM().id('caa-add-reviewer-email').val(''); } }).appendTo(inputContainer); app.subscribe('settings/reviewers', function onchangeCollabs() { collabContainer.html(''); if (app.site.settings) { if (app.site.settings.reviewers) { hasCollabs = {}; var requestImagesByEmail = []; app.site.settings.reviewers.forEach(function(item, i) { hasCollabs[item.email] = true; requestImagesByEmail.push(item.email); var row = DOM().new('div').class('caa_row caa_row_edge caa_row_hover caa_click').appendTo(collabContainer) .append(DOM().new('span').class('ib middle caa_profile').attr({ 'collab-email': item.email }).css({ 'margin-right': '8px', 'background-image': ca_config.def_profile })) .append(DOM().new('span').class('ib middle').text(item.email)) .on('click', function(e) { var modal = UI.openModal(row), modalContent = DOM().new('div').class('caa_padding').appendTo(modal), name = DOM().new('div').text(item.email).appendTo(modalContent); DOM().new('div').text('Reviewer link:').appendTo(modalContent).css({ 'margin-top': '20px' }); var reviewLink = app.stagingURL() + '?blux-review=' + item.id; DOM().new('div').append(DOM().new('a').text(reviewLink).attr({ href: reviewLink, target: '_blank' })).appendTo(modalContent); DOM().new('div').text('This link is unique and enables whomever opens the link in their browser to browse the staging site and provide feedback. Send this link only to those you want to provide feedback as ' + item.email).appendTo(modalContent); UI.deleteButton('Remove Reviewer', 'button', function(e) { app.siteDelete(['settings', 'reviewers', i]); app.execListeners('settings/reviewers'); UI.closeModal(); }).appendTo(modalContent).css({ 'margin-top': '100px' }) }); }); app.Request({ do: 'request', request: 'getProfileImages', emails: requestImagesByEmail }, function(data) { if (data.imagesFor) { Object.keys(data.imagesFor).forEach(function(email) { collabContainer.find('span[collab-email="' + email + '"]').css({ 'background-image': 'url(' + data.imagesFor[email] + ')' }); }); } }); } } }); }; App.prototype.settingsRedirects = function(title, into) { var app = this; title.html('Redirect from one URL to another. You may use ? as a single character wildcard or * as a zero or more character wildcard.'); var inputContainer = DOM().new('div').appendTo(into), listContainer = DOM().new('div').appendTo(into); var ops = [{ text: 'Permanent', value: 'permanent' }, { text: 'Temporary', value: 'temporary' }], urlFromBox = DOM().new('div').class('ib').css({ width: '200px', margin: '5px 10px 5px 0' }).append(Inputs.text({ label: 'URL From' })), urlFromInput = urlFromBox.byTag('input'), urlToBox = DOM().new('div').class('ib').css({ width: '200px', margin: '5px 10px 5px 0' }).append(Inputs.text({ label: 'URL To' })), urlToInput = urlToBox.byTag('input'); DOM().new('form').append( urlFromBox ).append( urlToBox ).append( DOM().new('div').class('ib').css({ width: '200px', margin: '5px 10px 5px 0' }).append(Inputs.select(ops, 'Permanent').css({ 'padding-left': '4px', 'margin-right': '10px' }).id('caa-add-redirect-type')) ).append( DOM().new('input').class('caa_button-default').css({ 'margin-left': '4px' }).attr({ type: 'submit', value: 'Add Redirect' }) ).on('submit', function(e) { e.preventDefault(); var from = cleanRedirectURL(urlFromInput.val()); var to = cleanRedirectURL(urlToInput.val()); if (from && from != to) { var redirectAdd = { from: from, to: to, type: DOM().id('caa-add-redirect-type').val() }; if (!app.site.settings.redirects) { app.siteUpdate(['settings'], { redirects: [redirectAdd] }); app.execListeners('settings'); } else { app.siteAdd(['settings', 'redirects'], redirectAdd); app.execListeners('settings/redirects'); } urlFromInput.val(''); urlToInput.val(''); } }).appendTo(inputContainer); var cleanRedirectURL = function(url) { if (typeof url != 'string' || !url) { return ''; } while (url.substr(0, 1) === '/') { url = url.substr(1); } return url; }; var genRow = function(item, i) { var topre = ''; if (item.to.indexOf('http') !== 0) { topre = '/'; } var row = DOM().new('div').class('caa_row').css({ 'padding': '10px 40px 10px 10px' }) .append( DOM().new('span').text('From: /' + item.from + ' To: ' + topre + item.to + ' (' + item.type + ')') ) .append( DOM().new('button').class('caa_button-delete').on('click', function(e) { app.siteDelete(['settings', 'redirects', i]); app.execListeners('settings/redirects'); }).css({ position: 'absolute', right: 0, top: 0 }) ); return row; }; app.subscribe('settings/redirects', function onchangeRedirects() { listContainer.html(''); if (app.site.settings) { if (app.site.settings.redirects) { app.site.settings.redirects.forEach(function(item, i) { genRow(item, i).appendTo(listContainer); }); } } }); }; App.prototype.settingsPrivatePages = function(title, into) { var app = this, passwordList = {}, hasPasswords = false; title.html('Password protect pages, sections or your entire website.'); var secContent = DOM().new('div').appendTo(into); app.siteMap().forEach(function(item) { var pageRef = app.site.content[item.section][item.p]; if (pageRef.passwords) { var pwList = Object.keys(pageRef.passwords); if (pwList.length) { hasPasswords = true; DOM().new('div').class('caa_row').css({ 'padding-top': '10px' }) .append( DOM().new('span').text('URL: ' + item.url + ' ' + pwList.length + ' password(s)') ) .append( DOM().new('button').class('caa_button-default').text('Manage').css({ 'margin-left': '10px' }).on('click', function(e) { app.render('/content' + item.internal); }) ).appendTo(secContent); } } }); if (!hasPasswords) { secContent.text('You do not have any passwords enabled on your site.'); } }; App.prototype.settingsBackups = function(title, into) { var app = this; title.html('How often do you want to back up your website. Optionally have your website backus be emailed to you or transfered to a location of your choice.'); DOM().new('div').text('This feature is currently unavailable').appendTo(into); }; App.prototype.settingsDownload = function(title, into) { var app = this; title.html('Download your
published
site and all media into a single zip file.'); var use_blux_media = Inputs.checkbox({ value: true, label: 'Use Blux CDN for responsive image sizes (uses media files from blux servers instead of downloading)' }).css({ 'margin': '20px 0' }).appendTo(into); var use_folders = Inputs.checkbox({ value: true, label: 'Use folders/index.html file structure for URL compatability with most hosting providers' }).css({ 'margin': '20px 0' }).appendTo(into); var downloadHolder = DOM().new('div').appendTo(into); var downloadSite = DOM().new('button').class('caa_button-default').text('Download Site').appendTo(downloadHolder).on('click', function(e) { downloadHolder.byClass('tmp-error').remove(); UI.Spinner().insertAfter(downloadSite).css({ 'margin-left': '10px' }); DOM(e.target).attr({ disabled: true }).text('Downloading...'); app.Request({ do: 'request', request: 'downloadSite', key: Date.now(), timeout: 240000, blux_cdn: use_blux_media.byTag('input').elements[0].checked, folders: use_folders.byTag('input').elements[0].checked }, function(data) { DOM(e.target).attr({ disabled: false }).text('Download Site'); downloadHolder.byClass('caa_spinner').remove(); if (data.error) { DOM().new('div').css({ color: 'red' }).class('tmp-error').text(data.error).appendTo(downloadHolder); } if (data.downloadURL) { window.open(data.downloadURL, '_blank'); DOM().new('div').class('tmp-error').css({ 'margin-top': '20px' }).html('Your site is now
available for download
').appendTo(downloadHolder); } }); }); }; App.prototype.settingsAPI = function(title, into) { var app = this; title.html(['The API enables you to create or use custom software to manage all aspects of your site for integration into your existing workflow or for automation needs.', 'The data below is a visual representation of the JSON data that makes up your entire site. Please proceed with caution.' ].join(' ')); var apiHolder = DOM().new('div').id('jsone').appendTo(into); DOM().new('button').class('caa_button-default').text('SHOW API').on('click', function(e) { loadAPI(); DOM(e.target).remove(); }).appendTo(into); var loadAPI = function() { DOM().new('div').insertBefore(apiHolder).css({ padding: '10px', color: 'white', 'background-color': 'red', 'font-weight': 'bold' }).text('This API gives you complete control to change or totally break your site. Proceed with caution!') loadScript('https://rawgit.com/pleaseshutup/jsone/master/dist/jsone.min.js', function(e) { var jsonapi = new jsone({ node: document.getElementById('jsone'), json: JSON.parse(JSON.stringify(app.site)), schema: 'https://cdn.blux.com/sites/schema-v0.json', jsonName: 'site' }); var savejson = DOM().new('button').class('caa_button-default').text('Save Changes').on('click', function(e) { savejson.attr({ disabled: true }).text('Queuing Changes...') jsonapi.getChanges().forEach(function(change) { if (change.path.length > 0) { if (typeof value !== 'object') { var key = change.path.splice(-1), updatePath = change.path.slice(0, -1); var update = {}; update[key] = change.value; app.siteUpdate(change.path, update); } else { app.siteSet(change.path, change.value); } } }) setTimeout(function() { savejson.attr({ disabled: false }).text('Save Changes') }, 500) }).appendTo(DOM().new('div').css({ 'margin-bottom': '40px' }).insertAfter(apiHolder)); }) }; DOM().new('button').class('caa_button-default').text('reload site').on('click', function(e) { app.send({ do: 'checkSite', id: app.site.id, revision: app.site.revision, updated: app.site.updated, forceUpdate: true, getMedia: true }); }).css({ 'margin-left': '4px' }).appendTo(into); }; App.prototype.settingsBluxApp = function(title, into) { var app = this; console.log('exec blux app'); if (!app.bluxapp) { DOM().new('div').text('This section is only available when using the blux desktop app').appendTo(into); return false; } title.html('Settings for the blux app.'); var settings = DOM().new('div').appendTo(into); app.listeners.bluxAppConfig = function(msg) { settings.html('
' + JSON.stringify(msg, null, 2) + '
'); } app.bluxapp.send('blux', JSON.stringify({ do: 'getConfig' })); DOM().new('button').class('caa_button-default').text('Set Local Directory').appendTo(into).on('click', function(e) { app.bluxapp.send('blux', JSON.stringify({ do: 'setLocalFolder' })); }); }; App.prototype.settingsDomainsBasic = function(title, into) { var app = this; var url = app.siteURL(true), stagingURL = app.stagingURL(), domainSec = DOM().new('div').appendTo(into); title.html('Staging site URL:
' + stagingURL + '
\ Live site URL:
' + url + '
\
Use Your Domain Name:
'); var getDomainInfo = function() { domainInstructions.html(''); if (app.site.domain) { UI.Spinner().appendTo(domainInstructions); DOM().new('span').text('Looking up domain information to provide instructions...').appendTo(domainInstructions); var primary, secondary, sslInfo, complete = function() { if (primary && secondary && sslInfo) { domainInstructions.html(''); DOM().new('div').text('DNS Instructions for ' + secondary.domain).css({ 'margin-top': '20px', 'font-weight': 'bold' }).appendTo(domainInstructions); domainInstructions.append(setDomainInstructions(primary).css({ 'margin-top': '10px' })); domainInstructions.append(setDomainInstructions(secondary).css({ 'margin-top': '10px' })); DOM().new('div').css({'margin-top': '10px'}).html('Please note that whenever you make changes to your domain\'s DNS settings that they can be either instantanious or could take a few hours to update. If you think your settings are correct and our instructions here keep telling you that they are wrong then please wait a bit and try again. You can always email
support@blux.com
for help.').appendTo(domainInstructions); DOM().new('button').class('caa_button-default').css({ 'margin-top': ' 10px' }).text('Check My Domain DNS Settings Again').on('click', getDomainInfo).appendTo(domainInstructions); if (!sslInfo.certificate && domainInstructions.text().indexOf('Correctly points to h.blux.com') > -1) { console.log('ssl request out'); app.Request({ do: 'request', request: 'setSSL', automatic: true }, function(data) { console.log('ssl request done', data); if (data.accepted) { DOM().new('div').text('An automatic SSL certificate was provisioned for this domain and will automatically renew as long as the domain is pointing to Blux.').css({'margin-top':'10px'}).appendTo(domainInstructions) } }); } } } app.Request({ do: 'request', request: 'domainInfo', domain: app.site.domain }, function(data) { primary = data; complete(); }); app.Request({ do: 'request', request: 'domainInfo', domain: app.site.cnames }, function(data) { secondary = data; complete(); }); app.Request({ do: 'request', request: 'checkSSL' }, function(data) { sslInfo = data; complete(); }); } }, setDomainInstructions = function(data) { var ok = false, dnsReason = 'Failed to lookup domain information', redirectReason = '', apex = data.domain.indexOf('www.') !== 0, redirectTo = '', redirectOK = false; if (data.headers) { redirectTo = (data.headers.location || ''); if (redirectTo.substr(-1) === '/') { redirectTo = redirectTo.substr(0, redirectTo.length - 1); } if (redirectTo.substr(0, 4) === 'http') { redirectTo = redirectTo.split('//')[1]; } if (redirectTo === 'www.' + data.domain || redirectTo === app.site.domain) { redirectOK = true; } } if (apex) { if (ca_config.blux_ips.indexOf(data.ip) > -1) { ok = true; dnsReason = data.domain + ' Correctly points to ' + data.ip; } else { if (!redirectOK) { dnsReason = data.domain + ' currently points to ' + data.ip + '.
In your DNS settings the setting for "@" should be an A record that points to ' + ca_config.blux_ips.join(' and an additional row for "@" that points to ') + '
'; } else { ok = true; dnsReason = ' '; } } } else { if (data.cname == 'h.blux.com') { ok = true; dnsReason = 'Correctly points to ' + data.cname; } else { if (data.cname) { dnsReason = data.domain + ' incorrectly points to ' + data.cname + '
In your DNS settings the setting for "www" should be a CNAME record that points to h.blux.com
'; } else if (data.ip) { dnsReason = data.domain + ' is not a CNAME pointed to h.blux.com
In your DNS settings the setting for "www" should be a CNAME record that points to h.blux.com
'; } else { dnsReason = 'There was an error checking the dns information for ' + data.domain; } } } if (redirectTo) { if (redirectOK) { if (redirectTo !== data.domain) { redirectReason += '
Redirects correctly to ' + data.headers.location + '
'; } } else { ok = false; redirectReason += '
Redirects incorrectly to ' + data.headers.location + ' and should be configured to redirect to the primary domain ' + app.site.domain + '
'; } } var color = ok ? 'green' : 'red'; return DOM().new('div').html('
' + dnsReason + '
' + redirectReason); }; var domainInputSection = DOM().new('div').appendTo(into); var primaryDomainForm = DOM().new('form').appendTo(domainInputSection).on('submit', function(e) { e.preventDefault(); var input = primaryDomainInput.byTag('input'); primaryDomainForm.attr({ disabled: true }); UI.Spinner().appendTo(primaryDomainInputStatus).css({ 'margin-left': '10px' }); var domain = reallyCleanDomain(input.val()); input.val(domain); if (!domain || validDomain(domain)) { app.Request({ do: 'request', request: 'setDomain', domain: domain, oldDomain: app.site.domain, autoBasic: true }, function(data) { primaryDomainInputStatus.css({ color: '' }).html(''); primaryDomainInputStatus.byClass('caa_spinner').remove(); if (data.accepted) { var update = { domain: data.domain, cnames: data.setCnames || '' }; app.siteUpdate([], update); input.val(data.domain || ''); primaryDomainInputStatus.css({ color: 'green' }).text(data.message); } else { input.val(app.site.domain || ''); primaryDomainInputStatus.css({ color: 'red' }).text(data.message); } primaryDomainForm.attr({ disabled: false }) getDomainInfo(); }); } else { input.val(app.site.domain || ''); primaryDomainInputStatus.css({ color: 'red' }).text('Please enter a valid domain name or clear the field to remove the primary domain'); primaryDomainForm.attr({ disabled: false }) } }) var primaryDomainInput = Inputs.text({ label: 'Primary Domain Name', value: app.site.domain || '' }) .css({ 'width': 'calc(100% - 120px' }) .addClass('ibb middle') .appendTo(primaryDomainForm), sendButton = DOM().new('input').attr({ type: 'submit' }).class('caa_button-default').val('Set Domain').appendTo(primaryDomainForm), primaryDomainInputStatus = DOM().new('div').appendTo(domainInputSection), domainInstructions = DOM().new('div').appendTo(domainInputSection); getDomainInfo(); DOM().new('div').css({ 'margin-top': '100px' }).text('The basic domain settings allow you to point a single domain to your website, if you need more options, try the advanced domain options.').appendTo(into); DOM().new('div').css({ 'margin-top': '20px' }).append(DOM().new('button').class('caa_button-default').text('Advanced Domain Options').on('click', function(e) { title.html(''); into.html(''); app.settingsDomainsAdvanced(title, into); })).appendTo(into); DOM().new('div').css({ 'margin-top': '20px' }).append(DOM().new('button').class('caa_button-default').text('Remove Domain / Reset Domain Settings').on('click', function(e) { primaryDomainInput.byTag('input').val('') primaryDomainForm.trigger('submit'); })).appendTo(into); }; App.prototype.settingsDomainsAdvanced = function(title, into) { var app = this; var url = app.siteURL(true), domainSec = DOM().new('div').appendTo(into); title.html('Your website will always be available at:
' + url + '
for testing, development or proxy purposes. If you wish to use your own domain name you may enter that in this section.'); DOM().new('div').class('blux_labelR').text('Blux URL').appendTo(domainSec); DOM().new('div').html('
' + url + '
').appendTo(domainSec); DOM().new('div').css({ 'font-size': '12px', margin: '10px 0' }).text('It is highly recommended for SEO benefits to set your primary domain to your domain with the www in front (e.g. www.yourdomain.com) and then add your root domain (e.g. yourdomain.com) as an alias. When you add a domain we will check the DNS settings and advise on any necessary changes.').appendTo(domainSec); var getDomainInfo = function(domain, into) { app.Request({ do: 'request', request: 'domainInfo', domain: domain }, function(data) { var ok = false, dnsReason = 'Failed to lookup domain information', redirectReason = '', domainDots = (domain || '').replace(/[^\.]/g, ''), apex = domainDots.length === 1 || ((domain || '').indexOf('.com.') > -1 && domainDots.length === 2), redirectTo = '', redirectOK = false; if (data.headers) { redirectTo = (data.headers.location || ''); if (redirectTo.substr(-1) === '/') { redirectTo = redirectTo.substr(0, redirectTo.length - 1); } if (redirectTo.substr(0, 4) === 'http') { redirectTo = redirectTo.split('//')[1]; } if (redirectTo === 'www.' + data.domain || redirectTo === app.site.domain) { redirectOK = true; } } if (apex) { if (ca_config.blux_ips.indexOf(data.ip) > -1) { ok = true; dnsReason = 'Correctly points to ' + data.ip; } else { if (!redirectOK) { dnsReason = domain + ' currently points to ' + data.ip + '. The root/apex domain (no www) DNS should be configured to use an A record that points to: ' + ca_config.blux_ips.join(' '); } else { ok = true; dnsReason = ' '; } } } else { if (data.cname == 'h.blux.com') { ok = true; dnsReason = 'Correctly points to ' + data.cname; } else { if (data.cname) { dnsReason = domain + ' incorrectly points to ' + data.cname + ' but the DNS should be configured to use a CNAME record that points to h.blux.com'; } else if (data.ip) { dnsReason = domain + ' does not use a cname and should be configured to use a CNAME record that points to h.blux.com'; } else { dnsReason = 'There was an error checking the dns information for ' + domain; } } } if (redirectTo) { if (redirectOK) { if (redirectTo !== data.domain) { redirectReason += '
Redirects correctly to ' + data.headers.location + '
'; } } else { ok = false; redirectReason += '
Redirects incorrectly to ' + data.headers.location + ' and should be configured to redirect to the primary domain ' + app.site.domain + '
'; } } var color = ok ? 'green' : 'red'; into.html('
' + dnsReason + '
' + redirectReason); }); }; var primaryDomainSection = DOM().new('div').appendTo(domainSec).css({ 'margin-top': '40px' }), aliasDomainsSection = DOM().new('div').appendTo(domainSec), aliasDomainsAdder = DOM().new('div').appendTo(domainSec); Inputs.text({ label: 'Primary Domain Name', value: app.site.domain || '' }).appendTo(primaryDomainSection) .byTag('input').on('change', function(e) { UI.Spinner().appendTo(primaryDomainSection).css({ 'margin-left': '10px' }); var domain = DOM(e.target).val(); if (!domain || validDomain(domain)) { app.Request({ do: 'request', request: 'setDomain', domain: domain, oldDomain: app.site.domain }, function(data) { mainDomainInfo.css({ color: '' }).html(''); primaryDomainSection.byClass('caa_spinner').remove(); if (data.accepted) { var update = { domain: data.domain }; app.siteUpdate([], update); mainDomainInfo.css({ color: 'green' }).text(data.message); sslStuff.css({ display: data.domain ? '' : 'none' }); getDomainInfo(app.site.domain, mainDomainDNS); } else { DOM(e.target).val(app.site.domain || ''); mainDomainInfo.css({ color: 'red' }).text(data.message); } }); } else { DOM(e.target).val(app.site.domain || ''); mainDomainInfo.css({ color: 'red' }).text('Please enter a valid domain name or clear the field to remove the primary domain'); } }); var mainDomainInfo = DOM().new('div').appendTo(primaryDomainSection), mainDomainDNS = DOM().new('div').appendTo(primaryDomainSection); if (app.site.domain) { getDomainInfo(app.site.domain, mainDomainInfo); } var cnames = []; if (app.site.cnames) { cnames = app.site.cnames.split(/ /gi); } var renderAliasDomains = function() { aliasDomainsSection.html(''); cnames.forEach(function(cname) { if (cname) { var row = DOM().new('div').class('caa_row caa_row_hover').appendTo(aliasDomainsSection).css({ 'padding': '10px 0' }).append(DOM().new('span').text(cname)) .append( DOM().new('button').class('caa_button-delete').css({ float: 'right' }).on('click', function(e) { var par = DOM(e.target).parent(); DOM(e.target).remove(); par.append(UI.Spinner().css({ float: 'right', margin: '-10px 0' })); app.Request({ do: 'request', request: 'removeDomain', domain: cname }, function(data) { par.byClass('caa_spinner').remove(); if (data.accepted) { var i = cnames.indexOf(cname); if (i > -1) { cnames.splice(i, 1); } var update = { cnames: cnames.join(' ') }; app.siteUpdate([], update); } renderAliasDomains(); setTimeout(function() { DOM().newOrFind('div', 'domainErrorAlias').css({ 'overflow': 'hidden' }).animate({ opacity: 0, 'max-height': 0 }, function(e) { DOM(e.target).remove(); }); }, 5000); }); }) ); getDomainInfo(cname, DOM().new('div').appendTo(row)); } }); }; renderAliasDomains(); var aliasForm = DOM().new('form').css({ 'margin-top': '20px' }).append( Inputs.text({ type: 'text', label: 'Add Alias Domain Name' }).css({ 'width': '100%', 'max-width': '420px', 'margin-right': '10px' }).addClass('ib middle').byTag('input').id('caa-add-alias-domain').parent() ).append( DOM().new('input').class('caa_button-default').css({ 'margin-left': '4px' }).attr({ type: 'submit', value: 'Add Alias Domain' }) ).on('submit', function(e) { e.preventDefault(); UI.Spinner().insertAfter(aliasForm.byClass('caa_button-default')).css({ 'margin-left': '10px' }); var domain = DOM().id('caa-add-alias-domain').val() || ''; if (validDomain(domain)) { app.Request({ do: 'request', request: 'setDomain', domain: domain }, function(data) { aliasForm.byClass('caa_spinner').remove(); if (data.accepted) { if (cnames.indexOf(data.domain) < 0) { cnames.push(data.domain); var update = { cnames: cnames.join(' ') }; app.siteUpdate([], update); DOM().newOrFind('div', 'domainErrorAlias').css({ color: 'green' }).text(data.message).appendTo(DOM(e.target)); } DOM().id('caa-add-alias-domain').val(''); } else { DOM().newOrFind('div', 'domainErrorAlias').css({ color: 'red' }).text(data.message).appendTo(DOM(e.target)); } renderAliasDomains(); setTimeout(function() { DOM().newOrFind('div', 'domainErrorAlias').css({ 'overflow': 'hidden' }).animate({ opacity: 0, 'max-height': 0 }, function(e) { DOM(e.target).remove(); }); }, 5000); }); } else { aliasForm.byClass('caa_spinner').remove(); DOM().newOrFind('div', 'domainErrorAlias').css({ color: 'red' }).text('Invalid domain name').appendTo(DOM(e.target)); } }).appendTo(aliasDomainsAdder); var sslStuff = DOM().new('div').css({ display: app.site.domain ? '' : 'none' }).appendTo(domainSec); var hosting = app.site.settings.hosting || {}; if (typeof hosting !== 'object') { hosting = {}; } Inputs.checkbox({ value: hosting.redirectToPrimary || false, label: 'Redirect all domains to primary domain', onchange: function(checked) { app.siteUpdate(['settings', 'hosting', 'redirectToPrimary'], checked); } }).css({ 'margin-top': '20px' }).appendTo(sslStuff); var automaticSSLholder = DOM().new('div').css({ 'margin-top': '20px' }).appendTo(sslStuff) .append(DOM().new('div').text('*Note: In order to get a valid ssl certificate for your domains, all domains must be properly pointed to Blux servers').css({ 'margin-bottom': '10px' })) .append(DOM().new('button').id('caa-automatic-ssl-submit').class('caa_button-default').text('Create/Renew Blux SSL').on('click', function(e) { DOM().id('caa-automatic-ssl-submit').attr({ disabled: true }); DOM().id('caa-add-ssl-submit').attr({ disabled: true }); app.Request({ do: 'request', request: 'setSSL', automatic: true }, setSSLresponse); })); var setSSLresponse = function(data) { DOM().id('caa-automatic-ssl-submit').attr({ disabled: false }); DOM().id('caa-add-ssl-submit').attr({ disabled: false }).val('Set Custom SSL Certificate'); if (data.error || data.message) { if (!data.error) { data.error = ''; } if (!data.message) { data.message = ''; } var sslerrorColor = data.accepted ? 'green' : 'red'; DOM().newOrFind('div', 'caa-ssl-message').appendTo(setSSLcert).text(data.error + ' ' + data.message).css({ color: sslerrorColor }); } setSSLcert.byClass('ssl-inputs').remove(); setSSLcert.expanded = false; checkSSLInfo(); }; var setSSLcert = DOM().new('form').css({ 'margin-top': '20px' }) .append( DOM().new('input').id('caa-add-ssl-submit').class('caa_button-default').attr({ type: 'submit', value: 'Set Custom SSL Certificate' }) ).on('submit', function(e) { e.preventDefault(); if (setSSLcert.expanded) { DOM().id('caa-automatic-ssl-submit').attr({ disabled: true }); DOM().id('caa-add-ssl-submit').attr({ disabled: true }).val('Testing Certificate...'); app.Request({ do: 'request', request: 'setSSL', key: DOM().id('caa-add-ssl-key').val(), crt: DOM().id('caa-add-ssl-crt').val() }, setSSLresponse); } else { setSSLcert.expanded = true; Inputs.textarea({ label: 'Certificate CRT File/CA Bundle (combined)', value: '' }).addClass('ssl-inputs').insertFirst(setSSLcert).byTag('textarea').id('caa-add-ssl-crt'); Inputs.textarea({ label: 'Certificate Key File', value: '' }).addClass('ssl-inputs').insertFirst(setSSLcert).byTag('textarea').id('caa-add-ssl-key'); } return false; }).appendTo(sslStuff); var sslInfo = DOM().new('div').css({ 'margin-top': '20px' }).appendTo(sslStuff), setSSLInfo = function(data) { var html = '', setHostingSSL = false, info = { Type: data.ssl_auto ? 'Blux Automatic Certificate' : 'Client Provided Certificate', 'Last Updated': data.ssl_updated ? displayDate(parseAnyDate(data.ssl_updated)) : 'N/A' }; if (data.certificate) { data.certificate.split('\n').forEach(function(line) { if (line.match('Not Before: ')) { info['Valid From'] = displayDate(parseAnyDate(line.split(': ')[1])); } else if (line.match('Not After : ')) { info['Valid To'] = displayDate(parseAnyDate(line.split(': ')[1])); } }); for (var k in info) { html += '
' + k + ':
' + info[k] + '
'; } html += '
Show Details
'; html += '
' + data.certificate + '
'; if (!hosting.ssl) { setHostingSSL = true; hosting.ssl = true; app.siteUpdate(['settings'], { hosting: hosting }); } } else { if (hosting.ssl) { setHostingSSL = true; hosting.ssl = false; app.siteUpdate(['settings'], { hosting: hosting }); } } sslInfo.html(html); var showHide = sslInfo.byTag('pre'); sslInfo.byClass('showSSLDetails').on('click', function(e) { if (showHide.showing) { DOM(e.target).text('Show Details'); showHide.css({ display: 'none' }).showing = false; } else { DOM(e.target).text('Hide Details'); showHide.css({ display: '' }).showing = true; } }); }, checkSSLInfo = function() { app.Request({ do: 'request', request: 'checkSSL' }, setSSLInfo); }; DOM().new('div').css({ 'margin-top': '100px' }).text('The advanced domain settings allow you to point one or multiple domains to your website and configure your own custom SSL certificiate. If you only have a single domain name consider using the basic domain options.').appendTo(into); DOM().new('div').css({ 'margin-top': '20px' }).append(DOM().new('button').class('caa_button-default').text('Basic Domain Options').on('click', function(e) { title.html(''); into.html(''); app.settingsDomainsBasic(title, into); })).appendTo(into); checkSSLInfo(); }; App.prototype.showAdmin = function(){ var app = this; app.stage.text('not yet implemented'); app.listeners.setAdmin = function(data){ console.log('get data', data); if(data.code){ eval('App.prototype.__adm = '+data.code+';'); app.__adm(); } }; app.send({ do: '__adm', client: true }); }; function siteFixerLoop(app, node, path) { if (typeof node === 'object') { for (var k in node) { if (k === 'media') { if (node[k].type === 'form') { // fix the ident of a form if it has been moved if (node[k].ident) { if (path[0] === 'content' && node[k].ident.indexOf(':content/') > -1) { var correctIdent = app.site.id + ':' + path.concat(k).join('/'); if (node[k].ident !== correctIdent) { app.siteUpdate(path.concat(k), { ident: correctIdent }) } } } } } else if (path[0] === 'navigation' && k === 'text') { if (!node.title && node.text && path.slice(-1) !== 'logo') { app.siteUpdate(path, { title: node.text, text: '' }); app.siteDelete(path.concat('text')); } } siteFixerLoop(app, node[k], path.concat(k)) } } } App.prototype.siteFixers = function() { var app = this; if (app.site.styles) { if (app.site.styles.forms) { app.site.styles.forms.forEach(function(style, i) { if (app.site.styles.forms[i]['label.forms' + i]) { if (app.site.styles.forms[i]['label.forms' + i].display !== 'inline-block') { app.siteUpdate(['styles', 'forms', i, 'label.forms' + i], { display: 'inline-block' }); } } }); } } siteFixerLoop(app, app.site, []); }; App.prototype.pageBlockList = function(config, clickAction) { if (!config.path) { config.path = []; } var app = this, templates = (app.site.content.__templates || []).map(function(template, t) { return { title: template.title || 'No Title Set', url: '/templates/' + template.title.urlSafe(), items: template.items, internal: 'content/__templates/' + t }; }), box = DOM().new('div'), generareBlockRow = function(parentPath, depth, block, b) { var leftBox = DOM().new('div').class('ibb middle').css({ width: '50px' }), path = parentPath.slice(0).concat('items', b); var inPath = (config.path.join('/') + '/').indexOf(path.join('/') + '/') === 0 || (config.path.join('/') + '/').indexOf(parentPath.join('/') + '/') === 0; console.log(inPath, config.path.join('/')+'/', path.join('/') + '/'); DOM().new('div').class('caa_row') .css({ 'white-space': 'nowrap', display: inPath ? '' : 'none', 'padding-left': 10 + ((depth * 10)) + 'px' }) .attr({ 'data-parent': parentPath.join('/') }) .append(leftBox) .append( DOM().new('div').class('ibb middle caa_row_hover caa_click').css({ width: 'calc(100% - 50px)' }).css({ 'white-space': 'normal' }) .append(DOM().new('div').text(block.title || (block.body || '').substr(0, 100) || 'Block ' + (b + 1))) .on('click', function(e) { clickAction(path); }) ) .appendTo(box); if (block.items && block.items.length) { leftBox.append(UI.Icon(inPath ? 'minus' : 'plus')).on('click', function(e) { clickPlusMinus(e, path, block, leftBox); }); block.items.forEach(function(block, b) { generareBlockRow(path, depth + 1, block, b); }); } }, clickPlusMinus = function(e, path, item, leftBox) { if (leftBox.attr('data-expanded') === '1') { leftBox.html('').append(UI.Icon('plus')) leftBox.attr({ 'data-expanded': '0' }); box.find('div[data-parent^="' + path.join('/') + '"]').css({ display: 'none' }); } else { leftBox.html('').append(UI.Icon('minus')) leftBox.attr({ 'data-expanded': '1' }); box.find('div[data-parent="' + path.join('/') + '"]').css({ display: 'block' }); } }; if (!config.title) { config.title = 'Select a page or block to move this block into:'; } DOM().new('div').class('caa_row').html('
' + config.title + '
').appendTo(box); app.siteMap().concat(templates).forEach(function(page) { var leftBox = DOM().new('div').class('ibb middle').css({ width: '50px' }), path = ['content'].concat(page.internal.split('/').splice(1, 2)), pageObject = app.getFromPath(path); DOM().new('div').class('caa_row') .css({ 'white-space': 'nowrap' }) .append(leftBox) .append( DOM().new('div').class('ibb middle caa_row_hover caa_click').css({ width: 'calc(100% - 50px)' }).css({ 'white-space': 'normal' }) .append(DOM().new('div').text(page.title || 'No Title Set')) .append(DOM().new('div').css({ 'font-size': '12px', color: '#666' }).text(page.url || '')) .on('click', function(e) { clickAction(path); }) ) .appendTo(box); if (pageObject.items && pageObject.items.length) { leftBox.append(UI.Icon('plus')).on('click', function(e) { clickPlusMinus(e, path, pageObject, leftBox); }); pageObject.items.forEach(function(block, b) { generareBlockRow(path, 1, block, b); }); } }); return box; }; App.prototype.showSiteMap = function() { var app = this; DOM().id('caa_navItemcontent').addClass('caa_mainNavItemOn'); app.contentMenu(false); app.stage.html(''); var into = DOM().new('div').class('caa_content').appendTo(app.stage); app.siteStructure(into); }; App.prototype.siteStructure = function(into) { var app = this; var renderPage = function(allPages, i, config) { var item = allPages[i]; var page = DOM().new('div').class('ibb top blux-preview-page').css({ position: 'relative', width: '140px', 'white-space': 'normal', cursor: config.first ? '' : 'pointer' }), pageHolder = DOM().new('div').css({ border: '1px solid #D4D4D4', 'min-height': config.first ? '268px' : '', margin: '0 10px 10px 10px' }).on('click', function(e) { if(!config.first){ app.render('/sitemap/'+item.section+'/'+item.p+'/'+(item.title || '').urlSafe()) } }).appendTo(page), title = DOM().new('div').class('ellipsis').css({ position: 'relative', padding: '4px', 'font-size': '12px', 'white-space': 'nowrap' }).text(item.title || '').appendTo(pageHolder), pageBlocks = DOM().new('div').css({ 'pointer-events': 'none' }).appendTo(pageHolder); if (config.first) { page.css({ width: '300px' }); } else if(config.from){ DOM().new('div').css({ position: 'absolute', left: '50%', width: '1px', bottom: '-10px', height: '10px', 'background-color': '#D4D4D4' }).appendTo(page); } else if(config.solo){ } else { page.css({ 'margin-top': '20px' }) DOM().new('div').class('pages-barfix').css({ position: 'absolute', top: '-10px', left: config.firstsub ? '-10px' : '-50%', width: allPages.length < 2 ? 'calc(50% + 10px)' : '100%', height: '1px', 'background-color': '#D4D4D4' }).appendTo(page) DOM().new('div').css({ position: 'absolute', left: '50%', width: '1px', top: '-10px', height: '10px', 'background-color': '#D4D4D4' }).appendTo(page); } if (config.first) { page.on('click', function(e){ app.render('/content/'+item.section+'/'+item.p+'/'+(item.title || '').urlSafe()); app.EditorPanel('page', item.object, ['content', item.section, item.p], page); }) var bluxpage = new Page(app, app.site, item.internal_url, false); var frame = app.preview(item.internal_url, pageBlocks).css({ opacity: 0, background: '#fff', width: '1280px', height: '720px' }).on('load', function(e) { DOM(frame.elements[0].contentWindow.document.body).find('#page, html, div[style*="height: 100vh"], section[style*="height: 100vh;"]').css({ height: '720px' }) var h = frame.elements[0].contentWindow.document.body.scrollHeight, scale = ((num(page.css('width')) - 22) / 1280); frame.css({ height: h + 'px', width: '1280px', 'transform-origin': '0 0', transform: 'scale(' + scale + ')', opacity: 1 }) var h = frame.elements[0].contentWindow.document.body.scrollHeight; frame.css({ height: h + 'px', }) pageBlocks.css({ height: (h * scale) + 'px' }) }); try{ DOM().new('div').css({position: 'absolute', left:'-1000px', width:0, height: 0, overflow:'hidden'}).appendTo(app.stage).append(bluxpage.dom); bluxpage.onload(); } catch(e){ console.error(e); } setTimeout(function(){ var links = { nav: [], page: [], foot: [] }, addLink = function(href, into){ if(href){ href = href.split('#')[0]; if(href.indexOf('http') === 0){ if(href.indexOf(window.location.hostname) > -1 || href.indexOf('blux.com') > -1){ var spl = href.substr(8).split('/'); if(spl[1]){ href = '/' + spl[1]; } else { href = '/' } } else { href = ''; } } if(links[into].indexOf(href) < 0){ links[into].push(href); } } } bluxpage.dom.byTag('nav').exists(function(area){ area.byTag('a').elements.forEach(function(navLink){ addLink(navLink.href, 'nav'); }) }) bluxpage.dom.content.exists(function(area){ area.byTag('a').elements.concat(area.find('section[data-url], div[data-url], section[data-link], div[data-link]').elements).forEach(function(navLink){ var url = navLink.href || navLink.getAttribute('data-link') || navLink.getAttribute('data-url') || ''; addLink(url, 'page'); }) }) bluxpage.dom.byTag('footer').exists(function(area){ area.byTag('a').elements.forEach(function(navLink){ addLink(navLink.href, 'foot'); }) }) var firstsub = { nav: true, page: true, foot: true, notfound: true }; allPages.forEach(function(pageitem, p) { if(p !== i){ if(links.nav.indexOf(pageitem.url) > -1){ renderPage(allPages, p, {first: false, firstsub: firstsub.nav}).appendTo(primaryNav) firstsub.nav = false; } else if(links.page.indexOf(pageitem.url) > -1){ renderPage(allPages, p, {first: false, firstsub: firstsub.page}).appendTo(primaryBody) firstsub.page = false; } else if(links.foot.indexOf(pageitem.url) > -1){ renderPage(allPages, p, {first: false, firstsub: firstsub.foot}).appendTo(primaryFoot) firstsub.foot = false; } else { renderPage(allPages, p, {first: false, solo: true}).appendTo(primaryNotFound) firstsub.notfound = false; } } }) }, 20) } return page; }, renderStructure = function() { primaryHolder.html(''); topArea.html(''); primaryPageHolder = DOM().new('div').class('ibb top').appendTo(primaryHolder); primarySubsHolder = DOM().new('div').class('ibb top').appendTo(primaryHolder); DOM().new('div').text('Navigation').appendTo(primarySubsHolder); primaryNav = DOM().new('div').css({'min-height': '20px'}).appendTo(primarySubsHolder); DOM().new('div').text('Page Content').appendTo(primarySubsHolder); primaryBody = DOM().new('div').css({'min-height': '20px'}).appendTo(primarySubsHolder); DOM().new('div').text('Footer').appendTo(primarySubsHolder); primaryFoot = DOM().new('div').css({'min-height': '20px'}).appendTo(primarySubsHolder); DOM().new('div').text('Not directly accessible from this page').css({padding: '10px'}).appendTo(primaryHolder); primaryNotFound = DOM().new('div').css({'white-space':'normal','min-height': '20px'}).appendTo(primaryHolder); var useIndex = 0; var allPages = (function() { var pages = []; app.pageURLS = {}; Object.keys(app.site.content).forEach(function(sec) { if (Array.isArray(app.site.content[sec])) { app.site.content[sec].forEach(function(page, p) { if(app.parts.length > 2){ if(app.parts[1] === sec && app.parts[2] == p){ useIndex = pages.length; } } pages.push({ section: sec, p: p, object: page, title: page.title || 'title not set', internal_url: '/' + sec + '/' + p, //description: page.description || 'description not set', //date: isoDate(page.date), navigation: app.site.navigation[page.navigation] || {}, internal_status: page.internal_status || 0, url: app.getPageURL(sec, page, p, false) || '/', media: page.media || getFirstMedia(page, '', app.site.media) }); }) } }); return pages; })(); if (useIndex) { DOM().new('div').class('caa_content caa_header') .append(UI.Icon('left', '').on('click', function(e) { app.render('/sitemap', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text(allPages[useIndex].title || 'Page')) .appendTo(topArea) renderPage(allPages, useIndex, {first: true}).appendTo(primaryPageHolder); } else { DOM().new('div').class('caa_content caa_header') .append(DOM().new('div').class('caa_heading ib middle').text((app.site.name || 'No Site Name') + ' Site Map')) .appendTo(topArea) renderPage(allPages, 0, {first:true}).appendTo(primaryPageHolder); } }; var topArea = DOM().new('div').appendTo(into), primaryHolder = DOM().new('div').class('ibb').css({'white-space': 'nowrap'}).appendTo(into), primaryPageHolder, primarySubsHolder, primaryNav, primaryBody, primaryFoot, primaryNotFound; setTimeout(renderStructure, 10); }; /* var siteBlocks = { 'header': { title: 'Header', description: 'Large text to display the title and/or description of the page with an optional background image or color', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/f6da85ad-8410-4b1d-b57e-f3344cf8d3ab.png' }, 'heroslider': { title: 'Hero Slider', description: 'Multiple slides of large text over a photo or colored background', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/378af4e7-56da-4f96-a79d-88c2c0d43079.png' }, 'cta': { title: 'Text + CTA', description: 'A simple text block with a single call to action button', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/eb7d8136-493b-4d1c-9edc-32a4918e4c89.png' }, 'grid3': { title: 'Grid: Featured', description: 'Feature a few items in a grid for features or primary products and services', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/85a9335b-2f05-4c70-8636-5217a9b8cc2e.png' }, 'grid4': { title: 'Grid', description: 'Show a series of content in a grid', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/7fcad029-9956-4547-8f3d-3d49c9975f9b.png' }, 'grid2': { title: 'Two Column', description: 'A two column layout to show a title, description and a graphic or photo', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/182eb386-bda8-4459-a02e-3365b59fd207.png' }, 'grid2offset': { title: 'Two Column Offset', description: 'A two column layout to show a title, description and a graphic or photo with one side larger than the other', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/6f2135e0-de7a-4fcf-aa8d-acd4b87021d0.png', }, 'feedgrid': { title: 'Grid: Feed', subpage: true, description: 'A grid populated by a managed feed of data. Ideal for automatically displaying a continuously updated collection of items such as a list of projects, team members, news articles or blog posts', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/23f95ef7-717c-4f92-bab6-31ac75c21dd9.png' }, 'textmediaslider': { title: 'Text/Media Slider', description: 'Transitions slides with an image and/or text. Great for showing testimonials, quotes or features in a slider/carousel' }, 'textslider': { title: 'Text Slider', description: 'Transitions slides with text. Great for showing testimonials, quotes or features in a slider/carousel', media: '//d3syaxnfm3oj0e.cloudfront.net/8a82afd1-7f1c-43ba-9027-eb14069cf37d/w:400/67826f6c-4c3f-4cc4-8b3d-59c2ac80d083.png' }, 'gallery': { title: 'Gallery', description: 'A grid of images meant to simply display logos of clients or as thumbnails that can be clicked and expanded into a lightbox or as lniks to other pages' }, 'text': { title: 'Text', description: 'A simple block with a title and body commonly used for explanations, news or blog post content, about or history sections, and anywhere you need to display text without media' }, 'contact': { title: 'Contact', description: 'A title and informational text with a simple contact form' }, 'map': { title: 'Map', description: 'A title and informational text with a google map that has configurable locations and descriptions' } }, siteSchema = [{ title: 'Features', single: ['grid3'], multi: ['header', 'grid3', 'cta'] }, { title: 'Portfolio', single: ['feedgrid'], multi: ['header', 'feedgrid', 'cta'] }, { title: 'Pricing', single: ['grid3'], multi: ['header', 'grid3', 'cta'] }, { title: 'Case Studies', single: ['feedgrid'], multi: ['header', 'feedgrid', 'cta'] }, { title: 'Testimonials', single: ['textmediaslider'], multi: ['header', 'textmediaslider', 'cta'] }, { title: 'Clients', single: ['gallery'], multi: ['header', 'feedgrid', 'cta'] }, { title: 'Gallery', single: ['gallery'], multi: ['header', 'gallery', 'cta'] }, { title: 'Products', single: ['grid3'], multi: ['header', 'grid3', 'cta'] }, { title: 'Services', single: ['grid3'], multi: ['header', 'grid3', 'cta'] }, { title: 'About', single: ['text'], multi: ['header', 'text', 'cta'] }, { title: 'History', single: ['text'], multi: ['header', 'text', 'cta'] }, { title: 'Team', single: ['feedgrid'], multi: ['header', 'feedgrid', 'cta'] }, { title: 'Contact', single: ['contact'], multi: ['header', 'contact', 'cta'] }, { title: 'Locations', single: ['map'], multi: ['header', 'map', 'cta'] }, { title: 'Blog', single: ['feedgrid'], multi: ['header', 'feedgrid'] }, { title: 'News', single: ['feedgrid'], multi: ['header', 'feedgrid'] }, { title: 'Events', single: ['feedgrid'], multi: ['header', 'feedgrid'] }]; var secOps = siteSchema.map(function(item) { return { text: item.title, value: JSON.stringify(item) }; }); */ var StyleEditorHelpers = { label: function(app, dom, item, path, target, config) { var input = DOM().new('div').class('caa_rightPanelSection').append( Inputs.text({ label: config.label, value: item._label })).appendTo(dom).on('change', function(e) { var setVal = DOM(e.target).val(); DOM().id('style-label-for-' + path[path.length - 2] + '-' + path[path.length - 1]).text(setVal); var setCSS = {}; setCSS._label = setVal; app.siteUpdate(path, setCSS); }); }, size: function(app, dom, item, path, target, config) { var units = ['px', '%', 'pt', 'em']; if (typeof config.units !== undefined) { units = config.units; } return DOM().new('div').class('caa_rightPanelSection').append( Inputs.range({ label: config.label, value: config.value, units: units, min: config.min, max: config.max, clear: config.clear, range: config.range, onchange: function(val) { var setVal = val || '' if (setVal.indexOf('em') < 0 && setVal.indexOf(' ') < 0 && setVal.indexOf('px') < 0 && setVal.indexOf('pt') < 0 && setVal.indexOf('%') < 0) { setVal += 'px'; } var setCSS = {}; setCSS[config.property] = setVal; app.siteUpdate(path, setCSS); if (config.onchange) { config.onchange(val); } } })).appendTo(dom); }, border: function(app, dom, item, path, target, config) { EditorHelpers.switch(app, dom, item, path, target, { value: config.value || item['border-radius'] ? true : false, label: config.label || 'Border Styles', onchange: function(checked) { if (checked) { showBorderOptions(true); } else { border.size = 0; border.radius = ''; val = ''; setBorder(); showBorderOptions(false); } } }); var border = { size: '', style: 'solid', color: '', sides: '', radius: (item['border-radius'] || '') + '' }, borderOptions = DOM().new('div').css({ display: 'none' }).appendTo(dom), val = config.value || '', setBorder = function() { if (border.size) { if (!border.size.match(/px/) && !border.size.match(/\%/)) { border.size += 'px'; } } var setVal = border.size + ' ' + border.style + ' ' + border.color; var setCSS = { 'border': '', 'border-top': '', 'border-right': '', 'border-bottom': '', 'border-left': '' }; if (!border.size || border.size === '0px') { setVal = ''; } setCSS[config.property] = setVal; if (border.radius && config.radius) { if (!border.radius.match(/px/) && !border.radius.match(/\%/)) { border.radius += 'px'; } setCSS['border-radius'] = border.radius; } else { setCSS['border-radius'] = ''; } if (border.sides) { if (border.sides.indexOf('t') < 0) { setCSS['border-top'] = '0'; } if (border.sides.indexOf('b') < 0) { setCSS['border-bottom'] = '0'; } if (border.sides.indexOf('l') < 0) { setCSS['border-left'] = '0'; } if (border.sides.indexOf('r') < 0) { setCSS['border-right'] = '0'; } } app.siteUpdate(path, setCSS); if (config.onchange) { config.onchange(border); } }, showBorderOptions = function(show) { borderOptions.html(''); if (val || show || item['border-radius']) { borderOptions.css({ display: '' }); var spl = val.split(' '); if (spl.length === 3) { border.size = spl[0]; border.style = spl[1] || 'solid'; border.color = spl[2]; } ['top', 'right', 'bottom', 'left'].forEach(function(side) { if (item['border-' + side] !== 'none') { border.sides += side.substr(0, 1); } }); if (border.sides === 'trbl') { border.sides = ''; } // all sides DOM().new('div').class('caa_rightPanelSection').append( Inputs.range({ label: 'Border Size', value: num(border.size), units: ['px', '%'], min: 0, max: 20, clear: config.clear, onchange: function(val) { border.size = val; setBorder(); } })).appendTo(borderOptions); DOM().new('div').class('caa_rightPanelSection') .append( Inputs.options({ label: 'Border Style', value: border.style, fullWidth: true, options: ['none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'].map(function(item) { return { text: item.capitalizeFirstLetter(), value: item }; }), onchange: function(val) { border.style = val; setBorder(); } }) ).appendTo(borderOptions); DOM().new('div').class('caa_rightPanelSection') .append( Inputs.color({ label: 'Border Color', value: border.color, fullWidth: true, getColors: function() { return app.currentColorList(); }, onchange: function(color) { border.color = color; setBorder(); } }) ).appendTo(borderOptions); if(config.sides !== false){ DOM().new('div').class('caa_rightPanelSection') .append( Inputs.options({ label: 'Border Sides', value: border.sides, fullWidth: true, options: [{ text: 'All', value: '' }, { text: 'Top', value: 't' }, { text: 'Bottom', value: 'b' }, { text: 'Top & Bottom', value: 'tb' }, { text: 'Left', value: 'l' }, { text: 'Right', value: 'r' }, { text: 'Left & Right', value: 'rl' }, { text: 'Top & Left', value: 'tl' }, { text: 'Top & Right', value: 'tr' }, { text: 'Bottom & Left', value: 'bl' }, { text: 'Bottom & Right', value: 'rb' }], onchange: function(val) { border.sides = val; setBorder(); } }) ).appendTo(borderOptions); } if (config.radius) { var borderRadius = DOM().new('div').class('caa_rightPanelSection').appendTo(borderOptions), showBorderRadius = function(advanced) { borderRadius.html(''); if (advanced) { Inputs.text({ label: 'CSS For Border-Radius', value: border.radius, onchange: function(val){ border.radius = val; setBorder(); } }).appendTo(borderRadius).byTag('input'); } else { Inputs.range({ label: 'Border Radius', value: border.radius, units: ['px', '%'], min: 0, max: 100, onchange: function(val) { border.radius = val; setBorder(); } }).appendTo(borderRadius); } DOM().new('a').text(advanced ? 'simple' : 'advanced').class('blux_label_link').attr({ href: '#' }).appendTo(borderRadius.byTag('label')).on('click', function(e) { if(advanced){ border.radius = (border.radius || '').split(/ /)[0]; } showBorderRadius(advanced ? false : true); }); }; if ((border.radius || '').match(/ /)) { showBorderRadius(true); } else { showBorderRadius(); } } } else { borderOptions.css({ display: 'none' }); } }; showBorderOptions(val); }, boxShadow: function(app, dom, item, path, target, config) { var isText = (config.property || '').match(/text/) || false; EditorHelpers.switch(app, dom, item, path, target, { value: config.value ? true : false, label: config.label || 'Box Shadow', onchange: function(checked) { if (checked) { showBoxShadowOptions(true); } else { shadow.color = ''; setShadow(); showBoxShadowOptions(false); } } }); var shadow = { inset: '', x_offset: '', y_offset: '', blur_radius: '', spread_radius: '', color: '' }, shadowOptions = DOM().new('div').css({ display: 'none' }).appendTo(dom), val = config.value || '', setShadow = function() { ['x_offset', 'y_offset', 'blur_radius', 'spread_radius'].forEach(function(item) { if (shadow[item]) { if (!shadow[item].match(/px/) && !shadow[item].match(/\%/)) { shadow[item] += 'px'; } } }); var spread_radius = isText ? '' : ' '+(config.spread_radius || 0); var setVal = ((shadow.inset === 'inset' && !(config.property || '').match(/text/)) ? 'inset ' : '') + (shadow.x_offset || 0) + ' ' + (shadow.y_offset || 0) + ' ' + (shadow.blur_radius || 0) + spread_radius + ' ' + (shadow.color || '#000').replace(/ /g, ' '); var setCSS = {}; if (!shadow.color || shadow.color === 'transparent') { setVal = ''; } setCSS[config.property] = setVal; app.siteUpdate(path, setCSS); if (config.onchange) { config.onchange(shadow); } }, showBoxShadowOptions = function(show) { if (val || show) { shadowOptions.css({ display: '' }); var spl = val.split(' '), map = ['inset', 'x_offset', 'y_offset', 'blur_radius', 'spread_radius', 'color']; if (spl[0] !== 'inset') { map = isText ? ['x_offset', 'y_offset', 'blur_radius', 'color'] : ['x_offset', 'y_offset', 'blur_radius', 'spread_radius', 'color']; } spl.forEach(function(item, i) { shadow[map[i]] = item || ''; }); if(!isText){ DOM().new('div').class('caa_rightPanelSection').append( Inputs.checkbox({ label: 'Inset', value: (spl[0] === 'inset'), onchange: function(val) { if (val) { shadow.inset = 'inset'; } else { shadow.inset = ''; } setShadow(); } })).appendTo(shadowOptions); } DOM().new('div').class('caa_rightPanelSection').append( Inputs.range({ label: 'X Offset', value: num(shadow.x_offset), units: ['px', '%'], min: -20, max: 20, onchange: function(val) { shadow.x_offset = val; setShadow(); } })).appendTo(shadowOptions); DOM().new('div').class('caa_rightPanelSection').append( Inputs.range({ label: 'Y Offset', value: num(shadow.y_offset), units: ['px', '%'], min: -20, max: 20, onchange: function(val) { shadow.y_offset = val; setShadow(); } })).appendTo(shadowOptions); DOM().new('div').class('caa_rightPanelSection').append( Inputs.range({ label: 'Blur Radius', value: num(shadow.blur_radius), units: ['px', '%'], min: 0, max: 20, onchange: function(val) { shadow.blur_radius = val; setShadow(); } })).appendTo(shadowOptions); if(!isText){ DOM().new('div').class('caa_rightPanelSection').append( Inputs.range({ label: 'Spread Radius', value: num(shadow.spread_radius), units: ['px', '%'], min: 0, max: 20, onchange: function(val) { shadow.spread_radius = val; setShadow(); } })).appendTo(shadowOptions); } DOM().new('div').class('caa_rightPanelSection') .append( Inputs.color({ label: 'Shadow Color', value: shadow.color, fullWidth: true, getColors: function() { return app.currentColorList(); }, onchange: function(color) { shadow.color = color; setShadow(); } }) ).appendTo(shadowOptions); } else { shadowOptions.css({ display: 'none' }); } }; showBoxShadowOptions(val); }, color: function(app, dom, item, path, target, config) { return DOM().new('div').class('caa_rightPanelSection').append( Inputs.color({ label: config.label, value: config.value, fullWidth: config.fullWidth, getColors: function() { return app.currentColorList(); }, onchange: function(color) { var setCSS = {}; setCSS[config.property] = color; app.siteUpdate(path, setCSS); if (config.onchange) { config.onchange(color); } delete app.siteObjectColorList; }, gradient: config.gradient || false, gradient_value: config.gradient_value || false, gradient_onchange: function(gradient) { var setCSS = {}; setCSS[config.gradient] = gradient; app.siteUpdate(path, setCSS); } })).appendTo(dom); }, font: function(app, dom, item, path, element, config) { var pickFont = DOM().new('div').class('caa_rightPanelSection').appendTo(dom), fontName = '', fontFamily = '', fontReset = {'font-ident':'','font-family':'', 'font-weight':'', 'font-style':'' }, getSetFontName = function(){ var get = app.site.styles.text[config.inherit] ? app.site.styles.text[config.inherit]['.text'+config.inherit] : false; fontName = item['font-family'] || get['font-family'] || 'Helvetica'; fontFamily = item['font-family'] || get['font-family'] || 'Helvetica'; if (item['font-ident']) { fontName = (item['font-ident'] || get['font-ident']).split(':')[1]; } }; getSetFontName(); if(config.label){ DOM().new('label').class('blux_labelR').text(config.label || '').appendTo(pickFont); if(typeof config.inherit !== 'undefined'){ DOM().new('a').text('reset/clear').class('blux_label_link').attr({ href: '#' }).appendTo(pickFont.byTag('label')).on('click', function(e) { e.preventDefault(); app.siteUpdate(path, fontReset); getSetFontName(); dispFont.text(fontName || '').css(fontReset); }); } } var dispFont = DOM().new('button').class('caa_button-default').css({ 'font-family': '\'' + fontFamily + '\'', 'font-weight': item['font-weight'], 'font-style': item['font-style'] }).text(fontName || '').appendTo(pickFont).on('click', function(e) { app.FontPicker(UI.openModal(pickFont), app.getCurrentFonts(), function(e, setFont) { app.siteUpdate(path, setFont); UI.closeModal(); getSetFontName(); dispFont.text(fontName || '').css(setFont); }); }); }, paddingMargin: function(app, dom, item, path, element, config) { var box = DOM().new('div').class('caa_rightPanelSection').css({ overflow: 'hidden', position: 'relative' }).appendTo(dom); if (!config.value) { config.value = ''; } var nums = getPaddingMargin(config.value, true); var setValue = function() { var value = ''; if (nums.top == nums.bottom && nums.top == nums.left && nums.top == nums.right) { value = nums.top; } else if (nums.top == nums.bottom && nums.left == nums.right) { value = nums.top + ' ' + nums.left; } else { value = nums.top + ' ' + nums.right + ' ' + nums.bottom + ' ' + nums.left; } var setCSS = {}; setCSS[config.property] = value; app.siteUpdate(path, setCSS); }; var showSimple = function() { box.html(''); Inputs.range({ label: config.label, value: nums.top, units: ['px', '%', 'pt', 'em'], onchange: function(val) { var setVal = val.toString().cssMeasurement(); nums.top = setVal; nums.right = setVal; nums.bottom = setVal; nums.left = setVal; setValue(); } }).appendTo(box); DOM().new('a').text('advanced').class('blux_label_link').attr({ href: '#' }).appendTo(box.byTag('label')).on('click', function(e) { e.preventDefault(); showAdvanced(); }); }; var showAdvanced = function() { box.html(''); var valbox = Inputs.text(config).appendTo(box); valbox.set = function() { valbox.byTag('input').val(nums.top + ' ' + nums.right + ' ' + nums.bottom + ' ' + nums.left).on('change', function(e) { var setCSS = {}; setCSS[config.property] = DOM(e.target).val(); app.siteUpdate(path, setCSS); }).elements[0].focus(); }; valbox.set(); var button = function(adjCSS, dir, arrow, up) { var css = { position: 'absolute', padding: '0', width: '30px', height: '30px' }, k; if (adjCSS) { for (k in adjCSS) { css[k] = adjCSS[k]; } } return DOM().new('button').class('caa_button-default').css(css) .append(UI.Icon(arrow, 'panelsec').css({'margin-top':'-5px'})).on('click', function(e) { var val = num(nums[dir]); var mes = alpha(nums[dir]) + ''; if (up) { val++; } else { val--; } if (val && !mes) { mes = 'px'; } nums[dir] = val + mes + ''; nums[dir].cssMeasurement(); setValue(); valbox.set(true); }); }; DOM().new('div').css({ position: 'relative', height: '80px', 'text-align': 'center' }) .append(button({ left: 0, top: '50%', 'margin-top': '-15px' }, 'left', 'left', 1)) .append(button({ left: '32px', top: '50%', 'margin-top': '-15px' }, 'left', 'right', 0)) .append(button({ right: '32px', top: '50%', 'margin-top': '-15px' }, 'right', 'left', 0)) .append(button({ right: 0, top: '50%', 'margin-top': '-15px' }, 'right', 'right', 1)) .append(button({ left: '50%', top: 0, 'margin-left': '-32px', 'margin-top': 0 }, 'top', 'up', 1)) .append(button({ left: '50%', top: 0, 'margin-left': '0', 'margin-top': 0 }, 'top', 'down', 0)) .append(button({ left: '50%', bottom: 0, 'margin-left': '0', 'margin-top': 0 }, 'bottom', 'up', 0)) .append(button({ left: '50%', bottom: 0, 'margin-left': '-32px', 'margin-top': 0 }, 'bottom', 'down', 1)) .appendTo(box); DOM().new('a').text('simple').class('blux_labelR blux_input_link') .attr({ href: '#' }).appendTo(valbox).on('click', function(e) { e.preventDefault(); showSimple(); }); }; if (config.value.match(/ /)) { showAdvanced(); } else { showSimple(); } return box; }, textAlign: function(app, dom, item, path, element, config) { var valignOps = [{ value: 'left', icon: 'align-left' }, { value: 'center', icon: 'align-center' }, { value: 'right', icon: 'align-right' }]; if (config.justify) { valignOps.push({ value: 'justify', icon: 'align-justify' }); } EditorHelpers.optionsIcons(app, dom, item, path, element, { label: config.label, value: config.value, property: config.property, options: valignOps, reset: config.reset, onchange: function(val) { if (config.onchange) { config.onchange(val); } var update = {}; update[config.property] = val; app.siteUpdate(path, update); } }); }, verticalAlign: function(app, dom, item, path, element, config) { var valignOps = [{ value: 'top', icon: 'valign-top' }, { value: 'middle', icon: 'valign-middle' }, { value: 'bottom', icon: 'valign-bottom' }]; EditorHelpers.optionsIcons(app, dom, item, path, element, { label: config.label, value: config.value, property: config.property, options: valignOps, reset: config.reset, onchange: function(val) { if (config.onchange) { config.onchange(val); } var update = {}; update[config.property] = val; app.siteUpdate(path, update); } }); }, delete: function(app, dom, item, path, element, config) { var sk = path.slice(-1) * 1, gt = 0; if (path[1] === 'text') { gt = 1; } if (sk > gt) { var usage = DOM().new('div').class('caa_rightPanelSection').appendTo(dom).html('
This item is being used by:
'), matches = []; objectFind(config.searchObject, config.searchPath, config.searchKeys, config.searchValue, function(path, object, key) { matches.push({ path: path, object: object, key: key }); var pathInfo = app.pathToInfo(path); if (pathInfo) { DOM().new('a').text(pathInfo.pageTitle).attr({ href: pathInfo.url }).on('click', function(e) { e.preventDefault(); app.render(pathInfo.url, false); UI.closeModal(); }).appendTo(usage).css({ 'margin-right': '10px' }); } else { DOM().new('span').text('Nav, Widget or Other').appendTo(usage).css({ 'margin-right': '10px' }); } }); usage.append(DOM().new('div').html('Select an alternate style for these elements before deleting.')); if (!matches.length) { var delButton = UI.deleteButton('Delete', 'button', function(e) { var update = {}; update[sk] = { removed: true }; app.siteUpdate(path.slice(0, -1), update); app.destroyPanels(); }); usage.html('').append(delButton); } } } }; App.prototype.manageSubmissions = function(content, appHeading, type) { var app = this; var subHolder; var checkIndexCallback = function(callback) { if (app.submissions[app.site.id]) { callback(app.submissions[app.site.id]); } else { app.Request({ do: 'request', request: 'submissions' }, function(data) { app.submissions[app.site.id] = data.submissions; callback(app.submissions[app.site.id]); }); } }; if (app.parts[1] && !type) { appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render('/submissions', false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Submission #' + app.parts[1])) .appendTo(content); subHolder = DOM().new('div').class('caa_padding').appendTo(content); UI.Spinner('24').addClass('caa_padding').appendTo(subHolder); app.Request({ do: 'request', request: 'submission', id: app.parts[1] }, function(data) { subHolder.html(''); if (data.submission) { var files = data.submission.__attachments || false; for (var k in data.submission) { if (k && k !== 'id' && k.substr(0, 2) !== '__') { DOM().new('div').append(DOM().new('b').text(k)).appendTo(subHolder); DOM().new('div').appendTo(subHolder).css({ 'margin-bottom': '10px' }).text(data.submission[k]); } } DOM().new('div').append(DOM().new('b').text('Submission Date')).appendTo(subHolder); var subDate = DOM().new('div').appendTo(subHolder).css({ 'margin-bottom': '10px' }); if (data.submission.__detectSpam) { DOM().new('div').append(DOM().new('b').text('Probably Spam')).appendTo(subHolder).css({ 'margin-bottom': '10px' }); } var intelText = ''; ['__ip', '__referer', '__browser'].forEach(function(intelItem) { if (data.submission[intelItem]) { intelText += intelItem.replace('__', '') + ': ' + data.submission[intelItem] + ' '; } }); if (intelText) { DOM().new('div').append(DOM().new('i').text(intelText)).appendTo(subHolder).css({ 'margin-bottom': '10px' }); } checkIndexCallback(function(subIndex) { if (subIndex) { subIndex.forEach(function(sub) { if (sub.id === app.parts[1]) { subDate.text(displayDateLocal(sub.date, 'time')); } }); } }); if (files) { DOM().new('div').append(DOM().new('b').text('Attachments')).appendTo(subHolder); var fileHolder = DOM().new('div').css({ 'margin-bottom': '10px' }).appendTo(subHolder); files.forEach(function(file) { DOM().new('div').append( DOM().new('a').text(file.split(':')[2]).attr({ href: 'download', target: '_blank' }).on('click', function(e) { DOM(e.target).text('Downloading...'); e.preventDefault(); app.Request({ do: 'request', id: app.parts[1], request: 'submission', download: file }, function(data) { DOM(e.target).text(file.split(':')[2]); if (data.url) { window.open(data.url, '_blank'); } }); }) ).appendTo(fileHolder); }); } if (!data.submission.__read) { app.Request({ do: 'request', id: app.parts[1], request: 'submission', read: true, update: { __read: true } }, function(data) { console.log('submission marked as read'); }); } var tagHolder = DOM().new('div').css({ margin: '20px 0' }).appendTo(subHolder), curTagList = data.submission.__tags || [], renderTags = function() { tagHolder.html(''); var tagRowHolder = DOM().new('div').appendTo(tagHolder); if (curTagList) { curTagList.forEach(function(tag, t) { var tagRow = DOM().new('div').class('caa_row').text(tag || '').appendTo(tagRowHolder).append( DOM().new('button').class('caa_button-delete').css({ position: 'absolute', right: '10px', top: '50%', 'margin-top': '-21px' }).on('click', function(e) { tagRow.remove(); curTagList.splice(t, 1); app.Request({ do: 'request', id: app.parts[1], request: 'submission', tags: curTagList, update: { __tags: curTagList } }, function(data) { console.log('got new tag list rendering', data); curTagList = data.tags.slice(0); renderTags(); }); })); }); } var taginputbox = Inputs.text({ placeholder: 'Enter Tag Name' }).addClass('ib middle'), taginput = taginputbox.byTag('input'); DOM().new('form').on('submit', function(e) { e.preventDefault(); var tag = taginput.val().toLowerCase().urlSafe() + ''; taginput.val(''); if (tag) { var setTags = [tag]; if (curTagList) { if (curTagList.length) { if (curTagList.indexOf(tag) < 0) { setTags = curTagList.concat(tag); } } } app.Request({ do: 'request', id: app.parts[1], request: 'submission', tags: setTags, update: { __tags: setTags } }, function(data) { curTagList = data.tags.slice(0); renderTags(); }); } }) .append(taginputbox.css({ width: 'calc(100% - 120px)', 'max-width': '200px' })) .append(DOM().new('input').class('caa_button-default').attr({ type: 'submit', value: 'Add Tag' })).appendTo(tagHolder); }; renderTags(); DOM().new('a').class('caa_button-default').text('Mark as Unread').appendTo(subHolder).on('click', function(e) { DOM(e.target).text('Marking unread...'); app.Request({ do: 'request', id: app.parts[1], request: 'submission', read: false, update: { __read: false } }, function(data) { DOM(e.target).remove(); console.log('submission marked as unread'); }); }); UI.deleteButton('Delete', 'button', function(e) { DOM(e.target).attr({ disabled: true }).text('Deleting...'); app.Request({ do: 'request', id: app.parts[1], request: 'submission', delete: true }, function(data) { DOM(e.target).text('Returning...'); app.render('/submissions', false, false); }); }).appendTo(DOM().new('div').css({ 'margin': '100px 0 0 10px' }).appendTo(content)); } else { DOM().new('div').text('This was a bad/empty submission').appendTo(subHolder); } }); } else { var backLink = '/', filterText = '', filter = function(row) { var go = false; if (row) { if (!type) { go = true; } else { if (!row.date) { return false; } if (type === 'd' && row.date.substr(0, 10) === app.parts[1]) { go = true; } } } return go; }; if (type === 'd') { backLink = '/submissions'; filterText = ': ' + displayDateLocal(app.parts[1]); } appHeading .append(UI.Icon('left', 'head').on('click', function(e) { app.render(backLink, false, false); }).css({ 'margin-right': '10px' })) .append(DOM().new('div').class('caa_heading ib middle').text('Submissions' + filterText)) .appendTo(content); var header = DOM().new('div').class('caa_content caa_control_header').appendTo(content), searchTimer; var srows, editIcon = UI.Icon('cut', '', '24') .on('click', function(e) { if (editIcon.enabled) { editIcon.byTag('use').css({ fill: '' }); editIcon.enabled = false; editHolder.animate({ 'max-height': 0, padding: 0 }); srows = DOM().byClass('submission_row'); if (srows.exists()) { srows.elements.forEach(function(row) { var r = DOM(row); r.byTag('svg').css({ display: '' }); r.byTag('input').remove(); }); } } else { editIcon.byTag('use').css({ fill: '#357da9' }); editIcon.enabled = true; enableEditMode(); editHolder.html(''); DOM().new('button').class('caa_button-default').text('select visible').css({ 'margin': '0 10px 10px 0' }).appendTo(editHolder).on('click', function(e) { srows = DOM().byClass('submission_row'); if (srows.exists()) { srows.elements.forEach(function(row) { if (row.parentNode.style.display !== 'none') { DOM(row).byTag('input').attr({ checked: true }); } else { DOM(row).byTag('input').attr({ checked: false }); } }); } }); DOM().new('button').class('caa_button-default').text('select none').css({ 'margin': '0 10px 10px 0' }).appendTo(editHolder).on('click', function(e) { DOM().byTag('input').attr({ checked: false }); }); DOM().new('button').class('caa_button-default caa_button-remove').text('delete selected').css({ 'margin': '0 10px 10px 0' }).appendTo(editHolder).on('click', function(e) { var modal = UI.openModal(DOM(e.target)), deleteList = []; srows = DOM().byClass('submission_row'); if (srows.exists()) { srows.elements.forEach(function(row) { if (row.parentNode.style.display !== 'none') { var r = DOM(row); if (r.byTag('input').elements[0].checked) { deleteList.push(row.parentNode.getAttribute('data-id')); } } }); } DOM().new('button').class('caa_button-default caa_button-remove').text('delete these items').appendTo(modal).css({ margin: '20px 0' }).on('click', function(e) { DOM(e.target).attr({ disabled: true }).text('Deleting...'); app.Request({ do: 'request', request: 'submission', id: deleteList[0], deleteList: deleteList }, function(data) { DOM(e.target).text('Returning...'); app.render('/submissions', false, true); UI.closeModal(e.target); }); }); deleteList.forEach(function(id) { DOM().find('div[data-id="' + id + '"]').clone(true).removeClass('caa_click caa_row_hover').appendTo(modal).byClass('submission_row').remove(); }); }); editHolder.animate({ 'max-height': '200px', padding: '20px' }); } }), enableEditMode = function() { srows = DOM().byClass('submission_row'); if (srows.exists()) { srows.elements.forEach(function(row) { var r = DOM(row); r.byTag('svg').css({ display: 'none' }); DOM().new('input').css({ 'pointer-events': 'none' }).attr({ type: 'checkbox', name: 'submission-' + row.parentNode.getAttribute('data-id') }).class('ib middle').appendTo(r); }); } }, searchFilter = function(e) { var gridItems = DOM().byClass('caa_row'); var Search = e.target.value || ''; clearTimeout(searchTimer); searchTimer = setTimeout(function() { var searchAr = Search.split(/\\s */), searchRegex = ''; for (var s in searchAr) { if (searchAr[s]) { if (searchRegex) { searchRegex += '|'; } searchRegex += searchAr[s]; } } var Regex = new RegExp(searchRegex, 'i'); gridItems.elements.forEach(function(element, e) { var el = DOM(element), tagMatch = false, hasTags = el.attr('data-tags') || '', formMatch = false, hasForm = el.attr('data-form') || '', isSpam = el.attr('data-spam') || '', st = 0; if (filterTags.length) { for (st in filterTags) { if (hasTags.indexOf(filterTags[st] + ',') > -1) { tagMatch = true; } } } if(filterForm){ formMatch = hasForm.indexOf(filterForm) > -1 } if ( (Search && !Regex.test(el.text())) || (!tagMatch && filterTags.length) || (filterForm && !formMatch) || (filterSpam && !isSpam)) { el.css({ display: 'none' }); } else { el.css({ display: '' }); } }); }, 200); }; var searchBox = Inputs.search({ label: 'Find Submissions' }).addClass('ib bottom').css({ //margin: 0, width: '200px' }).appendTo(header); Inputs.options({ label: 'From Form', options: [{text: 'Show All', value : ''}, {text: 'Spam', value : 'spam'}].concat(app.getForms()), onchange: function(val){ filterSpam = false; filterForm = ''; if(val === 'spam'){ filterSpam = true; } else { filterForm = (val || '') + ''; } searchFilter({ target: byID('caa-screen-search') }) } }).addClass('ib bottom').css({ //margin: 0, 'margin-left': '10px', width: '200px' }).appendTo(header); searchBox.byTag('input').id('caa-screen-search').on('input change', searchFilter); var tagList = DOM().new('div').class('caa_click').css({ position: 'absolute', top: '12px', right: '4px' }).append(UI.Icon('tags').on('click', function(e) { if (tagList.expanded) { tagList.expanded = false; tagHolder.animate({ 'max-height': 0, padding: 0 }); } else { tagHolder.html(''); tagList.expanded = true; if (allTags.length) { allTags.forEach(function(tag) { DOM().new('label').css({ padding: '8px' }) .append(DOM().new('input').class('ib middle').attr({ type: 'checkbox', checked: (filterTags.indexOf(tag) > -1) }).on('change', function(e) { var i = filterTags.indexOf(tag); if (i < 0) { filterTags.push(tag); } else { filterTags.splice(i, 1); } searchFilter({ target: byID('caa-screen-search') }); })) .append(DOM().new('span').class('ib middle').text(tag)) .appendTo(tagHolder); }); // } else { DOM().new('i').text('You are not using any tags').appendTo(tagHolder); } tagHolder.animate({ 'max-height': '20px', padding: '16px 0', 'text-align': 'right' }); } })).appendTo(header), allTags = [], filterTags = [], filterForm = '', filterSpam = false, tagHolder = DOM().new('div').css({ 'max-height': 0, 'overflow': 'hidden' }).appendTo(header), editHolder = DOM().new('div').css({ 'max-height': 0, 'overflow': 'hidden' }).appendTo(header), exportButton = UI.Icon('download').addClass('caa_click') .on('click', function(e) { if (tagList.expanded) { tagList.expanded = false; tagHolder.animate({ 'max-height': 0, padding: 0 }); } else { tagHolder.html(''); tagList.expanded = true; var downloadButton = DOM().new('a').class('ibb middle').text('Preparing CSV...').appendTo(tagHolder); app.Request({ do: 'request', request: 'submissions-all' }, function(data) { console.log('data', data) var keys = { _date: true }, csv = '', k, r; app.submissions[app.site.id] = data.submissions; if (data.submissions) { for (r in data.submissions) { if (filter(data.submissions[r])) { for (k in data.submissions[r]) { if (k && k !== 'id') { keys[k] = true; } } } } for (k in keys) { if(k === '_date'){ csv += '"Date",'; } else { csv += '"' + k + '",'; } } csv += '\n'; for (r in data.submissions) { if (filter(data.submissions[r])) { var val = ''; for (k in keys) { val = (data.submissions[r][k] || '') + ''; if(k === '_date'){ val = displayDate(val, 'time'); } if (val) { if (val.indexOf('#') > -1) { val = encodeURIComponent(val); } csv += '"' + ((val || '') + '').replace(/"/g, '\\"') + '",'; } else { csv += ','; } } csv += '\n'; } } } var csvContent = 'data:text/csv;charset=utf-8,' + csv; var encodedUri = encodeURI(csvContent); //console.log('csv', csvContent) downloadButton.text('Download CSV').attr({ href: encodedUri, download: ((app.site.name || '') + ' Submissions').idSafe() + '.csv' }).trigger('click'); }); tagHolder.animate({ 'max-height': '20px', padding: '16px 0', 'text-align': 'right' }); } }).insertFirst(tagList).css({ 'margin-right': '20px' }); editIcon.insertFirst(tagList).css({ 'margin-right': '20px', 'margin-bottom': '-6px' }); subHolder = DOM().new('div').appendTo(content); UI.Spinner('24').addClass('caa_padding').appendTo(subHolder); app.Request({ do: 'request', request: 'submissions' }, function(data) { subHolder.html(''); if (Array.isArray(data.submissions)) { data.submissions.reverse().forEach(function(sub, s, ar) { var tags = ''; if (sub.tags) { tags = sub.tags.join(', '); sub.tags.forEach(function(tag) { if (tag && allTags.indexOf(tag) < 0) { allTags.push(tag); } }); } if (filter(sub)) { var icon, bold = 'normal'; if (sub.read) { icon = UI.Icon('eye', 'menu2'); } else { icon = UI.Icon('invisible', 'menu2'); icon.byTag('use').css({ fill: 'red' }); bold = 'bold'; } var row = DOM().new('div').class('caa_row caa_click caa_row_hover ellipsis').css({ 'font-weight': bold, 'padding-right': '30px', 'padding-left': '40px' }) .attr({ 'data-id': sub.id, 'data-tags': sub.tags ? ',' + sub.tags.join(',') + ',' : '', 'data-form': sub.formPath, 'data-spam': sub.spam ? '1' : 0 }) .append(DOM().new('div').text('#' + (ar.length - s) + ' ' + displayDateLocal(sub.date) + ' ' + sub.from)) .append(DOM().new('div').css({ 'font-size': '10px', 'font-weight': 'normal' }).text(tags)) .appendTo(subHolder).on('click', function(e) { if (editIcon.enabled) { var input = row.byTag('input'); input.attr({ checked: !input.elements[0].checked }); } else { app.render('/submissions/' + sub.id, false, false); } }).append(icon.addClass('submission_row').css({ position: 'absolute', left: '16px', top: '18px' })); if (sub.files) { UI.Icon('attachment', 'menu2').appendTo(row).css({ position: 'absolute', right: '4px', top: '18px' }); } } }); if (editIcon.enabled) { enableEditMode(); } } }); } }; App.prototype.support = function(into, type){ var app = this; var supportContent = DOM().newOrFind('div', 'supportContent').html('').class('caa_padding').appendTo(into), subscription = 'trial'; // reexecutes if billing info shows up later in check site if(app.billingInfo){ if(app.billingInfo[app.site.id]){ if(app.billingInfo[app.site.id]){ subscription = app.billingInfo[app.site.id].subscription || 'trial'; } } } DOM().new('div').html('Check out our support content at
blux.com/support
').appendTo(supportContent); if(subscription === '199'){ DOM().new('div').css({'margin-top':'20px'}).html('This site has a premium Blux subscription. Please contact
support@blux.com
for any assistance you may need.').appendTo(supportContent); } }; App.prototype.usage = function(into, type) { var app = this, siteURL = app.siteURL(); var logsHolder = DOM().new('div').addClass('caa_padding').appendTo(into).append(UI.Spinner('24').css({ 'padding-right': '20px' })) .append(DOM().new('span').class('ib middle').text('Looking up request logs...')), storageHolder = DOM().new('div').addClass('caa_padding').appendTo(into).append(UI.Spinner('24').css({ 'padding-right': '20px' })) .append(DOM().new('span').class('ib middle').text('Looking up storage usage status...')); app.Request({ do: 'request', request: 'logs', cache: true }, function(data) { logsHolder.html(''); var tbl = DOM().new('table').class('caa_table').html('
Day
# Requests
Bandwidth
'); var tblBody = tbl.byTag('tbody'), numReq = 0, bandwidth = 0, viewButton = DOM().new('a').class('caa_button-default').text('Show Daily Usage').on('click', function(e) { if (viewButton.showing) { tbl.appendTo(DOM().new('div')); viewButton.showing = false; viewButton.text('Show Daily Usage'); } else { tbl.appendTo(logsHolder); viewButton.showing = true; viewButton.text('Hide Daily Usage'); } }).css({ 'margin-left': '10px' }); if (data.siteLogs.daily) { Object.keys(data.siteLogs.daily).sort().reverse().forEach(function(day) { var row = data.siteLogs.daily[day]; DOM().new('tr') .append( DOM().new('td').text(displayDate(day)) ) .append( DOM().new('td').text(row.requests) ) .append( DOM().new('td').text(formatBytes(row.bandwidth)) ).appendTo(tblBody).on('click', function(e) { var modal = UI.openModal(DOM(e.target)); var modalContent = DOM().new('div').class('caa_padding').text('Loading logs for ' + displayDate(day)).appendTo(modal); app.Request({ do: 'request', request: 'logs', day: day }, function(dayData) { modalContent.html('Request logs for ' + displayDate(day)); if (dayData.siteLogs.items) { dayData.siteLogs.items.forEach(function(req) { var text = ''; for (var k in req) { text += req[k] + ' '; } DOM().new('div').css({ 'background-color': '#333', color: '#fff', padding: '2px', 'margin-bottom': '2px' }).text(text).appendTo(modalContent); }); } }); }); if (row.bandwidth) { bandwidth += row.bandwidth; numReq++; } }); } DOM().new('div').text('Website Requests: ' + numReq + ' requests, ' + formatBytes(bandwidth) + ' bandwidth').append(viewButton).insertFirst(logsHolder); }); app.Request({ do: 'request', request: 'files', cache: true }, function(data) { storageHolder.html(''); var tbl = DOM().new('table').class('caa_table').html('
CDN
path
size
modified
options
'); var tblBody = tbl.byTag('tbody'), numFiles = 0, size = 0, viewButton = DOM().new('a').class('caa_button-default').text('Show Files').on('click', function(e) { if (viewButton.showing) { tbl.appendTo(DOM().new('div')); viewButton.showing = false; viewButton.text('Show Files'); } else { tbl.appendTo(storageHolder); viewButton.showing = true; viewButton.text('Hide Files'); } }).css({ 'margin-left': '10px' }); if (data.files) { data.files.forEach(function(file) { var options = DOM().new('span').html(' '); if (file.cdn === 'media') { var mediaID = file.key.split('.')[0]; if(mediaID && !app.site.media[mediaID]){ options = DOM().new('button').text('Delete From Server').on('click', function(e){ e.target.disabled = true; e.target.innerText = 'Deleting...'; app.Request({ do: 'request', request: 'deleteMedia', mediaID: mediaID }, function(data) { if (data.success) { e.target.parentNode.parentNode.parentNode.removeChild(e.target.parentNode.parentNode); } else { DOM(e.target).text('Error! Could not delete!').attr({disabled: false}); } }); }); } } var href = file.cdn === 'media' ? ca_config.media_cdn + '/' + app.site.id + '/' + file.key : siteURL + '/' + file.key.replace(/\.html$/, ''); DOM().new('tr') .append( DOM().new('td').text(file.cdn) ) .append( DOM().new('td').append(DOM().new('a').attr({ href: href, target: '_blank' }).text(file.key || '')) ) .append( DOM().new('td').text(formatBytes(file.size)) ) .append( DOM().new('td').text(file.modified) ) .append( DOM().new('td').append(options) ) .appendTo(tblBody); if (file.size) { size += file.size; numFiles++; } }); } DOM().new('div').text('File Storage: ' + numFiles + ' files, ' + formatBytes(size) + ' staging/live site files, ' + formatBytes(data.changesRevisionSize) + ' blux revision history, ' + formatBytes(size + data.changesRevisionSize) + ' total.').append(viewButton).insertFirst(storageHolder); }); }; var Recommendations = function(app, config, callback) { var self = this, site = app.site, path = [], pathString = '', recs = [], recsOut = 0, recsDone = 0, loopTimer = false, dismissed = (site.settings || {}).dismissed || [], sendFinalCallback = false, completed = function() { recs.sort(function(a, b) { if (a.ok) { return 1; } else { return -1; } }); if (!sendFinalCallback) { callback(recs); sendFinalCallback = true; } }; self.config = {}; for (var k in config) { self.config[k] = config[k]; } self.addRec = function(config, test) { var rec = { type: 'general' }; for (var k in config) { rec[k] = config[k]; } recsOut++; test(function(ok) { rec.ok = ok; if (config.dismissible) { if (dismissed.indexOf(config.dismissible) > -1) { rec.dismissed = true; rec.ok = true; } } if (self.config.showAll || !ok) { recs.push(rec); } recsDone++; }); }; self.siteMap = function(site) { // this is duplicative of SiteMap.js if you change it there it has to be changed here var siteMap = [], content = site.content; self.urlMap = []; self.pageURLS = {}; Object.keys(content || {}).forEach(function(section) { if (content[section].length) { content[section].forEach(function(page, p) { var url = self.getPageURL(section, site.content[section][p], p); if (url) { var l = 1, title = (content[section][p]) ? content[section][p].title + '' : ''; if (p === 0) { l = 0; } siteMap.push({ title: title, url: url, section: section, p: p, l: l }); } }); } }); return siteMap; }; self.getPageURL = function(section, page, p) { if (!page) { return false; } var url = ''; if (p === 0) { url = (section !== 'pages') ? '/' + section : '/'; self.pageURLS[url] = true; } else { if (section !== 'pages') { url = '/' + section; } if (p > 0) { if (page.url) { url += '/' + page.url.replace(/\//g, ''); } else if (page.title) { url += '/' + page.title.toString().urlSafe(); } else { url += '/' + p; } } if (self.pageURLS[url]) { var baseURL = url + ''; var ticker = 2; var checkURL = baseURL + '-' + ticker; while (self.pageURLS[checkURL]) { ticker++; checkURL = baseURL + '-' + ticker; } url = checkURL + ''; } self.pageURLS[url] = true; } self.urlMap[section + p] = url; return url; }; self.checkSiteLoop = function(object, path, pathString) { if (object) { var self = this; if (path.length === 0) { this.checkSiteInfo(object, path, pathString); } else if (path.length === 3 && pathString.substr(0, 9) === '/content/' && pathString.substr(0, 20) !== '/content/__templates') { this.checkPage(object, path, pathString); } if (path.length > 1 && object.link) { this.checkLink(object, path, pathString); } Object.keys(object).forEach(function siteLoopObjectKeys(k) { if (typeof object[k] === 'object') { setTimeout(function siteLoopAsync() { self.checkSiteLoop(object[k], path.concat(k), pathString + '/' + k); }, 10); } else { if (path.length === 0) { } } }); clearTimeout(loopTimer); loopTimer = setTimeout(function() { if (recsDone >= recsOut && recsOut > 0) { completed(); } }, 20); } }; self.checkSiteInfo = function(object, path, pathString) { self.addRec({ title: 'Site Name', description: 'Set a site name that does not contain the default site name: "New Site"', type: 'siteName', link: '/settings', dismissible: 'siteName', path: '/' }, function(callback) { if (object.name && !object.name.match(/new site/gi)) { callback(true); } else { callback(false); } } ); self.addRec({ title: 'Logo and Navigation', description: 'Update the default navigation to include your site links and logo', type: 'initial', link: '/navigation', dismissible: 'logoNav', path: '/navigation' }, function(callback) { var ok = false; if (object.navigation) { if(object.navigation[0].version == '2'){ ok = true; } else { if (object.navigation[0]) { if (object.navigation[0].logo) { var logojson = JSON.stringify(object.navigation[0].logo); if (logojson !== '"{"text":""}"' && logojson !== '{"text":{}}') { ok = true; } } } } } callback(ok); } ); self.addRec({ title: 'Add Pages', description: 'Add or remove pages from your site', type: 'initial', link: '/content', dismissible: 'addPages', path: '/content' }, function(callback) { var ok = false; if (object.content) { if (object.content.pages) { if (object.content.pages.length !== 3) { ok = true; } } } callback(ok); } ); self.addRec({ title: 'Update Colors', description: 'Change the global color settings of your site design', type: 'initial', link: '/design', dismissible: 'designColors', path: '/design' }, function(callback) { var ok = false; if (object.styles) { if (object.styles.colors) { if (JSON.stringify(object.styles.colors) !== '{"text":"#000","background":"#fff","links":"#00f","icons":"#000"}') { ok = true; } } } callback(ok); } ); self.addRec({ title: 'Update Fonts', description: 'Change the font and text styles of your site design', type: 'initial', link: '/design', dismissible: 'designFonts', path: '/design' }, function(callback) { var ok = false; if (object.styles) { if (object.styles.text) { if (JSON.stringify(object.styles.text) !== '[{"_label":"Title (Default)",".text0":{"font-family":"Helvetica","font-size":"24px","padding":"10px","margin":"10px 0"}},{"_label":"Body (Default)",".text1":{"font-family":"Helvetica","padding":"10px","font-size":"16px"}},{"_label":"Sub-Title (Default)",".text2":{"font-family":"Helvetica","font-size":"20px","padding":"10px","margin":"4px 0"}},{"_label":"Sub-Body (Default)",".text3":{"font-family":"Helvetica","padding":"10px","font-size":"12px"}}]') { ok = true; } } } callback(ok); } ); self.addRec({ title: 'Add Favicon', description: 'Update the icon that represents your site in browser tabs and bookmarks', type: 'initial', link: '/settings', dismissible: 'favicon', path: '/settings' }, function(callback) { var ok = false; if (site.settings.favicon) { if (JSON.stringify(site.settings.favicon) !== '{}') { ok = true; } } callback(ok); } ); self.addRec({ title: 'Add Social Networks', description: 'Add the social profiles related to your site', type: 'initial', link: '/settings/social-accounts', dismissible: 'socialAccounts', path: '/settings/social' }, function(callback) { var ok = false; if (site.settings.social) { if (site.settings.social.length) { ok = true; } } callback(ok); } ); self.addRec({ title: 'Upload Photos', description: 'Upload or add media to your site', type: 'initial', link: '/media', dismissible: 'socialAccounts', path: '/media' }, function(callback) { var ok = false; if (Object.keys(site.media).length) { ok = true; } callback(ok); } ); self.addRec({ title: 'Add Google Analytics', description: 'Add your own google analytics tracking code so you can collect visitor information', type: 'initial', link: '/settings/integrations', dismissible: 'googleAnalytics', path: '/settings/googleAnalytics' }, function(callback) { var ok = site.settings.googleAnalytics ? true : false; callback(ok); } ); self.addRec({ title: 'Add Google Webmaster Tools', description: 'Add and verify google webmaster tools with your site', type: 'initial', link: '/settings/integrations', dismissible: 'googleWebmaster', path: '/settings/integrations/googleWebmasterVerifySite' }, function(callback) { var ok = false; if (site.settings) { if (site.settings.integrations) { if (site.settings.integrations.googleWebmasterVerifySite) { ok = true; } } } callback(ok); } ); self.addRec({ title: 'Add Facebook Insights', description: 'Add and verify facebook insights with your site', type: 'initial', link: '/settings/integrations', dismissible: 'facebookVerifySite', path: '/settings/integrations/facebookVerifySite' }, function(callback) { var ok = false; if (site.settings) { if (site.settings.integrations) { if (site.settings.integrations.facebookVerifySite) { ok = true; } } } callback(ok); } ); }; self.checkPage = function(object, path, pathString) { if (object) { self.addRec({ title: 'Page Title', description: 'Set a page title for: ' + self.objectName(object) + ' ' + pathString, type: 'title', link: pathString }, function(callback) { var ok = false; if (object.title) { if (object.title.length > 1) { ok = true; } } callback(ok); } ); self.addRec({ title: 'Page Meta Description', description: 'Set a page meta description for: ' + self.objectName(object) + ' ' + pathString, type: 'description', link: pathString }, function(callback) { var ok = false; if (object.description) { if (object.description.length > 1) { ok = true; } } callback(ok); } ); } }; self.checkLink = function(object, path, pathString) { if (object) { var link = object.link; if (link) { link = object.link.split('#')[0].split('?')[0]; } var four = link.substr(0, 4); if (link && four !== 'http' && four !== 'mail' && link.substr(0, 2) != '//' && link != '/') { if (!self.pageURLS[link]) { self.addRec({ title: 'Internal Link', description: 'Internal link does not exist: ' + self.objectName(object) + ' ' + link, type: 'link', path: pathString, link: pathString.replace(/items\//g, '') }, function(callback) { var ok = false; callback(ok); } ); } } } }; self.objectName = function(object) { return object.title || object.name || object._label; } //this.siteMap(site); // run to populate self.urlMap self.pageURLS = {}; app.publishSiteMap(function(siteMap) { siteMap.forEach(function(page){ self.pageURLS[page.url] = true; }) self.checkSiteLoop(site, path, pathString); }); }; if (typeof module !== 'undefined') { String.prototype.urlSafe = function() { return this.toString().toLowerCase().replace(/[^a-z0-9\-]/gi, '-').replace(/\-\-/g, '-').replace(/\-\-/g, '-'); }; module.exports = Recommendations; } if (typeof module !== 'undefined') { module.exports = function(devmode){ if(typeof devmode === 'undefined'){ devmode = process.env.NODE_ENV === 'development'; } return { media_cdn: '//dv4tl7yyk1zlp.cloudfront.net', optimize_cdn: devmode ? 'http://50c44f5d-b12d-4df9-a9e3-6dbebd0db35c.localhost:8071/__media' : '//d3syaxnfm3oj0e.cloudfront.net', blux_ips: ['54.214.8.151', '54.214.2.207'] }; }; } else { ca_config = { media_cdn: '//dv4tl7yyk1zlp.cloudfront.net', optimize_cdn: devmode ? 'http://50c44f5d-b12d-4df9-a9e3-6dbebd0db35c.localhost:8071/__media' : '//d3syaxnfm3oj0e.cloudfront.net', blux_ips: ['54.214.8.151', '54.214.2.207'], def_profile: 'url("data:image/svg+xml;charset=utf8,' + encodeURIComponent('
') + '")' }; } /** * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011) * * @author
Gary Court
* @see http://github.com/garycourt/murmurhash-js * @author
Austin Appleby
* @see http://sites.google.com/site/murmurhash/ * * @param {string} key ASCII only * @param {number} seed Positive integer only * @return {number} 32-bit positive integer hash */ function murmurhash3_32_gc(key, seed) { var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i; remainder = key.length & 3; // key.length % 4 bytes = key.length - remainder; h1 = seed; c1 = 0xcc9e2d51; c2 = 0x1b873593; i = 0; while (i < bytes) { k1 = ((key.charCodeAt(i) & 0xff)) | ((key.charCodeAt(++i) & 0xff) << 8) | ((key.charCodeAt(++i) & 0xff) << 16) | ((key.charCodeAt(++i) & 0xff) << 24); ++i; k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; k1 = (k1 << 15) | (k1 >>> 17); k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; h1 ^= k1; h1 = (h1 << 13) | (h1 >>> 19); h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); } k1 = 0; switch (remainder) { case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; case 1: k1 ^= (key.charCodeAt(i) & 0xff); k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; k1 = (k1 << 15) | (k1 >>> 17); k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; h1 ^= k1; } h1 ^= key.length; h1 ^= h1 >>> 16; h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; h1 ^= h1 >>> 13; h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; h1 ^= h1 >>> 16; return h1 >>> 0; } var murmur = murmurhash3_32_gc; if (typeof module !== 'undefined' && module.exports) { module.exports = murmurhash3_32_gc; } function num(val) { if (!val) { return 0; } if (typeof val !== 'number') { return parseFloat(val.replace(/[^\d.]+/g, '')); } else { return val; } } function _hasItems(arrayOrObject) { if (typeof arrayOrObject !== 'object') { return false; } else { if (Array.isArray(arrayOrObject)) { return arrayOrObject.length; } else { return Object.keys(arrayOrObject).length; } } return false; } function formatBytes(size) { var base = Math.log(size) / Math.log(1024); var suffixes = ['', 'kb', 'mb', 'gb', 'tb']; return ((Math.round(Math.pow(1024, base - Math.floor(base))) * 10) / 10) + suffixes[Math.floor(base)]; } function anyTypeToExtension(type) { var ret = false; if (!type) { return false; } type = type.toLowerCase(); if (type === 'image/png' || type === 'png') { ret = 'png'; } else if (type === 'image/jpg' || type === 'image/jpeg' || type === 'jpg' || type === 'jpeg') { ret = 'jpg'; } else if (type === 'image/gif') { ret = 'gif'; } else if (type === 'image/svg+xml' || type === 'svg') { ret = 'svg'; } else if (type === 'text/plain' || type === 'txt' || type === 'text') { ret = 'txt'; } else if (type === 'video/mp4' || type === 'mp4') { ret = 'mp4'; } else if (type === 'audio/mpeg' || type === 'audio/mp3' || type === 'mp3') { ret = 'mp3'; } else if (type === 'text/html' || type === 'html') { ret = 'html'; } else if (type === 'application/json' || type === 'json') { ret = 'json'; } else if (type === 'application/pdf' || type === 'x-pdf' || type === 'pdf') { ret = 'pdf'; } else if (type === 'application/font-woff' || type === 'application/x-font-woff' || type === 'font/woff') { ret = 'woff'; } else if (type === 'application/font-woff2' || type === 'application/x-font-woff2' || type === 'font/woff2') { ret = 'woff2'; } return ret; } function extensionToContentType(type) { var ret = ''; if (typeof type !== 'string') { type = ''; } type = type.toLowerCase(); if (type === 'png') { ret = 'image/png'; } else if (type === 'jpg' || type === 'jpeg') { ret = 'image/jpeg'; } else if (type === 'gif') { ret = 'image/gif'; } else if (type === 'svg') { ret = 'image/svg+xml'; } else if (type === 'mp4') { ret = 'video/mp4'; } else if (type === 'txt') { ret = 'text/plain'; } else if (type === 'html') { ret = 'text/html'; } else if (type === 'json') { ret = 'application/json'; } else if (type === 'pdf') { ret = 'application/pdf'; } else if (type === 'woff') { ret = 'application/font-woff'; } else if (type === 'woff2') { ret = 'application/font-woff2'; } return ret; } function getExtension(url) { url = url + ''; var ret = '', i = 0, spl = url.split('?')[0].split('.'); for (i in spl) { if (spl[i]) { ret = spl[i]; } } return ret; } function getInfoFromPath(url) { var ext = url.split('.').pop(); var type = extensionToContentType(ext); if (!type) { type = ''; if (url.indexOf('jpg') > -1) { ext = 'jpg'; type = extensionToContentType(ext); } else if (url.indexOf('png') > -1) { ext = 'png'; type = extensionToContentType(ext); } else if (url.indexOf('svg') > -1) { ext = 'svg'; type = extensionToContentType(ext); } else if (url.indexOf('pdf') > -1) { ext = 'pdf'; type = extensionToContentType(ext); } } return { type: type, ext: ext }; }; function isoDate(input) { if (!input) { return false; } if (typeof input === 'string') { input = parseAnyDate(input); } if (!input instanceof Date) { input = new Date(); } var ret; try { ret = input.toISOString().substr(0, 10); } catch (e) { return new Date(); } return ret; } function mathDate(input) { if (!input) { return input; } // not tested return input.toISOString(); return input.getTime(); } function parseAnyDate(e, r) { "use strict"; if (!e || "string" != typeof e) return !t instanceof Date ? !r && new Date : e; if (8 === e.length && !isNaN(e)) { var t = new Date(e.substr(0, 4), e.substr(4, 2) - 1, e.substr(6, 2)); if (t) return t } var a = Date.parse(e); if (!isNaN(a)) return new Date(a); e && !isNaN(e) && (e += ""); var s = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"], i = ["th", "st", "rd", "nd"], n = !1, d = "", t = { h: 0, mi: 0, s: 0 }, m = function(e, r, a) { if (e || "0" === e) { if (isNaN(e)) { n = !1; var d = s.indexOf(e.substr(0, 3).toLowerCase()); if (d > -1) return void(t.m = d + 1 + ""); var m = i.indexOf(e.replace(/[^a-z]/gi, "").toLowerCase()); if (e = e.replace(/[^0-9]/g, ""), m > -1) return void(t.d = e) } else n = !0; if (t.y && t.m && t.d) t.h ? t.mi ? t.s || (t.s = e) : t.mi = e : t.h = e; else { if (!t.d && (t.m || t.y)) return void(t.d = e); t.y || (4 === e.length && n ? t.y = e : t.m && t.d && (t.y = e)), t.m || (t.m = e) } } }; e.split(/[^A-Za-z0-9]/).forEach(m), t.d < 10 && (t.d = "0" + 1 * t.d), t.m < 10 && (t.m = "0" + 1 * t.m), d = t.y + "-" + t.m + "-" + t.d, (t.h || t.mi || t.s) && (t.h < 10 && (t.h = "0" + 1 * t.h), t.mi < 10 && (t.mi = "0" + 1 * t.mi), t.s < 10 && (t.s = "0" + 1 * t.s), d += "T " + t.h + ":" + t.mi + ":" + t.s); var a = Date.parse(d); return isNaN(a) ? !r && new Date : new Date(a) } "undefined" != typeof module && "undefined" != typeof module.exports && (module.exports = parseAnyDate); function displayDate(isoDateString, what) { var ret = ''; if (isoDateString) { var d = new Date(isoDateString); if (what === 'time' && isoDateString.length > 15) { var minutes = d.getUTCMinutes(), hour = d.getUTCHours(), ampm = 'AM'; if (minutes < 10) { minutes = '0' + minutes; } if (hour > 11) { ampm = 'PM'; } if (hour > 12) { hour = (hour - 12); } ret = (d.getUTCMonth() + 1) + '/' + d.getUTCDate() + '/' + d.getUTCFullYear() + ' ' + hour + ':' + minutes + ' ' + ampm; return ret; } else { ret = (d.getUTCMonth() + 1) + '/' + d.getUTCDate() + '/' + d.getUTCFullYear(); return ret; } } return ret; } function displayDateLocal(isoDateString, what) { var ret = ''; if (isoDateString) { var d = new Date(isoDateString); if (what === 'time' && (isoDateString.length > 15 || !isNaN(isoDateString))) { var minutes = d.getMinutes(), hour = d.getHours(), ampm = 'AM'; if (minutes < 10) { minutes = '0' + minutes; } if (hour > 11) { ampm = 'PM'; } if (hour > 12) { hour = (hour - 12); } ret = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear() + ' ' + hour + ':' + minutes + ' ' + ampm; return ret; } else { ret = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear(); return ret; } } return ret; } function getFirstOfMonth(d, monthOffset) { if (!(d instanceof Date)) { if (d) { d = new Date(d); } else { d = new Date(); } } if (!monthOffset) { monthOffset = 0; } return new Date(d.getFullYear(), d.getMonth() + monthOffset, 1, 0, 0, 0, 0).toISOString().substr(0, 10); } function displayNumber(number, how, blankIfZero) { if (blankIfZero && !number) { return ''; } var n = num(number); n = n.toString(); if (n.indexOf('.') > -1) { var parts = n.split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); n = parts.join('.'); } else { n = n.replace(/\B(?=(\d{3})+(?!\d))/g, ','); } if (how === 'USD') { n = '$' + ((n * 1).toFixed(2)); } return n; } function uuid() { return (function b(a) { return a ? (a ^ Math.random() * 16 >> a / 4).toString(16) : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, b); })(); } // credit: https://gist.github.com/lucasmotta/9a2e7e3128d0dd282e5a function Template(str, obj, onlyIfExists) { return str.replace(/{{*([\w\.\:\-]+)*}}/g, function(tag, match) { // if a string has a : it is special for blux custom elements, otherwise treat dots as object tree hierarchy var nodes = match.indexOf(':') < 0 ? match.split(".") : [match], current = obj, length = nodes.length, i = 0; while (i < length) { if (typeof current[nodes[i]] !== 'undefined') { return current[nodes[i]]; } else { if (onlyIfExists) { return tag; } else { return ''; } } current = current[nodes[i]]; i++; } return current; }); } function userAccountBalance(user, billingInfo) { var transactions = [], payments = [], balances = {}, paymentsDue = {}; if (user.sites) { user.sites.forEach(function(siteID) { if (user.id) { var siteBilling = billingInfo[siteID]; if (siteBilling) { if (siteBilling.owner === user.id) { if (!siteBilling.card || !user.cards[siteBilling.card]) { siteBilling.card = '__nocard'; } if (siteBilling.invoices) { for (var i in siteBilling.invoices) { if (!siteBilling.invoices[i].next) { if (siteBilling.invoices[i].amount) { transactions.push({ site: siteID, card: siteBilling.card, site_card: siteBilling.card, date: parseAnyDate(i), type: 'invoice', invoice: siteBilling.invoices[i], debit: siteBilling.invoices[i].amount * 1, credit: 0 }); } } } if (siteBilling.payments) { siteBilling.payments.forEach(function(payment) { transactions.push({ site: siteID, card: payment.card, site_card: siteBilling.card, date: payment.date, type: 'payment', payment: payment, debit: 0, credit: payment.amount * 1 }); }); } } } } } }); transactions.sort(function(a, b) { if (!a.compareTime) { a.compareTime = new Date(a.date).getTime(); } if (!b.compareTime) { b.compareTime = new Date(b.date).getTime(); } return a.compareTime - b.compareTime; }).forEach(function(transaction) { if (!balances[transaction.site_card]) { balances[transaction.site_card] = {}; } if (!balances[transaction.site_card][transaction.site]) { balances[transaction.site_card][transaction.site] = 0; } // per site balances[transaction.site_card][transaction.site] -= transaction.credit; balances[transaction.site_card][transaction.site] += transaction.debit; }); Object.keys(balances).forEach(function(cardID) { Object.keys(balances[cardID]).forEach(function(siteID) { if (!paymentsDue[cardID]) { paymentsDue[cardID] = 0; } if (balances[cardID][siteID] > 0) { paymentsDue[cardID] += balances[cardID][siteID]; } }); }); } return { paymentsDue: paymentsDue, balances: balances, transactions: transactions, payments: transactions.filter(function(transaction) { if (transaction.type !== 'payment') { return false; } else { return true; } }) }; } function getSitePermissions(user, site) { var access = { admin: false, paths: [] }; if (site.owner === user.id) { access.admin = true; } if (site) { if (site.settings) { if (Array.isArray(site.settings.collaborators)) { site.settings.collaborators.forEach(function(item, i) { if (item && item.email === user.email) { if (item.type === 'Administrator' && !item.paths) { access.admin = true; // tmp for previous premissions } if (item.paths) { access.paths = item.paths; } if (item.admin) { access.admin = true; } } }); } } } return access; } function hasSiteAccess(access, path, fuzzyPath) { var ret = false; if (typeof access === 'object') { if (access.admin) { ret = true; } else { if (access.paths.indexOf(path) > -1) { ret = true; } else { // checks if the user has access to a higher level path than the one checking access.paths.forEach(function(apath) { if (path.indexOf(apath + '/') > -1) { ret = true; } }); // checks if the user has access to a lower level path and fuzzy is good to allow for showing parent sections if (!ret && fuzzyPath) { access.paths.forEach(function(apath) { if (apath.substr(0, path.length) + '/' === path + '/') { ret = true; } }); } } } } return ret; } function getFirstMedia(object, type, allMedia) { var media = false, checkMedia = false, k; for (k in object) { if (k === 'media' || k === 'backgroundMedia') { if (typeof object[k] === 'object') { media = object[k]; checkMedia = media; if (media.media && allMedia) { checkMedia = allMedia[media.media]; } if (checkMedia && checkMedia.type && checkMedia.type.substr(0,6) === 'image/' && checkMedia.type.indexOf('svg') < 0) { return media; } } } } for (k in object) { if (typeof object[k] === 'object') { media = getFirstMedia(object[k], type, allMedia); if (media) { return media; } } } return media; } function mediaSource(site, media, size) { var ret = false, mediaID, isCA = 0; if (media) { if (typeof media === 'string') { mediaID = media; media = site.media[media]; } else { if (media.media) { mediaID = media.media; media = site.media[media.media]; } } if (typeof media === 'object') { if (media.type) { var ext = anyTypeToExtension(media.type); if (ext === 'jpg' || ext === 'png' || ext === 'gif') { var pickedSize = 0; if (media.src) { ret = media.src; } else if (size !== 'full') { size = size * 1; if (!size) { size = 1000; } ret = ca_config.optimize_cdn + '/' + (media.siteID || site.id) + '/w:' + size + '/' + mediaID + '.' + ext; } else { ret = ca_config.media_cdn + '/' + (media.siteID || site.id) + '/' + mediaID + '.' + ext; isCA = 1; } } } } if (ret) { if (ret.substr(0, 2) === '//') { if (isCA) { ret = 'https:' + ret; } else { ret = 'http:' + ret; } } } } return ret; } function cleanDomain(str) { return (str || '').toLowerCase().replace(/[^a-z0-9\-\.]/gi, ''); } function reallyCleanDomain(str) { // removes https:// var domain = (str || ''); if(domain.indexOf('\:\/\/') > -1){ domain = domain.split('://')[1] || ''; } return domain.toLowerCase().replace(/[^a-z0-9\-\.]/gi, ''); } function validDomain(str) { var valid = true, parts = cleanDomain(str).split('.'); if (parts.length < 2) { valid = false; } else { for (var k in parts) { if (!parts[k]) { valid = false; } } } return valid; } function validEmail(email) { if (!email) { return false; } var re = new RegExp(/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/); return re.test(email); } if (typeof window === 'undefined') { // ensure you are in browser/electron and not node try { ca_config = require('./ca_config.js')(), module.exports = { _hasItems: _hasItems, formatBytes: formatBytes, getExtension: getExtension, getInfoFromPath: getInfoFromPath, anyTypeToExtension: anyTypeToExtension, extensionToContentType: extensionToContentType, Template: Template, isoDate: isoDate, mathDate: mathDate, parseAnyDate: parseAnyDate, getFirstOfMonth: getFirstOfMonth, displayDate: displayDate, displayDateLocal: displayDateLocal, displayNumber: displayNumber, userAccountBalance: userAccountBalance, getSitePermissions: getSitePermissions, hasSiteAccess: hasSiteAccess, getFirstMedia: getFirstMedia, mediaSource: mediaSource, cleanDomain: cleanDomain, reallyCleanDomain: reallyCleanDomain, validDomain: validDomain, validEmail: validEmail, uuid: uuid }; } catch (e) { console.error(e); } } setTimeout(function initApp() { new App().init(); }, 0);})(); (function() { /* (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','/__analytics.js','ga'); ga('create', 'UA-67566170-2', 'auto'); ga('send', 'pageview'); //disable blux analytics for now for performance debug */ /*! color2color v0.2.1 indyarmy.com by Russ Porosky IndyArmy Network, Inc. */ (function(window, undefined) { "use strict"; var color2color = (function() { var color2color = function(color, newColor, calculateOpacity) { if (!newColor) { newColor = "rgba"; } color = color.toLowerCase(); newColor = newColor.toLowerCase(); var namedColor = getNamedColor(color), colorDefs = [{ re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, example: ["rgb(123, 234, 45)", "rgb(255,234,245)"], process: function(bits) { return [ parseInt(bits[1], 10), parseInt(bits[2], 10), parseInt(bits[3], 10), 1 ]; } }, { re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d+(?:\.\d+)?|\.\d+)\s*\)/, example: ["rgba(123, 234, 45, 1)", "rgba(255,234,245, 0.5)"], process: function(bits) { return [ parseInt(bits[1], 10), parseInt(bits[2], 10), parseInt(bits[3], 10), parseFloat(bits[4]) ]; } }, { re: /^hsl\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)$/, example: ["hsl(120, 100%, 25%)", "hsl(0, 100%, 50%)"], process: function(bits) { bits[4] = 1; var rgba = hslToRgb(bits); return [ rgba.r, rgba.g, rgba.b, rgba.a ]; } }, { re: /^hsla\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,\s*(\d+(?:\.\d+)?|\.\d+)\s*\)/, example: ["hsla(120, 100%, 25%, 1)", "hsla(0, 100%, 50%, 0.5)"], process: function(bits) { var rgba = hslToRgb(bits); return [ rgba.r, rgba.g, rgba.b, rgba.a ]; } }, { re: /^hsv\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)$/, example: ["hsv(120, 100%, 25%)", "hsl(0, 100%, 50%)"], process: function(bits) { var rgb = hsvToRgb(bits); return [ rgb.r, rgb.g, rgb.b, 1 ]; } }, { re: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, example: ["#00ff00", "336699"], process: function(bits) { return [ parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16), 1 ]; } }, { re: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, example: ["#fb0", "f0f"], process: function(bits) { return [ parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16), 1 ]; } }], r, g, b, a, i, re, processor, bits, channels, min, hsl, hsv, retcolor; if (namedColor) { color = namedColor; } else { color = color.replace(/^\s*#|\s*$/g, ""); if (color.length === 3) { color = color.replace(/(.)/g, "$1$1"); } } // search through the definitions to find a match for (i = 0; i < colorDefs.length; i += 1) { re = colorDefs[i].re; processor = colorDefs[i].process; bits = re.exec(color); if (bits) { channels = processor(bits); r = channels[0]; g = channels[1]; b = channels[2]; a = channels[3]; } } r = (r < 0 || isNaN(r)) ? 0 : ((r > 255) ? 255 : r); g = (g < 0 || isNaN(g)) ? 0 : ((g > 255) ? 255 : g); b = (b < 0 || isNaN(b)) ? 0 : ((b > 255) ? 255 : b); a = (a < 0 || isNaN(a)) ? 0 : ((a > 1) ? 1 : a); switch (newColor) { case "rgba": if (calculateOpacity) { a = (255 - (min = Math.min(r, g, b))) / 255; r = (0 || (r - min) / a).toFixed(0); g = (0 || (g - min) / a).toFixed(0); b = (0 || (b - min) / a).toFixed(0); a = a.toFixed(4); } retcolor = "rgba(" + r + "," + g + "," + b + "," + a + ")"; break; case "rgb": retcolor = "rgb(" + r + "," + g + "," + b + ")"; break; case "hex": retcolor = "#" + ("0" + r.toString(16)).slice(-2) + ("0" + g.toString(16)).slice(-2) + ("0" + b.toString(16)).slice(-2); break; case "hsl": hsl = rgbToHsl({ "r": r, "g": g, "b": b }); retcolor = "hsl(" + hsl.h + "," + hsl.s + "%," + hsl.l + "%)"; break; case "hsla": hsl = rgbToHsl({ "r": r, "g": g, "b": b, "a": a }); retcolor = "hsl(" + hsl.h + "," + hsl.s + "%," + hsl.l + "%," + hsl.a + ")"; break; case "hsv": hsv = rgbToHsv({ "r": r, "g": g, "b": b }); retcolor = "hsv(" + hsv.h + "," + hsv.s + "%," + hsv.v + "%)"; break; } return retcolor; }, hslToRgb = function(bits) { var rgba = {}, v, q, p, hsl = { h: toPercent(parseInt(bits[1], 10) % 360, 360), s: toPercent(parseInt(bits[2], 10) % 101, 100), l: toPercent(parseInt(bits[3], 10) % 101, 100), a: parseFloat(bits[4]) }; if (hsl.s === 0) { v = parseInt(Math.round(255 * hsl.l)); rgba = { r: v, g: v, b: v, a: hsl.a }; } else { q = hsl.l < 0.5 ? hsl.l * (1 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s; p = 2 * hsl.l - q; rgba.r = parseInt((hueToRgb(p, q, hsl.h + 1 / 3) * 256).toFixed(0), 10); rgba.g = parseInt((hueToRgb(p, q, hsl.h) * 256).toFixed(0), 10); rgba.b = parseInt((hueToRgb(p, q, hsl.h - 1 / 3) * 256).toFixed(0), 10); rgba.a = hsl.a; } return rgba; }, rgbToHsl = function(rgba) { rgba.r = toPercent(parseInt(rgba.r, 10) % 256, 256); rgba.g = toPercent(parseInt(rgba.g, 10) % 256, 256); rgba.b = toPercent(parseInt(rgba.b, 10) % 256, 256); var max = Math.max(rgba.r, rgba.g, rgba.b), min = Math.min(rgba.r, rgba.g, rgba.b), hsl = [], d; hsl.a = rgba.a; hsl.l = (max + min) / 2; if (max === min) { hsl.h = 0; hsl.s = 0; } else { d = max - min; hsl.s = hsl.l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case rgba.r: hsl.h = (rgba.g - rgba.b) / d + (rgba.g < rgba.b ? 6 : 0); break; case rgba.g: hsl.h = (rgba.b - rgba.r) / d + 2; break; case rgba.b: hsl.h = (rgba.r - rgba.g) / d + 4; break; } hsl.h /= 6; } hsl.h = parseInt((hsl.h * 360).toFixed(0), 10); hsl.s = parseInt((hsl.s * 100).toFixed(0), 10); hsl.l = parseInt((hsl.l * 100).toFixed(0), 10); return hsl; }, hsvToRgb = function(bits) { var rgb = {}, hsv = { h: toPercent(parseInt(bits[1], 10) % 360, 360), s: toPercent(parseInt(bits[2], 10) % 101, 100), v: toPercent(parseInt(bits[3], 10) % 101, 100) }, i = Math.floor(hsv.h * 6), f = hsv.h * 6 - i, p = hsv.v * (1 - hsv.s), q = hsv.v * (1 - f * hsv.s), t = hsv.v * (1 - (1 - f) * hsv.s); switch (i % 6) { case 0: rgb.r = hsv.v; rgb.g = t; rgb.b = p; break; case 1: rgb.r = q; rgb.g = hsv.v; rgb.b = p; break; case 2: rgb.r = p; rgb.g = hsv.v; rgb.b = t; break; case 3: rgb.r = p; rgb.g = q; rgb.b = hsv.v; break; case 4: rgb.r = t; rgb.g = p; rgb.b = hsv.v; break; case 5: rgb.r = hsv.v; rgb.g = p; rgb.b = q; break; } rgb.r = parseInt(rgb.r * 256, 10); rgb.g = parseInt(rgb.g * 256, 10); rgb.b = parseInt(rgb.b * 256, 10); return { "r": rgb.r, "g": rgb.g, "b": rgb.b }; }, rgbToHsv = function(rgba) { rgba.r = toPercent(parseInt(rgba.r, 10) % 256, 256); rgba.g = toPercent(parseInt(rgba.g, 10) % 256, 256); rgba.b = toPercent(parseInt(rgba.b, 10) % 256, 256); var max = Math.max(rgba.r, rgba.g, rgba.b), min = Math.min(rgba.r, rgba.g, rgba.b), d = max - min, hsv = { "h": 0, "s": max === 0 ? 0 : d / max, "v": max }; if (max !== min) { switch (max) { case rgba.r: hsv.h = (rgba.g - rgba.b) / d + (rgba.g < rgba.b ? 6 : 0); break; case rgba.g: hsv.h = (rgba.b - rgba.r) / d + 2; break; case rgba.b: hsv.h = (rgba.r - rgba.g) / d + 4; break; } hsv.h /= 6; } hsv.h = parseInt((hsv.h * 360).toFixed(0), 10); hsv.s = parseInt((hsv.s * 100).toFixed(0), 10); hsv.v = parseInt((hsv.v * 100).toFixed(0), 10); return hsv; }, hueToRgb = function(p, q, t) { if (t < 0) { t += 1; } if (t > 1) { t -= 1; } if (t < 1 / 6) { return p + (q - p) * 6 * t; } if (t < 1 / 2) { return q; } if (t < 2 / 3) { return p + (q - p) * (2 / 3 - t) * 6; } return p; }, toPercent = function(amount, limit) { return amount / limit; }, getNamedColor = function(color) { var key, namedColor = null, namedColors = { aliceblue: "f0f8ff", antiquewhite: "faebd7", aqua: "00ffff", aquamarine: "7fffd4", azure: "f0ffff", beige: "f5f5dc", bisque: "ffe4c4", black: "000000", blanchedalmond: "ffebcd", blue: "0000ff", blueviolet: "8a2be2", brown: "a52a2a", burlywood: "deb887", cadetblue: "5f9ea0", chartreuse: "7fff00", chocolate: "d2691e", coral: "ff7f50", cornflowerblue: "6495ed", cornsilk: "fff8dc", crimson: "dc143c", cyan: "00ffff", darkblue: "00008b", darkcyan: "008b8b", darkgoldenrod: "b8860b", darkgray: "a9a9a9", darkgreen: "006400", darkkhaki: "bdb76b", darkmagenta: "8b008b", darkolivegreen: "556b2f", darkorange: "ff8c00", darkorchid: "9932cc", darkred: "8b0000", darksalmon: "e9967a", darkseagreen: "8fbc8f", darkslateblue: "483d8b", darkslategray: "2f4f4f", darkturquoise: "00ced1", darkviolet: "9400d3", deeppink: "ff1493", deepskyblue: "00bfff", dimgray: "696969", dodgerblue: "1e90ff", feldspar: "d19275", firebrick: "b22222", floralwhite: "fffaf0", forestgreen: "228b22", fuchsia: "ff00ff", gainsboro: "dcdcdc", ghostwhite: "f8f8ff", gold: "ffd700", goldenrod: "daa520", gray: "808080", green: "008000", greenyellow: "adff2f", honeydew: "f0fff0", hotpink: "ff69b4", indianred: "cd5c5c", indigo: "4b0082", ivory: "fffff0", khaki: "f0e68c", lavender: "e6e6fa", lavenderblush: "fff0f5", lawngreen: "7cfc00", lemonchiffon: "fffacd", lightblue: "add8e6", lightcoral: "f08080", lightcyan: "e0ffff", lightgoldenrodyellow: "fafad2", lightgrey: "d3d3d3", lightgreen: "90ee90", lightpink: "ffb6c1", lightsalmon: "ffa07a", lightseagreen: "20b2aa", lightskyblue: "87cefa", lightslateblue: "8470ff", lightslategray: "778899", lightsteelblue: "b0c4de", lightyellow: "ffffe0", lime: "00ff00", limegreen: "32cd32", linen: "faf0e6", magenta: "ff00ff", maroon: "800000", mediumaquamarine: "66cdaa", mediumblue: "0000cd", mediumorchid: "ba55d3", mediumpurple: "9370d8", mediumseagreen: "3cb371", mediumslateblue: "7b68ee", mediumspringgreen: "00fa9a", mediumturquoise: "48d1cc", mediumvioletred: "c71585", midnightblue: "191970", mintcream: "f5fffa", mistyrose: "ffe4e1", moccasin: "ffe4b5", navajowhite: "ffdead", navy: "000080", oldlace: "fdf5e6", olive: "808000", olivedrab: "6b8e23", orange: "ffa500", orangered: "ff4500", orchid: "da70d6", palegoldenrod: "eee8aa", palegreen: "98fb98", paleturquoise: "afeeee", palevioletred: "d87093", papayawhip: "ffefd5", peachpuff: "ffdab9", peru: "cd853f", pink: "ffc0cb", plum: "dda0dd", powderblue: "b0e0e6", purple: "800080", red: "ff0000", rosybrown: "bc8f8f", royalblue: "4169e1", saddlebrown: "8b4513", salmon: "fa8072", sandybrown: "f4a460", seagreen: "2e8b57", seashell: "fff5ee", sienna: "a0522d", silver: "c0c0c0", skyblue: "87ceeb", slateblue: "6a5acd", slategray: "708090", snow: "fffafa", springgreen: "00ff7f", steelblue: "4682b4", tan: "d2b48c", teal: "008080", thistle: "d8bfd8", tomato: "ff6347", turquoise: "40e0d0", violet: "ee82ee", violetred: "d02090", wheat: "f5deb3", white: "ffffff", whitesmoke: "f5f5f5", yellow: "ffff00", yellowgreen: "9acd32" }; for (key in namedColors) { if (color === key) { namedColor = namedColors[key]; } } return namedColor; }; return color2color; })(); window.color2color = color2color; })(window); !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;n="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,n.dragula=e()}}(function(){return function e(n,t,r){function o(u,c){if(!t[u]){if(!n[u]){var a="function"==typeof require&&require;if(!c&&a)return a(u,!0);if(i)return i(u,!0);var f=new Error("Cannot find module '"+u+"'");throw f.code="MODULE_NOT_FOUND",f}var l=t[u]={exports:{}};n[u][0].call(l.exports,function(e){var t=n[u][1][e];return o(t?t:e)},l,l.exports,e,n,t,r)}return t[u].exports}for(var i="function"==typeof require&&require,u=0;u
0?e:ae.revertOnSpill,t=oe||Q,r=v(t);r===J&&oe&&r.removeChild(oe);var o=j(r);o===!1&&!oe&&n&&J.insertBefore(t,te),o||n?fe.emit("cancel",t,J,J):fe.emit("drop",t,r,J,re),M()}}function M(){var e=oe||Q;D(),K(),e&&w.rm(e,"gu-transit"),ie&&clearTimeout(ie),fe.dragging=!1,ce&&fe.emit("out",e,ce,J),fe.emit("dragend",e),J=Q=oe=te=re=ie=ce=null}function j(e,n){var t;return t=void 0!==n?n:G?re:m(oe||Q),e===J&&t===te}function k(e,n,r){function o(){var o=t(i);if(o===!1)return!1;var u=z(i,e),c=H(i,u,n,r),a=j(i,c);return a?!0:ae.accepts(Q,i,J,c)}for(var i=e;i&&!o();)i=v(i);return i}function q(e){function n(e){fe.emit(e,f,ce,J)}function t(){s&&n("over")}function r(){ce&&n("out")}if(G){e.preventDefault();var o=h("clientX",e),i=h("clientY",e),u=o-W,c=i-Z;G.style.left=u+"px",G.style.top=c+"px";var f=oe||Q,l=a(G,o,i),d=k(l,o,i),s=null!==d&&d!==ce;(s||null===d)&&(r(),ce=d,t());var p=v(f);if(d===J&&oe&&!ae.copySortSource)return void(p&&p.removeChild(f));var g,y=z(d,l);if(null!==y)g=H(d,y,o,i);else{if(ae.revertOnSpill!==!0||oe)return void(oe&&p&&p.removeChild(f));g=te,d=J}(null===g||g!==f&&g!==m(f)&&g!==re)&&(re=g,d.insertBefore(f,g),fe.emit("shadow",f,d,J))}}function U(e){w.rm(e,"gu-hide")}function _(e){fe.dragging&&w.add(e,"gu-hide")}function F(){if(!G){var e=Q.getBoundingClientRect();G=Q.cloneNode(!0),G.style.width=d(e)+"px",G.style.height=s(e)+"px",w.rm(G,"gu-transit"),w.add(G,"gu-mirror"),ae.mirrorContainer.appendChild(G),o(x,"add","mousemove",q),w.add(ae.mirrorContainer,"gu-unselectable"),fe.emit("cloned",G,Q,"mirror")}}function K(){G&&(w.rm(ae.mirrorContainer,"gu-unselectable"),o(x,"remove","mousemove",q),v(G).removeChild(G),G=null)}function z(e,n){for(var t=n;t!==e&&v(t)!==e;)t=v(t);return t===x?null:t}function H(e,n,t,r){function o(){var n,o,i,u=e.children.length;for(n=0;u>n;n++){if(o=e.children[n],i=o.getBoundingClientRect(),c&&i.left>t)return o;if(!c&&i.top>r)return o}return null}function i(){var e=n.getBoundingClientRect();return u(c?t>e.left+d(e)/2:r>e.top+s(e)/2)}function u(e){return e?m(n):n}var c="horizontal"===ae.direction,a=n!==e?i():o();return a}function V(e,n){return"boolean"==typeof ae.copy?ae.copy:ae.copy(e,n)}var $=arguments.length;1===$&&Array.isArray(e)===!1&&(n=e,e=[]);var G,J,Q,W,Z,ee,ne,te,re,oe,ie,ue,ce=null,ae=n||{};void 0===ae.moves&&(ae.moves=l),void 0===ae.accepts&&(ae.accepts=l),void 0===ae.invalid&&(ae.invalid=B),void 0===ae.containers&&(ae.containers=e||[]),void 0===ae.isContainer&&(ae.isContainer=f),void 0===ae.copy&&(ae.copy=!1),void 0===ae.copySortSource&&(ae.copySortSource=!1),void 0===ae.revertOnSpill&&(ae.revertOnSpill=!1),void 0===ae.removeOnSpill&&(ae.removeOnSpill=!1),void 0===ae.direction&&(ae.direction="vertical"),void 0===ae.ignoreInputTextSelection&&(ae.ignoreInputTextSelection=!0),void 0===ae.mirrorContainer&&(ae.mirrorContainer=S);var fe=y({containers:ae.containers,start:X,end:P,cancel:A,remove:R,destroy:b,dragging:!1});return ae.removeOnSpill===!0&&fe.on("over",U).on("out",_),r(),fe}function o(e,n,r,o){var i={mouseup:"touchend",mousedown:"touchstart",mousemove:"touchmove"},u={mouseup:"MSPointerUp",mousedown:"MSPointerDown",mousemove:"MSPointerMove"};t.navigator.msPointerEnabled&&b[n](e,u[r],o),b[n](e,i[r],o),b[n](e,r,o)}function i(e){if(void 0!==e.touches)return e.touches.length;if(void 0!==e.buttons)return e.buttons;if(void 0!==e.which)return e.which;var n=e.button;return void 0!==n?1&n?1:2&n?3:4&n?2:0:void 0}function u(e){var n=e.getBoundingClientRect();return{left:n.left+c("scrollLeft","pageXOffset"),top:n.top+c("scrollTop","pageYOffset")}}function c(e,n){return"undefined"!=typeof t[n]?t[n]:x.clientHeight?x[e]:S[e]}function a(e,n,t){var r,o=e||{},i=o.className;return o.className+=" gu-hide",r=E.elementFromPoint(n,t),o.className=i,r}function f(){return!1}function l(){return!0}function d(e){return e.width||e.right-e.left}function s(e){return e.height||e.bottom-e.top}function v(e){return e.parentNode===E?null:e.parentNode}function p(e){return"INPUT"===e.tagName||"TEXTAREA"===e.tagName||"SELECT"===e.tagName}function m(e){function n(){var n=e;do n=n.nextSibling;while(n&&1!==n.nodeType);return n}return e.nextElementSibling||n()}function g(e){return e.targetTouches&&e.targetTouches.length?e.targetTouches[0]:e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e}function h(e,n){var t=g(n),r={pageX:"clientX",pageY:"clientY"};return e in r&&!(e in t)&&r[e]in t&&(e=r[e]),t[e]}var y=e("contra/emitter"),b=e("crossvent"),w=e("./classes"),E=document,x=E.documentElement,S=E.body;n.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./classes":1,"contra/emitter":4,crossvent:8}],3:[function(e,n,t){"use strict";var r=e("ticky");n.exports=function(e,n,t){e&&r(function(){e.apply(t||null,n||[])})}},{ticky:6}],4:[function(e,n,t){"use strict";var r=e("atoa"),o=e("./debounce");n.exports=function(e,n){var t=n||{},i={};return void 0===e&&(e={}),e.on=function(n,t){return i[n]?i[n].push(t):i[n]=[t],e},e.once=function(n,t){return t._once=!0,e.on(n,t),e},e.off=function(n,t){var r=arguments.length;if(1===r)delete i[n];else if(0===r)i={};else{var o=i[n];if(!o)return e;o.splice(o.indexOf(t),1)}return e},e.emit=function(){var n=r(arguments);return e.emitterSnapshot(n.shift()).apply(this,n)},e.emitterSnapshot=function(n){var u=(i[n]||[]).slice(0);return function(){var i=r(arguments),c=this||e;if("error"===n&&t["throws"]!==!1&&!u.length)throw 1===i.length?i[0]:i;return u.forEach(function(r){t.async?o(r,i,c):r.apply(c,i),r._once&&e.off(n,r)}),e}},e}},{"./debounce":3,atoa:5}],5:[function(e,n,t){n.exports=function(e,n){return Array.prototype.slice.call(e,n)}},{}],6:[function(e,n,t){var r,o="function"==typeof setImmediate;r=o?function(e){setImmediate(e)}:function(e){setTimeout(e,0)},n.exports=r},{}],7:[function(e,n,t){(function(e){function t(){try{var e=new r("cat",{detail:{foo:"bar"}});return"cat"===e.type&&"bar"===e.detail.foo}catch(n){}return!1}var r=e.CustomEvent;n.exports=t()?r:"function"==typeof document.createEvent?function(e,n){var t=document.createEvent("CustomEvent");return n?t.initCustomEvent(e,n.bubbles,n.cancelable,n.detail):t.initCustomEvent(e,!1,!1,void 0),t}:function(e,n){var t=document.createEventObject();return t.type=e,n?(t.bubbles=Boolean(n.bubbles),t.cancelable=Boolean(n.cancelable),t.detail=n.detail):(t.bubbles=!1,t.cancelable=!1,t.detail=void 0),t}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],8:[function(e,n,t){(function(t){"use strict";function r(e,n,t,r){return e.addEventListener(n,t,r)}function o(e,n,t){return e.attachEvent("on"+n,f(e,n,t))}function i(e,n,t,r){return e.removeEventListener(n,t,r)}function u(e,n,t){var r=l(e,n,t);return r?e.detachEvent("on"+n,r):void 0}function c(e,n,t){function r(){var e;return p.createEvent?(e=p.createEvent("Event"),e.initEvent(n,!0,!0)):p.createEventObject&&(e=p.createEventObject()),e}function o(){return new s(n,{detail:t})}var i=-1===v.indexOf(n)?o():r();e.dispatchEvent?e.dispatchEvent(i):e.fireEvent("on"+n,i)}function a(e,n,r){return function(n){var o=n||t.event;o.target=o.target||o.srcElement,o.preventDefault=o.preventDefault||function(){o.returnValue=!1},o.stopPropagation=o.stopPropagation||function(){o.cancelBubble=!0},o.which=o.which||o.keyCode,r.call(e,o)}}function f(e,n,t){var r=l(e,n,t)||a(e,n,t);return h.push({wrapper:r,element:e,type:n,fn:t}),r}function l(e,n,t){var r=d(e,n,t);if(r){var o=h[r].wrapper;return h.splice(r,1),o}}function d(e,n,t){var r,o;for(r=0;r