CINXE.COM
HubSpot Community
<!DOCTYPE html><html prefix="og: http://ogp.me/ns#" dir="ltr" lang="es" class="no-js"> <head> <title> HubSpot Community </title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <meta content="Welcome to the HubSpot Community! Connect with peers, maximize your HubSpot knowledge, and learn how to grow better with HubSpot." name="description"/><meta content="width=device-width, initial-scale=1.0" name="viewport"/><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/><link href="https://community.hubspot.com/" rel="canonical"/> <meta content="community.hubspot.com" property="og:site_name"/><meta content="website" property="og:type"/><meta content="https://community.hubspot.com/" property="og:url"/><meta content="Welcome to the HubSpot Community! Connect with peers, maximize your HubSpot knowledge, and learn how to grow better with HubSpot." property="og:description"/><meta content="HubSpot Community" property="og:title"/> <link class="lia-link-navigation hidden live-links" title="Temas nuevos de foro de HubSpot Community" type="application/rss+xml" rel="alternate" id="link" href="/mjmao93648/rss/Community?interaction.style=forum"></link> <link class="lia-link-navigation hidden live-links" title="Todos los mensajes publicados de HubSpot Community" type="application/rss+xml" rel="alternate" id="link_0" href="/mjmao93648/rss/Community?interaction.style=forum&feeds.replies=true"></link> <link class="lia-link-navigation hidden live-links" title="Artículos nuevos de blog de HubSpot Community" type="application/rss+xml" rel="alternate" id="link_1" href="/mjmao93648/rss/Community?interaction.style=blog"></link> <link class="lia-link-navigation hidden live-links" title="Todos los mensajes publicados de blog de HubSpot Community" type="application/rss+xml" rel="alternate" id="link_2" href="/mjmao93648/rss/Community?interaction.style=blog&feeds.replies=true"></link> <link class="lia-link-navigation hidden live-links" title="Intercambio de ideas nuevo de ideas de HubSpot Community" type="application/rss+xml" rel="alternate" id="link_3" href="/mjmao93648/rss/Community?interaction.style=idea"></link> <link class="lia-link-navigation hidden live-links" title="Todos los mensajes publicados de intercambios de ideas de HubSpot Community" type="application/rss+xml" rel="alternate" id="link_4" href="/mjmao93648/rss/Community?interaction.style=idea&feeds.replies=true"></link> <link class="lia-link-navigation hidden live-links" title="Nuevos productos" type="application/rss+xml" rel="alternate" id="link_5" href="/mjmao93648/rss/Community?interaction.style=review"></link> <link class="lia-link-navigation hidden live-links" title="Todas las opiniones y comentarios" type="application/rss+xml" rel="alternate" id="link_6" href="/mjmao93648/rss/Community?interaction.style=review&feeds.replies=true"></link> <link class="lia-link-navigation hidden live-links" title="rss.livelink.threads-in-node@place:occasion" type="application/rss+xml" rel="alternate" id="link_7" href="/mjmao93648/rss/Community?interaction.style=occasion"></link> <link class="lia-link-navigation hidden live-links" title="rss.livelink.posts-in-node@place:occasion" type="application/rss+xml" rel="alternate" id="link_8" href="/mjmao93648/rss/Community?interaction.style=occasion&feeds.replies=true"></link> <link class="lia-link-navigation hidden live-links" title="Nuevos mensajes publicados de medios en HubSpot Community" type="application/rss+xml" rel="alternate" id="link_9" href="/mjmao93648/rss/Community?interaction.style=media"></link> <link class="lia-link-navigation hidden live-links" title="Todos los mensajes publicados de medios en HubSpot Community" type="application/rss+xml" rel="alternate" id="link_10" href="/mjmao93648/rss/Community?interaction.style=media&feeds.replies=true"></link> <link href="/skins/6566941/cf3d09a7a299b32f8a1bbd2f844fb61f/hubspot.css" rel="stylesheet" type="text/css"/> <!-- Twitter Card metadata: For Japanese Blog Articles only --> <meta name="google-site-verification" content="JhdbLb5-5cPIvkeSYPUWX4n-wvBOsUlTzu7NjgCxLjQ" /> <script> window.$start = performance.now(); window.$stats = {}; // We need to define this BEFORE the lib is loaded so it initializes properly with this config window.__unocss = { theme: { breakpoints: { '@s': '(max-width: 479px)', '@m': '(max-width: 767px)', '@l': '(max-width: 1023px)', '@xl': '(min-width: 1200px)', }, px2rem: false, }, /** /* Within the RegEx rules below are named groups: /* - <d> stands for direction, think top, right, bottom, left, x, y /* - <g> stands for global, think values like auto|inherit|initial|revert|revert-layer|unset etc. /* - <m> stands for modifier, used for sub-properties like "-size" in "background-size" /* - <p> stands for property /* - <s> stands for selector where applicable /* - <u> stands for unit, default is px, no need to add that, for all other units, write them behind the value /* - <v> stands for value /*/ rules: [ // if you need a class to be !important simply prefix the class in HTMl with ! (it's automatic) // animation/transition utilities [/^a:(?<p>[a-z\-]+)?\/?(?<dur>[\d.ms]+)?\/?(?<e>[a-z\-]+)?\/?(?<del>[\d.ms]+)?$/, ([, p, dur, e, del]) => ( Object.entries({ 'transition-property': p || false, 'transition-duration': dur || '236ms', 'transition-timing-function': e || 'ease-in-out', 'transition-delay': del || false, }).reduce((rules, [prop, value]) => { if ( value ) { rules[prop] = /^[\d\.]+$/.test(value) ? `${value}ms` : value.replace(/(?<!var\()(?<v>--\S+)/, `var(${value})`); } return rules; }, {}) )], // border utilities // This one is a bit special, it's basically able to set a variety of properties if specified, the pattern is like // `b:<direction><color>/<width>/<style>/<radius>` if you want to omit certain values, you need the slash (/), // but with no value in between, so let's say you only want to set the border-style, you would do `b:///dashed`, // only the border-width: `t:/3`, only border-top-color: `b:tred`, all properties support CSS custom properties // and properties that have numeric values support also `calc()`, e.g. `b:t--color-red` and `t:blue/calc(100px/5)` // The order of properties is different than standard CSS which is `<width><style><color>` as in my experience // 90% of border styling are color, but we mostly write `1px solid <color>`, which is annoying, so this utility // defaults to `border-width: 1px` and `border-style: solid` which can of course easily be changed, but doing simply // `b:green` will result in a 1px solid green border in all directions, which cuts down on how much we have to type // if you don't like these defaults, it's quite simple to change it to whatever behaviour you like! // @limitations: This utility does NOT deal with any kind of border-image stuff, I can't even remember when I have // used this feature last, so not going to include it as a utility, if you really want to use it, write CSS... // @note: The strange looking negative lookaheads in the regex below are there to deal with 'reserved' word like // `transparent` or all kinds of named colors that would otherwise get chopped up by the direction indicators // workaround is simply using a hex color with 0 alpha, e.g. #0000... // TODO: Add in support for `outline`, don't want to make a separate util for it as it is relatively similar to // a border and mostly just annoying default focus behavior for lazy people who don't care about :focus... // TODO: Add support for border radius, probably best to take everything at the end (e.g. after <style>) and // split it by slashes, discard anything more than 4 and then apply them as border-radius would be applied /* TODO: think about how to implement fake directional borders (use box-shadow outlines for full ones) &r-fake { position: relative; &:after { color: red; content: ''; position: absolute; top: 0; bottom: 0; width: 1px; } } */ [/^b:(?<d>[bi][se]|r(?![ego])|t(?![r])|l(?![aei])|b(?![eilru])|y(?![e])|x|o(?![lr]))?\(?(?<v>(?:[a-z\-]+?\([\S]+?\)|[^\s\(\)]+?)+?)\)?$/, ([, d, v]) => ( ({ t: ['-top'], r: ['-right'], b: ['-bottom'], l: ['-left'], x: ['-right', '-left'], y: ['-top', '-bottom'], is: ['-inline-start'], ie: ['-inline-end'], bs: ['-block-start'], be: ['-block-end'], }[d] || ['']).reduce((rules, dir) => ( (v || '') .split(/\/?(?<v>[a-z\-]+\([\S]+?\)+(?![,\)_])|[^\s\/]+)\/?/g) .filter((x) => x.trim()) // handles shortcut values for inherit (`i`) and skip (`x`) // you can optionally specify border radius separated by _: `.b:red/1/solid/1px_2px_3px_4px` // but it has to be specified with the unit! slash-notation doesn't need the unit, will default to px // there's a special class `.b:none` to remove a border, but `.b:x/0` is shorter .map((x, i) => /^[\d\.]+$/.test(x) ? `${x}px` : x.replace(/(?<!var\()(--[^\s,/]+)/g, 'var($1)').replace(/_/g, ' ').replace(/^i$/g, 'inherit').replace(/^c$/g, 'currentColor').replace(/^s$/g, 'solid').replace(/^x$/g, '')) // we want always minimum 3 values, as we want to set defaults for width/style if not defined .reduce((arr, val, i, values) => (values.length < 3 ? [...values, ...Array(3-Math.min(values.length, 3)).fill(null)] : values), []) .reduce((ret, val, i, arr) => ({ ...ret, ...({ 0: !['', 'none'].includes(val) ? { [({o: 'outline'}[d] || `border${dir}`) + '-color']: val } : {}, 1: ![''].includes(val) ? { [({o: 'outline'}[d] || `border${dir}`) + '-width']: arr[0] === 'none' ? '0' : val || '1px' } : {}, 2: ![''].includes(val) ? { [({o: 'outline'}[d] || `border${dir}`) + '-style']: val || 'solid' } : {}, 3: { 'border-radius': val }, 4: { 'border-radius': `${ret['border-radius']} ${val}` }, 5: { 'border-radius': `${ret['border-radius']} ${val}` }, 6: { 'border-radius': `${ret['border-radius']} ${val}` }, }[i] || {}) }), {}) ), {}) )], /* OLD border version [/^(?<p>b):(?<d>[bi][se]|r(?![ego])|t(?![r])|l(?![aei])|b(?![eilru])|y(?![e])|x)?(?<g>inherit|initial|revert|revert-layer|unset)?(?<outline>o(?![lr]))?(?<color>[^\/\s:@]*)?\/?(?<width>[\d.]+|--[^\/\s:@]+|calc\(.*?\))?(?<u>[a-zA-Z%]+)?\/?(?<style>[^\/]*)?\/?(?<radius>[\S]+)?$/, ([, p, d, g, outline, color, width, u, style, radius]) => ( { undefined: [''], t: ['-top'], r: ['-right'], b: ['-bottom'], l: ['-left'], x: ['-right', '-left'], y: ['-top', '-bottom'], is: ['-inline-start'], ie: ['-inline-end'], bs: ['-block-start'], be: ['-block-end'], }[d].reduce((rules, dir) => { // global values like auto, initial, revert will be captured by the <u> group Object.entries({ [(outline ? 'outline' : `border${dir}`) + '-color']: color || g ? `${color?.replace(/(?<!var\()(?<v>--\S+)/, `var(${color})`) || ( g || '')}` : false, [(outline ? 'outline' : `border${dir}`) + '-width']: `${width?.replace(/(?<!var\()(?<v>--\S+)/, `var(${width})`) || '1'}${u || (!width?.startsWith('--') && !width?.includes('calc') ? 'px' : '')}`, [(outline ? 'outline' : `border${dir}`) + '-style']: `${style?.replace(/(?<!var\()(?<v>--\S+)/, `var(${style})`) || 'solid'}`, 'border-radius': radius ? radius.split(/\//g).map((v) => (/^[\d\.]+$/.test(v) ? `${v}px` : v.replace(/(?<!var\()(?<v>--\S+)/, `var(${v})`))).join(' ') : false, }).forEach(([prop, value]) => { if ( value ) { rules[prop] = g ? g : value; } }); return rules; }, {}) )], */ [/^b:(?<c>circle)|(?:rad\(?(?<v>(?:[a-z\-]+?\([\S]+?\)|[^\s\(\)]+?)+?)\)?)$/, ([, c, v]) => ( c ? { 'border-radius': '50%' } : (v || '') .split(/\/?(?<v>[a-z\-]+\([\S]+?\)+(?![,\)_])|[^\s\/]+)\/?/g) .filter((x) => x.trim()) .map((x, i) => /^[\d\.]+$/.test(x) ? `${x}px` : x.replace(/(?<!var\()(--[^\s,/]+)/g, 'var($1)').replace(/_/g, ' ').replace(/^i$/g, 'inherit').replace(/^c$/g, 'currentColor').replace(/^x$/g, '')) .reduce((ret, val, i) => ({ ...ret, ...({ 'border-radius': `${ret['border-radius'] || ''} ${val}` }) }), {}) )], // background: shorthand and advanced multi-value uncovered sub-property accessor // @note: if you encounter problems consider disabling this rule and swap it out // for the commented out one below that just takes in custom properties [/^bg:(?<m>-[a-z]+)?_?(?<v>['"0-9A-Za-z .,\/()\-_!%#]+)$/, ([, m, v]) => ({ [`background${m || ''}`]: v?.replace(/_/g, ' ')?.replace(/(?<!var\()(?<v>--\S+)/, `var(${v})`) })], // background[-prop]: variable/custom property interpolation, use like `bg:-image--var-name` // @note: swap with rule above if that one creates problems, it does this as well // [/^bg:(?<m>-[a-z]+)?_?(?<v>--.*|none)$/, ([, m, v]) => ({ // [`background${m || ''}`]: /^none$/.test(v) ? 'none' : `var(${v})` // })], // background-color: Use custom property syntax for actual colors like `bg:--c-green` [/^bg:(?<v>current|transparent)$/, ([, v]) => ({ 'background-color': v?.replace('current', 'currentColor') })], // background-position: we only support the 1 value version with utils /* TODO: think about implementing these modifiers from the SCSS version @include modifiers(( 'b': 'bottom', 'c': 'center', 'l': 'left', 'lb': 'left bottom', 'lt': 'left top', 'r': 'right', 'rb': 'right bottom', 'rt': 'right top', 't': 'top', ), $properties: 'background-position', $prefix: 'pos-', $separator: '-'); */ [/^bg:(?<v>center|top|right|bottom|left)$/, ([, v]) => ({ 'background-position': v })], // background-repeat: we only support the 1 value version with utils [/^bg:(?<v>repeat-x|repeat-y|repeat|space|no-repeat)$/, ([, v]) => ({ 'background-repeat': v })], // background-size: only word values suported with utils [/^bg:(?<v>auto|cover|contain)$/, ([, v]) => ({ 'background-size': v })], // box-shadow [/^bs:(?<p>oi|o)?\/?(?<v>[^\s]+)?$/, ([, p, v]) => ({ // `/([^\s\/]+\([\S]+?\))|\//g` => splits by slash except when they are between parenthesis like `calc(100px/2)` // `b`/`o` and `oi` are shortcuts for box-shadow outlines/borders (they don't affect the box-model), `o` creates // and outline outside of the box, `oi` one that does not go beyond the box-boundaries. This can be useful // for scenarios where you want a border in a certain state but not others and then have to set // `border-color: transparent` on those elements. But box-shadow outlines can't be direction controlled, // so they are only useful if the element should have a border on all sides 'box-shadow': ({ 'o': '0 0 0 ', 'oi': 'inset 0 0 0 ', }[p] || '') + v.split(/([^\s\/]+\([\S]+?\))|\//g).filter((x) => x).map((x) => (/^[\d\.]+$/.test(x) ? `${x}px` : x.replace(/(?<!var\()(--\S+)/, `var(${x})`))).join(' ') })], // cursor: just make sure you got the value right, unrestricted for brevity sake [/^c:(?<v>\S+)$/, ([, v]) => ({ 'cursor': v })], // display: There's a lot of different utilities summarized under the d: prefix, see preflights // still working on figuring out the best way to implement them as some might still require // browser prefixes, or target multiple properties etc. [/^(?<p>bg|d):(?<filter>blur|brightness|contrast|drop-shadow|grayscale|hue-rotate|invert|opacity|saturate|sepia)\(?(?<v>calc\([\S]+?\)|[^\s)]+)?\)?$/, ([, p, filter, v]) => ({ [`${p === 'bg' ? 'backdrop-' : ''}filter`]: `${filter}(${v?.startsWith('calc') ? v : v?.replace(/\//g, ' ') || ''})` })], ['d:b', { 'display': 'block' }], // `d:c(<name>/<type>)` || `d:c(<name>)` || `d:c` // https://developer.mozilla.org/en-US/docs/Web/CSS/container [/^d:c(?:\((?<n>[^\s\/]+)\/?(?<t>[^\s\/]+)?\))?$/, ([, n, t]) => ({ 'container': `${n || 'x'} / ${t || 'inline-size'}` })], ['d:i', { 'display': 'inline' }], ['d:ib', { 'display': 'inline-block' }], ['d:none', { 'display': 'none' }], ['d:hide', { 'visibility': 'hidden' }], ['d:show', { 'visibility': 'visible' }], ['d:invisible', { 'border': '0', 'clip': 'rect(1px, 1px, 1px, 1px)', 'height': '1px', 'outline': 'none', 'overflow': 'hidden', 'padding': '0', 'position': 'absolute', 'width': '1px', }], /* 1 */ ['d:f', { 'display': 'flex' }], ['d:fi', { 'display': 'flex inline' }], ['d:f-col', { 'flex-direction': 'column' }], ['d:f-row', { 'flex-direction': 'row' }], ['d:f-wrap', { 'flex-wrap': 'wrap' }], ['d:fc-items-center', { 'align-items': 'center' }], ['d:fc-justify-between', { 'justify-content': 'space-between' }], ['d:fc-justify-center', { 'justify-content': 'center' }], // If functions are used the value wrapping with () is mandatory! `d:f(col/1/0/calc(3px*100))` [/^d:f\(?(?<dir>col|row)?\/?(?<grow>[\d.]+)?\/?(?<shrink>[\d.]+)?\/?(?<basis>[\S]+)?\)+?$/, ([, dir, grow, shrink, basis]) => ( Object.entries({ 'flex-direction': { col: 'column', row: 'row' }[dir] || false, 'flex-grow': grow || false, 'flex-shrink': shrink || false, 'flex-basis': /^[\d\.]+$/.test(basis) ? `${basis}px` : (basis || '').replace(/(?<!var\()(?<v>--\S+)/, `var(${basis})`) || false, }).reduce((rules, [prop, value]) => { if ( value ) { rules[prop] = value; } return rules; }, {}) )], // order matters here, needs to be below the general `d:f` rule [/^d:f-(?<v>none|auto|initial)$/, ([, v]) => ({ 'flex': v })], // grid/flexbox gap, be careful though when using `d:g` it needs the gap defined within it's values // to properly calculate column width! so specify gap there if you use `d:g(<values>)`, it's fine to // use `d:gap` if you use `d:g` (without values) and define your template-columns yourself via CSS [/^d:gap(?<row>calc\([\S]+?\)|[^\s\/]+)?\/?(?<col>[^\s]+)?$/, ([, row, col]) => ( Object.entries({ 'row-gap': col ? row : false, 'column-gap': row ? col : false, 'gap': (row && !col) ? row : false, }).reduce((rules, [prop, value]) => { if ( value ) { rules[prop] = /^[\d\.]+$/.test(value) ? `${value}px` : value.replace(/(?<!var\()(?<v>--\S+)/, `var(${value})`); } return rules; }, {}) )], // flexbox/grid align and justify utils to be used like: // `.d:jself(center) or .d:j-self(center) or .d:js(center) or .d:aitems(start) or .d:a-items(start) or .d:ai(start)` [/^d:(?<d>a|j)-?(?<scope>c|i|s|t|content|items|self|tracks)[\(-](?<v>\S*?)\)?$/, ([, d, scope, v]) => ( { [`${{ a: 'align', j: 'justify' }[d]}-${{ c: 'content', i: 'items', s: 'self', t: 'tracks' }[scope] || scope}`]: v } )], // grid: format `d:g` to just set the display property, `d:g(<template-cols>/<gap/row-gap>?/<col-gap>?/<template-rows>?)` // TODO: Keep an eye on `grid-template-rows: masonry` support, it would be awesome, but is not supported as of 2023 // it's technically implemented as the 4th via `grid-template-rows`: That one is a bit different, can't do it with // optional gap values, so even if no gaps should be defined, it needs to be written like `d:g(12/0/0/masonry)` // there is a special value `equal` that will make all rows equal height to the tallest one: `d:g(12/0/0/equal)` // the 4th value is basically a free-for-all, you can go crazy with stuff like `repeat(auto,minmax(calc(100vh/3),1fr)))` // to define the grid-template-rows, I use it rarely, but it's there if needed. [/^d:(?<p>g|gi)(?:\((?<v>[^\s]+)?\))?$/, ([, p, v], ctx) => ( ({ 'g': [ ['display', 'grid'] ], 'gi': [ ['display', 'inline-grid'] ], }[p] || []).reduce((rules, [prop, value]) => { if ( value ) { //console.log('rule matcher args', p, v, ctx); // set the display property rules[prop] = value; // parse the grid config values and inject additional properties into the outer reduced array // depending on how many config values were provided, do not give unit to first value automatically // as it is the number of grid-columns and needs to be a unitless value for the internal calc(), it // can be a custom CSS property/variable or calc() resolving in a unitless number itself though, // meaning: `d:g(--var-cols/12px/calc(100px/4))` or `d:g(calc(48/4)/12px/calc(100px/4))` are fine. // Does it make sense to calc() within calc()? not sure... but it's possible ;). // If the first value has a unit, no automatic cols calculation will happen, but the value will // be used as a min-width of a grid-column letting the browser do the heavy lifting, this can be // very helpful not having to define any kind of @media queries for responsiveness! // `d:g(264px)` => `grid-template-columns: repeat(auto-fit, minmax(264px, 1fr));` // auto-fill vs auto-fit: https://css-tricks.com/auto-sizing-columns-css-grid-auto-fill-vs-auto-fit/ if ( v ) { v = v.split(/\/?(?<v>[a-z\-]+\([\S]+?\)(?![,\)])+|[^\s\/]+)\/?/g).filter(x => x).map((x, i) => /^[\d\.]+$/.test(x) && i !== 0 ? `${x}px` : x.replace(/(?<!var\()(?<v>--\S+)/, `var(${x})`)); // The last value can be 'fit' or 'fill' regardless of position to select auto-filling algo const f = /(fit|fill)/.test(v.at(-1)) ? v.pop() : 'fit'; const props = ({ 1: [['grid-template-columns', `repeat(auto-${f}, minmax(${/[\d\.]+[a-z%]+$/.test(v[0]) ? v[0] : `calc(100%/${v[0]})`}, 1fr))`]], 2: [['grid-template-columns', `repeat(auto-${f}, minmax(${/[\d\.]+[a-z%]+$/.test(v[0]) ? v[0] : `calc(100%/${v[0]} - ${v[1]})`}, 1fr))`], ['gap', v[1]]], 3: [['grid-template-columns', `repeat(auto-${f}, minmax(${/[\d\.]+[a-z%]+$/.test(v[0]) ? v[0] : `calc(100%/${v[0]} - ${v[2]})`}, 1fr))`], ['row-gap', v[1]], ['column-gap', v[2]]], 4: [['grid-template-columns', `repeat(auto-${f}, minmax(${/[\d\.]+[a-z%]+$/.test(v[0]) ? v[0] : `calc(100%/${v[0]} - ${v[2] || 0})`}, 1fr))`], ['row-gap', v[1]], ['column-gap', v[2]], ( v[3] === 'equal' ? ['grid-auto-rows', '1fr'] : ['grid-template-rows', ( v[3] ? v[3].replace(/_/g, ' ') : null )] )], }[Math.min(v.length, 4)] || []).forEach(([_p, _v]) => (rules[_p] = _v)); } } return rules; }, {}) )], [/^d:(?:g-?)?(?<p>col|row)\(?(?<v>\S+?)\)?$/, ([, p, v]) => ({ [`grid-${p === 'col' ? 'column' : 'row'}`]: v.replace(/_/g, ' ') })], // grid col/row span // regex captures everything after `d:span<v>` (or within parenthesis `d:span(<v>)`), syntax is: // variant a): `d:span<v[<col[<start>-<end?>]>/<row?[<start>-<end?>]>]>` // variant b): `d:span(<v[<col[<start>-<end?>]>/<row?[<start>-<end?>]>]>)`, // we deal with the value inside the matcher function and split it into it's components // TODO: Re-evaluate if the separate util is worth it as we can simply use `.d:g-col(<v>` and `.d:g-row(<v>)` [/^d:(?:g-?)?span\(?(?<v>(?:[a-z\-]+?\([\S]+?\)|[^\s\(\)]+?)+?)\)?$/, ([, v]) => ( (v || '') .split(/\/?(?<v>[a-z\-]+\([\S]+?\)+(?![,\)_])|[^\s\/]+)\/?/g) .filter(x => x.trim()) // don't need the auto-pixelator here, span values are unitless, but we support CSS vars //.map((x, i) => /^[\d\.]+$/.test(x) ? `${x}px` : x.replace(/(?<!var\()(--[^\s,/]+)/g, 'var($1)').replace(/_/g, ' ')) .map((x, i) => x.replace(/(?<!var\()(--[^\s,/]+)/g, 'var($1)')) .reduce((rules, value, i) => ({ ...rules, ...({ // if useing CSS vars, specify the full value, like this it's most flexible 0: { 'grid-column': value.includes('var(') ? value : value.split('-').map((x, i, a) => a.length === 1 ? `span ${x}` : x ).join(' / ') }, 1: { 'grid-row': value.includes('var(') ? value : value.split('-').map((x, i, a) => a.length === 1 ? `span ${x}` : x ).join(' / ') }, }[i] || {}) }), {}) )], ['d:noverflow', { 'overflow': 'hidden' }], // order (flexbox/grid), syntax: `d:order(?-?<v>)?` [/^d:order\(?(?<v>[-\d]+)\)?$/, ([, v]) => ({ 'order': v })], // display => overflow(-[x|y]) auto [/^d:scroll(?<m>-[xy])?$/, ([, m]) => ({ [`overflow${m || ''}`]: 'auto' })], ['d:scroll', { 'overflow': 'auto' }], ['d:scroll(x)', { 'overflow-x': 'auto' }], ['d:scroll(y)', { 'overflow-y': 'auto' }], // it's a bit tricky to yield those ::selectors, but this is how it can be done... // question is: should we just preflight those as raw CSS instead of doing constructs like this? // the strings ship with the bundle, one way or the other, but as preflights at least the utils // are readable... and after all, there's nothing dynamic about them, simply creating overhead here // futhermore it's questionable to do it like that as it will most likely result in more // characters/bytes shipped than if it was just pure CSS... [/^(?<sel>d:scroll-nobar)$/, ([, sel], context) => { return `${context.constructCSS({ 'scrollbar-width': 'none', /* Firefox */ '-ms-overflow-style': 'none', /* IE 10+ */ })}\n.${CSS.escape(sel)}::-webkit-scrollbar { width: 0; height: 0; }` /* WebKit */ }], // pointer-events [/^e:(?<v>\S+)$/, ([, v]) => ({ 'pointer-events': v })], // list-style: order of values is type | image | position, escape quotes with ^ [/^l:(?<v>.{3,}?)?(?:_(?<url>.+?))?(?:_(?<pos>outside|inside))?$/, ([, v, url, pos]) => ({ 'list-style': `${v?.replaceAll('^', '"')} ${url || ''} ${pos || ''}` })], // margin and padding: supports basics plus custom properties (variables), optional directions and global word values [/^(?<p>m|p):(?<d>r(?!e)|[ltbxy]|[bi][se])?(?<v>(?:(?:-(?!-))?[\d._]+)|--\S+|calc\(.*?\))?(?<u>[a-zA-Z%]+)?$/, ([, p, d, v, u]) => ( { undefined: [''], t: ['-top'], r: ['-right'], b: ['-bottom'], l: ['-left'], x: ['-right', '-left'], y: ['-top', '-bottom'], is: ['-inline-start'], ie: ['-inline-end'], bs: ['-block-start'], be: ['-block-end'], }[d].reduce((rules, dir) => { // global values like auto, initial, revert will be captured by the <u> group // TODO: not sure what the `.replaceAll('_', ' ')` is for, maybe a copy paste leftover from another rul? rules[`${{m: 'margin', p: 'padding'}[p]}${dir}`] = `${v?.replaceAll('_', ' ')?.replace(/(?<!var\()(?<v>--\S+)/, `var(${v})`) || ''}${u || (!v?.startsWith('--') && !v?.includes('calc') ? 'px' : '')}`; return rules; }, {}) )], // opacity // technically the spec allows for percantage values, but we convert anything to float, makes things easier [/^o:(?<v>[\d.%]+|--\S+|calc\(.*?\))?$/, ([, v]) => ({ 'opacity': isNaN(parseFloat(v)) ? (v?.replace(/(?<!var\()(?<v>--\S+)/, `var(${v})`) || '') : ( parseFloat(v) <= 1 ? parseFloat(v) : parseFloat(v)/100 ) })], // position utils [/^(?<p>pos):(?<d>r(?![e]|$)|[ltb])?(?<v>[\S]+)?$/, ([, p, d, v]) => ( { 'a': [ ['position', 'absolute'] ], 'f': [ ['position', 'fixed'], ['backface-visibility', 'hidden'] ], 'r': [ d ? ['right', null] : ['position', 'relative'] ], 's': [ ['position', 'sticky'] ], 'center': [ ['position', 'absolute'], ['top', '50%'], ['left', '50%'], ['transform', 'translate(-50%, -50%)'] ], 'center-x': [ ['position', 'relative'], ['left', '50%'], ['transform', 'translateX(-50%) perspective(1px)'] ], 'center-y': [ ['position', 'relative'], ['top', '50%'], ['transform', 'translateY(-50%) perspective(1px)'] ], 'reset': [ ['position', 'static'] ], // direction utils, set the value falsy so we can set it within reduce 't': [ ['top', null] ], 'b': [ ['bottom', null] ], 'l': [ ['left', null] ], undefined: [], }[d || v].reduce((rules, [prop, value]) => { if ( value ) { rules[prop] = value; } else if ( d && v ) { rules[prop] = /^[\d\.]+$/.test(v) ? `${v}px` : v.replace(/(?<!var\()(?<v>--\S+)/, `var(${v})`); } return rules; }, {}) )], /** /* FLUID MEDIA CONTENT UTILS (IMG, VIDEOS, IFRAMES etc.) /* 1. Element will be stretched to the full extend of the nearest realtively-positioned /* ancestor. /* 2. Element will be stretched to the entire viewport and follow the user's scrolling, /* good for modal windows and overlays /* 3. Add this class to the element that contains the fluid media content and do not forget /* to define the aspect ratio like `.scale:frame(16/9)`. /* 4. Add this class to the element that should scale in a specific ratio, useful for /* fluid videos, iframes (maps anybody?), embeds but also images. /* 5. Allows an image to be responsvie up to its container width but not exceeding /* it's native size. /*/ [/^scale:(?<v>[^\s(]+)\(?(?<ratio>[\d\/]+)?\)?$/, ([, v, ratio]) => ( { 'fit': [ ['bottom', '0'], ['left', '0'], ['margin', 'auto'], ['position', 'absolute'], ['right', '0'], ['top', '0'] ], /* 1 */ 'fullscreen': [ ['backface-visibility', 'hidden'], ['bottom', '0'], ['left', '0'], ['margin', 'auto'], ['position', 'fixed'], ['right', '0'], ['top', '0'] ], /* 2 */ 'frame': [ ['display', 'block'], ['position', 'relative'], ['aspect-ratio', (ratio ? `${ratio}` : null) ] ], /* 3 */ // The padding hack is old-school now, we now have native aspect ratio, but for reference // I'll leave those here anyways, the calculation goes as follows: `9 / 16 * 100% = 56.25%` // So if a custom aspect ratio is needed one could simply apply `p:tcalc(2/12*100%)` //'frame(16/9)': [ ['padding-top', '56.25%'] ], //'frame(3/2)': [ ['padding-top', '66.66666%'] ], //'frame(4/3)': [ ['padding-top', '75%'] ], 'content': [ ['bottom', '0'], ['left', '0'], ['margin', 'auto'], ['position', 'absolute'], ['right', '0'], ['top', '0'] ], /* 4 */ 'img': [ ['display', 'block'], ['height', 'auto'], ['max-width', '100%'] ], /* 5 */ undefined: [], }[v].reduce((rules, [prop, value]) => { if ( value ) { rules[prop] = value; } return rules; }, {}) )], /** /* TEXT UTILS /* /* 1. Enables font kerning in all browsers. /* see also: http://blog.typekit.com/2014/02/05/kerning-on-the-web/ /* 2. Ensure that the node has a maximum width after which truncation can occur. /* 3. Fix for IE 8/9 if 'word-wrap: break-word' is in effect on ancestor nodes. /* 4. A little helper to increase the font-weight slightly without having to rely /* on font-style. Especially useful to increase readability of very small type! /*/ // This one is a bit special, it's basically able to set a variety of properties if specified, the pattern is like // `t:<color>/<font-size>/<line-height>/<font-weight>/<font-style>/<font-family>` if you want to omit certain values, // you need the slash (/), but with no value in between, so let's say you only want to set the font family, // you would do `t://///Arial`, only the font-weight: `t:///700`, only the color: `t:red`, all properties // support CSS custom properties and properties that have numeric values support also `calc()`, e.g. `t:--color-red` // and `t:blue/calc(100px/5)/calc(100px/4)` // TODO: support letter-spacing here or in separate utility? // TODO: support other functions than calc(), clamp() in particular, but basically all CSS math functions [/^(?<p>t):(?<color>[^\/\s:@]*)?\/?(?<size>[\d.]+|--[^\/\s:@]+|calc\(.*?\))?(?<u>[a-zA-Z%]+)?\/?(?<lh>[\d.]+|--[^\/\s:@]+|calc\(.*?\))?(?<lhu>[a-zA-Z%]+)?\/?(?<weight>[\d.]+|--[^\/\s:@]+|calc\(.*?\))?\/?(?<style>[^\/\s:@]*)?\/?(?<family>[^\/\s:@]*)?$/, ([, p, color, size, u, lh, lhu, weight, style, family]) => ( Object.entries({ 'color': color ? `${color?.replace(/(?<!var\()(?<v>--\S+)/, `var(${color})`) || ''}` : false, 'font-size': size || size === '0' ? `${size?.replace(/(?<!var\()(?<v>--\S+)/, `var(${size})`) || ''}${u || (!size?.startsWith('--') && !size?.includes('calc') ? 'px' : '')}` : false, 'line-height': lh || lh === '0' ? `${lh?.replace(/(?<!var\()(?<v>--\S+)/, `var(${lh})`) || ''}${lhu || ''}` : false, 'font-weight': weight ? `${weight?.replace(/(?<!var\()(?<v>--\S+)/, `var(${weight})`) || ''}` : false, 'font-style': style ? `${style?.replace(/(?<!var\()(?<v>--\S+)/, `var(${style})`) || ''}` : false, 'font-family': family ? `${family?.replace(/(?<!var\()(?<v>--\S+)/, `var(${family})`) || ''}` : false, }).reduce((rules, [prop, value]) => { if ( value ) { rules[prop] = value; } return rules; }, {}) )], // font-family // This utility isn't really meant to define full font-stacks, you may try to use the general utility // like `t://///Arial` even though it's questionable to use like that. By default it just applies the global CSS // keywords for font-family, including such as ui-serif etc. which are not supported by browsers today // the power of this one is that it will also look for pre-defined custom CSS properties/variables at // :root level with the specific pattern of `---t-family-<keyword>`, if found it will use the variable // value. In this way font stacks can easily be defined via such variables. Besides the standrad spec // keywords, it also supports some custom short ones: sans => sans-serif, mono => monospace, ui => system-ui // TODO: Make variable names configurable via theme or at least the prefix and allow passing in the specific // `--t-family-<name>` variable via CSS class as well, like this we could reference full font stacks without // making things too ugly? How can we access theme within rules? [/^t:(?<v>serif|sans-serif|sans|monospace|mono|cursive|fantasy|system-ui|ui|ui-serif|ui-sans-serif|ui-monospace|ui-rounded|emoji|math|fangsong)$/, ([, v]) => ({ 'font-family': !!getComputedStyle(document.documentElement).getPropertyValue(`---t-family-${v}`) ? `var(---t-family-${v})` : v.replace(/^(sans|mono|ui)$/gi, x => ({'sans': 'sans-serif', 'mono': 'monospace', 'ui': 'system-ui'}[x])) })], // font-style // Shortcuts for what is doable with the 'general' utility above as well, the key word `normal` // is already used by the font-weight utility below, so `t:regular` is used to set `font-style: normal` // specifying the angle for `font-style: oblique 20deg` is supported as well with `t:oblique/20` // valid angle values are +-90deg, but most fonts don't support it anyways... [/^t:(?<v>italic|oblique|regular)\/?(?<deg>-?\d{1,2})?$/, ([, v, deg]) => ({ 'font-style': `${v.replace('regular', 'normal')}${deg ? ` ${deg}deg`: ''}` })], // font-weight // Those are shortcuts which can all be achieved by using the above 'general' utility as well, but they // are still included for convenience, lighter/bolder are relative-to-parent font-weights (see MDN) // this util has a feature where it looks for custom CSS properties (variables) defined at `:root` level // that match the specific pattern of `---t-weight-<word|weight>`, if found, it will use those instead of // the actual word or numeric weight, this allows to re-define what those words/weights mean in terms of // actual font-weight, e.g. if default for `font-weight: normal` is 400, if you set `---t-weight-normal: 300` // at `:root` level and use the utility `t:normal` on some element, it's font-weight will now be 300 // these custom CSS properties/variables are intentionally prefixed with 3! dashes (---) to hopefully avoid // any conflicts with 'regularly' defined custom CSS variables which accidentially have the same name! [/^t:(?<v>lighter|bolder|thin|normal|bold|heavy|\d00)$/, ([, v]) => ({ 'font-weight': !!getComputedStyle(document.documentElement).getPropertyValue(`---t-weight-${v}`) ? `var(---t-weight-${v})` : v.replace('thin', '100').replace('heavy', '900') })], // `t:boldest` applies a text-shadow which adds to the visual boldness of text regardless of font-weight applied ['t:boldest', { 'text-shadow': '0 0 0.3px currentColor' }], // text-align: we only support the 1 value version with utils, the string thing seems fringe anyways // additionally we convert left/right 'absolute' values to start/end which is text-direction aware // `justify-all` and `match-parent` are in the spec but seem very poorly supported! [/^t:(?<v>start|end|left|right|center|justify|justify-all|match-parent)$/, ([, v]) => ({ 'text-align': v.replace('left', 'start').replace('right', 'end') })], // text-decoration // We don't support multiple text-decoration-line values, if you really need that, specify it via multiple classes // text-decoration-skip is also not supported as browser support is 0, but text-decoration-skip-ink is supported // There is a shortcut `t:del` which translates to `t:line-through` automatically. // `blink` is deprecated and only Opera and Safari still support it...We don't, it's bullshit UX anyways... // A text-decoration-line value has to be defined, otherwise this util won't catch, the other additional properties // can be omitted, the format is `t:<decoration-line>/<style>/<color>/<thickness>/<skip-ink> [/^t:(?<line>none|underline|overline|line-through|del)\/?(?<style>solid|double|dotted|dashed|wavy|--[^\/\s:@]+)?\/?(?<color>[^\/\s:@]*)?\/?(?<width>[\d.]+|--[^\/\s:@]+|calc\(.*?\))?(?<u>[a-zA-Z%]+)?\/?(?<skip>none|auto|all|--[^\/\s:@]+)?$/, ([, line, style, color, width, u, skip]) => ( Object.entries({ 'text-decoration-line': line ? `${line?.replace(/(?<!var\()(?<v>--\S+)/, `var(${line})`).replace('del', 'line-through') || ''}` : false, 'text-decoration-style': style ? `${style?.replace(/(?<!var\()(?<v>--\S+)/, `var(${style})`) || ''}` : false, 'text-decoration-color': color ? `${color?.replace(/(?<!var\()(?<v>--\S+)/, `var(${color})`) || ''}` : false, 'text-decoration-thickness': width || width === '0' ? `${width?.replace(/(?<!var\()(?<v>--\S+)/, `var(${width})`) || ''}${u || (!width?.startsWith('--') && !width?.includes('calc') ? 'px' : '')}` : false, 'text-decoration-skip-ink': skip ? `${skip?.replace(/(?<!var\()(?<v>--\S+)/, `var(${skip})`) || ''}` : false, }).reduce((rules, [prop, value]) => { if ( value ) { rules[prop] = value; } return rules; }, {}) )], // text-tranform [/^t:(?<v>capitalize|caps|lowercase|lcase|uppercase|ucase)$/, ([, v]) => ({ 'text-transform': v.replace('caps', 'capitalize').replace('lcase', 'lowercase').replace('ucase', 'uppercase') })], ['t:break', { 'word-wrap': 'break-word' /* 4 */ }], ['t:nowrap', { 'white-space': 'nowrap' }], // TODO: not sure if this even does something visually, what is it's purpose? remove it? ['t:kern', { '-webkit-font-feature-settings': '"kern" 1', 'font-feature-settings': '"kern" 1', '-webkit-font-kerning': 'normal', 'font-kerning': 'normal', 'text-rendering': 'optimizeLegibility' }], // 1 ['t:truncate', { 'max-width': '100%' /* 2 */, 'overflow': 'hidden', 'text-overflow': 'ellipsis', 'white-space': 'nowrap', 'word-wrap': 'normal' /* 3 */ }], // transform // transform function values are very diverse, just write them as usual separated with commas just NO spaces! // You can use `calc()` or custom css properties `--some-var` if they are allowed to be used for function values // we can't cast non-pixel values to pixels either, because different functions have different inputs, like `scale()` // for example expects unitless values, so for the values, you do need to specify the unit if appropriate // Does NOT support specifying multiple transform functions in one call, write proper CSS for a use-case like that! // Does support transform-origin/box/style with the appropriate prefix `b|o|s` e.g. `.tr:o(center/50px)` // note that the classname consistently has to encapsulate the value in parenthesis, e.g. `.tr:rotate(120deg)`, but // also `.tr:o(--some-var/calc(100px/2))` => `transform-origin: var(--some-var) calc(100px/2);` // The order of the transform functions in the RegEx matters, so don't touch! [/^tr:(?<p>[bo]|s(?![ck]))?(?<fn>matrix3d|matrix|none|perspective|rotate3d|rotateX|rotateY|rotateZ|rotate|scale3d|scaleX|scaleY|scaleZ|scale|skewX|skewY|skew|translate3d|translateX|translateY|translateZ|translate)?\((?<v>[^\s]+)?\)$/, ([, p, fn, v]) => ({ [{ b: 'transform-box', o: 'transform-origin', s: 'transform-style', undefined: 'transform', }[p]]: p // `/\/(?![\S]+\))/g` => splits by slash except when they followed by `)` like `calc(100px/2)` ? v.split(/\/(?![\S]+\))/g).map((x) => (/^[\d\.]+$/.test(x) ? `${x}px` : x.replace(/(?<!var\()(--\S+)/, `var(${x})`))).join(' ') : fn.match(/none/) ? fn : `${fn}(${v?.replace(/(?<!var\()(?<v>--\S+)/g, `var(${v})`)})` })], // width & height [/^(?<p>w|h):(?<m>min|max|screen)?(?<v>[\d.]+|--\S+|calc\(.*?\))?(?<u>[a-zA-Z%]+)?$/, ([, p, m, v, u]) => ( { undefined: [''], min: ['min-'], max: ['max-'], screen: [(rules) => (rules[`${{w: 'width', h: 'height'}[p]}`] = `100v${p}`)] }[m].reduce((rules, mod) => { if ( mod instanceof Function ) { mod(rules); return rules; } // global values like auto, initial, revert will be captured by the <u> group // replacing _ with ' ' allows for escaping required spaces in calc +/- operations like calc(100% - 32px) rules[`${mod}${{w: 'width', h: 'height'}[p]}`] = `${v?.replace(/(?<!var\()(?<v>--\S+)/, `var(${v})`).replaceAll('_', ' ') || ''}${u || (!v?.startsWith('--') && !v?.includes('calc') ? 'px' : '')}`; return rules; }, {}) )], [/^z:(?<v>.+)$/, ([, v]) => ({ 'z-index': v.replace(/(?<!var\()(?<v>--\S+)/, `var(${v})`) })], // debug/dev tools, simply add the class `?` to an element and it will make itself very visible ;) // It might very often be the case that you need to overrule existing styles that conflict with the // dev tool class, so just prefix with `!` to make everything !important. [/^(\?)$/, (_, { constructCSS, generator }) => ( `@keyframes __imhere{0%{box-shadow:inset 0 0 0 2px red}100%{box-shadow:inset 0 0 0 6px yellow}}\n${constructCSS({ animation: '__imhere 0.5s ease-in-out alternate infinite' })}` )], // create a box around an element, good for highlighting stuff // arrows can be useful for screenshots, try it out with `?[]>`, `?[]^`, `?[]<`, `?[]>t` etc. [/^(?<sel>\?\[(?<inset>[0-9-]+)?\/?(?<width>\d+)?\](?:(?<arrow>\>|\<|\^)(?<top>t)?)?\/?(?<hue>\d+)?\/?(?<opacity>[\d.%]+)?)$/, ([, sel, inset, width, arrow, top, hue, opacity], ctx) => ( `${ctx.constructCSS({ overflow: 'visible !important', position: 'relative', })}${ arrow ? `\n.${CSS.escape(sel)}:before { color: hsl(${hue || 0} 100% 50%) !important; content: '↗' !important; font-size: 36px !important; font-weight: 300 !important; line-height: 1 !important; position: absolute; ${top ? `top: -${Math.abs(inset || 0)}px` : `bottom: -${Math.abs(inset || 0)}px`}; ${arrow === '<' ? `right: -${Math.abs(inset || 0)}px` : `left: ${ arrow === '^' ? '50%' : `-${Math.abs(inset || 0)}px` }`}; transform: translate(${arrow === '<' ? '150%' : `${arrow === '^' ? '-50%' : '-150%'}`}, ${ top ? '-125%' : '125%'}) ${arrow === '<' ? 'rotate(-90deg)' : arrow === '^' ? 'rotate(-45deg)' : ''} ${ top ? `scale(${arrow === '<' ? '-1,1' : arrow === '^' ? '-1' : '1,-1'})` : ''}; z-index: 9999 !important; }` : ''}\n.${CSS.escape(sel)}:after { box-shadow: inset 0 0 0 ${Math.abs(inset || 0)}px hsl(${hue || 0} 100% 50% / ${opacity || .1}) !important; content: '' !important; inset: ${inset || 0}px !important; margin: 0 !important; padding: 0 !important; outline: ${width || 1}px solid hsl(${hue || 0} 100% 50%) !important; position: absolute !important; transform: none !important; z-index: 9999 !important; }` )], // and the dev grid overlay [/^(?<sel>\?#\(?(?<s>\d+)?\/?(?<o>[\d.]+)?\/?(?<h>[\d]+)?(?<r>r)?\)?)$/, ([, sel, s, o, h, r], ctx) => ( `${ctx.constructCSS({ 'position': 'relative', })}\n.${CSS.escape(sel)}:before { background-image: linear-gradient(hsl(${ h ? h : '0'} 100% ${ h ? '50%' : '0%'} / ${ o ? o : '.12'}) 1px, transparent 1px), linear-gradient(90deg, hsl(${ h ? h : '0'} 100% ${ h ? '50%' : '0%'} / ${ o ? o : '.12'}) 1px, transparent 1px); /*background-position: -1px -1px, -1px -1px;*/ background-size: ${ s ? `${s}px ${s}px, ${s}px ${s}px` : '24px 24px, 24px 24px'}; box-shadow: inset 0 0 0 1px hsl(${ h ? h : '0'} 100% ${ h ? '50%' : '0%'} / ${ o ? o : '.12'}); content: ''; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 100%; z-index: 10000; }\n.${CSS.escape(sel)} > [class*="${CSS.escape('b:')}"] { border-color: red !important; border-radius: 0 !important; }\n.${CSS.escape(sel)} > :not([class*="${CSS.escape('b:')}"]) { border-radius: 0 !important; box-shadow: inset 0 0 0 1px red !important; }${ r ? `\n.${CSS.escape(sel)}:after { background-image: linear-gradient(hsl(0 100% 0% / 1) 1px, transparent 1px), linear-gradient(90deg, hsl(0 100% 0% / 1) 1px, transparent 1px), linear-gradient(90deg, hsl(0 100% 0% / 1) 1px, transparent 1px), linear-gradient(-90deg, hsl(0 100% 0% / 1) 1px, transparent 1px); background-position: left bottom; background-repeat-y: no-repeat; background-size: ${ s ? `${s/2}px 6px, ${s/2}px 6px, ${s}px 11px, 100% 11px` : '6px 6px, 6px 6px, 12px 11px, 100% 11px'}; content: attr(data-width); display: block; font-size: 10px; line-height: 1; padding-bottom: 16px; position: absolute; top: 0; left: 0; text-align: center; transform: translateY(-125%); width: 100%; }` : '' }` )], ], shortcuts: [ // you could still have object style /*{ 'forum-nav-bar': '!bg:cyan', },*/ // dynamic shortcuts //[/^btn-(.*)$/, ([, c]) => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`], ], variants: [ // Allows targeting child/sub elements of the element the util is applied to // Any valid combinator (or none) are supported, just add the child selector between pipes `|` // and add the util after, give that class to the wrapping element of whatever should be targeted // this helps a lot for use-cases where every child (imagine a ul>li structure) should get the // same styles, with regular utils, every li has to have all util classes, which is very // redundant and one of the major downsides of utility-based CSS approaches. With the help of this // variant this is a thing of the past as only one class has to be defined on the parent targeting // any and all decendent nodes with the appropriate selector. // `|>li|bg:red` => `.\|\>li\|bg\:red > li { background-color: red; }` { name: 'combinators', match: (matcher) => { const rx = /^\|(?<combinator>[>+~])?(?<selector>\S+)\|(?<util>\S+)$/; if ( !rx.test(matcher) ) { return matcher; } const { groups: { combinator, selector, util } } = matcher.match(rx); // the combinator is optional, but makes no sense to continue without selector or util if ( !selector || !util ) { return matcher; } //console.log('Found combinator match', `(selector) ${combinator} ${selector}`, util); return { matcher: util, selector: (s) => `${s} ${combinator || ''} ${selector}`, } }, multipass: false, //order: -1, }, // Targets basically every advanced CSS selector and pesudo content if they are prefixed with a colon `:` // this is very powerful as it allows targeting stuff like `:not(:last-child)` purely through CSS // classes, like `.b:b1/red::not(:last-child)` or `.t:bold::after` the double colon separator is needed // so we can actually do stuff like `:not(:last-child)`, which wouldn't work with a single colon (or put // differently: I'm too dumb to figure out the regex to do that!) // TODO: Figure out why those don't work in conjunction with combinator variants { name: 'pseudo', match: (matcher, ctx) => { const rx = /^[^:|]+:[^:]+(?<pseudoclass>:\S+)$/; //if ( !/:(:.+)$/.test(matcher) ) { return matcher; } if ( !rx.test(matcher) ) { return matcher; } const { groups: { pseudoclass } } = matcher.match(rx); // You can define any custom pseudo-classes and their selector interpolations here const custom = function(pc, s) { return { ':hocus': `${s}:hover, ${s}:focus`, ':hocus-within': `${s}:hover, ${s}:focus-within`, }[pc]; }; //console.log('Pseudoclass match found', matcher, pseudoclass); return { // slice pseudo-class and pass to the next variants and rules matcher: (pseudoclass ? matcher.slice(0, -(pseudoclass.length)) : matcher), selector: (s) => (pseudoclass ? custom(pseudoclass, s) || `${s}${pseudoclass}` : s), } }, // doesn't really work yet, probably my fault (regex?), not that important, specify two classes meanwhile multipass: false, //order: -1, }, // Converts `©(width>500px)` to `@container(width>500px)` to be dealt with by the atrule variant // => meh: I prefer the shortcut atrules like @c, @s, @l... /*{ name: '©rules', match: (matcher, ctx) => { if ( !matcher.includes('©') ) { return matcher; } return { matcher: matcher.replace(/©/g, '@container'), } }, multipass: false, },*/ // @rules { name: '@rules', match: (matcher, ctx) => { const rx = /^\S+:\S+(?<atrule>@[^:]+)/; if ( !rx.test(matcher) ) { return matcher; } const { groups: { atrule } } = matcher.match(rx); /** /* We want to support a variety of @rules, not all make sense to be specified via classes /* but the goal is to support: /* - pre-configured theme breakpoints which are mapped to @media, they are simply a string /* with the exact syntax of a regular CSS media query, this allows for complex breakpoints /* with logical operators etc. without creating a massive parsing overhead here. /* - on-the-fly evaluated breakpoints to be specified like CSS 4 range queries: /* `@(<|<=|=|>=|>)<number><unit>(width|height)(<|<=|=|>=|>)<number><unit>` supporting `width` and `height` /* There's a limit on how far I think it makes sense to go with supporting the offical spec /* it would get highly complex to implement all of it, so for now as we want to translate /* those expressions into the wider supported min-<prop> max-<prop> syntax, once browser support /* for range syntax is not that recent anymore, it should be easy to simply evaluate and forward /* complex range syntax queries with multiple conditions and operators. An implementation detail /* worth noting is the use of `=` (which usually makes 0 sense for media queries, who wants to /* specify an exact pixel value where styles apply?) to communicate values for props, so for example /* you'd specify the orientation feature (normally `@media (orientation: landscape)`) like /* `@orientation=landscape` or `@media(orientation=landscape)` or `@(orientation=landscape) (all valid) /* - @supports(display=grid) => https://css-tricks.com/how-supports-works/ /* - @layer(name), /* - @container((<|<=|=|>=|>)<number><unit>(width|height)(<|<=|=|>=|>)<number><unit>), /* => if none of those 3 keywords are found, @media, is assumed by default, as values can /* contain colons (:) we 'escape' those within the CSS class names with `=` as the colon /* is already used for pseudo classes this goes also for stuff like `@supports(selector(=last-child))` /* and is then translated to `@supports (selector(:last-child))` /*/ function transform(atrule) { //console.log('transform', atrule, ctx.theme.breakpoints[atrule], ctx.theme); // Check theme config for matching breakpoint (with or without the @) and return that early if ( ctx.theme.breakpoints[atrule] || ctx.theme.breakpoints[atrule.substring(1)] ) { return `@media ${(ctx.theme.breakpoints[atrule] || ctx.theme.breakpoints[atrule.substring(1)])}`; } let { groups: { at, rule } } = atrule.match(/^@(?<at>media|c|container|l|layer|s|supports)?(?<rule>\S+)$/); // Map @rule shortcuts like @c, @l, @s, those are different from theme breakpoints as they have a value! // => @l(<layer-name>), @s(display=grid), @c(width>618px) at = { c: 'container', l: 'layer', s: 'supports', }[at] || at; const operators = { '&&': () => ') and (', '||': () => '), (', '!': () => '), not all and (', '<': (p, inv) => (!inv ? `max-${p}: ` : `min-${p}: `), '<=': (p, inv) => (!inv ? `max-${p}: ` : `min-${p}: `), '=': () => ':', '>=': (p, inv) => (!inv ? `min-${p}: ` : `max-${p}: `), '>': (p, inv) => (!inv ? `min-${p}: ` : `max-${p}: `), }; let invert = false; let property = 'width'; // Unwarp @rule from parenthesis if it comes in wrapped rule = (rule.startsWith('(') ? rule.substring(1, rule.length-1) : rule); // Deal with simple values with no operators like @320px, prefix so it transforms to `max-width` // this allows something like `bg:red@320` to translate to `@media (max-width: 320px)` rule = rule.replace(/^(?<v>[\d.]+)(?<u>[a-z%]{1,4})?$/, (m, v, u) => `<${v}${u || 'px'}`); // Deal with range syntax, anything else won't be matched, transform into CSS3 conditions // don't check for proper units here, stop being lazy and write them... rule = rule.replace(/(?<left>[^<>=\s]+)?(?<oleft><=|>=|=|<|>)?(?<prop>width|height)(?<oright><=|>=|=|<|>)(?<right>[^<>=\s]+)/, (match, left, oleft, prop, oright, right) => { invert = !!oleft; property = prop; return `${oleft||''}${left||''}${oleft ? '&&' : ''}${oright}${right}`; }); // Use `.split()` with a RegEx and a capturing group to include the separators const parts = rule.split(/([^<>=&|!]+)?(&&|\|\||!|<=|>=|=|<|>)([^<>=&|!]+)/).filter(x => x); const result = parts.reduce((r, v, i, arr) => { if ( operators[v] ) { r.push(operators[v](property, invert)); // Only applies to range syntax, we have to invert the first operator, then reset the var invert = false; } else { // Resolve custom CSS properties/variables, we can't use them in @rules // a bit like https://github.com/WolfgangKluge/postcss-media-variables if ( v.startsWith('--') ) { v = getComputedStyle(document.documentElement).getPropertyValue(v).trim() || `${v}__var-undefined`; } // Cast unitless numeric values to pixels r.push((/^[\d\.]+$/.test(v) ? `${v}px` : v)); } // Add closing parenthesis if we reached the end (i == arr.length-1 && !(at || '').includes('layer')) && r.push(')'); return r; }, ['@', (at || 'media'), `${!(at || '').includes('layer') ? ' (' : ' '}`]).join(''); //console.log(result); return result; } return { // slice @rule and pass to the next variants and rules matcher: matcher.replace(atrule, ''), //selector: (s) => s, handle: (input, next) => { //console.log('input', input, 'next', next); return next({ ...input, parent: `${input.parent ? `${input.parent} $$ ` : ''}${transform(atrule)}`, }) }, } }, multipass: true, }, // Adds !important to a rules resulting CSS if the class is prefixed with !, e.g. `!t:red` { name: 'important', match: (matcher, ctx) => { if ( !matcher.startsWith('!') ) { return matcher; } return { matcher: matcher.slice(1), // body is an array of tuples like `[ [<prop>, <value>], [<prop>, <value>] ]` body: (body) => { body.forEach(([prop, val], i, arr) => { arr[i] = [prop, ( val ? val += ' !important' : val )]; }); return body; }, } }, multipass: false, }, ], preflights: [ { layer: 'recss', //getCSS: async () => (await fetch('my-style.css')).text(), // `:` (colon) needs double escaping when used in template literal! e.g. `<foo>\\:<bar>` getCSS: ({ theme }) => ` /** /* Little pseudo content helpers. /*/ [data-before]:before { content: attr(data-before); } [data-after]:after { content: attr(data-after); } [data-class]:after { content: attr(class); } /** /* Yes, invalid attribute, but no browser cares, useful for easily showing/hiding entire blocks /* based on FreeMarker/JS conditions. Use like <div class="..." if="{somebooleanexpression?c}">. /*/ [if="false"] { display: none !important; } /** /* Use for elements that should only be visible when handled by JavaScript, it's the JS code's /* responsibility to remove this class once it has done whatever it's doing. Useful for /* pre-rendering markup in FreeMarker and then progressively enhance it with JS. /*/ .js--only { display: none !important; } /** TODO: IMPLEMENT THESE DYNAMICALLY! **/ /** /* LAYOUT, DISPLAY & POSITIONING UTILS /* 1. Completely remove from the flow but leave available to screen readers. /* 2. Fix for Firefox bug: an image styled 'max-width:100%' within an /* inline-block will display at its default size, and not limit its width to /* 100% of an ancestral container. /* 3. The space content is one way to avoid an Opera bug when the /* 'contenteditable' attribute is included anywhere else in the document. /* Otherwise it causes space to appear at the top and bottom of the /* element. /* 4. The use of 'table' rather than 'block' is only necessary if using /* ':before' to contain the top-margins of child elements. /* 5. Make sure fixed elements are promoted into a new layer, for performance /* reasons. /* 6. Element will be absolutely centered inside the nearest relatively-positioned ancestor. /* 7. Element will be centered horizontally regardless of width. Setting 'transform: perspective(1px)' /* prevents element from being blurry if positioned on a "half-pixel", alternatively, setting /* 'transform-style: preserve-3d;' on the parent element has the same effect! /* 8. Element will be centered vertically regardless of height. Setting 'transform: perspective(1px)' /* prevents element from being blurry if positioned on a "half-pixel", alternatively, setting /* 'transform-style: preserve-3d;' on the parent element has the same effect! /* 9. Fix for Chrome 44 bug. https://code.google.com/p/chromium/issues/detail?id=506893 /* 10. Setting percentage height is rather rare, not worth the bloat of all utility classes /*/ .d\\:ib-fix { font-size: 0; line-height: 0; } .d\\:ib-fix > *, .d\\:ib-fix *:before, .d\\:ib-fix *:after { font-size: initial; line-height: initial; vertical-align: middle; } .d\\:f-col-r { -webkit-box-orient: vertical; -webkit-box-direction: reverse; -webkit-flex-direction: column-reverse; -ms-flex-direction: column-reverse; flex-direction: column-reverse; } .d\\:f-row-r { -webkit-box-orient: horizontal; -webkit-box-direction: reverse; -webkit-flex-direction: row-reverse; -ms-flex-direction: row-reverse; flex-direction: row-reverse; } .d\\:f-wrap-r { -webkit-flex-wrap: wrap-reverse; -ms-flex-wrap: wrap-reverse; flex-wrap: wrap-reverse; } .d\\:fc-items-start { -webkit-box-align: start; -webkit-align-items: flex-start; -ms-flex-align: start; align-items: flex-start; } .d\\:fc-items-end { -webkit-box-align: end; -webkit-align-items: flex-end; -ms-flex-align: end; align-items: flex-end; } .d\\:fc-items-baseline { -webkit-box-align: baseline; -webkit-align-items: baseline; -ms-flex-align: baseline; align-items: baseline; } .d\\:fc-items-stretch { -webkit-box-align: stretch; -webkit-align-items: stretch; -ms-flex-align: stretch; align-items: stretch; } .d\\:fc-justify-start { -webkit-box-pack: start; -webkit-justify-content: flex-start; -ms-flex-pack: start; justify-content: flex-start; } .d\\:fc-justify-end { -webkit-box-pack: end; -webkit-justify-content: flex-end; -ms-flex-pack: end; justify-content: flex-end; } .d\\:fc-justify-around { -webkit-justify-content: space-around; -ms-flex-pack: distribute; justify-content: space-around; } .d\\:fc-justify-evenly { -webkit-box-pack: space-evenly; -webkit-justify-content: space-evenly; -ms-flex-pack: space-evenly; justify-content: space-evenly; /* not supported in Edge! */ } .d\\:fc-content-start { -webkit-align-content: flex-start; -ms-flex-line-pack: start; align-content: flex-start; } .d\\:fc-content-end { -webkit-align-content: flex-end; -ms-flex-line-pack: end; align-content: flex-end; } .d\\:fc-content-center { -webkit-align-content: center; -ms-flex-line-pack: center; align-content: center; } .d\\:fc-content-between { -webkit-align-content: space-between; -ms-flex-line-pack: justify; align-content: space-between; } .d\\:fc-content-around { -webkit-align-content: space-around; -ms-flex-line-pack: distribute; align-content: space-around; } .d\\:fc-content-stretch { -webkit-align-content: stretch; -ms-flex-line-pack: stretch; align-content: stretch; } .d\\:fi-self-start { -webkit-align-self: flex-start; -ms-flex-item-align: start; align-self: flex-start; } .d\\:fi-self-end { -webkit-align-self: flex-end; -ms-flex-item-align: end; align-self: flex-end; } .d\\:fi-self-center { -webkit-align-self: center; -ms-flex-item-align: center; align-self: center; } .d\\:fi-self-baseline { -webkit-align-self: baseline; -ms-flex-item-align: baseline; align-self: baseline; } .d\\:fi-self-stretch { -webkit-align-self: stretch; -ms-flex-item-align: stretch; align-self: stretch; } .d\\:fi-grow { -webkit-box-flex: 1; -webkit-flex: 1 1 auto; -ms-flex: 1 1 auto; flex: 1 1 auto; min-width: 0; /* 9 */ min-height: 0; /* 9 */ } .d\\:table { display: table; } .d\\:table-collapse { border-collapse: collapse; } .d\\:table-separate { border-collapse: separate; } .d\\:table-spacing { border-spacing: 1px; } .d\\:td { display: table-cell; } .d\\:tr { display: table-row; } .d\\:left { float: left; } .d\\:right { float: right; } .d\\:clear:before, .d\\:clear:after { content: " "; /* 3 */ display: table; /* 4 */ } .d\\:clear:after { clear: both; } .d\\:valign-baseline { vertical-align: baseline; } .d\\:valign-top { vertical-align: top; } .d\\:valign-middle { vertical-align: middle; } .d\\:valign-bottom { vertical-align: bottom; } .d\\:valign-all-baseline > * { vertical-align: baseline; } .d\\:valign-all-top > * { vertical-align: top; } .d\\:valign-all-middle > * { vertical-align: middle; } .d\\:valign-all-bottom > * { vertical-align: bottom; } /** /* Skeleton loader styles /* @credits: https://css-tricks.com/a-bare-bones-approach-to-versatile-and-reusable-skeleton-loaders/ /* Multi-row skeleton loaders can be added by adding <br/> elements assuming that all /* child (content) elements get replaced with actual content once loading is done. /*/ .is--loading, .is--loading * { pointer-events: none; user-select: none; cursor: default; } .is--loading .sk\\:el { animation: 2s sk\\:progress linear infinite; background-size: 200% 100%; /* for loading animation */ background: var(--c-skeleton-bg); background: var(--c-skeleton-gradient); border-color: rgba(0,0,0,0) !important; border-radius: 2px; color: rgba(0,0,0,0) !important; } .is--loading .sk\\:el:is(.sk\\:static) { animation: none !important; background: var(--c-skeleton-bg); } @media (prefers-reduced-motion) { .is--loading .sk\\:el { animation: none !important; background: var(--c-skeleton-bg); } } /* Make sure all child elements are hidden, but preserve their dimensions and layout */ .is--loading .sk\\:el * { visibility: hidden; } /** * Make sure that an element has at least a whitespace character as a child so it displays * properly. This is useful when no text placeholder is present (element is empty). */ .is--loading .sk\\:el:empty:after, .is--loading .sk\\:el *:empty:after { content: ' '; /* Can't use 00a0 (octal escape sequences) in template literls! */ } @keyframes sk\\:progress { to { background-position-x: -200%; } } ` }, ], /*transformers: [ { name: 'my-transformer', enforce: 'pre', // enforce before other transformers idFilter(id) { // only transform .tsx and .jsx files //return id.match(/\.[tj]sx$/) //console.log('transformer: idFilter', id); return true; }, async transform(code, id, { uno }) { // code is a MagicString instance //console.log('transformer: transform()', code, id, uno); }, } ],*/ /* preprocess: (t) => { // for example prefix all classes with ! which makes them !important (bad idea!) if (t.includes('!')) return t; return `!${t}`; }, */ // convert pixels to rem for all utils postprocess: (util, ...args) => { if ( !window || !window.__unocss?.theme?.px2rem ) { return } const px = /(-?[\.\d]+)px/g; const reminpx = parseFloat(getComputedStyle(document.documentElement).fontSize); util.entries.forEach((i) => { const value = i[1]; if ( typeof value === 'string' && px.test(value) ) { i[1] = value.replace(px, (_, v) => `${v / reminpx}rem`); } }); }, /*extractors: [ // This is the default split extractor of UnoCSS, comment out what is below if you encounter // issues and try this one, it's very crude... but works with more or less false positives // depending on the markup your are working with { name: '@unocss/core/extractor-split', order: 0, extract({ code }) { const defaultSplitRE = /[\\:]?[\s'"`;{}]+/g; function splitCode(code) { return code.split(defaultSplitRE); }; console.log('split extractor code', typeof code, code.split(defaultSplitRE)); return splitCode(code) }, }, { name: 're:css', order: 0, extract({ code }) { const classes = []; for ([_, q, c] of code.matchAll(/(?:class\s*?=\s*?)(["'])((?:(?=(?:\\)*)\\.|.)*?)\1/gi)) { classes.push(...c.split(/\s+/g)); } console.log('re:css extractor classes', classes); return classes; }, } ],*/ // disable the default extractor //extractorDefault: false, // override the default extractor // This one WILL FAIL if you do not quote your class attribute values (as you should anyways)! // But this extractor is 5-10x faster than the default extractor extractorDefault: { name: 're:css', order: 0, extract({ code }) { //const start = performance.now(); const classes = []; for (match of code.matchAll(/(?:class\s*?=\s*?)(["'])((?:(?=(?:\\)*)\\.|.)*?)\1/gi)) { // we use the default splitter RegEx, but only to split class attribute values, nothing else // it properly deals with inline riot `<template>` tags that contain unparsed expressions // `{ <expression> }` which cause problems with a 'simple' whitespace splitter... classes.push(...match[2].split(/[\\:]?[\s'"`;{}]+/g)); } //console.log('re:css extractor classes', classes); //console.log(`custom extractor done in ${performance.now()-start}ms`); return classes; }, }, // This is actually the default extractor, takes 60ms+ for a large HTML document /*extractorDefault: { name: '@unocss/core/extractor-split', order: 0, extract({ code }) { //const start = performance.now(); const defaultSplitRE = /[\\:]?[\s'"`;{}]+/g; function splitCode(code) { return code.split(defaultSplitRE); }; const tokens = splitCode(code); //console.log(`default extractor done in ${performance.now()-start}ms`); return tokens; }, },*/ runtime: { inject: (styleElement) => document.head.append(styleElement), observer: { target: () => document.querySelector('.lia-page'), attributeFilter: ['class'], }, //inspect: (el) => { console.log(el); if ( /\S+:\S+/gi.test(el.getAttribute('class') || '') ) { console.log('uno inspect', el, el.classList, el.classList.matchAll(/\S+:\S+/gi)); } return true; }, ready: (ctx) => { //console.log('uno ready?', `${performance.now()-window.$start}ms`, ctx); // we can't pass the inspect callback directly via runtime config? why? ctx.inspect((el) => { if ( /\S+:\S+/gi.test(el.getAttribute('class') || '') ) { [...el.classList].filter((x) => /\S+:\S+/i.test(x)).forEach((v) => { window.$stats[v] = (window.$stats[v] || 0) + 1; }); } // need to return true from inspector callback return true; }); // need to return true from ready return true; }, //configResolved: (config, defaults) => { console.log('uno config resolved, modify it?', `${performance.now()-window.$start}ms`, config, defaults); }, }, }; </script> <script src="https://community.hubspot.com/html/@BAA2A9A38B8DF4DC5426B3D61241E9AB/assets/_core.libs.min.js" type="text/javascript"></script> <script src="https://community.hubspot.com/html/@B5A089E4D43239236FCE70D92814096D/assets/_core.global.min.js" type="text/javascript"></script> <script src="https://community.hubspot.com/html/@F771820AC374A1A1436A3D822BE61093/assets/_cmp.min.js" type="text/javascript"></script> <link rel="icon" href="https://community.hubspot.com/html/@46292D292824DF071B6641C2DA6FDD8E/assets/favicon.png"> <!--[if IE]><link rel="shortcut icon" href="https://community.hubspot.com/html/@46292D292824DF071B6641C2DA6FDD8E/assets/favicon.png"><![endif]--> <meta class="swiftype" name="doc-type" data-type="string" content="Community"> <script data-external-hs-domain="true" data-gtm-id="GTM-TM3F7HX" src="https://www.hubspot.com/wt-assets/static-files/compliance/index.js" defer nonce></script> <script type="text/javascript" src="/t5/scripts/A8A4D60844A7A24245ECDC960EA81DEE/lia-scripts-head-min.js"></script><script language="javascript" type="text/javascript"> <!-- LITHIUM.PrefetchData = {"Components":{},"commonResults":{}}; LITHIUM.DEBUG = false; LITHIUM.CommunityJsonObject = { "Validation" : { "image.description" : { "min" : 0, "max" : 1000, "isoneof" : [ ], "type" : "string" }, "tkb.toc_maximum_heading_level" : { "min" : 1, "max" : 6, "isoneof" : [ ], "type" : "integer" }, "tkb.toc_heading_list_style" : { "min" : 0, "max" : 50, "isoneof" : [ "disc", "circle", "square", "none" ], "type" : "string" }, "blog.toc_maximum_heading_level" : { "min" : 1, "max" : 6, "isoneof" : [ ], "type" : "integer" }, "tkb.toc_heading_indent" : { "min" : 5, "max" : 50, "isoneof" : [ ], "type" : "integer" }, "blog.toc_heading_indent" : { "min" : 5, "max" : 50, "isoneof" : [ ], "type" : "integer" }, "blog.toc_heading_list_style" : { "min" : 0, "max" : 50, "isoneof" : [ "disc", "circle", "square", "none" ], "type" : "string" } }, "User" : { "settings" : { "imageupload.legal_file_extensions" : "*.jpg;*.JPG;*.jpeg;*.JPEG;*.gif;*.GIF;*.png;*.PNG", "config.enable_avatar" : true, "integratedprofile.show_klout_score" : true, "layout.sort_view_by_last_post_date" : false, "layout.friendly_dates_enabled" : true, "profileplus.allow.anonymous.scorebox" : false, "tkb.message_sort_default" : "topicPublishDate", "layout.format_pattern_date" : "MMM d, yyyy", "config.require_search_before_post" : "off", "isUserLinked" : false, "integratedprofile.cta_add_topics_dismissal_timestamp" : -1, "layout.message_body_image_max_size" : 1000, "profileplus.everyone" : false, "integratedprofile.cta_connect_wide_dismissal_timestamp" : -1, "blog.toc_maximum_heading_level" : "", "integratedprofile.hide_social_networks" : false, "blog.toc_heading_indent" : "", "contest.entries_per_page_num" : 20, "layout.messages_per_page_linear" : 12, "integratedprofile.cta_manage_topics_dismissal_timestamp" : -1, "profile.shared_profile_test_group" : false, "integratedprofile.cta_personalized_feed_dismissal_timestamp" : -1, "integratedprofile.curated_feed_size" : 10, "contest.one_kudo_per_contest" : false, "integratedprofile.enable_social_networks" : false, "integratedprofile.my_interests_dismissal_timestamp" : -1, "profile.language" : "es", "layout.friendly_dates_max_age_days" : 31, "layout.threading_order" : "thread_descending", "blog.toc_heading_list_style" : "disc", "useRecService" : false, "layout.module_welcome" : "", "imageupload.max_uploaded_images_per_upload" : 100, "imageupload.max_uploaded_images_per_user" : 6000, "integratedprofile.connect_mode" : "", "tkb.toc_maximum_heading_level" : "", "tkb.toc_heading_list_style" : "disc", "sharedprofile.show_hovercard_score" : true, "config.search_before_post_scope" : "container", "tkb.toc_heading_indent" : "", "p13n.cta.recommendations_feed_dismissal_timestamp" : -1, "imageupload.max_file_size" : 3072, "layout.show_batch_checkboxes" : false, "integratedprofile.cta_connect_slim_dismissal_timestamp" : -1 }, "isAnonymous" : true, "policies" : { "image-upload.process-and-remove-exif-metadata" : false }, "registered" : false, "emailRef" : "", "id" : -1, "login" : "Anonymous" }, "Server" : { "communityPrefix" : "/mjmao93648", "nodeChangeTimeStamp" : 1732786559813, "tapestryPrefix" : "/t5", "deviceMode" : "DESKTOP", "responsiveDeviceMode" : "DESKTOP", "membershipChangeTimeStamp" : "0", "version" : "24.8", "branch" : "24.8-release", "showTextKeys" : false }, "Config" : { "phase" : "prod", "integratedprofile.cta.reprompt.delay" : 30, "profileplus.tracking" : { "profileplus.tracking.enable" : false, "profileplus.tracking.click.enable" : false, "profileplus.tracking.impression.enable" : false }, "app.revision" : "2410251442-s96644fcabc-b95", "navigation.manager.community.structure.limit" : "1000" }, "Activity" : { "Results" : [ { "name" : "UserUpdated", "user" : { "uid" : -1, "login" : "Anonymous" } } ] }, "NodeContainer" : { "viewHref" : "https://community.hubspot.com/t5/Top/ct-p/top", "description" : "", "id" : "top", "shortTitle" : "Top", "title" : "Top", "nodeType" : "category" }, "Page" : { "skins" : [ "hubspot", "responsive_peak" ], "authUrls" : { "loginUrl" : "https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2F", "loginUrlNotRegistered" : "https://app.hubspot.com/khoros/integration/jwt/authenticate?redirectreason=notregistered&referer=https%3A%2F%2Fcommunity.hubspot.com%2F", "loginUrlNotRegisteredDestTpl" : "https://app.hubspot.com/khoros/integration/jwt/authenticate?redirectreason=notregistered&referer=%7B%7BdestUrl%7D%7D" }, "name" : "CommunityPage", "rtl" : false, "object" : { "viewHref" : "/", "id" : "mjmao93648", "page" : "CommunityPage", "type" : "Community" } }, "WebTracking" : { "Activities" : { }, "path" : "Community:HubSpot Community" }, "Feedback" : { "targeted" : { } }, "Seo" : { "markerEscaping" : { "pathElement" : { "prefix" : "@", "match" : "^[0-9][0-9]$" }, "enabled" : false } }, "TopLevelNode" : { "viewHref" : "https://community.hubspot.com/", "description" : "Welcome to the HubSpot Community! Connect with peers, maximize your HubSpot knowledge, and learn how to grow better with HubSpot.", "id" : "mjmao93648", "shortTitle" : "HubSpot Community", "title" : "HubSpot Community", "nodeType" : "Community" }, "Community" : { "viewHref" : "https://community.hubspot.com/", "integratedprofile.lang_code" : "en", "integratedprofile.country_code" : "US", "id" : "mjmao93648", "shortTitle" : "HubSpot Community", "title" : "HubSpot Community" }, "CoreNode" : { "viewHref" : "https://community.hubspot.com/", "settings" : { }, "description" : "Welcome to the HubSpot Community! Connect with peers, maximize your HubSpot knowledge, and learn how to grow better with HubSpot.", "id" : "mjmao93648", "shortTitle" : "HubSpot Community", "title" : "HubSpot Community", "nodeType" : "Community", "ancestors" : [ ] } }; LITHIUM.Components.RENDER_URL = "/t5/util/componentrenderpage/component-id/#{component-id}?render_behavior=raw"; LITHIUM.Components.ORIGINAL_PAGE_NAME = 'community/Page'; LITHIUM.Components.ORIGINAL_PAGE_ID = 'CommunityPage'; LITHIUM.Components.ORIGINAL_PAGE_CONTEXT = 'Q84rhXN5GOdCNwfN5nuJ6nFbphtGBh1g1oofl3ijSMuNrN9UJ7m3EBYsy9BirlqK9DpkbqN8cNQ2_oQdLOlbBerE0zTBKa6_lUFMfdsuaQrN2ib56cvEUhGQcpuVaybA7OJD6seDoVCfhdU73qv2GlDhnnyvMczoVysQGKVRy2e1Fj1-naq4JQj2fZN9yFFkamVESFkl91Cn7vpSHSKJ5W2FP2r7nFUPzaNRJfzqJWmNdpo8HC8_v271ch7cW9QopxzlS633ovz60fRBGAfp8JhdjOmHLcEcfcvYaC_aybcInJa9Wnp9EbNlaak49gj8U-qzSd4CBHx1lp2mzIejx5RWIVAXX_XcrYFEzC5esTg.'; LITHIUM.Css = { "BASE_DEFERRED_IMAGE" : "lia-deferred-image", "BASE_BUTTON" : "lia-button", "BASE_SPOILER_CONTAINER" : "lia-spoiler-container", "BASE_TABS_INACTIVE" : "lia-tabs-inactive", "BASE_TABS_ACTIVE" : "lia-tabs-active", "BASE_AJAX_REMOVE_HIGHLIGHT" : "lia-ajax-remove-highlight", "BASE_FEEDBACK_SCROLL_TO" : "lia-feedback-scroll-to", "BASE_FORM_FIELD_VALIDATING" : "lia-form-field-validating", "BASE_FORM_ERROR_TEXT" : "lia-form-error-text", "BASE_FEEDBACK_INLINE_ALERT" : "lia-panel-feedback-inline-alert", "BASE_BUTTON_OVERLAY" : "lia-button-overlay", "BASE_TABS_STANDARD" : "lia-tabs-standard", "BASE_AJAX_INDETERMINATE_LOADER_BAR" : "lia-ajax-indeterminate-loader-bar", "BASE_AJAX_SUCCESS_HIGHLIGHT" : "lia-ajax-success-highlight", "BASE_CONTENT" : "lia-content", "BASE_JS_HIDDEN" : "lia-js-hidden", "BASE_AJAX_LOADER_CONTENT_OVERLAY" : "lia-ajax-loader-content-overlay", "BASE_FORM_FIELD_SUCCESS" : "lia-form-field-success", "BASE_FORM_WARNING_TEXT" : "lia-form-warning-text", "BASE_FORM_FIELDSET_CONTENT_WRAPPER" : "lia-form-fieldset-content-wrapper", "BASE_AJAX_LOADER_OVERLAY_TYPE" : "lia-ajax-overlay-loader", "BASE_FORM_FIELD_ERROR" : "lia-form-field-error", "BASE_SPOILER_CONTENT" : "lia-spoiler-content", "BASE_FORM_SUBMITTING" : "lia-form-submitting", "BASE_EFFECT_HIGHLIGHT_START" : "lia-effect-highlight-start", "BASE_FORM_FIELD_ERROR_NO_FOCUS" : "lia-form-field-error-no-focus", "BASE_EFFECT_HIGHLIGHT_END" : "lia-effect-highlight-end", "BASE_SPOILER_LINK" : "lia-spoiler-link", "BASE_DISABLED" : "lia-link-disabled", "FACEBOOK_LOGOUT" : "lia-component-users-action-logout", "FACEBOOK_SWITCH_USER" : "lia-component-admin-action-switch-user", "BASE_FORM_FIELD_WARNING" : "lia-form-field-warning", "BASE_AJAX_LOADER_FEEDBACK" : "lia-ajax-loader-feedback", "BASE_AJAX_LOADER_OVERLAY" : "lia-ajax-loader-overlay", "BASE_LAZY_LOAD" : "lia-lazy-load" }; LITHIUM.noConflict = true; LITHIUM.useCheckOnline = false; LITHIUM.RenderedScripts = [ "jquery.ui.mouse.js", "jquery.placeholder-2.0.7.js", "Loader.js", "jquery.iframe-shim-1.0.js", "ForceLithiumJQuery.js", "jquery.ui.widget.js", "jquery.json-2.6.0.js", "Auth.js", "Tooltip.js", "jquery.effects.core.js", "Sandbox.js", "json2.js", "jquery.css-data-1.0.js", "jquery.viewport-1.0.js", "DataHandler.js", "Forms.js", "jquery.ui.position.js", "SpoilerToggle.js", "AutoComplete.js", "Text.js", "Namespace.js", "jquery.delayToggle-1.0.js", "jquery.fileupload.js", "prism.js", "jquery.ui.dialog.js", "LiModernizr.js", "jquery.tools.tooltip-1.2.6.js", "Video.js", "ElementMethods.js", "PolyfillsAll.js", "jquery.ajax-cache-response-1.0.js", "AjaxSupport.js", "jquery.js", "jquery.appear-1.1.1.js", "DeferredImages.js", "jquery.ui.draggable.js", "jquery.ui.resizable.js", "SearchAutoCompleteToggle.js", "SearchForm.js", "jquery.effects.slide.js", "ActiveCast3.js", "Components.js", "jquery.tmpl-1.1.1.js", "ResizeSensor.js", "jquery.function-utils-1.0.js", "jquery.blockui.js", "jquery.iframe-transport.js", "jquery.scrollTo.js", "InformationBox.js", "jquery.position-toggle-1.0.js", "PolyfillsOld.js", "ElementQueries.js", "Link.js", "HelpIcon.js", "Events.js", "Placeholder.js", "PartialRenderProxy.js", "jquery.lithium-selector-extensions.js", "NoConflict.js", "Globals.js", "UserListActual.js", "Throttle.js", "jquery.autocomplete.js", "Cache.js", "AjaxFeedback.js", "Lithium.js", "jquery.hoverIntent-r6.js", "jquery.clone-position-1.0.js", "jquery.ui.core.js" ];// --> </script><script type="text/javascript" src="/t5/scripts/D60EB96AE5FF670ED274F16ABB044ABD/lia-scripts-head-min.js"></script></head> <body class="lia-user-status-anonymous CommunityPage lia-body" id="lia-body"> <div id="36B-192-4" class="ServiceNodeInfoHeader"> </div> <div class="lia-page"> <center> <noscript class=" " id="hubspot" data-page="CommunityPage" data-style="none" data-rootid="mjmao93648" data-roottype="community" data-topid="mjmao93648" data-nodeid="mjmao93648" data-nodetype="community" data-nodelang="en" data-userlang="es" data-skin="hubspot"> <p>Se debe instalar y activar JavaScript para utilizar estos foros.<p> Parece que el navegador tiene JavaScript desactivado o que no lo admite. Consulte el archivo de ayuda del navegador para determinar cómo activar JavaScript.</p> </noscript> <svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <symbol id="i:hubspot" viewBox="0 0 32 32"> <path d="M23.7 10.92V7.36a2.74 2.74 0 0 0 1.59-2.48V4.8a2.75 2.75 0 0 0-2.74-2.74h-.08a2.75 2.75 0 0 0-2.74 2.74v.08c0 1.1.64 2.03 1.56 2.47h.02v3.57a7.7 7.7 0 0 0-3.71 1.64l.01-.01-9.78-7.62a3.12 3.12 0 1 0-1.45 1.9h-.01l9.62 7.49a7.75 7.75 0 0 0 .14 8.81l-.02-.03-2.93 2.94a2.54 2.54 0 1 0 1.81 2.43c0-.27-.04-.52-.12-.75v.01l2.9-2.9a7.8 7.8 0 1 0 5.98-13.91h-.04zm-1.2 11.72a3.55 3.55 0 1 1 .01 0z" /> </symbol> <symbol id="i:link" viewBox="0 0 20 20"> <path d="M7.859 14.691l-0.81 0.805c-0.701 0.695-1.843 0.695-2.545 0-0.336-0.334-0.521-0.779-0.521-1.252s0.186-0.916 0.521-1.252l2.98-2.955c0.617-0.613 1.779-1.515 2.626-0.675 0.389 0.386 1.016 0.384 1.403-0.005 0.385-0.389 0.383-1.017-0.006-1.402-1.438-1.428-3.566-1.164-5.419 0.675l-2.98 2.956c-0.715 0.709-1.108 1.654-1.108 2.658 0 1.006 0.394 1.949 1.108 2.658 0.736 0.73 1.702 1.096 2.669 1.096s1.934-0.365 2.669-1.096l0.811-0.805c0.389-0.385 0.391-1.012 0.005-1.4s-1.014-0.39-1.403-0.006zM16.891 3.207c-1.547-1.534-3.709-1.617-5.139-0.197l-1.009 1.002c-0.389 0.386-0.392 1.013-0.006 1.401 0.386 0.389 1.013 0.391 1.402 0.005l1.010-1.001c0.74-0.736 1.711-0.431 2.346 0.197 0.336 0.335 0.522 0.779 0.522 1.252s-0.186 0.917-0.522 1.251l-3.18 3.154c-1.454 1.441-2.136 0.766-2.427 0.477-0.389-0.386-1.016-0.383-1.401 0.005s-0.384 1.017 0.005 1.401c0.668 0.662 1.43 0.99 2.228 0.99 0.977 0 2.010-0.492 2.993-1.467l3.18-3.153c0.712-0.71 1.107-1.654 1.107-2.658s-0.395-1.949-1.109-2.659z"></path> </symbol> <symbol id="i:linkedin" viewBox="0 0 20 20"> <path d="M10 0.4c-5.302 0-9.6 4.298-9.6 9.6s4.298 9.6 9.6 9.6 9.6-4.298 9.6-9.6-4.298-9.6-9.6-9.6zM7.65 13.979h-1.944v-6.256h1.944v6.256zM6.666 6.955c-0.614 0-1.011-0.435-1.011-0.973 0-0.549 0.409-0.971 1.036-0.971s1.011 0.422 1.023 0.971c0 0.538-0.396 0.973-1.048 0.973zM14.75 13.979h-1.944v-3.467c0-0.807-0.282-1.355-0.985-1.355-0.537 0-0.856 0.371-0.997 0.728-0.052 0.127-0.065 0.307-0.065 0.486v3.607h-1.945v-4.26c0-0.781-0.025-1.434-0.051-1.996h1.689l0.089 0.869h0.039c0.256-0.408 0.883-1.010 1.932-1.010 1.279 0 2.238 0.857 2.238 2.699v3.699z"></path> </symbol> <symbol id="i:xcom" viewBox="0 0 32 32"> <path d="M24.325 3h4.411l-9.636 11.013 11.336 14.987h-8.876l-6.952-9.089-7.955 9.089h-4.413l10.307-11.78-10.875-14.22h9.101l6.284 8.308zM22.777 26.36h2.444l-15.776-20.859h-2.623z"></path> </symbol> <symbol id="i:connectcom" viewBox="0 0 24 24"> <path fill="#192733" style="fill: var(--color1, #192733)" d="M17.585 5.753c-1.941 0-3.675 0.886-4.822 2.273l0.005 0.005c-0.025 0.030-0.052 0.060-0.075 0.092l-3.988 5.512c-0.608 0.75-1.335 1.171-2.291 1.171-1.549 0-2.806-1.258-2.806-2.806s1.258-2.806 2.806-2.806c1.082 0 1.953 0.603 2.519 1.492l2.261-2.712c-1.146-1.36-2.861-2.221-4.78-2.221-3.452 0.003-6.248 2.799-6.248 6.248s2.797 6.248 6.248 6.248c1.941 0 3.675-0.886 4.822-2.273l-0.005-0.005c0.067-0.067 0.132-0.136 0.189-0.216l4.023-5.559c0.579-0.642 1.263-1 2.142-1 1.549 0 2.806 1.258 2.806 2.806s-1.258 2.806-2.806 2.806c-1.082 0-1.953-0.603-2.519-1.492l-2.261 2.712c1.146 1.36 2.861 2.221 4.78 2.221 3.452 0 6.248-2.797 6.248-6.248s-2.797-6.248-6.248-6.248z"></path> <path fill="#ff5c35" style="fill: var(--color2, #ff5c35)" d="M17.585 10.15c-0.747 0-1.389 0.446-1.682 1.085h-7.737c-0.293-0.64-0.935-1.085-1.682-1.085-1.020 0-1.849 0.829-1.849 1.849s0.829 1.849 1.849 1.849c0.747 0 1.389-0.446 1.682-1.085h7.737c0.293 0.64 0.935 1.085 1.682 1.085 1.020 0 1.849-0.829 1.849-1.849s-0.829-1.849-1.849-1.849z"></path> </symbol> <symbol id="i:globe" viewBox="0 0 24 24"> <path d="M16.951 11c-0.214-2.69-1.102-5.353-2.674-7.71 1.57 0.409 2.973 1.232 4.087 2.346 1.408 1.408 2.351 3.278 2.581 5.364zM14.279 20.709c1.483-2.226 2.437-4.853 2.669-7.709h3.997c-0.23 2.086-1.173 3.956-2.581 5.364-1.113 1.113-2.516 1.936-4.085 2.345zM7.049 13c0.214 2.69 1.102 5.353 2.674 7.71-1.57-0.409-2.973-1.232-4.087-2.346-1.408-1.408-2.351-3.278-2.581-5.364zM9.721 3.291c-1.482 2.226-2.436 4.853-2.669 7.709h-3.997c0.23-2.086 1.173-3.956 2.581-5.364 1.114-1.113 2.516-1.936 4.085-2.345zM12.004 1c0 0 0 0 0 0-3.044 0.001-5.794 1.233-7.782 3.222-1.99 1.989-3.222 4.741-3.222 7.778s1.232 5.789 3.222 7.778c1.988 1.989 4.738 3.221 7.774 3.222 0 0 0 0 0 0 3.044-0.001 5.793-1.233 7.782-3.222 1.99-1.989 3.222-4.741 3.222-7.778s-1.232-5.789-3.222-7.778c-1.988-1.989-4.738-3.221-7.774-3.222zM14.946 13c-0.252 2.788-1.316 5.36-2.945 7.451-1.729-2.221-2.706-4.818-2.945-7.451zM11.999 3.549c1.729 2.221 2.706 4.818 2.945 7.451h-5.89c0.252-2.788 1.316-5.36 2.945-7.451z"></path> </symbol> </defs> </svg> <style class="core-cmp-icons/core" type="text/css"> .i { display: inline-block; fill: currentColor; height: 1rem; width: 1rem; stroke-width: 0; stroke: currentColor; } /* Single-colored icons can be modified like so but this usually happens directly where they are used: */ /* .i\:<name> { font-size: 32px; color: red; } */ </style> <style class="cmp-global-styles/core" type="text/css"> /** /* TODO: Potentially move to skin or leave here? Might be easier to find changes done by us this way? /*/ /* Center category banner card icons (often the HTMl is CC23 based), for example Advocacy */ #lia-body .custom-home-banner-section__cards .card-item__icon { align-self: center; } /* Fix unstyled layout for NotifyModeratorPage quilt */ .lia-quilt-notify-moderator-page > .lia-quilt-row-header .lia-page-header, .lia-quilt-notify-moderator-page > .lia-quilt-row-main { margin: 0 auto; max-width: 1236px; padding-left: 15px; padding-right: 15px; } /* KBCOM-2818: Add node description the hacky way */ .CategoryPage .custom-v2-banner__wrapper .page-title-wrapper:after, .ForumPage .custom-v2-banner__wrapper .page-title-wrapper:after, .GroupHubPage .custom-v2-banner__wrapper .page-title-wrapper:after { content: "Welcome to the HubSpot Community! Connect with peers, maximize your HubSpot knowledge, and learn how to grow better with HubSpot."; display: block; margin-bottom: -24px; } /* KBCOM-2802: Fix BlogDashboardPage filter alignment issue */ .BlogDashboardPage .dashboard-wrapper { margin: 0 auto; max-width: 1236px; } .BlogDashboardPage .dashboard-wrapper .lia-node-selector-dropdown { left: auto !important; right: 0; } .BlogDashboardPage .dashboard-wrapper .lia-component-blog-dashboard-tabs ul.lia-tabs-standard, .BlogDashboardPage .dashboard-wrapper .lia-component-blog-widget-dashboard-tabs ul.lia-tabs-standard { padding-left: 0 !important; } /* KBCOM-2831: Remove advanced search options toggle on SearchPage */ .SearchPage .lia-advanced-search-toggle { display: none; } /* re-css cloaking class to hide components relying on dynamically generated classes to only show when they are ready */ [un-cloak] { display: none; } /** /* Custom styles for core feedback elements. Those are usually only used to provide info and hints /* to priviledged roles when issues occur within custom components, so they are not part of the /* regular community theme. /*/ .admininfo { --b-radius: 3px; --H: 0; --S: 0%; --L: 41%; --A: 1; background: hsla(var(--H), var(--S), var(--L), var(--A)); border-radius: var(--b-radius); color: white; display: flex; align-items: center; gap: 24px; /*filter: grayscale(1);*/ font-size: 12px; line-height: 1.25; margin: 24px 0; padding: 24px; transition: all 236ms ease; } .admininfo .checkmark { display: none; } .admininfo__title { display: block; font-weight: bold; font-size: 125%; } .admininfo code { background: white; border-radius: var(--b-radius); color: hsla(var(--H), var(--S), var(--L), 1); display: inline-block; font-size: 90%; font-weight: bold; padding: 2px 4px; } .admininfo a { color: white; display: inline-block; position: relative; } .admininfo a:hover, .admininfo a:focus { text-decoration: none; } .admininfo a:before, .admininfo a:after { border-bottom: 1px dotted white; content: ''; position: absolute; left: 0; right: 0; bottom: -1px; transition: all 382ms ease; } .admininfo a:after { border-bottom: 1px solid white; max-width: 0; width: 0; right: auto; } .admininfo a:hover:after, .admininfo a:focus:after { max-width: 100%; width: 1200px; } .admininfo a:active:after { transform: scaleX(1.0618); } .admininfo.is--error { --S: 100%; --L: 41%; background: hsla(var(--H), var(--S), var(--L), var(--A)); filter: grayscale(0); } .admininfo.is--error .checkmark { display: block; } .admininfo.is--error code { background: #ff4444; color: white; } .admininfo.is--success { --H: 135; --S: 100%; background: hsla(var(--H), var(--S), var(--L), var(--A)); filter: grayscale(0); } .admininfo.is--success code { background: #00c851; color: white; } .checkmark { flex-shrink: 0; /* prevents shrinking under 48px! */ min-width: 48px; width: 48px; height: 48px; border-radius: 50%; display: block; stroke-width: 3px; stroke: white; stroke-miterlimit: 10; } .checkmark_circle_error { stroke-dasharray: 166; stroke-dashoffset: 166; stroke-width: 5px; stroke-miterlimit: 10; stroke: #ff4444; animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards; } .checkmark.error { box-shadow: inset 0px 0px 0px #ff4444; animation: fillerror 0.4s ease-in-out 0.4s forwards, scale 0.3s ease-in-out 0.9s both; } .checkmark_check { transform-origin: 50% 50%; stroke-dasharray: 48; stroke-dashoffset: 48; animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.9s forwards; } .progress { position: absolute; top: 5%; left: 5%; stroke: black; transform: rotate(-90deg); } .progress.progress--thin { left: auto; right: 5%; } .progress circle { stroke-dasharray: 130; stroke-dashoffset: 130; animation: dash 1.5s infinite; } @keyframes dash { 50% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: -130; } } @keyframes stroke { 100% { stroke-dashoffset: 0; } } @keyframes scale { 0%, 100% { transform: none; } 50% { transform: scale3d(1.1, 1.1, 1); } } @keyframes fillerror { 100% { box-shadow: inset 0px 0px 0px 75px #ff4444; } } </style><style class="cmp-global-search-external/core" type="text/css"> @media (min-width: 799px) { .lia-search-input-message + .lia-autocomplete-container { width: 200% !important; max-width: 768px !important; } } .lia-search-input-message + .lia-autocomplete-container .lia-autocomplete-content { display: flex; margin: 0; } @media (max-width: 799px) { .mobile-header form.SerachForm [name="messageSearchField"] + .lia-autocomplete-container > ul:first-of-type { max-height: 210px !important; } /*.mobile-header form.SerachForm [name="messageSearchField"] + .lia-autocomplete-container .collapse-results.fa-chevron-down + ul { max-height: 36px !important; overflow: hidden !important; }*/ .lia-search-input-message + .lia-autocomplete-container .lia-autocomplete-content { flex-direction: column; } } .lia-search-input-message + .lia-autocomplete-container .lia-autocomplete-content>ul>li { padding: 8px 15px 8px 15px; } /* default tag styles */ .SearchPage .search-external-link:after, .is--tag { background-color: var(--color-calypso-light); border: 1px solid transparent; border-radius: 2px; color: var(--color-link-hover); display: inline-block; font-size: 12px; font-weight: 600; line-height: 22px; padding: 0 8px; position: relative; vertical-align: baseline; } .SearchPage .search-external-link:after { line-height: 16px; margin-left: 6px; } /* Override styles form the native Khoros skin... */ .SearchPage .lia-tabs-standard .lia-tabs:first-child { padding-left: 0; } .SearchPage .lia-tabs-standard-wrapper>.lia-tabs-standard { padding: 0 15px !important; /* This one is especially stubborn for some reason I can't explain! */ } </style> <script> // glowingblue: really? xhr.open()? when 5 lines up you were aware you have jQuery? oh boy... function followunfollow(id,value,currentUser,top){ const xhttp = new XMLHttpRequest(); xhttp.onload = function() { if (value=='Unfollow') { document.getElementById("tunfollow-"+id+"").style.display = 'none'; document.getElementById("tfollow-"+id+"").style.display = 'flex'; } if (value=='follow') { document.getElementById("tunfollow-"+id+"").style.display = 'flex'; document.getElementById("tfollow-"+id+"").style.display = 'none'; } } xhttp.open("GET", "/plugins/custom/hubspot/hubspot/follow-unfollow-hover-card-button?id="+id+"&val="+value+"¤tUser="+currentUser+"",true);xhttp.send(); } </script> <div class="MinimumWidthContainer"> <div class="min-width-wrapper"> <div class="min-width"> <div class="lia-content"> <div class="lia-browser-support-alert"> <div class="lia-browser-support-alert-text"> Ya no admitimos Internet Explorer 10 ni versiones anteriores. O puede que tengas activada la vista de compatibilidad. Desactiva la vista de compatibilidad, actualiza a una versión más reciente o usa otro navegador. </div> <div class="lia-browser-support-alert-close"> <a class="lia-link-navigation lia-link-ticket-post-action" data-lia-action-token="JuGoXNSNj5xjs3-e8ZE0VDQerXV-V2hQuUx4UQsgeMs." rel="nofollow" id="dismissAlert" href="https://community.hubspot.com/t5/community/page.liabase.basebody.browsersupportalert.dismissalert:dismissalert?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw.."><span class="lia-img-close-small lia-fa-close lia-fa-small lia-fa" title="Descartar esta alerta" alt="Descartar esta alerta" aria-label="Descartar esta alerta" role="img" id="display"></span></a> </div> </div> <div class="lia-quilt lia-quilt-community-page-v2 lia-quilt-layout-one-column lia-top-quilt"> <div class="lia-quilt-row lia-quilt-row-header"> <div class="lia-quilt-column lia-quilt-column-24 lia-quilt-column-single lia-quilt-column-common-header"> <div class="lia-quilt-column-alley lia-quilt-column-alley-single"> <div class="lia-quilt lia-quilt-header lia-quilt-layout-one-column lia-component-quilt-header"> <div class="lia-quilt-row lia-quilt-row-header"> <div class="lia-quilt-column lia-quilt-column-24 lia-quilt-column-single lia-quilt-column-common-header"> <div class="lia-quilt-column-alley lia-quilt-column-alley-single"> <!-- hs.custom.responsive-header --> <style> #lia-body .mobile-header .navbar .menu .menu-item.active.has-collapsible .menu-child{ display: flex; flex-direction: column; } .jp-resources-list{ display:flex; flex-direction:column; } .jp-resources-list>li.menu-child-item.jp-class-HubSpot.Community.Blog{ order:1; } .header-dropdown-menu .lia-header-nav-component-widget .private-notes-link:before { content: "Mensajes Privados"; } #lia-body .mobile-header .navbar .menu-wrapper.offcanvas::before {width: 0px;} .profile-menu-dropdown{display: none !important;} .pagination-recent-post.pagination a#jp-previous:after { content: "Anterior"; } .pagination-recent-post.pagination a#jp-next:before { content: "Siguiente"; } #lia-body .MessageView.lia-message-view-idea-message-item .lia-quilt-idea-message-item .lia-message-footer-action .lia-link-navigation.lia-message-comment-post:after { content: "0 Comentario"; } </style> <div class="header mobile-header"> <nav class="navbar"> <span class="open-menu"> <img src="https://community.hubspot.com/html/@3A38E73C772F7CCD402C2EC02A244F14/assets/Hamburger-Nav.svg"> </span> <span class="hubspot-mobile-logo-wrapper"> <a href="/"> <img src="https://community.hubspot.com/html/@813D252A70F0A7024C8EA3BB1B8B9CFD/assets/sticky-logo.png"> </a> </span> <div class="menu-wrapper"> <div class="menu-block"> <span class="close-menu"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"> <path fill="#252a32" fill-rule="evenodd" d="M17.778.808l1.414 1.414L11.414 10l7.778 7.778-1.414 1.414L10 11.414l-7.778 7.778-1.414-1.414L8.586 10 .808 2.222 2.222.808 10 8.586 17.778.808z" /> </svg> </span> </div> <ul class="menu"> <li class="menu-item has-collapsible"> <a><span></span>Conversaciones</a> <ul class="menu-child"> <li class="menu-child-item"> <a href="/t5/Foro-de-CRM-y-Sales-Hub/ct-p/crm_sales_hub_es" class="nav-dropdown-link nav-discussions-crm"> CRM & Sales </a> </li> <li class="menu-child-item"> <a href="/t5/Foro-de-Marketing-Hub/ct-p/marketing_hub_es" class="nav-dropdown-link nav-discussions-mktg"> Marketing & Contenido </a> </li> <li class="menu-child-item"> <a href="/t5/Foro-de-Service-Hub/ct-p/service_hub_es" class="nav-dropdown-link nav-discussions-svc"> Éxito del cliente & Servicio al cliente </a> </li> <li class="menu-child-item"> <a href="/t5/Operaciones-y-gesti%C3%B3n-de/ct-p/operations_es" class="nav-dropdown-link nav-discussions-ops"> Operaciones y gestión de ingresos </a> </li> <li class="menu-child-item"> <a href="/t5/Commerce/ct-p/commerce" class="nav-dropdown-link nav-discussions-commerce in-english"> Commerce </a> </li> <li class="menu-child-item"> <a href="/t5/HubSpot-Developers/ct-p/developers" class="nav-dropdown-link nav-discussions-developers in-english"> Desarrolladores </a> </li> <li class="menu-child-item"> <a href="https://community.hubspot.com/t5/Getting-Started-on-the-Community/How-to-join-the-Solutions-Partner-Program/ba-p/400205" class="nav-dropdown-link nav-partners in-english"> Solutions Partner Program </a> </li> <li class="menu-child-item"> <a href="/t5/HubSpot-Ideas/idb-p/HubSpot_Ideas" class="nav-dropdown-link nav-discussions-ideas in-english"> Ideas </a> </li> </ul> </li> <li class="menu-item has-collapsible"> <a><span></span>Academy</a> <ul class="menu-child"> <li class="nav-dropdown-item"> <a href="https://academy.hubspot.com/es/courses?page=1" class="nav-dropdown-link nav-external-link" target="_blank"> Cursos </a> </li> <li class="nav-dropdown-item"> <a href="https://academy.hubspot.com/es/certification-overview" class="nav-dropdown-link nav-external-link" target="_blank"> Certificaciones </a> </li> <li class="nav-dropdown-item"> <a href="https://www.hubspot.es/academy/bootcamps/inicio?hubs_content=www.hubspot.com%2Facademy%2Fbootcamps%2Fhome&hubs_content-cta=cl-dropdown-menu-link&__hstc=20629287.dd61fd337366ed0846198065dee2bf43.1720706970340.1723038547450.1723051045741.66&__hssc=20629287.14.1723051045741&__hsfp=2390368378" class="nav-dropdown-link nav-external-link" target="_blank"> Cursos intensivos de HubSpot Academy </a> </li> <li class="nav-dropdown-item"> <a href="https://academy.hubspot.com/learning-paths" class="nav-dropdown-link nav-external-link in-english" target="_blank"> Rutas de aprendizaje </a> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/HubSpot-Academy-en-Espa%C3%B1ol/bd-p/academy_es" class="nav-dropdown-link"> Soporte HubSpot Academy </a> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/Grupos-de-estudio/bd-p/academy-education-study-group-es" class="nav-dropdown-link"> Grupos de estudio </a> </li> </ul> </li> <li class="menu-item has-collapsible"> <a><span></span>Recursos</a> <ul class="menu-child jp-resources-list"> <li class="menu-child-item "> <a href="/t5/Primeros-Pasos/ct-p/getting_started_es" class="nav-dropdown-link nav-discussions-gs"> Primeros Pasos </a> </li> <li class="nav-dropdown-item"> <a href="https://help.hubspot.com/es/" class="nav-dropdown-link nav-external-link" target="_blank"> Centro de ayuda de HubSpot </a> </li> <li class="nav-dropdown-item"> <a href="https://knowledge.hubspot.com/" class="nav-dropdown-link nav-external-link" target="_blank"> Base de conocimientos </a> </li> <li class="nav-dropdown-item"> <a href="https://developers.hubspot.es/beta-docs/reference/api/overview?__hstc=20629287.dd61fd337366ed0846198065dee2bf43.1720706970340.1723038547450.1723051045741.66&__hssc=20629287.43.1723051045741&__hsfp=2390368378&uuid=3bec601b-d3d6-456a-a114-baf48d4c4c02" class="nav-dropdown-link nav-external-link" target="_blank"> Documentación de referencia de la API </a> </li> <li class="nav-dropdown-item"> <a href="https://developers.hubspot.es/beta-docs/reference/cms?__hstc=20629287.dd61fd337366ed0846198065dee2bf43.1720706970340.1723038547450.1723051045741.66&__hssc=20629287.44.1723051045741&__hsfp=2390368378&uuid=46f4de7e-a9d2-4993-a0a7-1c45b8086d87" class="nav-dropdown-link nav-external-link" target="_blank"> Documentación de CMS </a> </li> <li class="menu-child-item "> <a href="/t5/Noticias-Networking-y-Eventos/ct-p/community_news_announcement_es" class="nav-dropdown-link nav-news"> Noticias </a> </li> <li class="menu-child-item "> <a href="/t5/Resources/ct-p/resources?node_id=webinars&order_by=last_updated" class="nav-dropdown-link nav-resource-blog-Webinars in-english"> Seminarios web </a> </li> <li class="menu-child-item "> <a href="/t5/Novedades-sobre-la-herramienta/bg-p/product_updates_es" class="nav-dropdown-link nav-resource-blog-Releases and Updates "> Lanzamientos y actualizaciones </a> </li> <li class="menu-child-item "> <a href="/t5/Resources/ct-p/resources?node_id=resources" class="nav-dropdown-link nav-resource-blog-HubSpot Community Blog in-english "> Blog de la comunidad </a> </li> <li class="menu-child-item "> <a href="/t5/Resources/ct-p/resources?node_id=workflows_library" class="nav-dropdown-link nav-resource-blog-Workflows Library "> Biblioteca de Workflows </a> </li> <li class="menu-child-item "> <a href="/t5/Resources/ct-p/resources?node_id=ai-library" class="nav-dropdown-link nav-resource-blog-Breeze Library "> Breeze Library </a> </li> </ul> </li> <li class="menu-item has-collapsible"> <a href="#"><span></span>Eventos</a> <ul class="menu-child"> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/Ask-Me-Anything-and-Panel/bd-p/ama_discussions" class="nav-dropdown-link in-english"> Preguntas y respuestas </a> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/Community-Led-Events/bd-p/adapt" class="nav-dropdown-link in-english"> Eventos organizados por la Comunidad </a> </li> <li class="nav-dropdown-item"> <a href="https://www.hubspot.com/resources/webinar" class="nav-dropdown-link nav-external-link in-english" target="_blank"> Webinars </a> </li> <li class="nav-dropdown-item"> <a href="https://www.hubspot.com/hubspot-user-groups" class="nav-dropdown-link nav-external-link in-english" target="_blank"> HUGS </a> </li> </ul> </li> <li class="menu-item has-collapsible"> <a><span></span>Advocacy</a> <ul class="menu-child"> <li class="menu-child-item"> <a href='/t5/Advocacy/ct-p/advocacy' class="nav-dropdown-link nav-hubFans-program in-english"> Programa de Champions de la Comunidad </a> </li> <li class="menu-child-item"> <a href="/t5/Advocates-Blog/bg-p/advocates-blog" class="nav-dropdown-link nav-adovcates-blog in-english"> Blog de Champions </a> </li> </ul> </li> </ul> <!-- --> <div class="lang-picker-wrapper"> <div class="lang-picker-container"> <a id="current-language" class="current-language"> <span class="lang-picker-globe-icon"></span> Español </a> <div id="lang-picker-global" class="nav-popover lang-picker"> <div class="nav-popover-arrow" style="border-top-color: transparent; border-left-color: transparent; width: 20px; height: 20px; transform: rotate(-135deg); top: -10px; right: calc(50% - 48px);"></div> <ul id="lang-picker-dropdown" class="nav-dropdown-list"> <a href="https://community.hubspot.com/?profile.language=en" class="nav-dropdown-link" data-lang="en"> <li class="nav-dropdown-item"> English </li> </a> <a href="https://community.hubspot.com/?profile.language=es" class="nav-dropdown-link" data-lang="es"> <li class="nav-dropdown-item"> Español </li> </a> <a href="https://community.hubspot.com/?profile.language=pt-br" class="nav-dropdown-link" data-lang="pt-br"> <li class="nav-dropdown-item"> Português </li> </a> <a href="https://community.hubspot.com/?profile.language=fr" class="nav-dropdown-link" data-lang="fr"> <li class="nav-dropdown-item"> Français </li> </a> <a href="https://community.hubspot.com/?profile.language=de" class="nav-dropdown-link" data-lang="de"> <li class="nav-dropdown-item"> Deutsch </li> </a> <a href="https://community.hubspot.com/?profile.language=ja" class="nav-dropdown-link" data-lang="ja"> <li class="nav-dropdown-item"> 日本語 </li> </a> </ul> </div> </div></div> </div> <div class="header-right-col"> <div class="search_icon" onclick="myFunction()"> <img src="/html/assets/search-icon-grey.svg?version=preview" alt=""> </div> <div class="wrapper-search" style="display:none"> <div id='lia-searchformV32_24bce4066ce448' class='SearchForm lia-search-form-wrapper lia-mode-default lia-component-common-widget-search-form'> <div class='lia-inline-ajax-feedback'> <div class='AjaxFeedback' id='ajaxfeedback_24bce4066ce448'></div> </div> <div id='searchautocompletetoggle_24bce4066ce448'> <div class='lia-inline-ajax-feedback'> <div class='AjaxFeedback' id='ajaxfeedback_24bce4066ce448_0'></div> </div> <form enctype='multipart/form-data' class='lia-form lia-form-inline SearchForm' action='https://community.hubspot.com/t5/community/page.searchformv32.form.form' method='post' id='form_24bce4066ce448' name='form_24bce4066ce448'><div class='t-invisible'><input value='q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..' name='t:ac' type='hidden'></input><input value='search/contributions/page' name='t:cp' type='hidden'></input><input value='8v6hueWKJ-eEBlDa6GlxFX3xzOY_F6y_oy_FKJuEU3nobM4-rFHBTVEnL3zgmJrXJ8teafUgHVr5K3YKwx8S3S6FiLMD-5stVe4bi5jL1BXYCxbBG8JifvBBGpvFdNukNxdBlZijyOcqt9PKH1XpEPSFYUhPdIwq-PIgoEm7dwqquZ--2ZRwLqECUwAdwEBNUM-6ErnMe0LWVqf_6Huz1keMiYkqxp49L8Iab7r8l4t2cv256-U8z4xndHEpYUragu7Oe9QZZRymT9jqyyrObDJ62YbCUcHdaTUtnF5Gk6d0sq6Et7xtQwwVKJjBmpoXGOeIocdcDoA6fHQzQHdHWSnYDP0FwM7gZPtfWYUDo328jlmWsk9CB3ZDA1UB3W3KRhUxXkLtICVAGgBhg8QN7mNcO01NjnGu4e9I3-eJNsMvPSSMUdiaM78upx0YV46UHCch7EQXvlGH70nyFZKESomj_HGxg-2_hg9Usnf1inlf0Gr21zjHscYlg2aR4O-ZRqvOkrNtXr7b_aA4UBsjm7AXSDVq-ipLyOEtbJo9FAU2FCYDGyhfpmkAC75p_4vrIozzEjHFZAF7wBgh7_aTql7PoluU7aabkJHZQVLcxwUhyS2fLyaTJ5kPDyK4RsRh57g00oM5CD3H1_qsvtjfCNy0bKPWw_ZPyx9xrFgkE1q7Ch3nU7mA9ZL8zQ2Abnglc2JfPer-DUnrfDmSvk1PoYpJuB6flXQqDMoZ5VosXwml2oRPcKm8HNoaJNpmOP0aJzI8BwRrnD5oMdR0k-JCuEw8-MtsShI_NbIFpG8dMLKFvWdI7xaMeFH76dpaGPMnwtTcoXe_-7vLr6qZPzf0NwFESLR7wHffZQIncwJXJIpt0oFwFvH9ZpS3ptn6uvdQJohzlXRAR6x7XE_zxKP2rh09fqhiQ8JQw8QqJi1_n4AIc07pK4jcKWv8KbU05UprhoeM07AOl_5zOT1Z44mOW0iO1piCu1WL0mK4Cd79YLVYarXixoRrnZA7bDA1ovLj265lqwAAe3tS2GhhPQeaHO56k_NF6mBWBnwj6btAZM746qIFY1gbM-xWdMPFFeCVB0EIywCVvHYplGKped8HkE44fYQfhBHoUA2vP2kDeAgsH5WehDTg_O0IHJZ_cKFGeLi-IJosTdqesriEuD0D92a_BqMSuWbBls8C6uqaj4Y.' name='lia-form-context' type='hidden'></input><input value='CommunityPage::searchformv32.form:' name='liaFormContentKey' type='hidden'></input><input value='yDZKQFNI0U/sd9X4pbUemqvQQZw=:H4sIAAAAAAAAALWSzUrDQBSFr4Wuigiib6DbiajdqAhFUISqweBaZibTNJpk4sxNEzc+ik8gvkQX7nwHH8CtKxfmzxJbwaTUVZhzw/nOmblP79COD+FAC6r40OAyQOWyCF0ZaMOkjtgrJgOp/NHONtER810sP9nfIkGtoCuVQ2hI+VAQpKHQqO67hEslPJcRRrUgPZaKlOOxKzx7wxIYhZtX487b+stnC5b60MnZ0junvkBY7d/QETU8GjiGlUYKnP0kRFguwEcFeAHBe02Dm0pyobWV+Wid0sbP9u7g4/G1BZCE8QWc1U3kpzapWoqZ+S+SvoMHgPQ+ypGVj/IoC2dlqHZ8CWZdV7xljUqszZa43voPYNHkFE7qGkdaqKrl1Pm7wEqmV59gcYjGkQOJP25h6jyJnOlzRv4DUURusIWhknbEsWo5K002vhzNufG1WHmDLwdzh8gDBQAA' name='t:formdata' type='hidden'></input></div> <div class='lia-inline-ajax-feedback'> <div class='AjaxFeedback' id='feedback_24bce4066ce448'></div> </div> <input value='K3tMFjBaR4QMZNUxUbfu_gOrauzpK3D-wY_C8k2h2Gw.' name='lia-action-token' type='hidden'></input> <input value='form_24bce4066ce448' id='form_UIDform_24bce4066ce448' name='form_UID' type='hidden'></input> <input value='' id='form_instance_keyform_24bce4066ce448' name='form_instance_key' type='hidden'></input> <span class='lia-search-input-wrapper'> <span class='lia-search-input-field'> <span class='lia-button-wrapper lia-button-wrapper-secondary lia-button-wrapper-searchForm-action'><input value='searchForm' name='submitContextX' type='hidden'></input><input class='lia-button lia-button-secondary lia-button-searchForm-action' value='Buscar' id='submitContext_24bce4066ce448' name='submitContext' type='submit'></input></span> <input placeholder='Buscar en la Comunidad' aria-label='Buscar' title='Buscar' class='lia-form-type-text lia-autocomplete-input search-input lia-search-input-message' value='' id='messageSearchField_24bce4066ce448_0' name='messageSearchField' type='text'></input> <input placeholder='Buscar en la Comunidad' aria-label='Buscar' title='Buscar' class='lia-form-type-text lia-autocomplete-input search-input lia-search-input-tkb-article lia-js-hidden' value='' id='messageSearchField_24bce4066ce448_1' name='messageSearchField_0' type='text'></input> <input ng-non-bindable='' title='Especifique un nombre de usuario o clasificación' class='lia-form-type-text UserSearchField lia-search-input-user search-input lia-js-hidden lia-autocomplete-input' aria-label='Especifique un nombre de usuario o clasificación' value='' id='userSearchField_24bce4066ce448' name='userSearchField' type='text'></input> <input placeholder='Enter a keyword to search within the private messages' title='Especifique una palabra de búsqueda' class='lia-form-type-text NoteSearchField lia-search-input-note search-input lia-js-hidden lia-autocomplete-input' aria-label='Especifique una palabra de búsqueda' value='' id='noteSearchField_24bce4066ce448_0' name='noteSearchField' type='text'></input> <input title='Especifique una palabra de búsqueda' class='lia-form-type-text ProductSearchField lia-search-input-product search-input lia-js-hidden lia-autocomplete-input' aria-label='Especifique una palabra de búsqueda' value='' id='productSearchField_24bce4066ce448' name='productSearchField' type='text'></input> <input class='lia-as-search-action-id' name='as-search-action-id' type='hidden'></input> </span> </span> <span class='lia-cancel-search'>cancelar</span> </form> <div class='search-autocomplete-toggle-link lia-js-hidden'> <span> <a class='lia-link-navigation auto-complete-toggle-on lia-link-ticket-post-action lia-component-search-action-enable-auto-complete' data-lia-action-token='cXtysxGDKavvwb_2FaPMTfRbfbobh2NyuBj9OHev3Lk.' rel='nofollow' id='enableAutoComplete_24bce4066ce448' href='https://community.hubspot.com/t5/community/page.enableautocomplete:enableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions'>Activar sugerencias</a> <span class='HelpIcon'> <a class='lia-link-navigation help-icon lia-tooltip-trigger' role='button' aria-label='Icono de ayuda' id='link_24bce4066ce448' href='#'><span class='lia-img-icon-help lia-fa-icon lia-fa-help lia-fa' alt='La sugerencia automática le ayuda a obtener, de forma rápida, resultados precisos de su búsqueda al sugerirle posibles coincidencias mientras escribe.' aria-label='Icono de ayuda' role='img' id='display_24bce4066ce448'></span></a><div role='alertdialog' class='lia-content lia-tooltip-pos-bottom-left lia-panel-tooltip-wrapper' id='link_24bce4066ce448_0-tooltip-element'><div class='lia-tooltip-arrow'></div><div class='lia-panel-tooltip'><div class='content'>La sugerencia automática le ayuda a obtener, de forma rápida, resultados precisos de su búsqueda al sugerirle posibles coincidencias mientras escribe.</div></div></div> </span> </span> </div> </div> <div class='spell-check-showing-result'> Mostrando los resultados de <span class='lia-link-navigation show-results-for-link lia-link-disabled' aria-disabled='true' id='showingResult_24bce4066ce448'></span> </div> <div> <span class='spell-check-search-instead'> Buscar en lugar de <a class='lia-link-navigation search-instead-for-link' rel='nofollow' id='searchInstead_24bce4066ce448' href='#'></a> </span> </div> <div class='spell-check-do-you-mean lia-component-search-widget-spellcheck'> Quiere decir: <a class='lia-link-navigation do-you-mean-link' rel='nofollow' id='doYouMean_24bce4066ce448' href='#'></a> </div> </div> </div> <script> function myFunction() { var x = document.getElementsByClassName("wrapper-search")[0]; if (x.style.display === "none") { x.style.display = "block"; } else { x.style.display = "none"; } } </script><div class="search-icon-plus-top"> <button class="lia-button search-toggle-action-icon-plus"><img src='https://community.hubspot.com/html/@5320E40129AA1377479EABCA2009B53A/assets/Start-dicsucssion.svg' alt=""><i class="lia-fa lia-fa-caret-down"></i></button> <div class="plus-bar-main-content" style="display: none;"> <ul id="plus-bar-top-main"> <li class="plus-bar"> <a href="https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2Ft5%2Fforums%2Fpostpage%2Fcategory-id%2Fhubspot_community_es%2Fchoose-node%2Ftrue" class="white-btn transpaent"><i><img src="https://community.hubspot.com/html/@38F5B2AB35958F39F47C2BFFE5486135/assets/Edit.svg"></i> Crea una publicación</a> </li> <li class="plus-bar"><a href="https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2Ft5%2Fforums%2Fpostpage%2Fboard-id%2FHubSpot_Ideas"><i><img src="https://community.hubspot.com/html/@C71A42AEB76B8A3A82335DA9F5B9C717/assets/lightbulb.svg"></i> Añade una idea</a></li> </ul> </div> </div> <div class="login-container"> <a class='lia-link-navigation login-link lia-authentication-link lia-component-users-action-login' rel='nofollow' id='loginPageV2_24bce40bce36f2' href='https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2F%3Fprofile.language%3Des'>Iniciar Sesión</a> </div> </div> </nav> </div> <script> const openMenu = document.querySelector(".open-menu"); const closeMenu = document.querySelector(".close-menu"); const menuWrapper = document.querySelector(".menu-wrapper"); const hasCollapsible = document.querySelectorAll(".has-collapsible"); // Sidenav Toggle openMenu.addEventListener("click", function () { menuWrapper.classList.add("offcanvas"); }); closeMenu.addEventListener("click", function () { menuWrapper.classList.remove("offcanvas"); }); // Collapsible Menu hasCollapsible.forEach(function (collapsible) { collapsible.addEventListener("click", function () { collapsible.classList.toggle("active"); // Close Other Collapsible hasCollapsible.forEach(function (otherCollapsible) { if (otherCollapsible !== collapsible) { otherCollapsible.classList.remove("active"); } }); }); }); </script> </div> </div> </div><div class="lia-quilt-row lia-quilt-row-main"> <div class="lia-quilt-column lia-quilt-column-24 lia-quilt-column-single lia-quilt-column-main-content"> <div class="lia-quilt-column-alley lia-quilt-column-alley-single"> <script> // Inline click listeners function getHubSpotClickListener(btnId) { if(btnId == "get-hubspot-free-v2"){ if (document.getElementById('get-hubspot-v2')) { document.getElementById('get-hubspot-v2').classList.toggle("show"); } } } function langPickerClickListener() { if (document.getElementById('lang-picker-global')) { document.getElementById('lang-picker-global').classList.toggle("show"); } } </script> <style> /* Text customization for CSS generated content */ .lia-list-row-thread-solved:after { content: "Resuelta"!important; text-transform: uppercase; } .SearchPage .lia-replies-toggle-link:before { content: "Respuestas"!important; } label.lia-form-label:after { // content: "(Obligatorio)"; margin-left: 4px; } .lia-form-board-entry label.lia-form-label:after, .lia-form-subject-entry label.lia-form-label:after, .lia-form-body-entry label.lia-form-label:after, .lia-form-labels-entry label.lia-form-label:after { content: "(Obligatorio)"; } .lia-form-login-entry .lia-form-input-wrapper:before { content: "Nombre de usuario*"!important; } .lia-form-profile-first-name-entry:before { content: "Nombre*"!important; } .lia-form-profile-last-name-entry:before { content: "Apellido*"!important; } .lia-note-unread:after { content: "No leído"; text-transform: uppercase; } .EditPage label.lia-form-label:after, .EditPage .lia-form-label.lia-fieldset-title:after, .EditPage .lia-component-tkb-article-editor-form .lia-form-label.lia-form-compare-title:after, .lia-component-tkb-article-editor-form .EditPage .lia-form-label.lia-form-compare-title:after, .EditPage .lia-component-tkb-article-editor-form .lia-form-label.lia-revision-info-title:after, .lia-component-tkb-article-editor-form .EditPage .lia-form-label.lia-revision-info-title:after, .EditPage .lia-component-tkb-article-editor-form .lia-form-label.lia-related-messages-title:after, .lia-component-tkb-article-editor-form .EditPage .lia-form-label.lia-related-messages-title:after, .ReplyPage label.lia-form-label:after, .ReplyPage .lia-form-label.lia-fieldset-title:after, .ReplyPage .lia-component-tkb-article-editor-form .lia-form-label.lia-form-compare-title:after, .lia-component-tkb-article-editor-form .ReplyPage .lia-form-label.lia-form-compare-title:after, .ReplyPage .lia-component-tkb-article-editor-form .lia-form-label.lia-revision-info-title:after, .lia-component-tkb-article-editor-form .ReplyPage .lia-form-label.lia-revision-info-title:after, .ReplyPage .lia-component-tkb-article-editor-form .lia-form-label.lia-related-messages-title:after, .lia-component-tkb-article-editor-form .ReplyPage .lia-form-label.lia-related-messages-title:after, .PostPage label.lia-form-label:after, .PostPage .lia-form-label.lia-fieldset-title:after, .PostPage .lia-component-tkb-article-editor-form .lia-form-label.lia-form-compare-title:after, .lia-component-tkb-article-editor-form .PostPage .lia-form-label.lia-form-compare-title:after, .PostPage .lia-component-tkb-article-editor-form .lia-form-label.lia-revision-info-title:after, .lia-component-tkb-article-editor-form .PostPage .lia-form-label.lia-revision-info-title:after, .PostPage .lia-component-tkb-article-editor-form .lia-form-label.lia-related-messages-title:after, .lia-component-tkb-article-editor-form .PostPage .lia-form-label.lia-related-messages-title:after, .MyProfilePage label.lia-form-label:after, .MyProfilePage .lia-form-label.lia-fieldset-title:after, .MyProfilePage .lia-component-tkb-article-editor-form .lia-form-label.lia-form-compare-title:after, .lia-component-tkb-article-editor-form .MyProfilePage .lia-form-label.lia-form-compare-title:after, .MyProfilePage .lia-component-tkb-article-editor-form .lia-form-label.lia-revision-info-title:after, .lia-component-tkb-article-editor-form .MyProfilePage .lia-form-label.lia-revision-info-title:after, .MyProfilePage .lia-component-tkb-article-editor-form .lia-form-label.lia-related-messages-title:after, .lia-component-tkb-article-editor-form .MyProfilePage .lia-form-label.lia-related-messages-title:after, .KudosMessagePage label.lia-form-label:after, .KudosMessagePage .lia-form-label.lia-fieldset-title:after, .KudosMessagePage .lia-component-tkb-article-editor-form .lia-form-label.lia-form-compare-title:after, .lia-component-tkb-article-editor-form .KudosMessagePage .lia-form-label.lia-form-compare-title:after, .KudosMessagePage .lia-component-tkb-article-editor-form .lia-form-label.lia-revision-info-title:after, .lia-component-tkb-article-editor-form .KudosMessagePage .lia-form-label.lia-revision-info-title:after, .KudosMessagePage .lia-component-tkb-article-editor-form .lia-form-label.lia-related-messages-title:after, .lia-component-tkb-article-editor-form .KudosMessagePage .lia-form-label.lia-related-messages-title:after { // content: "(Obligatorio)"; } .ForumPage span.in-english:after, .CategoryPage span.in-english:after { content: "EN"; } a.in-english:after { content: "EN"; } .nav-menu a.in-english:after { content: "EN"; } .header-search-wrapper{margin-right:5px;margin-top: 33px;} #lia-body .nav-wrapper .header-search-wrapper .lia-search-form-wrapper{position: relative;left: 0px;border:none;box-shadow:none;max-width: 460px;width: 100%;} #lia-body .nav-wrapper .header-search-wrapper .lia-button-searchForm-action{top:8px !important;position: absolute;right: 6px;min-width: auto !important; background-color: transparent !important;border: none !important;max-height: 18px !important; background-size:contain !important;background-image: url(/html/assets/search-icon.svg)} #lia-body .nav-wrapper .header-search-wrapper .search-input::-webkit-input-placeholder{font-size: 16px !important;} #lia-body .nav-wrapper .header-search-wrapper .search-input{height: 32px !important;padding: 10px !important;padding-right: 50px !important;border: 1px solid #CBD6E2 !important;box-shadow: none !important;background-color: white !important;font-size: 16px !important; border-radius: 3px !important;color: #33475B !important;line-height:24px !important;} #lia-body .header-search-wrapper .lia-search-input-wrapper {width: 460px !important;} #lia-body .nav-wrapper .header-search-wrapper .lia-search-input-wrapper input:focus {box-shadow: 0 0 4px 1px rgb(255 255 255 / 30%), 0 0 0 1px #fff!important;} .header-search-wrapper .lia-search-granularity-wrapper .lia-search-form-granularity{display:none !important;} .header-search-wrapper .lia-search-granularity-wrapper:before{display:none !important;} @media only screen and (max-width: 992px) { #lia-body .nav-wrapper .header-search-wrapper .lia-search-form-wrapper{z-index: 1;} } @media only screen and (max-width: 767px) { .user-nav-bar{ position: relative; height: 100%; } #lia-body .header-search-wrapper .lia-search-input-wrapper{ width: 100% !important; max-width: none;} #lia-body .nav-wrapper .header-search-wrapper .lia-search-form-wrapper{padding: 10px 24px !important; background: #fff;border: 1px solid #eee2e2;margin-left: 4px;max-width:none !important;width: 100%;} #lia-body .nav-wrapper .header-search-wrapper .lia-button-searchForm-action {right:20px;top:17px !important;} .header-search-wrapper{display:none; position: absolute; top: 121px; width: 100% !important;} #lia-body .nav-wrapper .header-search-wrapper .lia-search-input-message{ margin-right:-7px;} #lia-body .nav-wrapper .header-search-wrapper .lia-search-form-wrapper::before{position: absolute; top: -6px;content: "";right: 67px;width: 10px;height: 10px;background-color: white;transform: rotate(45deg);border-top: 1px solid #eee2e2; border-left: 1px solid #eee2e2;} } </style> <section class="community-header-nav v2"> <div class="nav-wrapper"> <div class="user-nav-bar"> <nav class="nav-menu template-centered template-section"> <!-- --> <div class="lang-picker-wrapper"> <div class="lang-picker-container"> <a id="current-language" class="current-language"> <span class="lang-picker-globe-icon"></span> Español </a> <div id="lang-picker-global" class="nav-popover lang-picker"> <div class="nav-popover-arrow" style="border-top-color: transparent; border-left-color: transparent; width: 20px; height: 20px; transform: rotate(-135deg); top: -10px; right: calc(50% - 48px);"></div> <ul id="lang-picker-dropdown" class="nav-dropdown-list"> <a href="https://community.hubspot.com/?profile.language=en" class="nav-dropdown-link" data-lang="en"> <li class="nav-dropdown-item"> English </li> </a> <a href="https://community.hubspot.com/?profile.language=es" class="nav-dropdown-link" data-lang="es"> <li class="nav-dropdown-item"> Español </li> </a> <a href="https://community.hubspot.com/?profile.language=pt-br" class="nav-dropdown-link" data-lang="pt-br"> <li class="nav-dropdown-item"> Português </li> </a> <a href="https://community.hubspot.com/?profile.language=fr" class="nav-dropdown-link" data-lang="fr"> <li class="nav-dropdown-item"> Français </li> </a> <a href="https://community.hubspot.com/?profile.language=de" class="nav-dropdown-link" data-lang="de"> <li class="nav-dropdown-item"> Deutsch </li> </a> <a href="https://community.hubspot.com/?profile.language=ja" class="nav-dropdown-link" data-lang="ja"> <li class="nav-dropdown-item"> 日本語 </li> </a> </ul> </div> </div></div> <div class="header-search-wrapper"> <div id='lia-searchformV32_24bce40c10967f' class='SearchForm lia-search-form-wrapper lia-mode-default lia-component-common-widget-search-form'> <div class='lia-inline-ajax-feedback'> <div class='AjaxFeedback' id='ajaxfeedback_24bce40c10967f'></div> </div> <div id='searchautocompletetoggle_24bce40c10967f'> <div class='lia-inline-ajax-feedback'> <div class='AjaxFeedback' id='ajaxfeedback_24bce40c10967f_0'></div> </div> <form enctype='multipart/form-data' class='lia-form lia-form-inline SearchForm' action='https://community.hubspot.com/t5/community/page.searchformv32.form.form' method='post' id='form_24bce40c10967f' name='form_24bce40c10967f'><div class='t-invisible'><input value='q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..' name='t:ac' type='hidden'></input><input value='search/contributions/page' name='t:cp' type='hidden'></input><input value='H2ECDKVK0kPMDuOSHMWD17TevY6BV_HoFnob7X5f1hq0ec3sMIuojQFBi7FjWGvOAe6xq7NZHzpIlMGRuxV0x877TWeTxa1fH6uHccE6YHWbw_3ajhPLTZwal20efyjh_NgdeROvka0H-nyahAdEnVqn4wY3M9GHqDBLCttnK1UfAbwgiTbf_XoQao_k7i6wFZSYqpCdYsafZZipYSUrJNmHk9PbV9CfYFmL5nkzpw29uilAkTI6YeiX5kFZgw6-kj2AuwHXcpmYrDghE8_ml7elnel_zih9NFYf07ZatGd62imulEZYi5VOX45H6FmRXrDr7-V0eyVPV1-7o6ryC0JJLW6UEE0CvjCpSiIu2o_2c6l1tEqy3j57ddCUlPBLcI7Y4DbGDfFPfa_Or-pqKMVp3bMz3WG59BKcuSMhjvBMLZ8D0A7PIgJzUjCvpZE0dLYm1lqHtc2MhHz_LOH_udezf5HQk51ITlUTK_2GZ4qEEmFhBxlylK7lLhpA7JIW4wffkoUwhdGBqKUjTWlXpNeBeMW62RObpPDnPzvF3U892bhnIhUOg3RuOGAvP63CctVezn4_TwXQGZFAiWqnEF4cWyFJ929eWRAeIL_A2ANGAMbmaJoi2fk3Tiei2AvrsJX1kqfrlngDn71gLWQHtWS3ZrCZmS4Pik63EU2CsNSsUnDkdw6uOzc6bn9LnOBtvidLrbwIK97aixTt3uDMwJEVL_4aH85Tg0Lg1RvhoTghd5Tg_u3-yefK9Lk2Wdivc7Bzc08F9wov-yivAQk2wZ8EV7rQjcgg67Lr6JJ8GYaCO8nX6iRpLfCOhHNCcRDlkJ9n_-snjIWN-aF3DIuB8Qi7nvYuesg_nkJ04AcmrWRC6dWhdPKKbYf9gmXkxpAHQkoJpr4nind-kwCMGsszycc_qtMNfFuokXd4aLy5Bbq3k70NOnqUOBjbyQZfuYMx4JZwHZj1bfoEdrLjNNvG7VSXXRsl0hZ9l69BSJ3Umoygd74jTvhYbDglPR__2H_r7ToLcaisFK_OzK0j7YQCyb4kDMoLicy-Yqc6aAOMlPizVom-atfGQDDilOx6rh6aybtXUPCb6qkDWSM9U5yB0t0bW6tGTbQ3eHOGlyG9hBezhgPuSEqcxkMJSIhIUmUrBUFCHi6lPsUNVajtuuEFgeUTom3VnTaxaEQyWwvkiX6nbqr97vBLzdMpktIgtsdhPxb7-xD1ixnJS5WdwLE0VRo3lSbSkmb6bSfPiLcLyNc.' name='lia-form-context' type='hidden'></input><input value='CommunityPage::searchformv32.form:' name='liaFormContentKey' type='hidden'></input><input value='5DI9GWMef1Esyz275vuiiOExwpQ=:H4sIAAAAAAAAALVSTU7CQBR+krAixkj0BrptjcpCMSbERGKCSmxcm+kwlGrbqTOvFDYexRMYL8HCnXfwAG5dubDtFKxgYgu4mrzvm3w/M+/pHcphHQ4kI4L2dMo9FLYZoM09qbeJxQ4V0+XC7e/tamqyBPEChwgbh1JAjQtLIz6hPaYh8ZlEMaxplAvm2KZmEsm0hhmBhOKpzZzOlsEw8LevR5W3zZfPEqy0oJIYc+eCuAyh2rolfaI7xLN0I8rjWfWBj7CuzJvf5osmbxRN3hacMimNwHRtKSOr0XNnv/vx+FoCGPjhMRzljhNLYHrEt9kA5T08ACCsKvREoYuqxqLl8BLO84q4UcMITcG49y/QOGs1pYyESl5p6V6qwRW086rinVmoxMZsiZud/zBUTc6gmVc4kExkJafmcYG1GM9+wfIsCkf2OP54hal5EjnG54z8h0XhjfcF7wQUs5Kz0GTjU2rOjc/llTT4Au07pDOcBQAA' name='t:formdata' type='hidden'></input></div> <div class='lia-inline-ajax-feedback'> <div class='AjaxFeedback' id='feedback_24bce40c10967f'></div> </div> <input value='rWDDOFFBo9caRHbDvTvtrAKYfVcxAQ8BcTiSAR56NUM.' name='lia-action-token' type='hidden'></input> <input value='form_24bce40c10967f' id='form_UIDform_24bce40c10967f' name='form_UID' type='hidden'></input> <input value='' id='form_instance_keyform_24bce40c10967f' name='form_instance_key' type='hidden'></input> <span class='lia-search-granularity-wrapper'> <select title='Buscar granularidad' class='lia-search-form-granularity search-granularity' aria-label='Buscar granularidad' id='searchGranularity_24bce40c10967f' name='searchGranularity'><option title='Todos los resultados' selected='selected' value='mjmao93648|community'>Todos los resultados</option><option title='Usuarios' value='user|user'>Usuarios</option></select> </span> <span class='lia-search-input-wrapper'> <span class='lia-search-input-field'> <span class='lia-button-wrapper lia-button-wrapper-secondary lia-button-wrapper-searchForm-action'><input value='searchForm' name='submitContextX' type='hidden'></input><input class='lia-button lia-button-secondary lia-button-searchForm-action' value='Buscar' id='submitContext_24bce40c10967f' name='submitContext' type='submit'></input></span> <input placeholder='Buscar en la Comunidad' aria-label='Buscar' title='Buscar' class='lia-form-type-text lia-autocomplete-input search-input lia-search-input-message' value='' id='messageSearchField_24bce40c10967f_0' name='messageSearchField' type='text'></input> <input placeholder='Buscar en la Comunidad' aria-label='Buscar' title='Buscar' class='lia-form-type-text lia-autocomplete-input search-input lia-search-input-tkb-article lia-js-hidden' value='' id='messageSearchField_24bce40c10967f_1' name='messageSearchField_0' type='text'></input> <input ng-non-bindable='' title='Especifique un nombre de usuario o clasificación' class='lia-form-type-text UserSearchField lia-search-input-user search-input lia-js-hidden lia-autocomplete-input' aria-label='Especifique un nombre de usuario o clasificación' value='' id='userSearchField_24bce40c10967f' name='userSearchField' type='text'></input> <input placeholder='Enter a keyword to search within the private messages' title='Especifique una palabra de búsqueda' class='lia-form-type-text NoteSearchField lia-search-input-note search-input lia-js-hidden lia-autocomplete-input' aria-label='Especifique una palabra de búsqueda' value='' id='noteSearchField_24bce40c10967f_0' name='noteSearchField' type='text'></input> <input title='Especifique una palabra de búsqueda' class='lia-form-type-text ProductSearchField lia-search-input-product search-input lia-js-hidden lia-autocomplete-input' aria-label='Especifique una palabra de búsqueda' value='' id='productSearchField_24bce40c10967f' name='productSearchField' type='text'></input> <input class='lia-as-search-action-id' name='as-search-action-id' type='hidden'></input> </span> </span> <span class='lia-cancel-search'>cancelar</span> </form> <div class='search-autocomplete-toggle-link lia-js-hidden'> <span> <a class='lia-link-navigation auto-complete-toggle-on lia-link-ticket-post-action lia-component-search-action-enable-auto-complete' data-lia-action-token='xrvTWtsj8SFOeMEBt94ugozbgyBf60hm-WRCzpGHdtY.' rel='nofollow' id='enableAutoComplete_24bce40c10967f' href='https://community.hubspot.com/t5/community/page.enableautocomplete:enableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions'>Activar sugerencias</a> <span class='HelpIcon'> <a class='lia-link-navigation help-icon lia-tooltip-trigger' role='button' aria-label='Icono de ayuda' id='link_24bce40c10967f' href='#'><span class='lia-img-icon-help lia-fa-icon lia-fa-help lia-fa' alt='La sugerencia automática le ayuda a obtener, de forma rápida, resultados precisos de su búsqueda al sugerirle posibles coincidencias mientras escribe.' aria-label='Icono de ayuda' role='img' id='display_24bce40c10967f'></span></a><div role='alertdialog' class='lia-content lia-tooltip-pos-bottom-left lia-panel-tooltip-wrapper' id='link_24bce40c10967f_0-tooltip-element'><div class='lia-tooltip-arrow'></div><div class='lia-panel-tooltip'><div class='content'>La sugerencia automática le ayuda a obtener, de forma rápida, resultados precisos de su búsqueda al sugerirle posibles coincidencias mientras escribe.</div></div></div> </span> </span> </div> </div> <div class='spell-check-showing-result'> Mostrando los resultados de <span class='lia-link-navigation show-results-for-link lia-link-disabled' aria-disabled='true' id='showingResult_24bce40c10967f'></span> </div> <div> <span class='spell-check-search-instead'> Buscar en lugar de <a class='lia-link-navigation search-instead-for-link' rel='nofollow' id='searchInstead_24bce40c10967f' href='#'></a> </span> </div> <div class='spell-check-do-you-mean lia-component-search-widget-spellcheck'> Quiere decir: <a class='lia-link-navigation do-you-mean-link' rel='nofollow' id='doYouMean_24bce40c10967f' href='#'></a> </div> </div> </div> <div class="user-nav-options"> <!-- community-header-nav-upper-v2 --> <style>.get-hubspot .nav-popover-arrow {border-top-color: transparent; border-left-color: transparent; width: 20px; height: 20px; transform: rotate(-135deg); top: -10px; display: block;}</style> <div class="search-icon-plus-top"> <button class="lia-button search-toggle-action-icon-plus"><img src='https://community.hubspot.com/html/@5320E40129AA1377479EABCA2009B53A/assets/Start-dicsucssion.svg' alt=""><i class="lia-fa lia-fa-caret-down"></i></button> <div class="plus-bar-main-content" style="display: none;"> <ul id="plus-bar-top-main"> <li class="plus-bar"> <a href="https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2Ft5%2Fforums%2Fpostpage%2Fcategory-id%2Fhubspot_community_es%2Fchoose-node%2Ftrue" class="white-btn transpaent"><i><img src="https://community.hubspot.com/html/@38F5B2AB35958F39F47C2BFFE5486135/assets/Edit.svg"></i> Crea una publicación</a> </li> <li class="plus-bar"><a href="https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2Ft5%2Fforums%2Fpostpage%2Fboard-id%2FHubSpot_Ideas"><i><img src="https://community.hubspot.com/html/@C71A42AEB76B8A3A82335DA9F5B9C717/assets/lightbulb.svg"></i> Añade una idea</a></li> </ul> </div> </div> <div class="login-container"> <a class='lia-link-navigation login-link lia-authentication-link lia-component-users-action-login' rel='nofollow' id='loginPageV2_24bce410577e37' href='https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2F%3Fprofile.language%3Des'>Iniciar Sesión</a> <a id="get-hubspot-free" class="btn btn-sm button-tertiary get-hubspot">Obtener HubSpot gratis</a> <div id="get-hubspot" class="get-hubspot"> <div class="nav-popover-arrow"></div> <ul id="get-hs-dropdown" class="nav-dropdown-list"> <li class="nav-dropdown-item nav-crm"> <a href="https://www.hubspot.es/products/get-started" class="nav-dropdown-link nav-crm"> Crear una cuenta de HubSpot CRM </a> </li> <li class="nav-dropdown-item nav-dev"> <a href="https://developers.hubspot.com/" class="nav-dropdown-link nav-dev"> Crear una cuenta de desarrollador de HubSpot </a> </li> </ul> </div> </div> </div> </nav> </div> <div class="forum-nav-bar"> <nav class="nav-menu template-centered template-section"> <a href="/" id="nav-logo" class="es nav-wordmark"> <img src='https://community.hubspot.com/html/@60C06466C7735C4373198758B1428669/assets/Community-logo-new.svg' alt="hubspot" class="nav-wordmark"> <span class="page-title nav-wordmark">Comunidad de</span> </a> <a href="/" id="nav-logo-v2" class="es nav-wordmark v2"> <img src='https://community.hubspot.com/html/@813D252A70F0A7024C8EA3BB1B8B9CFD/assets/sticky-logo.png' alt="hubspot" class="nav-wordmark"> </a> <style> .jp-resources-list{ display:flex; flex-direction:column; } .jp-resources-list>li.nav-dropdown-item.jp-class-HubSpot.Community.Blog{ order:1; } .nav-external-link::after { background: none; content: "\f08e"; font-family: "FontAwesome"; margin-left: 5px; font-size: 14px; } </style> <div class="nav-group-wrapper"> <div class="nav-menu"> <ul class="nav-group-primary"> <li class="nav-group-item nav-group-item-has-dropdown"> <div class="nav-link-wrapper"> <a class="nav-link forum"> <span class="nav-link-label"> Conversaciones </span> <span class="dropdown-caret"></span> </a> <div class="nav-popover-arrow"></div> <div class="nav-popover forum"> <ul class="nav-dropdown-list"> <li class="nav-dropdown-item"> <a href="/t5/Foro-de-CRM-y-Sales-Hub/ct-p/crm_sales_hub_es" class="nav-dropdown-link nav-discussions-crm"> CRM & Sales </a> </li> <li class="nav-dropdown-item"> <a href="/t5/Foro-de-Marketing-Hub/ct-p/marketing_hub_es" class="nav-dropdown-link nav-discussions-mktg"> Marketing & Contenido </a> </li> <li class="nav-dropdown-item"> <a href="/t5/Foro-de-Service-Hub/ct-p/service_hub_es" class="nav-dropdown-link nav-discussions-svc"> Éxito del cliente & Servicio al cliente </a> </li> <li class="nav-dropdown-item"> <a href="/t5/Operaciones-y-gesti%C3%B3n-de/ct-p/operations_es" class="nav-dropdown-link nav-discussions-ops"> Operaciones y gestión de ingresos </a> </li> <li class="nav-dropdown-item"> <a href="/t5/Commerce/ct-p/commerce" class="nav-dropdown-link nav-discussions-commerce in-english"> Commerce </a> </li> <li class="nav-dropdown-item"> <a href="/t5/HubSpot-Developers/ct-p/developers" class="nav-dropdown-link nav-discussions-developers in-english"> Desarrolladores </a> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/Getting-Started-on-the-Community/How-to-join-the-Solutions-Partner-Program/ba-p/400205" class="nav-dropdown-link nav-partners in-english"> Solutions Partner Program </a> </li> <li class="nav-dropdown-item"> <a href="/t5/HubSpot-Ideas/idb-p/HubSpot_Ideas" class="nav-dropdown-link nav-discussions-ideas in-english"> Ideas </a> </li> </ul> </div> </div> </li> <li class="nav-group-item nav-group-item-has-dropdown secondInList"> <div class="nav-link-wrapper"> <a class="nav-link forum"> <span class="nav-link-label"> Academy </span> <span class="dropdown-caret"></span> </a> <div class="nav-popover-arrow"></div> <div class="nav-popover forum"> <ul class="nav-dropdown-list"> <li class="nav-dropdown-item"> <a href="https://academy.hubspot.com/es/courses?page=1" class="nav-dropdown-link nav-external-link" target="_blank"> Cursos </a> </li> <li class="nav-dropdown-item"> <a href="https://academy.hubspot.com/es/certification-overview" class="nav-dropdown-link nav-external-link" target="_blank"> Certificaciones </a> </li> <li class="nav-dropdown-item"> <a href="https://www.hubspot.es/academy/bootcamps/inicio?hubs_content=www.hubspot.com%2Facademy%2Fbootcamps%2Fhome&hubs_content-cta=cl-dropdown-menu-link&__hstc=20629287.dd61fd337366ed0846198065dee2bf43.1720706970340.1723038547450.1723051045741.66&__hssc=20629287.14.1723051045741&__hsfp=2390368378" class="nav-dropdown-link nav-external-link" target="_blank"> Cursos intensivos de HubSpot Academy </a> </li> <li class="nav-dropdown-item"> <a href="https://academy.hubspot.com/learning-paths" class="nav-dropdown-link nav-external-link" target="_blank"> Rutas de aprendizaje </a> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/HubSpot-Academy-en-Espa%C3%B1ol/bd-p/academy_es" class="nav-dropdown-link "> Soporte HubSpot Academy </a> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/Grupos-de-estudio/bd-p/academy-education-study-group-es" class="nav-dropdown-link"> Grupos de estudio </a> </li> </ul> </div> </div> </li> <li class="nav-group-item"> <div class="nav-link-wrapper"> <a class="nav-link nav-resources"> <span class="nav-link-label"> Recursos </span> <span class="dropdown-caret"></span> </a> <div class="nav-popover-arrow"></div> <div class="nav-popover forum"> <ul class="nav-dropdown-list jp-resources-list"> <li class="nav-dropdown-item "> <a href="/t5/Primeros-Pasos/ct-p/getting_started_es" class="nav-dropdown-link nav-discussions-gs"> Primeros Pasos </a> </li> <li class="nav-dropdown-item"> <a href="https://help.hubspot.com/es/" class="nav-dropdown-link nav-external-link" target="_blank"> Centro de ayuda de HubSpot </a> </li> <li class="nav-dropdown-item"> <a href="https://knowledge.hubspot.com/" class="nav-dropdown-link nav-external-link" target="_blank"> Base de conocimientos </a> </li> <li class="nav-dropdown-item"> <a href="https://developers.hubspot.es/beta-docs/reference/api/overview?__hstc=20629287.dd61fd337366ed0846198065dee2bf43.1720706970340.1723038547450.1723051045741.66&__hssc=20629287.43.1723051045741&__hsfp=2390368378&uuid=3bec601b-d3d6-456a-a114-baf48d4c4c02" class="nav-dropdown-link nav-external-link" target="_blank"> Documentación de referencia de la API </a> </li> <li class="nav-dropdown-item"> <a href="https://developers.hubspot.es/beta-docs/reference/cms?__hstc=20629287.dd61fd337366ed0846198065dee2bf43.1720706970340.1723038547450.1723051045741.66&__hssc=20629287.44.1723051045741&__hsfp=2390368378&uuid=46f4de7e-a9d2-4993-a0a7-1c45b8086d87" class="nav-dropdown-link nav-external-link" target="_blank"> Documentación de CMS </a> </li> <li class="nav-dropdown-item "> <a href="/t5/Noticias-Networking-y-Eventos/ct-p/community_news_announcement_es" class="nav-dropdown-link nav-news"> Noticias </a> </li> <li class="nav-dropdown-item "> <a href="/t5/Resources/ct-p/resources?node_id=webinars&order_by=last_updated" class="nav-dropdown-link nav-resource-blog-Webinars in-english"> Seminarios web </a> </li> <li class="nav-dropdown-item "> <a href="/t5/Novedades-sobre-la-herramienta/bg-p/product_updates_es" class="nav-dropdown-link nav-resource-blog-Releases and Updates "> Lanzamientos y actualizaciones </a> </li> <li class="nav-dropdown-item "> <a href="/t5/Resources/ct-p/resources?node_id=resources" class="nav-dropdown-link nav-resource-blog-HubSpot Community Blog in-english "> Blog de la comunidad </a> </li> <li class="nav-dropdown-item "> <a href="/t5/Resources/ct-p/resources?node_id=workflows_library" class="nav-dropdown-link nav-resource-blog-Workflows Library in-english "> Biblioteca de Workflows </a> </li> <li class="nav-dropdown-item "> <a href="/t5/Resources/ct-p/resources?node_id=ai-library" class="nav-dropdown-link nav-resource-blog-Breeze Library "> Breeze Library </a> </li> </ul> </div> </div> </li> <li class="nav-group-item nav-group-item-has-dropdown"> <div class="nav-link-wrapper"> <a class="nav-link forum"> <span class="nav-link-label"> Eventos </span> <span class="dropdown-caret"></span> </a> <div class="nav-popover-arrow"></div> <div class="nav-popover forum"> <ul class="nav-dropdown-list"> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/Ask-Me-Anything-and-Panel/bd-p/ama_discussions" class="nav-dropdown-link in-english"> Preguntas y respuestas </a> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/Community-Led-Events/bd-p/adapt" class="nav-dropdown-link in-english"> Eventos organizados por la Comunidad </a> </li> <li class="nav-dropdown-item"> <a href="https://www.hubspot.com/resources/webinar" class="nav-dropdown-link nav-external-link" target="_blank"> Webinars </a> </li> <li class="nav-dropdown-item"> <a href="https://www.hubspot.com/hubspot-user-groups" class="nav-dropdown-link nav-external-link" target="_blank"> HUGS </a> </li> </ul> </div> </div> </li> <li class="nav-group-item nav-group-item-has-dropdown"> <div class="nav-link-wrapper en-only"> <a class="nav-link forum"> <span class="nav-link-label"> Advocacy </span> <span class="dropdown-caret"></span> </a> <div class="nav-popover-arrow"></div> <div class="nav-popover forum"> <ul class="nav-dropdown-list"> <li class="nav-dropdown-item"> <a href='/t5/Advocacy/ct-p/advocacy' class="nav-dropdown-link nav-hubFans-program in-english"> Programa de Champions de la Comunidad </a> </li> <li class="nav-dropdown-item"> <a href="/t5/Advocates-Blog/bg-p/advocates-blog" class="nav-dropdown-link nav-adovcates-blog in-english"> Blog de Champions </a> </li> </ul> </div> </div> </li> </ul> <div class="login-container v2"> <style> #lia-body .community-header-nav.v2 .forum-nav-bar.ch-sticky .nav-menu > ul.nav-group-primary { transform: none !important; } #lia-body .community-header-nav.v2 .forum-nav-bar.ch-sticky .login-container.v2 { display: flex; align-items: center; gap: 12px; padding-left: 0; width: 116px; } #lia-body.lia-user-status-anonymous .community-header-nav.v2 .forum-nav-bar.ch-sticky .login-container.v2 { gap: 0; width: 24px; } .ch-sticky .nav-menu { gap: 36px; } .custom-search-focus { background-image: url('https://community.hubspot.com/html/@C11BAC294B66222FECF4AA35890ACE71/assets/search-icon.svg'); background-repeat: no-repeat; background-size: contain; cursor: pointer; margin: 0; width: 24px; height: 24px; } </style> <label class="custom-search-focus"></label> <div class="nav-link-wrapper custom-user-menu-v2"> <div class="nav-popover-arrow"></div> <div class="nav-popover profile first"> <div class="header-dropdown-menu"> <div class="user-heading">Anonymous</div> <ul class="header-tab-nav"> <li><span id="profile" class="active">Perfil</span></li> </ul> <div class="header-tab-nav-content"> <div id="profile-list-wrapper"> <div class="nav-link-wrapper"> <a href="https://app.hubspot.com/l/reports-dashboard/" class="text-link my-account nav-hubspot-account" target="_blank"> Mi cuenta de HubSpot </a> </div> <ul class="nav-dropdown-list"> <li class="nav-dropdown-item"> <a href="/t5/user/viewprofilepage/user-id/-1" class="nav-dropdown-link nav-account-profile-2"> Mi Perfil </a> </li> <li class="nav-dropdown-item"> <a href="/t5/user/myprofilepage/tab/personal-profile" class="nav-dropdown-link nav-account-user-settings"> Parámetros </a> </li> <li class="nav-dropdown-item"> </li> <li class="nav-dropdown-item"> <a href="https://community.hubspot.com/t5/community/page.logoutpage?t:cp=authentication/contributions/unticketedauthenticationactions&dest_url=https%3A%2F%2Fcommunity.hubspot.com%2F&lia-action-token=dIScs4d01waitpidrj1yBrvxIHOVkDOcDqPTItDSgEs.&lia-action-token-id=logoff" class="nav-dropdown-link nav-account-sign-out"> Cerrar sesión </a> </li> </ul> </div> <div id="admin-list-wrapper" style="display: none;"> <div class="admin-menu-list"> </div> </div> </div> </div> </div> </div> </div> </div> </div> </nav> </div> </div> </section> </div> </div> </div><div class="lia-quilt-row lia-quilt-row-footer"> <div class="lia-quilt-column lia-quilt-column-24 lia-quilt-column-single lia-quilt-column-common-footer lia-mark-empty"> </div> </div> </div> </div> </div> </div><div class="lia-quilt-row lia-quilt-row-main"> <div class="lia-quilt-column lia-quilt-column-24 lia-quilt-column-single lia-quilt-column-main-content"> <div class="lia-quilt-column-alley lia-quilt-column-alley-single"> <!-- homepage-search-hero-v2 --> <section class="homepage-hero v2 page-full-width guest-banner-wrapper" style="background-image:url('/html/assets/bg.community_page.png');" > <div class="custom-homepage-banner guest-mode"> <div class="custom-v2-banner__announcement"> <div class="community-banner-message transparent"> <div class="banner-message-inner-wrapper"> <div class="hsg-promo-bar__wrapper" data-background="gradient4"> <div class="hsg-page-width-normal" data-background-image="circle2"> <div class="hsg-promo-bar" id="promo-bar"> </div> </div> </div> </div> </div> </div> <style> .lia-page { overflow-x: hidden; } .custom-v2-banner__announcement:not(:has(.transparent)) { margin-bottom: -20px; transform: translateY(-20px); } .CommunityPage .custom-v2-banner__announcement:not(:has(.transparent)) { margin-bottom: -72px; transform: translateY(-72px); } #promo-bar { background: #c1eaeb; border: 0; padding: 16px 0; position: relative; } #promo-bar:before, #promo-bar:after { background: #c1eaeb; content: ''; width: 300%; position: absolute; top: 0; bottom: 0; left: 0; } #promo-bar:before { transform: translateX(-100%); } #promo-bar:after { left: auto; right: 0; transform: translateX(100%); } #promo-bar .banner-message-text { display: flex; gap: 16px; align-items: center; justify-content: center; font-size: 16px !important; font-weight: 300; line-height: 1.75; text-align: center; } #promo-bar .banner-message-text .banner-cta-link { margin: 0; text-align: center; } @media only screen and (max-width: 767px) { #promo-bar .banner-message-wrapper:not(:first-child) { display: none; } #promo-bar .banner-message-text { flex-direction: column; gap: 8px; } #promo-bar .banner-message-text .banner-cta-link { min-width: 50%; } } @media only screen and (max-width: 1023px) { .custom-v2-banner__announcement:not(:has(.transparent)) { margin-bottom: -30px !important; transform: translateY(-30px) !important; } } </style> <script> const userLang = 'es'; const injectContent = (results) => { let promoBar = document.querySelector('#promo-bar'); // glowingblue: Remove stage test announcements if there are real ones if ( results.length ) { promoBar.replaceChildren(); } results.forEach(result => { if (result.message.length) { if (document.querySelector('.community-banner-message.transparent')) { document.querySelector('.community-banner-message.transparent').classList.remove('transparent'); } let messageWrapper = document.createElement('div'); messageWrapper.classList.add('banner-message-wrapper'); let message = document.createElement('p'); message.classList.add("banner-message-text"); message.innerHTML = result.message.trim(); promoBar.appendChild(messageWrapper); messageWrapper.appendChild(message) if (result.ctaLink.length && result.ctaText.length) { let ctaWrapper = document.createElement('div'); let cta = document.createElement('a'); ctaWrapper.classList.add('banner-cta-link'); cta.classList.add('banner-cta-link'); cta.setAttribute('href',result.ctaLink.trim()); cta.innerHTML = result.ctaText.trim(); message.appendChild(cta); } } else { return; } }) } const processBanner = (results) => { if (sessionStorage.getItem("HSCommunityAnnouncements")) { let data = JSON.parse(sessionStorage.getItem('HSCommunityAnnouncements')); if (data.lang === userLang) { data.messages = results; sessionStorage.setItem("HSCommunityAnnouncements", JSON.stringify(data)); return; } else { injectContent(results); data.lang = userLang; data.messages = results; sessionStorage.setItem("HSCommunityAnnouncements", JSON.stringify(data)); } } else { injectContent(results); messageData = { lang: userLang, messages: results } sessionStorage.setItem("HSCommunityAnnouncements", JSON.stringify(messageData)); } } if (sessionStorage.getItem('HSCommunityAnnouncements')) { let data = JSON.parse(sessionStorage.getItem('HSCommunityAnnouncements')); if (userLang === data.lang) { injectContent(data.messages); } } </script> <script src="https://script.google.com/a/hubspot.com/macros/s/AKfycbySpmgzEjP1bEnrLD5xM_fdMOxDn47Kt9buJO9HtQER7pZmhu0/exec?lang=es&callback=processBanner" async> </script><!-- [{"subject": "Novedades destacadas de octubre 2024","body": " Marketing Hub Asociar las campañas a formularios en la nueva herramienta de formularios En la nueva herramienta de formularios, simplemente elige un formulario desde la opción desplegable de archivos para conectarlo fácilmente a tu campaña y mejorar tu estrategia de marketing. Lo","href": "/t5/Novedades-sobre-la-herramienta/Novedades-destacadas-de-octubre-2024/ba-p/1071663"},{"subject": "¿Qué es Breeze Content Agent?","body": " ¡Te presentamos Breeze Content Agent! Esta poderosa herramienta de IA facilita la creación de contenido en múltiples formatos como blogs, páginas de destino, podcasts y estudios de caso, todo basado en los datos de tu CRM. Con Breeze, puedes generar contenido personalizado, asegurando que tu marc","href": "/t5/Anuncios/Qu%C3%A9-es-Breeze-Content-Agent/td-p/1063350"},{"subject": "¿Qué es Breeze Customer Agent?","body": " ¡Transforma tu atención al cliente al instante! Con el agente de atención al cliente de Breeze, siempre disponible para resolver las consultas de tus clientes de manera humana y eficiente. ¡Haz que cada interacción cuente! ¡Mira nuestro video para saber más! Activa CC para obteb","href": "/t5/Anuncios/Qu%C3%A9-es-Breeze-Customer-Agent/td-p/1064577"},{"subject": "¿Qué es Breeze Copilot?","body": " ¡Conoce Breeze Copilot! Esta herramienta de IA integrada en HubSpot no solo te ayuda a generar contenido y automatizar tareas, sino que también prioriza la privacidad de tus datos . Ya sea que estés escribiendo un correo electrónico o gestionando tus clientes potenciales, Copilot te ofrece una ","href": "/t5/Anuncios/Qu%C3%A9-es-Breeze-Copilot/td-p/1062593"}] --> <div class="custom-homepage-banner__wrapper"> <div class="custom-homepage-banner__header"> <div class="custom-homepage-banner__title"> <div class="custom-homepage-banner__title"> <h2>Bienvenido a la Comunidad de HubSpot.</h2> <p>Conecta con otros profesionales, maximiza tu conocimiento de HubSpot y aprende cómo puedes crecer mejor con HubSpot. </p> </div> <div class="custom-homepage-banner__actions"> <div><a class="btn banner-action-btn" href="https://community.hubspot.com/t5/Comenzando-con-la-Comunidad/5-Consejos-para-empezar-a-interactuar-con-la-Comunidad-de/td-p/443383">Primeros Pasos</a></div> </div> </div> </div> <div class="custom-homepage-banner__body"> <div class="banner-grid-container"> <a href="/t5/Novedades-sobre-la-herramienta/Novedades-destacadas-de-octubre-2024/ba-p/1071663"class="item1"> <h4> Novedades destacadas de octubre 2024 </h4> <p> Marketing Hub Asociar las campañas a formularios en la nueva herramienta de formularios En la nueva ... </p> </a> <a href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Content-Agent/td-p/1063350"class="item2"> <h4> ¿Qué es Breeze Content Agent? </h4> <p> ¡Te presentamos Breeze Content Agent! Esta poderosa herramienta de IA facilit... </p> </a> <a href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Customer-Agent/td-p/1064577"class="item3"> <h4> ¿Qué es Breeze Customer Agent? </h4> <p> ¡Transforma tu atención al cliente al instante! Con el agente de atención al cliente de Breeze, siempre disponible pa... </p> </a> <a href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Copilot/td-p/1062593"class="item4"> <h4> ¿Qué es Breeze Copilot? </h4> <p> ¡Conoce Breeze Copilot! Esta herramienta de IA integrada en HubSpot no solo te ayuda a generar contenido y automatizar tareas, sino que también prioriza la privacidad de tus datos . Ya sea que estés escribiendo un c... </p> </a> </div> </div> </div> <style> .item1 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2022/Whats%20hot%204%20(490%20x%201166)/Dianis%20designs%20(4).png") ; } .item2 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2022/Whats%20Hot%202%20(346%20x%20326)/Dianis%20designs%20(2).png") ; } .item3 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2022/Whats%20hot%203%20(224%20x%20290)/Dianis%20designs%20(2).png") ; } .item4 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2022/Whats%20hot%201%20(312%20x%20327)/Dianis%20designs%20(2).png") ; } @media(max-width:767px){ .item1 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2024/Whats%20hot%204%20(490%20x%201166)/Mobile%20Images/Dianis%20designs%20(4).png") ; } .item2 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2022/Whats%20Hot%202%20(346%20x%20326)/Mobile/Dianis%20designs%20(2).png") ; } .item3 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2022/Whats%20hot%203%20(224%20x%20290)/Mobile/Dianis%20designs%20(2).png") ; } .item4 { background-image : url("https://knowledge.hubspot.com/hubfs/%5BHubSpot_Community%5D_/2022/Whats%20hot%201%20(312%20x%20327)/Mobile/Dianis%20designs%20(2).png") ; } } </style> </div> </section> <div class="custom-tabs-with-accordian custom-top-community-conversations custom-home-banner-section wrapper-container"> <div class="custom-home-banner-section__header"><h2>Las mejores conversaciones de la Comunidad</h2><p>Consulta aquí las conversaciones más populares de la Comunidad</p></div> <div id="top-conversations-tabs" class="custom-dashboard-tabs desktop-view"> <ul class="custom-dashboard-tabs__list"> <li class="custom-dashboard-tabs__item active " data-tab-id="tab-1" title="Primeros Pasos"> <a href="#">Primeros Pasos</a> </li> <li class="custom-dashboard-tabs__item " data-tab-id="tab-2" title="Foro de CRM y Sales Hub"> <a href="#">Foro de CRM y Sales Hub</a> </li> <li class="custom-dashboard-tabs__item " data-tab-id="tab-3" title="Foro de Marketing Hub"> <a href="#">Foro de Marketing Hub</a> </li> <li class="custom-dashboard-tabs__item " data-tab-id="tab-4" title="Éxito del cliente & Servicio al cliente"> <a href="#">Éxito del cliente & Servicio al cliente</a> </li> <li class="custom-dashboard-tabs__item " data-tab-id="tab-5" title="Noticias, Networking y Eventos"> <a href="#">Noticias, Networking y Eventos</a> </li> <li class="custom-dashboard-tabs__item " data-tab-id="tab-6" title="HubSpot Academy en Español"> <a href="#">HubSpot Academy en Español</a> </li> </ul> </div> <div id="top-conversations-tabs" class="custom-dashboard-tabs mobile-view"> <select class="custom-dashboard-tabs__list"> <option class="custom-dashboard-tabs__item" data-tab-id="tab-1"><a href="#" title="Primeros Pasos">Primeros Pasos</a></option> <option class="custom-dashboard-tabs__item" data-tab-id="tab-2"><a href="#" title="Foro de CRM y Sales Hub">Foro de CRM y Sales Hub</a></option> <option class="custom-dashboard-tabs__item" data-tab-id="tab-3"><a href="#" title="Foro de Marketing Hub">Foro de Marketing Hub</a></option> <option class="custom-dashboard-tabs__item" data-tab-id="tab-4"><a href="#" title="Éxito del cliente & Servicio al cliente">Éxito del cliente & Servicio al cliente</a></option> <option class="custom-dashboard-tabs__item" data-tab-id="tab-5"><a href="#" title="Noticias, Networking y Eventos">Noticias, Networking y Eventos</a></option> <option class="custom-dashboard-tabs__item" data-tab-id="tab-6"><a href="#" title="HubSpot Academy en Español">HubSpot Academy en Español</a></option> </select> </div> <div class="custom-dashboard-tabs__content top-conversations-tabs__content"> <div class="custom-dashboard-tab-body active tab-1"> <ul class="custom-dashboard-accordian-list"> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Bienvenido/Feliz-5-%C2%BA-Aniversario-Comunidad-en-Espa%C3%B1ol/td-p/1012867">🎉¡Feliz 5.º Aniversario Comunidad en Español!🎈</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Feliz 5.º Aniversario a todos los miembros de la Comunidad en Español! Nos alegra enormemente contemplar todo lo que hemos logrado en colaboración. Y para celebrarlo, hemos elaborado esta publicación como muestra de agra ...<a href="/t5/Bienvenido/Feliz-5-%C2%BA-Aniversario-Comunidad-en-Espa%C3%B1ol/td-p/1012867" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Videos-Tutoriales-de-HubSpot/correos-electr%C3%B3nicos/td-p/998958">correos electrónicos</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Hola, tengo un plan pago y tambien estoy pagando extra por contactos de marketing. Saben si los correos electrónicos se acumulan al siguiente mes o terminando el mes vuelven a cero? Si me pueden ayudar porfavor. Gracias. ...<a href="/t5/Videos-Tutoriales-de-HubSpot/correos-electr%C3%B3nicos/td-p/998958" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Comenzando-con-la-Comunidad/Toma-las-riendas-tu-gu%C3%ADa-para-actualizar-tu-nombre-de-usuario/td-p/924898">Toma las riendas: tu guía para actualizar tu nombre de usuario.</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Tenemos noticias emocionantes para los miembros de nuestra comunidad! Nos complace anunciar el lanzamiento del autoservicio para cambiar tu nombre de usuario. ¡Sí, así es! Ya no tendrás que llenar formularios ni esperar. Ahora tienes el poder ...<a href="/t5/Comenzando-con-la-Comunidad/Toma-las-riendas-tu-gu%C3%ADa-para-actualizar-tu-nombre-de-usuario/td-p/924898" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Videos-Tutoriales-de-HubSpot/Imagen-de-fondo/td-p/918605">Imagen de fondo</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Hola, estoy con la modalidad gratuita y en el encabezado me sale una imagen que quiero cambiar por un vídeo. ¿Cómo lo puedo hacer? ...<a href="/t5/Videos-Tutoriales-de-HubSpot/Imagen-de-fondo/td-p/918605" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Videos-Tutoriales-de-HubSpot/Como-cambiar-el-tama%C3%B1o-de-video-en-una-plantilla/td-p/907300">Como cambiar el tamaño de video en una plantilla</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Hola a todos, estoy editando una landing page para agendar llamadas y quiero agregar una sección de video para poder reproducirlo de manera automatica una vez ingresen en la landing, pero 1- no encuentro el boton para que el video se reproduca de ma ...<a href="/t5/Videos-Tutoriales-de-HubSpot/Como-cambiar-el-tama%C3%B1o-de-video-en-una-plantilla/td-p/907300" class="read-more">Leer más </a> </li> </ul> </li> </ul> <div class="custom-home-banner-section__see-all"><a href="/t5/Primeros-Pasos/ct-p/getting_started_es">Ve a Primeros Pasos </a> </div> </div> <div class="custom-dashboard-tab-body tab-2"> <ul class="custom-dashboard-accordian-list"> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Voz-de-marca/td-p/1066258">Voz de marca</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Las herramientas de Voz de Marca de HubSpot, impulsadas por IA, ofrecen la solución perfecta para crear contenido que realmente capture el tono y la voz única de tu negocio. ¡Mira nuestro video para saber más! ...<a href="/t5/Consejos-trucos-y-buenas/Voz-de-marca/td-p/1066258" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Simplificaci%C3%B3n-de-formularios/td-p/1065120">Simplificación de formularios</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡La reducción dinámica de formularios asegura que continúes recopilando la información esencial para entender, calificar y orientar a tus leads de manera rápida y precisa. ¡Mira nuestro video para saber más! ...<a href="/t5/Consejos-trucos-y-buenas/Simplificaci%C3%B3n-de-formularios/td-p/1065120" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/CRM/Blob-a-campo-tipo-archivo-usando-el-api-de-env%C3%ADo-de-formularios/td-p/1028806">Blob a campo tipo archivo usando el api de envío de formularios</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Hola. Estoy tratando de usar el api de envío de formularios para djuntar un blob que estoy creando directamente del formulario, la cuestión es que al guardar el envío, lo guarda como un objeto y dicho valor queda vacío. ¿Cuál debería ser el ...<a href="/t5/CRM/Blob-a-campo-tipo-archivo-usando-el-api-de-env%C3%ADo-de-formularios/td-p/1028806" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Correo-electr%C3%B3nico-de-Sales-Hub/variable-para-conseguir-nombre-apellido-y-mail-de-la-cuenta-que/td-p/1028588">variable para conseguir nombre, apellido y mail de la cuenta que se conecta en HS</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Buenas! Estoy creando una plantilla de mail con hubl donde necesito obtener el mail, nombre y apellido del que se conecta esa cuenta para posteriormente comparla con unos valores que tengo en hubdb, pero no logro encontrar esas variables: tambien ...<a href="/t5/Correo-electr%C3%B3nico-de-Sales-Hub/variable-para-conseguir-nombre-apellido-y-mail-de-la-cuenta-que/td-p/1028588" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Paneles-e-informes/Como-podr%C3%ADa-realizar-el-mejor-informe-de-reuniones/td-p/1028162">Como podría realizar el mejor informe de reuniones</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Buenas, vengo buscando ayuda, porque queria realizar el mejor informe de reuniones, cuando me refiero a mejor me refiero a que los datos esten bien y no haya ninguna discordancia, actualmente tengo este que estuve probando Pero no se si e ...<a href="/t5/Paneles-e-informes/Como-podr%C3%ADa-realizar-el-mejor-informe-de-reuniones/td-p/1028162" class="read-more">Leer más </a> </li> </ul> </li> </ul> <div class="custom-home-banner-section__see-all"><a href="/t5/Foro-de-CRM-y-Sales-Hub/ct-p/crm_sales_hub_es">Ve a Foro de CRM y Sales Hub </a> </div> </div> <div class="custom-dashboard-tab-body tab-3"> <ul class="custom-dashboard-accordian-list"> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Creador-de-Landing-Pages-con-IA/td-p/1065733">Creador de Landing Pages con IA</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Potencia tus conversiones con nuestra herramienta de Landing Pages con IA , que te permite crear fácilmente páginas personalizadas y atractivas , diseñadas para convertir visitantes en leads . ¡Mira nuestro video para saber más! ...<a href="/t5/Consejos-trucos-y-buenas/Creador-de-Landing-Pages-con-IA/td-p/1065733" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Customer-Agent/td-p/1064577">¿Qué es Breeze Customer Agent?</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Transforma tu atención al cliente al instante! Con el agente de atención al cliente de Breeze, siempre disponible para resolver las consultas de tus clientes de manera humana y eficiente. ¡Haz que cada interacción cuente! ¡Mira nuestro ...<a href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Customer-Agent/td-p/1064577" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Content-Agent/td-p/1063350">¿Qué es Breeze Content Agent?</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Te presentamos Breeze Content Agent! Esta poderosa herramienta de IA facilita la creación de contenido en múltiples formatos como blogs, páginas de destino, podcasts y estudios de caso, todo basado en los datos de tu CRM. Con Breeze, puedes gener ...<a href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Content-Agent/td-p/1063350" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Copilot/td-p/1062593">¿Qué es Breeze Copilot?</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Conoce Breeze Copilot! Esta herramienta de IA integrada en HubSpot no solo te ayuda a generar contenido y automatizar tareas, sino que también prioriza la privacidad de tus datos . Ya sea que estés escribiendo un correo electrónico o gestionand ...<a href="/t5/Anuncios/Qu%C3%A9-es-Breeze-Copilot/td-p/1062593" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Informe-del-Estado-del-Marketing/td-p/1048422">📑 Informe del Estado del Marketing</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Estamos en un momento de continuo cambio y evolución en el ámbito del marketing, y es fundamental estar preparados para los desafíos y oportunidades que se avecinan. Con el propósito de descubrir el panorama actual en el ámbito del m ...<a href="/t5/Consejos-trucos-y-buenas/Informe-del-Estado-del-Marketing/td-p/1048422" class="read-more">Leer más </a> </li> </ul> </li> </ul> <div class="custom-home-banner-section__see-all"><a href="/t5/Foro-de-Marketing-Hub/ct-p/marketing_hub_es">Ve a Foro de Marketing Hub </a> </div> </div> <div class="custom-dashboard-tab-body tab-4"> <ul class="custom-dashboard-accordian-list"> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Reporte-gratuito-Estado-del-servicio-al-cliente/td-p/990212">Reporte gratuito: Estado del servicio al cliente</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Encuestamos a 500 líderes empresariales y 500 consumidores finales de países como Chile, Colombia, España y México para descubrir cuáles son los retos y tendencias de servicio al cliente y entender un poco más la perspectiva de las empresa ...<a href="/t5/Consejos-trucos-y-buenas/Reporte-gratuito-Estado-del-servicio-al-cliente/td-p/990212" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Archivos-vs-documentos/td-p/962773">Archivos vs. documentos</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Hola comunidad! Queremos compartir un archivo pdf fuera de HubSpot pero con un enlace generado por este para poder hacerle seguimiento y conseguir analíticas (no solo de un usuario, si no de todo el mundo que quiera verlo). Nos surgen dudas p ...<a href="/t5/Consejos-trucos-y-buenas/Archivos-vs-documentos/td-p/962773" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Se-adjuntan-los-iconos-del-pie-de-email-como-fotos/td-p/932623">Se adjuntan los iconos del pie de email como fotos</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Hola! Tenemos un problema con la respuesta de los emails, ya que siempre que responden a nuestro email se adjuntan los iconos del pie del email nuestro como fotos: ¿Qué solución hay para evitar esto? Qeudamos a la espera. Gracias. ...<a href="/t5/Consejos-trucos-y-buenas/Se-adjuntan-los-iconos-del-pie-de-email-como-fotos/td-p/932623" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Consejos-trucos-y-buenas/Problemas-con-la-respuesta-en-ticket/td-p/918529">Problemas con la respuesta en ticket</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> ¡Hola! Actualmente cuando un cliente quiere hacer una devolución en nuestra web, nos llega un correo con toda la información de su email etc, nosotros creamos el ticket y ya le respondemos desde la bandeja de entrada, hasta ahí todo bien, pero h ...<a href="/t5/Consejos-trucos-y-buenas/Problemas-con-la-respuesta-en-ticket/td-p/918529" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Herramienta-de-feedback-de/Rotaci%C3%B3n-de-tickets/td-p/908445">Rotación de tickets</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Cordial saludo, Me encantaría saber si la herramienta de bandeja de entrada puede realizar una rotación para asignar los tickets que se ponen por formulario a cada uno de los agentes, tengo 6 agentes y les llegan más casos a unos que a otros. ...<a href="/t5/Herramienta-de-feedback-de/Rotaci%C3%B3n-de-tickets/td-p/908445" class="read-more">Leer más </a> </li> </ul> </li> </ul> <div class="custom-home-banner-section__see-all"><a href="/t5/%C3%89xito-del-cliente-Servicio-al/ct-p/service_hub_es">Ve a Éxito del cliente & Servicio al cliente </a> </div> </div> <div class="custom-dashboard-tab-body tab-5"> <ul class="custom-dashboard-accordian-list"> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Novedades-sobre-la-herramienta/Novedades-destacadas-de-octubre-2024/ba-p/1071663">Novedades destacadas de octubre 2024</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Marketing Hub Asociar las campañas a formularios en la nueva herramienta de formularios En la nueva herramienta de formularios, simplemente elige un formulario desde la opción desplegable de archivos para conectarlo fácilmente a t ...<a href="/t5/Novedades-sobre-la-herramienta/Novedades-destacadas-de-octubre-2024/ba-p/1071663" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Pautas-y-anuncios/HubSpot-recibe-el-reconocimiento-como-l%C3%ADder-en-el-Magic-Quadrant/td-p/1060479">HubSpot recibe el reconocimiento como líder en el Magic Quadrant™ de Gartner® de 2024</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Marketing Hub de HubSpot ha sido reconocido por cuarto año consecutivo como líder en el Magic Quadrant™ de Gartner® sobre plataformas de automatización de marketing B2B. La evaluación se basó en criterios específicos para el análisis de la ...<a href="/t5/Pautas-y-anuncios/HubSpot-recibe-el-reconocimiento-como-l%C3%ADder-en-el-Magic-Quadrant/td-p/1060479" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Pautas-y-anuncios/Conoce-las-nuevas-herramientas-de-datos-sensibles-de-HubSpot-en/td-p/1060472">Conoce las nuevas herramientas de datos sensibles de HubSpot en el Smart CRM</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> En HubSpot, entendemos la necesidad de combinar seguridad y comodidad al gestionar la información de los clientes. Por eso, hemos mejorado la configuración para que los datos sensibles puedan almacenarse de forma segura directamente en el Smart CRM ...<a href="/t5/Pautas-y-anuncios/Conoce-las-nuevas-herramientas-de-datos-sensibles-de-HubSpot-en/td-p/1060472" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Pautas-y-anuncios/Descubre-las-novedades-de-Sales-Hub-en-INBOUND-2024/td-p/1060461">Descubre las novedades de Sales Hub en INBOUND 2024</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> En INBOUND 2024, HubSpot desveló todas las nuevas características con IA de Sales Hub, con las que los equipos de ventas pueden aprovechar el poder de esta tecnología y dar a sus vendedores las herramientas y la orientación que necesitan para capta ...<a href="/t5/Pautas-y-anuncios/Descubre-las-novedades-de-Sales-Hub-en-INBOUND-2024/td-p/1060461" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Pautas-y-anuncios/Presentamos-Breeze-la-IA-f%C3%A1cil-de-usar-que-da-vida-a-toda-la/td-p/1060458">Presentamos Breeze: la IA fácil de usar que da vida a toda la plataforma de clientes</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> En 2023, integramos la IA en toda nuestra plataforma, y en el INBOUND de este año, lanzamos Breeze: una nueva y completa solución para ayudar a equipos como el tuyo a crecer mejor. Qué es Breeze Breeze es la IA de HubSpot y da ...<a href="/t5/Pautas-y-anuncios/Presentamos-Breeze-la-IA-f%C3%A1cil-de-usar-que-da-vida-a-toda-la/td-p/1060458" class="read-more">Leer más </a> </li> </ul> </li> </ul> <div class="custom-home-banner-section__see-all"><a href="/t5/Noticias-Networking-y-Eventos/ct-p/community_news_announcement_es">Ve a Noticias, Networking y Eventos </a> </div> </div> <div class="custom-dashboard-tab-body tab-6"> <ul class="custom-dashboard-accordian-list"> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/CURSO/td-p/1024941">CURSO</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Ralmente un curso interesante. Nos fcilita el traajo del día a día! Muchas gracias! ...<a href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/CURSO/td-p/1024941" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/Reinicio-o-eliminaci%C3%B3n-de-de-certificados/td-p/1020223">Reinicio o eliminación de de certificados</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Hola. ¿Es posible restablecer o eliminar las certificaciones asociadas a una cuenta de HubSpot Academy Nuestra empresa utiliza correos electrónicos numéricos para identificar a los miembros de nuestro equipo de ventas. Al producirse un cambio de ...<a href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/Reinicio-o-eliminaci%C3%B3n-de-de-certificados/td-p/1020223" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/Gracias-por-confianza/td-p/1016659">Gracias por confianza</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Gracias por los s videos y los cursos nos ayudan atener más conocimiento para poder ayudar a nuestra empresa a creser ...<a href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/Gracias-por-confianza/td-p/1016659" class="read-more">Leer más </a> </li> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/Un-curso-pr%C3%A1ctico/td-p/1016638">Un curso práctico</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> </ul> </li> <li class="custom-dashboard-accordian-item off"> <div class="custom-dashboard-accordian-item__header"> <span class="toggle-action on"><i class="fa fa-chevron-down nav-item-icon"></i></span> <h4 class="custom-dashboard-accordian-item__title"> <a class="con-link on" href="/t5/Grupos-de-estudio/certificado-de-ventas/td-p/1015579">certificado de ventas</a> </h4> </div> <ul class="custom-dashboard-accordian-posts-list"> <li class="custom-dashboard-accordian-post-item scroll-class"> Hola buenas tardes, no sé por que motivo en el certificado de ventas, aun me dice que el ejercicio importar contactos aun no está corregido aún habiendolo enviado 2 veces. Necesito su ayuda. Gracias ...<a href="/t5/Grupos-de-estudio/certificado-de-ventas/td-p/1015579" class="read-more">Leer más </a> </li> </ul> </li> </ul> <div class="custom-home-banner-section__see-all"><a href="/t5/HubSpot-Academy-en-Espa%C3%B1ol/ct-p/Academy_es">Ve a HubSpot Academy en Español </a> </div> </div> </div> </div> <!-- 2 --> <style> #lia-body .featured-places-tabs__content .wrapper-container{ padding-left:0px; padding-right:0px; } </style> <div class="custom-home-banner-section custom-featured-boards"> <div class="custom-home-banner-section__wrapper wrapper-container"> <div class="custom-home-banner-section__header"> <h2>Secciones destacadas</h2> <p>Descubre diferentes foros, blogs y grupos de la Comunidad</p> </div> <div class="custom-home-banner-section__cards"> <a class="card-item" href="/t5/Bienvenido/bd-p/welcome_es"> <div class="card-item__icon"><img src="/t5/image/serverpage/image-id/48903i3C460AB2C207019F/image-size/tiny?v=v2&px=100"></div> <h4 class="card-item__head">Bienvenido</h4> <p class="card-item__desc"> ¿Eres nuevo en la Comunidad HubSpot? Presénta... </p> <div class="card-item__stats"> <span title="Total posts">580</span> </div> </a> <a class="card-item" href="/t5/Videos-Tutoriales-de-HubSpot/bd-p/videos_tutoriales"> <div class="card-item__icon"><img src="/t5/image/serverpage/image-id/60123i0AD9B1F619AD1E41/image-size/tiny?v=v2&px=100"></div> <h4 class="card-item__head">Videos Tutoriales de HubSpot</h4> <p class="card-item__desc"> En este espacio encontrarás videos y contenid... </p> <div class="card-item__stats"> <span title="Total posts">173</span> </div> </a> <a class="card-item" href="/t5/Startups/bd-p/Startups_es"> <div class="card-item__icon"><img src="/t5/image/serverpage/image-id/48890iE0B7FC2845F58798/image-size/tiny?v=v2&px=100"></div> <h4 class="card-item__head">Startups</h4> <p class="card-item__desc"> Aprende de las startups que utilizan HubSpot,... </p> <div class="card-item__stats"> <span title="Total posts">384</span> </div> </a> <a class="card-item" href="/t5/Integraciones/bd-p/Integraciones"> <div class="card-item__icon"><img src="/html/assets/sunny.svg"></div> <h4 class="card-item__head">Integraciones</h4> <p class="card-item__desc"> Conoce integraciones entre HubSpot y otras ap... </p> <div class="card-item__stats"> <span title="Total posts">129</span> </div> </a> </div> </div> </div> <!-- 2 --> <div class="custom-home-banner-section custom-featured-groups"> <div class="custom-home-banner-section__wrapper wrapper-container"> <div class="custom-home-banner-section__header"> <h2>Grupos destacados</h2> <p>Únete a los grupos para compartir y conectar con los miembros de la comunidad de HubSpot</p> </div> <!-- ******* --> <div class="custom-home-banner-section__cards"> <a class="card-item" href = "/t5/Women-in-Tech/gh-p/Women_In_Tech"> <div class="card-item__icon"><img src="/t5/image/serverpage/image-id/35492i55896808D811C855/image-size/medium?v=v2&px=400"></div> <h4 class="card-item__head">Women in Tech</h4> <p class="card-item__desc"> Women in Tech HubSpot User Group </p> <div class="card-item__stats"> <span class="member-count" title="Group Members">734</span> <span class="topic-count" title="Total posts">36</span> </div></a> <a class="card-item" href = "/t5/Education-Partner-Program/gh-p/education_partner_program_community"> <div class="card-item__icon"><img src="/t5/image/serverpage/image-id/43217i7E07E72D907E816A/image-size/medium?v=v2&px=400"></div> <h4 class="card-item__head">Education Partner Program Community</h4> <p class="card-item__desc"> Community for members of HubSpot's Education ... </p> <div class="card-item__stats"> <span class="member-count" title="Group Members">508</span> <span class="topic-count" title="Total posts">131</span> </div></a> <a class="card-item" href = "/t5/World-Certification-Week-2022/gh-p/world_certificate_week"> <div class="card-item__icon"><img src="/t5/image/serverpage/image-id/64846i10D1A7B17D723DA5/image-size/medium?v=v2&px=400"></div> <h4 class="card-item__head">World Certification Week 2022</h4> <p class="card-item__desc"> A group dedicated to all things "World Certif... </p> <div class="card-item__stats"> <span class="member-count" title="Group Members">200</span> <span class="topic-count" title="Total posts">15</span> </div></a> </div> <div class="custom-home-banner-section__see-all"> <a href="/t5/Groups/ct-p/groups">Ver Todo</a> </div> </div> </div> <div class="custom-home-banner-section v2 custom-live-events"> <div class="custom-home-banner-section__wrapper"> <style> .events-section-main{ min-height: 228px; } .events-section-top{ display: flex; justify-content: space-between; box-shadow: 0 1px 5px 0 rgba(45,62,80,0.12); border-radius: 3px; } .events-section-heading{ background:#fff; padding: 30px 30px 30px 42px; width: calc(100% - 350px); display: inline-block; border-top-left-radius: 3px; border-bottom-left-radius: 3px; } .events-section-heading h1{ color: #33475B; font-size: 32px; font-weight: bold; letter-spacing: 0; line-height: 44px; } .events-section-heading p{ color: #33475B; font-size: 18px; letter-spacing: 0; line-height: 32px; } .events-section-tab{ display: inline-block; width: 100%; max-width: 350px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .events-section-tab img{ width:100%; height: 100%; border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .learn-more-btn{ border-radius: 3px; background-color: #FF7A59; color: #FFFFFF; font-size: 16px; font-weight: 600; letter-spacing: 0; line-height: 28px; padding: 8px 30px; } .learn-more-btn:hover{ text-decoration: none; color:#fff;} @media only screen and (max-width: 767px) { #lia-body .wrapper-container.events-section-bottom{ display:block; } .events-section-top{ display:flex; flex-flow:column; } .events-section-heading{ width:100%; } .events-section-tab{ order:-1;} } </style> <div class="events-section-main wrapper-container events-section-bottom"> <div class="events-section-top"> <div class="events-section-heading"> <h1>Eventos en vivo</h1> <p>Consulta los próximos eventos organizados por HubSpot. Con temas que van desde inmersiones profundas en productos hasta oportunidades de networking, hay un evento que te ayudará a aumentar tus habilidades y a seguir creciendo con HubSpot.</p> <a target="_blank" href="https://events.hubspot.com/" class="btn btn-primary learn-more-btn"><span>Ver Eventos</span></a> </div> <div class="events-section-tab"> <img src="https://community.hubspot.com/html/@A696DCC46884337F9626CCB93F41EBF5/assets/hubspot-live-event.png" alt=""> </div> </div> </div> </div> </div> <style> #lia-body .champion-box .recentContributorLeaderboard { box-shadow: none; margin: 0; } #lia-body .champion-box .recentContributorLeaderboard ul li:nth-child(n+6) { display: inherit; } </style> <div class="spotlight-wrapper"> <div class="template-centered"> <div class="spotlight-row"> <div class="spotlight-left-col"> <h4>Community Spotlight</h4> <div class="customer-box"> <div class="customer-img-box"> <a href = "/t5/Advocates-Blog/Meet-the-Champion-of-the-Month-November-2024/ba-p/1063777"><P style=" text-align: center; "><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Profile Background Option 6 (1).png" style="width: 200px;"><img src="https://community.hubspot.com/t5/image/serverpage/image-id/130751iA78F59A707CC783F/image-size/small?v=v2&px=200" role="button" title="Profile Background Option 6 (1).png" alt="Profile Background Option 6 (1).png" /></span><a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/91608">@alyssamwilie</a> </P></a> </div> <div class="customer-info-box"> <div class="customer-head">Meet the Champion of the Month: November 2024</div> <div class="customer-description"> Hello Community! I am thrilled to announce that our Champion of the Month for November 2024 is: Alyssa Wilie @alyssamwilie Let's give Alyssa a big round of applause for her contributions in the HubSpot Community What makes Alyssa our Community Champion of the Month? Alyssa is a front end developer at LyntonWe... </div> <div class="cta-box"> <a href="/t5/Advocates-Blog/Meet-the-Champion-of-the-Month-November-2024/ba-p/1063777">Lee más aquí</a> <a href="https://offers.hubspot.com/community-champions" target="_blank">Conviértete en un Community Champion</a> </div> </div> </div> </div> <div class="spotlight-right-col"> <div class="champion-box"> <style> div.top-solutions .UserAvatar {display: inline-block;} </style> <style>.top-solutions .UserAvatar.lia-user-avatar.lia-component-common-widget-user-avatar{display: inline-block;} </style> <section class="advisor-features"> <div class="advisor-features-container page-width-body center-block"> <div class="card-container"> <div class="top-advisors top-solutions"> <h2>Los autores de soluciones más leídos</h2> <div class="top-solutions-column-header"> <h6>Usuario</h6> <h6 class="count-column">Soluciones</h6> </div> <div class="top-solution-column-content" id="top-solution-container"> <ul id="top-solutions"> </ul> </div> <div class="view-all-wrapper" id="viewallwrapper" style="display:none;"><a class="view-all microcopy top-solutions-view-all" href="/t5/solutions/acceptedsolutionsleaderboardpage/node-display-id/category%3Ahubspot_community_es/timerange/six_months">Ver todo</a></div> </div> </div> </div> </section> <!-- <div class="lia-panel lia-panel-standard recentContributorLeaderboard"> <!-- <div class="lia-panel-content-wrapper"> <div class="lia-panel-content-box"> <div class="lia-panel lia-panel-standard KudoedAuthorsLeaderboardTaplet Chrome lia-component-kudos-widget-authors-leaderboard"><div class="lia-decoration-border"><div class="lia-decoration-border-top"><div> </div></div><div class="lia-decoration-border-content"><div><div class="lia-panel-heading-bar-wrapper"><div class="lia-panel-heading-bar"><span aria-level="3" role="heading" class="lia-panel-heading-bar-title">Autores con más kudos dados</span></div></div><div class="lia-panel-content-wrapper"><div class="lia-panel-content"> <div class="UserList lia-component-users-widget-user-list"> <span id="user-listuserList_24bce443d81bf6"> </span> <div class="t-data-grid" id="grid_24bce443d81bf6"> <table role="presentation" class="lia-list-slim"> <thead class="lia-table-head" id="columns_24bce443d81bf6"><tr><th scope="col" class="userColumn lia-data-cell-primary lia-data-cell-text t-first"> <span class="lia-view-filter lia-link-disabled" aria-disabled="true" id="link_24bce443d81bf6">Usuario</span> </th><th scope="col" class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer t-last"> Cantidad </th></tr></thead> <tbody> <tr class="lia-list-row lia-row-odd t-first"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-111325 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6" href="/t5/user/viewprofilepage/user-id/111325"><img class="lia-user-avatar-message" title="karstenkoehler" alt="karstenkoehler" id="display_24bce443d81bf6" src="/t5/image/serverpage/image-id/94937i541C6229094CA9C4/image-dimensions/38x38/image-coordinates/0%2C0%2C400%2C400?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Hall-of-Famer---Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de karstenkoehler" itemprop="url" id="link_24bce443d81bf6_0" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/111325"><span class="">karstenkoehler</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Miembro del salón de la fama | Partner" alt="Miembro del salón de la fama | Partner" id="display_0_24bce443d81bf6" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/partner-color.svg"/> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 74"> 74 </td></tr><tr class="lia-list-row lia-row-even"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-833252 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6_0" href="/t5/user/viewprofilepage/user-id/833252"><img class="lia-user-avatar-message" title="nlakeland" alt="nlakeland" id="display_24bce443d81bf6_0" src="https://community.hubspot.com/t5/image/serverpage/avatar-name/Avatar-Hubspot/avatar-theme/candy/avatar-collection/1_Hubspot/avatar-display-size/profile/version/2?xdesc=1.0"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Member"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de nlakeland" itemprop="url" id="link_24bce443d81bf6_1" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/833252"><span class="">nlakeland</span></a> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 20"> 20 </td></tr><tr class="lia-list-row lia-row-odd"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-73173 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6_1" href="/t5/user/viewprofilepage/user-id/73173"><img class="lia-user-avatar-message" title="franksteiner79" alt="franksteiner79" id="display_24bce443d81bf6_1" src="/t5/image/serverpage/image-id/17243i5D1F32478A522B19/image-dimensions/38x38/image-coordinates/320%2C0%2C1600%2C1280?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Key-Advisor"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de franksteiner79" itemprop="url" id="link_24bce443d81bf6_2" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/73173"><span class="">franksteiner79</span></a> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 14"> 14 </td></tr><tr class="lia-list-row lia-row-even"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-53340 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6_2" href="/t5/user/viewprofilepage/user-id/53340"><img class="lia-user-avatar-message" title="jforte" alt="jforte" id="display_24bce443d81bf6_2" src="/t5/image/serverpage/image-id/61195i3146EA87F3BF6BBC/image-dimensions/38x38?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Top-Contributor"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de jforte" itemprop="url" id="link_24bce443d81bf6_3" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/53340"><span class="">jforte</span></a> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 11"> 11 </td></tr><tr class="lia-list-row lia-row-odd"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-2062 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6_3" href="/t5/user/viewprofilepage/user-id/2062"><img class="lia-user-avatar-message" title="Josh" alt="Josh" id="display_24bce443d81bf6_3" src="/t5/image/serverpage/image-id/33700iE12B3A1E02232C5C/image-dimensions/38x38?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Recognized-Expert---Diamond-Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de Josh" itemprop="url" id="link_24bce443d81bf6_4" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/2062"><span class="">Josh</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Experto reconocido | Partner nivel Diamond" alt="Experto reconocido | Partner nivel Diamond" id="display_0_24bce443d81bf6_0" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/diamond-color.svg"/> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 10"> 10 </td></tr><tr class="lia-list-row lia-row-even"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-169593 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6_4" href="/t5/user/viewprofilepage/user-id/169593"><img class="lia-user-avatar-message" title="JuanGomez0818" alt="JuanGomez0818" id="display_24bce443d81bf6_4" src="/t5/image/serverpage/image-id/122609i532ECAB49295D450/image-dimensions/38x38/image-coordinates/0%2C0%2C1080%2C1080?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Key-Advisor"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de JuanGomez0818" itemprop="url" id="link_24bce443d81bf6_5" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/169593"><span class="">JuanGomez0818</span></a> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 9"> 9 </td></tr><tr class="lia-list-row lia-row-odd"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-141 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6_5" href="/t5/user/viewprofilepage/user-id/141"><img class="lia-user-avatar-message" title="TomM2" alt="TomM2" id="display_24bce443d81bf6_5" src="/t5/image/serverpage/image-id/85434iB7C5AAFDC991A8DE/image-dimensions/38x38/image-coordinates/0%2C204%2C1232%2C1436?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Thought-Leader---Platinum-Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de TomM2" itemprop="url" id="link_24bce443d81bf6_6" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/141"><span class="">TomM2</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Líder intelectual | Partner nivel Platinum" alt="Líder intelectual | Partner nivel Platinum" id="display_0_24bce443d81bf6_1" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/platinum-color.svg"/> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 9"> 9 </td></tr><tr class="lia-list-row lia-row-even t-last"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-20235 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce443d81bf6_6" href="/t5/user/viewprofilepage/user-id/20235"><img class="lia-user-avatar-message" title="rachaelsink" alt="rachaelsink" id="display_24bce443d81bf6_6" src="/t5/image/serverpage/avatar-name/feline/avatar-theme/candy/avatar-collection/animals/avatar-display-size/message/version/2?xdesc=1.0"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Participant"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de rachaelsink" itemprop="url" id="link_24bce443d81bf6_7" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/20235"><span class="">rachaelsink</span></a> </span> </div> </div> </div> </td><td class="kudosCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de kudos: 9"> 9 </td></tr> </tbody> </table> </div> </div> <div class="lia-view-all"><a class="lia-link-navigation view-all-link" id="link_24bce443d81bf6_8" href="/t5/forums/kudosleaderboardpage/timerange/one_week/page/1/tab/authors">Ver todo</a></div> </div></div></div></div><div class="lia-decoration-border-bottom"><div> </div></div></div></div><div class="lia-panel lia-panel-standard AcceptedSolutionsLeaderboardTaplet Chrome lia-component-solutions-widget-accepted-solutions-leaderboard-taplet"><div class="lia-decoration-border"><div class="lia-decoration-border-top"><div> </div></div><div class="lia-decoration-border-content"><div><div class="lia-panel-heading-bar-wrapper"><div class="lia-panel-heading-bar"><span aria-level="3" role="heading" class="lia-panel-heading-bar-title">Contribuyentes principales</span></div></div><div class="lia-panel-content-wrapper"><div class="lia-panel-content"> <div class="UserList lia-component-users-widget-user-list"> <span id="user-listuserList_24bce446ab7df8"> </span> <div class="t-data-grid" id="grid_24bce446ab7df8"> <table role="presentation" class="lia-list-slim"> <thead class="lia-table-head" id="columns_24bce446ab7df8"><tr><th scope="col" class="userColumn lia-data-cell-primary lia-data-cell-text t-first"> <span class="lia-view-filter lia-link-disabled" aria-disabled="true" id="link_24bce446ab7df8">Usuario</span> </th><th scope="col" class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer t-last"> Cantidad </th></tr></thead> <tbody> <tr class="lia-list-row lia-row-odd t-first"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-111325 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8" href="/t5/user/viewprofilepage/user-id/111325"><img class="lia-user-avatar-message" title="karstenkoehler" alt="karstenkoehler" id="display_24bce446ab7df8" src="/t5/image/serverpage/image-id/94937i541C6229094CA9C4/image-dimensions/38x38/image-coordinates/0%2C0%2C400%2C400?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Hall-of-Famer---Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de karstenkoehler" itemprop="url" id="link_24bce446ab7df8_0" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/111325"><span class="">karstenkoehler</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Miembro del salón de la fama | Partner" alt="Miembro del salón de la fama | Partner" id="display_0_24bce446ab7df8" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/partner-color.svg"/> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 2.036"> 2036 </td></tr><tr class="lia-list-row lia-row-even"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-363300 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8_0" href="/t5/user/viewprofilepage/user-id/363300"><img class="lia-user-avatar-message" title="Jnix284" alt="Jnix284" id="display_24bce446ab7df8_0" src="/t5/image/serverpage/image-id/63384iEE9BBBF006FB1880/image-dimensions/38x38/image-coordinates/0%2C0%2C400%2C400?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Hall-of-Famer"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de Jnix284" itemprop="url" id="link_24bce446ab7df8_1" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/363300"><span class="">Jnix284</span></a> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 715"> 715 </td></tr><tr class="lia-list-row lia-row-odd"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-640 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8_1" href="/t5/user/viewprofilepage/user-id/640"><img class="lia-user-avatar-message" title="Lucila-Andimol" alt="Lucila-Andimol" id="display_24bce446ab7df8_1" src="/t5/image/serverpage/image-id/51165iEDCBDF635B851437/image-dimensions/38x38/image-coordinates/769%2C0%2C3086%2C2317?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Thought-Leader---Platinum-Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de Lucila-Andimol" itemprop="url" id="link_24bce446ab7df8_2" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/640"><span class="">Lucila-Andimol</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Líder intelectual | Partner nivel Platinum" alt="Líder intelectual | Partner nivel Platinum" id="display_0_24bce446ab7df8_0" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/platinum-color.svg"/> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 273"> 273 </td></tr><tr class="lia-list-row lia-row-even"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-141 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8_2" href="/t5/user/viewprofilepage/user-id/141"><img class="lia-user-avatar-message" title="TomM2" alt="TomM2" id="display_24bce446ab7df8_2" src="/t5/image/serverpage/image-id/85434iB7C5AAFDC991A8DE/image-dimensions/38x38/image-coordinates/0%2C204%2C1232%2C1436?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Thought-Leader---Platinum-Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de TomM2" itemprop="url" id="link_24bce446ab7df8_3" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/141"><span class="">TomM2</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Líder intelectual | Partner nivel Platinum" alt="Líder intelectual | Partner nivel Platinum" id="display_0_24bce446ab7df8_1" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/platinum-color.svg"/> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 232"> 232 </td></tr><tr class="lia-list-row lia-row-odd"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-87451 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8_3" href="/t5/user/viewprofilepage/user-id/87451"><img class="lia-user-avatar-message" title="Ben_M" alt="Ben_M" id="display_24bce446ab7df8_3" src="/t5/image/serverpage/avatar-name/suv/avatar-theme/candy/avatar-collection/transit/avatar-display-size/message/version/2?xdesc=1.0"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Key-Advisor"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de Ben_M" itemprop="url" id="link_24bce446ab7df8_4" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/87451"><span class="">Ben_M</span></a> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 171"> 171 </td></tr><tr class="lia-list-row lia-row-even"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-781425 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8_4" href="/t5/user/viewprofilepage/user-id/781425"><img class="lia-user-avatar-message" title="Gaurav_Aggarwal" alt="Gaurav_Aggarwal" id="display_24bce446ab7df8_4" src="/t5/image/serverpage/image-id/121558iBA0D96D36ABB09C4/image-dimensions/38x38/image-coordinates/0%2C0%2C340%2C340?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Key-Advisor---Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de Gaurav_Aggarwal" itemprop="url" id="link_24bce446ab7df8_5" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/781425"><span class="">Gaurav_Aggarwal</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Asesor destacado | Partner" alt="Asesor destacado | Partner" id="display_0_24bce446ab7df8_2" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/partner-color.svg"/> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 152"> 152 </td></tr><tr class="lia-list-row lia-row-odd"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-73173 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8_5" href="/t5/user/viewprofilepage/user-id/73173"><img class="lia-user-avatar-message" title="franksteiner79" alt="franksteiner79" id="display_24bce446ab7df8_5" src="/t5/image/serverpage/image-id/17243i5D1F32478A522B19/image-dimensions/38x38/image-coordinates/320%2C0%2C1600%2C1280?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Key-Advisor"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de franksteiner79" itemprop="url" id="link_24bce446ab7df8_6" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/73173"><span class="">franksteiner79</span></a> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 148"> 148 </td></tr><tr class="lia-list-row lia-row-even t-last"><td class="userColumn lia-data-cell-primary lia-data-cell-text"> <div class="UserProfileSummary lia-user-item lia-js-data-userId-346639 lia-user-info-group"> <div class="UserAvatar lia-user-avatar lia-component-common-widget-user-avatar"> <a class="UserAvatar lia-link-navigation" tabindex="-1" target="_self" id="link_1_24bce446ab7df8_6" href="/t5/user/viewprofilepage/user-id/346639"><img class="lia-user-avatar-message" title="GRajput" alt="GRajput" id="display_24bce446ab7df8_6" src="/t5/image/serverpage/image-id/94960iD89D3FDEC001CBFE/image-dimensions/38x38/image-coordinates/96%2C48%2C1010%2C961?v=v2"/> </a> </div> <div class="lia-user-attributes"> <div class="lia-user-name"> <span class="UserName lia-user-name lia-user-rank-Recognized-Expert---Platinum-Partner"> <a class="lia-link-navigation lia-page-link lia-user-name-link" style="" target="_self" aria-label="Ver el perfil de GRajput" itemprop="url" id="link_24bce446ab7df8_7" href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/346639"><span class="">GRajput</span></a> <img class="lia-user-rank-icon lia-user-rank-icon-right" title="Experto reconocido | Partner nivel Platinum" alt="Experto reconocido | Partner nivel Platinum" id="display_0_24bce446ab7df8_3" src="https://cdn2.hubspot.net/hubfs/53/Partners%20Redesign%202019/Agencies/tag-icons/platinum-color.svg"/> </span> </div> </div> </div> </td><td class="acceptedSolutionsCountColumn lia-data-cell-tertiary lia-data-cell-integer" aria-label="Número de soluciones aceptadas: 137"> 137 </td></tr> </tbody> </table> </div> </div> <div class="lia-view-all"><a class="lia-link-navigation" id="link_24bce446ab7df8_8" href="/t5/solutions/acceptedsolutionsleaderboardpage/node-display-id/community%3Amjmao93648/timerange/six_months">Ver todo</a></div> </div></div></div></div><div class="lia-decoration-border-bottom"><div> </div></div></div></div> </div> </div> --> </div> </div> </div> </div> </div> </div> <div class="custom-home-banner-section v3 custom-get-experience"> <div class="custom-home-banner-section__wrapper wrapper-container"> <div class="custom-home-banner-section__header"> <h2>Beneficiate de toda la experiencia de la Comunidad de HubSpot.</h2> </div> <div class="custom-home-banner-section__cards"> <div class="card-item"> <div class="card-item__icon"><img src="/html/assets/announcement.svg"></div> <a href = " https://community.hubspot.com/t5/Advocacy/ct-p/advocacy "><h4 class="card-item__head">HubFans</h4></a> <p class="card-item__desc">Gana puntos e insignias compartiendo tu amor por HubSpot y ayudando a otros. <span><a href="/t5/Advocacy/ct-p/advocacy">Más información</a></span></p> </div> <div class="card-item"> <div class="card-item__icon"><img src="/html/assets/People (1).svg"></div> <a href = "https://www.hubspot.com/hubspot-user-groups# "><h4 class="card-item__head">Grupos de usuarios de HubSpot (HUG)</h4></a> <p class="card-item__desc">Únete a un grupo de usuarios de HubSpot para conectar con entusiastas de HubSpot con ideas afines y conocer los próximos eventos. <span><a href="https://www.hubspot.com/hubspot-user-groups#">Más información</a></span></p> </div> <div class="card-item"> <div class="card-item__icon"><img src="/html/assets/Solutions Directory.svg"></div> <a href = " https://www.hubspot.es/partners/solutions?__hstc=20629287.c495cc43fe21e0acc5341a34ea19f39d.1626187141364.1634739498973.1641826015645.40&__hssc=20629287.10.1641826015645&__hsfp=2648115164&_ga=2.256009803.1369406416.1641810162-1668693059.1612523514 "><h4 class="card-item__head">Solutions Partner Program</h4></a> <p class="card-item__desc">Conecta con otros partners y conoce los programas para partners de HubSpot. <span><a href="https://www.hubspot.es/partners/solutions?__hstc=20629287.c495cc43fe21e0acc5341a34ea19f39d.1626187141364.1634739498973.1641826015645.40&__hssc=20629287.10.1641826015645&__hsfp=2648115164&_ga=2.256009803.1369406416.1641810162-1668693059.1612523514 ">Más información</a></span></p> </div> <div class="card-item"> <div class="card-item__icon"><img src="/html/assets/Availability.svg"></div> <a href = ""><h4 class="card-item__head">Conversaciones</h4></a> <p class="card-item__desc">Regístrate para participar en conversaciones sobre estrategia y productos con otros profesionales. </p> </div> </div> <div class="custom-home-banner-section__join-btn"> <a href="https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2Fcommunity.hubspot.com%2F">Únete a la Comunidad</a> </div> </div> </div> </div> </div> </div><div class="lia-quilt-row lia-quilt-row-footer"> <div class="lia-quilt-column lia-quilt-column-24 lia-quilt-column-single lia-quilt-column-common-footer"> <div class="lia-quilt-column-alley lia-quilt-column-alley-single"> <!-- FOOTER START --> <footer class="community-footer"> <div class="community-footer-wrapper template-centered"> <div class="footer-responsive"> <div class="contain-top"> <div class="col"> <h5>HubSpot</h5> <ul> <li><a href="https://www.hubspot.es/?__hstc=20629287.c495cc43fe21e0acc5341a34ea19f39d.1626187141364.1634739498973.1641826015645.40&__hssc=20629287.71.1643795059694&__hsfp=4237209502&_ga=2.78974353.464296981.1643621446-1668693059.1612523514">Home</a></li> <li><a href="https://help.hubspot.com/es/">Centro de Ayuda</a></li> <li><a href="https://academy.hubspot.com/es/">Academy en Español</a></li> <li><a href="https://knowledge.hubspot.com/es">Base de Conocimientos</a></li> <li><a href="https://ecosystem.hubspot.com/es/marketplace/solutions">Solutions Directory</a></li> <li><a href="https://blog.hubspot.es/">Blog</a></li> </ul> </div> <div class="col"> <h5>Participa</h5> <ul> <li><a href= "https://offers.hubspot.com/community-champions" class=" in-english">Community Champions</a> </li> <li><a href= "https://www.hubspot.com/hubspot-user-groups" class="">HubSpot User Groups</a></li> <li><a href= "https://www.hubspot.com/partners/solutions" class="">Solutions Partner Program</a></li> <li><a href= "https://www.hubspot.com/community-newsletter" class=" in-english">Community Newsletter</a></li> </ul> </div> <div class="col"> <h5>Comunidad</h5> <ul> <li><a href= "https://community.hubspot.com/t5/Foro-de-CRM-y-Sales-Hub/ct-p/crm_sales_hub_es">CRM & Sales</a></li> <li><a href= "https://community.hubspot.com/t5/Foro-de-Marketing-Hub/ct-p/marketing_hub_es">Marketing</a></li> <li><a href= "https://community.hubspot.com/t5/Foro-de-Service-Hub/ct-p/service_hub_es">Service</a></li> <li><a href= "https://community.hubspot.com/t5/Operaciones-y-gesti%C3%B3n-de/ct-p/operations_es">Operaciones y gestión de ingresos</a></li> <li><a href= "https://community.hubspot.com/t5/HubSpot-Developers/ct-p/developers" class=" in-english">Desarrolladores de HubSpot</a></li> <li><a href= "https://community.hubspot.com/t5/Getting-Started-on-the-Community/How-to-join-the-Solutions-Partner-Program/ba-p/400205" class=" in-english">Solutions Partner Program</a></li> </ul> </div> <div class="col"> <ul> <li><a href= "https://community.hubspot.com/t5/HubSpot-Academy-en-Espa%C3%B1ol/ct-p/Academy_es">Academy</a></li> <li><a href= "https://community.hubspot.com/t5/Groups/ct-p/groups">Todos los Grupos</a></li> <li><a href= "https://community.hubspot.com/t5/Advocacy/ct-p/advocacy" class=" in-english">Advocacy</a></li> <li><a href= "/t5/HubSpot-Ideas/idb-p/HubSpot_Ideas" class=" in-english">Ideas</a></li> </ul> </div> </div> <div class="contain-top-two"> <hr class="seperator"> </div> </div> <div class="footer-main-two"> <div class="footer-copywrite-container"> <a href="/" id="footer-logo" class="footer-wordmark"> <img src="https://community.hubspot.com/html/@B5A74D0D426EC31D4B4C76F0526FF1E5/assets/HS_Logo_Wordmark-White.svg" alt="hubspot"> </a> <span id="copywrite">Copyright © 2024 HubSpot, Inc.</span> </div> <div class="footer-links-container"> <ul class="footer-link"> <li> <a href="https://legal.hubspot.com/es/privacy-policy" class="footer-terms">Política de Privacidad</a> </li> <li> <a href="https://legal.hubspot.com/es/community-tou" class="footer-privacy">Términos de Uso de la Comunidad de HubSpot</a> </li> <li> <a href="https://community.hubspot.com/t5/Pautas-y-anuncios/Gu%C3%ADa-de-Uso-de-la-Comunidad-de-HubSpot/m-p/268792#M1" class="footer-guidelines">Guía de Uso de la Comunidad</a> </li> <li> <a href="https://status.hubspot.com/" class="footer-status">Status</a> </li> <li> <a href="https://legal.hubspot.com/digital-services-act" class="footer-dsa">DSA Statement</a> </li> <li class="hs-footer-cookie-settings footer-cookie-settings" hidden> <a href=""></a> </li> </ul> </div> </div> </div> </footer> </div> </div> </div> </div> </div> </div> </div> </div> <script> document.cookie = "Crowdvocate_user_ck=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; //console.log('deleting cookie for logged out case'); //console.log('is cookie set? '+ getCookie('Crowdvocate_user_ck')); </script> <!-- Start HubSpot SDK Script --> <script>window.acsdk = {cid: 'WSUMXJFRDOXTWNTJ8YKRUEQ6GHNP1UAUP9EA', params: {popupDelay: 10, position: [0, 20, 50, 0, 0]}};</script> <script>(function(){var w=window;var ac=w.Crowdvocate;if(typeof ac==="function"){ac('init',w.acsdk);}else{var a=function(){a.c(arguments)};a.q=[];a.c=function(args){a.q.push(args)};w.Crowdvocate=a;} var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src='https://d29zub39v1xeg4.cloudfront.net/api/v1/sdk.js';var x=document.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);})();</script> <!-- End of HubSpot SDK Script --> </center> </div> <script type="text/javascript"> new Image().src = ["/","b","e","a","c","o","n","/","1","2","5","9","0","2","5","0","9","5","0","6","_","1","7","3","2","7","8","6","6","4","5","8","6","6",".","g","i","f"].join(""); </script> <script type="text/javascript" src="/t5/scripts/8016E4FC3B23A5110FC1769E8A07C73D/lia-scripts-common-min.js"></script><script type="text/javascript" src="/t5/scripts/B1F5AEA9EDE360355D99A0C0F7016E3B/lia-scripts-body-min.js"></script><script language="javascript" type="text/javascript"> <!-- LITHIUM.Sandbox.restore(); LITHIUM.jQuery.fn.cssData.defaults = {"dataPrefix":"lia-js-data","pairDelimeter":"-","prefixDelimeter":"-"}; (function($){ jQuery(document).on('click', '#hs-eu-confirmation-button', function() { location.reload(); }); })(LITHIUM.jQuery); LITHIUM.CommunityJsonObject.User.policies['forums.action.message-view.batch-messages.allow'] = false; // <script> // $ prefix because 'core' is kinda prone to conflict with other stuff that might define a variable 'core' // If there are issues with markup_output (on communities that have auto-escaping enabled!) you can add // ?no_esc behind the expression, but can't have that conditionally there because FreeMarker will just throw // an exception just because the built in is in the code if auto-escaping is disabled... var $core = { config: {"initialized" : true,"debug" : false,"devmode" : false,"env" : "prod","context" : "component","versions" : {"lithium" : 24.8,"freemarker" : "2.3.26-incubating","core.component" : 23.8,"core.users" : 23.5,"core" : 23.4},"file" : "core.cmp.noscript","output" : "undefined","locale" : {"charset" : "UTF-8","timezone" : "US/Eastern","format" : {"date" : "MMM d, yyyy","time" : "h:mm a","full" : "MMM d, yyyy h:mm a","relative" : true,"cutoff" : 31}},"lang" : "en","langs" : ["en","de","es","fr","ja","pt-br"],"node" : {"id" : "mjmao93648","uid" : 1,"lang" : "en","type" : "community","style" : "none","url" : "https://community.hubspot.com/","quilt" : "CommunityPage","skin" : "hubspot","path" : "\/","top" : "\/categories/id/mjmao93648","settings_key" : "config_node"},"user" : {"admin" : false,"mod" : false,"auth" : false,"device" : "desktop","lang" : "en","registered" : false,"roles" : [],"show_text_keys" : false,"settings_key" : "config_user","settings" : {}},"cache" : {"cached" : false,"type" : "","map" : {},"config" : {"usercache" : {"inactiveTime" : 1200000,"maximumTime" : 7200000,"maxSize" : 10000},"appcache" : {"inactiveTime" : 1200000,"maximumTime" : 7200000,"maxSize" : 10000}}},"modules" : {"api" : false,"community" : false,"component" : true,"nodes" : false,"templates" : false,"users" : true},"ids" : {"lang" : {"en" : "hubspot_community_en","de" : "hubspot_community_de","es" : "hubspot_community_es","fr" : "hubspot_community_fr","ja" : "hubspot_community_jp","pt" : "hubspot_community_pt"}},"request" : {"get" : "","uri" : "https://community.hubspot.com/?profile.language=es","type" : "GET","https" : true,"options" : {},"context" : "","endpoint" : "https://community.hubspot.com/mjmao93648/plugins/custom/hubspot/hubspot/controller"},"rest_default_version" : 1,"rest_base_url_v1" : "https://community.hubspot.com/restapi/v1","rest_base_url_v2" : "https://community.hubspot.com/api/2.0/search?q=","stats" : {"requests" : 0,"total" : 0,"calls" : []},"logs" : []}, properties: {}, // Add a reference to the global (native) JS object for the community, can be useful lithium: LITHIUM?.CommunityJsonObject, version: LITHIUM?.CommunityJsonObject?.Config?.['app.revision'] || null }; // </script> // <script> just for inline syntax-highlighting... ;(function($){ var tools = { admin: { /** /* By default admin/studio pages all have the same page title "Community Settings" which is extermely unhelpful /* when having 10 admin/studio tabs open and then having to cycle through them just to find the right one. /* This fix makes admin/studio tabs more distinguishable. /*/ fixStudioTitle: function() { var title = [ $('.lia-bizapps-tab-studio-tab-group .lia-tabs-active').text(), $('.lia-bizapps-tab-community-tab-group .lia-tabs-active').text(), $('.lia-bizapps-page-title-community').text(), ]; $('title').text(title.join(' - ')); }, /** /* In multi-language communities it can be difficult to distinguish nodes if they all have the same title but another language. /* Usually we add a language suffix to the node ID but that is not easily visible in the community structure. Thea idea of this /* enhancement is to extract that language suffix from the node id and add it to the node title within the community structure. /*/ structureAddLanguageFromID: function(validLanguages = ['de', 'fr', 'it', 'jp', 'en', 'es', 'pt']) { $('.lia-component-admin-widget-node-editor-tree .lia-list-tree-toggle-node').each(function() { var $listitem = $(this); var $title = $listitem.find('span.lia-node-display-node-title:first'); var id = $listitem.find('.manage-node-link').first().prop('href').split('_').pop().trim().toLowerCase(); // console.log(id); if ( validLanguages.includes(id) ) { $title.text($title.text() + ' (' + id.toUpperCase() + ')'); } }); }, }, dom: function() { /** /* Just a little clutter saver for components. We should specify both aria-label and title /* attributes, but doing so can lead to very messy markup. As aria-label is more important /* devs have the option of simply adding an empty title attribute as well to elements which /* have aria-label already. This little tool will look for those and simply copy the aria-label /* text over to the title attribute so mouse-users can also get the hints as tooltips. /*/ $('[aria-label][title=""]').each(function() { $(this).attr('title', $(this).attr('aria-label')); }); /** /* A 'big-target' implementation I came up with using a `data-target` attribute on the actual link. /*/ (function(attr = 'data-target') { document.querySelectorAll(`a[${attr}]`).forEach(link => { //console.log('handling big target', link); let trigger = link.parentNode; const selector = link?.getAttribute(attr); while (trigger && trigger !== document) { if ( (!selector || trigger.matches(selector)) && !trigger.matches('[data-edit], [data-bind]') ) { trigger.style.cursor = 'pointer'; trigger.querySelectorAll('a').forEach(link => link.addEventListener('click', (e) => e.stopPropagation())); trigger.addEventListener('click', (e) => (!window.getSelection().toString() && link.click())); break; } trigger = trigger.parentNode; } }); })(); }, installKV: function() { /** /* Creates a Deno KV-like key-value store based on the localStorage with optional /* (custom) versioning and migration support. /* This has passed basic testing, although not how well it aligns with what native Deno KV does itself! /* The API is the same minus atomic operations and some options like consistency level, Kv64 etc. /* that don't really make sense or are insanely complex or impossible to do with a synchronous /* API like localStorage is. The KV's methods are all fake async (because Deno KV's api is async) /* so code written and used in the browser with this implementation should (hopefully) work /* with Deno KV on the server side as well (muuuch more testing needed to confirm that)! /* Aside from `open()` and `close()` this implementation should cover the entire Deno KV API. /* /* There are of course differences in behavior you should be aware of if you build any logic around it: /* - The most important limitation with this mock is that if you use non-serializable values in /* in your keys (your values too!), it will not behave like you expect! Stick to types that can be /* serialized to JSON... localStorage can only handle strings, that's the reason. /* - With Deno KV you can pass an `expireIn` option, but the values you receive from `get()` /* will never return that expiration date. This implementation returns that information /* when querying a key, e.g. besides value and versionstamp you get back `expires` /* if a TTL was provided when setting the value, it's going to be an ISO timestamp otherwise `null`. /* - `list()` is an AsyncIterator like it is with Deno KV, but it does NOT support cursor, consistency /* or batchSize options, you can pass them to the method, but nothing will happen. /* Deno KV `list()` requires a selector, this implementation does not, it will simply list all /* KV entries if you don't provide a selector. /* Furthermore this `list()` implementation supports an optional 3rd argument which is a function /* passed to `Array.filter()` that allows filtering the returned entries further after selector(s) /* and options have been applied. /* - This implementation does support some features Deno KV does not have: /* 1. You can optionally provide a `version` function that will replace how the versionstamp is created /* and thus provide your own versioning implementation. /* 2. You can also provide a `migrate` function that will be applied if an outdated versionstamp /* is encountered, you can for example extend the old value with some new ones keeping what was stored. /* 3. There is a `toJSON()` method you can use to serialize either the entire KV store or a portion of it. /* It supports the same arguments as `list()` (because it internally calls it) and has options to /* serialize prettified JSON or streamable (individual store entries separated by newlines) JSON. /* /* @param {Function} [version] - Optional function to generate a versionstamp for stored values. /* @param {Function} [migrate] - Optional function to migrate outdated values. It is called with the key and outdated value and should return the migrated value. /* @param {String} [prefix='kv:'] - Prefix to be used for keys in localStorage, helping in namespacing and avoiding key conflicts. /* /* @returns {Object} - An object providing the mocked Deno KV API methods to interact with the store. /*/ Object.defineProperties(window, { $kv: { value: function(version, migrate, prefix = 'kv:') { const $hash = typeof version === 'function' ? version : ( $hash || ((v) => 1) ); const _queueListeners = new Set(); const _key = { inrange: (key, start, end) => { const orderedKey = _key.order(key); const orderedStart = start ? _key.order(start) : null; const orderedEnd = end ? _key.order(end) : null; if (orderedStart && orderedKey < orderedStart) { return false; } if (orderedEnd && orderedKey >= orderedEnd) { return false; } return true; }, order: (key) => key.slice().sort((a, b) => { const order = ['Uint8Array', 'string', 'number', 'bigint', 'boolean']; const typeA = typeof a, typeB = typeof b; return typeA === typeB ? (typeA === 'number' ? a - b : String(a).localeCompare(String(b))) : order.indexOf(typeA) - order.indexOf(typeB); }), // Check how Deno KV actually does it here: // https://github.com/denoland/deno/blob/main/ext/kv/codec.rs serialize: (key) => prefix + JSON.stringify(key), deserialize: (serializedKey) => JSON.parse(serializedKey.substring(prefix.length)) }; return { /** /* Retrieves a value from the store by its key(s). /* /* @param {Array} key - The keys array to look up the value. /* /* @returns {Promise<Object>} - An object containing the key, its associated value, versionstamp and expiry. /*/ get: async (key) => { const serializedKey = _key.serialize(key); const data = JSON.parse(localStorage.getItem(serializedKey)); if ( !data || (data.expires && new Date(data.expires) < new Date()) ) { data && data.expires && localStorage.removeItem(serializedKey); return { key, value: null, versionstamp: null }; } if ( data.versionstamp !== $hash(data.value) ) { if (typeof migrate === 'function') { data.value = await migrate(key, data.value); data.versionstamp = $hash(data.value); localStorage.setItem(serializedKey, JSON.stringify(data)); } else { console.warn('Outdated value found but no migration function defined!', key, data); } } return { key, ...data }; }, /** /* Retrieves multiple values from the store based on the provided keys. /* /* @param {Array<Array>} keys - An array of key arrays to look up the values. /* /* @returns {Promise<Array<Object>>} - An array of objects. /*/ getMany: async function(keys) { return Promise.all(keys.map(key => this.get(key))) }, /** /* Stores a value in the store with the given key. /* /* @param {Array} key - The key array to associate with the value. /* @param {*} value - The value to be stored. /* @param {Object} [options] - Optional parameters for storing the value. `expireIn` sets the expiration time in milliseconds. /* /* @returns {Promise<Object>} - An object indicating the success and the versionstamp of the stored value. /*/ set: async (key, value, options = {}) => { const data = { value, versionstamp: $hash(value), expires: options.expireIn ? new Date(Date.now() + options.expireIn).toISOString() : null }; localStorage.setItem(_key.serialize(key), JSON.stringify(data)); return { ok: true, versionstamp: data.versionstamp }; }, /** /* Removes a value from the store by its key. /* /* @param {Array} key - The key array of the value to be removed. /*/ delete: async (key) => localStorage.removeItem(_key.serialize(key)), /** /* Iterates over values in the store based on the provided selector prefix, range, or limited by options. /* This method provides an AsyncIterator to be used with `for await...of` loops. /* This `list()` implementation supports an additional third argument which is NOT STANDARD for Deno KV. /* It's a function that allows for further filtering the results before yielding them within the iterator. /* /* The selector can either be a prefix selector or a range selector: /* - A prefix selector selects all keys that start with the given prefix (optionally starting at a given key). /* - A range selector selects all keys that are lexicographically between the given start and end keys. /* /* @param {Object} [selector] - The selection criteria. NOT STANDARD: Can be undefined here, not with Deno KV! /* @property {Array} [selector.prefix] - Defines the prefix for filtering the results. /* @property {Array} [selector.start] - The starting key for range selection. /* @property {Array} [selector.end] - The ending key for range selection. /* @param {Object} [options] - Optional parameters for the listing. /* @property {number} [options.limit] - Limits the number of results. /* @property {boolean} [options.reverse] - If true, reverses the order of results. /* @param {Function} [fn] - NON STANDARD: Optional filter function to filter entries before yielding. /* /* @returns {AsyncIterator} - An AsyncIterator yielding store entries. /*/ list: async function*(selector, options = {}, fn) { const keys = options?.reverse ? Object.keys(localStorage).reverse() : Object.keys(localStorage); for (const serializedKey of keys) { // Limit results based on `options.limit` if ( options?.limit !== undefined && options.limit <= 0 ) { break; } if ( !serializedKey.startsWith(prefix) ) { continue; }; const deserializedKey = _key.deserialize(serializedKey); if ( selector?.prefix && !deserializedKey.slice(0, selector.prefix.length).every((part, index) => part === selector.prefix[index]) ) { continue; } if ( selector?.start && !_key.inrange(deserializedKey, selector?.start, selector?.end) ) { continue; } const entry = await this.get(deserializedKey); if ( entry.value !== null ) { if ( !fn || (typeof fn === 'function' && fn(entry)) ) { if ( options?.limit !== undefined ) { options.limit--; } yield entry; } } } }, /** /* Adds a value into a mock database queue to be delivered to queue listeners. /* This method simulates the behavior of the Deno KV's enqueue(). /* `keysIfUndelivered` option is not supported, you can pass it, but won't have an effect. /* /* @param {*} value - The value to be enqueued. /* @param {Object} [options] - Optional settings for the enqueue operation. /* @param {number} [options.delay] - Delays the delivery of the value by the specified number of milliseconds. /* @returns {Promise<Object>} - An object indicating the success of the enqueue operation. /*/ enqueue: async (value, options) => { for (const fn of _queueListeners) { options?.delay && await (new Promise(res => setTimeout(res, options.delay))); await fn(value); }; }, /** /* Listens for queue values to be delivered from the mock database queue. /* This method simulates the behavior of the Deno KV's listenQueue(). /* /* @param {Function} handler - A callback function that gets when a new value is dequeued. /* /* @returns {Promise<void>} /*/ listenQueue: async (handler) => { if ( !_queueListeners.has(handler) ) { _queueListeners.add(handler) } }, /** /* Provides a mock for Deno Kv's AtomicOperation API with the same chainable methods, but /* they do nothing...you can provide a function to each of the mock methods that receives /* `this`, just return it again, otherwise you break the chaining! Something like this: /* /* @example /* ``` /* (await $core.kv().atomic()).check((t) => (console.log('check'), t)).min((t) => (console.log('min'), t)).commit(); /* // you can pass an arbitrary number of additional args to those mock functions, like /* (await $core.kv().atomic()).check((t, arg1, arg2) => (console.log('check', arg1, arg2), t), 'foo', 'var') /* ``` /* /* @returns {Promise<*>} - A mocked API of Deno KV's atomic(). /*/ atomic: async () => { console.warn('Atomic ops are not supported!'); return [ 'check', 'commit', 'delete', 'enqueue', 'max', 'min', 'mutate', 'set', 'sum' ].reduce((r, m) => (r[m] = function(fn, ...args) { return typeof fn === 'function' ? fn(this, ...args) : this }, r), Object.create(null)); }, /** /* NON STANDARD: Serializes the store to a JSON string. /* The methods first 3 arguments match the ones from list() (see there for details). /* /* @param {Object} selector - The selection criteria for list(). /* @param {Object} [options] - Optional parameters for list(). /* @param {Function} [fn] - Optional filter function list(). /* @param {Number|String} [pretty] - JSON.stringify() space param to prettify output. Defatuls to tab indent. /* @param {Boolean} [streamable] - If the output should be stringified entries separated by newlilnes. /* /* @returns {String} - A JSON string representation of the KV store. /*/ toJSON: async function(selector, options, fn, pretty = '\t', streamable = false) { let data = []; for await (const entry of this.list(selector, options, fn)) { data.push(entry); } data = data.reduce((r, entry) => { if ( streamable ) { r.push(JSON.stringify({ key: entry.key, value: entry.value })); return r; } return r[JSON.stringify(entry.key)] = entry.value, r; }, streamable ? [] : {}); return streamable ? data.join('\n') : JSON.stringify(data, null, pretty); }, }; }, configurable: false, // Cannot be deleted enumerable: false, // Will not show up in loops writable: false, // Cannot be overwritten } }); }, logMeIn: function() { /** /* Enable 'magic' redirect to login page when "logmein" is typed into the void =) /* just for convenience and speed, only useful on stage if SSO is activated for the community /*/ var keycodes = { logmein: [76, 79, 71, 77, 69, 73, 78], listudio: [], liadmin: [] }; var neededkeys = [76, 79, 71, 77, 69, 73, 78]; var watching = false; var count = 0; $(document).keydown(function(e) { var key = e.keyCode; // console.log(key); // Set start to true only if the first key in the sequence is pressed if ( !watching ) { if ( key == neededkeys[0] ) { watching = true; } } // If watching, pay attention to key presses, looking for right sequence. if ( watching ) { // console.log('watching: ' + key); if ( neededkeys[count] == key ) { // We're good so far. count++; } else { // Oops, not the right sequence, lets restart from the top. watching = false; count = 0; return; } if ( count == neededkeys.length ) { // We made it! Execute whatever should happen when entering the right sequence window.location.replace('/t5/user/userloginpage'); // Reset the conditions so that someone can do it all again. watching = false; count = 0; return; } } else { // Oops. watching = false; count = 0; return; } }); }, scssCompile: function() { /** /* Handle on-the-fly SCSS compilation if any text/scss inline style tags are found /* This primarily useful for development, no style/scss tags should remain when on /* production as they would still be compiled. /*/ if ( $('style[type$="scss"]').length ) { $('style[type$="scss"]').each(function() { var $el = $(this); var scss = $el.text(); $core?.config?.user?.admin && console.log('Found inline SCSS style tag, compiling to CSS...', $el); $.ajax({ type: 'POST', url: 'https://www.sassmeister.com/app/lib/compile', data: { input: scss, compiler: 'lib', syntax: 'scss', original_syntax: 'scss', output_style: 'nested' }, contentType: 'multipart/form-data', dataType: 'json' }) .done(function(response) { $core?.config?.user?.admin && console.log('core.cmp.tools: SCSS successfully compiled, injecting usable CSS...'); // inject compiled CSS into irignal source tag $el.text(response.css).attr('type', 'text/css'); }) .fail(function(err) { console.log('fail', err); }); }); } }, redirect: function() { /** /* Handles redirects specified in `cmp.global.scripts` (or elsewhere) and added to /* the `$core.redirects` object. /*/ if ( $core?.redirects ) { Object.entries($core.redirects).some(function([source, target]) { if ( window.location.pathname === source ) { $core?.config?.user?.admin && console.log('core.cmp.tools: redirect match found, redirecting...'); window.location.href = target; // Stop the .some() iteration by returning true return true; } }); } }, fixAmp: function() { /** /* Handle & ampersand bug in SEO field of ArticleEditorPage (TKB, more?) /* & gets replace with & but each time the article is saved again, the & of the & /* gets encoded again, resulting in repeated and invalid encoding, e.g. &amp;amp;amp;amp; /*/ $('.lia-form-message-seo-description-input, .lia-form-message-seo-title-input').each(function() { $(this).val($(this).val().replaceAll(/amp;/gm, '')); }); }, fixTOC: function() { /** /* Adds 'is--toc' class to `ul`-tag of BlogArticle TOC (table of contents, an Angular component by Khoros) /* as it natively does not have any identifier, making it tricky to target with CSS /* WebKit browsers remove list semantics when list-style-type is none, we fix that with `role=list` /*/ $('.BlogArticlePage a[href*="#toc-hId"]').first().parents('ul').addClass('is--toc').attr('role', 'list'); }, inview: function() { // Make sure nothing explodes in older browsers that do not support IntersectionObserver if ( 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype ) { // Minimal polyfill for Edge 15's lack of `isIntersecting` // See: https://github.com/w3c/IntersectionObserver/issues/211 if ( !('isIntersecting' in window.IntersectionObserverEntry.prototype) ) { Object.defineProperty(window.IntersectionObserverEntry.prototype, 'isIntersecting', { get: function () { return this.intersectionRatio > 0; } }); } // Set up the intersection observer const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { // If the element is fully in view, trigger custom event with jQuery if (entry.isIntersecting && entry.intersectionRatio === 1) { entry.target.dataset.inview = 'true'; $(document).trigger('inview', [entry.target]); } else if ( entry.target.dataset.inview !== 'false' ) { entry.target.dataset.inview = 'false'; } }); }, { threshold: 1 }); // Observe each element with attribute `data-inview` $('[data-inview]').each(function() { observer.observe(this); }); } }, XHRmiddleware: function() { // Middleware storage const middlewares = []; // Override the XMLHttpRequest constructor (breaks Khoros for some reason...) /* const xhrRequest = XMLHttpRequest; XMLHttpRequest = function() { const xhr = new xhrRequest(); return new Proxy(xhr, { get: function(target, prop) { // You can intercept specific properties here and provide custom values if ( prop === 'responseText' ) { let value = target[prop]; middlewares.forEach((fn) => { if ( !fn.on || fn.on.includes('response') { // make sure in case the dev forgets to return from the fn() // we still return a value, it's gonna be the unmodified one // but better than nothing... value = fn(target, 'response', value) || value; } }); return value; } // For all other properties, return the original value return target[prop]; }, set: function(target, prop, value) { target[prop] = value; return true; } }); }; XMLHttpRequest.prototype = xhrRequest.prototype; */ // Save original XHR methods const xhrSend = XMLHttpRequest.prototype.send; const xhrOpen = XMLHttpRequest.prototype.open; // Define the .$use() method using Object.defineProperty Object.defineProperty(XMLHttpRequest, '$use', { value: function(fn) { if ( typeof fn === 'function' ) { middlewares.push(fn); } }, writable: false, // Cannot be overwritten enumerable: false, // Will not show up in loops configurable: false, // Cannot be deleted }); // Override the .open() method XMLHttpRequest.prototype.open = function(method, url, async, user, password) { middlewares.forEach((fn) => { !fn.on || fn.on.includes('open') ? fn(this, 'open', method, url, async, user, password) : null; }); xhrOpen.apply(this, arguments); }; // Override the .send() method XMLHttpRequest.prototype.send = function(body) { const xhr = this; middlewares.forEach((fn) => { !fn.on || fn.on.includes('send') ? fn(xhr, 'send', body) : null; }); // Attach an event listener for the 'readystatechange' event xhr.addEventListener('readystatechange', function() { if ( xhr.readyState === XMLHttpRequest.DONE ) { middlewares.forEach((fn) => { !fn.on || fn.on.includes('done') ? fn(xhr, 'done') : null; }); } }); xhrSend.apply(this, arguments); }; // Example middleware /* XMLHttpRequest.$use((xhr, event, ...args) => { if ( event === 'open' ) { // args is going to be [method, url, async, user, password] if defined console.log('Request created:', xhr, ...args); } else if ( event === 'send' ) { // args is going to be [body] the optional payload/body of the request console.log('Request payload is about to be sent:', args[0]); } else if ( event === 'response' ) { // args is going to be [responseText]! console.log('Can modify response text!, xhr); // IMPORTANT: Return something from here, // otherwise response is gonna be returned umodified to the caller! return xhr; } else if ( event === 'done' ) { console.log('Response received:', xhr.responseText); } }); */ }, }; // Install tools before extending core in case we need access to globally defined tools! Object.entries(tools).map(function([name, fn]) { if ( typeof fn === 'function' ) { $core?.config?.user?.admin && console.info(`core.cmp.tools: Running tools.${name}()`); fn(); } }); // Extend $core base variable with additional capabilities if ( $core ) { /** /* Helper method to automatically proxy requests to external URL's through the proxy endpoint /* when they can't be requested directly via JS due to CORS restrictions. /*/ $core.compile = async function(mount) { console.time("compiling"); // start benchmark // Handles inline tag definitions and script-linked tags with `[type="riot/tag"]`. // Why not go with the native riot.compile()? a) we want to check first if we actually // need to fetch the tag file or not (if it wasn't modified) and b) we want to compile // tags that are defined inline as well and cache the compiled result of both for faster // loading during prototyping. const usedb = true; const db = localStorage; const sources = Array.prototype.slice.call(document.querySelectorAll('script[type*="riot"]')).concat(Array.prototype.slice.call(document.querySelectorAll('template[type*="riot"]'))); const tags = await Promise.all( sources.map(async (el, i, arr) => { //console.log('compiling from:', el.hasAttribute('data-src') ? 'File' : 'Inline Template'); let cached; let hash; let tag; let response; if (el.hasAttribute('data-src')) { try { if ( usedb ) { // first we want to check the last modified header! // if the dev server is not running this will fail and enter catch block response = await fetch(el.getAttribute('data-src'), { // credentials: 'include', method: 'HEAD', }); // typecast to string for localStorage (keys are strings!) hash = `riot:${await $hash(el.getAttribute('data-src') + new Date(response.headers.get('last-modified')).getTime())}`; cached = db.getItem(hash); } if ( !cached ) { console.log('compile(): No cached version found, fetching source!'); response = await fetch(el.getAttribute('data-src'), { // credentials: 'include', method: 'GET', }); data = await response.json(); response = { headers: [...response.headers].reduce((acc, header) => { return { ...acc, [header[0]]: header[1] }; }, {}), status: response.status, data: data, }; //console.log('response', response); // add attribute data-scoped="false" to the include script tag to turn off CSS scoping //tag = riot.compileFromString(response.data, { scopedCss: !['false', '0', 0].includes(el.getAttribute('data-scoped')) }).code; // TODO: Dev server should return compiled code exactly as riot.deno.dev does tag = response.data?.code; //console.log('tag', tag); if ( tag && usedb ) { db.setItem(hash, tag); } console.log(`compile(): No cached tag found, file-tag compiled ${usedb ? `and cached with hash ${hash}`: ''}`); } else { tag = cached; console.log(`compile(): Found cached version of file-tag!`); } } catch (ex) { // We do not get details for net errors (e.g. if the server is down), so we try to // isolate those because they don't have a message (well, which ones do? custom ones?) if ( !ex.data?.message ) { console.warn(`compile(): fetching ${el.getAttribute('data-src')} failed: Dev server is not reachable...`); } else { console.error(ex); } } } // if `tag` is still undefined, we can assume the dev server wasn't running, // so we compile the content locally if ( !tag ) { // `.innerHTML` returns the 'fixed' (browser interpreted) HTML, but it will encode // `&` to `&`, also within riot expressions, which of course messes up the compiler // so once we have the tag html, we need to get those encoded ampersands back to normal tag = el.innerHTML.replace(/&/g, '&').trim(); if ( !tag ) { console.warn(`compile(): Tried to get content from inline tag, but was empty, did you forget to paste the component code in?`, el); return; } hash = `riot:${await $hash(tag)}`; cached = db.getItem(hash); if ( !cached ) { // add attribute data-scoped="false" to the template tag to turn off CSS scoping //tag = riot.compileFromString(tag, { scopedCss: !['false', '0', 0].includes(el.getAttribute('data-scoped')) }).code; try { response = await (await fetch('https://riot.deno.dev', { method: 'POST', body: JSON.stringify({ markup: encodeURIComponent(tag), versionstamp: await $hash(tag), key: await $hash(window.location.origin), }), headers: { 'content-type': 'application/json', }, })).json(); if ( response.code ) { tag = response.code; } else { console.error('compile(): Faulty response', response); if ( response.payload ) { console.warn('compile(): Creating downloadable file from failed component markup!'); const file = new File([response.payload.markup], 'failed.tag.html', { type: 'text/plain', }); const fr = new FileReader(); fr.onload = function(e) { const link = `<span class="compile-error">Download uncompilable markup: <a href="${URL.createObjectURL(file)}" download="${file.name}">${file.name}</a></span>`; $('body').append(link); } fr.readAsText(file); } throw new Error('compile(): response.code could not be found!', { cause: 'fetch()', message: response }); } } catch(ex) { console.error(ex); tag = null; } if ( tag && usedb ) { db.setItem(hash, tag); } console.log(`compile(): No cached tag found, inline-tag compiled ${usedb ? `and cached with hash ${hash}` : ''}`); } else { tag = cached; console.log(`compile(): Found cached version of inline-tag!`); } } try { const { groups: { name = null } } = tag.match(/^riot\.register\(['"](?<name>[^\s'"]+)/) || { groups: {} }; console.log('compile(): tag name = ', name); //riot.inject(tag, name, `./${name}.html`); // yeahyeah, eval is evil, but we are the author of the code, so nothing to worry... } catch (ex) { console.error('compile(): Something went wrong with tag name extraction', ex); } try { eval(tag); } catch(ex) { console.error(`compile(): Something went wrong with tag evaluation for '${name}'`, ex); } return { name: name, hash: hash, cached: cached !== null, code: tag }; }) ); console.log('compile(): result', tags); console.timeEnd('compiling'); // end benchmark // optionally mount tag(s) via the compile() method if ( typeof mount === 'string' ) { console.time('mounting'); riot.mount(mount); console.timeEnd('mounting'); } else if ( typeof mount === 'boolean' ) { // auto-mount all top level components, but not the nested ones, they will be handled by the parent riot.mount('[is]:not([is] [is])'); } }; /** /* Helper method to automatically proxy requests to external URL's through the proxy endpoint /* when they can't be requested directly via JS due to CORS restrictions. /* /* @usage `$core.fetch('<url>', {<fetch.options>});` /* /* @param {string} url - The URL to fetch via proxy. /* @param {object} options - An optional fetch options object. /* /* @returns {any} - The proxied response data. /*/ $core.fetch = function(url = '', options = {}, cache) { return fetch(`${$core.config.request.endpoint}?get=proxy&url=${encodeURIComponent(url)}${cache ? '&cache=' + cache : ''}`, options); }; $core.fmt = { /** /* Adapted from https://github.com/lukeed/tinydate/blob/master/src/index.js /* /* @usage `$core.fmt.date('Current time: [{HH}:{mm}:{ss}]')(new Date())` /* /* @param str - Output string with placeholders /* @param custom - Custom formatter functions for placeholders (optional) /* /* @return - Returns a rendering function that will optionally accept a date value as its only argument. /*/ date: function(str, custom) { const RGX = /([^{]*?)\w(?=\})/g; const MAP = { YYYY: 'getFullYear', YY: 'getYear', MM: function (d) { return d.getMonth() + 1; }, DD: 'getDate', HH: 'getHours', mm: 'getMinutes', ss: 'getSeconds', fff: 'getMilliseconds' }; let parts=[], offset=0; str.replace(RGX, function(key, _, idx) { // save preceding string parts.push(str.substring(offset, idx - 1)); offset = idx += key.length + 1; // save function parts.push(custom && custom[key] || function(d) { return ('00' + (typeof MAP[key] === 'string' ? d[MAP[key]]() : MAP[key](d))).slice(-key.length); }); }); if ( offset !== str.length ) { parts.push(str.substring(offset)); } return function(arg) { var out='', i=0, d=arg||new Date(); for (; i<parts.length; i++) { out += (typeof parts[i]==='string') ? parts[i] : parts[i](d); } return out; }; }, }; /** /* Map (now) global $hash function to $core namespace for backwards compatibility. /*/ $core.hash = $hash; /** /* Dynamically imports and appends scripts to the DOM. /* Offers extended functionality such as manual deferral, error handling, and initialization tasks. /* /* @usage /* ``` /* $import('path/to/script.js').then(() => { /* console.log('All scripts loaded!'); /* }).catch(error => { /* console.error('Error loading script:', error); /* }); /* ``` /* /* @param {String|Array|HTMLElement|NodeList} input - Path(s) to the script(s) to be imported, or DOM nodes. /* @param {Object} [options] - Optional configuration object. /* @param {Function} [options.on] - Function to manually handle the script injection. /* @param {Function} [options.init] - Function to run initial tasks, e.g. for setup purposes. /* @param {HTMLElement} [options.target=document.body] - DOM element to which the script will be appended. /* @param {Object} [options.attributes={}] - Additional attributes to set on the script element. /* /* @returns {Promise} - Resolves when all scripts are loaded; rejects on any error. /*/ $core.import = function(scripts, { on, init, target = document.body, attributes = {} } = {}) { // Ensure scripts is always an array and not an already loaded script scripts = [].concat(scripts).filter(s => !(s?.src || document.querySelector(`script[src="${s}"]`))); typeof init === 'function' && init(scripts); return Promise.all(scripts.map(script => new Promise((resolve, reject) => { let el = script instanceof HTMLElement ? script : document.createElement('script'); if ( el.tagName === 'SCRIPT' ) { if ( el.querySelector(':is(script[data-src])') ) { el.src = el.getAttribute('data-src'); } else { Object.entries({ ...attributes, src: script }).forEach(([attr, val]) => el.setAttribute(attr, val)); } } else { return reject({ message: `Invalid input!`, data: script }); } el.addEventListener('load', resolve(el, script)); el.addEventListener('error', (e) => reject({ message: `Failed to load script: ${e.target.src}`, event: e })); // If an `on` function is provided, pass the script element to it for manual deferring typeof on === 'function' ? on(el, script) : target.appendChild(el); }))); }; /** /* Map global KV localStorage wrapper to $core for convenience. /*/ $core.kv = $kv; /** /* Proximity sensor helper method. Triggers a callback function when the mouse is within /* a certain distance of the given element. With the optional `check` flag set to `true` the method /* will check if the target element is reachable by the user, e.g. not hidden or obstructed by /* other elements. These checks are off by default, as they will be triggered with every tracked /* mousemove event which can potentially cause performance issues. If the target element is initially /* hidden, consider binding `$near()` AFTER the element has become visible! /* /* @usage /* ``` /* $near('.my-button', 50, (el, threshold) => { /* console.log(`Mouse is within ${threshold}px of ${el}`); /* }); /* ``` /* /* @param {Element|String} el - The target DOM element or a selector string to identify the element. /* @param {Number} threshold - The proximity threshold (in pixels) at which the callback will be invoked. /* @param {Function} fn - The callback function to be invoked when the mouse is within the defined distance of the target. /* @param {Boolean} [once=false] - If true, the callback will be triggered only once. /* @param {Boolean} [check=false] - If true, performs enhanced checks on the element that it's visible and not obstructed. /* /* @returns {void} /*/ $core.near = function(el, threshold, fn, { once = false, check = false } = {}) { el = typeof el === 'string' ? document.querySelector(el) : el; if ( !el || typeof fn !== 'function' || typeof threshold !== 'number' ) { return; } // make sure element exists let run = false; let within = false; // flag to track if the mouse is inside the proximity zone const proximity = function(target, x, y) { const { left, right, top, bottom } = target.getBoundingClientRect(); if ( check ) { const style = window.getComputedStyle(target); if ( Object.entries({ display: 'none', visibility: 'hidden', opacity: '0' }).some(([p, v]) => style[p] === v) ) { return false; } } return x > left - threshold && x < right + threshold && y > top - threshold && y < bottom + threshold; }; const handler = (e) => { if (run) { return; } run = true; window.requestAnimationFrame(() => { const near = proximity(el, e.clientX, e.clientY); if ( near && !within ) { within = true; fn(el, threshold); once && window.removeEventListener('mousemove', handler); } else if ( !near && within ) { within = false; } run = false; }); }; window.addEventListener('mousemove', handler); // return a function that removes the event listener when called return () => window.removeEventListener('mousemove', handler); }; /** /* This is the velocity parser implemented in core ported over to javascript, but it's only /* half useful, as it can't interpolate native strings, so this is only used to interpret /* non-interpolated velocity expressions. /*/ $core.parseVelocity = function(key = '', value = '', args = []) { // Cast all placeholder values to strings, otherwise the parser can't deal with the args args = args.map(String); const scopes_map = { component: $core.config.file, device: $core.config.user.device, page: $core.config.node.quilt, place: $core.config.node.type, lang: $core.config.user.lang, }; const scopes_matches = [...key.matchAll(/@([^@\r\n\t\f\v ]+)/gm)] || []; const scopes = scopes_matches.reduce((obj, match) => { const scope = match[1].split(':')[0]; const value = match[1].split(':')[1]; if ( scopes_map[scope] ) { obj[scope] = (scopes_map[scope] == value); } return obj; }, {}); const choice = (expr = '', args = []) => { const value = args[parseInt(expr.split(',').shift())]; const choices = expr.split('choice,').pop().trim(); return choices.match(`(${value})#(.*?)\\|`)?.[2] || choices.split('|').pop().replace(/\d+</, '') }; const rx = /\$\{(?<i>.+?)\}|\{(?<p>[0-5])\}|\{(?<e>[^\$]+?)\}/gm; let result = value; let cnt = 1; // Enter recursion to resolve nested velocity variables/placeholders/expressions // Have a safety max recursion depth to avoid unintentional memory leaks / endless loops while ( result.match(rx) ) { result = $core.parseVelocity(key, value.replace(rx, (match, i, p, e) => (i ? $core.str(i, null, ...args) : ( p ? args[parseInt(p)] || '' : choice(e, args) ))), args).value; if ( cnt >= 10 ) { console.warn('$core.parseVelocity(): Recursion depth of 10 exceeded!', result, result.match(rx), !!result.match(rx)); break; } cnt++; } return { key: key, value: result, scopes: scopes }; }; $core.serializeForm = function(form, json = false, filter, reducer) { // The shortest way of getting an object from FormData is // `Object.fromEntries((new FormData(form)).entries())` // but it will not handle select multiple inputs as the entries will have the same key // and therefore only the last selected option is returned as a value, to aggregate such array-like fields // properly, we have to manually loop over the fields after destructuring them into tuples (array of arrays) // this can also handle any type of field as an array of values by specifying the name with `[]` at the end // and furthermore it is also possible to directly aggregate form inputs into objects by specifying the name // attribute like so `name='object\{key}'`. NOTE: I'm not sure if the backslash escape is needed outside of // frameworks that interpolate expressions with `{`. Check the admin component for a practial example. const data = [...(new FormData(form)).entries()].reduce(reducer ? reducer : (obj, [name, value]) => { value = name.startsWith('(bool)') ? ({ '0': false, 'false': false, '1': true, 'true': true})[value.trim()] : value; const key = name.replace(/{(.+)}/gm, '').replace('(bool)', ''); value = obj[key] && key.endsWith('[]') ? [...obj[key], value] : ( key.endsWith('[]') ? [value] : ( /{(.+)}/gm.test(name) ? { ...obj[key], [[...name.matchAll(/{(?<k>.+)}/gm)][0]?.groups?.k]: value } : value ) ); if ( typeof filter === 'function' && filter(key, value) ) { obj[key] = value; } else { obj[key] = value; } return obj; }, {}); // Return a JSON string if requested return json ? JSON.stringify(data) : data; }; $core.obj = { /** /* Filters properties defined in props from the input object (non-destructive). /* /* @param {object} obj - The input object to operate on. /* @param {array} props - The properties to skip from the input object if present. /* /* @returns {object} - A new object without the properties defined in props. /*/ skip: function(obj = {}, props = []) { return Object.entries(obj).reduce((acc, [prop, value]) => { return props.includes(prop) ? acc : ((acc[prop] = value), acc); }, {}); }, /** /* Include only properties defined in props from the input object (non-destructive). /* Basically the opposite of _.skip(). /* /* @param {object} obj - The input object to operate on. /* @param {array} props - The properties to include from the input object if present. /* /* @returns {object} - A new object with only the properties defined in props. /*/ only: function(obj = {}, props = []) { return Object.entries(obj).reduce((acc, [prop, value]) => { return !props.includes(prop) ? acc : ((acc[prop] = value), acc); }, {}); }, }; $core.str = function(_key = null, _default = null, ...placeholders) { if ( !_key ) { return _default; } if ( _key && !_default ) { _default = _key; } // Try a direct lookup first, should work in most cases, except when there are @scopes // that weren't specified in the key let key = _key; let value = $core.properties[`${key}@component:${$core.config.file}`]; if ( !value ) { // Try to find a matching key by checking all properties //console.log(`$core.str(): could not find matching string for key ${key}: ${key}@component:${$core.config.file}, trying all properties:`, Object.entries($core.properties).find(([k, v]) => (k.includes(`@component:${$core.config.file}`) && k.split('@component').pop().includes(key)))); [ key, value ] = Object.entries($core.properties).find(([k, v]) => (k.includes(`@component:${$core.config.file}`) && k.split('@component').pop().includes(key))) || []; // console.log(`$core.str(): Could not find string by direct key (${_key}) lookup, find result:`, key, value); } /*else { console.log(`$core.str(): found matching string for key ${key}: ${key}@component:${$core.config.file}`); }*/ if ( value ) { return $core.parseVelocity(`${key}@component:${$core.config.file}`, value, placeholders).value; } else { return $core.parseVelocity(`${_key}@component:${$core.config.file}`, _default, placeholders).value; } }; /** /* Helper method facilitating watching for a DOM element for mutations and run a callback on them. /* /* @usage /* ``` /* $core.watch('<selector>', (mutation) => { /* console.log('I am here!', mutation); /* }, <optional:options>, <optional.immediate>); /* ``` /* /* @param {string} selector - The CSS selector to watch for mutations. /* @param {function} fn - The callback function to call when the element is mutated. /* @param {object} options - An optional options object for `.observe(<target>, <option>)` /* @param {boolean} immediate - If the callback function should be executed immediately once if the element is present. /*/ $core.watch = (selector, fn, options = {}, immediate = false) => { // Make sure nothing explodes in older browsers that do not support MutationObserver if ( window.MutationObserver ) { // Look for watched selector matching elements already present in the DOM, // and execute the callback on them immediately. if ( immediate && document.querySelector(selector) ) { [document.querySelector(selector)].forEach(fn); } options = { attributes: true, // can't have it set by default, otherwise not all attributes are monitored //attributeFilter: ['style', 'class'], attributeOldValue: false, characterData: false, characterDataOldValue: false, childList: false, subtree: false, ...(options || {}) } // One might have to do `const target = el.target as HTMLElement;` // within the callback to get an actual HTMLElement with its expected methods return (new MutationObserver(mutations => mutations.forEach(fn))) .observe(document.querySelector(selector), options); } }; /** /* Helper method facilitating waiting for a DOM element to appear and execute a callback. /* /* @usage `$core.when('<selector>', (el) => { console.log('I am here!', el); }, <optional:targetNode>);` /* /* @param {string} selector - The CSS selector to wait for. /* @param {function} fn - The callback function to call when the element appears. /* @param {HTMLElement} watch - The node to watch for mutations within. /*/ $core.when = (selector, fn, watch = document.body, existing = false) => { // Check if we even have a valid node to watch, otherwise MutationObserver will throw! watch = typeof watch === 'string' ? document.querySelector(watch) : watch; if ( !(watch instanceof Node) ) { console.warn(`$core.when(): 'watch' param wasn't a Node, aborting!`, watch); return; } // Make sure nothing explodes in older browsers that do not support MutationObserver if ( window.MutationObserver ) { // Look for watched selector matching elements already present in the DOM, // and execute the callback on them immediately. if ( document.querySelectorAll(selector).length ) { document.querySelectorAll(selector).forEach(fn); } return (new MutationObserver(mutations => [...mutations] .flatMap((mutation) => [...mutation.addedNodes]) .filter((node) => node.matches && node.matches(selector)) .forEach(fn))) .observe(watch, { childList: true, subtree: true }); } }; } // Initialize Tools // Make sure jQuery is available in some form which is not always the case in admin/studio and // several tools rely on it. if ( $ ) { // Tools only useful in admin/studio if ( $('body').is('.BizAppsPage') ) { Object.entries(tools.admin).map(function([name, fn]) { if ( typeof fn === 'function' ) { $core?.config?.user?.admin && console.info(`core.cmp.tools: Running tools.admin.${name}()`); fn(); } else { $core?.config?.user?.admin && console.warn(`core.cmp.tools: fn was not a function!`, fn); } }); } } // Bootstrap riot with global stuff if present // TODO: Maybe this should be its own component, separated from general purpose tools code! if ( window.riot ) { /** /* Stateless minimal router. /* Being stateless is a feature! The real "state" (i.e., the current route, history, etc.) /* is managed by the browser itself through the History API and the current URL. /* The router's job is to react to changes in that state and inform the rest of the app /* (via events or other mechanisms) about those changes. /*/ riot.$router = function(base = '/', options = {}) { const routes = []; base = '/' + base.replace(/^\/|\/$/g, ''); function parseRoute(route) { const { k, r } = route.split('/').reduce(({ k, r }, segment, i) => { switch (segment[0]) { case '*': return { k: k.concat('*'), r: r + '/(?<wild>.*)' }; case ':': const { key, con, ext, opt } = segment.match(/^:(?<key>[^\s(.?]+)(?:\((?<con>[\S]+?)\)(?![\)]))?(?<opt>\?)?\.?\(?(?<ext>[a-z0-9|]+)?\)?$/i)?.groups || {}; const p = `(?<${key}>${(con || '[^/]+?')}${ext ? `\\.(?<ext>${ext})` : ''})`; return key ? { k: k.concat(key), r: r + (opt ? `(?:/${p})?` : `/${p}`), } : { k, r }; default: console.log('parse index', i, Boolean(i)); return segment ? { k, r: r + `/(?<type${i > 1 ? i : ''}>${segment})` } : { k, r }; } }, { k: [], r: '' }); return { keys: k, pattern: new RegExp('^' + r + '/?$','i'), }; } function on(route, handler) { const { keys, pattern } = parseRoute(route); routes.push({ keys, pattern, handler }); } function navigate(path, replace) { const url = new URL(path, location.origin); const { keys, pattern } = parse(url.pathname); const match = routes.find(r => pattern.test(r.path)); if (match) { const match = match.pattern.exec(path); history[replace ? 'replaceState' : 'pushState'](null, null, path); $trigger('route', { url, match, keys, pattern }); } else if (options['404']) { options['404'](path); } } document.addEventListener('click', e => { const href = e.target.closest('a') && e.target.getAttribute('href'); const skip = [ !href, href.startsWith('#'), href.startsWith('javascript:'), !href.startsWith(base), e.defaultPrevented, e.button !== 0, e.metaKey, e.ctrlKey, e.shiftKey, e.altKey, ...(options.skipConditions || []) ]; if ( skip.some((con) => (typeof con === 'function' ? con(e) : Boolean(con))) ) { return; } e.preventDefault(); navigate(href); }); return { on, navigate }; }; riot.install((cmp) => { /** /* Override native riot `tag.$` (we don't touch `tag.$$`) with a much more powerful /* jQuery like API (it's not complete of course, but very mighty for 3.6KB code)! /* Of course we could also just map an already present jQuery instance to `tag.$`! /* This doesn't work, riot component internals are frozen! /*/ /*delete cmp.$; cmp['$'] = (selector) => { console.log('overwritten tag.$', selector); return cmp.$(selector); }; */ /** /* Install global event bus proxy methods. We do not want these methods scoped to every /* component individually but for them to be the same for all components so they can talk /* to each other on a global scope. /* /* - `on` will automatically bind `this` within the event listener function to the component. /*/ // This auto binding magic creates trouble, bind the component to the handler yourself if needed! //cmp['on'] = (e, fn, once) => $on(e, fn.bind(cmp), once); cmp['on'] = $on; cmp['off'] = $off; cmp['trigger'] = $trigger; /** /* Look for 'magic' listener methods defined within the component and automatically /* create a listener for them. These methods need to be named in a particular way: /* `$on<event.name.capitalized>` (note the $ prefix!), e.g. for an event type 'results' /* the component method needs to be defined as `$onResults: (e, results) => {}`, /* This approach is eliminating the need to define an explicit event listener somewhere /* within a regular lifecycle method with `tag.on('results', (e, results) => {})`... /* Using this automatic approach eliminates the need to remove any explicitely defined /* event listeners when a component is unmounted, as this is done automatically through /* the proxied lifecycle methods below. /* /* @note Be aware that if you need `this` bound to the component within your listeners /* (regardless if automatic or explicitely defined) you need to use the `function` way /* e.g. `$onResults: funciton(e, results) {}`! /* /* As this will create a listener for all events for every component, it's not enabled /* by default, only when the component has a property `events: true`. This way 'dumb' /* components do not get useless listeners registered which have to be processed! /*/ // We can either override riot.$trigger or 'properly' use the event bus, I'm not sure what // is actually better, both approaches seem to work just fine, when overriding obviously // there are no listeners stored and thus don't need to be removed when unmounting, resulting // in slightly less bootstrap code, but other than that it somehow feels wrong to me... /* if ( cmp.events ) { const $trigger = riot.$trigger; riot.$trigger = async (e, ...args) => { const $ = `$on${e.replace(/\b\w/, (c) => c.toUpperCase())}`; if ( cmp[$] ) { console.log(`automatically triggering ${$} listener for ${cmp.name}`); await cmp[$](e, ...args); } await $trigger(e, ...args); }; } */ let off = null; if ( cmp.events ) { // `on` will return a function to remove that listener, we store it for auto-cleanup off = cmp.on('*', async function(e, ...args) { const $ = `$on${e.replace(/\b\w/, (c) => c.toUpperCase())}`; if ( cmp[$] ) { await cmp[$](e, ...args); } }); } /** /* Proxy component lifecycle methods to give some debug info in debug mode /* allows us to define debugging stuff once here instead of having to repeat /* the same lengthy logging code in every single component increasing bundle /* size for nothing... we can reference component.name safely as it is part of the /* default component implementation along with .css and .template even though those /* properties are not enumerable (e.g. shown when console.log(component)) /* to proxy lifecycle methods simply set the .proxy property within the component to true /* if undefined or false nothing will be done here (e.g. the proxy is opt-in) /*/ ['onBeforeMount', 'onMounted', 'onBeforeUnmount'].forEach((method) => { // make a reference to the original lifecycle method and bind the component to it const org = cmp[method].bind(cmp); // add proxy method calling the original after it has done global stuff cmp[method] = (props, state) => { org(cmp.props, cmp.state); // automatically removes auto-event listeners when the component is unmounted if ( method === 'onBeforeUnmount' && off ) { off(); } cmp.debug && console.log(`${cmp.name}.${method}()`, cmp.props, cmp.state, method === 'onBeforeMount' ? cmp : null); }; }); //console.log('riot.install() done!', cmp); }); } if ( $core?.config?.env?.includes('stage') && $core?.config?.user?.roles?.includes('GlowingBlue') && document.querySelectorAll('[type*="riot"]').length && window.riot ) { // Live compiling riot components in dev mode console.log('core.cmp.tools: Compiling and registering riot components'); (async () => { await $core.compile(); // Useful for profiling component performance if ( window.performance ) { window.start = performance.now(); } if ( $trigger ) { await $trigger('compiled'); } })(); } else { // directly trigger on prod as components are pre-compiled! (async () => { if ( $trigger ) { // Wait for next event loop, if not it can cause strange non-mounting issues // due to no work having to be done (e.g. compile event basically happening immediately) // and the order in which @liaAddScript adds the JS from various places within the codebase await $wait(0); await $trigger('compiled'); } })(); } //document.addEventListener('DOMContentLoaded', function() {}); })(LITHIUM?.jQuery || jQuery); // Pull in global jQuery reference // </script> // <script> just for inline syntax-highlighting... ;(function($){ // This is very much work in progress, but a synk object should generally look something like: /* { type: <event-type-synk-understands>, event: { data: {}, source: { node: {}, page: {}, user: {}, }, verified: <bool>, } } */ // Store objectified request payloads for later use let payload = {}; // Define which particular routes we want to forward to synk. Those can be from forms, // links etc. // The key is the form action or link (partial) to check for when a request comes in // the value is an object with an `only`array for filtering the payload and a `type` // function to dynamically determine the type of event that is witnessed. // TODO: Look into those `t:cp=solutions/contributions/acceptedsolutionsactions` // identifiers that most actions seem to have, maybe they are an easier to detect way // of what to track on different pages, then the changing URL's which force us to use // URL partials... => unfortunately not, the identifier stays the same, the action is // still burried in the URL, like `markmessageasacceptedsolutionsecondarybutton` (WTF?): // t5/forums/v5/forumtopicpage.markmessageasacceptedsolutionsecondarybutton/message-uid/1844 const synk = { // AJAX: inline reply form submit 'inlinemessagereplyeditor.form.form.form.form': { only: [ 'attachment-key', 'liaFormContentKey', 'mediaSnippetUrl', 'multipleUpload', 'parentMessageRef', 't:ac', 'tags_', 'tinyMceEditor', ], type: (xhr) => 'post-reply', }, // AJAX: Kudos button 'kudosbuttonv2.kudoentity': { only: ['triggerEvent', 'parameterOverrides'], type: (xhr) => (xhr.responseURL.includes('revoke-kudos/true') ? 'dislike' : 'like'), }, // not AJAX: Report content to moderator 'notifymoderatorform.form.form.form': { type: (xhr) => 'mod-check', }, // subscribe: /t5/forums/v5/forumtopicpage.__addmessageuseremailsubscription__/message-uid/1841?t:cp=subscriptions/contributions/messageactions // post-mute: /t5/forums/v5/forumtopicpage.__addmessageusermute__/message-uid/1924?t:cp=subscriptions/contributions/messageactions // bookmark: /t5/forums/v5/forumtopicpage.__addmessageuserbookmark__/message-uid/1924?t:cp=subscriptions/contributions/messageactions // post-edit: /t5/forums/v5/forumtopicpage.__editmessageinline:editmessage__/message-uid/1924?t:cp=boards/contributions/messageactions // post-delete: /t5/forums/v5/forumtopicpage.__deletemessage:deletemessage__/message-uid/1924?t:cp=boards/contributions/messageactions // post-move: /t5/forums/v5/forumtopicpage.__movemessage:movemessage__/message-uid/1924?t:cp=boards/contributions/messageactions // post-solved: /t5/forums/v5/forumtopicpage.__markmessageasacceptedsolutionsecondarybutton__/message-uid/1844?t:cp=solutions/contributions/acceptedsolutionsactions // post-unsolved: /t5/forums/v5/forumtopicpage.__unmarkmessageasacceptedsolution__/message-uid/1844?t:cp=solutions/contributions/acceptedsolutionsactions }; $on('xhr', (e, state, xhr, ...args) => { //console.log('$onXHR', e, xhr, args); if ( state === 'open' ) { $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Request created', args, xhr); } else if ( state === 'send' ) { $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Request payload is about to be sent', Object.fromEntries([...(new URLSearchParams(args[0]))])); payload = args[0] ? Object.fromEntries([...(new URLSearchParams(args[0]))]) : {}; } else if ( state === 'response' ) { $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Can modify response text!', args, xhr); // important to return modified response from here return args[0]; } else if ( state === 'done' ) { if ( !Object.entries(synk).some(([urlpartial, obj]) => xhr.responseURL.includes(urlpartial)) ) { $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: skipping response processing for', xhr.responseURL); return; } $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Response received', xhr.responseText); try { // Do some basic sanity checks before attempting to parse JSON... // Usually Khoros XHR responses are a huge object that is then processed and // injected into the current page via some very convoluted logic, most of the data // is irrelevant for us and is contained within a response's `components` property let data = xhr.responseText.trim().startsWith('{') ? $core.obj.skip(JSON.parse(xhr.responseText)?.response, ['components']) : xhr.responseText; if ( typeof data !== 'string' ) { const { only, type } = (Object.entries(synk).find(([urlpartial, obj]) => xhr.responseURL.includes(urlpartial))[1] || {}); data = { type: type(xhr) || 'undefined', event: { url: xhr.responseURL, timestamp: (new Date()).toISOString(), // the result of the event data: data, // the initiator of the event source: { payload: $core.obj.only(payload, (only || [])), user: $core.obj.skip(LITHIUM.CommunityJsonObject.User, ['settings', 'policies', 'emailRef']), node: LITHIUM.CommunityJsonObject.CoreNode, page: { ...($core.obj.only(LITHIUM.CommunityJsonObject.Page, ['object'])?.object || {}), }, } } }; $trigger('synk', data); //console.log('Forwarded data:', data); } else { $core.config.devmode === 'xhr' && console.warn('XHRmiddlaware: Respsone was a string, skipping sync!'); } } catch(ex) { console.error(ex); } } }); // The above handles (old school) AJAX requests, but we also need to deal with actions/events // that occur the even old-schooler way through regular link clicks that reload the page. // To do that we attach a global link listener. I believe to catch Khoros related events we // can safely filter links by `data-lia-action-token` as all the relevant action links seem // to have such an attribute! // TODO: Make sure we do not somehow also track links that are handled by AJAX requests and // thus would be double-synk'ed... document.querySelectorAll('a[data-lia-action-token]').forEach((el) => { el.addEventListener('click', (e) => { if ( e.target.getAttribute('href') ) { const url = new URL(e.target.getAttribute('href')); const params = Object.fromEntries([...url.searchParams]); $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Action link params', url, params, e.target.getAttribute('href')); } else { $core.config.devmode === 'xhr' && console.warn('XHRmiddlaware: Action link did not have a href attribute?', e.target, e); } if ( $core.config.user.roles.includes('GlowingBlue') ) { $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Preventing action from glowingblue user'); //e.preventDefault(); } // We would then build a synk object and trigger a 'synk' event through the global // event bus... // TODO: We also need to think about what happens if an action fails, maybe storing // potential sync objects in localStorage with an attribute of `verified: false` // would be a good idea, for AJAX requests we can more or less reliably track // if an action was successful, as the returned objects contain a property `state` // (NOT `status`, that one is always 'success'!) that will indicate any errors... }); }); // There are also forms that are not handled via AJAX! It seems this listener does not // conflict with the AJAX ones, as those are implemented by Khoros earlier on, so this // listener is never called for AJAX handled forms, which is good because then we don't // have to deal with duplicate synk events... document.querySelectorAll('input[name="lia-action-token"]').forEach((el) => { $(el).parents('form')[0].addEventListener('submit', (e) => { if ( $core.config.user.roles.includes('GlowingBlue') ) { $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Preventing form submission from glowingblue user'); //e.preventDefault(); $core.config.devmode === 'xhr' && console.log('XHRmiddlaware: Serialized form', $core.serializeForm(e.target)); } else { //return true; } }); }); $on('synk', (e, data) => { console.log('$onSynk', e, data); // TODO: make sure there is no issue with aborted requests due to page reloading // if it is, we might have to store the synk objects in local storage before sending // out the request and then when we get a successful response, delete them and on page // load check if we have any leftover items to synk and process those again... // TODO: Push requests through proxy (not sure if it already handles POST requests!) // So we do not leak any user IP information to a third party which Deno deploy is... fetch('https://synk.deno.dev', {method:'POST', body: JSON.stringify(data)}); }); // Simply trigger a custom xhr event and handle whatever logic in the event listener! XMLHttpRequest.$use((xhr, state, ...args) => { $trigger('xhr', state, xhr, ...args); }); })(LITHIUM.jQuery); // Pull in global jQuery reference // </script> // <script> just for inline syntax-highlighting... ;(function($){ /** /* Deals with any redirects that need to be handled in JavaScript for some reason, like 404 Pages /* as we don't get the request in page.init and therefore can't do a redirect form there. /* /* You only need to specify the project specific redirects by adding them to the global `$core` /* object. The actual redirect logic will be dealt with from `core.cmp.tools` via `tools.redirect()`, /* just make sure you don't change the property name as the tool method looks for `$core.redirects`. /* /* @usage: Just define key/value paris where key = url.pathname and value the url to redirect to /*/ $core.redirects = { //'/some/path/to/redirect': 'https://www.community.tld/some/url/to/target/redirect/to', }; /** /* @issue KBCOM-2655 /* /* Immediately makes the inline 'Reply' button disabled on click instead of waiting for TinyMCE /* to be initialized as OOB does. /*/ $('.lia-component-messages-widget-reply-inline-button .lia-button.lia-action-reply').each(function() { $(this).on('click', function(e) { $(this).attr('disabled', true) }); }); })(LITHIUM.jQuery); // Pull in global jQuery reference // </script> // <script> ;(function() { if ( $core ) { $core.config.file = 'cmp.global.search-external'; $core.properties = { ...($core.properties || {}), ...{"general.in@component:cmp.global.search-external" : "in","general.of@component:cmp.global.search-external" : "\/","general.from-community@component:cmp.global.search-external" : "コミュニティから","title@component:cmp.global.search-external" : "Additional Resources","filter.title.resources@component:cmp.global.search-external" : "Included お役立ちリソース","filter.title.languages@component:cmp.global.search-external" : "言語","filter.knowledge@component:cmp.global.search-external" : "Knowledge Base","filter.academy@component:cmp.global.search-external" : "Academy","filter.cms@component:cmp.global.search-external" : "CMS Documentation","filter.api@component:cmp.global.search-external" : "API Documentation","filter.customer@component:cmp.global.search-external" : "Customer Blog","filter.language.en@component:cmp.global.search-external" : "en","filter.language.de@component:cmp.global.search-external" : "de","filter.language.es@component:cmp.global.search-external" : "es","filter.language.fr@component:cmp.global.search-external" : "fr","filter.language.pt@component:cmp.global.search-external" : "pt","filter.language.ja@component:cmp.global.search-external" : "ja","result@component:cmp.global.search-external" : "result","results@component:cmp.global.search-external" : "結果","results.in@component:cmp.global.search-external" : "{0} {0,choice,0#${results}|1#${result}|1<${results}} ${general.in} {1}","results.none.title@component:cmp.global.search-external" : "No results for \"{0}\"","results.none.text@component:cmp.global.search-external" : "Try a different search term or use the filter on the left to search other resources.","paging.prev@component:cmp.global.search-external" : "前へ","paging.next@component:cmp.global.search-external" : "次へ"}, }; } })(); // </script> // <script> just for inline syntax-highlighting... ;(function($){ const params = (new URL(window.location.href)).searchParams; // Allows testing production behavior on stage by switching env temporarily via URL param if ( $core.config.env.includes('stage') && params.get('test') ) { $core.config.env = 'prod'; console.warn('Production test mode enabled', $core.config); } // The most primitive in-memory cache you can imagine // it will hold HubSpot search API results as long as the page is not reloaded, this // speeds things up drastically when using typeahead (e.g. reacting to every key stroke) $core.cache = new Map(); const title = $core.str('title', 'Additional Resources'); /** /* Searchbar autosuggest integration. /* We can't really use riot here as we are hacking into the existing Khoros auto-suggest dropdown /* Furthermore the SearchForm is added twice to every page due to how the mobile header was done. /* It's entirely separate from the desktop header and therefore needs to be targetet properly when /* it's visible from 1024px down. /*/ const search_form = window.innerWidth <= 1024 ? '.mobile-header form.SearchForm' : '.community-header-nav .SearchForm'; $core.when(`${search_form} [name="messageSearchField"] + .lia-autocomplete-container .lia-autocomplete-content`, function(el) { $(`${search_form} [name="messageSearchField"]`).each(function() { var $input = $(this); var $results = $input.find('+ .lia-autocomplete-container .lia-autocomplete-content'); /** /* The autosuggest-dropdown closes on a click anywhere besides it's own results, /* not too crazy of an issue, but it annoys me and I can't fix it, don't know what /* triggers which event, tried to find out but without success... /*/ /*if ( window.innerWidth <= 1024 ) { $results .prepend(`<i class="collapse-results lia-autocomplete-no-event-item lia-fa fa-chevron-up p:x15 p:y11 pos:a pos:r0 pos:t0"></i>`) .find('.collapse-results') .on('click', function(e) { e.stopPropagation(); console.log($(this).siblings('ul:first'), $(this)); $(this).toggleClass('fa-chevron-up fa-chevron-down'); }); }*/ if ( !$results.find('ul.custom-external-results').length ) { $results.append(`<ul class="custom-external-results d:f(row/0/1/100%) h:max300 d:scroll(y) t:/12//400 d:b:before p:y8:before p:l15:before pos:r t:ucase:before" aria-label="${title}" data-before="${title}"></ul>`); } var $container = $results.find('ul.custom-external-results'); $input.on('input', async function(e) { // TODO: find out what is the URL param to limit `limit=` does not work... // => well, it seems the autocomplete endpoint of the HubSpot search API does not // support any kind of configuration at all. If it's needed, we might have to switch // to the slower 'full' API endpoint var url = `https://wtcfns.hubspot.com/wt-api/search/autocomplete?queryString=${$input.val()}&language=${$core.config.user.lang}&limit=5`; //console.log($input.val()); if ( !$core.cache.has(url) ) { $core.cache.set(url, (await (await $core.fetch(url)).json())); } //console.log($core.cache.get(url)); // HubSpot search API will return `{'message': 'Missing search key'}` when the `queryString` is empty // in that case, markup will be `undefined`, which we have to catch, otherwise it's going to be // an empty array if there are really no results for a search term. var markup = $core.cache.get(url).data?.searchResults?.results?.reduce((r, v) => { // As limit doesn't work on the autocomplete endpoint we have to limit the auto-suggest results like this //if ( r.length < 3) { r.push(` <li class="lia-autocomplete-node-item lia-autocomplete-custom-item"> <a class="lia-link-navigation board-icon" tabindex="-1" href="#"> <span class="custom-img-icon-help lia-fa-icon lia-fa-question lia-fa bg:--color-lorax t:--color-olaf" title="${v.resource}" aria-label="${v.resource}" role="img"></span> </a> <a class="lia-link-navigation lia-js-autocomplete-list-item-link lia-autocomplete-message-list-item-link" tabindex="-1" href="${v.url}" target="_blank"> ${v.title.replace('hs-search-highlight hs-highlight-title', 'lia-search-match-lithium')} </a> <div class="lia-autocomplete-suggestion-additional-details lia-component-nodes-widget-auto-complete-node-list-item"> <span class="lia-autocomplete-suggestion-board-title t:caps">${v.resource}</span> </div> </li> `); //} return r; }, []); if ( markup === []._ ) { return; } if ( markup.length ) { $container.html(markup.join('\n')); } else { $container.html(`<div class="pos:center t:center t:/14">${$core.str('results.none.title', null, $input.val())}</div>`); } }); }); }, document.querySelector(`${search_form}`)); /** /* Global SearchPage integration of external search. /* Adds a new tab to the search sections area and additionally a filter-like fake dropdown /* That additional filter was removed again via KBCOM-2830! /* that triggers a click on the new tab, it's just for more visual exposure as we worry the /* new tab might be too unassuming and might be overlooked. /*/ if ( $core.config.node.quilt.includes('SearchPage') ) { let results = null; const getResults = async function(query, resources = ['knowledge', 'academy', /*'customer', 'api', 'cms'*/], language = ($core?.config?.user?.lang || 'en'), page = 1, limit = 10, offset = 0, padding = 2) { offset = (page-1) * limit; // HubSpot search API resources are targeted with `contentKey: api, cms, knowledge, academy, customer` const url = `https://wtcfns.hubspot.com/wt-api/search?queryString=${query}&limit=${limit}&offset=${offset}&page=${page}&language=${language}&contentKey=${resources.join(',')}`; //console.log(url); if ( !$core.cache.has(url) ) { $core.cache.set(url, (await (await $core.fetch(url, null, 'appcache')).json())); } // once received, the HubSpot search API results are agumented with custom stuff // that helps rendering things like pagination etc. let results = Object.entries(($core.cache.get(url)?.data?.searchResults || {})).reduce((r, [k, v]) => ({ ...r, [k]: v }), { active: resources, lang: language, query: query, url: url }); // calculate the total amount of pages first and set it to minimum 1 const pages = Array.from({length: Math.max(Math.ceil(results.total/limit), 1)}, (el, i) => i+1); // calculate collection object const collection = { limit: limit, offset: offset, total: results.total, paging: { page: page, pages: pages.length, // TODO: there are still some issues with this, it does work for page // 1, but for the last page, only 3 (instead of 5) pages are returned display: pages.length ? (() => { const num = (padding * 2) + 1; const i = pages.indexOf(page); const from = Math.max(i - Math.floor(num / 2), 0); const to = Math.min(from + num - 1, pages.length - 1); return pages.slice(from, to + 1); })() : [], // number of page-links left and right of current page padding: padding, // rendering helpers is_first: page === 1, is_last: page == pages.length } }; results = { ...results, collection: collection }; //console.log('response', res); //console.log('results', results); // Trigger a custom jQuery event globally that we can hook into from any other code $(document).trigger('results', results); // We can trigger the custom global riot event-bus from outside of components as it // is attached to the global riot object! if ( $trigger ) { $trigger('results', results); } return results; }; const injectSearchExternal = function() { // Inject our custom tab const $tab = $('.lia-search-tab-bar .lia-component-search-tabs .lia-tabs-standard').append(` <li role="presentation" class="search-external-tab lia-tabs lia-tabs-inactive is--custom"> <span><a class="search-external-link lia-link-navigation tab-link" role="tab" aria-selected="false" tabindex="0" href="${window.location.href}">${title}</a></span> </li> `).find('.search-external-tab'); // Removed via KBCOM-2830 /* const $filter = $(` <div class="lia-form-fieldset-wrapper lia-component-search-widget-external is--custom"> <a href="${window.location.href}" class="lia-common-dropdown-toggle" role="button">${title}</a> </div> `).insertBefore('.lia-component-quilt-search-page-thread-filters .lia-component-search-widget-location-filter'); */ // Handle clicks on our new tab: // The idea is to basically wipe the existing content from the page and mount the // custom search component instead. Any click on the regular tabs will behave like always and // trigger a page reload which will show the original content again $tab.find('.search-external-link').on('click', function(e) { e.preventDefault(); // Handle active state of tabs $(this).parents('.search-external-tab').addClass('lia-tabs-active').siblings('.lia-tabs-active').removeClass('lia-tabs-active'); // Then we clean out some of the content of the current page and make it look like a tab switch $('.lia-search-tab-bar .lia-component-search-widget-advanced-search-toggle, .lia-search-tab-bar .lia-component-search-actions, .lia-search-results .search-result-sorting').remove(); $('.lia-search-results .search-result-count').remove(); // Once cleaned up we inject the base tag and mount our custom component $('.lia-quilt-column-main-content .lia-quilt-row-main').empty().append('<div is="search-external" class="p:x15" data-cmp="cmp.global.search-external"></div>'); riot.mount('[is]:not([is] [is])', { title: title, results: results, params: params, getResults: getResults }); }); // The fake injected filter simply triggers the tab, it's meant to provide greater exposure (visually) // $filter.on('click', function(e) { // e.preventDefault(); // $tab.find('.search-external-link').trigger('click'); // }); }; // Pre-fetch results, why wait as we already know the query here, this also allows to inject a variety of // dynamic information into the native search results content and agument it with external results data // this also deals with the fact that the search page is an Angular component that reloads dynamically // when doing certain things... (not tab switching though) $core.when('.lia-message-search-container', async (el) => { if ( !document.querySelector('.lia-tabs.external-tab') ) { //console.log('Injecting external search!'); injectSearchExternal(); results = await getResults(params.get('q')); } }); // Attach custom event listener here to deal with non-component DOM updates as I don't want to handle those // within the custom component but also be updated if something changes there... $(document).on('results', function(e, results) { //console.log('onResults', e, results); if ( $('.lia-search-results .search-result-count').text().trim().length ) { $('.lia-search-results .search-result-count').attr('data-after', $core.str('general.from-community')); } // Update the tab tag $('.search-external-link').attr('data-after', (results?.total || 0)); }); } // Re-set production test mode if ( $core.config.env.match('stage') && params.get('test') ) { $core.config.env = 'stage'; } })(LITHIUM.jQuery); // Pull in global jQuery reference // </script> (function($) { //START END-USER CONFIGURATION //------------------------------ //selectors for hover card triggers var allHoverCardTriggers = '.author-name-link,.friend-list .friend a,.username a,.avatar,.user-avatar,.author-img, .authors a, .messageauthorusername a, a.lia-user-name-link, .js-latest-post-by-from a, .user-online-list li a, a.UserAvatar, .customUsersOnline a, #authors a,.dashboard-followers a.user-name, .dashboard-following a.user-name,.author-login-wrapper a, .hb-leaderboard a, .author-img-floated'; // Forward calling page's URL params to endpoint URL as well, helps with testing! var params = (new URL(location.href)).searchParams; var userApiUrl = '/plugins/custom/hubspot/hubspot/hovercardendpoint?' + ((params.set('user_id', '') == []._) && params.toString()); if($('.hover-card-container').length<1){ $('body').append('<div class="hover-card-container"></div>'); } var cardWrapper = $('.hover-card-container'); var error = false; var thisUserID = ''; var thisUserLogin = ''; var userLink =''; var cardTimer; var leaveTimer; function mouseenter(Elem) { var thisEl = Elem; cardTimer = setTimeout(function(){ var docWidth = $(document).width(); var rightSide = false; var userLink = thisEl.attr('href'); if($('.ViewProfilePage').length && $('img.lia-user-avatar-profile',thisEl).length){thisUserID = '';} else if(thisEl.attr('href')=='#' || thisEl.attr('href')=='' || !userLink.match('viewprofilepage')){ return false;} else{ var thisLen = (userLink).split('/'); thisUserID = (thisLen)[thisLen.length-1]; } var thisCard = $('.profileCard[data-user='+thisUserID+']',cardWrapper); var cardId = 'userProfileCard-'+ thisUserID; var addAttr = thisEl.attr('aria-describedby',cardId); var thisElTopOffset = Math.round(thisEl.offset().top+(thisEl.height()/2)+30); var thisElbottomoffset = "auto"; var className = ""; var winHeight = $(window).height(); var elOffset = thisEl.offset(); var scrollTop = $(window).scrollTop(); var elementOffset = thisEl.offset().top; var distanceTop = (elementOffset - scrollTop); var distanceBottom = (winHeight + scrollTop) - (elOffset.top + thisEl.outerHeight(true)); var distanceLeft = Math.round(thisEl.offset().left); var bodyHight = $('body').height(); var topParam = ''; var bottomparam = ''; var position = ''; var className = 'topArrow'; cardId if(distanceBottom < 300 ){ if(distanceLeft < 59){ thisCard.removeClass('bottomArrow'); var className = 'leftArrow'; var distanceLeft = (distanceLeft)+(39); var thisElTopOffset = (thisElTopOffset)-(150); }else{ var thisElTopOffset = (thisElTopOffset)-(301); var className = 'bottomArrow'; thisCard.removeClass('topArrow'); thisCard.removeClass('leftArrow'); var distanceLeft = (distanceLeft)-(45); } } else{ if(distanceLeft < 59){ thisCard.removeClass('topArrow'); var className = 'leftArrow'; var distanceLeft = (distanceLeft)+(39); var thisElTopOffset = (thisElTopOffset)-(150); }else{ thisCard.removeClass('leftArrow'); thisCard.removeClass('bottomArrow').addClass('topArrow'); var distanceLeft = (distanceLeft)-(45); } } if(thisCard.length && $('.profileCard[data-user='+thisUserID+'] .preloader',cardWrapper).length<1){ $('.profileCard',cardWrapper).hide(); thisCard.addClass(className); rightSide?thisCard.addClass('rightArrow'):thisCard.removeClass('rightArrow'); thisCard.delay(0).css({'top':(thisElTopOffset),'left':distanceLeft,'bottom':thisElbottomoffset}).fadeIn(); } else { var ajaxReturn = ''; //just in case thisCard.remove(); //hover card wrapper markup var rightArrowClass = rightSide?'rightArrow':''; if(thisElTopOffset != "auto"){ topParam = 'px'; } if(thisElbottomoffset != "auto"){ bottomparam = 'px'; } var profileCardHtml = '<div id="'+cardId+'" role="tooltip" class="AllCard profileCard '+rightArrowClass+' '+className+'"style="display:block;top:'+thisElTopOffset+topParam+';left:'+distanceLeft+'px;bottom:'+thisElbottomoffset+bottomparam+';" data-user="'+thisUserID+'"></div>'; $.when( //get the background $.ajax({ type: 'GET', url: userApiUrl+thisUserID, dataType: 'html', success: function(data) { $('.profileCard',cardWrapper).hide(); ajaxReturn = data; } }) ) .done(function(){ cardWrapper.append(profileCardHtml); $('.profileCard[data-user='+thisUserID+']',cardWrapper).eq(0).empty().html(ajaxReturn); if($('.profileCard[data-user='+thisUserID+'] .preloader',cardWrapper).length){ $('.profileCard[data-user='+thisUserID+'] .preloader',cardWrapper).parents('div.profileCard').remove(); } }) .fail(function(){ //uh oh - bail out! $('.profileCard',cardWrapper).hide(); }); } }, 360); } function mouseleave(e) { clearTimeout(cardTimer); // glowingblue: When the user leaves the hovercard trigger, wait because the leaving could be // to interact with the hovercard, if we don't wait it will just disappear...because // we left the trigger, right...so we'll have another handler that check if the mouse is // over the hovercard and if so clears this timer, so the card doesn't close here leaveTimer = setTimeout(function() { if ($('.profileCard[data-user="'+thisUserID+'"]',cardWrapper).length) { $('.profileCard[data-user="'+thisUserID+'"]',cardWrapper).fadeOut('fast'); } else { $(".profileCard").fadeOut('fast'); } }, 2400); } $(document).on("mouseenter focusin", allHoverCardTriggers, function(event) { if(!($(this).parents().hasClass('custom-header'))&& !($(this).parents().hasClass('green-wrap'))){ (leaveTimer !== []._) && clearTimeout(leaveTimer); mouseenter($(this)); event.stopPropagation(); } }); $(document).on("mouseleave focusout", allHoverCardTriggers, function(event) { (leaveTimer !== []._) && clearTimeout(leaveTimer); mouseleave(event); event.stopPropagation(); }); // glowingblue: Add handlers for when the users interacts with the hovercard, no closing! $('.hover-card-container').on('mouseenter', function(e) { (leaveTimer !== []._) && clearTimeout(leaveTimer); }); $('.hover-card-container').on('mouseleave', function(e) { (leaveTimer !== []._) && clearTimeout(leaveTimer); if ( $(e.target).is('.profileCard[style*="block"]') ) { leaveTimer = setTimeout(function() { $(e.target).fadeOut('fast'); }, 2400); } }); // glowingblue: add one global root level click handler to also close any visible hovercards // if the user taps/clicks outside the hovercard $(document).on('mousedown', function(e) { if ( !$(e.target).parents('.hover-card-container').length ) { (leaveTimer != []._) && clearTimeout(leaveTimer); $('.hover-card-container .profileCard[style*="block"]').each(function() { $(this).fadeOut('fast'); }); } }); })(LITHIUM.jQuery); (function($) { <!-- Expire all cookies --> document.cookie = "advocacyToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; document.cookie = "Crowdvocate_jwt_token=; domain=.hubspot.com; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; document.cookie = "Crowdvocate_user_ck=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; })(LITHIUM.jQuery); (function($) { document.addEventListener('gdpr.allow', function() { if (document.querySelector('.lia-cookie-banner-alert-accept a')) { document.querySelector('.lia-cookie-banner-alert-accept a').click(); } }); })(LITHIUM.jQuery); LITHIUM.Link({"linkSelector":"a.lia-link-ticket-post-action"}); ;(function($){ var langMap = { 'en':'hubspot_community_en', 'es':'hubspot_community_es', 'fr':'hubspot_community_fr', 'ja':'hubspot_community_jp', 'pt-br':'hubspot_community_pt', 'de':'hubspot_community_de' } var nodeType = "community"; var langScope = langMap['es']; var isSearchPage = jQuery('body').hasClass('SearchPage'); var isIdeasLandingPage = jQuery('body').hasClass('ideaslandingpage'); if (nodeType === "community" && !isSearchPage && !isIdeasLandingPage) { var inputFormFilter = '<input name="filter" value="location" type="hidden">'; var inputFormLocation = '<input name="location" value="category:' + langScope + '" type="hidden">'; $('form.SearchForm').append(inputFormFilter).append(inputFormLocation); } else if (nodeType === "community" && isIdeasLandingPage) { var searchUrl = "/t5/forums/searchpage/tab/message?filter=location&location=idea-board:HubSpot_Ideas&collapse_discussion=true"; var query = jQuery('.SearchForm .lia-search-input-message').val(); jQuery(document).on('submit', 'form.SearchForm', function(e) { e.preventDefault(); var newQ = "&q=" + document.querySelector('.SearchForm .lia-search-input-wrapper input.search-input').value; window.location = window.location.origin + searchUrl + newQ; }) } })(LITHIUM.jQuery) LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce4066ce448","feedbackSelector":".InfoMessage"}); LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce4066ce448_0","feedbackSelector":".InfoMessage"}); LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce4066ce448_1","feedbackSelector":".InfoMessage"}); LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce4066ce448_2","feedbackSelector":".InfoMessage"}); LITHIUM.AjaxFeedback(".lia-inline-ajax-feedback", "LITHIUM:hideAjaxFeedback", ".lia-inline-ajax-feedback-persist"); LITHIUM.Placeholder(); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.defaultAjaxFeedbackHtml = \"<div class=\\\"lia-inline-ajax-feedback lia-component-common-widget-ajax-feedback\\\">\\n\\t\\t\\t<div class=\\\"AjaxFeedback\\\" id=\\\"ajaxFeedback_24bce40802b405\\\"><\\/div>\\n\\t\\t\\t\\n\\t\\n\\n\\t\\n\\n\\t\\t<\\/div>\";LITHIUM.AjaxSupport.defaultAjaxErrorHtml = \"<span id=\\\"feedback-errorfeedback_24bce408167685\\\"> <\\/span>\\n\\n\\t\\n\\t\\t<div class=\\\"InfoMessage lia-panel-feedback-inline-alert lia-component-common-widget-feedback\\\" id=\\\"feedback_24bce408167685\\\">\\n\\t\\t\\t<div role=\\\"alert\\\" class=\\\"lia-text\\\">\\n\\t\\t\\t\\t\\n\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t<p ng-non-bindable=\\\"\\\" tabindex=\\\"0\\\">\\n\\t\\t\\t\\t\\t\\tNo se pudo completar la acción solicitada.\\n\\t\\t\\t\\t\\t<\\/p>\\n\\t\\t\\t\\t\\n\\n\\t\\t\\t\\t\\n\\n\\t\\t\\t\\t\\n\\n\\t\\t\\t\\t\\n\\t\\t\\t<\\/div>\\n\\n\\t\\t\\t\\n\\t\\t<\\/div>\";LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce4073c59a9', 'disableAutoComplete', '#ajaxfeedback_24bce4066ce448_0', 'LITHIUM:ajaxError', {}, 'wK3S57T1LcED2GU2MoomlBVDc2oR3Keg1iuIXCW0cVQ.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"v3u1jLf91XyxrHcWDB_Ui0gn_A62w81lzXU-z_2fHXc.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce4073c59a9\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":3},"inputSelector":"#messageSearchField_24bce4066ce448_0","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.messagesearchfield.messagesearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce409043011', 'disableAutoComplete', '#ajaxfeedback_24bce4066ce448_0', 'LITHIUM:ajaxError', {}, 'k4WQi0JakUAJKfjHl_lraEcz-gMZqPKoRN5yrk1wxOM.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"j-GzM4cgfDEl8h4PM7Q3-b8wpTLWXM3FJmAA3hgHcuc.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce409043011\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":3},"inputSelector":"#messageSearchField_24bce4066ce448_1","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.tkbmessagesearchfield.messagesearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando por usuarios...","emptyText":"No existen coincidencias","successText":"Usuarios encontrados:","defaultText":"Especifique un nombre de usuario o clasificación","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce4099d43e1', 'disableAutoComplete', '#ajaxfeedback_24bce4066ce448_0', 'LITHIUM:ajaxError', {}, 'In26ftwNyF3a5-Dyg3y7s8X30YDzAybG-ifD0B_GwxA.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"pUrHMTDkaEKWZUMz4vNXbvtbgtLdgp749vIx8LA6-04.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce4099d43e1\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":0},"inputSelector":"#userSearchField_24bce4066ce448","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.usersearchfield.usersearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AjaxSupport({"ajaxOptionsParam":{"event":"LITHIUM:userExistsQuery","parameters":{"javascript.ignore_combine_and_minify":"true"}},"tokenId":"ajax","elementSelector":"#userSearchField_24bce4066ce448","action":"userExistsQuery","feedbackSelector":"#ajaxfeedback_24bce4066ce448_0","url":"https://community.hubspot.com/t5/community/page.searchformv32.usersearchfield:userexistsquery?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","ajaxErrorEventName":"LITHIUM:ajaxError","token":"oID_W-BeCbnoFFU_P3buvePGjcYBuB6wb42Q2QCS6OA."}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce40a980e0f', 'disableAutoComplete', '#ajaxfeedback_24bce4066ce448_0', 'LITHIUM:ajaxError', {}, 'ALHexXLuvsvQsQwHRgugjhoJwulDQ879qtMzaRamjS4.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"9F4dQPbFa5lBgrgmvmhSllwdk4XWxqLK2KOQ2GbN9BU.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce40a980e0f\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":0},"inputSelector":"#noteSearchField_24bce4066ce448_0","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.notesearchfield.notesearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce40b415b29', 'disableAutoComplete', '#ajaxfeedback_24bce4066ce448_0', 'LITHIUM:ajaxError', {}, 'nTN4fUAi3dpQVCfy0NeWnRIwGbwfv1pIbOCFTBG7-NM.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"qkOHHqqOyMMlrsNEwma_4CNzzg734IDzqY_qNYDTJeg.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce40b415b29\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":0},"inputSelector":"#productSearchField_24bce4066ce448","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.productsearchfield.productsearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AjaxSupport.fromLink('#enableAutoComplete_24bce4066ce448', 'enableAutoComplete', '#ajaxfeedback_24bce4066ce448_0', 'LITHIUM:ajaxError', {}, 'DTeyxa-ZA8xofxY5pOTl0_Qz3jryAoIOo2CjisPZ3hw.', 'ajax'); LITHIUM.Tooltip({"bodySelector":"body#lia-body","delay":30,"enableOnClickForTrigger":false,"predelay":10,"triggerSelector":"#link_24bce4066ce448","tooltipContentSelector":"#link_24bce4066ce448_0-tooltip-element .content","position":["bottom","left"],"tooltipElementSelector":"#link_24bce4066ce448_0-tooltip-element","events":{"def":"focus mouseover keydown,blur mouseout keydown"},"hideOnLeave":true}); LITHIUM.HelpIcon({"selectors":{"helpIconSelector":".help-icon .lia-img-icon-help"}}); LITHIUM.SearchAutoCompleteToggle({"containerSelector":"#searchautocompletetoggle_24bce4066ce448","enableAutoCompleteSelector":".search-autocomplete-toggle-link","enableAutocompleteSuccessEvent":"LITHIUM:ajaxSuccess:enableAutoComplete","disableAutoCompleteSelector":".lia-autocomplete-toggle-off","disableAutocompleteSuccessEvent":"LITHIUM:ajaxSuccess:disableAutoComplete","autoCompleteSelector":".lia-autocomplete-input"}); LITHIUM.SearchForm({"asSearchActionIdSelector":".lia-as-search-action-id","useAutoComplete":true,"selectSelector":".lia-search-form-granularity","useClearSearchButton":false,"buttonSelector":".lia-button-searchForm-action","asSearchActionIdParamName":"as-search-action-id","formSelector":"#lia-searchformV32_24bce4066ce448","asSearchActionIdHeaderKey":"X-LI-AS-Search-Action-Id","inputSelector":"#messageSearchField_24bce4066ce448_0:not(.lia-js-hidden)","clearSearchButtonSelector":null}); LITHIUM.Form.resetFieldForFocusFound(); (function($) { document.querySelector('a.login-link').classList.add('homepage-nav-login'); })(LITHIUM.jQuery); ;(function($){ $(document).ready(function() { $(".custom-user-menu-v2 .nav-link").click(function(e) { e.preventDefault(); $(".nav-popover.profile").toggleClass('show'); }); $(".search-toggle-action-icon-plus").on("click",function(e){ e.preventDefault(); $(this).parent().find(".plus-bar-main-content").toggle(); }); //User Avatar $('.header-tab-nav li span').click(function() { $('.header-tab-nav li span').removeClass("active"); if(this.id == 'profile'){ $('span#profile').addClass("active"); $('.header-tab-nav-content > div#profile-list-wrapper').show(); $('.header-tab-nav-content > div#admin-list-wrapper').hide(); $('.header-tab-nav-content > div#profile-list-wrapper').removeClass('profile-menu-dropdown'); } if(this.id == 'admin'){ $('span#admin').addClass("active"); $('.header-tab-nav-content > div#profile-list-wrapper').hide(); $('.header-tab-nav-content > div#admin-list-wrapper').show(); $('.header-tab-nav-content > div#profile-list-wrapper').addClass('profile-menu-dropdown'); } var indexer = $(this).index(); //gets the current index of (this) which is #header-tab-nav li $('.header-tab-nav-content > div:eq(' + indexer + ')').fadeIn(); //uses whatever index the link has to open the corresponding box }); $(this).mouseup(function (e){ var customButton = $('.nav-popover.profile'); if(!$('.custom-menu-caret').is(e.target) && $('.custom-menu-caret').has(e.target).length === 0){ if(!customButton.is(e.target) && customButton.has(e.target).length === 0){ if (!$('.custom-user-menu-v2 > .nav-link').is(e.target) && $('.custom-user-menu-v2 > .nav-link').has(e.target).length === 0) { customButton.removeClass('show'); } } } var menuWrapper = $('.menu-wrapper'); if(!menuWrapper.is(e.target) && menuWrapper.has(e.target).length === 0){ if (!$('.menu').is(e.target) && $('.menu').has(e.target).length === 0) { menuWrapper.removeClass('offcanvas'); } } var container = $(".plus-bar-main-content"); var customButton = $(".search-toggle-action-icon-plus"); if (!customButton.is(e.target) && customButton.has(e.target).length === 0) { container.hide(); } if(!$('.lang-picker-wrapper').is(e.target) && $('.lang-picker-wrapper').has(e.target).length === 0){ if (!$('.lang-picker').is(e.target) && $('.lang-picker').has(e.target).length === 0) { $('.lang-picker').removeClass('show'); } } }); //SCROLL JS $(window).scroll(function(e) { e.preventDefault(); if($('.nav-popover.profile').hasClass("show")){ if ($(this).scrollTop() > 0) { $('.nav-popover.profile').removeClass("show"); } else { $('.nav-popover.profile').addClass("show"); } } if($('.nav-popover.get-hubspot').hasClass("show")){ if ($(this).scrollTop() > 0) { $('.nav-popover.get-hubspot').removeClass("show"); } else { $('.nav-popover.get-hubspot').addClass("show"); } } if ($(this).scrollTop() > 0) { $('.search-input.lia-search-input-message').blur(); $('.plus-bar-main-content').hide(); } }); }); jQuery('.lang-picker-wrapper').click(function(){ jQuery(".lang-picker").toggleClass('show'); }); jQuery('.lia-cat-sub-editor-modal .lia-ui-modal-footer .lia-button-Submit-action').live('click',function(){ setTimeout( function() { location.reload(true); },1000); }); })(LITHIUM.jQuery); ;(function($){ var langMap = { 'en':'hubspot_community_en', 'es':'hubspot_community_es', 'fr':'hubspot_community_fr', 'ja':'hubspot_community_jp', 'pt-br':'hubspot_community_pt', 'de':'hubspot_community_de' } var nodeType = "community"; var langScope = langMap['es']; var isSearchPage = jQuery('body').hasClass('SearchPage'); var isIdeasLandingPage = jQuery('body').hasClass('ideaslandingpage'); if (nodeType === "community" && !isSearchPage && !isIdeasLandingPage) { var inputFormFilter = '<input name="filter" value="location" type="hidden">'; var inputFormLocation = '<input name="location" value="category:' + langScope + '" type="hidden">'; $('form.SearchForm').append(inputFormFilter).append(inputFormLocation); } else if (nodeType === "community" && isIdeasLandingPage) { var searchUrl = "/t5/forums/searchpage/tab/message?filter=location&location=idea-board:HubSpot_Ideas&collapse_discussion=true"; var query = jQuery('.SearchForm .lia-search-input-message').val(); jQuery(document).on('submit', 'form.SearchForm', function(e) { e.preventDefault(); var newQ = "&q=" + document.querySelector('.SearchForm .lia-search-input-wrapper input.search-input').value; window.location = window.location.origin + searchUrl + newQ; }) } })(LITHIUM.jQuery) LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce40c10967f","feedbackSelector":".InfoMessage"}); LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce40c10967f_0","feedbackSelector":".InfoMessage"}); LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce40c10967f_1","feedbackSelector":".InfoMessage"}); LITHIUM.InformationBox({"updateFeedbackEvent":"LITHIUM:updateAjaxFeedback","componentSelector":"#informationbox_24bce40c10967f_2","feedbackSelector":".InfoMessage"}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce40d8d15cb', 'disableAutoComplete', '#ajaxfeedback_24bce40c10967f_0', 'LITHIUM:ajaxError', {}, 'pFbf0o3iICYP_euDCGdWxD4Wcjr67Is9kLTPSplAtdc.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"U324iDM5RxARcXBLcTE-d3xtbGAUMTKaJ379_oBVRN4.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce40d8d15cb\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":3},"inputSelector":"#messageSearchField_24bce40c10967f_0","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.messagesearchfield.messagesearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce40ee71bae', 'disableAutoComplete', '#ajaxfeedback_24bce40c10967f_0', 'LITHIUM:ajaxError', {}, 'FcQ9gRw2H68649yVyIH4AMwAgA9J2amRrzJzCUlbIi4.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"jaRHfO93_w4AsWdyVlAESvloHZoZlmQu-COLRQzWjMg.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce40ee71bae\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":3},"inputSelector":"#messageSearchField_24bce40c10967f_1","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.tkbmessagesearchfield.messagesearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando por usuarios...","emptyText":"No existen coincidencias","successText":"Usuarios encontrados:","defaultText":"Especifique un nombre de usuario o clasificación","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce40f5205d6', 'disableAutoComplete', '#ajaxfeedback_24bce40c10967f_0', 'LITHIUM:ajaxError', {}, 'CNdQHpuX11MobiwC6Ir-P9Td1IMFK6FJY-4pRUPjdWU.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"6AXXEQZGFe5zzU3ZWFddantZo2Vh_qk9vufjtZoSsUU.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce40f5205d6\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":0},"inputSelector":"#userSearchField_24bce40c10967f","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.usersearchfield.usersearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AjaxSupport({"ajaxOptionsParam":{"event":"LITHIUM:userExistsQuery","parameters":{"javascript.ignore_combine_and_minify":"true"}},"tokenId":"ajax","elementSelector":"#userSearchField_24bce40c10967f","action":"userExistsQuery","feedbackSelector":"#ajaxfeedback_24bce40c10967f_0","url":"https://community.hubspot.com/t5/community/page.searchformv32.usersearchfield:userexistsquery?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","ajaxErrorEventName":"LITHIUM:ajaxError","token":"4Ib6QsirFOj83VmVlYNDvSsqAyjX_h1J8MkQx2RzeFo."}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce40f79ebd4', 'disableAutoComplete', '#ajaxfeedback_24bce40c10967f_0', 'LITHIUM:ajaxError', {}, 'lyW8owLXyQbyXv-fwdlasjzFvHrIXm9WiPHfKeCzbyQ.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"wVWAd5QyHJwnWNDo36mjUscZyEAG4ylWNyqLZ-m4mZg.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce40f79ebd4\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":0},"inputSelector":"#noteSearchField_24bce40c10967f_0","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.notesearchfield.notesearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AutoComplete({"options":{"triggerTextLength":0,"updateInputOnSelect":true,"loadingText":"Buscando...","emptyText":"No existen coincidencias","successText":"Resultados:","defaultText":"Especifique una palabra de búsqueda","disabled":false,"footerContent":[{"scripts":"\n\n;(function($){LITHIUM.Link=function(params){var $doc=$(document);function handler(event){var $link=$(this);var token=$link.data('lia-action-token');if($link.data('lia-ajax')!==true&&token!==undefined){if(event.isPropagationStopped()===false&&event.isImmediatePropagationStopped()===false&&event.isDefaultPrevented()===false){event.stop();var $form=$('<form>',{method:'POST',action:$link.attr('href'),enctype:'multipart/form-data'});var $ticket=$('<input>',{type:'hidden',name:'lia-action-token',value:token});$form.append($ticket);$(document.body).append($form);$form.submit();$doc.trigger('click');}}}\nif($doc.data('lia-link-action-handler')===undefined){$doc.data('lia-link-action-handler',true);$doc.on('click.link-action',params.linkSelector,handler);$.fn.on=$.wrap($.fn.on,function(proceed){var ret=proceed.apply(this,$.makeArray(arguments).slice(1));if(this.is(document)){$doc.off('click.link-action',params.linkSelector,handler);proceed.call(this,'click.link-action',params.linkSelector,handler);}\nreturn ret;});}}})(LITHIUM.jQuery);\r\n\nLITHIUM.Link({\n \"linkSelector\" : \"a.lia-link-ticket-post-action\"\n});LITHIUM.AjaxSupport.fromLink('#disableAutoComplete_24bce40fe02e8e', 'disableAutoComplete', '#ajaxfeedback_24bce40c10967f_0', 'LITHIUM:ajaxError', {}, 'RQnXeezxz5f4aPc_GlKVWID5q43xTACSXdnTBnWwEGM.', 'ajax');","content":"<a class=\"lia-link-navigation lia-autocomplete-toggle-off lia-link-ticket-post-action lia-component-search-action-disable-auto-complete\" data-lia-action-token=\"7iI1L6dyKYkE9p3tJf96c1WdOg8hp9LMuXJhvHvf6sE.\" rel=\"nofollow\" id=\"disableAutoComplete_24bce40fe02e8e\" href=\"https://community.hubspot.com/t5/community/page.disableautocomplete:disableautocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=action/contributions/searchactions\">Desactivar sugerencias<\/a>"}],"prefixTriggerTextLength":0},"inputSelector":"#productSearchField_24bce40c10967f","redirectToItemLink":false,"url":"https://community.hubspot.com/t5/community/page.searchformv32.productsearchfield.productsearchfield:autocomplete?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..&t:cp=search/contributions/page","resizeImageEvent":"LITHIUM:renderImages"}); LITHIUM.AjaxSupport.fromLink('#enableAutoComplete_24bce40c10967f', 'enableAutoComplete', '#ajaxfeedback_24bce40c10967f_0', 'LITHIUM:ajaxError', {}, 'VkNU4Ck5JM8d-vIi7blkjCEpvHDgG2fCOWK4EvMJQMI.', 'ajax'); LITHIUM.Tooltip({"bodySelector":"body#lia-body","delay":30,"enableOnClickForTrigger":false,"predelay":10,"triggerSelector":"#link_24bce40c10967f","tooltipContentSelector":"#link_24bce40c10967f_0-tooltip-element .content","position":["bottom","left"],"tooltipElementSelector":"#link_24bce40c10967f_0-tooltip-element","events":{"def":"focus mouseover keydown,blur mouseout keydown"},"hideOnLeave":true}); LITHIUM.HelpIcon({"selectors":{"helpIconSelector":".help-icon .lia-img-icon-help"}}); LITHIUM.SearchAutoCompleteToggle({"containerSelector":"#searchautocompletetoggle_24bce40c10967f","enableAutoCompleteSelector":".search-autocomplete-toggle-link","enableAutocompleteSuccessEvent":"LITHIUM:ajaxSuccess:enableAutoComplete","disableAutoCompleteSelector":".lia-autocomplete-toggle-off","disableAutocompleteSuccessEvent":"LITHIUM:ajaxSuccess:disableAutoComplete","autoCompleteSelector":".lia-autocomplete-input"}); LITHIUM.SearchForm({"asSearchActionIdSelector":".lia-as-search-action-id","useAutoComplete":true,"selectSelector":".lia-search-form-granularity","useClearSearchButton":false,"buttonSelector":".lia-button-searchForm-action","asSearchActionIdParamName":"as-search-action-id","formSelector":"#lia-searchformV32_24bce40c10967f","nodesModel":{"user|user":{"title":"Usuarios","inputSelector":".lia-search-input-user"},"mjmao93648|community":{"title":"Buscar Comunidad: HubSpot Community","inputSelector":".lia-search-input-message"}},"asSearchActionIdHeaderKey":"X-LI-AS-Search-Action-Id","inputSelector":"#messageSearchField_24bce40c10967f_0:not(.lia-js-hidden)","clearSearchButtonSelector":null}); (function($) { document.querySelector('a.login-link').classList.add('homepage-nav-login'); })(LITHIUM.jQuery); (function($) { if ( $('.lia-notification-feed-page-link').length ) { $('.lia-notification-feed-page-link').addClass('nav-notifs'); } if ( $('.private-notes-link').length ) { $('.private-notes-link').addClass('nav-mail'); } })(LITHIUM.jQuery); ;(function($){ $('.custom-search-focus').on('click', function() { $('.lia-search-input-message').focus(); }); })(LITHIUM.jQuery); // Pull in global jQuery reference if (document.querySelectorAll('.lia-component-admin-widget-moderation-manager')[0]) { document.querySelectorAll('.lia-component-admin-widget-moderation-manager')[0].href = "/t5/bizapps/page/tab/community%3Amoderation?filter=includeForums&sort_by=-topicPostDate&include_forums=true&collapse_discussion=true" } ;(function($) { $("#get-hubspot-free").click(function(){ $("#get-hubspot").toggleClass("show"); }); // Closes dropdown boxes when clicking outside of the box // click listener applied inline, function in script tag window.onclick = function(e) { if (e.target?.matches && !e.target?.matches('#get-hubspot-free')) { if (document.getElementById("get-hubspot")) { if (document.getElementById("get-hubspot").classList.contains('show')) { document.getElementById("get-hubspot").classList.remove('show'); } } } if (e.target?.matches && !e.target?.matches('#current-language')) { if (document.getElementById("lang-picker-global")) { if (document.getElementById("lang-picker-global").classList.contains('show')) { document.getElementById("lang-picker-global").classList.remove('show'); } } } }; $(window).scroll(function(){ if ($(this).scrollTop() > 65) { $('.forum-nav-bar').addClass('ch-sticky'); $('.community-header-nav').addClass('ch-space'); } else { $('.forum-nav-bar').removeClass('ch-sticky'); $('.community-header-nav').removeClass('ch-space');; } }); $('span.custom-menu-caret').on('click',function(){ $(this).siblings('.nav-popover.profile').toggleClass('show'); }); })(LITHIUM.jQuery); (function($) { $(document).ready(function(){ try{ var PostURl = '' if('community'==='board'){ var PostURl = '/t5/forums/postpage/board-id/mjmao93648' }else if('community'==='category') { var PostURl = '/t5/forums/postpage/category-id/mjmao93648'} var searchSelector = $('.custom-search-wrapper .lia-autocomplete-container .lia-autocomplete-footer'); var data = "<div class='search-post-buttons'><span>¿No encuentras lo que buscas?</span> <a href='"+PostURl+"' class='btn btn-sm button-primary'><span>Hacer una pregunta</span></a> </div>"; $(data).insertAfter(searchSelector[0]); }catch(err){ console.log(err); } }); })(LITHIUM.jQuery); (function($) { $(document).ready(function(){ $('.lia-quilt-idea-exchange-page-filtered-v2 .custom-v2-banner .search-input, .lia-quilt-idea-page-filtered .custom-v2-banner .search-input').attr('placeholder', 'Buscar ideas'); }); })(LITHIUM.jQuery); (function($) { $('#loggedInUser').append('Anonymous'); })(LITHIUM.jQuery); ;(function($) { // Custom Tabs Accordian JS var tab = $('.custom-dashboard-tabs__list .custom-dashboard-tabs__item'); var mobileTab = $('.custom-dashboard-tabs__list'); tab.on('click',function(e){ e.preventDefault(); $(this).addClass('active').siblings().removeClass('active'); var selectedTab = $(this).attr('data-tab-id'); var tabsType = $(this).closest('.custom-dashboard-tabs').attr('id'); loadTabContent(selectedTab,tabsType); }); mobileTab.on('change',function(){ var selectedMobileTab= $(this).find(":selected").attr('data-tab-id'); var selectedMobileTabType= $(this).closest(".custom-dashboard-tabs").attr('id'); loadTabContent(selectedMobileTab,selectedMobileTabType); }); function loadTabContent(selectedTab,tabType){ var tabContent = $('.'+tabType+'__content'+' '+'.custom-dashboard-tab-body'); tabContent.removeClass('active'); $('.'+selectedTab).addClass('active'); }; jQuery('.custom-dashboard-accordian-item').click(function(e){ if (!$('.read-more').is(e.target) && $('.read-more').has(e.target).length === 0){ e.preventDefault(); jQuery(this).toggleClass('active').toggleClass('off').siblings().removeClass('active').addClass('off'); jQuery('.off > .custom-dashboard-accordian-item__header > .toggle-action').addClass('on'); jQuery('.active > .custom-dashboard-accordian-item__header > .toggle-action').removeClass('on'); jQuery('.off > .custom-dashboard-accordian-posts-list').slideUp(); jQuery('.active > .custom-dashboard-accordian-posts-list').slideDown(); } }); // Custom Tabs Accordian JS })(LITHIUM.jQuery); function getOuterHtml(elementList) { let returnList = []; for (var i = 0; i < elementList.length; i++) { returnList.push(elementList[i].outerHTML); } return returnList; } function printAuthorRow(element, avatars, users, counts) { const div = document.getElementById(element); for (var i = 0; i < users.length && i < 5; i++) { div.insertAdjacentHTML('beforeend', '<li id="top-author-'+ i +'">'); let li = document.getElementById('top-author-' + i); li.insertAdjacentHTML('beforeend', avatars[i]); li.insertAdjacentHTML('beforeend', users[i]); li.insertAdjacentHTML('beforeend', counts[i]); if(i >= 4){ document.getElementById("viewallwrapper").style.display = "block"; } } } var xhr = new XMLHttpRequest(); var host = window.location.hostname; xhr.open("GET", "https://" + host + "/t5/solutions/acceptedsolutionsleaderboardpage/node-display-id/category%3Ahubspot_community_es/timerange/six_months", true); xhr.onload = function (e) { if (xhr.readyState === 4) { if (xhr.status === 200) { const d = xhr.responseXML; const usernames = d.getElementsByClassName('UserName'); const usernameLinks = d.getElementsByClassName('lia-user-name-link'); const avatars = d.getElementsByClassName('lia-component-common-widget-user-avatar'); const solutionCount = d.getElementsByClassName('base-count-number'); const leaderboardInfo = { usernames: getOuterHtml(usernames), usernameLinks: getOuterHtml(usernameLinks), avatars: getOuterHtml(avatars), solutionCount: getOuterHtml(solutionCount), }; console.log(leaderboardInfo); printAuthorRow('top-solutions', leaderboardInfo.avatars, leaderboardInfo.usernameLinks, leaderboardInfo.solutionCount) } else { console.error(xhr.statusText); } } }; xhr.responseType = "document"; xhr.onerror = function (e) { console.error(xhr.statusText); }; xhr.send(null); LITHIUM.UserListActual({"acceptedSolutionsColumnSelector":".UserList .lia-list-row .acceptedSolutionsCountColumn","kudosColumnSelector":".UserList .lia-list-row .kudosCountColumn"}); ;(function ($) { if ($(window).width() <= 991) { $(".community-footer .col:nth-child(3)").on('click',function(){ if ($(this).hasClass('active')) { $(this).removeClass('active'); $(this).children("ul").hide(); $(this).children("h5").removeClass("addedClass"); } else { $(".community-footer .col").removeClass('active'); $('.community-footer .col ul').hide(); $(this).addClass('active'); $(this).children("ul").show(); $('.community-footer .col').children("h5").removeClass("addedClass"); $(this).children("h5").addClass("addedClass"); } if ( $(".community-footer .col:nth-child(4) ul").hasClass('custom-footer-res')) { $(".community-footer .col:nth-child(4) ul").removeClass('custom-footer-res'); } else { $(".community-footer .col:nth-child(4) ul").addClass('custom-footer-res'); } }) $('.community-footer .col:nth-child(1)').on("click", function () { if ($(this).hasClass('active')) { $(this).removeClass('active'); $(this).children("ul").hide(); $(this).children("h5").removeClass("addedClass"); } else { $(".community-footer .col").removeClass('active'); $('.community-footer .col ul').hide(); $(this).addClass('active'); $(this).children("ul").show(); $('.community-footer .col').children("h5").removeClass("addedClass"); $(this).children("h5").addClass("addedClass"); } if ( $(".community-footer .col:nth-child(4) ul").hasClass('custom-footer-res')) { $(".community-footer .col:nth-child(4) ul").removeClass('custom-footer-res'); } }) $('.community-footer .col:nth-child(2)').on("click", function () { if ($(this).hasClass('active')) { $(this).removeClass('active'); $(this).children("ul").hide(); $(this).children("h5").removeClass("addedClass"); } else { $(".community-footer .col").removeClass('active'); $('.community-footer .col ul').hide(); $(this).addClass('active'); $(this).children("ul").show(); $('.community-footer .col').children("h5").removeClass("addedClass"); $(this).children("h5").addClass("addedClass"); } if ( $(".community-footer .col:nth-child(4) ul").hasClass('custom-footer-res')) { $(".community-footer .col:nth-child(4) ul").removeClass('custom-footer-res'); } }) } })(LITHIUM.jQuery); LITHIUM.PartialRenderProxy({"limuirsComponentRenderedEvent":"LITHIUM:limuirsComponentRendered","relayEvent":"LITHIUM:partialRenderProxyRelay","listenerEvent":"LITHIUM:partialRenderProxy"}); LITHIUM.AjaxSupport({"ajaxOptionsParam":{"event":"LITHIUM:partialRenderProxyRelay","parameters":{"javascript.ignore_combine_and_minify":"true"}},"tokenId":"ajax","elementSelector":document,"action":"partialRenderProxyRelay","feedbackSelector":false,"url":"https://community.hubspot.com/t5/community/page.liabase.basebody.partialrenderproxy:partialrenderproxyrelay?t:ac=q-p/cHJvZmlsZS5sYW5ndWFnZTplcw..","ajaxErrorEventName":"LITHIUM:ajaxError","token":"xE55Rd7cCUibdkHkDAY6bVkuJCEx4MwuXiYqUQHlYyo."}); LITHIUM.Auth.API_URL = "/t5/util/authcheckpage"; LITHIUM.Auth.LOGIN_URL_TMPL = "https://app.hubspot.com/khoros/integration/jwt/authenticate?referer=https%3A%2F%2FREPLACE_TEXT"; LITHIUM.Auth.KEEP_ALIVE_URL = "/t5/status/blankpage?keepalive"; LITHIUM.Auth.KEEP_ALIVE_TIME = 300000; LITHIUM.Auth.CHECK_SESSION_TOKEN = 'OzWudxGZf-sQX9GGrvZznDXQPyD5uesBa0K1vDyi3Ac.'; LITHIUM.AjaxSupport.useTickets = false; LITHIUM.Loader.runJsAttached(); // --> </script></body> </html>