[{"data":1,"prerenderedAt":877},["ShallowReactive",2],{"blog-post-\u002Fblog\u002Ffixing-the-sitefinity-page-editor-drag-and-drop-experience":3,"blog-nav-posts":22},{"id":4,"title":5,"author":6,"body":6,"content":7,"description":6,"extension":8,"image":6,"legacyUrl":6,"markdown":9,"meta":10,"navigation":9,"path":11,"publishedAt":12,"seo":13,"seoDescription":14,"slug":6,"stem":15,"tags":16,"updatedAt":6,"__hash__":21},"blog\u002Fblog\u002Ffixing-the-sitefinity-page-editor-drag-and-drop-experience.json","Why the Sitefinity page editor jumps when you drag a widget",null,"The MVC page editor ships with a pile of drag and drop defects:\n\n- The whole page shifts the moment you pick a widget up, so your drop target moves out from under the cursor\n- Row, column and container all highlight at once, and nothing tells you which one takes the drop\n- The highlight strobes on and off as you cross zone boundaries\n- The thing following your pointer is a pale bar the width of the page instead of something widget shaped\n- Outlines stay on the canvas after the drop until you reload\n- Spacing in the editor doesn't match what publishes\n\nNone of it is your template's fault. It's the default behavior of the Telerik RadDock controls the editor is built on, controls that have not been meaningfully touched since MVC widgets shipped.\n\nAll of it is fixable. Most from your own theme stylesheet, the rest from around 250 lines of javascript, because the strobing is a *timing* problem and a stylesheet can't put a delay on a class it doesn't own. What you end up with: the page holds still, zones fade in and out instead of strobing, the drag helper is a small chip under your cursor, outlines clear themselves, and editor spacing matches published spacing.\n\nEverything below assumes a plain MVC Sitefinity site on a stock Bootstrap 5 resource package. No custom widget framework, nothing exotic in the project. If you've got a Bootstrap 5 package and some `.row` and `.col-*` layouts, this applies to you.\n\n## The page editor is not an iframe\n\nThis trips up most people, and it matters a lot.\n\nYour page gets composed directly into the editor document. Which means two things at once. Your theme stylesheet is already loaded and already applying, so any CSS you write is live in the editor with no extra plumbing. And Sitefinity's editor markup is sitting in the same DOM as your markup, wrapping it.\n\nThat second part is where nearly every problem below comes from. Telerik wraps every layout and every widget in extra nesting that has no counterpart on the published page:\n\n```\n\u003Cdiv class=\"col-md-6 d-flex flex-column gap-3\">   \u003C- yours\n  \u003Cdiv class=\"RadDockZone\">                       \u003C- injected by the editor\n    \u003Cdiv class=\"RadDock\">...widget 1...\u003C\u002Fdiv>      \u003C- injected\n    \u003Cdiv class=\"RadDock\">...widget 2...\u003C\u002Fdiv>      \u003C- injected\n    \u003Cdiv class=\"RadDock rdPlaceHolder\">...\u003C\u002Fdiv>   \u003C- injected, one per zone\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n```\n\nWatch what happens to the gap. On the live page that column has two flex children and spaces them 16px apart. In the editor it has exactly ONE flex child, the `.RadDockZone`, and your widgets are grandchildren. The gap has nothing left to space. So your carefully spaced column renders flush in the editor, an author looks at it, reasonably decides the spacing is broken, and starts \"fixing\" it.\n\nBootstrap's own row gutters survive this, because `.g-4` puts padding on the `.col-*` itself and the injected zone sits inside that padding. Anything that spaces children instead of padding them breaks: `d-flex flex-column gap-3` and friends, plus any custom grid of your own built on `gap`.\n\n## Give yourself a way to win specificity\n\nBefore you write any fixes, add a class of your choosing to `\u003Cbody>` in your page template. Call it whatever you like, I'm using `mytheme` below. Or hang an id on your outer wrapper if that suits your markup better. It just needs to exist.\n\nSitefinity's own editor rules are mostly three classes deep and they are NOT marked `!important`. One extra class on your selector outranks them cleanly and you don't start an `!important` war you'll regret in six months:\n\n```css\n\u002F* Sitefinity: .sfPageContainer .RadDockZone { ... }      = 0,3,0\n   Yours:      body.mytheme.sfPageEditor ... .RadDockZone = 0,4,0 *\u002F\nbody.mytheme.sfPageEditor .sfPageContainer .RadDockZone {\n  margin-bottom: 0;\n}\n```\n\n`sfPageEditor` is a class Sitefinity puts on `\u003Cbody>` in the editor, so that's how you scope anything to editor-only. A few of the fixes below do genuinely need `!important` because Sitefinity marked its own rule that way, and I've called those out.\n\n## Putting back the spacing the editor ate\n\nSince the injected `.RadDockZone` swallows your `gap`, you have to put the spacing back manually between the docks. Sibling margin is what works:\n\n```css\n\u002F* Restores the column gap that the injected zone ate.\n   margin-top, not bottom, so nothing trails the last item.\n   The placeholder is excluded at both ends; it collapses to zero height\n   during a drag, and spacing a zero-height box reintroduces a jump. *\u002F\nbody.mytheme.sfPageEditor\n  .sfPageContainer\n  .gap-3\n  > .RadDockZone\n  > .RadDock:not(.rdPlaceHolder)\n  ~ .RadDock:not(.rdPlaceHolder) {\n  margin-top: 1rem;\n}\n```\n\nKeying off the Bootstrap utility class means you write it once and every column using that utility is covered. If your layouts use a few different gap sizes, write one of these per size, or key off your own layout class instead.\n\nWhile you're in there, kill the spacing that goes the *other* way. Sitefinity puts a 12px bottom margin under every widget dock and another 12px under every empty drop zone. Neither one ships to the published page, so your authors are judging their spacing against 12px of padding that's about to vanish:\n\n```css\nbody.mytheme.sfPageEditor .sfPageContainer .zeControlDock,\nbody.mytheme.sfPageEditor .sfPageContainer .RadDockZone {\n  margin-bottom: 0;\n}\n```\n\nThe widget title bars already separate the docks visually, so you lose nothing by removing it.\n\n## The whole page jumps when you pick anything up\n\nThis is the ugliest default in the editor and the cause genuinely surprised me.\n\nTelerik pre-renders a drop placeholder inside every single zone on the page. I counted 35 of them on one page, all sitting there `display: none` at rest. Start a drag and Telerik puts ALL of them into flow at once, then marks every one except the hovered zone's as `visibility: hidden`.\n\nHidden, but still taking up space. So picking up one widget injects an invisible box into every other zone on the page simultaneously, and everything shifts under your cursor before you've really moved it.\n\nCollapse the resting placeholder to a true zero:\n\n```css\nbody.mytheme.sfPageEditor .sfPageContainer .RadDock.rdPlaceHolder {\n  height: 0 !important;\n  margin: 0 !important;\n  border-width: 0 !important;\n\n  \u002F* Not cosmetic. The placeholder's own box is 0px here, but it holds a 14px\n     \"Drop here\" label that escapes the zeroed box and grows the zone the\n     instant Telerik flips display. Clipping it makes the collapsed\n     placeholder contribute a true 0px. Measured: 13.5px down to 0. *\u002F\n  overflow: hidden;\n}\n```\n\nNotice what that rule does *not* touch: `display`. That's deliberate, and it's the trap. Telerik decides which placeholder is the live one by writing `display` inline from javascript. Override `display` with `!important` and you've taken that decision away from it, so now every zone on the page lights up at once. Zero out the box, leave `display` alone.\n\nThen bring the placeholder back on the zone that's actually the drop target:\n\n```css\nbody.mytheme.sfPageEditor\n  .sfPageContainer\n  .zePlaceholderHighlighted.sfCurrentDragZone:not(.zeDockZoneEmpty):not(\n    :has(.zePlaceholderHighlighted)\n  )\n  .RadDock.rdPlaceHolder {\n  height: 58px !important;\n  margin: 0 12px 1rem !important;\n  border-width: 1px !important;\n}\n```\n\nThat `:not(:has(.zePlaceholderHighlighted))` is doing real work, it isn't tidying. Sitefinity flags every ancestor zone up the chain with the same highlight classes, so without it the rule reads as \"any placeholder anywhere under the drag\" and restores all 35 again, which is the exact problem you just fixed.\n\n## The 1px nudge on drag-approach\n\nSmaller one, but it makes the editor feel loose. Sitefinity ships these three rules, all `!important`:\n\n```css\n.sfPageContainer .RadDockZone                              { padding: 1px }\n.sfPageContainer .RadDockZone.zePlaceholderHighlighted     { padding: 0   }\n.sfPageContainer .zeDockZoneEmpty.zePlaceholderHighlighted { padding: 1px }\n```\n\nSo drag-enter removes 1px of padding on all four sides and the zone's contents step outward. Reads like a border vanishing and everything getting slightly bigger.\n\nThat third rule is Sitefinity trying to undo the second one, and it can never match. Sitefinity strips `.zeDockZoneEmpty` at the same moment it adds `.zePlaceholderHighlighted`, so those two classes are never on an element together. Put the padding back yourself, on every zone:\n\n```css\nbody.mytheme.sfPageEditor .sfPageContainer .RadDockZone.zePlaceholderHighlighted {\n  padding: 1px !important;\n}\n```\n\n### The `.zeDockZoneEmpty` trap\n\nThat generalizes, and it's probably the most useful thing in this post, so it gets its own heading.\n\n`.zeDockZoneEmpty` is a *rest state* flag. Sitefinity removes it the instant a drag enters the zone and adds it back afterwards. So any styling you hang off it disappears at exactly the moment it was doing its job.\n\nI hit this three separate times before the pattern clicked. An empty-state height floor keyed on that class collapsed cards from 120px to 71px mid-drag, so everything below jumped under the cursor. Empty-zone styling vanished the second a drag arrived, leaving the placeholder fill flooding a white card.\n\nTest for emptiness by content instead. It survives Sitefinity's class swapping because it describes what's actually in the zone:\n\n```css\n\u002F* \"holds no dock of its own that isn't the placeholder\" *\u002F\n.RadDockZone:not(:has(> .RadDock:not(.rdPlaceHolder)))\n```\n\n## Stacked dashed outlines that never go away\n\nSitefinity marks every zone up the ancestor chain with `.zePlaceholderHighlighted.sfCurrentDragZone`, so one drop target draws a stack of nested dashed outlines. On a Bootstrap layout that's usually three deep, container and row and column, all outlined at once. Sitefinity also never clears those flags after the drop, so the outlines just sit on the canvas until you reload.\n\nThe placeholder fill already marks the live target, so the outlines are noise:\n\n```css\nbody.mytheme.sfPageEditor .sfPageContainer .zePlaceholderHighlighted,\nbody.mytheme.sfPageEditor .sfPageContainer .sfCurrentDragZone {\n  \u002F* transparent, not `border: none`. The width has to stay, or every ancestor\n     loses 2px on hover and the whole page shifts. *\u002F\n  border-color: transparent !important;\n}\n```\n\nThen bring the outline back on the one zone where it's actually useful, an empty leaf zone, using the content test from above instead of `.zeDockZoneEmpty`:\n\n```css\nbody.mytheme.sfPageEditor\n  .sfPageContainer\n  .RadDockZone.sfCurrentDragZone:not(:has(> .RadDock:not(.rdPlaceHolder))) {\n  border-color: var(--bs-primary) !important;\n  background-color: rgb(13 110 253 \u002F 6%);\n}\n```\n\nColors only here, never the border *width*. Rest state can be a fractional border width, so writing `1px` resizes the border box on drag-enter and shifts the page. Same reason the rule above says `transparent` instead of `border: none`.\n\n## That page-wide bar you drag around\n\nWhen you drag a widget, the thing following your cursor should look like a widget. By default it's a pale bar spanning the full page width with a tiny label way over at the far left.\n\nThere's no ghost and no clone involved here. Telerik drags the real element. On drag start it measures the dock, writes that measurement back as an inline `width`, bumps the z-index and reparents the live node, then adds a class to it. That inline width is the widget's full layout width, which is why you get a bar.\n\nAn author `!important` rule outranks an inline style, so this is fixable. The `editor-dragging` class comes from the script in the next section:\n\n```css\nbody.mytheme.sfPageEditor.editor-dragging .RadDock.rdDragHelper {\n  width: fit-content !important;\n  max-width: 220px !important;\n  min-width: 0 !important;\n  height: auto !important;\n  overflow: hidden;\n\n  border: 1px solid var(--bs-border-color);\n  border-radius: var(--bs-border-radius);\n  background: var(--bs-body-bg);\n  box-shadow:\n    0 1px 2px rgb(0 0 0 \u002F 8%),\n    0 8px 20px -4px rgb(0 0 0 \u002F 18%);\n}\n```\n\nThree things about that, and the third is why this section doesn't end here.\n\nThe class name is `.rdDragHelper`, which I got by reading `RadDock.prototype._draggedCssClass` in the browser console on a live editor page. It is not documented anywhere. Guessing gets you `.rdDrag` or `.rdDockDragWrapper`, neither of which matches anything, and your rule just sits there dead. Check that property against your own Sitefinity version before you write the selector.\n\nYou don't need to clean the overrides up. Telerik restores the inline width and z-index on drag end and removes the class, so all of it lapses on its own.\n\nAnd now your chip is in the wrong place. Telerik never stores your grab point. On mousedown the dragged element just keeps whatever offset it had from the cursor, and every mousemove applies a delta to wherever the element currently sits. That's invisible at full width, because the bar is under the pointer no matter where you grabbed it. Shrink an 800px title bar down to 100px though, and a grab at x=400 leaves the chip stranded 400px to the left of your pointer, still faithfully tracking your movements from over there. Fixing the width is what creates this, so the CSS above is only half the fix. Other half is `anchorToCursor` in the script.\n\n## Why a stylesheet can't finish the job\n\nEverything so far has been CSS, and CSS runs out of road at four specific points.\n\nThe strobing is a *timing* problem, not an appearance one. RadDock has no drag hysteresis at all. A zone lights on the very first hit-test frame that touches it and goes dark on the first frame that misses, so a cursor traveling across zone borders makes the highlight flicker. Then it gets worse. Lighting a populated zone inflates its placeholder by around 80px, which reflows everything below it and can slide a *different* zone under a stationary cursor, which re-triggers the whole thing. That's the feedback loop behind zones that seem to chase your pointer around, and no stylesheet can add a delay to a class it doesn't control.\n\nThe drag-helper rule needs a hook. Telerik adds `.rdDragHelper` to the dock, but nothing on `body` says a drag is in progress, so there's no way to scope drag-only rules from CSS alone.\n\nThe chip needs repositioning, which is the stranding problem from the last section. That's arithmetic against a live mouse event.\n\nAnd the placeholder height transition silently refuses to run. Telerik flips the placeholder from `display: none` to `block` and your class arrives in the same style recalculation, so the browser has no start value to interpolate from and jumps straight to the end. It needs a forced style flush in between, which is a javascript-only trick.\n\nSo that's what the script is for. Four jobs, and none of them are clever: it debounces the un-highlight so a zone stays lit for a beat while your mouse settles, forces a style flush so the placeholder height actually animates instead of snapping, puts a class on `body` for the drag-only CSS to key off, and yanks the shrunken chip back under your cursor once at drag start.\n\nNote which edge gets the debounce. Lighting a zone is immediate, at `ENTER_DELAY_MS = 0`, because a delay there just reads as lag. It's the *un*-lighting that waits, 80ms, and re-entering inside that window cancels it outright. That's the whole trick behind zones that stop flickering when you drag across a boundary.\n\nIt's around 250 lines, and it patches Telerik prototypes, which means it is going to look extremely deletable to whoever finds it next. Leave a header comment explaining why it's there.\n\n```javascript\n(function () {\n  'use strict';\n\n  \u002F\u002F Enter is immediate. A non-zero enter delay splits the drop feedback into a\n  \u002F\u002F staged three-beat pop, because zePlaceholderHighlighted is not just a\n  \u002F\u002F highlight: Sitefinity gates the \"Drop here\" label on it, our placeholder\n  \u002F\u002F inflate rule keys on it, and Telerik sets the placeholder's display from JS\n  \u002F\u002F synchronously. Delaying the class delays two of the three beats and leaves\n  \u002F\u002F the third at t=0. Tested at 100ms and it reads as laggy.\n  var ENTER_DELAY_MS = 0;\n  \u002F\u002F The exit linger is the part that earns its keep. It stops the highlight\n  \u002F\u002F flickering off and on when the cursor grazes a zone boundary. It is also a\n  \u002F\u002F delay the user feels on every leave, and it stacks on the fade-out\n  \u002F\u002F transition, so keep the two together near 100ms total.\n  var LEAVE_LINGER_MS = 80;\n  var DRAGGING_CLASS = 'editor-dragging';\n  var CURSOR_OFFSET_PX = 10;\n\n  \u002F\u002F Defence in depth. Never let this run on a published page.\n  function isPageEditor() {\n    var body = document.body;\n    if (!body) {\n      return false;\n    }\n    return body.classList.contains('mytheme') && body.classList.contains('sfPageEditor');\n  }\n\n  var patched = false;\n  \u002F\u002F Zones with a pending or applied highlight, so a drag end can flush them all.\n  var trackedZones = [];\n\n  function state(zone) {\n    if (!zone._highlight) {\n      zone._highlight = { enterTimer: null, leaveTimer: null, cssClass: null, lit: false };\n    }\n    return zone._highlight;\n  }\n\n  function clearTimers(st) {\n    if (st.enterTimer) {\n      clearTimeout(st.enterTimer);\n      st.enterTimer = null;\n    }\n    if (st.leaveTimer) {\n      clearTimeout(st.leaveTimer);\n      st.leaveTimer = null;\n    }\n  }\n\n  \u002F\u002F Runs fn with the zone's own class helpers shadowed, and returns the class\n  \u002F\u002F name the original code tried to add or remove. This is how only the\n  \u002F\u002F highlight gets deferred while everything else stays synchronous.\n  function captureHighlightClass(zone, fn) {\n    var captured = null;\n    zone.addCssClass = function (cssClass) {\n      captured = cssClass;\n    };\n    zone.removeCssClass = function (cssClass) {\n      captured = cssClass;\n    };\n    try {\n      fn();\n    } finally {\n      delete zone.addCssClass;\n      delete zone.removeCssClass;\n    }\n    return captured;\n  }\n\n  function light(zone, cssClass) {\n    var st = state(zone);\n    st.cssClass = cssClass;\n    st.lit = true;\n\n    \u002F\u002F Load-bearing, not a stray debug line. Telerik's _showPlaceholder has just\n    \u002F\u002F flipped the placeholder from display:none to block; without a flush here\n    \u002F\u002F the height change lands in the same style recalc, the transition has no\n    \u002F\u002F start value to interpolate from, and it silently does not run. Reading\n    \u002F\u002F the placeholder's own computed height is what establishes that start\n    \u002F\u002F value. Reading document.body.offsetHeight also forces layout but does\n    \u002F\u002F not establish it, and cost 66ms on a full page.\n    var placeholder = zone.get_element().querySelector(':scope > .RadDock.rdPlaceHolder');\n    if (placeholder) {\n      void getComputedStyle(placeholder).height;\n    }\n    zone.addCssClass(cssClass);\n  }\n\n  function unlight(zone) {\n    var st = state(zone);\n    if (st.cssClass) {\n      zone.removeCssClass(st.cssClass);\n    }\n    st.lit = false;\n  }\n\n  function scheduleEnter(zone, cssClass) {\n    var st = state(zone);\n    \u002F\u002F Re-entering during the linger window is a no-op: the zone is still lit,\n    \u002F\u002F which is the whole point of a sticky target.\n    clearTimers(st);\n    if (trackedZones.indexOf(zone) === -1) {\n      trackedZones.push(zone);\n    }\n    if (st.lit) {\n      return;\n    }\n    \u002F\u002F Zero means synchronous, not setTimeout(0). The highlight has to land in\n    \u002F\u002F the same frame as the placeholder Telerik just showed, and a 0ms timer is\n    \u002F\u002F still a separate macrotask and a separate paint.\n    if (ENTER_DELAY_MS \u003C= 0) {\n      light(zone, cssClass);\n      return;\n    }\n    st.enterTimer = setTimeout(function () {\n      st.enterTimer = null;\n      light(zone, cssClass);\n    }, ENTER_DELAY_MS);\n  }\n\n  function scheduleLeave(zone) {\n    var st = state(zone);\n    clearTimers(st);\n    \u002F\u002F Left before the enter delay elapsed, so it never lit. Nothing to undo.\n    if (!st.lit) {\n      return;\n    }\n    st.leaveTimer = setTimeout(function () {\n      st.leaveTimer = null;\n      unlight(zone);\n    }, LEAVE_LINGER_MS);\n  }\n\n  \u002F\u002F A drag can end mid-linger. Without this the highlight stays on the page.\n  function flushAll() {\n    for (var i = 0; i \u003C trackedZones.length; i++) {\n      var zone = trackedZones[i];\n      clearTimers(state(zone));\n      unlight(zone);\n    }\n    trackedZones.length = 0;\n  }\n\n  function patchZoneHysteresis(zoneProto) {\n    if (typeof zoneProto.dragEnterTarget !== 'function' || typeof zoneProto.dragLeaveTarget !== 'function') {\n      return;\n    }\n\n    var originalEnter = zoneProto.dragEnterTarget;\n    var originalLeave = zoneProto.dragLeaveTarget;\n\n    zoneProto.dragEnterTarget = function () {\n      var zone = this;\n      var args = arguments;\n      var cssClass = captureHighlightClass(zone, function () {\n        originalEnter.apply(zone, args);\n      });\n      if (cssClass) {\n        scheduleEnter(zone, cssClass);\n      }\n    };\n\n    zoneProto.dragLeaveTarget = function () {\n      var zone = this;\n      var args = arguments;\n      captureHighlightClass(zone, function () {\n        originalLeave.apply(zone, args);\n      });\n      scheduleLeave(zone);\n    };\n  }\n\n  \u002F\u002F Re-anchors the shrunken chip to the pointer. Once, on drag start.\n  \u002F\u002F\n  \u002F\u002F Telerik's Draggable positions classically: each mousemove computes a delta\n  \u002F\u002F against the previous mouse position and applies it to wherever the element\n  \u002F\u002F currently is. It never recomputes an absolute position from the grab point,\n  \u002F\u002F so one correction here is preserved for the rest of the drag and the chip\n  \u002F\u002F tracks the pointer 1:1 from then on. That is why this does not need a\n  \u002F\u002F per-move handler, and why adding one would be strictly worse.\n  \u002F\u002F\n  \u002F\u002F Do not switch this to overwriting the Draggable's startPosition. That field\n  \u002F\u002F only drives the useTransformations branch, which this build does not take.\n  function anchorToCursor(dock, args) {\n    var domEvent = args && typeof args.get_domEvent === 'function' ? args.get_domEvent() : null;\n    \u002F\u002F jQuery-normalized events keep the native one on .originalEvent.\n    var raw = domEvent && domEvent.originalEvent ? domEvent.originalEvent : domEvent;\n    if (!raw) {\n      return;\n    }\n\n    var pageX = raw.pageX;\n    var pageY = raw.pageY;\n    if (typeof pageX !== 'number' && raw.touches && raw.touches.length > 0) {\n      pageX = raw.touches[0].pageX;\n      pageY = raw.touches[0].pageY;\n    }\n    if (typeof pageX !== 'number' || typeof pageY !== 'number') {\n      return;\n    }\n\n    \u002F\u002F setLocation takes page coordinates and works out left\u002Ftop against the\n    \u002F\u002F offset parent, which matters because _startDragDrop has just reparented\n    \u002F\u002F the dock to the form.\n    if (!window.$telerik || typeof $telerik.setLocation !== 'function') {\n      return;\n    }\n    $telerik.setLocation(dock.get_element(), {\n      x: pageX + CURSOR_OFFSET_PX,\n      y: pageY + CURSOR_OFFSET_PX\n    });\n  }\n\n  function patchDockDrag(dockProto) {\n    if (typeof dockProto._dragStartHandler !== 'function' || typeof dockProto._dragEndHandler !== 'function') {\n      return;\n    }\n\n    var originalStart = dockProto._dragStartHandler;\n    var originalEnd = dockProto._dragEndHandler;\n\n    dockProto._dragStartHandler = function (sender, args) {\n      var result = originalStart.apply(this, arguments);\n      \u002F\u002F The original returns false when the drag is refused or cancelled.\n      if (result !== false) {\n        document.body.classList.add(DRAGGING_CLASS);\n        anchorToCursor(this, args);\n      }\n      return result;\n    };\n\n    dockProto._dragEndHandler = function () {\n      try {\n        return originalEnd.apply(this, arguments);\n      } finally {\n        document.body.classList.remove(DRAGGING_CLASS);\n        flushAll();\n      }\n    };\n  }\n\n  function applyPatches() {\n    if (patched || !isPageEditor()) {\n      return;\n    }\n    var ui = window.Telerik && window.Telerik.Web && window.Telerik.Web.UI;\n    if (!ui || !ui.RadDock || !ui.RadDockZone) {\n      return;\n    }\n    patchZoneHysteresis(ui.RadDockZone.prototype);\n    patchDockDrag(ui.RadDock.prototype);\n    patched = true;\n  }\n\n  \u002F\u002F RadControls load late and re-register after every WebForms partial\n  \u002F\u002F postback, so try on each load until the prototypes are actually there.\n  if (window.Sys && window.Sys.Application) {\n    Sys.Application.add_load(applyPatches);\n  }\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', applyPatches);\n  } else {\n    applyPatches();\n  }\n})();\n```\n\nFour things before you paste that in.\n\nThe rule a future edit must not break is that the structural calls inside `dragEnterTarget` and `dragLeaveTarget`, meaning `_showPlaceholder` and `_hidePlaceholder` plus the enter and leave events, stay synchronous. Drop targeting and `canDrop` read that state, so deferring it breaks where widgets actually land. Only the highlight class gets deferred, and `captureHighlightClass` is how it manages that. It shadows the *instance's* `addCssClass` and `removeCssClass` for the duration of the original call, while the placeholder helpers reach for `Sys.UI.DomElement.addCssClass` directly and are unaffected. Verify that on your own build.\n\nEvery patch is guarded. If a method goes missing after an upgrade the patch is skipped and you get default behavior rather than a broken editor. Which matters more than usual here, because these hooks came out of `Object.getOwnPropertyNames(Telerik.Web.UI.RadDockZone.prototype)` in the console, not out of documentation. Run that yourself if the script ever goes quiet.\n\nRegistration happens on every `Sys.Application` load, not once on DOM ready. RadControls load late and re-register after WebForms partial postbacks, so a single early attempt finds no prototypes and silently does nothing.\n\nAnd `_dragEndHandler` wraps the original in `try`\u002F`finally`. If the original throws, the body class and any lingering highlights still get cleaned up, instead of leaving the editor stuck in a permanent drag state until somebody reloads.\n\n## Matching the CSS to the script\n\nWith the timing handled in javascript, add a pair of transitions. Asymmetric on purpose:\n\n```css\n\u002F* Soft in, quick out. The base rule is the exit duration, because it is the\n   computed style once the class comes off. A symmetric fade stacks on top of\n   the 80ms leave linger and the highlight reads as hanging around after the\n   cursor has gone. *\u002F\nbody.mytheme.sfPageEditor .sfPageContainer .RadDockZone {\n  transition:\n    background-color 80ms ease-out,\n    border-color 80ms ease-out;\n}\n\nbody.mytheme.sfPageEditor .sfPageContainer .RadDockZone.zePlaceholderHighlighted {\n  transition:\n    background-color 130ms ease-out,\n    border-color 130ms ease-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  body.mytheme.sfPageEditor .sfPageContainer .RadDockZone {\n    transition: none;\n  }\n}\n```\n\nAnimating layout during a drag is normally the thing you avoid. It's safe here for one specific reason: RadDock hit-tests only from raw mouse events, so layout moving under a stationary cursor cannot re-fire the hit test. No cursor motion, no feedback loop.\n\n## Two small ones\n\nSitefinity's widget title bars are `#f4f6f7`, which assumes a white canvas. Bootstrap's default `--bs-body-bg` is white so out of the box you may never notice. Set it to anything else, which most real sites do, and the bars all but vanish and the editor loses its structure. Pick a color that reads as a header band against both your canvas and your cards, and keep it lighter than the widget it labels. The title bar is chrome, it should sit behind the content it names.\n\nFair warning, Sitefinity's border rule on those bars is six classes deep AND `!important`, so a short selector will silently apply your background while dropping your border. That's an odd-looking half-applied result that cost me a while to figure out.\n\nThe other one is a single rule. Every toolbox tile and every placed widget carries a blue \"MVC\" badge drawn as `::after` content. On a busy page that's over a hundred of them, labeling an implementation detail no author will ever act on:\n\n```css\nbody.mytheme.sfPageEditor .sfMvcIcn::after {\n  display: none;\n}\n```\n\n## None of this should be my job\n\nNone of it touches how the page renders for visitors, at least. Every rule is scoped behind `.sfPageEditor`, and the script refuses to patch anything unless it finds that class on `body`. Worst case is that a Sitefinity upgrade renames a hook, the selector stops matching or the guarded patch gets skipped, and you're back to the default behavior with nothing broken.\n\nBut look at what's actually in this post. A drop placeholder pre-rendered into all 35 zones on the page and shoved into flow the instant you pick anything up. A CSS rule Sitefinity wrote to undo its own padding change that can never match, because the two classes in the selector are never on an element at the same time. A drag helper stretched to the full page width, which then strands itself hundreds of pixels from your pointer the moment you correct the width, because nobody ever stored the grab point. Highlight logic with no hysteresis whatsoever, feeding back into itself through its own reflow. These aren't edge cases you'd only hit on a weird template, this is what the editor does on a stock Bootstrap 5 package on day one.\n\nAnd it has done all of it, unchanged, since MVC widgets shipped. Same RadDock, same behavior, same 12px margins that don't exist on the published page. Nobody at Progress or Telerik has spent an afternoon dragging a Content Block around and asking why the page moves. I got there by monkey-patching `dragEnterTarget` from the outside, off class names I pulled out of `Object.getOwnPropertyNames` because none of it is documented, and by forcing a style flush through a `getComputedStyle` read to make a transition run at all. Progress owns the source. An 80ms leave linger is not a hard problem when you can just edit the control.\n\nWhat actually bothers me is the reason. Progress moved on to the .NET Core renderer, so MVC gets security patches and nothing else. Fine as a roadmap decision, I guess. Except there are a very large number of MVC sites in production right now, built by people who bought the platform on the strength of MVC widgets, and the content authors who live in that editor eight hours a day are not going to get a rewritten frontend because their vendor changed direction. They just get an editor that fights them, permanently, and a partner who has decided that's finished. Maintenance mode is a decision about a codebase. Somebody still has to use the thing.\n\nAnyway. Verify every class name against your own editor rather than trusting a blog post, this one included. These are internal Telerik class names and prototype methods. They're stable enough to build on, they're not contractual, and one wrong name is the difference between a fix and a rule that silently does nothing.\n","json",true,{},"\u002Fblog\u002Ffixing-the-sitefinity-page-editor-drag-and-drop-experience","2026-08-05T10:45:00",{"title":5},"The Sitefinity MVC page editor shifts the page on every drag, strobes drop zones and drags a page-wide bar. The CSS and RadDock patches that fix it.","blog\u002Ffixing-the-sitefinity-page-editor-drag-and-drop-experience",[17,18,19,20],"Tutorial","Fixes","Sitefinity","Rants","FZFcoIJg8QC4FwrlG2eIs3KEQ-g9CPEOH3U1qA_HQ_M",[23,25,30,36,41,46,51,56,61,66,71,76,81,86,91,96,101,106,112,117,123,128,134,139,144,149,154,159,164,169,174,179,184,189,194,199,205,210,215,220,225,230,235,240,245,250,255,261,266,271,276,281,286,291,296,301,306,311,316,321,326,331,336,341,346,351,356,361,366,371,376,381,386,391,396,401,406,411,416,421,426,431,436,441,446,451,456,461,466,471,476,481,486,491,496,501,506,511,516,521,526,531,536,541,546,551,556,561,566,571,576,581,586,591,596,601,606,611,616,621,626,631,636,641,646,651,656,661,666,671,676,681,686,691,697,702,707,712,717,722,727,732,737,742,747,752,757,762,767,772,777,782,787,792,797,802,807,812,817,822,827,832,837,842,847,852,857,862,867,872],{"path":11,"title":5,"publishedAt":12,"tags":24},[17,18,19,20],{"path":26,"title":27,"publishedAt":28,"tags":29},"\u002Fblog\u002Fsitefinity-search-not-finding-text-inside-pdf-powerpoint-excel","Sitefinity search can't find the words inside your PDFs, PowerPoints or spreadsheets","2026-07-14T09:20:00",[17,18,19],{"path":31,"title":32,"publishedAt":33,"tags":34},"\u002Fblog\u002Fvue-3-vite-8-tailwind-css-v4-on-sitefinity-cms-complete-setup-guide-with-code-splitting","Vue 3 + Vite 8 + Tailwind CSS v4 on Sitefinity CMS: Complete Setup Guide with Code Splitting","2026-03-19T19:44:00",[17,35],"VueJs",{"path":37,"title":38,"publishedAt":39,"tags":40},"\u002Fblog\u002Fsitefinity-mcp-server-ai-tools-for-your-cms","I Built an MCP Server for Sitefinity","2026-02-12T10:00:00.000Z",[17,19],{"path":42,"title":43,"publishedAt":44,"tags":45},"\u002Fblog\u002Fsitefinity-discover-formresponse-metafields-for-custom-export","Sitefinity Discover FormResponse MetaFields for custom export","2026-01-16T09:12:00.000Z",[17,19],{"path":47,"title":48,"publishedAt":49,"tags":50},"\u002Fblog\u002Fdirect-sql-access-to-sitefinity-dynamic-content-for-easy-poco-mapping","Direct SQL Access to Sitefinity Dynamic Content for Easy POCO Mapping","2025-08-15T14:28:00",[19],{"path":52,"title":53,"publishedAt":54,"tags":55},"\u002Fblog\u002Fkendoui-pricing-is-disjointed-from-reality-and-other-things","KendoUI pricing is disjointed from reality, and other things","2025-08-05T14:59:00",[20],{"path":57,"title":58,"publishedAt":59,"tags":60},"\u002Fblog\u002Fautomatically-correcting-semantic-headings-for-cms-content","Automatically Correcting Semantic Headings for CMS Content","2025-07-18T09:00:00",[],{"path":62,"title":63,"publishedAt":64,"tags":65},"\u002Fblog\u002Feasier-faster-sitefinity-contentlocations-api","Easier, Sitefinity ContentLocations API","2025-06-03T10:32:00",[17,19],{"path":67,"title":68,"publishedAt":69,"tags":70},"\u002Fblog\u002Fshowing-instructions-sitefinity-autogenerated-designers","Instructions for Sitefinity Autogenerated Designers","2025-03-10T12:04:58.788Z",[17,19],{"path":72,"title":73,"publishedAt":74,"tags":75},"\u002Fblog\u002Fnativescript-ios-simulator-laravel-api-error-the-certificate-for-this-server-is-invalid","Nativescript iOS Simulator Laravel API Error: The certificate for this server is invalid","2024-12-19T14:26:15.640Z",[17,18],{"path":77,"title":78,"publishedAt":79,"tags":80},"\u002Fblog\u002Finstall-unsupported-visual-studio-2022-extension-into-vs2022-arm","This extension is not installable on any currently installed products Visual Studio 2022 ARM","2024-02-29T00:52:53.302Z",[17,18],{"path":82,"title":83,"publishedAt":84,"tags":85},"\u002Fblog\u002Frunning-sitefinity-on-apple-silicon-with-parallels","Running Sitefinity on Apple Silicon with Parallels","2023-11-23T14:59:55.098Z",[17],{"path":87,"title":88,"publishedAt":89,"tags":90},"\u002Fblog\u002Fdefining-which-controller-action-or-json-route-to-post-to-when-theres-more-than-one-on-the-page","Defining which Controller Action or Json route to POST to when there's more than one on the page","2023-08-11T18:56:52.701Z",[17,19,18],{"path":92,"title":93,"publishedAt":94,"tags":95},"\u002Fblog\u002Ftimezone-conversion-from-sitefinity-odata-event-api-service","Timezone conversion from Sitefinity OData Event API Service","2023-04-13T19:08:48.349Z",[17,19],{"path":97,"title":98,"publishedAt":99,"tags":100},"\u002Fblog\u002Fhow-to-get-the-saved-controller-properties-for-a-widget-on-a-page","How to get the saved Controller properties for a widget on a page","2023-04-04T16:01:53.545Z",[17,19],{"path":102,"title":103,"publishedAt":104,"tags":105},"\u002Fblog\u002Funable-to-directly-link-to-a-backend-advanced-configuration-section","Unable to directly link to a backend Advanced Configuration Section","2023-03-17T16:44:12.109Z",[17,19],{"path":107,"title":108,"publishedAt":109,"tags":110},"\u002Fblog\u002Fhow-to-join-a-party-with-xbox-xcloud-and-not-get-the-ms-xbl-multiplayer-link-error","How to join a party with XBox xCloud and not get the ms-xbl-multiplayer link error","2022-12-27T21:48:01.644Z",[17,111],"Other",{"path":113,"title":114,"publishedAt":115,"tags":116},"\u002Fblog\u002Fauditing-page-permissions","Auditing page permissions","2022-11-16T14:07:18.061Z",[17,19],{"path":118,"title":119,"publishedAt":120,"tags":121},"\u002Fblog\u002Flaravel-is-better-than-sitefinity-for-small-projects","Laravel is better than Sitefinity for small projects","2022-08-19T14:20:29.093Z",[122,19],"Reviews",{"path":124,"title":125,"publishedAt":126,"tags":127},"\u002Fblog\u002Fadding-a-class-to-the-body-tag-when-a-widget-is-on-the-page","Adding a class to HTML when a custom widget is on the page","2022-04-07T11:42:59.789Z",[17,19],{"path":129,"title":130,"publishedAt":131,"tags":132},"\u002Fblog\u002Fcustom-function-validation-in-kendoui-spreadsheet","Custom Function Validation in KendoUI Spreadsheet","2021-12-08T14:20:23.396Z",[17,133],"KendoUI",{"path":135,"title":136,"publishedAt":137,"tags":138},"\u002Fblog\u002Fadding-telerik-reporting-v15-to-sitefinity-in-2021","Adding Telerik Reporting v15+ to Sitefinity in 2021","2021-11-26T16:36:51.711Z",[17,19,35,133],{"path":140,"title":141,"publishedAt":142,"tags":143},"\u002Fblog\u002Fuse-vuejs-with-sitefinity","Use VueJs with Sitefinity","2021-11-16T14:15:04.251Z",[17,35,19],{"path":145,"title":146,"publishedAt":147,"tags":148},"\u002Fblog\u002Fvuejs-upload-input-though-a-regular-form-postback","VueJs Upload Input though a regular form postback","2021-09-09T12:14:01.621Z",[17,35],{"path":150,"title":151,"publishedAt":152,"tags":153},"\u002Fblog\u002Fdownloading-a-file-through-a-login-page","Downloading a file through a login page","2021-08-05T14:27:59.581Z",[17,19],{"path":155,"title":156,"publishedAt":157,"tags":158},"\u002Fblog\u002Fsitefinity-anonymous-form-submissions","Sitefinity anonymous form submissions","2021-06-15T19:10:54.296Z",[17,19],{"path":160,"title":161,"publishedAt":162,"tags":163},"\u002Fblog\u002Fadding-metaproperties-like-opengraph-to-sitefinity-actionresult-routes","Adding MetaProperties like OpenGraph to ActionResult routes","2021-04-06T12:40:46.905Z",[17,19],{"path":165,"title":166,"publishedAt":167,"tags":168},"\u002Fblog\u002Fviewing-whats-in-your-sitefinity-sitemap","Viewing what's in your Sitefinity Sitemap","2021-03-25T13:41:01.367Z",[17,19],{"path":170,"title":171,"publishedAt":172,"tags":173},"\u002Fblog\u002Fsitefinity-controller-actionresult-not-routing-properly","Sitefinity Controller ActionResult not routing properly","2021-03-19T18:03:13.041Z",[18,19],{"path":175,"title":176,"publishedAt":177,"tags":178},"\u002Fblog\u002Fblocking-bottraffic-or-trafficbot-url-requests-from-jacking-up-your-google-analytics","Blocking bottraffic or trafficbot url requests from jacking up your Google Analytics","2021-02-04T19:15:06.784Z",[17,19],{"path":180,"title":181,"publishedAt":182,"tags":183},"\u002Fblog\u002Fcreate-a-scheduled-task-cron-job-in-sitefinity","Create a Scheduled Task\\Cron job in Sitefinity","2021-01-22T15:05:14.948Z",[17,19],{"path":185,"title":186,"publishedAt":187,"tags":188},"\u002Fblog\u002Fsitefinity-signing-certificate-not-configured","Sitefinity Signing certificate not configured","2021-01-08T13:44:06.598Z",[17,19],{"path":190,"title":191,"publishedAt":192,"tags":193},"\u002Fblog\u002Fbinding-sitefinity-form-field-to-remote-data","Populating a Sitefinity Form Field from a remote API","2020-09-29T18:03:07.941Z",[17,19],{"path":195,"title":196,"publishedAt":197,"tags":198},"\u002Fblog\u002Fexclude-pages-from-netlifys-sitemap-plugin","Exclude pages from netlifys sitemap plugin","2020-08-19T23:01:18.599Z",[17,35],{"path":200,"title":201,"publishedAt":202,"tags":203},"\u002Fblog\u002Ftailwindcss-current-responsive-size","Showing your Tailwindcss Responsive Breakpoint","2020-08-05T09:35:32.000Z",[17,204],"TailwindCss",{"path":206,"title":207,"publishedAt":208,"tags":209},"\u002Fblog\u002Fsitefinity-saml2-login","Configure Sitefinity with SAML2 Authentication","2020-07-06T23:27:17.9000000Z",[17],{"path":211,"title":212,"publishedAt":213,"tags":214},"\u002Fblog\u002Fdynamically-navigate-content-from-list-to-detail","Navigating from List to Detail no hardcoded routes","2020-06-23T19:43:37.8430000Z",[17,19],{"path":216,"title":217,"publishedAt":218,"tags":219},"\u002Fblog\u002Fswapping-sitefinity-page-for-a-new-version","Replacing a Sitefinity Page with a new version","2020-06-16T21:42:27.6300000Z",[17],{"path":221,"title":222,"publishedAt":223,"tags":224},"\u002Fblog\u002Fwhy-isnt-sitefinity-serving-me-new-versions-of-an-updated-file","Sitefinity serving old versions of files","2020-06-16T16:07:49.1170000Z",[17,18,19],{"path":226,"title":227,"publishedAt":228,"tags":229},"\u002Fblog\u002Fopen-facebook-app-to-someones-profile-nativescript","Open facebook app to someones profile","2020-05-12T19:22:56.8530000Z",[17,18],{"path":231,"title":232,"publishedAt":233,"tags":234},"\u002Fblog\u002Fsitefinity-12.2-performance-review","Sitefinity 12.2 Performance Review","2019-11-06T18:09:20.4800000Z",[122,19],{"path":236,"title":237,"publishedAt":238,"tags":239},"\u002Fblog\u002Femailtextfield-for-authenticated-users","EmailTextField for Authenticated users","2019-10-30T19:31:38.8500000Z",[17,19,18],{"path":241,"title":242,"publishedAt":243,"tags":244},"\u002Fblog\u002Fcustomize-toolbox-widget-icons","Changing the look of toolbox widget icons","2019-06-11T17:31:14.4030000Z",[17,19],{"path":246,"title":247,"publishedAt":248,"tags":249},"\u002Fblog\u002Fpersonalization-issues-with-sitefinity-api","Personalization Problems with the Sitefinity API","2019-05-22T18:10:36.7270000Z",[20],{"path":251,"title":252,"publishedAt":253,"tags":254},"\u002Fblog\u002Ffiguring-out-the-logged-in-users-identity-provider","Finding out which provider a user logged in with","2019-03-29T17:43:26.0230000Z",[17,19],{"path":256,"title":257,"publishedAt":258,"tags":259},"\u002Fblog\u002Fnew-sitefinity-twitter-feed-widget-service","New Sitefinity Twitter Feed\\Widget\\Service","2018-12-19T16:10:43.5300000Z",[19,260],"News",{"path":262,"title":263,"publishedAt":264,"tags":265},"\u002Fblog\u002Fmacbook-stuck-keys-or-laggy-mouse","Macbook stuck keys or laggy mouse","2018-09-19T16:18:09.4530000Z",[20],{"path":267,"title":268,"publishedAt":269,"tags":270},"\u002Fblog\u002Ftesting-functionality-with-cypress-io","Testing functionality with cypress.io","2018-07-20T18:26:08.8030000Z",[122],{"path":272,"title":273,"publishedAt":274,"tags":275},"\u002Fblog\u002Fduplicate-urlname-popup","Duplicate urlname popup fix using custom script","2018-03-01T16:26:25.7600000Z",[17,19,18],{"path":277,"title":278,"publishedAt":279,"tags":280},"\u002Fblog\u002Ffinding-sitefinity-widgets-on-a-page","Finding sitefinity widgets on a page","2018-02-27T20:10:07.0070000Z",[17,19],{"path":282,"title":283,"publishedAt":284,"tags":285},"\u002Fblog\u002Fangular-widgets-in-sitefinity","Angular widgets in Sitefinity","2018-01-31T15:15:17.5970000Z",[17,19],{"path":287,"title":288,"publishedAt":289,"tags":290},"\u002Fblog\u002Fsocial-logout-in-sitefinity","Social Logout in Sitefinity","2017-12-20T20:16:51.7770000Z",[17,19],{"path":292,"title":293,"publishedAt":294,"tags":295},"\u002Fblog\u002Ffree-ssl-in-sitefinity-with-letsencrypt","Free SSL in Sitefinity with LetsEncrypt","2017-11-21T19:29:32.9030000Z",[17,19],{"path":297,"title":298,"publishedAt":299,"tags":300},"\u002Fblog\u002Fsupercharge-sitefinity-load-times-with-roslyn","Supercharge Sitefinity load times with Roslyn","2017-10-01T03:41:15.0500000Z",[17,19],{"path":302,"title":303,"publishedAt":304,"tags":305},"\u002Fblog\u002Fsitefinity-forms-popup-template","Sitefinity forms popup template","2017-09-08T15:40:50.8700000Z",[17,19],{"path":307,"title":308,"publishedAt":309,"tags":310},"\u002Fblog\u002Fhelp-my-pageeditor-is-broken","Help! My PageEditor is broken!","2017-08-25T15:59:40.1370000Z",[17,19,18],{"path":312,"title":313,"publishedAt":314,"tags":315},"\u002Fblog\u002Fsitefinity-10.1-and-development-load-times","Sitefinity 10.1 and Development Load times","2017-07-18T13:47:11.4130000Z",[17,19],{"path":317,"title":318,"publishedAt":319,"tags":320},"\u002Fblog\u002Fremote-certificate-is-invalid","Remote certificate is invalid error, self sign a cert","2017-05-15T17:00:49.7670000Z",[17,19],{"path":322,"title":323,"publishedAt":324,"tags":325},"\u002Fblog\u002Ffeather-mvc-bootstrap-dropdown-navigation-template","Feather MVC bootstrap dropdown navigation template","2017-03-20T14:41:07.4270000Z",[17,19],{"path":327,"title":328,"publishedAt":329,"tags":330},"\u002Fblog\u002Fkendo-grid-update-cannot-read-property-data-of-undefined","Kendo Grid: cannot read property data of undefined","2017-01-27T15:17:03.1300000Z",[18,133,17],{"path":332,"title":333,"publishedAt":334,"tags":335},"\u002Fblog\u002Fsanitize-pasted-content-sitefinity-editor","Sanitize pasted content in the Sitefinity Editor","2017-01-09T18:08:14.8200000Z",[17,19,133],{"path":337,"title":338,"publishedAt":339,"tags":340},"\u002Fblog\u002Fhardcoded-taxa-content-filtering-assumptions","Sitefinity Taxa Filtering hardcoded to only use AND","2016-11-15T20:59:39.7570000Z",[17,20,19],{"path":342,"title":343,"publishedAt":344,"tags":345},"\u002Fblog\u002Fdefine-markup-for-content-linked-in-the-wysiwyg-editors","Set rendered html for images and docs in the editor","2016-11-05T23:17:07.0200000Z",[17,19,133,18],{"path":347,"title":348,"publishedAt":349,"tags":350},"\u002Fblog\u002Fcustomizing-forms-column-names-with-feather-mvc-forms","Customizing Sitefinity MVC Form Column Names","2016-10-04T14:39:51.8670000Z",[17,19,18],{"path":352,"title":353,"publishedAt":354,"tags":355},"\u002Fblog\u002Feasy-css-setup-for-tablet-and-phone-nativescript","Easy Css Setup for Tablet and Phone NativeScript","2016-07-12T23:11:14.4400000Z",[17],{"path":357,"title":358,"publishedAt":359,"tags":360},"\u002Fblog\u002Fnew-widget-document-folder-list","New Widget - Document Folder List","2016-05-27T18:03:10.6400000Z",[260,19],{"path":362,"title":363,"publishedAt":364,"tags":365},"\u002Fblog\u002Ffinding-mvc-widgets-in-your-page-designer","Finding MVC widgets in your page designer","2016-05-19T18:31:34.6800000Z",[17,19],{"path":367,"title":368,"publishedAt":369,"tags":370},"\u002Fblog\u002Ffixing-cached-ldap-roles","Fixing Cached Ldap Roles","2016-03-03T17:28:53.9230000Z",[17,19,20],{"path":372,"title":373,"publishedAt":374,"tags":375},"\u002Fblog\u002Fdetect-indexing-in-your-feather-view","Detect Indexing in your feather view","2015-10-14T15:15:38.4170000Z",[17,19],{"path":377,"title":378,"publishedAt":379,"tags":380},"\u002Fblog\u002Fhybrid-feather-resource-package-loading","Loading a specific Feather Template in Hybrid Mode","2015-10-07T18:46:30.0970000Z",[19,17],{"path":382,"title":383,"publishedAt":384,"tags":385},"\u002Fblog\u002Fsitefinity-8-2-beta-announcement","Sitefinity 8.2 Beta Announcement","2015-09-25T15:07:32.1470000Z",[260,19],{"path":387,"title":388,"publishedAt":389,"tags":390},"\u002Fblog\u002Forganizing-mvc-feather-widgets-in-your-toolbox","Organizing widgets in your Sitefinity Page Editor","2015-03-27T18:21:23.3530000Z",[17,19],{"path":392,"title":393,"publishedAt":394,"tags":395},"\u002Fblog\u002Fhow-to-stop-radlistview-bloating-your-page","Prevent RadListView bloating your page with HTML","2015-03-05T16:43:55.1670000Z",[17,19],{"path":397,"title":398,"publishedAt":399,"tags":400},"\u002Fblog\u002Fsitefinity-feather-gets-list-mode-right","Sitefinity Feather gets list mode right","2015-02-06T18:07:09.5700000Z",[122,19],{"path":402,"title":403,"publishedAt":404,"tags":405},"\u002Fblog\u002Fwrite-fast-javascript-on-your-live-site","Rapidly write and debug javascript in a page","2014-12-22T17:12:32.9500000Z",[17],{"path":407,"title":408,"publishedAt":409,"tags":410},"\u002Fblog\u002Fis-sitefinity-not-evangalizable","Is Sitefinity not evangalizable?","2014-11-17T19:13:59.5470000Z",[20,19],{"path":412,"title":413,"publishedAt":414,"tags":415},"\u002Fblog\u002Fallow-users-to-download-media-through-login-without-a-401","Redirect to protected document after login","2014-11-11T13:31:31.6000000Z",[17,19],{"path":417,"title":418,"publishedAt":419,"tags":420},"\u002Fblog\u002Fsingle-hierarchical-to-new-multi-widget-system","Sitefinity 7.1s new multi-widget module system","2014-08-15T18:37:43.6870000Z",[17,19],{"path":422,"title":423,"publishedAt":424,"tags":425},"\u002Fblog\u002Fexport-html-or-content-to-pdf-word-etc-with-sitefinity","Export Sitefinity Content to Pdf or MSWord","2014-07-30T14:57:17.5270000Z",[17,19],{"path":427,"title":428,"publishedAt":429,"tags":430},"\u002Fblog\u002Fmvc-widgets-in-webforms-templates","MVC Widgets in your Sitefinity WebForms Templates","2014-05-16T17:40:16.2670000Z",[17,19],{"path":432,"title":433,"publishedAt":434,"tags":435},"\u002Fblog\u002Fappending-your-domain-or-sitename-to-the-page-title","Append text to a Sitefinity Page Title","2014-04-28T15:27:58.1000000Z",[17,19],{"path":437,"title":438,"publishedAt":439,"tags":440},"\u002Fblog\u002Fkendoui-sortable-widget-with-mvvm","KendoUI Sortable Widget with MVVM","2014-04-22T14:56:38.5500000Z",[17,133],{"path":442,"title":443,"publishedAt":444,"tags":445},"\u002Fblog\u002Fwhy-i-dont-like-my-surface-2s","Why I don't like my Surface 2","2014-04-14T20:27:33.7100000Z",[122],{"path":447,"title":448,"publishedAt":449,"tags":450},"\u002Fblog\u002Fsitefinity-7-review","Sitefinity 7 Review","2014-04-10T19:30:03.7130000Z",[122,19],{"path":452,"title":453,"publishedAt":454,"tags":455},"\u002Fblog\u002Fcustomize-custom-sitefinity-toolbox-elements","Customize Custom Sitefinity Toolbox Elements","2014-01-26T18:49:52.6670000Z",[17,19],{"path":457,"title":458,"publishedAt":459,"tags":460},"\u002Fblog\u002Fsitefinity-cache","Sitefinity Cache","2014-01-07T11:55:17.3500000Z",[17,19],{"path":462,"title":463,"publishedAt":464,"tags":465},"\u002Fblog\u002Fmake-your-loginwidget-react-to-a-clientside-login","Make your LoginWidget react to a clientside login","2013-11-27T19:09:05.1370000Z",[19,17],{"path":467,"title":468,"publishedAt":469,"tags":470},"\u002Fblog\u002Fshow-alt-text-in-the-images-grid","Show Alt Text in the Sitefinity Images Module Grid","2013-11-25T21:09:22.6670000Z",[17,19],{"path":472,"title":473,"publishedAt":474,"tags":475},"\u002Fblog\u002Fdefouting-the-new-61-sitefinity-nav-menu","Defouting the new 6.1 Sitefinity Nav Menu","2013-08-08T14:48:59.7730000Z",[17,19,133,18],{"path":477,"title":478,"publishedAt":479,"tags":480},"\u002Fblog\u002Fhow-precompiled-templates-work","How PreCompiled templates work","2013-07-23T12:19:15.9430000Z",[17,19],{"path":482,"title":483,"publishedAt":484,"tags":485},"\u002Fblog\u002Fuse-sitefinity-layout-controls-without-drag-drop","Use Sitefinity Layout Controls without Drag\\Drop","2013-07-01T04:54:44.9700000Z",[17,19],{"path":487,"title":488,"publishedAt":489,"tags":490},"\u002Fblog\u002Fsitefinity-twitter-is-dead","Sitefinity Twitter is dead","2013-06-18T12:38:36.6230000Z",[260,19],{"path":492,"title":493,"publishedAt":494,"tags":495},"\u002Fblog\u002Fintroducing-the-scriptstyle-widget","Introducing the ScriptStyle Widget","2013-05-30T17:36:48.8200000Z",[19,17],{"path":497,"title":498,"publishedAt":499,"tags":500},"\u002Fblog\u002Fcontentview-master-detail-confusion","Sitefinitys ContentView can be an ass#$%@ sometimes","2013-04-23T15:25:51.2300000Z",[20,19],{"path":502,"title":503,"publishedAt":504,"tags":505},"\u002Fblog\u002Ffixing-ugly-hierarchical-dynamiccontent-urls","Fixing Ugly Hierarchical DynamicContent Urls","2013-04-02T17:51:04.4430000Z",[17,19],{"path":507,"title":508,"publishedAt":509,"tags":510},"\u002Fblog\u002Fmyth-of-the-sitefinity-jquery-double-load","Myth of the Sitefinity jQuery Double Load","2013-02-19T13:59:11.9570000Z",[20,19],{"path":512,"title":513,"publishedAt":514,"tags":515},"\u002Fblog\u002Fsitefinity-54-this-is-the-release-youve-been-waiting-for","Sitefinity 5.4 - The release you've been waiting for","2013-02-14T13:22:14.8100000Z",[122,19],{"path":517,"title":518,"publishedAt":519,"tags":520},"\u002Fblog\u002Fadd-custom-taxonomies-to-a-designer","Add Custom Taxonomies to a Designer","2013-01-02T14:58:44.9800000Z",[17,19],{"path":522,"title":523,"publishedAt":524,"tags":525},"\u002Fblog\u002Fpost-53-looking-to-54","Sitefinity 5.4 and beyond, more work to do","2012-12-18T17:51:07.9670000Z",[19,122,20],{"path":527,"title":528,"publishedAt":529,"tags":530},"\u002Fblog\u002Fsitefinity-context-management-explained-from-the-experts","Sitefinity ORM Context Management explained","2012-12-17T17:43:31.8230000Z",[17,19],{"path":532,"title":533,"publishedAt":534,"tags":535},"\u002Fblog\u002Fdisable-embedded-jquery-on-radcontrols","Disable RadControls embedded jQuery in Sitefinity","2012-12-10T17:48:44.9430000Z",[17,19],{"path":537,"title":538,"publishedAt":539,"tags":540},"\u002Fblog\u002Fmore-efficent-sitefinity-breadcrumb","More Efficent Sitefinity Breadcrumb","2012-11-26T04:57:00.5930000Z",[17,19],{"path":542,"title":543,"publishedAt":544,"tags":545},"\u002Fblog\u002Fsitefinity-dropbox-doesnt-work-the-way-you-think-it-does","Sitefinity Dropbox doesn't work the way you think it does","2012-11-20T16:12:23.7470000Z",[122,19],{"path":547,"title":548,"publishedAt":549,"tags":550},"\u002Fblog\u002Fsmall-thing-to-boost-performance","Loading Sitefinity faster on your dev box","2012-11-20T13:52:36.8000000Z",[17,19],{"path":552,"title":553,"publishedAt":554,"tags":555},"\u002Fblog\u002Fcustom-attributes-for-sitefinity-taxa","Custom attributes for Sitefinity Taxa","2012-11-01T16:19:24.1470000Z",[17,19],{"path":557,"title":558,"publishedAt":559,"tags":560},"\u002Fblog\u002Fwhats-new-in-sitefinity-52-webinar-qa-log","What's new in Sitefinity 5.2 Webinar QA Log","2012-10-25T16:00:16.5570000Z",[260,19],{"path":562,"title":563,"publishedAt":564,"tags":565},"\u002Fblog\u002Fsitefinity-53-planning-roadmap","Planning Roadmap for Sitefinity 5.3","2012-10-22T02:33:08.9000000Z",[260,19],{"path":567,"title":568,"publishedAt":569,"tags":570},"\u002Fblog\u002Fbetter-sitefinity-taxonomy-widget-you-should-use-this","Simplified no bloat html Sitefinity taxonomy widget","2012-09-15T21:02:57.9200000Z",[18,19,17],{"path":572,"title":573,"publishedAt":574,"tags":575},"\u002Fblog\u002Fwhats-new-in-sitefinity-51-webinar-qa-log","What's new in Sitefinity 5.1 Webinar QA Log","2012-07-19T16:24:33.7830000Z",[260],{"path":577,"title":578,"publishedAt":579,"tags":580},"\u002Fblog\u002Fintroducing-sitefinity-primer-nuget-101","Introducing Sitefinity Primer NuGet 1.0.1","2012-06-17T19:27:38.7000000Z",[260,19],{"path":582,"title":583,"publishedAt":584,"tags":585},"\u002Fblog\u002Ftime-to-disqus","Adding Disqus to your Sitefinity 4 site","2012-06-11T12:28:58.6930000Z",[260,19],{"path":587,"title":588,"publishedAt":589,"tags":590},"\u002Fblog\u002Fcould-not-load-file-or-assembly-system-data-sqlite","Could not load file or assembly System.Data.SQLite","2012-06-06T16:05:26.1230000Z",[18,19],{"path":592,"title":593,"publishedAt":594,"tags":595},"\u002Fblog\u002Fdecorate-your-sitefinity-forms-with-kendoui","Decorate your Sitefinity Forms with KendoUI","2012-05-30T01:55:21.5400000Z",[17,19,133],{"path":597,"title":598,"publishedAt":599,"tags":600},"\u002Fblog\u002Fjavascript-date-formatting","Javascript Date Formatting","2012-05-25T19:51:16.5500000Z",[17,133],{"path":602,"title":603,"publishedAt":604,"tags":605},"\u002Fblog\u002Fdebugging-a-kendo-template-loop","Debugging a Kendo Template Loop","2012-05-03T02:33:14.5230000Z",[17,133],{"path":607,"title":608,"publishedAt":609,"tags":610},"\u002Fblog\u002Favoid-version-errors-with-assembly-binding","Avoid Version errors with Assembly Binding","2012-03-25T15:09:00.0000000Z",[17,19,18],{"path":612,"title":613,"publishedAt":614,"tags":615},"\u002Fblog\u002Fsitefinity-how-to-list","How To List","2012-03-24T17:49:00.0000000Z",[17,19],{"path":617,"title":618,"publishedAt":619,"tags":620},"\u002Fblog\u002Fclientside-debugging-the-telerik-radcontrols","Clientside Debugging the Telerik RadControls","2012-03-23T17:28:00.0000000Z",[17],{"path":622,"title":623,"publishedAt":624,"tags":625},"\u002Fblog\u002Fsitefinity-validation-of-viewstate-mac-failed","Validation of viewstate MAC failed","2012-03-16T02:54:21.6930000Z",[17,19],{"path":627,"title":628,"publishedAt":629,"tags":630},"\u002Fblog\u002Fcontinuing-the-sitefinity-kendoui-posts","Continuing the Sitefinity KendoUI posts","2012-03-16T02:53:15.2370000Z",[17,133],{"path":632,"title":633,"publishedAt":634,"tags":635},"\u002Fblog\u002Fsimple-wcf-by-sitefinity","Simple WCF in Sitefinity","2012-03-16T02:52:46.9870000Z",[17,19],{"path":637,"title":638,"publishedAt":639,"tags":640},"\u002Fblog\u002Fjustcode-template-list","JustCode Template List","2012-03-16T02:51:10.3930000Z",[260,19],{"path":642,"title":643,"publishedAt":644,"tags":645},"\u002Fblog\u002Fcustomize-the-page-editing-experience-for-your-users","Customizing the Sitefinity Page Editor","2012-03-16T02:50:36.0070000Z",[17,19],{"path":647,"title":648,"publishedAt":649,"tags":650},"\u002Fblog\u002Fsitefinity-43-44-webinar-notes","Sitefinity 4.3-4.4 Webinar notes","2012-03-16T02:49:50.3930000Z",[260,19],{"path":652,"title":653,"publishedAt":654,"tags":655},"\u002Fblog\u002Frow-not-found-genericoid-error","Row not found: GenericOID Error","2012-03-16T02:47:56.4170000Z",[17],{"path":657,"title":658,"publishedAt":659,"tags":660},"\u002Fblog\u002Fsitefinity-embedding-a-google-wave-instance","Sitefinity: Embedding a Google Wave Instance","2012-03-16T02:45:05.6070000Z",[260,19],{"path":662,"title":663,"publishedAt":664,"tags":665},"\u002Fblog\u002Fusing-cufon-with-asp-net-and-telerik","Using Cufon with ASP.NET and Telerik","2012-03-16T02:43:59.4000000Z",[17],{"path":667,"title":668,"publishedAt":669,"tags":670},"\u002Fblog\u002Fopenaccess-nested-repeater-to-generic-list-property","OpenAccess Nested Repeater to Generic List Property","2012-03-16T02:40:36.0800000Z",[17],{"path":672,"title":673,"publishedAt":674,"tags":675},"\u002Fblog\u002Ftelerik-reporting-needsdatasource","Telerik Reporting: NeedsDataSource","2012-03-16T02:39:59.7370000Z",[17],{"path":677,"title":678,"publishedAt":679,"tags":680},"\u002Fblog\u002Finstalling-elmah-with-sitefinity","Installing ELMAH with Sitefinity","2012-03-16T02:38:52.7370000Z",[17,19],{"path":682,"title":683,"publishedAt":684,"tags":685},"\u002Fblog\u002Fbetter-sitefinity-file-page","Better Sitefinity File Page in Sitefinity 3.x","2012-03-16T02:37:36.6870000Z",[17,19,18],{"path":687,"title":688,"publishedAt":689,"tags":690},"\u002Fblog\u002Fmore-editing-options-for-your-generic-content","More tools for Generic Content in Sitefinity 3.x","2012-03-16T02:36:03.1070000Z",[17,19],{"path":692,"title":693,"publishedAt":694,"tags":695},"\u002Fblog\u002Fscreenshot-of-sitefinity-4-analytics","Screenshot of Sitefinity 4 Analytics","2012-03-16T02:35:05.9000000Z",[696,19],"Previews",{"path":698,"title":699,"publishedAt":700,"tags":701},"\u002Fblog\u002Fusing-button-selectors","Using Button Selectors with Sitefinity 3.x","2012-03-16T02:33:32.3270000Z",[17,19],{"path":703,"title":704,"publishedAt":705,"tags":706},"\u002Fblog\u002Fhyperlinks-in-external-templates","Hyperlinks in External Templates","2012-03-16T02:29:46.4530000Z",[17,19],{"path":708,"title":709,"publishedAt":710,"tags":711},"\u002Fblog\u002Fstored-procedure-for-obtaining-wf4-bookmarks","Stored Procedure for obtaining WF4 bookmarks","2012-03-16T02:28:54.9770000Z",[17],{"path":713,"title":714,"publishedAt":715,"tags":716},"\u002Fblog\u002Fpeople-make-your-radeditor-voices-heard","Voice your RadEditor frustrations","2012-03-16T02:27:16.6030000Z",[260],{"path":718,"title":719,"publishedAt":720,"tags":721},"\u002Fblog\u002Fnew-old-controls-jul-2010","New Old Controls Jul, 2010","2012-03-16T02:23:38.4600000Z",[260,19],{"path":723,"title":724,"publishedAt":725,"tags":726},"\u002Fblog\u002Fsitefinity-4","Sitefinity 4.0","2012-03-16T02:22:51.3000000Z",[260,19,122],{"path":728,"title":729,"publishedAt":730,"tags":731},"\u002Fblog\u002Fusing-webservices-with-telerik-openaccess","Using Webservices with Telerik OpenAccess","2012-03-16T02:17:37.4530000Z",[17],{"path":733,"title":734,"publishedAt":735,"tags":736},"\u002Fblog\u002Fsitefinity-radwindow-popup-styles","Sitefinity RadWindow popup styles","2012-03-16T02:15:35.4400000Z",[17,19],{"path":738,"title":739,"publishedAt":740,"tags":741},"\u002Fblog\u002Fchanging-the-look-of-controls-dropped-onto-your-page","Changing the look of controls dropped onto your page","2012-03-16T02:13:11.3030000Z",[17],{"path":743,"title":744,"publishedAt":745,"tags":746},"\u002Fblog\u002Fnew-control-background-image-content","Background Image Content Widget for Sitefinity 3","2012-03-16T02:10:52.1570000Z",[260,19],{"path":748,"title":749,"publishedAt":750,"tags":751},"\u002Fblog\u002Fquerying-telerik-openaccess-with-linqpad","Querying Telerik OpenAccess with LinqPad","2012-03-16T02:02:11.3400000Z",[17],{"path":753,"title":754,"publishedAt":755,"tags":756},"\u002Fblog\u002Ffix-sitefinity-edit-mode-style","Fix Sitefinity 3.x Edit Mode Style","2012-03-16T01:58:29.3300000Z",[17,19],{"path":758,"title":759,"publishedAt":760,"tags":761},"\u002Fblog\u002Ftelerik-reporting-export-on-button-click","Telerik Reporting: Export On Button Click","2012-03-16T01:57:18.1630000Z",[17],{"path":763,"title":764,"publishedAt":765,"tags":766},"\u002Fblog\u002Ftelerik-please-fix-charting","Telerik, Please fix charting!","2012-03-16T01:55:30.9600000Z",[20],{"path":768,"title":769,"publishedAt":770,"tags":771},"\u002Fblog\u002Fcompiling-controls-against-multiple-sitefinity-versions","Compiling Projects against multiple versions","2012-03-16T01:53:19.1770000Z",[17,19],{"path":773,"title":774,"publishedAt":775,"tags":776},"\u002Fblog\u002Frandom-site-controls-updates","Sitefinity v3 RandomSiteControls Release Notes","2012-03-16T01:52:09.7700000Z",[260],{"path":778,"title":779,"publishedAt":780,"tags":781},"\u002Fblog\u002Fmoving-the-sitefinity-logo","Moving the sitefinity logo","2012-03-16T01:49:13.2570000Z",[17,19],{"path":783,"title":784,"publishedAt":785,"tags":786},"\u002Fblog\u002Fleverage-radeditor-to-strip-html","Stripping HTML using the RadEditor","2012-03-16T01:48:27.0170000Z",[17,19],{"path":788,"title":789,"publishedAt":790,"tags":791},"\u002Fblog\u002Fdebugging-a-bad-webresource-axd-request","Debugging a bad WebResource.axd request","2012-03-16T01:45:40.6070000Z",[17,18],{"path":793,"title":794,"publishedAt":795,"tags":796},"\u002Fblog\u002Fcreating-extension-methods-with-openaccess","Extension Methods with OpenAccess","2012-03-16T01:44:26.8970000Z",[17,19],{"path":798,"title":799,"publishedAt":800,"tags":801},"\u002Fblog\u002Fwhy-pits-is-the-pits","Why PITS is the PITS","2012-03-16T01:42:38.1430000Z",[20,19],{"path":803,"title":804,"publishedAt":805,"tags":806},"\u002Fblog\u002Fdb-driven-scripting-and-styling-with-sf4","DB Driven Scripting and Styling with SF4","2012-03-16T01:42:03.1700000Z",[17,19],{"path":808,"title":809,"publishedAt":810,"tags":811},"\u002Fblog\u002Fmissing-from-sitefinity-4-release","What's Missing from Sitefinity 4 Release","2012-03-16T01:41:29.6100000Z",[122,19],{"path":813,"title":814,"publishedAt":815,"tags":816},"\u002Fblog\u002Fsitefinity-ecommerce-module-coming-soon","Sitefinity eCommerce module coming","2012-03-16T01:40:38.8470000Z",[260,19],{"path":818,"title":819,"publishedAt":820,"tags":821},"\u002Fblog\u002Fpreventing-content-popping-with-kendoui-splitter","Preventing Content Popping with KendoUI","2012-03-16T01:39:31.3930000Z",[17,133],{"path":823,"title":824,"publishedAt":825,"tags":826},"\u002Fblog\u002Fsitefinity-43-44-roadmap-review","Sitefinity 4.3-4.4 Roadmap Review","2012-03-16T01:34:23.2630000Z",[122,19],{"path":828,"title":829,"publishedAt":830,"tags":831},"\u002Fblog\u002Fadvanced-radxmlhttppanel","Advanced RadXmlHttpPanel","2012-03-16T01:30:57.2470000Z",[17,133],{"path":833,"title":834,"publishedAt":835,"tags":836},"\u002Fblog\u002Fcross-browser-css-gradients","Cross-Browser CSS Gradients","2012-03-16T01:27:43.2130000Z",[17,111],{"path":838,"title":839,"publishedAt":840,"tags":841},"\u002Fblog\u002Fpositioning-in-sitefinity-4","Positioning in Sitefinity 4","2012-03-16T01:26:31.2870000Z",[17],{"path":843,"title":844,"publishedAt":845,"tags":846},"\u002Fblog\u002Fspeed-up-your-site-on-the-cheap","Improve performance with Rackspace Cdn","2012-03-16T01:23:51.3100000Z",[122],{"path":848,"title":849,"publishedAt":850,"tags":851},"\u002Fblog\u002F4-1-update-issues","Update Issues for Sitefinity 4.1","2012-03-16T01:15:53.1970000Z",[122,19,18],{"path":853,"title":854,"publishedAt":855,"tags":856},"\u002Fblog\u002Fradnotification-peering-into-the-future","RadNotification...peering into the future?","2012-03-16T01:13:56.5370000Z",[122],{"path":858,"title":859,"publishedAt":860,"tags":861},"\u002Fblog\u002Fthe-best-stored-procedure-youll-ever-use-for-sitefinity","Search All Tables SQL Stored Procedure","2012-03-16T01:11:10.7070000Z",[17,19],{"path":863,"title":864,"publishedAt":865,"tags":866},"\u002Fblog\u002Fblog-post-title-images","Blog Post Title Images","2012-03-15T23:44:47.0830000Z",[17],{"path":868,"title":869,"publishedAt":870,"tags":871},"\u002Fblog\u002Fhidden-but-powerful-q3-2010-styling-features","Hidden but powerful Q3 2010 styling features","2012-03-15T23:27:27.5730000Z",[696,17],{"path":873,"title":874,"publishedAt":875,"tags":876},"\u002Fblog\u002F43-roadmap-wishlist","Sitefinity 4.3 Roadmap wishlist","2012-03-15T23:23:18.9230000Z",[696,19,20],1786049908282]