I wonder if anyone can help. An HTML div in a page of mine contains a tree control which is shown or hidden depending upon a button pressed by a user. The button triggers an Ajax event which sets a variable on the server to show or hide the tree so that the state is persisted.
But here's the problem; when the tree is re-displayed, the icons for expanding / collapsing brances are not present. So far, I've not been able to work out why this is the case.
The tree is shown below: the first graphic shows the tree as it should be, the second shows it after it has been hidden and re-displayed.
alt text http://www.dcs.bbk.ac.uk/~martin/Tree_with_icons.png
alt text http://www.dcs.bbk.ac.uk/~martin/Tree_without_icons.png
The tree's HTML is built on the server as a list and each list item has a class reference to CSS as follows:
ul.tree li.liOpen .bullet {
background: url(myApp_Minus.png) center left no-repeat;
cursor: pointer;
}
ul.tree li.liClosed .bullet {
background: url(myApp_Plus.png) center left no-repeat;
cursor: pointer;
}
ul.tree li.liBullet .bullet {
background: url(myApp_Hyphen.png) center left no-repeat;
cursor: pointer;
}
Can anyone advise a method of showing the icons when the tree is re-displayed?
I've tried putting a link to the CSS file in the div, inline CSS elements and so on but without success.
Any help would be welcome.
I attach an extract of the tree's HTML at runtime:
<td align = "left">
<div id = "tree"><ul class = "tree" id = "navTree">
<li class = "liOpen">
<a href = "/myDataSharer/aboutConcept#communities">
<img alt = "Community" src = "/myDataSharer/images/myDataSharer_Community_Small.png">
</a> 
Martin
<ul>
<li class = "liOpen">
<a href = "/myDataSharer/aboutConcept#datasets">
<img alt = "Tabular dataset" src = "/myDataSharer/images/myDataSharer_TabularDataset_Small.png">
</a> 
Planets
</li>
<ul>
<li>
<a href = "/myDataSharer/aboutConcept#QAV">
<img alt = "Visualisation" src = "/myDataSharer/images/myDataSharer_Visualisation_Small.png">
</a> 
Test QAV
</li>
<li>
<a href
The tree itself is in a div called 'tree' which is updated from Javascript method as follows:
document.getElementById("tree").style.visibility = "visible";
document.getElementById("tree").innerHTML = str;
The Javascript for the tree is:
/* WRITTEN BY: Martin O'Shea for myDataSharerAlpha.
*
* This program has been inherited verbatim from the original author's sample code as mentioned
* below. No changes have been made other than a rename of a variable on line 121 from 'mktree' to 'tree'.
* ===================================================================
* Author: Matt Kruse <matt#mattkruse.com>
* WWW: http://www.mattkruse.com/
*
* NOTICE: You may use this code for any purpose, commercial or
* private, without any further permission from the author. You may
* remove this notice from your final code if you wish, however it is
* appreciated by the author if at least my web site address is kept.
*
* You may *NOT* re-distribute this code in any way except through its
* use. That means, you can include it in your product, or your web
* site, or any other form where the code is actually being used. You
* may not put the plain javascript up on your site for download or
* include it in your javascript libraries for download.
* If you wish to share this code with others, please just point them
* to the URL instead.
* Please DO NOT link directly to my .js files from your site. Copy
* the files to your server and use them there. Thank you.
* =====================================================================
* HISTORY
* ------------------------------------------------------------------
* December 9, 2003: Added script to the Javascript Toolbox
* December 10, 2003: Added the preProcessTrees variable to allow user
* to turn off automatic conversion of UL's onLoad
* March 1, 2004: Changed it so if a <li> has a class already attached
* to it, that class won't be erased when initialized. This allows
* you to set the state of the tree when painting the page simply
* by setting some <li>'s class name as being "liOpen" (see example)
*
* This code is inspired by and extended from Stuart Langridge's aqlist code:
* http://www.kryogenix.org/code/browser/aqlists/
* Stuart Langridge, November 2002
* sil#kryogenix.org
* Inspired by Aaron's labels.js (http://youngpup.net/demos/labels/)
* and Dave Lindquist's menuDropDown.js (http://www.gazingus.org/dhtml/?id=109)
*/
// Automatically attach a listener to the window onload, to convert the trees
addEvent(window,"load",convertTrees);
// Utility function to add an event listener
function addEvent(o,e,f){
if (o.addEventListener){ o.addEventListener(e,f,true); return true; }
else if (o.attachEvent){ return o.attachEvent("on"+e,f); }
else { return false; }
}
// utility function to set a global variable if it is not already set
function setDefault(name,val) {
if (typeof(window[name])=="undefined" || window[name]==null) {
window[name]=val;
}
}
// Full expands a tree with a given ID
function expandTree(treeId) {
var ul = document.getElementById(treeId);
if (ul == null) { return false; }
expandCollapseList(ul,nodeOpenClass);
}
// Fully collapses a tree with a given ID
function collapseTree(treeId) {
var ul = document.getElementById(treeId);
if (ul == null) { return false; }
expandCollapseList(ul,nodeClosedClass);
}
// Expands enough nodes to expose an LI with a given ID
function expandToItem(treeId,itemId) {
var ul = document.getElementById(treeId);
if (ul == null) { return false; }
var ret = expandCollapseList(ul,nodeOpenClass,itemId);
if (ret) {
var o = document.getElementById(itemId);
if (o.scrollIntoView) {
o.scrollIntoView(false);
}
}
}
// Performs 3 functions:
// a) Expand all nodes
// b) Collapse all nodes
// c) Expand all nodes to reach a certain ID
function expandCollapseList(ul,cName,itemId) {
if (!ul.childNodes || ul.childNodes.length==0) { return false; }
// Iterate LIs
for (var itemi=0;itemi<ul.childNodes.length;itemi++) {
var item = ul.childNodes[itemi];
if (itemId!=null && item.id==itemId) { return true; }
if (item.nodeName == "LI") {
// Iterate things in this LI
var subLists = false;
for (var sitemi=0;sitemi<item.childNodes.length;sitemi++) {
var sitem = item.childNodes[sitemi];
if (sitem.nodeName=="UL") {
subLists = true;
var ret = expandCollapseList(sitem,cName,itemId);
if (itemId!=null && ret) {
item.className=cName;
return true;
}
}
}
if (subLists && itemId==null) {
item.className = cName;
}
}
}
}
// Search the document for UL elements with the correct CLASS name, then process them
function convertTrees() {
setDefault("treeClass","tree");
setDefault("nodeClosedClass","liClosed");
setDefault("nodeOpenClass","liOpen");
setDefault("nodeBulletClass","liBullet");
setDefault("nodeLinkClass","bullet");
setDefault("preProcessTrees",true);
if (preProcessTrees) {
if (!document.createElement) { return; } // Without createElement, we can't do anything
uls = document.getElementsByTagName("ul");
for (var uli=0;uli<uls.length;uli++) {
var ul=uls[uli];
if (ul.nodeName=="UL" && ul.className==treeClass) {
processList(ul);
}
}
}
}
// Process a UL tag and all its children, to convert to a tree
function processList(ul) {
if (!ul.childNodes || ul.childNodes.length==0) { return; }
// Iterate LIs
for (var itemi=0;itemi<ul.childNodes.length;itemi++) {
var item = ul.childNodes[itemi];
if (item.nodeName == "LI") {
// Iterate things in this LI
var subLists = false;
for (var sitemi=0;sitemi<item.childNodes.length;sitemi++) {
var sitem = item.childNodes[sitemi];
if (sitem.nodeName=="UL") {
subLists = true;
processList(sitem);
}
}
var s= document.createElement("SPAN");
var t= '\u00A0'; //
s.className = nodeLinkClass;
if (subLists) {
// This LI has UL's in it, so it's a +/- node
if (item.className==null || item.className=="") {
item.className = nodeClosedClass;
}
// If it's just text, make the text work as the link also
if (item.firstChild.nodeName=="#text") {
t = t+item.firstChild.nodeValue;
item.removeChild(item.firstChild);
}
s.onclick = function () {
this.parentNode.className = (this.parentNode.className==nodeOpenClass) ? nodeClosedClass : nodeOpenClass;
return false;
}
}
else {
// No sublists, so it's just a bullet node
item.className = nodeBulletClass;
s.onclick = function () { return false; }
}
s.appendChild(document.createTextNode(t));
item.insertBefore(s,item.firstChild);
}
}
}
Thanks.
The Ajax of the web page is shown below:
<script language="Javascript">
function xmlhttpPost(strURL) {
var xmlHttpReq = false;
var self = this;
// Mozilla / Safari.
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
}
// IE.
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open('POST', strURL, true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
self.xmlHttpReq.onreadystatechange = function() {
if (self.xmlHttpReq.readyState == 4) {
updatePage(self.xmlHttpReq.responseText);
}
}
self.xmlHttpReq.send(getQueryStr());
}
function getQueryStr() {
queryStr = "action=toggleTree";
return queryStr;
}
function updatePage(str) {
if (str == "false") {
// Hide tree buttons and tree.
document.getElementById("tree").style.visibility = "hidden";
document.getElementById("expColTreeButtons").style.visibility = "hidden";
}
else {
// Show tree buttons.
document.getElementById("expColTreeButtons").style.visibility = "visible";
// Show tree.
document.getElementById("tree").style.visibility = "visible";
document.getElementById("tree").innerHTML = str;
}
}
function toggleTree() {
// Make call to server to toggle tree.
document.getElementById("tree").innerHTML = "<img src='/myDataSharer/images/myDataSharer_Wait.gif' alt='Growing tree' />"
xmlhttpPost("/myDataSharer/toggleTree");
}
The Ajax above is triggered from a form which has three buttons. The 'Show / hide' button sees to things; the other two of the buttons are also enclosed within a div but they are alright.
<form>
<input class = "treeButton" type="submit" value="Show / hide" onClick = "toggleTree(); return false;">
<div id = "expColTreeButtons">
<input class = "treeButton" type="submit" value="Expand all" onClick = "expandTree('navTree'); return false;">
<br />
<input class = "treeButton" type="submit" value="Collapse all" onClick = "collapseTree('navTree'); return false;">
<br />
</div>
</form>
Your CSS looks fine ad like something that could produce the example on the left, so it must be the HTML or the JavaScript that does the showing and hiding. How does the JavaScript work?
It's not likely a CSS problem, since it's working the first time. I'd bet the problem lies in how your server is generating content - i.e. not assigning the proper attributes to each node.
This question has now resolved. Thanks those who contributed.
The solution was to re-process the Javascript tree after the div had been updated.
Related
Does anyone have any experience with conditionally disabling fields based on value of a previous field in an AEM6.1 TouchUI dialog?
To give some context I have a checkbox in my TouchUI dialog used to enable/disable (hide/show) a Call To Action button within a component. I'd like to disable the CTA buttonText and href fields in the dialog itself where the author has disabled the CTA via the checkbox. Adversely I'd like to enable these fields where the CTA checkbox is checked enabling CTA.
I have investigated /libs/cq/gui/components/authoring/dialog/dropdownshowhide/clientlibs/dropdownshowhide.js but it's not really fit for purpose given that this is specifically designed for hiding or showing fields based on value of dropdown list and my attempts to modify it to allow similar funationality on a checkbox have been less than fruitful. I want to enable/disabled fields rather than hide of show them.
After a bit of messing around I got this working by adding class="cq-dialog-checkbox-enabledisable" to my sling:resourceType="granite/ui/components/foundation/form/checkbox" and class="cq-dialog-checkbox-enabledisable-target" to the sling:resourceType="granite/ui/components/foundation/form/textarea" that I wanted to disable in my cq:dialog.xml.
I then created my own clientLib that has dependencies on granite.jquery and categories cq.authoring.dialog.
UPDATE: turns out the disabled property can't be set programatically on pathbrowser field types at the top level, so you neeed to disable the child fields contained inside it (js-coral-pathbrowser-input and js-coral-pathbrowser-button) code snippet below updated to reflect this.
/**
* Extension to the standard checkbox component. It enables/disables other components based on the
* selection made in the checkbox.
*
* How to use:
*
* - add the class cq-dialog-checkbox-enabledisable to the checkbox element
* - add the class cq-dialog-checkbox-enabledisable-target to each target component that can be enabled/disabled
*/
(function(document, $) {
"use strict";
// when dialog gets injected
$(document).on("foundation-contentloaded", function(e) {
// if there is already an inital value make sure the according target element becomes visible
enableDisable($(".cq-dialog-checkbox-enabledisable", e.target));
});
$(document).on("change", ".cq-dialog-checkbox-enabledisable", function(e) {
enableDisable($(this));
});
function enableDisable(el){
el.each(function(i, element) {
if ($(element).attr("type") === "checkbox"){
if ($(element).prop('checked')){
$('.cq-dialog-checkbox-enabledisable-target').enable();
} else {
$('.cq-dialog-checkbox-enabledisable-target').disable();
}
}
})
}
//recurse all pathbrowser children and grandchildren etc
function iteratePathBrowserDescendants (node, enable) {
for (var i = 0; i < node.childNodes.length; i++) {
var child = node.childNodes[i];
if ((child.className.indexOf('js-coral-pathbrowser-input') > -1 ) || (child.className.indexOf('js-coral-pathbrowser-button') > -1 )) {
enablePathBrowser(child, enable);
} else {
iteratePathBrowserDescendants(child, enable);
}
}
}
function enablePathBrowser(node, enable) {
node.disabled = enable;
}
//iterate class cq-dialog-checkbox-enabledisable-target's and enable
$.prototype.enable = function () {
$.each(this, function (index, el) {
//special treatment for pathBrowser as it is made up of multiple fields and cannot be disabled at the top level
if (el.hasAttribute('data-init')) {
if (el.getAttribute('data-init') == 'pathbrowser'){
iteratePathBrowserDescendants(el, false);
};
} else {
el.disabled = false;
}
});
}
//iterate class cq-dialog-checkbox-enabledisable-target's and disable
$.prototype.disable = function () {
$.each(this, function (index, el) {
//special treatment for pathBrowser as it is made up of multiple fields and cannot be disabled at the top level
if (el.hasAttribute('data-init')) {
if (el.getAttribute('data-init') == 'pathbrowser'){
iteratePathBrowserDescendants(el, true);
};
} else {
el.disabled = true;
}
});
}
})(document,Granite.$);
I'm building a html-app for Android and I have an issue with the :active css rule. It works like it should BUT when I hide an element that is ':active'. the state is never dismissed.
For example:
I have a button with this css:
.button:active { background-color:rgba(0,0,0,0.5); }
and this javascript:
$(".button").on("click",function(evt){
$(evt.originalEvent.target).css("display","none");
});
When I tap the button it is hidden. But when I un-hide it, it will still have the .button:active css rule applied.
Help?
Try the following
$(".button").on("click",function(evt){
$(evt.originalEvent.target).removeClass("active");/*Or whatever your class name is**/
$(evt.originalEvent.target).css("display","none");
});
I think I got it working with a MAJOR workaround (because event.target for touches returns the element the user tapped on which may very well be a childnode of the actual element that binds the events (see example below, it will return the [img] elem, not the [div]). Seufs.
PS: #Richa's answer did help me to do a workaround instead of hoping there would be a fix for :active
HTML (snippet)
<div class='button activatablel'><img src='someicon.png'></div>
CSS
.activatablel { /* nothing, just used to find the elements with jquery) */ }
.activatablel_active {
background:#f00;
}
JAVASCRIPT
elems = $(".activatablel");
for (var i in elems) {
var elem = elems[i];
elem.ontouchstart = function(evt) {
// Now we have to find the ACTUAL element that bound this event
// because somebody decided it's useful to not do this &$*((#^#))_
var foundTheActualTarget = false;
var thetarget = evt.target;
var whilenum = 0;
while (!foundTheActualTarget) {
if (thetarget.className) {
if (thetarget.className.indexOf("activatablel")>=0) {
foundTheActualTarget = true;
break;
}
}
thetarget = thetarget.parentNode;
whilenum++;
if (whilenum>256) { break; } // TODO: unless we intend to do this job in Reno, we're in Barney
}
if ($(thetarget).hasClass("activatablel_active")) { return; }
$(thetarget).addClass("activatablel_active");
}
elem.ontouchend = function(evt) {
$("*").removeClass("activatablel_active");
}
elem.ontouchcancel = elem.ontouchend;
}
I'm using tinyMCE for small site, that is used by people to write simple articles. Usualy they write in MS word and copy text to tinyMCE and submit this.
That's why I only allowed few tags:
valid_elements: "a[href|target],strong/b,em/i,div[align],br,p[style|align],ul,li,ol,table,tr,td,iframe[*],img[*]",
But despite allowing img[*] after inserting image by 'Insert/edit image' only:
<img alt=""/>
appears in code. Same goes for iframe (which is complitly removed)
I've already tried every combination of valid_elements with full list of img and iframe attributes and with extended_valid_elements.
When I remove valid_elements clause everything works fine, but then word formatting which is not allowed (h1, h2, etc) is messing up styles.
TinyMCE version is 3.4.2.
I am using the paste_preprocess setting with the tinymce paste plugin and i filter out unwanted tags there. Here is an example:
in your tinymce init:
paste_preprocess : function(pl, o) {
//if(console) console.log('Object', o);
//if(console) console.log('Content:', o.content);
// usage param1 = the string to strip out tags from, param2 = tags to keep in the string
o.content = ir.im.strip_tags( o.content,'<p><div><br><br/>' );
},
Help function to strip out tags:
strip_tags = function (str, allowed_tags) {
var key = '', allowed = false;
var matches = []; var allowed_array = [];
var allowed_tag = '';
var i = 0;
var k = '';
var html = '';
var replacer = function (search, replace, str) {
return str.split(search).join(replace);
};
// Build allowes tags associative array
if (allowed_tags) {
allowed_array = allowed_tags.match(/([a-zA-Z0-9]+)/gi);
}
str += '';
// Match tags
matches = str.match(/(<\/?[\S][^>]*>)/gi);
// Go through all HTML tags
for (key in matches) {
if (isNaN(key)) {
// IE7 Hack
continue; }
// Save HTML tag
html = matches[key].toString();
// Is tag not in allowed list? Remove from str!
allowed = false;
// Go through all allowed tags
for (k in allowed_array) { // Init
allowed_tag = allowed_array[k];
i = -1;
if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+'>');}
if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+' ');}
if (i != 0) { i = html.toLowerCase().indexOf('</'+allowed_tag) ;}
// Determine
if (i == 0) { allowed = true;
break;
}
}
if (!allowed) {
str = replacer(html, "", str); // Custom replace. No regexing
}
}
return str;
};
I used a javascript FocusChange() in my aspx page. I have couple of controls and I need Hit enter key need to move next control based on tab index. It is working good in IE7 but not working in IE8... Please help me on this..
Thanks for your help in advance. The java script is given below.
function FocusChange() {
if (window.event.keyCode == 13) {
var formLength = document.form1.length; // Get number of elements in the form
var src = window.event.srcElement; // Gets the field having focus
var currentTabIndex = src.getAttribute('tabindex'); // Gets its tabindex
// scroll through all form elements and set focus in field having next tabindex
for (var i = 0; i < formLength; i++) {
if (document.form1.elements[i].getAttribute('tabindex') == currentTabIndex + 1) {
for (var j = i; j <= formLength; j++) {
if (document.form1.elements[j].disabled == false) {
document.form1.elements[j].focus();
event.returnValue = false;
event.cancel = true;
return;
}
}
}
}
}
}
I've got the same request as you, but solved it in a different manner, just replacing the Enter for Tab
<script language="JavaScript">
document.onkeydown = myOnkeydown;
function myOnkeydown()
{
var key = window.event.keyCode;
if (key == 13) //13 is the keycode of the 'Enter' key
{window.event.keyCode = 9; //9 is the code for the 'Tab' key. Essentially replacing the Enter with the Tab.
}
}
</script>
Warning: Works in IE only.
I am using ASP.NET with C# 2.0 and Visual Studio 2005. I am using a Master page and content pages. I have a treeview menu in the master page and when a user selects any menu item I redirect to that content page.
My problem is that after a user navigates to the content page all the treenodes refresh and the structure is collapsed. I want the selected treenode to stay expanded.
Can anybody help me out?
Are you using the treeview inside any UpdatePanel? Actually UpdatePanel does not support TreeView. I however managed the same using a lot of additional codes. You can see most of them on http://www.geekays.net/post/Using-TreeView-inside-AJAX-UpdatePanel.aspx and another post on the same site: http://www.geekays.net/post/TreeView-control-postbacks-on-check-and-uncheck-of-the-nodes-Checkbox.aspx
I added javascripts like the following also to scroll to a tree node that was selected, but the success was poor:
function scrollSelectedTviewNodeToDisplay(){
try{
var inpSelectedNode = document.getElementById("ctl00_contRMSMaster_TViewDeviceHeirarchy_SelectedNode");
var divTree = document.getElementById("ctl00_contRMSMaster_TViewDeviceHeirarchy");
if (inpSelectedNode.value != "")
{
var objScroll = document.getElementById(inpSelectedNode.value);
//my treeview is contained in a scrollable div element
var posY =findPosY(objScroll);
//alert(posY);
if (divTree){
divTree.scrollTop = posY;
//alert(divTree.nodeType);
}
//this works as well bu, but there is not as much control over the y position
//document.all(inpSelectedNode.value).scrollIntoView(true);
}
}
catch(oException)
{
//alert(document.getElementById("ctl00_contRMSMaster_divTree"));
}
}
function findPosX(obj){
var curleft = 0;
if (obj.offsetParent)
{
while (obj.offsetParent)
{
curleft += obj.offsetLeft
obj = obj.offsetParent;
}
}
else if (obj.x)
curleft += obj.x;
return curleft;
}
function findPosY(obj){
var curtop = 0;
if (obj.offsetParent)
{
while (obj.offsetParent)
{
curtop += obj.offsetTop
obj = obj.offsetParent;
}
}
else if (obj.y)
curtop += obj.y;
return curtop;
}