I implemented a jQuery UI accordion with several sections. My Problem is that every section is as large as the section with the longest content. (height of all sections is set to the height of the largest content section). So there is a lot of whitespace in sections with shorter content.
The Solution is to use heightStyle attribute.
$( function() {
$( "#accordion" ).accordion({
heightStyle: "content"
});
} );
Related
I have a standard component defined something like:
export default Ember.Component.extend({
hideIfEmptyChange: function() {
var thingOfInterest = ...;
var otherThingOfInterest = ...;
...
// Perform some logic
...
// Perform some logic using thingOfInterest
// Perform exactly the same logic using otherThingOfInterest
}.observes('hideIfEmpty.#each')
});
I want to move the logic for the last two pieces into their own function to prevent writing out the same code twice just for two different variables.
I could write an action on my component and use this.send('myAction',...) - but would it be best practice to have this as an action if it isn't going to be used (or even usable) from the component's template? If you shouldn't do it this way then how should you?
My other thought was mixin's - but the code here will be completely specific to the component, so again this doesn't feel 100% right.
Edit
The component is used here to observe an array of widgets, which are displayed in a sidebar. To start with the sidebar is hidden away as there are no widgets. When a widget is added the sidebar then slides out using a css3 transition between a bootstrap class I added (col-md-0) and something like col-md-2, at the same time the main column shrinks from something like col-md-10 to col-md-8. Because of the nature of it coming out from zero width the widgets inside squish around during the animation and so need to be hidden during it. So the generic piece of code will be:
function(element, classes) {
var lowWidth = 50;
// Transition looks awful if columns start from small width, so hide inner content until css3 transition complete if starting from low width
if ($(element).width() < lowWidth) {
$('div', element).hide();
$(element).toggleClass(classes);
$(element).on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) {
$('div', element).fadeIn(250);
$(this).off(e);
});
}
else {
$(element).toggleClass(classes);
}
}
My component here is in block form and actually has the sidebar within it in the template.
{{#hideable-cols hideIfEmpty=rightSidebarWidgets leftId="det-main" leftMinClass="col-md-8" leftMaxClass="col-md-10" rightId="det-sidebar-right" rightMinClass="col-md-0" rightMaxClass="col-md-2"}}
<div id="det-main" class="col-md-10 resizes">
{{outlet}}
</div>
<div id="det-sidebar-right" class="det-sidebar resizes col-md-0">
{{widget-area widgets=rightSidebarWidgets saveObjectFromWidget="saveObjectFromWidget" removeWidget="removeRightWidget"}}
</div>
{{/hideable-cols}}
The only other way to do what I wanted would have been if I could have set 'inner' components to only be able to react to changes in the array of widgets AFTER the parent block component is happy/done. I've used something similar in knockout js but couldn't see this kind of feature in Ember, so my workaround was to hide the div where the widgets are added, do the transition and show the div again afterward.
I'm currently working on a rendering in Sitecore 7.2 (MVC) that will show a jwPlayer given a link to a video (either in the Media Library or from an external source, like YouTube). When I add the rendering (with a valid data source) through Presentation Details in the Content Editor everything looks fine, and works perfectly. The trouble that I'm running into right now, though, is that when I try to do the same thing from the Page Editor (with the exact same rendering and data source), nothing is showing up in that placeholder at all.
The part of the rendering that deals with the video is as follows:
#if (Model.VideoLink != null && Model.Image != null)
{
var vidid = Guid.NewGuid().ToString();
<div class="article-video-module">
<p class="video-placeholder-text">#Html.Raw(Model.Heading)</p>
<div id="#vidid">Loading the player...</div>
<script type="text/javascript">
jwplayer("#vidid").setup({
file: "#Model.VideoLink.Url",
image: "#Model.Image.Src",
width: "100%",
aspectratio: "16:9",
sharing: {
link: "#Model.VideoLink.Url"
},
primary: 'flash'
});
jwplayer('videodiv-#vidid').onPlay(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').hide();
});
jwplayer('videodiv-#vidid').onPause(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').show();
});
</script>
</div>
#Editable(a => Model.Description)
}
Other things that might help:
When I comment out everything in the <script> tag above the rendering shows up perfectly.
A reference to jwplayer.js is found on the page (that was my first thought)
Console errors in Javascript:
No suitable players found and fallback enabled on jwplayer.js
Uncaught TypeError: undefined is not a function on jwplayer("#vidid").setup({ and on jwplayer('videodiv-#vidid').onPlay(function () { from above.
How can I get jwPlayer and Page Editor to work nicely with each other?
The issue is that when you add a component through Page Editor, the script is fired before the div <div id="#vidid"> element is added to DOM. Don't ask me why...
The solution is really simple: wrap your javascript code with if condition, checking if the div is already there:
<script type="text/javascript">
if (document.getElementById("#vidid")) {
jwplayer("#vidid").setup({
file: "#Model.VideoLink.Url",
image: "#Model.Image.Src",
width: "100%",
aspectratio: "16:9",
sharing: {
link: "#Model.VideoLink.Url"
},
primary: 'flash'
});
jwplayer('videodiv-#vidid').onPlay(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').hide();
});
jwplayer('videodiv-#vidid').onPause(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').show();
});
}
</script>
There is also another issue with your code - Guid can start with number, and this is not a valid id for html elements. You should change your code to:
var vidid = "jwp-" + Guid.NewGuid().ToString();
I wouldn't rule out a conflict with the version of JQuery that the Page Editor uses - this usually messes stuff up. There's a good post here on to overcome the issues.
http://jrodsmitty.github.io/blog/2014/11/12/resolving-jquery-conflicts-in-page-editor/
I'm writing an editor for the blog-posts on my homepage.
I'm using Ember's textarea-helper to bind an attribute of my model to the editor. In this textarea I type a post in markdown. Below will the output be automatically rendered (like the Stackoverflow-editor does).
My markdown also contains media-embeds from pages like YouTube or Soundcloud which makes the re-rendering very slow.
How can I limit the re-rendering of the page to like only once every five seconds?
You can use Ember.run.throttle to avoid updating render markup too often.
Example (see also JsBin):
App.IndexController = Ember.Controller.extend({
markdown: 'this is markdown',
rendered: '',
markdownChanged: function() {
Ember.run.throttle(this, this.renderOutput, 5000);
}.observes('markdown').on('init'),
renderOutput: function(){
this.set('rendered', 'I RENDERED THIS: ' + this.get('markdown'));
}
});
I'm using bootstrap popover in my app and I need to render an outlet inside it.
I have this nested route :
this.resource('pages', function(){
this.resource('page', { path: ':id' }, function(){
this.resource('edit', function(){
this.resource('images', function(){
this.resource('image', { path: ':image_id'}, function(){
this.route('edit');
})
});
});
});
});
When the user is here => /pages/1/edit/ when he click on an image it route to /images but render the {{outlet}} inside the popover like this :
<div class="popover-content hide">
{{outlet}}
</div>
This is my popover initialisation :
$img.popover({
html: true,
content: function() {
return $('.popover-content').html(); //need to have the outlet here
}
});
So far, it render correctly my outlet, but inside the images template, I have some button that modify the DOM and it doesn't update the html. Unless if I close and open the popover again I can see the modification.
Is it possible to render the outlet directly inside the code ? or is it possible to have my popover being updated ?
Thanks for the help.
See these links for an alternative approach to putting Ember stuff in Bootstrap popovers:
Bootstrap Popovers with ember.js template
https://cowbell-labs.com/2013-10-20-using-twitter-bootstrap-js-widgets-with-ember.html
Ember and Handlebars don't like this because it's basically copying the html content of a div and plopping it into another. But that html alone isn't everything that's needed. Ember is magic and there's lots of stuff happening in the background.
Your hidden div is real ember stuff, so let's try not to mess with it by calling .html() on it. My idea is to literally move the DOM itself instead.
first, modify your popover function call to always create this placeholder div:
content: '<div id="placeholder"></div>',
next, detach the content div from the dom in the didInsertElement of the view:
// get the popover content div and remove it from the dom, to be added back later
var content = Ember.$('.popover-content').detach();
// find the element that opens your popover...
var btn = Ember.$('#btn-popup-trigger').get(0);
// ... and whenever the popover is opened by this element being clicked, find the placeholder div and insert the content element
// (this could be improved. we really just want to know when the popover is opened, not when the button is clicked.)
btn.addEventListener("click", function() {
content.appendTo("#placeholder");
});
since the content div is immediately detached when didInsertElement is called, you can remove the "hide" css class from the content div.
edit: i tried this on my own project and it broke two-way binding. the controller updated my handlebars elements, but any two-way bound {{input}} helpers did not update the controller/model. i ended up using a single-item dropdown menu, and used this to prevent the menu from closing too quickly:
Twitter Bootstrap - Avoid dropdown menu close on click inside
I got a problem with my website.
On the left I have a sidebar, and next to it I have the container.
At the moment I have found this javascript function:
$(document).ready(function(){
$("#sidebar").height( $(document).height() );
});
This script makes sure that my sidebar is 100%. Also if I resize the screen, the sidebar automatically changes height.
The problem is that I have a dashboard in my container with moving divs, who can change size and are stackable underneath each other. (example: http://demo.webdeveloperplus.com/drag-drop-panels/)
If I stack these divs underneath each other, the sidebar does not change height automatically. How can I make sure that the sidebar is also changing height when I stack these divs in the container? Do I need to loop the script?
Hope someone can help me with this.
(ps. I do not have a footer in my website so the sidebar has to keep on the height of the document. (background))
Ok, this is a two part answer. Part one is that you will need to get the height of the viewport for the browser. Part two is that you will need to re-do this function whenever the window resizes. after some testing (in IE 9, Chrome and FF) I've found this to work well:
function getClientHeight() {
var retval = 0;
if (typeof (window.innerHeight) == 'number') {
retval = window.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) {
retval = document.documentElement.clientHeight;
} else if (document.body && document.body.clientHeight) {
retval = document.body.clientHeight;
}
return retval;
}
$(document).ready(function () {
$(window).resize(function (event) {
$("#sidebar").height(getClientHeight());
});
$("#sidebar").height(getClientHeight());
});
I Fixed the problem now. I used another way to set the height of the sidebar always 100%.
For people who want to know how I fixed this:
I gave the #sidebar style: position: fixed; and putted the divs inside the sidebar outside of the div and made a new div #sidebarcontent. Then gave the #sidebarcontent style position: absolute; and placed them on the right place. I tested this for cross browser and it worked even on IE6.