Sitecore Content tree scroll to top in Firefox - sitecore

When I expand the Sitecore content tree and when the vertical scroll bar appears for the content tree, and if I scroll down and select an item in the bottom of the tree, it scroll to top.
This only happens in Firefox, IE10, IE9, Chrome it works fine.
I did the Sitecore upgrade very recently. Has anyone encountered similar issue? Please help!
Sitecore.NET 6.6.0 (rev. 130404)
Firefox versions - 21,22

I have had a similar issue and contacted Sitecore support about it. They provided me with the following solution that works for us:
- open \sitecore\shell\Controls\Gecko.js
- replace at line 668
scBrowser.prototype.resizeFixsizeElements = function() {
var form = $$("form")[0];
this.fixsizeElements.each(function(element) {
var height = form.getHeight() - element.scHeightAdjustment + "px";
element.setStyle({ height: height });
});
/* trigger re-layouting to fix the firefox bug: table is not shrinking itself down on resize */
scGeckoRelayout();
}
by:
scBrowser.prototype.resizeFixsizeElements = function() {
var form = $$("form")[0];
if (!form) {
return;
}
this.fixsizeElements.each(function (element) {
if (!element.hasClassName('scFixSizeNested')) {
element.setStyle({ height: '100%' });
}
});
var maxHeight = 0;
var formChilds = form.childNodes;
for (var i = 0; i != formChilds.length; i++) {
var elementHeight = formChilds[i].offsetHeight;
if (elementHeight > maxHeight) {
maxHeight = elementHeight;
}
}
var formHeight = form.offsetHeight;
this.fixsizeElements.each(function (element) {
var height = element.hasClassName('scFixSizeNested')
? (form.getHeight() - element.scHeightAdjustment) + 'px'
: (element.offsetHeight - (maxHeight - formHeight)) + 'px';
element.setStyle({ height: height });
});
/* trigger re-layouting to fix the firefox bug: table is not shrinking itself down on resize */
scGeckoRelayout();
}

Thanks to Sitecore support, found the issue,
The issue occures due to Fixefox refreshes html controls as soon as some property was changed. Upon selecting an item, a content tree panels width is changed and as a result it is redrawn. Developed workaround forbids changing of the controls size for static controls for Firefox (like content tree). An aftermath might be incorrect window resizing (changing height of the browser window) in Firefox. To implement the workaround please replace an exicting one under the path 'Website\sitecore\shell\Controls\Gecko.js' with attached one and clear browser cache. Please notify us with the results.
scBrowser.prototype.resizeFixsizeElements = function() {
var form = $$("form")[0];
if (!form) {
return;
}
if (!this.isFirefox)
{
this.fixsizeElements.each(function (element) {
if (!element.hasClassName('scFixSizeNested')) {
element.setStyle({ height: '100%' });
}
});
var maxHeight = 0;
var formChilds = form.childNodes;
for (var i = 0; i != formChilds.length; i++) {
var elementHeight = formChilds[i].offsetHeight;
if (elementHeight > maxHeight) {
maxHeight = elementHeight;
}
}
var formHeight = form.offsetHeight;
this.fixsizeElements.each(function (element) {
var height = element.hasClassName('scFixSizeNested')
? (form.getHeight() - element.scHeightAdjustment) + 'px'
: (element.offsetHeight - (maxHeight - formHeight)) + 'px';
element.setStyle({ height: height });
});
}
/* trigger re-layouting to fix the firefox bug: table is not shrinking itself down on resize */
scGeckoRelayout();
}

Related

Passing Multiple Values

I have a visualization table that has an event listener on select.
The need: I want the user to be able to delete documents on the google drive without having to leave the webpage
The set up: I added a button so that when clicked, I get a confirm alert box that includes the value. Once I click OK, it runs the scripts from the client-side with an event handler. This works perfectly!
The problem: I can move one document at a time but if I need to move 20+ documents it gets really tedious to click rows one after the other. Is it possible to pass multiple values to the successhandler?
google.visualization.events.addListener(archiveChart.getChart(), 'select', function () {
$("#docArchive").on("click", function() {
var selection = archiveChart.getChart().getSelection();
var dt = archiveChart.getDataTable();
if (selection.length > 0) {
var item = selection[0];
var docurl = dt.getValue(item.row, 2);
var docname = dt.getValue(item.row, 1);
var folder = dt.getValue(item.row, 4);
if(confirm("Are you sure you want to archive " + docname + "?") == true) {
archiveChart.getChart().setSelection([]);
return google.script.run.withSuccessHandler(onSuccessArchive).withFailureHandler(function(err) {
alert(err);
}).archiveDoc(docurl,folder);
} else {
archiveChart.getChart().setSelection([]);
}
}});
})
I feel like I might need to add this:
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
I'm struggling a little with understanding what I might need to change (still learning). Any help or guidance is appreciated!
recommend confirming once, for all documents
then loop the selection to archive each document
google.visualization.events.addListener(archiveChart.getChart(), 'select', function () {
$("#docArchive").on("click", function() {
var selection = archiveChart.getChart().getSelection();
var dt = archiveChart.getDataTable();
var docNames = selection.map(function (item) {
return dt.getValue(item.row, 1);
}).join('\n');
if (selection.length > 0) {
if(confirm("Are you sure you want to archive the following document(s)?\n" + docNames) == true) {
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
var docurl = dt.getValue(item.row, 2);
var docname = dt.getValue(item.row, 1);
var folder = dt.getValue(item.row, 4);
return google.script.run.withSuccessHandler(onSuccessArchive).withFailureHandler(function(err) {
alert(err);
}).archiveDoc(docurl, folder);
}
}
archiveChart.getChart().setSelection([]);
}
});
});

How to get access to Chart instance related to current tooltip callback in Chart.js

I am trying to display percentage value inside doughnut chart. To my feature work properly i need to have access to chart instance inside callback. I don't know how to do that?
I handled that using Chart.pluginService beforeDraw event but it doesn't work as I expected.
Is there any way to move code from beforeDraw event inside tooltip callback ?
This is my code
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
var precentage = dataFromDoughnutChart;
localStorage.setItem("per", precentage.toString());
return precentage + "%";
}
}
}
Chart.pluginService.register({
beforeDraw: function (chart) {
var value = "";
var x = localStorage.getItem("per");
if (x != null)
value = x + "%";
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 100).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
var text = value,
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
},
afterEvent: function (chart, event) {
if (event.type == "mouseout") {
localStorage.removeItem("per");
}
}
});
I think the best approach to solving your problem is to actually use custom tooltips instead of attempting a plugin. Here is a working solution that I modified from one of the chart.js sample pages in their repo.
First define a container for the custom tooltip in yout HTML.
<div id="chartjs-tooltip"></div>
Then use the below custom tooltip function. You might have to tweak the centerX calculation for your needs. This function basically calculates the percentage value of the currently active slice (by dividing the datapoint by the total value of datapoints), places it in the custom tooltip div, and positions the div in the center of the doughnut.
Chart.defaults.global.tooltips.custom = function(tooltip) {
// Tooltip Element
var tooltipEl = document.getElementById('chartjs-tooltip');
// Hide if no tooltip
if (tooltip.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set Text
if (tooltip.body) {
var total = 0;
// get the value of the datapoint
var value = this._data.datasets[tooltip.dataPoints[0].datasetIndex].data[tooltip.dataPoints[0].index].toLocaleString();
// calculate value of all datapoints
this._data.datasets[tooltip.dataPoints[0].datasetIndex].data.forEach(function(e) {
total += e;
});
// calculate percentage and set tooltip value
tooltipEl.innerHTML = '<h1>' + (value / total * 100) + '%</h1>';
}
// calculate position of tooltip
var centerX = (this._chartInstance.chartArea.left + this._chartInstance.chartArea.right) / 2;
var centerY = ((this._chartInstance.chartArea.top + this._chartInstance.chartArea.bottom) / 2);
// Display, position, and set styles for font
tooltipEl.style.opacity = 1;
tooltipEl.style.left = centerX + 'px';
tooltipEl.style.top = centerY + 'px';
tooltipEl.style.fontFamily = tooltip._fontFamily;
tooltipEl.style.fontSize = tooltip.fontSize;
tooltipEl.style.fontStyle = tooltip._fontStyle;
tooltipEl.style.padding = tooltip.yPadding + 'px ' + tooltip.xPadding + 'px';
};
Here is the full end-to-end working example via codepen:
Chart.js Doughnut Center Percentage

How can I calcuate wrapping text height in a famo.us surface?

Within famo.us, I want to place a variable-length wrapping title near the top then have images etc follow. All items must be their own surface as some have click events and animations but all the positioning must be super fast to calculate and place based on the text height and of course must avoid DOM access for the 60fps. This must happen for a series of mini-posts, streaming real time and for infinite scroll.
So far, I came up with an approach that works using an ascii character map to pixel width load off screen on init if isn't already in localStorage. It uses jquery to do the sizing for each character, then determine line height by checking a breaking word and the height of that box. After that I use this map for calculations on the fly so I don't touch DOM again. It seems to work fine but is completely dependent on knowing the style of font going to be used in a very specific way. For each new style, I would have to have a different mapping which sucks.
Is there another approach that is more built in to famo.us?
I'm answering my own question because its frankly been awhile, the new framework is going to come out June 22nd of this month (at the time of the this writing). Just going to put how I'm doing this currently which is the way I described above.
Here's the 0.3.5 way of Famou.us to do this.
This is in a file "utils/lines.js" I whipped up. Hack, yes. Works, yes.
define(function(require) {
'use strict';
var $ = require('jquery');
var cache = require('utils/cache');
function getLineInfo(id) {
var cacheKey = 'lineInfo_' + id;
var savedLineInfo = cache.get(cacheKey);
if (savedLineInfo)
return savedLineInfo;
var charStart = 32; // space
var charEnd = 126; // ~
var $charDump = $('<div>', { id: id });
$('body').append($charDump);
for (var i = charStart; i <= charEnd; i++)
$charDump.append($('<div>', { class: 'char', css: { top: (i-32) * 20 } }).html('&#' + i));
var charMap = {};
$charDump.find('.char').each(function() {
var $this = $(this);
var char = $this.text().charCodeAt(0);
var w = $this.width();
charMap[char] = w;
});
$charDump.html('<div class="line">abc<br>123<br>456</div>');
var lineHeight = $charDump.height() / 3;
$charDump.remove();
savedLineInfo = {
lineHeight: lineHeight,
charMap: charMap
};
cache.set(cacheKey, savedLineInfo);
return savedLineInfo;
}
function getLines(text, width, id, maxLines) {
var lineInfo = getLineInfo(id);
var cleaned = $.trim(text.replace(/\s+/gm, ' '));
var words = cleaned.split(' ');
var lines = 1;
var lineWidth = 0;
var spaceLength = lineInfo.charMap[32];
var allLines = '';
words.forEach(function(word) {
var wordLength = 0;
word.split('').forEach(function(char) {
var charLength = lineInfo.charMap[char.charCodeAt(0)];
if (!charLength)
charLength = spaceLength;
wordLength += charLength;
});
if (lineWidth + wordLength + spaceLength <= width) {
lineWidth += wordLength + spaceLength;
if (maxLines)
allLines += word + ' ';
}
else {
lineWidth = wordLength;
if (maxLines && lines <= maxLines)
allLines += word + ' ';
else if (maxLines)
return {text: allLines.substr(0, allLines.length - 3) + '...', lines: lines};
lines++;
}
});
if (maxLines)
return {text: allLines, lines: lines};
return lines;
}
function getTextHeight(text, width, id, maxLines) {
var lineInfo = getLineInfo(id);
var info;
if (maxLines) {
info = getLines(text, width, id, maxLines);
info.height = lineInfo.lineHeight * info.lines;
return info;
}
return lineInfo.lineHeight * getLines(text, width, id);
}
return {
getLines: getLines,
getLineInfo: getLineInfo,
getTextHeight: getTextHeight
};
});

Scrollview Pull to Refresh Famo.us

I'm trying to implement a pull to reload/refresh type effect, that you see in lots of apps, with scrollview. I've got multiple pain points on this.
Just stopping a scrollview past where it wants to sit is a pain. Setting velocity or speed limit doesn't work, just setting the position just makes it bounce because it wants to continue back.
Then setting up an event call that doesn't just fire when they scroll too hard up while doing their normal browsing.
If anyone has thoughts on how to accomplish this I'd appreciate it. If I don't get any responses in a day I'll start posting my specific attempts and where they fell short. I can't believe I'm the only one trying to implement this pretty common feature.
You could use the FlexScrollView which supports this feature out of the box (it is nearly impossible to do it right with the stock famo.us scrollview..):
var FlexScrollView = require('famous-flex/FlexScrollView');
var RefreshLoader = require('famous-refresh-loader/RefreshLoader');
var scrollView = new FlexScrollView({
autoPipeEvents: true,
pullToRefreshHeader: new RefreshLoader({
size: [undefined, 60],
pullToRefresh: true,
color: 'green',
backgroundColor: 'white',
particleCount: 8,
particleSize: 7
})
});
Demo: https://rawgit.com/IjzerenHein/famous-flex-chat/master/dist/index.html
Repo: https://github.com/IjzerenHein/famous-flex
RefreshLoader: https://github.com/IjzerenHein/famous-refresh-loader
Tutorial: https://github.com/IjzerenHein/famous-flex/blob/master/tutorials/FlexScrollView.md
I finally have a solution for you. It relies only on start, and end events of the scrollview sync. To start you will see the scrollview.reset function. This function is taken for scrollviews internals to return _scroller to its default behavior.
We will use a transitionable and scrollview._scroller.positionFrom to control the behavior of the scrollview when it should not be default. Essentially everything is normalized on scrollview.sync.on 'start' and the update is carried out on scrollview.sync.on 'end' if the position of the scrollview has reached the refresh offset.
Much of the functionality is tied to the fact that I am using a timeout to simulate the load time of the refresh. It may be more appropriate to have a variable that is keeping track of whether a request is still being made.
Anyway, I hope this gives you some ideas.. Here is the full example.
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var Scrollview = require('famous/views/Scrollview');
var Transitionable = require('famous/transitions/Transitionable');
var SnapTransition = require('famous/transitions/SnapTransition');
Transitionable.registerMethod('snap',SnapTransition);
var snap = { method:'snap', period:200, dampingRatio:0.4 }
var context = Engine.createContext();
var scrollview = new Scrollview();
var surfaces = [];
scrollview.sequenceFrom(surfaces);
for (var i = 0; i < 20; i++) {
var surface = new Surface({
size: [undefined, 200],
properties: {
backgroundColor: "hsl(" + (i * 360 / 20) + ", 100%, 50%)",
}
});
surface.pipe(scrollview);
surfaces.push(surface);
}
scrollview.trans = new Transitionable(0);
// Timeout that will simulate loading time
scrollview.timer = null;
// Total simulated load time
scrollview.timeout = 500;
// Vertical offset scrollview will start load at
scrollview.refreshOffset = 100;
// Reset scroller to default behavior
scrollview.reset = function(){
scrollview._scroller.positionFrom(scrollview.getPosition.bind(scrollview));
}
scrollview.sync.on('start',function(){
clearTimeout(scrollview.timer);
scrollview.trans.halt();
var pos = scrollview.trans.get()
if (pos != 0) scrollview.setPosition(pos);
scrollview.reset()
});
scrollview.sync.on('end',function(){
var pos = scrollview.getPosition();
if (pos < (-scrollview.refreshOffset)) {
scrollview.trans.halt();
scrollview.trans.set(pos);
scrollview._scroller.positionFrom(function(){
return scrollview.trans.get();
});
scrollview.trans.set(-scrollview.refreshOffset,snap,function(){
scrollview.timer = setTimeout(function(){
scrollview.trans.halt();
scrollview.trans.set(0,snap,function(){
scrollview.reset()
});
}, scrollview.timeout );
});
} else {
scrollview.trans.halt();
scrollview.trans.set(0);
}
});
context.add(scrollview);

Increase scrollview's element height on clicking it

I am new to famo.us like everybody else.
I cannot think of a way to increase the height of each item (probably surface) inside my scrollview on clicking that item.
Eg. like below list view below
item 1
item 2
item 3
Now Clicked item 2
item 1
item 2
details of item 2
item 3
Here is a way I was able to achieve clicking to adjust height. It gets a bit more complicated is you want to animate the size.
Here is the simple click example..
Hope it helps!
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Scrollview = require('famous/views/Scrollview');
var surfaces = [];
var scrollview = new Scrollview();
scrollview.sequenceFrom(surfaces);
for (var i = 0; i < 5; i++) {
var surface = new Surface({
size:[undefined,200],
properties: {
backgroundColor:'hsl('+(i*360/8)+',100%,50%)'
}
});
surface.open = false;
surface.on('click',function(){
var size = this.open ? [undefined,200] : [undefined,400] ;
this.setSize(size);
this.open = !this.open;
}.bind(surface));
surfaces.push(surface);
surface.pipe(scrollview);
};
context.add(scrollview);