How to hide a *single* MVC/Kendo tabstrip tab? - javascript

How do I hide a single tab on a MVC/Kendo UI tabstrip?
I want to hide a tab based on a condition. My jQuery code goes like this:
//authUser is a hidden input whose value is set in the controller and passed into the view
if ($('#authUser').val() == 'False') //hide the last tab
{
$($("#tabstrip").data("kendoTabStrip").items()[6]).attr("style", "display:none");
}
When I run the code I get the following error on the line of code that's executed if authUser is False:
JavaScript runtime error: Unable to get property 'items' of undefined or null reference
Ideas?

The fact that 'items' is undefined implies that you never appropriately selected the tabstrip in the first place. Either your CSS selector is wrong (are you sure you named it tabstrip?) or you did not follow the Kendo method names appropriately.
Here are two ways I found to hide the last tab:
Hiding the last tabstrip element
var tabStrip = $("#tabstrip").kendoTabStrip().data("kendoTabStrip");
//Find the last tab item's index from the items list
var lastIndex = tabStrip.items().length - 1;
//Use jQuery's hide method on the element
$(tabStrip.items()[lastIndex]).hide();
Using Kendo's tabstrip remove method
I believe the following is more appropriate. Why not use the tabstrip's remove method and completely remove it from the DOM since the user should not have access anyway?
var tabStrip = $("#tabstrip").kendoTabStrip().data("kendoTabStrip");
tabStrip.remove("li:last");

I'm just stupid....
I looked some more at the code and I was leaving out the kendoTabStrip() word (bolded) from
$($("#tabstrip").kendoTabstrip().data("kendoTabStrip").items()[6]).attr("style","display:none")
i.e. Instead of (properly) having:
$($("#tabstrip").kendoTabStrip().data("kendoTabStrip").items()[6]).attr("style","display:none")
I had:
$($("#tabstrip").data("kendoTabStrip").items()[6]).attr("style","display:none")
Drew, thanks for your effort. Sometimes I just have to beat my head on a wall until I see what I've done.

Related

BootstrapToggle switch conditionally switch state

I'm trying to use bootstraptoggle in one of my pages. The initial state is off / disabled.
The page loads several boolean values and stores them as hidden text. Then I have a script which looks them up via their IDs. Upon that hidden text it should toggle the slider.
I was able to get the hidden text and make the conditional check but I'm not able to toggle the slider for some reason.
Here is my code:
$(document).ready(function () {
var flags = [];
var userID = '',
toggleSlider = '';
flags = document.querySelectorAll('*[id^="activeFlag_"]');
flags.forEach(function (flag) {
userID = flag.id.split('_')[1];
// This is where i search for the hidden text
if (flag.firstChild.data == 'True') {
// Nothing works here.
$('#activeToggle_' + userID).bootstrapToggle('toggle');
}
});
});
And this is the html code that I need to work with:
<p id="activeFlag_#user1">#item.activeFlag</p>
<div class="checkbox">
<label>
<input id="activeToggle_user1" type="checkbox" data-toggle="toggle" data-on="Enabled" data-off="Disabled">
</label>
</div>
Your code is too opaque without any data example.
However one thing could be a cause of its problem:
if (flag.firstChild.data == 'True') {
Try to replace it with:
if (flag.firstElementChild.data == 'True') {
Here you could find explanation:
The firstChild property returns the first child node of the specified node, as a Node object.
The difference between this property and firstElementChild, is that firstChild returns the first child node as an element node, a text node or a comment node (depending on which one's first), while firstElementChild returns the first child node as an element node (ignores text and comment nodes).
Note: Whitespace inside elements is considered as text, and text is considered as nodes (See "More Examples").
Update after example code was added
For the example code you provided, you should change the split argument:
userID = flag.id.split('_')[1];
to:
userID = flag.id.split('_#')[1];
Thanks to twain for initial jsfiddle. I have updated it accordingly: jsfiddle
I guess the problem is, that the following part does not use the correct id for the toggle $('#activeToggle_' + userID).bootstrapToggle('toggle');
Your html ID is activeToggle_user1, but the js part above will probably resolve to #activeToggle_1. So the text user is missing here.
I created a working fiddle here: https://jsfiddle.net/pbcrh5d2/
Ok, for some reason asp.net and javascript have a problem with coping together. I used asp.net to provide javascript to build the strings.
So I switched to the raw id that is used in the table.

Error if targeting multiple element Id's with Javascript and one of then is not found

I am trying to target multiple IDs with JavaScript so that I can disable the input field for them. It seems to be pretty straight forward using the following script, but I noticed that on pages where the middle Element does not exist, the script does not disable the 3rd one (as though it just stops working when not finding the second element).
<script>
document.getElementById("id_1").disabled = true;
document.getElementById("id_2").disabled = true;
document.getElementById("id_3").disabled = true;
</script>
So on pages when all 3 IDs exist, the script works perfectly. But on pages where either "id_1" or "id_2" does not exist, the remaining elements are not disabled even if they do exist.
Is there any way around that? Note that I can not create separate scripts for each page because this will go in the footer which is the same for all pages.
Thanks!
You should test for the existence first, then disable it if it exists. I also put the id's in an array to simplify the code.
var ids = ['id_1','id_2','id_3'];
for (var i = 0; i < ids.length; i++) {
var el = document.getElementById(ids[i]);
el && (el.disabled = true);
}
<input id="id_1" value="id_1">
<input id="id_3" value="id_3">
This is because document.getElementById returns null when the element has not been found, so effectively you're causing an exception while trying to set disabled on null. This would be the case when one of the elements are not set in the DOM. What you will have to do is check whether the element has been found correctly then set the element or loop through them all.
TL;DR:
The reason that the script stops working is that it is throwing an error when you try to disable an element that doesn't exist.
In Detail:
document.getElementById() will return null if the element that you tried to find does not exist (Here's the MDN page).
When you try to set the .disabled property to true on null JavaScript will throw a TypeError. Unless you handle that error with a try/catch block it will cause your script to stop executing and the later input elements will not become disabled.
Solution
To fix this you'll want to check that your element actually is an element before trying to set it to disabled. Something like this:
var el = document.getElementById('id_1');
if ('null' !== typeof el) {
el.disabled = true;
}

Jquery script not working to alter CSS on change

I've added some custom elements to be included with my WooCommerce account page to be seen with the order history. Unfortunately the page is setup with tabs to only display the information pertaining to the active tab.
I'm not very familiar with jquery, but I thought it would be simple enough to use Jquery to hide the divs I added when the order history has a display of none.
I added the following script to my theme's main.js file:
$(document).ready(function(){
var display = $('.my_account_orders');
if(display.css("display") == "none") {
$('.paging-nav').css("display","none");
}
});
When the class .my_account_orders has a display of none it should change the div I added (.paging-nav) to have a display of none. But it just doesn't work.
Is there something wrong with this script or do I need to do something special to initiate it? Since it's in my theme's main.js file and I used $(document).ready(function() I figured it would just load with the page.
Any help with this would be greatly appreciated.
Instead of using:
var display = $('.my_account_orders');
Implement it into the if statement like this:
if($('.my_account_orders').css("display") == "none") {
Because originally it is trying to find a variable called $display, so it would return a syntax error of undefined.
You've got an errant $ in your if statement. This should work instead:
$(document).ready(function(){
var display = $('.my_account_orders');
if(display.css("display") == "none") {
$('.paging-nav').css("display","none");
}
});
Also keep in mind that your var display is only going to match the first element that has a class of my_account_orders, so if there are multiple elements with that class, and they don't all have the same display, you could get unexpected results.
Try this:
$(document).ready(function(){
var display = $('.my_account_orders');
if(display.css("display") == "none") {
$('.paging-nav').css("display","none");
}
});
I believe it's a very lame way to check for a css property such as display to determine if an element is hidden or not. With jquery, you can make use of :hidden selector which determines whether an element is hidden and return a bool value.
$(document).ready(function(){
if($('.my_account_orders').eq(0).is(":hidden")) // eq(0) is optional - it basically targets the 1st occurring element with class 'my_account_orders'
{
$('.paging-nav').css("display","none");
}
});
Example : https://jsfiddle.net/DinoMyte/sgcrupm8/2/

Read more opens 1st one all the time

I've a page with about 10 short articles.
Each of them as a "Read More" button which when pressed displays hidden text
The issues I have at the moment is when I press the "Read More" on any of the 10 button it shows the 1st articles hidden content and not the selected one.
I think I need to set a unique ID to each article.. and the read more button be linked to it.. But I don't know how to set it.
I looked at this but couldn't get it working how to give a div tag a unique id using javascript
var WidgetContentHideDisplay = {
init:function() {
if ($('#content-display-hide').size() == 0) return;
$('.triggerable').click(function(e){
var element_id = $(this).attr('rel');
var element = $('#'+element_id);
element.toggle();
if (element.is(':visible')) {
$('.readmore').hide();
} else {
$('.readmore').show();
}
return false;
});
}
}
var div = documentElemnt("div");
div.id = "div_" + new Date().gettime().toString;
$(document).ready(function(){ WidgetContentHideDisplay.init(); });
OP Edit: Sorry, the original code wasn't in caps. I kept getting errors when trying to post, so I copied the code into Dreamweaver and it made it all caps for some reason.
Instead of selecting the element to toggle with an ID (i.e. $('#'+ELEMENT_ID)) you could setup a class for your item and use the class selection (e.g. $('.DETAILED-ARTICLE)') to select the child (or the brother, etc. depending how you built the HTML page).
In theory each ID should point to a single element but each class can be put to as many elements as you want.
If you're getting errors, read the errors and see what they are. Off of a quick read of your code, here are a couple things I noticed that will probably cause issues:
"documentElemnt" is misspelled, which will render it useless. Also, documentElement is a read-only property, not a function like you're using it.
toString is a function, not a property, without the parentheses (.toString()) it isn't going to function like you want it to.
Run the code, look at the errors in the console, and fix them. That's where you start.

selectmenu ('refresh', true)

I get form from zend framework site and put it in response in new file in function written by jquery mobile, but I get this error:
uncaught exception: cannot call methods on selectmenu prior to
initialization; attempted to call method 'refresh' .
Code of function this file:
function addItem(id) {
$.ajax({
url:'http://zf.darina.php.nixsolutions.com/order/index/create-order-mobile',
dataType:"jsonp",
data:{id_good:id},
success:function (resp) {
console.log(resp);
$('.product-table').empty();
$('.product-table').append(resp.prod);
$('.product-table').append(resp.form);
$('.add-order-btn').button();
$('.mob-size').selectmenu('refresh', true);
$('#block').page();
}
})
}
Force initialize the selectmenu(s) first:
$('.mob-size').selectmenu(); // Initializes
$('.mob-size').selectmenu('refresh', true);
or use this for short
$('.mob-size').selectmenu().selectmenu('refresh', true);
In my case, if I was not initializing the select before invoking the 'disable' method I got the error, while if I was initializing it, the select didn't disable but duplicate itself - I tried to select the object by TAG NAME instead of by CLASS or ID NAME,
$('select').selectmenu('disable');
instead of
$('.select-class-name').selectmenu('disable');
and it worked without forced initialization
you do this in your custom refresh delegation function:
var w = $("#yourinput");
if( w.data("mobile-selectmenu") === undefined) {
// not initialized yet, lets do so
w.selectmenu();
}
w.selectmenu("refresh",true);
according to enhancement resolution here
I found the same problem, but a more involved solution. When jqm wraps the select element, it puts it in a <span> element with the same class list as the select element. I changed my reference to it so that instead of reading:
row.find(".selectCompletion").selectmenu("disable");
it now reads:
row.find("select.selectCompletion").selectmenu("disable");
Specifying that jquery should only find the select element matching the class name, rather than all elements in .row that match the class name, solved the problem.
This happened to me when cloning existing select element in order to duplicate the original section multiple times.
Calling 'refresh' for the original element, worked fine, while calling it for the cloned sections was leading to the error appearing in the question.
However, calling selectmenu() was causing a 'vandalisation' to the form, as can be seen in the following image:
Explanation: top = original. bottom = vandalised cloned element right after calling selectmenu.
Solution:
The following code solved this vandalisation problem:
cloned_elem.find('select[name=MyClass]').selectmenu().selectmenu("destroy").selectmenu();
This is not an ideal solution because we must call the first selectmenu() in order to call selectmenu("destroy"), so I would be glad to hear of a cleaner solution.

Categories