Have a look at this simple fiddle:
http://jsfiddle.net/mercmobily/y4uG2/10/
Basically I declare a Widget, and start adding away sub-widgets. At one point, I have the sub-widget "section" which is a templated widget with a tab container and sub-tabs.
The main widget has:
'<div data-dojo-type="Section" data-dojo-props="title: \'Sub Widget\'" data-dojo-attach-point="section"></div>' +
And that "section" widget has:
templateString: '' +
' <div>' +
' <div class="subWidget" data-dojo-type="dijit.layout.TabContainer" tabPosition: \'left-h\'" dojo-attach-point="tabCont" >' +
' <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title: \'Second Widget one\'">Second Widget One</div>' +
' <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title: \'Second Widget Two\'">Section Widget Two</div>' +
' </div>'+
' </div>'
Now, I am having a bit of a hard time getting the sub-widget, "section", to render properly.
On my actual program right now I played with:
doTemplate
height attribute in CSS
Catching resize() from the main widget and calling resize() in the sub-widget
(About point (3), I had to do something like:
resize: function(){
this.inherited(arguments);
console.log("Resize in main widget called!");
this.settingsTab.resize();
}
At this point, I am going insane and hence the question: what is the accepted, normal and common way to make sure that, in the fiddle, the sub-widget is rendered when you instantiate the main one?
PLUS, do I need to specify the height:100% for every tab container I ever use? (it looks like it)
Thank you!
UPDATE
I updated the fiddle. At this point I added a "height" to the tab container. After that, rsizing the browser window actually does the trick (!). I am not quite clear why I need that height there, but OK.
http://jsfiddle.net/mercmobily/y4uG2/16/
I also did a on() when a user clicks on the "broken" widget, and -- guess what -- resize is run and it renders fine.
This makes even less sense. Why is my own widget behaving any different than the ones defined within the template? I started all sorts of theories: height cannot be calculated because it isn't displayed, for example. But then the SAME should apply to the other tab with sub-tabs, labelled as "Complex" on the left hand side!
I am out of ideas. No, really.
Indeed there is a typo, as Frode mentioned, but you will still need to click one of the tabs if you want your tab content to appear in the SubWidget.
I suggest that you correct the typo and make your widget subclass ContentPane rather than _WidgetBase to solve this issue, as ContentPanes know how to resize themselves, like this :
declare('SubWidget', [ContentPane, _TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: ''...
See http://jsfiddle.net/psoares/YwWst/
By the way, there is no need to specify widgetsInTemplate : true in 1.8. Adding _WidgetsInTemplateMixin is enough...
The templateString in your SubWidget has a typo. Could it simply be that?
...<div style="height:100%" data-dojo-type="dijit.layout.TabContainer" tabPosition: \'left-h\'" data-dojo-attach-point="tabContainer" >'...
Should probably be:
<div style="height:100%" data-dojo-type="dijit.layout.TabContainer" data-dojo-props="tabPosition: \'left-h\'" data-dojo-attach-point="tabContainer" >'
That seems to do the trick in your fiddle: http://jsfiddle.net/y4uG2/18/
Related
I have a script called equal-heights.js which works together with underscore.js. It equalize the divs to the size of the highest div with an animation (optional). The problem is that when I charge the page nothing happens, it starts to equalize the divs only when I resize the browser.
The initialising code on the HTML:
$(document).ready(function() {
$('.profile-panel').equalHeights({
responsive:true,
animate:true,
animateSpeed:500
});
});
You can see the equal-heights.js here: http://webdesign.igorlaszlo.com/templates/js/blogger-equal-heights-responsive.js
What should I do so that, when the page loads, the animation starts to equalize the divs automatically?
I created my own test and realized the issue is with the way the plugin has been written, namely that it only accepts one value for the class name, otherwise it will break.
This is because of the following line in the script:
className = '.'+$(this).prop('class');
What this does is that it takes the class property of your element and adds a dot (.) in front; a nice but not very scalable way of getting the current selector, because if you have multiple class names, it will only put a dot in front of the first one, so if you have...
<div class="profile-panel profile-panel-1st-row profile-panel1">
...it will transform it into...
$('.profile-panel profile-panel-1st-row profile-panel1')
...so understandably this will not work properly, as the dots are missing from the rest of the classes.
To go around this, until version 1.7, jQuery had a .selector property, that however has now been deprecated. Instead they're now suggesting to add the selector as an argument of your plugin's function as follows (and I tailored it to your situation):
First define an option called selector when calling the function:
$('.profile-panel-1st-row').equalHeights({
selector:'.profile-panel-1st-row',
// ...
});
Then setup the className variable inside the plugin as follows:
var className = options.selector;
Another thing you can do is the place the class you're using to activate the plugin as the first one for each element you want to use it on, so instead of...
<div class="profile-panel profile-panel-1st-row profile-panel1">
...do this...
<div class="profile-panel-1st-row profile-panel profile-panel1">
...then you can setup the className variable inside the plugin as follows:
var className = '.'+ $(this).prop('class').split(" ").slice(0,1);
This basically splits the class names into parts divided by space and takes the first one.
To have the best of both solutions, simply set className to the following:
var className = options.selector || '.'+ $(this).prop('class').split(" ").slice(0,1);
As to the animation, it only works on resize; that is intended, that's how the plugin has been built, you can play around with the original example of the plugin creator that I added to jsfiddle: http://jsfiddle.net/o9rjvq8j/1/
EDIT #2: If you're happy to change the plugin even more, just remove $(window).resize(function() in the if(settings.responsive === true) check and you'll have it working. ;)
if(settings.responsive === true) {
//reset height to auto
$(className).css("height","auto");
//re initialise
reInit();
}
I'm trying to display a form in a "Show" View and am wanting to use Foundation's equalizer to make the divs the same height but for some reason it doesn't work with one div being taller than the other.
My guess would be that it has something to do with using php inside the containers but I didn't find anything related to that on their docs page.
If anyone can point out where I went wrong or if they know for certain that this just wont work with Foundation I would appreciate your input! Thanks!
HTML:
<div class="row" data-equalizer>
<div class="small-6 columns" data-equalizer-watch>
<fieldset><legend>Order Information</legend>
<?php
echo "Number of Guests: ". $order_array['guestNumber' . $x].'<br>';
echo "Food: ". $order_array['food' . $x].'<br>';
?>
</fieldset>
</div>
<div class="small-6 columns k" data-equalizer-watch>
<fieldset><legend>Location</legend>
<?php
echo "Order Name: " . $order_array['orderName'] . '<br>';
?>
</fieldset>
</div>
</div>
My solution (before finding a more efficient solution using another plugin which I recommend) was to wrap the foundation init like so:
$(window).on('load', function () {
$(document).foundation();
});
Equalizer will have no effect if the items are stacking (if the offset().top value of all of them is not equal) and you have set equalize_on_stack: false. Try adding this configuration to your main js file:
$(document).ready(function() {
$(document).foundation({
equalizer : {
// Specify if Equalizer should make elements equal height once they become stacked.
equalize_on_stack: true
}
});
});
My issue was that I was initializing the Foundation js before the page was finished loading. Make sure you are wrapping your Foundation initializer in the jQuery ready() function:
$(function() {
$(document).foundation();
});
My first thought, is that Equalizer is working and it is making both <div class="small-6 columns">s the same height. Unless you have some visual clue to differentiate them such as different background colors or a border setting it may be hard to tell if Equalizer is working properly. Please note that I have made this mistake before.
If your intention was to make the <fieldset>s the same height, you would need to move the data-equalizer-watch from the <div class="small-6 columns">s to the <fieldset>s. This would also allow you to visually see if Equalizer is working, because of <fieldset>'s border.
I created this codepen,http://cdpn.io/igDoI, with two examples. One is your code above where I added a dashed border to both of your <div class="small-6 columns">s. The other example is your code above where I moved the data-equalizer-watch to the <fieldset>s.
I hope that helps,
Not sure if this applies to you, but when you are using foundation's equalizer you must ensure the following for each ancestor of elements with "data-equalizer-width" that are also children of the element with the "data-equalizer" attribute:
No borders
No padding
No margins
This isn't actually in the API, but these properties affect the height calculations of equalizer, and can sometimes cause it to go wrong.
Also, you must ensure the controls being "equalized" are visible when the equalizing code is called. So, if you are using equalizer in a tab that is hidden on page load, you need to trigger equalizer again when that part becomes visible. You can do this by triggering a resize event on the window object.
Initializing the Foundation after the page was finished loading, worked for me. I improved that solution by initializing only equalizer after loading. So the other stuff can start on "ready".
jQuery(window).on('load', function () {
var element = jQuery('[data-equalizer]');
var elem = new Foundation.Equalizer(element);
});
I'm new to the use of jQuery so the problem I'm facing should be fairly straight forward. Basically what I'm trying to accomplish is load a variety of simple text-only pages within DIV elements of my site, and with a navigation bar hide/unhide these individual DIVs.
DIVs are correctly loaded the requested pages using an script block. However, what is not working correctly is toggling the visibility of these DIV blocks. I've narrowed it down to a jQuery function I've created which blocks the entire script call whenever I refer to any of the DIV blocks. Let me explain better with a code snippet.
This is is some very simple code that, on the click of a menu link, runs a hide function then shows the corresponding DIV element.
$( document ).ready(function()
{
console.log("document ready."); <-- does NOT get called with hideDivs()
$('#button1').click(function(){
hideDivs();
$("#page1").show();
});
$('#button2').click(function(){
hideDivs();
$("#page2").show();
});
});
This is the hideDivs() function, JUST above the ready function:
function hideDivs()
{
$("#page1").hide(); <-- These lines cause the entire
$("#page2").hide(); <-- <script> block to note get called.
}
Finally, page1 and page2 are created with a script block halfway inside the page:
<div id="page1"></div>
<div id="page2"></div>
<script>
$("#page1").html('<object style="overflow:hidden; width: 100%; height: 500px;" data="page1.php">').show();
$("#page2").html('<object style="overflow:hidden; width: 100%; height: 500px;" data="page2.php">').hide();
</script>
Why then is it that the top SCRIPT block fails with the hideDivs() function? I've tried placing it inside the $( document ).ready function with no change. Again, if the function is blank, or contains something simple like 'console.log' it works, but when referring to DIV tags it breaks.
Even stranger, the code that makes the function FAIL, WORKS if I simply rewrite the code as such:
$('#button1').click(function(){
$("#page1").hide(); <-- This works fine
$("#page2").hide(); <-- (page1 repeated to match function code)
$("#page1").show();
});
I have quite a few pages so I would much rather be able to use a function as not to have lots of repetitive code.
I have no errors displayed in my javascript console. I've looked closely at functions calls with StackOverflow and Google searches but couldn't spot a solution. I'm sure I've made a really silly mistake I'm overlooking, so any help would be much appreciated.
So instead of the whole function to hide your divs, you can simply put a class on each one and hide them by selecting that class. For example, each page Div give a class="clickablePages", and then do:
$(".clickablePages").hide();
that will simply hide all the divs that you have added the class to.
As for repeating all the button clicks for each button, you can simply do it in one function based on the id of the button. You can again put a class on all of the buttons as well, trigger the function by selecting the class and then grab the id you need within that function. something like this:
$('.buttonclick').click(function(){
var pageID = $(this).attr('id');
$("#page" + pageID).show();
});
In this case, if your buttons just had an id of '1' or '2' that matched the page number, it would only show the div for that page number. Hope that makes sense.
Someone was able to so quickly help me with a problem I'd spent hours and hours on, that I'm hoping I'll get lucky and someone can point me in the right direction on this one, too.
I didn't see anyone else with quite my issue here - and I'm new to working with WP templates instead of plain old HTML/CSS/JS stuff.
Basically - on a site we did (www.opted.org) with a purchased WP theme - I can't get the mobile version collapsible menu to stop defaulting on page load to the last item in the Main Menu.
So instead of something that makes sense - like About ASCO, or even being able to add "Select Page" - the drop down shows "-- past issues"
I don't care how I fix it really, but the client just doesn't want that page to be the default. I tried adding an extra menu item at the end called "Select Page" with an href='#' and using CSS to hide it on screens above 480px - but I couldn't get it to work no matter how I tried to refer to it.
I feel like this should be easy - but I don't know where to set the selected LI among the many WP files.
Thanks!!
I had a look at the plugin.js file on the site www.opted.org.
On line 22, there is 'header' : false // Boolean: Show header instead of the active item
and on line 41 there is jQuery('<option/>').text('Navigation')
Try setting line 22 to true, and text('Navigation') to your 'Select Page' if you prefer that over the text 'Navigation'
Or, according to the tinynav.js page (http://tinynav.viljamis.com/), you can customize that as an option like this:
$("#nav").tinyNav({
active: 'selected', // String: Set the "active" class
header: 'Navigation', // String: Specify text for "header" and show header instead of the active item
label: '' // String: Sets the <label> text for the <select> (if not set, no label will be added)
});
In your main.js file, your calling it on line 14. You should add that header: 'Navigation', option there.
It's hard to answer this question without knowing how the theme you are using works. However, you can certainly change the selected attribute using javascript.
Here's the code you would use to set it to 'About Asco' using jQuery:
jQuery('.tinynav').val('/about-asco/')
alternatively (a little clearer, but more verbose):
jQuery('.tinynav option:first').prop('selected', true);
I have an array of 2000 items, that I need to display in html - each of the items is placed into a div. Now each of the items can have 6 links to click on for further action. Here is how a single item currently looks:
<div class='b'>
<div class='r'>
<span id='l1' onclick='doSomething(itemId, linkId);'>1</span>
<span id='l2' onclick='doSomething(itemId, linkId);'>2</span>
<span id='l3' onclick='doSomething(itemId, linkId);'>3</span>
<span id='l4' onclick='doSomething(itemId, linkId);'>4</span>
<span id='l5' onclick='doSomething(itemId, linkId);'>5</span>
<span id='l6' onclick='doSomething(itemId, linkId);'>6</span>
</div>
<div class='c'>
some item text
</div>
</div>
Now the problem is with the performance. I am using innerHTML to set the items into a master div on the page. The more html my "single item" contains the longer the DOM takes to add it. I am now trying to reduce the HTML to make it small as possible. Is there a way to render the span's differently without me having to use a single span for each of them? Maybe using jQuery?
First thing you should be doing is attaching the onclick event to the DIV via jQuery or some other framework and let it bubble down so that you can use doSomething to cover all cases and depending on which element you clicked on, you could extract the item ID and link ID. Also do the spans really need IDs? I don't know based on your sample code. Also, maybe instead of loading the link and item IDs on page load, get them via AJAX on a as you need them basis.
My two cents while eating salad for lunch,
nickyt
Update off the top of my head for vikasde . Syntax of this might not be entirely correct. I'm on lunch break.
$(".b").bind( // the class of your div, use an ID , e.g. #someID if you have more than one element with class b
"click",
function(e) { // e is the event object
// do something with $(e.target), like check if it's one of your links and then do something with it.
}
);
If you set the InnerHtml property of a node, the DOM has to interpret your HTML text and convert it into nodes. Essentially, you're running a language interpreter here. More text, more processing time. I suspect (but am not sure) that it would be faster to create actual DOM element nodes, with all requisite nesting of contents, and hook those to the containing node. Your "InnerHTML" solution is doing the same thing under the covers but also the additional work of making sense of your text.
I also second the suggestion of someone else who said it might be more economical to build all this content on the server rather than in the client via JS.
Finally, I think you can eliminate much of the content of your spans. You don't need an ID, you don't need arguments in your onclick(). Call a JS function which will figure out which node it's called from, go up one node to find the containing div and perhaps loop down the contained nodes and/or look at the text to figure out which item within a div it should be responding to. You can make the onclick handler do a whole lot of work - this work only gets done once, at mouse click time, and will not be multiplied by 2000x something. It will not take a perceptible amount of user time.
John Resig wrote a blog on documentDragments http://ejohn.org/blog/dom-documentfragments/
My suggestion is to create a documentDragment for each row and append that to the DOM as you create it. A timeout wrapping each appendChild may help if there is any hanging from the browser
function addRow(row) {
var fragment = document.createDocumentFragment();
var div = document.createElement('div');
div.addAttribute('class', 'b');
fragment.appendChild(div);
div.innerHtml = "<div>what ever you want in each row</div>";
// setting a timeout of zero will allow the browser to intersperse the action of attaching to the dom with other things so that the delay isn't so noticable
window.setTimeout(function() {
document.body.appendChild(div);
}, 0);
};
hope that helps
One other problem is that there's too much stuff on the page for your browser to handle gracefully. I'm not sure if the page's design permits this, but how about putting those 2000 lines into a DIV with a fixed size and overflow: auto so the user gets a scrollable window in the page?
It's not what I'd prefer as a user, but if it fixes the cursor weirdness it might be an acceptable workaround.
Yet Another Solution
...to the "too much stuff on the page" problem:
(please let me know when you get sick and tired of these suggestions!)
If you have the option of using an embedded object, say a Java Applet (my personal preference but most people won't touch it) or JavaFX or Flash or Silverlight or...
then you could display all that funky data in that technology, embedded into your browser page. The contents of the page wouldn't be any of the browser's business and hence it wouldn't choke up on you.
Apart from the load time for Java or whatever, this could be transparent and invisible to the user, i.e. it's (almost) possible to do this so the text appears to be displayed on the page just as if it were directly in the HTML.