velocity break loops if checkbox is checked - html

I'm using apache velocity in a web application (just for experimentation and practice)
for example:
<input id="limited" type="checkbox"> <strong>Limited view</strong>
so I need a code which would be... if the checkbox above is checked then do this:
#foreach( $customer in $customerList )
#if( $velocityCount > 5 )
#break
#end
$customer.Name
#end
else then don't break it
is that kind of syntax possible?
and if yes then can you show me how?
please no rude comments, I'm just trying to learn... can anyone help?

It seems you wish to get Velocity to instantly react on someones click, right?
This wouldn't work (without further effort, that is), because the Velocity template is rendered server sided. Your Velocity code would never 'notice' the click, as it is done on the client side. At least not in the same request, but I come to that later.
Furthermore Velocity isn't able to directly access the value of the checkbox, meaning there is no such thing as limited.isChecked().
So, first thing you need is a backing (form) object, where you evaluate and keep the status of your checkbox. Should be no problem, as you managed to provide the object $customerList. The checkbox status should be represented by a boolean var, say limitedView, so that you can write:
#foreach( $customer in $customerList )
#if($velocityCount > 5 && $yourBackingObject.isLimitedView())
#break
...
(Please see Breaking out of a foreach loop in Velocity, if you face problems with the #break instruction.)
If you actually need to show the shortened list immediately, then refresh (part of) the page using JavaScript/Ajax. This new request is what you need to update your backing object and to render the template again.
Edit:
Or even simpler (but a little outside of Veloctiy and depending on JavaScript) provide both lists in two different containers in the page, like <div>, and toggle the css class on a click at the checkbox so that one on of the two is always invisible.
.vm:
<div id="listLength">
#foreach( $customer in $customerList )
#if($velocityCount > 5)
#break
...
</div>
<div id="listLengthToggler">
#foreach( $customer in $customerList )
...
</div>
.css
div#listLengthToggler,
div#listLength {
... /* general styles for classes */
display: none;
}
div#listLengthToggler {
display: block;
}
.js
$(document).ready(
function() {
$('div#listLengthToggler').click(
function() {
$('div#listLength').slideToggle('slow');
}
);
}
);
Get http://code.jquery.com/jquery-2.1.4.min.js
You add a line that says 'Click to expand!' and 'Click to collapse!', respectively inside each div and get rid of the checkbox or adapt the JavaScript so the toggling starts on a click on it.

Related

Is there a way to show markup in the viewer outside of editMode?

I'm looking for a way to show markups when not in editMode. I want to be able to draw markups in the viewer while at the same time being able to use edit2D. Everytime I call leaveEditMode() on the markups extension, the markups disappear. If there was just a way to have them always showing even when not in edit mode, that would do the trick. I have seen stuff about a view mode but the enterViewMode() must be outdated as I cannot find it.
Another option would be to leave edit mode on in the markups extension and also use the edit2D tools simultaneously by changing which drawing layer/canvas is on top? I have no idea if that's possible or how to go about it though.
Any ideas would be helpful!
Okay so I figured out a way, I'm not sure what the repurcussions would be, but it seems to work.
Here's an edited code snippet I threw together quick to test and it seems to work. Basically I do the opposite of what enterEditMode() and leaveEditMode() already do. Basically markupsExtension.editModeSvgLayerNode holds the svg data for all the markups. When leaveEditMode() is called, it clears out markupsExtension.svg. So I just add it back after it's called manually. I also clear it out before re-entering because it does it on it's own and it might interfere.
if (buttonName === 'markup') {
let markupsExtension = this.viewer.getExtension('Autodesk.Viewing.MarkupsCore');
if (this.selectedButton === buttonName) {
// Exit markups
markupsExtension.leaveEditMode();
// Shows the markup after leaving
if (markupsExtension.editModeSvgLayerNode.svg) {
markupsExtension.svg.appendChild(markupsExtension.editModeSvgLayerNode.svg);
}
}
else {
this.selectedButton = buttonName;
// Remove the svg set we added so it can redraw it in "enterEditMode()"
if (markupsExtension.editModeSvgLayerNode && markupsExtension.editModeSvgLayerNode.svg.parentNode) {
markupsExtension.svg.removeChild(markupsExtension.editModeSvgLayerNode.svg);
}
markupsExtension.enterEditMode();
}
}

TabIndex - hitting tab moves me to Address Bar - unable to work around this using Focus or +tab indexes

I read several threads that talk about how the Address Bar in IE is basically the first one to get focus when using TAB (MSDN's own docs talk about this).
Yet, I have seen situations where this doesn't always have to be the case....
I have a master page and inside my content area is a formView.
It defaults to INSERT view and can never leave it (they can only insert not edit and reading is handled elsewhere)
So on my page load for the page I have:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If fvwLogEntry.CurrentMode = FormViewMode.Insert = True Then
'Set the default field to position the cursor there...hopefully
Dim FCtxtHrEmployeeId As TextBox
FCtxtHrEmployeeId = CType(fvwLogEntry.FindControl("txtHrEmployeeId"), TextBox)
Page.SetFocus(FCtxtHrEmployeeId.ClientID.ToString)
End If
Now that works, when the page loads it sets the cursor to the employeeID text box inside the formview's INSERT template.
HOWEVER, when I hit TAB it takes me to the address bar and THEN if I hit tab again it takes me through the rest of the items on the page.
I set the tab index of the first item to 11 and then incrimented from there (I had read that IE's toolbars have tab indexes too so I thought perhaps using a higher number would bypass those, but again that doesn't REALLY make sense since it would still start at the lowest number, but I gave it a shot thinking it would move forward from where the focus was set.) If I click on the textbox and then hit TAB it DOES move through the page like I would expect.
It is just when the page loads and gets the focus set to the employeeID textbox that hitting tab moves it to the address bar.
I also tried setting the other controls to -1 (those I didn't want it to tab to), still no luck there.
So... what can I do to get around this?
There MUST be a simple way to set the focus to the employeeID textbox and ensure that pressing TAB after that moves to the next control in the formview's insert template and does NOT jump up to the address bar?
The following jquery code seems to be working fine for me..
$(window).load(function () {
$('.myClass :visible:input:enabled:first').focus();
});
$('body').on('keydown', '.myClass :visible:input:enabled:first', function (e) {
if ((e.which == 9) || (e.keyCode == 9)) {
$('.myClass :visible:input:enabled:first').focus();
}
});
I found another better option which is fastest as of what I tried.
Here's the code for that
function handleTabOrder() {
$('.myClass :visible:input:enabled').each(function (index) {
$(this).attr('tabindex', index + 10);
});
$('.myClass :visible:input:enabled:first').keydown(function (e) {
if (e.keyCode == 9 || e.which == 9) {
$("[tabindex=10]").focus();
}
});
}
What I have done here is to assign Tab order to all the visible controls on the page, then I have handled the key down event of only first control(that shifts the control to address bar) and now it shifts the control to next visible input item on the screen..
Its just a work around but works faster than any of the other things mentioned in the thread.
Just write the above function and all it in on-load event of page.
I was having this issue as well. For me, it was being caused by the use of the .select() method in order to bring focus automatically on a text field as soon as the page loaded. I changed my code to instead use JQuery's .focus() method and that resolved the issue.
I faced similar problem in IE. After some analysis I found that, this problem occurs if there is any HTML content outside form.
for example:
<html>
<div id="1">
</div>
<form>
//other code
</form>
</html>
It worked for me, after I moved all HTML inside form tag.
<html>
<form>
<div id="1">
</div>
//other code
</form>
</html>
Have a look at: http://www.w3schools.com/tags/att_global_tabindex.asp
Your txtHrEmployeeId element should have tabindex 1 and all other elements should have higher values.
-1 is not valid
Also verify that the tabindex are correct in the html that gets rendered (right-click in page and "view source").
I realize this is an old post, but an even simpler method is to add a "tab-stop" attribute to the form element with the last tabindex. Then bind a keydown listener and force focus to the first tabindex when the tab-stop is encountered.
Here's a simple example:
<input type="text" tab-stop />
$document.bind("keydown", function(event) {
var attrs = event.currentTarget.activeElement.attributes;
if (attrs['tab-stop']) {
angular.element.find('select')[0].focus();
event.preventDefault();
}
});
};
The answer mentioned in my other post works fine but it made the page take a huge performance hit because with every key press on the page the whole DOM was being searched for the elements.
So I found a new more optimized solution
var myNameSpace = function(){
this.selector = '.myClass :visible:input:enabled:first';
this.myElement = $(selector);
this._body = $('body');
var _self= this;
this._body.on('keydown',_self.selector,function(e){
if ((e.which == 9) || (e.keyCode == 9)) {
_self.myElement.focus();
}
});
};
The general idea being to 'cache' the node to be accessed. No need to traverse the DOM again and again for just selecting.
I had this same problem. It turns out mine was related to the ajax modal popup extenders. a modal popup was being shown, even though technically i could not see it because it was wrapped inside a parent div that was hidden. if you are using modal popup extenders, this could be causing an issue like this.
If you are using JSF or Primefaces, you can make use of:
<p:focus for"formname"></p:focus>

no "current_page_item" class being added to top level nav item

If you go to www.lindysez.com and click on the top level navigation links, you'll notice that position presence is indicated by a slightly darker background (same as hover state). This works for each of the links EXCEPT "Tips & Techniques".
If I look under the hood, I noticed that the "current_page_item" class isn't being added to the parent of the "Tips & Techniques" menu item when you go to http://www.lindysez.com/tips
Also, curiously enough, when on the tips page, the parent of the "Blog" navigation item gets the class "current_page_parent", which is neither expected nor desired. This is harmless from a UI standpoint, but probably an indication what the underlying problem might be.
Anyone know why the "Tips & Techniques" menu item isn't getting the "current_page_item" class once selected?
Update: Directed #user2019515's comment below
Thanks for the nudge in this direction, it does seem like I could create a workaround that would fix this. Couple things however.
This treats the symptom of the problem rather than the root. I'd like to figure out how to get wp to just add the "current_page_item" class natively. Any idea what's causing this? I think it may also be related to another problem I'm having which involves "tips" not showing in the RSS feed. I posted another question about that, but haven't seen any answers...
https://stackoverflow.com/questions/15980846/custom-post-type-not-showing-up-in-wordpress-rss-feed
Even as a workaround, I'd rather try to avoid a solution that relies on hard coded "menu-item-##". My development and production servers both have different ID#'s. I know I can account for this, but I hope there's a better, scalable workaround.
The code you provided didn't work for me, not that I can find any fault in it, nor are there any errors. Seems like it should work, but just doesn't. I even tried creating a very simple version that would add a class to all the items, but this too isn't executing. Here's that code.
function add_class_to_wp_nav_menu($classes, $item)
{
$classes[] = 'classy-class';
return $classes;
}
add_filter('nav_menu_css_class', 'add_class_to_wp_nav_menu', 10, 2);
Thanks so much for your help!
The Tips page is a post archive page, it shows posts rather than a normal page that's why the blog was being highlighted. You can easily fix this issue by adding the following custom CSS to your style.css file.
.post-type-archive-tips .menu-item-23{
background:url(images/nav-hover.png) repeat-x;
}
You'll need to loop over your menu, by default the current page class is added to the blog page because in the end the custom posts.
//Change current_page_parent for custom post type
function remove_parent_classes($class)
{
// check for current page classes, return false if they exist.
return ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor' || $class == 'current-menu-item') ? FALSE : TRUE;
}
function add_class_to_wp_nav_menu($classes)
{
switch (get_post_type()) {
case 'portfolio':
// we're viewing a custom post type, so remove the 'current_page_xxx and current-menu-item' from all menu items.
$classes = array_filter($classes, "remove_parent_classes");
// add the current page class to a specific menu item (replace ###).
if (in_array('menu-item-14', $classes)) {
$classes[] = 'current_page_parent';
}
break;
case 'tips':
// we're viewing a custom post type, so remove the 'current_page_xxx and current-menu-item' from all menu items.
$classes = array_filter($classes, "remove_parent_classes");
// add the current page class to a specific menu item (replace ###).
if (in_array('menu-item-23', $classes)) {
$classes[] = 'current_page_parent';
}
break;
}
return $classes;
}
add_filter('nav_menu_css_class', 'add_class_to_wp_nav_menu');
There's just one custom post type in the function, but I'm sure you can figure out how to add more. Got any questions, feel free to leave a comment! :)

Razor: Retrieving variable from component template on page template

Hi all,
I've been working on a set of Razor templates that is either Site Editable with the Experience Manager and at the same time is fully responsive for several screenwidths with the Twitter bootstrap. As a result, I need to dynamically manipulate the DOM output based on what the Experience Manager editor adds or deletes but still maintain the responsive design. Part of this construction is adhering to the rules the twitter bootstrap dictates.
The twitter bootstrap allows for excellent responsive design by introducing dynamically calculated div widths using classes. A <div class="span12> uses the entire width of the wrapper, for example. A "span6" effectively uses half, with a certain margin calculated as well to allow for another div with "span6". However, this only works if the preceding class is called <div class="row-fluid">,and as long as the span<numbers> actually add up to exactly 12. The problem arises when I need to close the <div class="row-fluid"> when this number is actually reached.
To clarify: it has to output like this
<div class="row-fluid">
<div class="span6">..code</div>
<div class="span4">..code</div>
<div class="span2">..code</div>
</div>
The <div class="span[#]"> are rendered with a component template, in order to allow for multiple components within the <div class="row-fluid>, which the Page Template renders.
However, from a component template level I cannot seem to retrieve the actual amount of components of this template actually exist on the Page itself. I calculate the width of the component used based on a schema option of the component itself. I use the following Component Template code to render it correctly:
#{
var spanClass = String.Empty;
if (Fields.HasField("component_width") && Fields.component_width != null) {
if (Fields.component_width.ToLower() == "full") {
spanClass = "span12";
} else if (Fields.component_width.ToLower() == "half") {
spanClass = "span6";
} else if (Fields.component_width == "40%") {
spanClass = "span5";
} else if (Fields.component_width == "35%") {
spanClass = "span4";
} else if (Fields.component_width == "25%") {
spanClass = "span3";
}
}
}
<div class="#spanClass">...code
To get to my question: I need to be able to close the <row-fluid> div if the number 12 has been reached. So if one component with the options 'Full' (width) is selected, the following output code needs to appear:
<div class="row-fluid">
<div class="span12">..code</div>
</div>
If there are two components on the page with the option "half" are selected, it must allow
<div class="row-fluid">
<div class="span6">..code</div>
<div class="span6">..code</div>
</div>
mind the closing div on the end. Is there some way I can reach the variable i created on the Component Template var spanClass = String.Empty; from Page Template? Something like:
#foreach (var cp in GetComponentPresentationsByTemplate("XM_Generic Content")) {
#if (cp.Component.spanClass == "span6") {
<div class="row-fluid">
#cp.RenderComponentPresentation()
#if (cp.Index == 1) {
</div>
}
}
}
I'm still getting to know Razor templates, the practicalities of Responsive design and ofcourse StackOverflow. Chances are that I completely missed something, made dumb errors in my code of just asked a silly question. By all means, let me know.
The package is not shared between template runtimes, so this behavior is normal (not being able to see variables set in one template from a different instance).
There are ways around this, but you should consider that perhaps there is a good reason why Tridion chose to isolate the template execution.
See here for one of the ways to go around this.
Standard techniques using the ContextVariables dictionary don't allow you to set something in the CT and access it from the PT. Effectively, each time a Component is rendered, the render context gets a fresh copy of the variables from the page render context. Writing back to them, therefore isn't effective. There is a technique that gets round this, which is described in detail on tridion-practice. As already noted, resorting to these kinds of techniques shouldn't be your first option, but sometimes you need to.
Currently, its seems, the user is defining the width position in the component field. I think, its quite typical, but if you create 5 Component Template which will call a same Razor TBB, and also define, a parameter schema on component Template where can set the width of component then afterwards you can easily call these different CTs in the page template.

mootools - using addEvent to element not working properly?

bangin' my head against this and it's starting to hurt.
I'm having trouble with adding an event to an element.
I'm able to add the event, and then call it immediately with element.fireEvent('click'), but once the element is attached to the DOM, it does not react to the click.
example code:
var el = new Element('strong').setStyle('cursor','pointer');
el.addEvent('click',function () { alert('hi!'); });
el.replaces(old_element); // you can assume old_element exists
el.fireEvent('click'); // alert fires
however, once I attach this to the DOM, the element is not reactive to the click. styles stick (cursor is pointer when I mouseover), but no event fires. tried mouseover as well, to no avail.
any clues here? am I missing something basic? I am doing this all over the place, but in this one instance it doesn't work.
EDIT----------------
ok here's some more code. unfortunately I can't expose the real code, as it's for a project that is still under tight wraps.
basically, the nodes all get picked up as "replaceable", then the json found in the rel="" attribute sets the stage for what it should be replaced by. In this particular instance, the replaced element is a user name that should pop up some info when clicked.
again, if I fire the event directly after attaching it, all is good, but the element does not react to the click once it's attached.
HTML-----------
<p>Example: <span class='_mootpl_' rel="{'text':'foo','tag':'strong','event':'click','action':'MyAction','params':{'var1': 'val1','var2': 'val2'}}"></span></p>
JAVASCRIPT-----
assumptions:
1. below two functions are part of a larger class
2. ROOTELEMENT is set at initialize()
3. MyAction is defined before any parsing takes place (and is properly handled on the .fireEvent() test)
parseTemplate: function() {
this.ROOTELEMENT.getElements('span._mootpl_').each(function(el) {
var _c = JSON.decode(el.get('rel'));
var new_el = this.get_replace_element(_c); // sets up the base element
if (_c.hasOwnProperty('event')) {
new_el = this.attach_event(new_el, _c);
}
});
},
attach_event: function(el, _c) {
el.store(_c.event+'-action',_c.action);
el.store('params',_c.params);
el.addEvent(_c.event, function() {
eval(this.retrieve('click-action') + '(this);');
}).setStyle('cursor','pointer');
return el;
},
Works just fine. Test case: http://jsfiddle.net/2GX66/
debugging this is not easy when you lack content / DOM.
first - do you use event delegation or have event handlers on a parent / the parent element that do event.stop()?
if so, replace with event.preventDefault()
second thing to do. do not replace an element but put it somewhere else in the DOM - like document.body's first node and see if it works there.
if it does work elsewhere, see #1
though I realsie you said 'example code', you should write this as:
new Element('strong', {
styles: {
cursor: "pointer"
},
events: {
click: function(event) {
console.log("hi");
}
}
}).replaces(old_element);
no point in doing 3 separate statements and saving a reference if you are not going to reuse it. you really ought to show the ACTUAL code if you need advice, though. in this snippet you don't even set content text so the element won't show if it's inline. could it be a styling issue, what is the display on the element, inline? inline-block?
can you assign it a class that changes it on a :hover pseudo and see it do it? mind you, you say the cursor sticks which means you can mouseover it - hence css works. this also eliminates the possibility of having any element shims above it / transparent els that can prevent the event from bubbling.
finally. assign it an id in the making. assign the event to a parent element via:
parentEl.addEvent("click:relay(strong#idhere)", fn);
and see if it works that way (you need Element.delegate from mootools-more)
good luck, gotta love the weird problems - makes our job worth doing. it wouldn't be the worst thing to post a url or JSFIDDLE too...